~ubuntu-branches/ubuntu/oneiric/compiz/oneiric-proposed

« back to all changes in this revision

Viewing changes to src/window.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2011-07-19 08:00:29 UTC
  • mfrom: (0.168.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20110719080029-zn4l32f34modz570
Tags: 1:0.9.5.0-0ubuntu1
* New upstream release:
  - unity window decorator needs to support different metacity frame types
    (LP: #795048)
  - firefox window mapped fullscreen gets mapped under gnome-panel
    (LP: #800592)
* Switch to dpkg-source 3.0 (quilt) format
* remove all debian/patches/*:
  - upstream now directly deliver with our patches
* debian/control:
  - replace kdebase-workspace-dev build-dep by kde-workspace-dev
  - build on libdecoration0-dev to build the unity window decorator
  - make compiz-dev dep on gtk-3
* debian/compiz-plugins-default.install:
  - grid is now in -main
* debian/libdecoration0.symbols:
  - add new symbols
* debian/patches/01_don_t_init_a11y.patch:
  - don't initialize the GAIL and AT bridges when comipz initialize
    (LP: #810045)

Show diffs side-by-side

added added

removed removed

Lines of Context:
770
770
 
771
771
    if (input.left || input.right || input.top || input.bottom)
772
772
    {
773
 
        int        x, y, width, height;
 
773
        int        x, y, width, height;
774
774
        int        bw = serverGeometry.border () * 2;
775
775
 
776
776
        x      = serverGeometry.x () - input.left;
781
781
        if (shaded)
782
782
            height = input.top + input.bottom;
783
783
 
784
 
        XMoveResizeWindow (screen->dpy (), frame, x, y, width, height);
 
784
        /* Geometry is the same, so we're not going to get a ConfigureNotify
 
785
         * event when the window is configured, which means that other plugins
 
786
         * won't know that the client, frame and wrapper windows got shifted
 
787
         * around (and might result in display corruption, eg in OpenGL */
 
788
        if (geometry.x () - input.left == x &&
 
789
            geometry.y () - input.top  == y &&
 
790
            geometry.width () + input.left + input.right + bw == width &&
 
791
            geometry.height () + input.top + input.bottom + bw == height)
 
792
        {
 
793
            XConfigureEvent xev;
 
794
 
 
795
            xev.type   = ConfigureNotify;
 
796
            xev.event  = screen->root ();
 
797
            xev.window = priv->frame;
 
798
 
 
799
            xev.x                 = x;
 
800
            xev.y                 = y;
 
801
            xev.width             = width;
 
802
            xev.height            = height;
 
803
            xev.border_width      = window->priv->attrib.border_width;
 
804
 
 
805
            xev.above             = (window->prev) ? ROOTPARENT (window->prev) : None;
 
806
            xev.override_redirect = window->priv->attrib.override_redirect;
 
807
 
 
808
            XSendEvent (screen->dpy (), screen->root (), false,
 
809
                        SubstructureNotifyMask, (XEvent *) &xev);
 
810
        }
 
811
        else
 
812
            XMoveResizeWindow (screen->dpy (), frame, x, y, width, height);
 
813
 
785
814
        if (shaded)
786
815
        {
787
816
            XUnmapWindow (screen->dpy (), wrapper);
823
852
            XMoveResizeWindow (screen->dpy (), wrapper, 0, 0,
824
853
                               serverGeometry.width (), serverGeometry.height ());
825
854
        }
 
855
 
826
856
        XMoveResizeWindow (screen->dpy (), id, 0, 0,
827
857
                           serverGeometry.width (), serverGeometry.height ());
828
858
        window->sendConfigureNotify ();
829
859
        frameRegion = CompRegion ();
830
860
        window->windowNotify (CompWindowNotifyFrameUpdate);
831
861
    }
832
 
 
833
862
    window->recalcActions ();
834
863
}
835
864
 
1226
1255
        }
1227
1256
 
1228
1257
        XUngrabServer (screen->dpy ());
1229
 
        XSync (screen->dpy (), false);
1230
1258
    }
1231
1259
    else
