gtkmm Why window has black background and dialog does not - c++

I have a very simple gtkmm3 app with 2 widgets (a window and a dialog) that shows both in response to event on_activate via:
add_window(widget); widget.present();
Both the dialog and the window have exactly the same code, with the only difference being the base class (Gtk::ApplicationWindow vs Gtk::Dialog).
The code for them is following:
constructor()
{
set_decorated(false);
set_app_paintable();
set_default_size(640, 480);
// remove default child if present
auto child = get_child();
if (child) remove(), delete child;
}
bool on_draw(const ::Cairo::RefPtr< ::Cairo::Context> & cr)
{
// get the size of the window
int width, height;
get_size(width, height);
// semi-transparent grey background
cr->set_source_rgba(0.5,0.5,0.5,0.5);
// make round edges
const auto border_radius = 50;
cr->arc(width - border_radius, height - border_radius, border_radius, 0, M_PI_2);
cr->arc(border_radius, height - border_radius, border_radius, M_PI_2, M_PI);
cr->arc(border_radius, border_radius, border_radius, M_PI, 3 * M_PI_2);
cr->arc(width - border_radius, border_radius, border_radius, 3 * M_PI_2, 0);
cr->clip(); // clip the edges
cr->paint(); // paint the background
return false;
}
Surprisingly the result of both cases is different. The dialog gets the intended semi-transparent look, but the window has a black rectangular background.
I presume the window background must be drawn before on_draw, but I don't know when.
Q1: What is the difference between them?
Since Gtk::Dialog inherits from Gtk::Window, there must be a way to remove that black background.
Q2: How can I do that myself?
I already tried removing all CSS styles, by inserting * { all: unset; } in the Gtk inspector, with no visible effect (the inspector did showed all CSS nodes being reset). This makes me think that the black background may not be related to CSS, but I may be wrong.
This is what it looks like:

Related

Alt+Enter in Win32 apps, manage resizing and resolution

I'm struggling with resizing and full screen mode of my project. This is what I'm working on Mandelbrot in a Pixel Shader and here on GIT https://github.com/ShamanLKG/Mandelbrot
The app crashes when Alt+Enter is pressed and I don't understand why.
case WM_SIZE:
{
int width = LOWORD(lParam); // Macro to get the low-order word.
int height = HIWORD(lParam); // Macro to get the high-order word.
pThis->D3D->OnResize(width, height);
pThis->D3D = std::shared_ptr<Direct3D>(new Direct3D(hWnd, width, height));
pThis->D2D = std::shared_ptr<Direct2D>(new Direct2D(hWnd, pThis->D3D));
break;
}
I recreated the Direct3d and Direct2 objects on resize to solve issues with the navigation and to adjust the resolution of the window. But impossible so far to get the full screen working. The full screen works without recreating the D3D and D2D object but then I'm stucked with the original resolution and the navigation does not work properly. I use the OnResize() function from MSDN (https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/d3d10-graphics-programming-guide-dxgi#handling-window-resizing). I tried passing on a BOOL argument to InitD3D to tell the program if the swapchain is full screen or not from swapchain->GetFullScreenState but it did not help.
The navigation works as long at the window size is not changed, then it's not precise. Adjusting the yDelta with the change in screen ratio helps, but only when the window width is changed. It becomes again unstable when the window height is changed. So as workaround I recreated the D3D and D2D object to start with fresh parameters and having a function navigation. But as a result the full screen now crashes.
void Direct3D::CenterScreen(int xPos, int yPos)
{
//float ratio = startRatio / currentRatio;
int xDelta = xPos - width / 2;
int yDelta = (yPos - height / 2); //could divide by ratio to capture window width change
realStart += (float)xDelta / (float)width * 2 * mandelWidth;
imagStart += (float)yDelta / (float)height * 2 * mandelHeight;
}
Any clue how I could solve these issues? Many thanks in advance.
Found the error, the Direct2D resources were not released causing the ResizeBuffers to fail with code 0x887A0001. The tutorial from https://bell0bytes.eu/fullscreen/ has been very helpful.
hr = swapchain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
Lesson of the day, have a robust error handling system.

Change Cursor Image While Hovering Over An Object Drawn At OpenGL And Displaying Object's Variables

