~ubuntu-branches/ubuntu/vivid/compiz/vivid

« back to all changes in this revision

Viewing changes to plugins/scale/src/scale.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release, Chris Townsend, Marco Trevisan (Treviño)
  • Date: 2014-06-06 09:43:06 UTC
  • mfrom: (3248.176.39)
  • Revision ID: package-import@ubuntu.com-20140606094306-pbrwu3aaaafox0z2
Tags: 1:0.9.11+14.10.20140606-0ubuntu1
[ Chris Townsend ]
* Only ungrab the Mod2Mask modifier on buttons 4-7 to allow scrolling
  in unfocused Gtk windows while still allowing keybinding modifiers
  to other scroll wheel actions. (LP: #1311788)
* Fix issue where window decorations would be placed under the Panel
  when opening a new window from an already open window. This is due
  to the already open window being taller or just as tall without be
  maximized than the workspace. (LP: #1303462)
* Only constrain the non-modifier scrolling to the vertical scrolling
  buttons - buttons 4 & 5. (LP: #1311303)
* Fix issue where maximized windows would get moved to different
  workspaces when disconnecting/connecting an external monitor.
  Windows should stay in the same workspace they are in when the
  monitor event occurs. (LP: #1304531)
* Fix issue where custom keyboard shortcuts would get reset to
  defaults when rebooting or restarting Compiz. (LP: #1063617)
* Fixes issue in the Expo plugin where a gap is shown in the place
  where the Launcher and Panel should be when windows are maximized.
  This was originally removed in rev. 3481. (LP: #1087090)
* Fix issue where horizontal and vertical keyboard resizing could not
  happen at the same time. (LP: #347390)

[ Marco Trevisan (Treviño) ]
* Scale: use XShape extension to exclude dnd input in the screen-parts
  outside workArea This will work property also in multi-monitor,
  without requiring multiple X windows for each output device. Also
  don't terminate the scale unless a drag-n-drop action is not really
  over. Add a spinner that shows up over a window, during the DnD
  timeout. Plus, make sure we terminate the scale without focusing the
  selected icon when cancelling it and some code cleanup (LP: #607796)
* Event: set the screen grabbed also when we get a NotifyWhileGrabbed
  Focus{In,Out} event (LP: #1305586)

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
#include <sys/time.h>
31
31
 
32
32
#include <X11/Xatom.h>
33
 
#include <X11/cursorfont.h>
 
33
#include <X11/extensions/shape.h>
34
34
 
35
35
#include <core/atoms.h>
36
36
#include <scale/scale.h>
244
244
            }
245
245
        }
246
246
    }
 
247
 
 
248
    if (spScreen->optionGetDndTimeoutSpinner () &&
 
249
        priv->window->id() == spScreen->selectedWindow &&
 
250
        priv->slot &&
 
251
        spScreen->hover.active ())
 
252
    {
 
253
        GLTexture* spinner = NULL;
 
254
 
 
255
        if (!spScreen->dndSpinners.empty ())
 
256
        {
 
257
            int speed = spScreen->optionGetDndTimeoutSpinnerSpeed ();
 
258
            unsigned dndSpinnerIdx = (spScreen->hover.minTime() - spScreen->hover.minLeft()) / speed;
 
259
            const GLTexture::List& tex_list = spScreen->dndSpinners[dndSpinnerIdx % spScreen->dndSpinners.size()];
 
260
            spinner = tex_list.empty() ? NULL : tex_list.front();
 
261
        }
 
262
 
 
263
        if (spinner)
 
264
        {
 
265
            float  scale;
 
266
            int    x, y;
 
267
            int    size;
 
268
            int    scaledWinWidth, scaledWinHeight;
 
269
            int    spinnerMaxSize = spinner->width();
 
270
 
 
271
            scaledWinWidth  = priv->window->width () * priv->scale;
 
272
            scaledWinHeight = priv->window->height () * priv->scale;
 
273
 
 
274
            size = MIN (spinnerMaxSize, MIN (scaledWinWidth, scaledWinHeight));
 
275
            x = priv->tx + priv->window->x () + (scaledWinWidth - size) / 2;
 
276
            y = priv->ty + priv->window->y () + (scaledWinHeight - size) / 2;
 
277
            scale = 1.0;
 
278
 
 
279
            if (size != spinnerMaxSize)
 
280
            {
 
281
                size = spinnerMaxSize;
 
282
                scale = MIN (scaledWinWidth, scaledWinHeight) / (float) spinnerMaxSize;
 
283
            }
 
284
 
 
285
            priv->cWindow->addDamageRect (CompRect (x, y, size / scale, size / scale));
 
286
 
 
287
            mask |= PAINT_WINDOW_BLEND_MASK;
 
288
 
 
289
            CompRegion            iconReg (0, 0, size, size);
 
290
            GLTexture::MatrixList ml (1);
 
291
 
 
292
            ml[0] = spinner->matrix ();
 
293
            priv->gWindow->vertexBuffer ()->begin ();
 
294
 
 
295
            if (size)
 
296
                priv->gWindow->glAddGeometry (ml, iconReg, iconReg);
 
297
 
 
298
            if (priv->gWindow->vertexBuffer ()->end ())
 
299
            {
 
300
                GLMatrix            wTransform (transform);
 
301
                GLWindowPaintAttrib sAttrib (attrib);
 
302
 
 
303
                wTransform.scale (scale, scale, 1.0f);
 
304
                wTransform.translate (x / scale, y / scale, 0.0f);
 
305
                sAttrib.brightness *= 0.65f;
 
306
 
 
307
                priv->gWindow->glDrawTexture (spinner, wTransform, sAttrib, mask);
 
308
            }
 
309
        }
 
310
    }
247
311
}
248
312
 
249
313
bool
924
988
                activateEvent (false);
925
989
                state = ScaleScreen::Idle;
926
990
 
 
991
                screen->handleEventSetEnabled (this, false);
927
992
                cScreen->preparePaintSetEnabled (this, false);
928
993
                cScreen->donePaintSetEnabled (this, false);
929
994
                gScreen->glPaintOutputSetEnabled (this, false);
982
1047
}
983
1048
 
984
1049
void
985
 
PrivateScaleScreen::sendDndStatusMessage (Window source)
 
1050
PrivateScaleScreen::sendDndStatusMessage (Window source, bool asks)
986
1051
{
987
1052
    XEvent xev;
988
1053
 
994
1059
    xev.xclient.window       = source;
995
1060
 
996
1061
    xev.xclient.data.l[0] = dndTarget;
997
 
    xev.xclient.data.l[1] = 2;
 
1062
    xev.xclient.data.l[1] = 0;
998
1063
    xev.xclient.data.l[2] = 0;
999
1064
    xev.xclient.data.l[3] = 0;
1000
1065
    xev.xclient.data.l[4] = None;
1001
1066
 
 
1067
    if (asks)
 
1068
    {
 
1069
        xev.xclient.data.l[1] = 1 << 0 | 1 << 1;
 
1070
        xev.xclient.data.l[4] = xdndActionAsk;
 
1071
    }
 
1072
 
 
1073
    XSendEvent (screen->dpy (), source, false, 0, &xev);
 
1074
}
 
1075
 
 
1076
void
 
1077
PrivateScaleScreen::sendDndFinishedMessage (Window source)
 
1078
{
 
1079
    XEvent xev;
 
1080
 
 
1081
    xev.xclient.type    = ClientMessage;
 
1082
    xev.xclient.display = screen->dpy ();
 
1083
    xev.xclient.format  = 32;
 
1084
 
 
1085
    xev.xclient.message_type = xdndFinished;
 
1086
    xev.xclient.window       = source;
 
1087
 
 
1088
    xev.xclient.data.l[0] = dndTarget;
 
1089
    xev.xclient.data.l[1] = 0; // Not accepted
 
1090
    xev.xclient.data.l[2] = None;
 
1091
 
1002
1092
    XSendEvent (screen->dpy (), source, false, 0, &xev);
1003
1093
}
1004
1094
 
1037
1127
    }
1038
1128
 
1039
1129
    if (ss->priv->dndTarget)
 
1130
    {
 
1131
        ss->priv->dndCheck.stop ();
1040
1132
        XUnmapWindow (::screen->dpy (), ss->priv->dndTarget);
 
1133
    }
1041
1134
 
1042
1135
    ss->priv->grab = false;
1043
1136
 
1103
1196
    if (!dndTarget)
1104
1197
    {
1105
1198
        XSetWindowAttributes attr;
1106
 
        long                 xdndVersion = 3;
 
1199
        long                 xdndVersion = 5;
1107
1200
 
1108
 
        attr.override_redirect = true;
 
1201
        attr.override_redirect = True;
1109
1202
 
1110
1203
        dndTarget = XCreateWindow (screen->dpy (), screen->root (),
1111
1204
                                   0, 0, 1, 1, 0, CopyFromParent,
1118
1211
                         (unsigned char *) &xdndVersion, 1);
1119
1212
    }
1120
1213
 
 
1214
    if (screen->XShape ())
 
1215
    {
 
1216
        CompRegion workAreaRegion;
 
1217
 
 
1218
        foreach (const CompOutput& output, screen->outputDevs ())
 
1219
            workAreaRegion |= output.workArea ();
 
1220
 
 
1221
        XShapeCombineRegion (screen->dpy (), dndTarget, ShapeBounding, 0, 0, workAreaRegion.handle (), ShapeSet);
 
1222
    }
 
1223
 
1121
1224
    XMoveResizeWindow (screen->dpy (), dndTarget,
1122
1225
                       0, 0, screen->width (), screen->height ());
1123
1226
    XMapRaised (screen->dpy (), dndTarget);
 
1227
    XSync (screen->dpy (), False);
1124
1228
 
1125
1229
    return true;
1126
1230
}
1212
1316
        }
1213
1317
        else if (!grabIndex)
1214
1318
        {
1215
 
            grabIndex = screen->pushGrab (cursor, "scale");
 
1319
            grabIndex = screen->pushGrab (screen->normalCursor (), "scale");
1216
1320
            if (grabIndex)
1217
1321
                grab = true;
1218
1322
        }
1249
1353
 
1250
1354
        cScreen->damageScreen ();
1251
1355
 
 
1356
        screen->handleEventSetEnabled (this, true);
1252
1357
        cScreen->preparePaintSetEnabled (this, true);
1253
1358
        cScreen->donePaintSetEnabled (this, true);
1254
1359
        gScreen->glPaintOutputSetEnabled (this, true);
1531
1636
            }
