V41U
V41U

Reputation: 136

GdkCursor is randomly resetting to default with wglContext and gtk3

Short summary:

I have multiple GdkWindows that simultaneously get drawn into using OpenGL. For each of those windows it may happen that we want to set the GdkCursor. The change is registered and done, but randomly the cursor resets to the default pointer. This can be observed in my minimum working example as well. When moving the mouse around the mouse randomly 'flickers'.

I am looking for pointers where I can continue my research or whether this is a known bug. I have spent quite some time attempting to fix this in our application but so far no success. I am thankfull for anything!

More detailed explanation

We've recently upgraded from gtk2 to gtk3 (3.24 to be exact) and for this had to get rid of GtkGLExt as our OpenGL context as it does not support gtk3. Doing so we've decided to use wglContext and setting the render context ourself. We develop a heavily multi-threaded software where there's roughly a dozen of these contexts running simultaneously so we cannot go for a GdkGLContext as this is not thread-safe.

The rendering itself works and we have multiple GtkDrawingAreas where we render various images into from their corresponding thread and these are successfully displayed.

Problem

All of these DrawingAreas use GdkCursors to change the windows cursor so that the user can have a better usability. This worked like a charm in gtk2 and in gtk3 we're observing this weird behavior where the cursor is seemingly randomly resetting to the default cursor. When listening to the cursor changes we do not get any notification to this back-to-default-reset.

I have already tried GdkGLContext and with the minimal working example, and it works as wished. However, I did not find a way to have multiple render contexts be active for multiple threads at the same time using GdkGLContext. If I understand the documentation correctly, then GDK isn't supporting multi threading in Windows at all.

I would greatly appreciate any pointers as I'm getting to a point where I am loosing my mind about this issue.

Interesting note: We've also observed that if you drag the mouse while the left mouse button is pressed down the mouse cursor does NOT randomly reset. Maybe this is useful information, maybe not...

Minimal working example

This example gives a overview how we're setting up a single of these drawing areas. The window will be empty (as nothing is rendered) but the cursor flickering can still be observed.

#include <gtk/gtk.h>

#include "gdk/gdkwin32.h"
#ifdef WIN32
#   include <windows.h>
#endif
#include <GL/gl.h>
#include <GL/glu.h>
#include <glatter/glatter.h>

int main(int argc, char * argv[])
{
    // init gtk
    gtk_init(&argc, &argv);
    // just a simple window that contains a drawing area
    // that we want to use as the openGL context
    // and have a cursor stay
    auto pDialog = gtk_window_new(GtkWindowType::GTK_WINDOW_TOPLEVEL);
    auto pDrawingArea = gtk_drawing_area_new();
    gtk_container_add(GTK_CONTAINER(pDialog), pDrawingArea);
    gtk_widget_show_all(pDialog);
    auto pGDKwindow = gtk_widget_get_window(pDrawingArea);

    //// Add events to the event box
    gint iEvents = (GDK_POINTER_MOTION_MASK);
    gtk_widget_add_events(pDrawingArea, iEvents);
    g_object_ref_sink(pDrawingArea);

    // just a dumb bombardment of mouse changes on move
    g_signal_connect(pDrawingArea,
                     "motion-notify-event",
                     G_CALLBACK(+[](GtkWidget * pWidget, gpointer data)
                                {
                                    auto pCursor = gdk_cursor_new(GdkCursorType::GDK_DOUBLE_ARROW);
                                    gdk_window_set_cursor(gtk_widget_get_window(pWidget), pCursor);
                                    gdk_cursor_unref(pCursor);

                                    return FALSE;
                                }),
                     NULL);

    //opengl context creation (see https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context_(WGL) )
    PIXELFORMATDESCRIPTOR pfd =
        {
            .nSize = sizeof(pfd),
            .nVersion = 1,
            .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
            .iPixelType = PFD_TYPE_RGBA,
            .cColorBits = 32,
            .cAlphaBits = 8,
            .cDepthBits = 24,
            .cStencilBits = 8,
            .iLayerType = PFD_MAIN_PLANE,
        };

    HDC window_dc = GetDC(static_cast<HWND>(gdk_win32_window_get_handle(pGDKwindow)));

    int pixel_format = ChoosePixelFormat(window_dc, &pfd);
    SetPixelFormat(window_dc, pixel_format, &pfd);
    HGLRC context = wglCreateContext(window_dc);
    wglMakeCurrent(window_dc, context);

    // just iterate to show the window and display the bug
    do
    {
        gtk_main_iteration_do(true);
    } while (true);

    return 0;
}


Upvotes: 1

Views: 131

Answers (0)

Related Questions