1232
1260
    {
1314
1342
    if (priv->mapNum)
1315
1343
        priv->mapNum = 0;
1316
1344
 
 
1345
    /* Even though we're still keeping the backing
 
1346
     * pixmap of the window around, it's safe to
 
1347
     * unmap the frame window since there's no use
 
1348
     * for it at this point anyways and it just blocks
 
1349
     * input */
 
1350
 
 
1351
    XUnmapWindow (screen->dpy (), priv->wrapper);
 
1352
    XUnmapWindow (screen->dpy (), priv->frame);
 
1353
 
1317
1354
    priv->unmapRefCnt--;
1318
1355
    if (priv->unmapRefCnt > 0)
1319
1356
        return;
1425
1462
bool
1426
1463
CompWindow::resize (CompWindow::Geometry gm)
1427
1464
{
1428
 
    if (priv->geometry.x ()       != gm.width ()  ||
1429
 
        priv->geometry.y ()       != gm.height () ||
 
1465
    if (priv->geometry.width ()   != gm.width ()  ||
 
1466
        priv->geometry.height ()  != gm.height () ||
1430
1467
        priv->geometry.border ()  != gm.border ())
1431
1468
    {
1432
1469
        int pw, ph;
2001
2038
        }
2002
2039
 
2003
2040
        if (setFocus)
 
2041
        {
 
2042
            CompWindowList dockWindows;
 
2043
            XWindowChanges xwc;
 
2044
            unsigned int   mask;
 
2045
 
2004
2046
            screen->priv->nextActiveWindow = priv->id;
2005
2047
 
 
2048
            /* Ensure that docks are stacked in the right place
 
2049
             *
 
2050
             * When a normal window gets the focus and is above a
 
2051
             * fullscreen window, restack the docks to be above
 
2052
             * the highest level mapped and visible normal window,
 
2053
             * otherwise put them above the highest fullscreen window
 
2054
             */
 
2055
            if (PrivateWindow::stackDocks (this, dockWindows, &xwc, &mask))
 
2056
            {
 
2057
                Window sibling = xwc.sibling;
 
2058
                xwc.stack_mode = Above;
 
2059
 
 
2060
                /* Then update the dock windows */
 
2061
                foreach (CompWindow *dw, dockWindows)
 
2062
                {
 
2063
                    xwc.sibling = sibling;
 
2064
                    dw->configureXWindow (mask, &xwc);
 
2065
                }
 
2066
            }
 
2067
        }
 
2068
 
2006
2069
        if (!setFocus && !modalTransient)
2007
2070
        {
2008
2071
            CompWindow *ancestor;
2188
2251
            break;
2189
2252
        default:
2190
2253
            /* fullscreen and normal layer */
2191
 
            if (!(below->priv->type & belowMask))
 
2254
            if (!(below->priv->type & belowMask))
 
2255
            {
2192
2256
                if (stackLayerCheck (w, clientLeader, below))
2193
 
                    return below;
 
2257
                    return below;
 
2258
            }
2194
2259
            break;
2195
2260
        }
2196
2261
    }
2464
2529
}
2465
2530
 
2466
2531
bool
 
2532
PrivateWindow::stackDocks (CompWindow     *w,
 
2533
                           CompWindowList &updateList,
 
2534
                           XWindowChanges *xwc,
 
2535
                           unsigned int   *mask)
 
2536
{
 
2537
    CompWindow *firstFullscreenWindow = NULL;
 
2538
    CompWindow *belowDocks = NULL;
 
2539
 
 
2540
    foreach (CompWindow *dw, screen->windows ())
 
2541
    {
 
2542
        /* fullscreen window found */
 
2543
        if (firstFullscreenWindow)
 
2544
        {
 
2545
            /* If there is another toplevel window above the fullscreen one
 
2546
             * then we need to stack above that */
 
2547
            if (dw->focus () &&
 
2548
                !PrivateWindow::isAncestorTo (w, dw) &&
 
2549
                !(dw->type () & (CompWindowTypeFullscreenMask |
 
2550
                                 CompWindowTypeDockMask)) &&
 
2551
                !dw->overrideRedirect () &&
 
2552
                dw->defaultViewport () == screen->vp () &&
 
2553
                dw->isViewable ())
 
2554
            {
 
2555
                belowDocks = dw;
 
2556
            }
 
2557
        }
 
2558
        else if (dw->type () & CompWindowTypeFullscreenMask)
 
2559
        {
 
2560
            /* First fullscreen window found when checking up the stack
 
2561
             * now go back down to find a suitable candidate client
 
2562
             * window to put the docks above */
 
2563
            firstFullscreenWindow = dw;
 
2564
            for (CompWindow *dww = dw->prev; dww; dww = dww->prev)
 
2565
            {
 
2566
                if (!(dww->type () & (CompWindowTypeFullscreenMask |
 
2567
                                      CompWindowTypeDockMask)) &&
 
2568
                    !dww->overrideRedirect () &&
 
2569
                    dww->defaultViewport () == screen->vp () &&
 
2570
                    dww->isViewable ())
 
2571
                {
 
2572
                    belowDocks = dww;
 
2573
                    break;
 
2574
                }
 
2575
            }
 
2576
        }
 
2577
    }
 
2578
 
 
2579
    if (belowDocks)
 
2580
    {
 
2581
        *mask = CWSibling | CWStackMode;
 
2582
        xwc->sibling = ROOTPARENT (belowDocks);
 
2583
 
 
2584
        /* Collect all dock windows first */
 
2585
        foreach (CompWindow *dw, screen->windows ())
 
2586
            if (dw->priv->type & CompWindowTypeDockMask)
 
2587
                updateList.push_front (dw);
 
2588
 
 
2589
        return true;
 
2590
    }
 
2591
 
 
2592
    return false;
 
2593
}
 
2594
 
 
2595
bool
2467
2596
PrivateWindow::stackTransients (CompWindow      *w,
2468
2597
                                CompWindow      *avoid,
2469
2598
                                XWindowChanges *xwc,
2576
2705
    {
2577
2706
        CompWindowList transients;
2578
2707
        CompWindowList ancestors;
2579
 
        CompWindow     *siblingToThisWindow;
2580
 
        unsigned int   stackMode;
 
2708
        CompWindowList docks;
2581
2709
 
2582
2710
        /* Since the window list is being reordered in reconfigureXWindow
2583
2711
           the list of windows which need to be restacked must be stored
2599
2727
                xwc->sibling = ROOTPARENT (*w);
2600
2728
            }
2601
2729
 
2602
 
            /* First restack this window */
2603
2730
            this->priv->reconfigureXWindow (valueMask, xwc);
2604
 
            siblingToThisWindow = screen->findTopLevelWindow (xwc->sibling);
2605
 
            stackMode           = xwc->stack_mode;
2606
 
 
2607
2731
            xwc->sibling = ROOTPARENT (this);
2608
2732
 
2609
 
            /* Now restack the transient children above */
2610
2733
            for (CompWindowList::reverse_iterator w = transients.rbegin ();
2611
2734
                 w != transients.rend (); w++)
2612
2735
            {
2614
2737
                xwc->sibling = ROOTPARENT (*w);
2615
2738
            }
2616
2739
 
2617
 
            if (siblingToThisWindow && stackMode == Above)
 
2740
            if (PrivateWindow::stackDocks (this, docks, xwc, &valueMask))
2618
2741
            {
2619
 
                /* a normal window can be stacked above fullscreen windows but we
2620
 
                   don't want normal windows to be stacked above dock window so if
2621
 
                   the sibling we're stacking above is a fullscreen window we also
2622
 
                   update all dock windows. */
2623
 
                if ((siblingToThisWindow->priv->type & CompWindowTypeFullscreenMask) &&
2624
 
                    (!(this->priv-> type & (CompWindowTypeFullscreenMask |
2625
 
                                            CompWindowTypeDockMask))) &&
2626
 
                     !PrivateWindow::isAncestorTo (this, siblingToThisWindow))
2627
 
                {
2628
 
                    XWindowChanges dxwc;
2629
 
                    unsigned int   dmask = CWSibling | CWStackMode;
2630
 
                    CompWindow     *dw;
2631
 
 
2632
 
                    /* Find the sibling fullscreen window */
2633
 
                    for (dw = screen->windows ().back (); dw; dw = dw->prev)
2634
 
                        if (dw == siblingToThisWindow)
2635
 
                            break;
2636
 
 
2637
 
                    /* Collect all dock windows first */
2638
 
                    CompWindowList dockWindows;
2639
 
                    for (; dw; dw = dw->prev)
2640
 
                        if (dw->priv->type & CompWindowTypeDockMask)
2641
 
                            dockWindows.push_back (dw);
2642
 
 
2643
 
                    /* Then update the dock windows */
2644
 
                    foreach (CompWindow *dw, dockWindows)
2645
 
                    {
2646
 
                        /* Stack above the window being stacked above the docks */
2647
 
                        dxwc.stack_mode = Above;
2648
 
                        dxwc.sibling = ROOTPARENT (this);
2649
 
 
2650
 
                        dw->configureXWindow (dmask, &dxwc);
2651
 
                    }
2652
 
                }
2653
 
            }
 
2742
                Window sibling = xwc->sibling;
 
2743
                xwc->stack_mode = Above;
 
2744
 
 
2745
                /* Then update the dock windows */
 
2746
                foreach (CompWindow *dw, docks)
 
2747
                {
 
2748
                    xwc->sibling = sibling;
 
2749
                    dw->priv->reconfigureXWindow (valueMask, xwc);
 
2750
                }
 
2751
            }
2654
2752
        }
2655
2753
    }