1532
1637
            else
1533
1638
            {
1534
 
                CompOption::Vector o (0);
1535
 
                CompAction         *action;
1536
 
 
1537
1639
                /* terminate scale mode if the recently closed
1538
1640
                 * window was the last scaled window */
1539
 
 
1540
 
                o.push_back (CompOption ("root", CompOption::TypeInt));
1541
 
                o[0].value ().set ((int) screen->root ());
1542
 
 
1543
 
                action = &optionGetInitiateEdge ();
1544
 
                scaleTerminate (action, CompAction::StateCancel, o);
1545
 
 
1546
 
                action = &optionGetInitiateKey ();
1547
 
                scaleTerminate (action, CompAction::StateCancel, o);
 
1641
                terminateScale (false);
1548
1642
                break;
1549
1643
            }
1550
1644
        }
1551
1645
    }
1552
1646
}
1553
1647
 
 
1648
void PrivateScaleScreen::terminateScale (bool accept)
 
1649
{
 
1650
    CompOption::Vector o (0);
 
1651
 
 
1652
    o.push_back (CompOption ("root", CompOption::TypeInt));
 
1653
    o[0].value ().set ((int) screen->root ());
 
1654
 
 
1655
    scaleTerminate (&optionGetInitiateEdge (), accept ? 0 : CompAction::StateCancel, o);
 
1656
    scaleTerminate (&optionGetInitiateKey (), accept ? 0 : CompAction::StateCancel, o);
 
1657
 
 
1658
    activateEvent (false);
 
1659
}
 