I am currently working on a project that I use C++, OpenGL, Qt 5.9.2 and Microsoft Visual Studio Professional 2015 on a 64 bit Operating System, Windows 10 Pro.
I have a user interface that I have created and in that user interface, there is a QGLWidget, that I am using for draw processes, with other widgets like push buttons and a dockWidget. I have a class Ball and it has variables(distance(double) and angle(int)) that determines where an instance of that Ball is going to be drawn inside the QGLWidget. Ball class has got 2 more variables that is, id(int), model(String) and year(int) Every other draw process draws lines except Ball drawings.
Drawings are 2 dimensional.
Every Ball has the same color(rgb)!
First problem: I want to left click to one of the Ball instances and I want to display it's id, model and year at The dockWidget.
Second Problem: While doing the stuff that I have mentioned at the First Problem section. I want the cursor image to change while hovering above any of the Ball instances, and change back to default Windows mouse cursor while not.
I have created a function that checks if the MouseEvent is LeftClick:
void DisplayManager::mousePressEvent(QMouseEvent* ev) {
if (ev->buttons() & Qt::LeftButton) { // Balls Are Green
if(// CHECK IF THERE IS A BALL AT THE CLICKED COORDINATES) {
// DISPLAY THE X and Y OF THE BALL AT THE DOCK WIDGET
}
}
}
This is my initializeGL function: (DisplayManager is the name of my QGLWidget)
void DisplayManager::initializeGL() {
glEnable(GL_COLOR_MATERIAL); // Enables the changing of the draw color with glColor() functions
glColor3f(0.0, 1.0, 0.0);
glEnable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 1); //sets a black background 1 0 0 1
}
On the basis this is a Picking problem and there are several information about it at the internet but I am not using GLUT and I am not using any shader. So in the light of all these I was unable to find any effective solution or clue about how can I accomplish all that I want.
I would be really glad if someone could help me with at least one of these problems.
I have currently finished working with the project. I thought that I should provide an answer to my question in case someone with a similar problem comes across with my question in the future.
void DisplayManager::mousePressEvent(QMouseEvent* ev) {
// The processes that are being executed after a left mouse button click on the DisplayManager.
if (ev->buttons() & Qt::LeftButton) {
double aspectRatio = openGLWidgetWidth / openGLWidgetHeight;
int xOfClicked = ev->x() - (openGLWidgetWidth / 2);
int yOfClicked = - (ev->y() - (openGLWidgetHeight / 2));
// The variable to be used for calculating fault tolerance of the click event.
int distanceBetweenPressAndDraw = 0;
// Executes the processes inside for every ball in vector.
for (int i = 0; i < ballVector.length(); i++) {
// Calculates the screen coordinates of the i'th ball.
int rangeOfBallInScreenDistance = rangeToScreenDistance(ballVector.at(i).range);
double screenXOfBall = rangeOfBallInScreenDistance * sin(ballVector.at(i).degree * DEGTORAD);
double screenYOfBall = rangeOfBallInScreenDistance * cos(ballVector.at(i).degree * DEGTORAD);
// Calculates the distance between pressed position and the i'th ball according to the screen coordinates.
distanceBetweenPressAndDraw = sqrt(pow((screenXOfBall - xOfClicked), 2) + pow((screenYOfBall - yOfClicked), 2));
// Decides if the clicked position is a ball (considering the fault tolerance).
if (distanceBetweenPressAndDraw < 10) {
emit printXY(QPointF(xOfClicked, yOfClicked)); // Prints the screen coordinates of the clicked positions (At the Dock Widget inside Main Window).
}
}
}
}
This was the solution for my First Problem. I would be glad though if someone could answer my Second problem in a comment or answer somehow.

How do I get the window geometry of top level windows excluding any decorations like shadows?