2656
2754
    else
2878
2976
        case WestGravity:
2879
2977
        case SouthWestGravity:
2880
2978
            if (xwcm & CWX)
2881
 
                newX += priv->input.left * direction;
 
2979
                newX += priv->border.left * direction;
2882
2980
            break;
2883
2981
 
2884
2982
        case NorthGravity:
2885
2983
        case CenterGravity:
2886
2984
        case SouthGravity:
2887
2985
            if (xwcm & CWX)
2888
 
                newX -= (xwc->width / 2 - priv->input.left +
2889
 
                        (priv->input.left + priv->input.right) / 2) * direction;
 
2986
                newX -= (xwc->width / 2 - priv->border.left +
 
2987
                        (priv->border.left + priv->border.right) / 2) * direction;
2890
2988
            else
2891
2989
                newX -= (xwc->width - priv->serverGeometry.width ()) * direction;
2892
2990
            break;
2895
2993
        case EastGravity:
2896
2994
        case SouthEastGravity:
2897
2995
            if (xwcm & CWX)
2898
 
                newX -= xwc->width + priv->input.right * direction;
 
2996
                newX -= xwc->width + priv->border.right * direction;
2899
2997
            else
2900
2998
                newX -= (xwc->width - priv->serverGeometry.width ()) * direction;
