Bug 313909

Summary: XReconfigureWMWindow fails to stack (lower) a window using an Above CWSibling combination
Product: [Plasma] kwin Reporter: keith.kriewall
Component: coreAssignee: KWin default assignee <kwin-bugs-null>
Status: RESOLVED FIXED    
Severity: normal Flags: thomas.luebking: ReviewRequest+
Priority: NOR    
Version: 4.9.4   
Target Milestone: 4.11   
Platform: Ubuntu   
OS: Linux   
Latest Commit: Version Fixed In: 4.11
Sentry Crash Report:

Description keith.kriewall 2013-01-25 23:38:01 UTC
Bug 288721 corrected window stacking when a relative sibling window was specified, with one exception.  A window cannot be stacked lower by using an Above <sibling> reference.

Reproducible: Always

Steps to Reproduce:
Compile and run the following test application.  

/* 
 * File:   main.cpp
 * Created on January 15, 2013, 6:42 PM
 */
#include <stdlib.h>
#include <unistd.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

static const int width = 150;
static const int height = 100;
static const int visibleStepDelay = 2;

Window createManagedWindow(Display* disp, int x, int y, const char* fgColorName, const char* windowName)
{
    int screen_num = DefaultScreen(disp);

    XColor screenDef;
    XAllocNamedColor(disp, DefaultColormap(disp, screen_num), fgColorName, &screenDef, &screenDef);

    Window result = XCreateSimpleWindow(
            disp,
            RootWindow(disp, screen_num),
            x, y, width, height, 3,
            BlackPixel(disp, screen_num),   // border pixel
            screenDef.pixel                 // background pixel
    );

    XSizeHints* sizeHints = XAllocSizeHints();
    sizeHints->x = x;
    sizeHints->y = y;
    sizeHints->width = width;
    sizeHints->height = height;
    sizeHints->flags = USPosition | USSize;
    XSetWMNormalHints(disp, result, sizeHints);

    XStoreName(disp, result, windowName);

    XMapWindow(disp, result);
    XFlush(disp);
    sleep(visibleStepDelay);
    return result;
}

void stackWindow(Display* disp, Window winToStack, int aboveOrBelow, Window relativeTo)
{
    int screen_num = DefaultScreen(disp);
    XWindowChanges xwc;
    unsigned int mask;

    xwc.stack_mode = aboveOrBelow;
    mask = CWStackMode;
    if (relativeTo != 0)
    {
        xwc.sibling = relativeTo;
        mask |= CWSibling;
    }

    XReconfigureWMWindow(
            disp,
            winToStack,
            screen_num,
            mask,
            &xwc);
    XFlush(disp);
    sleep(visibleStepDelay);
}

int main(int argc, char** argv)
{
	Display * disp = XOpenDisplay("");

    // create three managed windows; window stacking (bottom to top) is 2 3 1
    Window win1, win2, win3;
    win2 = createManagedWindow(disp, 40, 40, "green", "Win 2");
    win3 = createManagedWindow(disp, 70, 70, "red",   "Win 3");
    win1 = createManagedWindow(disp, 10, 10, "blue",  "Win 1");

    // RAISE 2 by stacking it BELOW 1; window stacking now 3 2 1
    stackWindow(disp, win2, Below, win1);

    // stack 2 on bottom to restore original order; stacking now 2 3 1
    stackWindow(disp, win2, Below, 0);

    // RAISE 2 by stacking it ABOVE 3; window stacking now 3 2 1
    stackWindow(disp, win2, Above, win3);

    // stack 2 on bottom to restore original order; stacking now 2 3 1
    stackWindow(disp, win2, Below, 0);

    // LOWER 1 by stacking it ABOVE 2; stacking should be 2 1 3  [FAIL - stacking unchanged]
    stackWindow(disp, win1, Above, win2);

    // LOWER 1 by stacking it BELOW 3; stacking should be 2 1 3 [SUCCESS]
    stackWindow(disp, win1, Below, win3);

    XCloseDisplay(disp);
    return (EXIT_SUCCESS);
}
Actual Results:  
The visible steps of this application are:
  - Creates three windows, stacked (2 - 3 - 1) from bottom to top
  - Raise 2 "below 1" (3 - 2 - 1)
  - restore original stacking (2 - 3 - 1)
  - Raise 2 "above 3" (3 - 2 - 1)
  - restore original stacking (2 - 3 - 1)
  - Lower 1 "above 2" [FAILS - stacking is unchanged]
  - Lower 1 "below 3" (2 - 1 - 3)

Expected Results:  
The second to last step, with a starting stacking of (2 - 3 - 1) should have produced:
 - Lower 1 "above 2" (2 - 1 - 3)
Comment 1 Thomas Lübking 2013-01-26 21:39:17 UTC
https://git.reviewboard.kde.org/r/108609/

Thanks for the superb style of the report btw!
(Seriously. Compared to usual "does not works" junk, this is great to debug =)
Comment 2 Thomas Lübking 2013-01-26 21:55:41 UTC
FYI:
Compiz & Sawfish will act as you expect (and KWin with propsed patch)

- OpenBox will not stack ... reasonably (and esp. not down Above - it does perform a SO change but i've not tested which one is actually respected)
- Metacity does "something" (the windows do not appear in expected order, then seem to act correctly - but no downwards stack Above either)
- IceWM does not care about the requests altogether ;-)

I'll try E17 later on (unless you already have?)
Comment 3 Thomas Lübking 2013-01-30 12:34:47 UTC
Git commit e8fb7cd14fd7db3fc18afad1bab5f98f6de9f44b by Thomas Lübking.
Committed on 26/01/2013 at 22:22.
Pushed by luebking into branch 'master'.

don't shortcut Above restacks

just because we're above the sibling.
There could be another sibling to get below.
REVIEW: 108609
FIXED-IN: 4.11

M  +0    -2    kwin/layers.cpp

http://commits.kde.org/kde-workspace/e8fb7cd14fd7db3fc18afad1bab5f98f6de9f44b