GNOME Bugzilla – Bug 666842
[patch] "sticky" window state reported wrongly on X11
Last modified: 2011-12-28 16:24:38 UTC
Created attachment 204207 [details] [review] Patch: report window "sticky" state correctly Problem has been reported in various places: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=567607 https://bugzilla.xfce.org/show_bug.cgi?id=6192 http://redmine.audacious-media-player.org/issues/16 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.