2901
2999
            break;
3093
3191
        {
3094
3192
            if (!sibling)
3095
3193
            {
3096
 
                XLowerWindow (screen->dpy (), id);
3097
3194
                if (frame)
3098
3195
                    XLowerWindow (screen->dpy (), frame);
 
3196
                XLowerWindow (screen->dpy (), id);
3099
3197
 
3100
3198
                /* Restacking of compiz's window list happens
3101
3199
                 * immediately and since this path doesn't call
3337
3435
        {
3338
3436
            /* put active or soon-to-be-active fullscreen windows over
3339
3437
               all others in their layer */
3340
 
            if (priv->id == screen->activeWindow ())
 
3438
            if (priv->id == screen->activeWindow () ||
 
3439
                priv->id == screen->priv->nextActiveWindow)
3341
3440
            {
3342
3441
                aboveFs = true;
3343
3442
            }
4657
4756
PrivateWindow::processMap ()
4658
4757
{
4659
4758
    bool                   allowFocus;
4660
 
    bool                   wasManaged = priv->managed;
4661
4759
    CompStackingUpdateMode stackingMode;
4662
4760
 
4663
4761
    priv->initialViewport = screen->vp ();
4709
4807
 
4710
4808
    window->updateAttributes (stackingMode);
4711
4809
 
4712
 
    /* Window was either minimized by us, or it was mapped again
4713
 
     * since it has gone from withdrawn to iconic state, so
4714
 
     * unminimize it */
4715
 
    if (window->minimized () && (window->pendingMaps () || wasManaged))
 
4810
    if (window->minimized ())
4716
4811
        window->unminimize ();
4717
4812
 
4718
4813
    screen->leaveShowDesktopMode (window);
5115
5210
 
5116
5211
    startupId = getStartupId ();
5117
5212
 
5118
 
    if (oldId && startupId)
 
5213
    if (oldId)
5119
5214
    {
5120
5215
        if (strcmp (startupId, oldId) == 0)
5121
5216
            newId = false;
5171
5266
    return priv->syncAlarm;
5172
5267
}
5173
5268
 
5174
 
CompWindow::CompWindow (Window            aboveId,
 
5269
CompWindow *
 
5270
CoreWindow::manage (Window aboveId, XWindowAttributes &wa)
 
5271
{
 
5272
    return new CompWindow (aboveId, wa, priv);
 
5273
}
 
5274
 
 
5275
CoreWindow::CoreWindow (Window id)
 
5276
{
 
5277
    priv = new PrivateWindow ();
 
5278
    assert (priv);
 
5279
    priv->id = id;
 
5280
}
 
5281
 
 
5282
CompWindow::CompWindow (Window aboveId,
5175
5283
                        XWindowAttributes &wa,
5176
 
                        PrivateWindow     *priv) :
 
5284
                        PrivateWindow *priv) :
5177
5285
    PluginClassStorage (windowPluginClassIndices),
5178
5286
    priv (priv)
5179
5287
{
5205
5313
    priv->clientLeader = None;
5206
5314
 
5207
5315
    XSelectInput (screen->dpy (), priv->id,
 
5316
                  wa.your_event_mask |
5208
5317
                  PropertyChangeMask |
5209
5318
                  EnterWindowMask    |
5210
5319
                  FocusChangeMask);
5324
5433
    }
5325
5434
    else if (!overrideRedirect ())
5326
5435
    {
5327
 
        if (screen->priv->getWmState (priv->id) == IconicState ||
5328
 
            (priv->hints && priv->hints->initial_state == IconicState))
 
5436
        if (screen->priv->getWmState (priv->id) == IconicState)
5329
5437
        {
5330
5438
            // before everything else in maprequest
5331
5439
            if (!priv->frame)
5332
5440
                priv->reparent ();
5333
 
 
5334
 
            /* Not managed until map processing is done here
5335
 
             * since to go from Withdrawn -> Iconic the client
5336
 
             * needs to map the window again */
5337
 
            priv->managed = false;
5338
 
            priv->placed  = !(priv->hints && priv->hints->initial_state == IconicState);
5339
 
 
5340
 
            
5341
 
            /* FIXME: CompWindowStateShadedMask can't be set
5342
 
             * at this time anyways, so any window that wants
5343
 
             * to start out shaded will have to be minimized instead */
5344
 
            if (priv->state & CompWindowStateShadedMask)
5345
 
                priv->shaded = true;
5346
 
            else
5347
 
                priv->minimized = true;
 
5441
            priv->managed = true;
 
5442
            priv->placed  = true;
 
5443
 
 
5444
            if (priv->state & CompWindowStateHiddenMask)
 
5445
            {
 
5446
                if (priv->state & CompWindowStateShadedMask)
 
5447
                    priv->shaded = true;
 
5448
                else
 
5449
                    priv->minimized = true;
 
5450
            }
5348
5451
        }
5349
5452
    }
5350
5453
 
5365
5468
    }
5366
5469
}
5367
5470
 
5368
 
CompWindow *
5369
 
CoreWindow::manage (Window aboveId, XWindowAttributes &wa)
5370
 
{
5371
 
    return new CompWindow (aboveId, wa, priv);
5372
 
}
5373
 
 
5374
 
CoreWindow::CoreWindow (Window id)
5375
 
{
5376
 
    priv = new PrivateWindow ();
5377
 
    assert (priv);
5378
 
    priv->id = id;
5379
 
}
5380
 
 
5381
5471
CompWindow::~CompWindow ()
5382
5472
{
5383
5473
    screen->unhookWindow (this);
5695
5785
 
5696
5786
    if (!i)
5697
5787
        i = b;
5698
 
  
 
5788
 
5699
5789
    if (priv->input.left   != i->left ||
5700
5790
        priv->input.right  != i->right ||
5701
5791
        priv->input.top    != i->top ||
5722
5812
                         Atoms::frameExtents,
5723
5813
                         XA_CARDINAL, 32, PropModeReplace,
5724
5814
                         (unsigned char *) data, 4);
 
5815
 
5725
5816
        priv->updateSize ();
5726
5817
        priv->updateFrameWindow ();
5727
5818
    }
5784
5875
 
5785
5876
    if (parent_return != root_return)
5786
5877
    {
 
5878
        XFree (children);
5787
5879
        XUngrabServer (dpy);
5788
5880
        XSync (dpy, false);
5789
 
        XFree (children);
5790
5881
        return false;
5791
5882
    }
5792
5883
 
5834
5925
    /* Reparent the client into the wrapper window */
5835
5926
    XReparentWindow (dpy, id, wrapper, 0, 0);
5836
5927
 
5837
 
    attr.event_mask = PropertyChangeMask | FocusChangeMask |
5838
 
                      EnterWindowMask | LeaveWindowMask;
 
5928
    /* Restore events */
 
5929
    attr.event_mask = attrib.your_event_mask;
5839
5930
 
5840
5931
    /* We don't care about client events on the frame, and listening for them
5841
5932
     * will probably end up fighting the client anyways, so disable them */
5859
5950
    if (attrib.map_state == IsViewable || shaded)
5860
5951
        XMapWindow (dpy, frame);
5861
5952
 
5862
 
    attr.event_mask = SubstructureRedirectMask | StructureNotifyMask |
 
5953
    attr.event_mask = SubstructureRedirectMask |
5863
5954
                      SubstructureNotifyMask | EnterWindowMask |
5864
5955
                      LeaveWindowMask;
5865
5956
 
5881
5972
                  ExposureMask);