1660
 
1554
1661
bool
1555
1662
PrivateScaleScreen::hoverTimeout ()
1556
1663
{
1557
1664
    if (grab && state != ScaleScreen::In)
1558
1665
    {
1559
 
        CompWindow         *w;
1560
 
        CompOption::Vector o (0);
1561
 
 
1562
 
        w = screen->findWindow (selectedWindow);
 
1666
        CompWindow *w = screen->findWindow (selectedWindow);
1563
1667
        if (w)
1564
1668
        {
1565
1669
            lastActiveNum    = w->activeNum ();
1568
1672
            w->moveInputFocusTo ();
1569
1673
        }
1570
1674
 
1571
 
        o.push_back (CompOption ("root", CompOption::TypeInt));
1572
 
        o[0].value ().set ((int) screen->root ());
1573
 
 
1574
 
        scaleTerminate (&optionGetInitiateEdge (), 0, o);
1575
 
        scaleTerminate (&optionGetInitiateKey (), 0, o);
1576
 
    }
1577
 
 
 
1675
        terminateScale (true);
 
1676
    }
 
1677
 
 
1678
    return false;
 
1679
}
 
1680
 
 
1681
bool
 
1682
PrivateScaleScreen::dndCheckTimeout ()
 
1683
{
 
1684
    if (!dndTarget)
 
1685
        return false;
 
1686
 
 
1687
    CompWindow *w = screen->findWindow (dndTarget);
 
1688
 
 
1689
    if (!w || !w->isMapped ())
 
1690
        return false;
 
1691
 
 
1692
    Window drag_owner = XGetSelectionOwner (screen->dpy (), xdndSelection);
 
1693
 
 
1694
    if (drag_owner)
 
1695
    {
 
1696
        // evil hack because some apps (Qt) don't release the selection owner on drag finished
 
1697
        Window root_r, child_r;
 
1698
        int root_x_r, root_y_r, win_x_r, win_y_r;
 
1699
        unsigned int mask;
 
1700
        XQueryPointer (screen->dpy (), screen->root (), &root_r, &child_r,
 
1701
                       &root_x_r, &root_y_r, &win_x_r, &win_y_r, &mask);
 
1702
 
 
1703
        if (mask & (Button1Mask | Button2Mask | Button3Mask))
 
1704
            return true;
 
1705
    }
 
1706
 
 
1707
    terminateScale (false);
1578
1708
    return false;
1579
1709
}
1580
1710
 
