After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 666842 - [patch] "sticky" window state reported wrongly on X11
[patch] "sticky" window state reported wrongly on X11
Product: gtk+
Classification: Platform
Component: Backend: X11
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
Depends on:
Reported: 2011-12-25 20:26 UTC by John Lindgren
Modified: 2011-12-28 16:24 UTC
See Also:
GNOME target: ---
GNOME version: ---

Patch: report window "sticky" state correctly (698 bytes, patch)
2011-12-25 20:26 UTC, John Lindgren
none Details | Review

Description John Lindgren 2011-12-25 20:26:09 UTC
Created attachment 204207 [details] [review]
Patch: report window "sticky" state correctly

Problem has been reported in various places:

GTK's "window-state-event" reports completely bogus values for GDK_WINDOW_STATE_STICKY.  Installed version of GTK/GDK is 3.2.3, but the problem has been there for years, probably since the code was first written.  There are actually two problems:

Problem #1: In gdk_check_wm_desktop_changed() in gdkdisplay-x11.c, XGetWindowProperty() returns the 32-bit value (a "CARDINAL") of _NET_WM_DESKTOP in a 64-bit signed "long".  The problem lies in the fact that the X11 API leaves undefined the value of the high 32 bits in the "long".  If you look at the X11 source (_doXRead32() in XlibInt.c), the actual behavior alternates between extending the sign bit of the 32-bit word through the high bits of the 64-bit word and setting the high bits all to zero.  Hence the only correct option for GDK is to ignore the high 32 bits of the 64-bit word completely.  Instead, GDK first casts the signed 64-bit "long" to an unsigned 64-bit "gulong" (which is odd but not a problem) and then compares that "gulong" to the value 0xFFFFFFFF (which is wrong).  On my system, the result is that toplevel->on_all_desktops is always set to FALSE.  My patch masks off the high 32 bits of the "gulong" before the comparison.

Problem #2: In do_net_wm_state_changes() in gdkdisplay-x11.c, the logic used to decide whether to set or clear the GDK_WINDOW_STATE_STICKY flag is inconsistent.  The flag is set when either toplevel->have_sticky or toplevel->on_all_desktops are TRUE and cleared when either of the same are FALSE.  This means that when toplevel->have_sticky is TRUE but toplevel->on_all_desktops is FALSE (due to problem #1), GDK repeatedly flips GDK_WINDOW_STATE_STICKY back and forth.  My patch changes the behavior to only set GDK_WINDOW_STATE_STICKY when both toplevel->have_sticky and toplevel->on_all_desktops are TRUE.