GNOME Bugzilla – Bug 763783
GDK W32: Erase hidden layered windows before showing them
Last modified: 2016-03-29 14:34:37 UTC
Layered windows are not redrawn automatically when they are made visible. Instead Windows WM just re-uses their old contents until we update them with UpdateLayeredWindow(). This is a problem, because GDK does not keep track of hidden windows (does not redraw them and, according to Company, ignores invalidations) and does not redraw a window before making it visible. It schedules a redraw when window is shown, but it doesn't happen immediately. Meanwhile the window is made visible with the old content. That looks awful when window content *should* have changed. How to reproduce: 1) Create a window with a malleable widget (label, for example) 2) Set label text to "aaaaaaaaaaaa" 3) Show window 4) Hide window 5) Set label text to "bbbbbbbbbbbb" 6) Show window Expected result: Window is shown with "bbbbbbbbbbbb" Actual result: Window is shown with "aaaaaaaaaaaa" for the first 16 milliseconds or so, then quickly switches to "bbbbbbbbbbbb". Alternatively: 1) Run Glade 2) Hover over items in Glade widget palette to call the tooltip 3) Move pointer between items Expected result: Tooltip shows up with different text for different items Actual result: Tooltip shows up with the text for previous item, then quickly redraws itself to contain the text for the new item (very noticeable if text has different length, which means that tooltip width also changes).
Created attachment 324138 [details] [review] GDK W32: Erase hidden layered windows before showing them If a layered window was hidden and is made visible, erase its contents before showing it. GDK will schedule a redraw, but until then we generally don't want to show old contents.
Alternative version of this patch would take extra argument (GdkWindow corresponding to hWnd) and would clear and use actual layered window cache instead of creating a short-lived surface for that purpose. It would guarantee that window won't re-use old content, because it would clear the only cache we have, while current version keeps the cache intact and just erases the window (thus, if between erase and redraw something makes a call that ends in UpdateLayeredWindow() from cache, window will get old contents back). I went with this version, because it doesn't require argument changes for ShowWindow() calls, just a name change. Now that i'm thinking of it, this change should probably also cover SetWindowPos(), because it could be used to show a window. But that would be just for completeness, current version covers all the actual cases (that i could see in with real apps) where hidden window is shown with old contents.
Created attachment 324168 [details] [review] GDK W32: Erase hidden layered windows before showing them v2: * Fixed a typo
Review of attachment 324168 [details] [review]: Hi LRN, This reminds me of the video game "Psycho Pinball" where the game says "You need a quick eye to see this"--this issue is also seem from displaying various tooltips in the "Tool Palette" demo by hovering above the icons. I believe Nacho is better than finding code styling issues than me, but I think otherwise the code looks and works well for me in this respect. With blessings, thanks and cheers! ::: gdk/win32/gdkwindow-win32.c @@ +1313,1 @@ } Ah, the nasty tab disguised as spaces that eludes our eyes... perhaps change these to spaces?
Created attachment 324779 [details] [review] GDK W32: Erase hidden layered windows before showing them v3: * Fixed a nitpick
Review of attachment 324779 [details] [review]: Fine for me. Just minor niptick with the name of the vars. ::: gdk/win32/gdkwindow-win32.c @@ +4160,3 @@ +BOOL WINAPI +GtkShowWindow (HWND hWnd, + int nCmdShow) cmd_show and hwnd
Created attachment 324895 [details] [review] GDK W32: Erase hidden layered windows before showing them v4: * Fixed a nitpick
Review of attachment 324895 [details] [review]: Fine for me.
Attachment 324895 [details] pushed as 77eebbd - GDK W32: Erase hidden layered windows before showing them