I'm using the GetWindowRect function to get the bounding rectangle of native windows. For top level windows, this seems to include any 'decorations' around the window such as the drop shadows which are enabled by default on Windows 10. I would like to exclude such decorations, but I do want to include the rest (e.g. the minimise/maximise button). How would (Should?) I adjust the geometry returned by GetWindowRect to get this?
My first attempt was to consider the window style and then use the system metrics CM_CxSIZEFRAME (error handling omitted for brevity):
[..]
RECT r;
::GetWindowRect(handle, &r);
const bool isToplevelWindow = (::GetWindowLong(handle, GWL_STYLE) & WS_CHILD) == 0;
if (isToplevelWindow) {
const int frameWidth = ::GetSystemMetrics(SM_CXSIZEFRAME);
const int frameHeight = ::GetSystemMetrics(SM_CYSIZEFRAME);
r.left += frameWidth;
r.right -= frameWidth;
r.top += frameHeight;
r.bottom -= frameHeight;
}
// process `r`
This seems to work mostly except that on the Windows 10 style, adding the frame height to the Y coordinate (i.e. r.top) appears to be wrong, it cuts out the top of the title bar.
By now, I noticed that not only does the ::GetSystemMetrics functin support querying other frame metrics:
SM_C*DLGFRAME (aka SM_CxFIXEDFRAME)
SM_CxFRAME (aka `SM_CxSIZEFRAME)
SM_CxBORDER
SM_C*PADDEDBORDER
...there is also a 'newer' GetThemeSysSize function which provides access to some further seemingly relevant metrics.
Does anybody know which of these (if any) I should respect when trying to get rid of window decorations such as rounded edges or shadows?

Insane CPU usage in QT 5.0

I'm having trouble using the QT framework, particularly with the paintEvent of QWidget. I have a QWidget set up, and am overriding the paintEvent of it. I need to render a bunch of rectangles (grid system), 51 by 19, leading to 969 rectangles being drawn. This is done in a for loop. Then I also need to draw an image on each on of these grids. The QWidget is added to a QMainWindow, which is shown.
This works nicely, but it's using up 47% of CPU per window open! And I want to allow the user to open multiple windows like this, likey having 3-4 open at a time, which puts the CPU close to 150%.
Why does this happen? Here is the paintEvent contents. The JNI calls don't cause the CPU usage, commenting them out doesn't lower it, but commenting out the p.fillRect and Renderer::renderString (which draws the image) lowers the CPU to about 5%.
// Background
QPainter p(this);
p.fillRect(0, 0, this->width(), this->height(), QBrush(QColor(0, 0, 0)));
// Lines
for (int y = 0; y < Global::terminalHeight; y++) {
// Line and color method ID
jmethodID lineid = Manager::jenv->GetMethodID(this->javaClass, "getLine", "(I)Ljava/lang/String;");
error();
jmethodID colorid = Manager::jenv->GetMethodID(this->javaClass, "getColorLine", "(I)Ljava/lang/String;");
error();
// Values
jstring jl = (jstring) Manager::jenv->CallObjectMethod(this->javaObject, lineid, jint(y));
error();
jstring cjl = (jstring) Manager::jenv->CallObjectMethod(this->javaObject, colorid, jint(y));
error();
// Convert to C values
const char *l = Manager::jenv->GetStringUTFChars(jl, 0);
const char *cl = Manager::jenv->GetStringUTFChars(cjl, 0);
QString line = QString(l);
QString color = QString(cl);
// Render line
for (int x = 0; x < Global::terminalWidth; x++) {
QColor bg = Renderer::colorForHex(color.mid(x + color.length() / 2, 1));
// Cell location on widget
int cellx = x * Global::cellWidth + Global::xoffset;
int celly = y * Global::cellHeight + Global::yoffset;
// Background
p.fillRect(cellx, celly, Global::cellWidth, Global::cellHeight, QBrush(bg));
// String
// Renders the image to the grid
Renderer::renderString(p, tc, text, cellx, celly);
}
// Release
Manager::jenv->ReleaseStringUTFChars(jl, l);
Manager::jenv->ReleaseStringUTFChars(cjl, cl);
}
The problem you're having is that every time you call a draw function on QPainter, it has an overhead in setting up the painter for what it needs to draw, especially when the pen and brush needs changing. As you're calling the function over 900 times, that's over 900 times that Painter needs to change its internal properties for rendering and would explain why commenting out the drawRect and drawString functions reduce the CPU usage.
To solve this problem you need to batch up all the same types of paint calls, where a type uses the same brush and pen. To do this you can use the class QPainterPath and add the objects that you need with functions such as addRect(..); ensuring you do this outside of the paint function!
If, for example, you were going to draw a chess board pattern, you would create two QPainterPath objects and add all the white squares to one and all the black to another. Then when it comes to drawing use the QPainter function drawPath. This would only require two calls to draw the entire board.
Of-course, if you need each square to be a different colour, then you're still going to have the same problem, in which case I suggest looking to generate an image of what you need and rendering that instead.

Window resizing and scaling images / Redeclaring back buffer size / C++ / DIRECTX 9.0

C++ / Windows 8 / Win api / DirectX 9.0
I am having real big issues with this:
https://github.com/jimmyt1988/TheGame/tree/master/TheGame
Problem is that I have defined some adjust coordinate functions. They are for when a window is resized and I need to offset all of my coordinates so that my mouse cooridnates are working out the correct collisions and also to scale and yet keep ratio locked for the images I am drawing to the screen.
For example, If I had a screen at 1920 x 1080 and then resized to 1376 x 768, I need to make sure that the bounding boxes for my objects (for when my mouse hovers over them) is adjusted on the mouse coordinates I use to use to check if the mouse was in the bounding box.
I found out that I originally had problems because when I resized my window, directX was automatically scaling everything.. and on top of that, I too was rescaling things, so they would get utterly screwed... I was told by someone that I need to re-declare my screen buffer width and height, which I have done keeping in mind there is a border to my window and also a menu at the top.
Can anyone see why... regardless of doing all this stuff, I am still getting the incorrect results.
If you manage to run my application: Pressing the 1 key will make the resolution 1920 x 1080, pressing the 2 key will make it 1376 x 768. The resize is entirely wrong: https://github.com/jimmyt1988/TheGame/blob/master/TheGame/D3DGraphics.cpp
float D3DGraphics::ResizeByPercentageChangeX( float point )
{
float lastScreenWidth = screen.GetOldWindowWidth();
float currentScreenWidth = screen.GetWindowWidth();
if( lastScreenWidth > currentScreenWidth + screen.GetWidthOffsetOfBorder() )
{
float percentageMoved = currentScreenWidth / lastScreenWidth;
point = point * percentageMoved;
}
return point;
}
float D3DGraphics::ResizeByPercentageChangeY( float point )
{
float lastScreenHeight = screen.GetOldWindowHeight();
float currentScreenHeight = screen.GetWindowHeight();
if( lastScreenHeight > currentScreenHeight + screen.GetHeightOffsetOfBorderAndMenu() )
{
float percentageMoved = currentScreenHeight / lastScreenHeight;
point = point * percentageMoved;
}
return point;
}
and yet if you put the return point above this block of code and just do nothing to it, it scales perfectly because of blooming directX regardless of this which is being called correctly (presparams are previously declared in the D3DGraphics construct and a reference held in the class its self:
void D3DGraphics::ResizeSequence()
{
presParams.BackBufferWidth = screen.GetWindowWidth() - screen.GetWidthOffsetOfBorder();
presParams.BackBufferHeight = screen.GetWindowHeight() - screen.GetHeightOffsetOfBorderAndMenu();
d3dDevice->Reset( &presParams );
}
This is the problem at hand:
Here is the code that makes this abomination of a rectangle:
void Game::ComposeFrame()
{
gfx.DrawRectangle( 50, 50, screen.GetWindowWidth() - screen.GetWidthOffsetOfBorder() - 100, screen.GetWindowHeight() - screen.GetHeightOffsetOfBorderAndMenu() - 100, 255, 0, 0 );
}
EDIT::::::::::::::::
I noticed that On MSDN it says:
Before calling the IDirect3DDevice9::Reset method for a device, an
application should release any explicit render targets, depth stencil
surfaces, additional swap chains, state blocks, and D3DPOOL_DEFAULT
resources associated with the device.
I have now released the vbuffer and reinstantiated it after the presparams and device are reset.
EDIT::::::::::::
I placed an HRESULT on my reset in which I now manage to trigger an error... But, well.. it doesn't really help me! : http://i.stack.imgur.com/lqQ5K.jpg
Basically, the issue was I was being a complete derp. I was putting into my rectangle the window width and then readjusting that size based on the oldwidth / newwidth.. well the new width was already the screen size... GRRRRRRR.