Merge lp://qastaging/~compiz-team/compiz-core/compiz-core.stack_sync_fix into lp://qastaging/compiz-core/0.9.5

Proposed by Sam Spilsbury
Status: Merged
Merged at revision: 2824
Proposed branch: lp://qastaging/~compiz-team/compiz-core/compiz-core.stack_sync_fix
Merge into: lp://qastaging/compiz-core/0.9.5
Diff against target: 3069 lines (+1526/-428) (has conflicts)
16 files modified
include/core/core.h (+1/-1)
include/core/screen.h (+5/-1)
include/core/window.h (+4/-0)
plugins/composite/src/privates.h (+2/-0)
plugins/composite/src/screen.cpp (+35/-2)
plugins/composite/src/window.cpp (+2/-0)
plugins/decor/src/decor.cpp (+6/-15)
src/CMakeLists.txt (+1/-0)
src/event.cpp (+100/-64)
src/main.cpp (+11/-0)
src/privatescreen.h (+7/-0)
src/privatestackdebugger.h (+78/-0)
src/privatewindow.h (+2/-0)
src/screen.cpp (+271/-101)
src/stackdebugger.cpp (+487/-0)
src/window.cpp (+514/-244)
Text conflict in src/window.cpp
To merge this branch: bzr merge lp://qastaging/~compiz-team/compiz-core/compiz-core.stack_sync_fix
Reviewer Review Type Date Requested Status
Robert Carr (community) Approve
Sam Spilsbury Abstain
Review via email: mp+74815@code.qastaging.launchpad.net

Description of the change

Fixes some of the problems in bug 845719

Changes
1) Push destroyed windows into a separate tree which plugins can query in case they are holding references to them rather than keeping them in screen->windows () where they will only server to confuse the stacking code in the case of xid conflicts.
2) Use a separate serverWindows and windows in order to calculate pending restacking operations on windows last sent to server and last recieved from the server, rather than immediately restacking the window list and running the risk of having a ConfigureNotify come back and be processed relative to the stacking operation that was not in sync with the server and thus be invalid
3) Grab the server and directly query the tree whenever issuing synethetic ConfigureNotify events such that they will always be emitted relative to whats on the server rather than a half-complete version of what was last received from the server
4) Remove dead code
5) Wait for the server to issue a CreateNotify event for frame windows before adding them to the tree so that ConfigureNotify events that come before the CreateNotify event are not processed in an invalid way
6) Immediately remove windows from the window list on DestroyNotify
7) Ensure that we initiate all windows directly after querying the tree on startup to avoid race conditions where we will never receive a CreateNotify event for windows that are changing their state during a compositor or WM restart
8) Manage windows from top to bottom on startup
9) Don't force restack windows since the stack is already correct when we've managed all windows
10) When processing DestroyNotify events remove the client window from the list and create a CompWindow for it's frame as that has not been destroyed yet and we may receive ConfigureNotify events from previously processed ConfigureRequest events that are relative to the frame. It is safe to remove that CompWindow once the frame receives a DestroyNotify
11) Do not immediately update the last received stack on reconfigureXWindow
12) Added stack sync debugger object
13) Added stack sanity debugger object
14) Do not destroy window frames, instead keep them around in a separate map and unmap them (but keep them in the stack since clients may want to restack relative to them). When the withdrawn window is mapped again put it back into the same frame (keeping the frame below the client) (NB: This is a bit of a weird solution, but it works and might be something that we want to come back to later).
15) Process CreateNotify events relative to the last last recv from the server

Stuff that needs fixing
=======================

Apparantly firefox stacking can still go a bit wonky
We need to check the stack sync on Create and DestroyNotify events

Debugging Plan:
===============

I did the necessary changes in core to ensure that the stack you'd get if you grabbed the server, did XQueryTree, and then queued all events and ungrabbed the server at the start of PrivateScreen::processEvents would be exactly the same as the "last recieved from server" stack at the end of PrivateScreen::processEvents after processing ConfigureNotify events for windows which have had their stack positions updated.

As such, we can now reliably debug and warn when the stacks go out of sync. If you run with --debug, core will do XQueryTree at the beginning of each ::processEvents and compare that stack with the results of screen->windows () at the end of processEvents. If there is a mismatch, it will warn. A flag can also be changed in the code (specifically, StackDebugger::cmpStack (windows, serverWindows, verbose = false)) to enable a full readout of each stack, and indications of where there are mismatches. You can easily put a breakpoint there to trace which sets of communication/response are causing problems.