5882
5973
 
5883
5974
    XUngrabServer (dpy);
5884
 
    XSync (dpy, false);
5885
5975
 
5886
5976
    XMoveResizeWindow (dpy, frame, sg.x (), sg.y (), sg.width (), sg.height ());
5887
5977
 
5901
5991
    XWindowChanges       xwc;
5902
5992
    unsigned int         nchildren;
5903
5993
    Window               *children = NULL, root_return, parent_return;
 
5994
    XWindowAttributes    wa;
5904
5995
 
5905
5996
    if (!frame)
5906
5997
        return;
5912
6003
        XPutBackEvent (dpy, &e);
5913
6004
        alive = false;
5914
6005
    }
 
6006
    else
 
6007
    {
 
6008
        if (!XGetWindowAttributes (dpy, id, &wa))
 
6009
            alive = false;
 
6010
    }
5915
6011
 
5916
6012
    /* Also don't reparent back into root windows that have ended up
5917
6013
     * reparented into other windows (and as such we are unmanaging them) */
5947
6043
 
5948
6044
        XUnmapWindow (dpy, frame);
5949
6045
 
5950
 
        XSelectInput (dpy, id, PropertyChangeMask | EnterWindowMask |
5951
 
                      FocusChangeMask);
 
6046
        XSelectInput (dpy, id, wa.your_event_mask);
5952
6047
 
5953
6048
        XSelectInput (dpy, screen->root (),
5954
6049
                  SubstructureRedirectMask |
5965
6060
                  ExposureMask);
5966
6061
 
5967
6062
        XUngrabServer (dpy);
5968
 
        XSync (dpy, false);
5969
6063
 
5970
6064
        XMoveWindow (dpy, id, serverGeometry.x (), serverGeometry.y ());
5971
6065
    }