Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Register
  • Sign in
  • gtk gtk
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 1.6k
    • Issues 1.6k
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 239
    • Merge requests 239
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • GNOMEGNOME
  • gtkgtk
  • Issues
  • #147
Closed
Open
Issue created Mar 29, 2018 by LRN@lrnDeveloper

Mouse cursor handling is broken in GTK4

Steps to reproduce

  1. Run gtk4-demo
  2. Move mouse around
  3. Try to resize window

Current behavior

Mouse cursor often disappears, sometimes the cursor is not the right kind for the widget under the pointer, and it crashes eventually

Expected outcome

Everything should work

Version information

GTK4 master, W32

Additional information

I blame @fanc999 for this, it's due to a quick and dirty fix for GTK4 to compile after GdkCursor changes.

  1. It doesn't take into account cursor status and will try to call DestroyCursor() on cursors that must not be destroyed (see this MSDN page for the list of cursors that must not be destroyed)

  2. gdk_window_set_cursor() unrefs the window cursor at the beginning of the function. If that was the last reference, the cursor gets destroyed, and if it's still in use GDK does call SetCursor (NULL), which hides the cursor. gdk_window_set_cursor() creates and sets new cursor afterwards (more often than not - the same cursor!), but nevertheless there's a brief moment when there's no cursor. That can cause cursor blinking.

  3. (this might actually be caused by other commits made by this point, not by this specific patch) WM_SETCURSOR handler does not try to set cursor for the window under the cursor, it can only set cursor if there's a grab. Note that Windows is not X. On X we have XDefineCursor(), which sets cursor for a specific X window. On Windows the cursor is global and handling WM_SETCURSOR is the way to set specific cursor for a specific window. In the same vein, set_window_cursor() function shouldn't call SetCursor() if the window is not under the cursor (though, luckily, it is currently called only in these exact circumstances, so nothing weird actually happens).

I think that the right fix for this is to roll the code back somewhat and reintroduce a Windows cursor class (not necessarily a subclass of GdkCursor) that keeps track of the HCURSOR type (to avoid destroying shared cursors), knows how to defer DestroyCursor() until the cursor is no longer in use (or just delay it for a bit, to ensure that the code up the stack had a chance to set a new cursor, which might be the same as the old one, in which case there's no need to destroy anything). And W32 window impl should either keep the cursor set for this window around, or we should call gdk_window_get_cursor () (keeping a HCURSOR means that we avoid a hashtable lookup, so that way we save up on CPU cycles).

Assignee
Assign to
Time tracking