The other kind of stacking bug is where data is sent and received from the server correctly, but the stacking order sent to the server is not correct as defined by the Extended Window Manager Hints [1]. Though there are some omissions in the standard, the expected stacking order is from top to bottom:

 - 1) Docks stacked above toplevel windows which are stacked
      above fullscreen windows
 - 2) "Keep above" toplevel windows above fullscreen windows
      where a toplevel is in focus
 - 3) Toplevel windows in focus above fullscreen windows
 - 4) Fullscreen windows
 - 5) Dock windows
 - 6) Keep above windows
 - 7) Toplevel windows
 - 8) Docks which are marked "Keep Below"
 - 9) "Keep Below" windows
 - 10) Desktop windows

 There are also a few rules which apply here:
 - 1) Dock windows should always be above normal windows
      except if marked keep below on any layer.
 - 2) Dock windows should ONLY be on one layer at a time,
      eg if they are on layer 1 then there cannot
      also be dock windows on layer 5 (except in the
      case of below dock windows on layer 8)
 - 3) Fullscreen windows must always be above docks when in
      focus, no matter if there is another window with "Keep Above"
 - 4) Focused windows take priority over fullscreen windows and
      docks must always be above them (see rule 1)

The code in StackDebugger::checkSanity will check the outgoing stack to see if it matches these criteria, and if not, it will warn when doing so. In the vast majority of cases, I've found that this works fine, but there are a few edge cases where it still warns and there are visible errors (eg, with a Keep Above window and 2 Toplevels above a fullscreen with docks above them, grabbing one of the toplevels will place it below the fullscreen window, which is incorrectly).

[1] http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#STACKINGORDER

To post a comment you must log in.
2803. By Sam Spilsbury

Remove wrong code and fix typo

2804. By Sam Spilsbury

Fix some more typos, don't hold a server grab while initing the windows
since when loading plugins on the command line windowInitPlugins might be
called and then the opengl plugin will be loaded while we have a server grab
and that doesn't work on some drivers.

2805. By Sam Spilsbury

We process CreateNotify events relative to events so use the stack last
received from the server rather than the one that was last sent

2806. By Sam Spilsbury

We don't set the id of destroyed windows to 1 anymore on the first call
to ::destroy so check the destroy reference count instead

2807. By Sam Spilsbury

Also check the destroyed flag

2808. By Sam Spilsbury

Check if destroyRefCnt is 1, not 0

2809. By Sam Spilsbury

Immediately remove destroyed windows from the stacks last sent to the server
and last received from the server.

Having destroyed windows there was used as a means to have plugins keep references
to them for, eg, close animations. However, keeping them there meant that we needed
to resort to ugly hacks like setting the id to 0 and explicitly ignoring them in the
plugins if they were destroyed. It also meant that there could be stack sync problems
since a window could be restacked relative to an older destroyed window that was still
in the stack.

Now destroyed windows are pushed into a separate stack in the API and accessible only
through there. The composite plugin was also changed to paint both referenced destroyed
windows (since their textures are still valid) and also normal windows in the case
that there are referenced destroyed windows. This may require some changes in plugins
which might use screen->findWindow () or screen->windows () in order to locate or
process destroyed windows - they should use the composite plugin's getWindowPaintList
instead or also process screen->destroyedWindows ()

2810. By Sam Spilsbury

Fix typo

2811. By Sam Spilsbury

Fix a typo that was causing decoration frames to be added as normal windows (causing
stack sync problems) and improve the heuristics of the stack sync debugger

2812. By Sam Spilsbury

Bump ABI since we added a new mfunc

2813. By Sam Spilsbury

Merge in StackDebugger stack sanity checker

2814. By Sam Spilsbury

Merge in destroyed windows fix

2815. By Sam Spilsbury

Manage windows from bottom to top again.

Managing them this way makes debugging more of a pain, but core has a preference
for managing windows such that they'd be on top of everything on the stack, so
don't mess with that.

2816. By Sam Spilsbury

Merge in more stacking fixes

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Stuff that needs fixing at some point:

GIMP Stacking is broken (but this is probably unrelated)
Windows are not unreparented on iconification
The way that we handle unreparenting is a bit strange, keeping frame windows around.

review: Abstain
Revision history for this message
Robert Carr (robertcarr) wrote :

Sam walked me through all of this on IRC, i.e. where the problems come from and why approach them this way, and it all seems good. I'm a little hesitant about the detachedFrameWindows stuff, but it makes sense and as far as I can tell should work fine.

Gave the diff a walk through to make sure all the code seems to do what Sam told me it should do and it all looks good.

+1 from me.

review: Approve
2817. By Sam Spilsbury

Merge in further stacking fixes

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
The diff is not available at this time. You can reload the page or download it.

Subscribers

People subscribed via source and target branches