1606
1736
                state != ScaleScreen::In)
1607
1737
            {
1608
1738
                XButtonEvent       *button = &event->xbutton;
1609
 
                CompOption::Vector o (0);
1610
 
 
1611
 
                o.push_back (CompOption ("root", CompOption::TypeInt));
1612
 
                o[0].value ().set ((int) screen->root ());
1613
1739
 
1614
1740
                /* Button1 terminates scale mode, other buttons can select
1615
1741
                 * windows */
1616
 
                if (selectWindowAt (button->x_root, button->y_root, true) &&
1617
 
                    event->xbutton.button == Button1)
1618
 
                {
1619
 
                    scaleTerminate (&optionGetInitiateEdge (), 0, o);
1620
 
                    scaleTerminate (&optionGetInitiateKey (), 0, o);
1621
 
                }
1622
 
                else if (optionGetClickOnDesktop () == 1 &&
1623
 
                         event->xbutton.button == Button1)
1624
 
                {
1625
 
                    CompPoint pointer (button->x_root, button->y_root);
1626
 
                    CompRect  workArea (screen->workArea ());
1627
 
                    workArea.setX (workArea.x() + optionGetXOffset ());
1628
 
                    workArea.setY (workArea.y() + optionGetYOffset ());
1629
 
 
1630
 
                    if (workArea.contains (pointer))
1631
 
                    {
1632
 
                        scaleTerminate (&optionGetInitiateEdge (), 0, o);
1633
 
                        scaleTerminate (&optionGetInitiateKey (), 0, o);
1634
 
                        screen->enterShowDesktopMode ();
1635
 
                    }
1636
 
                }
1637
 
                else if (optionGetClickOnDesktop () == 2 &&
1638
 
                         event->xbutton.button == Button1)
1639
 
                {
1640
 
                    CompPoint pointer (button->x_root, button->y_root);
1641
 
                    CompRect  workArea (screen->workArea ());
1642
 
                    workArea.setX (workArea.x() + optionGetXOffset ());
1643
 
                    workArea.setY (workArea.y() + optionGetYOffset ());
1644
 
 
1645
 
                    if (workArea.contains (pointer))
1646
 
                    {
1647
 
                        scaleTerminate (&optionGetInitiateEdge (), 0, o);
1648
 
                        scaleTerminate (&optionGetInitiateKey (), 0, o);
 
1742
                if (event->xbutton.button != Button1)
 
1743
                    break;
 
1744
 
 
1745
                if (selectWindowAt (button->x_root, button->y_root, true))
 
1746
                {
 
1747
                    terminateScale (true);
 
1748
                }
 
1749
                else if (optionGetClickOnDesktop () != ScaleOptions::ClickOnDesktopNone)
 
1750
                {
 
1751
                    CompPoint pointer (button->x_root, button->y_root);
 
1752
                    CompRect  workArea (screen->workArea ());
 
1753
                    workArea.setX (workArea.x() + optionGetXOffset ());
 
1754
                    workArea.setY (workArea.y() + optionGetYOffset ());
 
1755
 
 
1756
                    if (workArea.contains (pointer))
 
1757
                    {
 
1758
                        terminateScale (false);
 
1759
 
 
1760
                        if (optionGetClickOnDesktop () == ScaleOptions::ClickOnDesktopShowDesktop)
 
1761
                            screen->enterShowDesktopMode ();
1649
1762
                    }
1650
1763
                }
1651
1764
            }
1669
1782
            w = screen->findWindow (event->xdestroywindow.window);
1670
1783
            break;
1671
1784
        case UnmapNotify:
1672
 
 
1673
1785
             w = screen->findWindow (event->xunmap.window);
1674
1786
             break;
1675
1787
        case ClientMessage:
1676
1788
            if (event->xclient.message_type == Atoms::xdndPosition)
1677
1789
            {
1678
 
                w = screen->findWindow (event->xclient.window);
1679
 
                if (w)
 
1790
                if (event->xclient.window == dndTarget)
1680
1791
                {
1681
 
                    if (w->id () == dndTarget)
1682
 
                        sendDndStatusMessage (event->xclient.data.l[0]);
 
1792
                    bool acceptsDnd = false;
1683
1793
 
1684
 
                    if (grab                     &&
1685
 
                        state != ScaleScreen::In &&
1686
 
                        w->id () == dndTarget)
 
1794
                    if (grab && state != ScaleScreen::In)
1687
1795
                    {
 
1796
                        dndCheck.stop ();
 
1797
 
1688
1798
                        ScaleWindow *sw = checkForWindowAt (pointerX, pointerY);
1689
1799
                        if (sw && sw->priv->isScaleWin ())
1690
1800
                        {
1691
1801
                            int time;
1692
1802
 
1693
1803
                            time = optionGetHoverTime ();
 
1804
                            acceptsDnd = true;
1694
1805
 
1695
1806
                            if (hover.active ())
1696
1807
                            {
1697
1808
                                int lastMotion = sqrt (pow (pointerX - lastPointerX, 2) + pow (pointerY - lastPointerY, 2));
1698
 
                                
 
1809
 
1699
1810
                                if (sw->window->id () != selectedWindow || lastMotion > optionGetDndDistance ())
1700
1811
                                    hover.stop ();
1701
1812
                            }
1713
1824
                                hover.stop ();
1714
1825
                        }
1715
1826
                    }
1716
 
                }
1717
 
            }
1718
 
            else if (event->xclient.message_type == Atoms::xdndDrop ||
1719
 
                     event->xclient.message_type == Atoms::xdndLeave)
1720
 
            {
1721
 
                w = screen->findWindow (event->xclient.window);
1722
 
                if (w)
1723
 
                {
1724
 
                    if (grab                     &&
1725
 
                        state != ScaleScreen::In &&
1726
 
                        w->id () == dndTarget)
 
1827
 
 
1828
                    sendDndStatusMessage (event->xclient.data.l[0], acceptsDnd);
 
1829
                }
 
1830
            }
 
1831
            else if (event->xclient.message_type == Atoms::xdndEnter)
 
1832
            {
 
1833
                if (event->xclient.window == dndTarget &&
 
1834
                    grab && state != ScaleScreen::In)
 
1835
                {
 
1836
                    dndCheck.stop ();
 
1837
                }
 
1838
            }
 
1839
            else if (event->xclient.message_type == Atoms::xdndLeave)
 
1840
            {
 
1841
                if (event->xclient.window == dndTarget &&
 
1842
                    grab && state != ScaleScreen::In)
 
1843
                {
 
1844
                    dndCheck.start ();
 
1845
                }
 
1846
            }
 
1847
            else if (event->xclient.message_type == Atoms::xdndDrop)
 
1848
            {
 
1849
                if (event->xclient.window == dndTarget)
 
1850
                {
 
1851
                    sendDndFinishedMessage (event->xclient.data.l[0]);
 
1852
 
 
1853
                    if (grab && state != ScaleScreen::In)
1727
1854
                    {
1728
 
                        CompOption::Vector o (0);
1729
 
                        o.push_back (CompOption ("root", CompOption::TypeInt));
1730
 
                        o[0].value ().set ((int) screen->root ());
1731
 
 
1732
 
                        scaleTerminate (&optionGetInitiateEdge (), 0, o);
1733
 
                        scaleTerminate (&optionGetInitiateKey (), 0, o);
 
1855
                        terminateScale (true);
1734
1856
                    }
1735
1857
                }
1736
1858
            }
1746
1868
 
1747
1869
    switch (event->type) {
1748
1870
        case UnmapNotify:
 
1871
            dndCheck.start ();
1749
1872
            if (w)
1750
1873
                windowRemove (w);
1751
1874
            break;
1832
1955
    grab (false),
1833
1956
    grabIndex (0),
1834
1957
    dndTarget (None),
 
1958
    xdndSelection (XInternAtom (screen->dpy (), "XdndSelection", False)),
 
1959
    xdndFinished (XInternAtom (screen->dpy (), "XdndFinished", False)),
 
1960
    xdndActionAsk (XInternAtom (screen->dpy (), "XdndActionAsk", False)),
1835
1961
    state (ScaleScreen::Idle),
1836
1962
    moreAdjust (false),
1837
 
    cursor (0),
1838
1963
    nSlots (0)
1839
1964
{
1840
1965
    leftKeyCode  = XKeysymToKeycode (screen->dpy (), XStringToKeysym ("Left"));
1842
1967
    upKeyCode    = XKeysymToKeycode (screen->dpy (), XStringToKeysym ("Up"));
1843
1968
    downKeyCode  = XKeysymToKeycode (screen->dpy (), XStringToKeysym ("Down"));
1844
1969
 
1845
 
    cursor = XCreateFontCursor (screen->dpy (), XC_left_ptr);
1846
 
 
1847
1970
    opacity = (OPAQUE * optionGetOpacity ()) / 100;
1848
1971
 
1849
1972
    hover.setCallback (boost::bind (&PrivateScaleScreen::hoverTimeout, this));
 
1973
    dndCheck.setCallback (boost::bind (&PrivateScaleScreen::dndCheckTimeout, this));
 
1974
    dndCheck.setTimes (200);
1850
1975
 
1851
1976
    optionSetOpacityNotify (boost::bind (&PrivateScaleScreen::updateOpacity, this));
1852
1977
 
1883
2008
 
1884
2009
#undef SCALEBIND
1885
2010
 
 
2011
    CompString pluginName("scale");
 
2012
    CompSize size;
 
2013
    CompString file;
 
2014
 
 
2015
    file = "dnd-spinner-000.png";
 
2016
    dndSpinners.push_back(GLTexture::readImageToTexture(file, pluginName, size));
 
2017
    file = "dnd-spinner-125.png";
 
2018
    dndSpinners.push_back(GLTexture::readImageToTexture(file, pluginName, size));
 
2019
    file = "dnd-spinner-250.png";
 
2020
    dndSpinners.push_back(GLTexture::readImageToTexture(file, pluginName, size));
 
2021
    file = "dnd-spinner-375.png";
 
2022
    dndSpinners.push_back(GLTexture::readImageToTexture(file, pluginName, size));
 
2023
    file = "dnd-spinner-500.png";
 
2024
    dndSpinners.push_back(GLTexture::readImageToTexture(file, pluginName, size));
 
2025
    file = "dnd-spinner-625.png";
 
2026
    dndSpinners.push_back(GLTexture::readImageToTexture(file, pluginName, size));
 
2027
    file = "dnd-spinner-750.png";
 
2028
    dndSpinners.push_back(GLTexture::readImageToTexture(file, pluginName, size));
 
2029
    file = "dnd-spinner-875.png";
 
2030
    dndSpinners.push_back(GLTexture::readImageToTexture(file, pluginName, size));
 
2031
 
1886
2032
    ScreenInterface::setHandler (s);
1887
2033
    CompositeScreenInterface::setHandler (cScreen, false);
1888
2034
    GLScreenInterface::setHandler (gScreen, false);
1889
 
}
1890
2035
 
1891
 
PrivateScaleScreen::~PrivateScaleScreen ()
1892
 
{
1893
 
    if (cursor)
1894
 
        XFreeCursor (screen->dpy (), cursor);
 
2036
    screen->handleEventSetEnabled (this, false);
 
2037
    cScreen->preparePaintSetEnabled (this, false);
 
2038
    cScreen->donePaintSetEnabled (this, false);
 
2039
    gScreen->glPaintOutputSetEnabled (this, false);
1895
2040
}
1896
2041
 
1897
2042
void