248
if (spScreen->optionGetDndTimeoutSpinner () &&
249
priv->window->id() == spScreen->selectedWindow &&
251
spScreen->hover.active ())
253
GLTexture* spinner = NULL;
255
if (!spScreen->dndSpinners.empty ())
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();
268
int scaledWinWidth, scaledWinHeight;
269
int spinnerMaxSize = spinner->width();
271
scaledWinWidth = priv->window->width () * priv->scale;
272
scaledWinHeight = priv->window->height () * priv->scale;
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;
279
if (size != spinnerMaxSize)
281
size = spinnerMaxSize;
282
scale = MIN (scaledWinWidth, scaledWinHeight) / (float) spinnerMaxSize;
285
priv->cWindow->addDamageRect (CompRect (x, y, size / scale, size / scale));
287
mask |= PAINT_WINDOW_BLEND_MASK;
289
CompRegion iconReg (0, 0, size, size);
290
GLTexture::MatrixList ml (1);
292
ml[0] = spinner->matrix ();
293
priv->gWindow->vertexBuffer ()->begin ();
296
priv->gWindow->glAddGeometry (ml, iconReg, iconReg);
298
if (priv->gWindow->vertexBuffer ()->end ())
300
GLMatrix wTransform (transform);
301
GLWindowPaintAttrib sAttrib (attrib);
303
wTransform.scale (scale, scale, 1.0f);
304
wTransform.translate (x / scale, y / scale, 0.0f);
305
sAttrib.brightness *= 0.65f;
307
priv->gWindow->glDrawTexture (spinner, wTransform, sAttrib, mask);
924
988
activateEvent (false);
925
989
state = ScaleScreen::Idle;
991
screen->handleEventSetEnabled (this, false);
927
992
cScreen->preparePaintSetEnabled (this, false);
928
993
cScreen->donePaintSetEnabled (this, false);
929
994
gScreen->glPaintOutputSetEnabled (this, false);
994
1059
xev.xclient.window = source;
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;
1069
xev.xclient.data.l[1] = 1 << 0 | 1 << 1;
1070
xev.xclient.data.l[4] = xdndActionAsk;
1073
XSendEvent (screen->dpy (), source, false, 0, &xev);
1077
PrivateScaleScreen::sendDndFinishedMessage (Window source)
1081
xev.xclient.type = ClientMessage;
1082
xev.xclient.display = screen->dpy ();
1083
xev.xclient.format = 32;
1085
xev.xclient.message_type = xdndFinished;
1086
xev.xclient.window = source;
1088
xev.xclient.data.l[0] = dndTarget;
1089
xev.xclient.data.l[1] = 0; // Not accepted
1090
xev.xclient.data.l[2] = None;
1002
1092
XSendEvent (screen->dpy (), source, false, 0, &xev);
1103
1196
if (!dndTarget)
1105
1198
XSetWindowAttributes attr;
1106
long xdndVersion = 3;
1199
long xdndVersion = 5;
1108
attr.override_redirect = true;
1201
attr.override_redirect = True;
1110
1203
dndTarget = XCreateWindow (screen->dpy (), screen->root (),
1111
1204
0, 0, 1, 1, 0, CopyFromParent,
1118
1211
(unsigned char *) &xdndVersion, 1);
1214
if (screen->XShape ())
1216
CompRegion workAreaRegion;
1218
foreach (const CompOutput& output, screen->outputDevs ())
1219
workAreaRegion |= output.workArea ();
1221
XShapeCombineRegion (screen->dpy (), dndTarget, ShapeBounding, 0, 0, workAreaRegion.handle (), ShapeSet);
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);
1250
1354
cScreen->damageScreen ();
1356
screen->handleEventSetEnabled (this, true);
1252
1357
cScreen->preparePaintSetEnabled (this, true);
1253
1358
cScreen->donePaintSetEnabled (this, true);
1254
1359
gScreen->glPaintOutputSetEnabled (this, true);
1534
CompOption::Vector o (0);
1537
1639
/* terminate scale mode if the recently closed
1538
1640
* window was the last scaled window */
1540
o.push_back (CompOption ("root", CompOption::TypeInt));
1541
o[0].value ().set ((int) screen->root ());
1543
action = &optionGetInitiateEdge ();
1544
scaleTerminate (action, CompAction::StateCancel, o);
1546
action = &optionGetInitiateKey ();
1547
scaleTerminate (action, CompAction::StateCancel, o);
1641
terminateScale (false);
1648
void PrivateScaleScreen::terminateScale (bool accept)
1650
CompOption::Vector o (0);
1652
o.push_back (CompOption ("root", CompOption::TypeInt));
1653
o[0].value ().set ((int) screen->root ());
1655
scaleTerminate (&optionGetInitiateEdge (), accept ? 0 : CompAction::StateCancel, o);
1656
scaleTerminate (&optionGetInitiateKey (), accept ? 0 : CompAction::StateCancel, o);
1658
activateEvent (false);
1555
1662
PrivateScaleScreen::hoverTimeout ()
1557
1664
if (grab && state != ScaleScreen::In)
1560
CompOption::Vector o (0);
1562
w = screen->findWindow (selectedWindow);
1666
CompWindow *w = screen->findWindow (selectedWindow);
1565
1669
lastActiveNum = w->activeNum ();
1568
1672
w->moveInputFocusTo ();
1571
o.push_back (CompOption ("root", CompOption::TypeInt));
1572
o[0].value ().set ((int) screen->root ());
1574
scaleTerminate (&optionGetInitiateEdge (), 0, o);
1575
scaleTerminate (&optionGetInitiateKey (), 0, o);
1675
terminateScale (true);
1682
PrivateScaleScreen::dndCheckTimeout ()
1687
CompWindow *w = screen->findWindow (dndTarget);
1689
if (!w || !w->isMapped ())
1692
Window drag_owner = XGetSelectionOwner (screen->dpy (), xdndSelection);
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;
1700
XQueryPointer (screen->dpy (), screen->root (), &root_r, &child_r,
1701
&root_x_r, &root_y_r, &win_x_r, &win_y_r, &mask);
1703
if (mask & (Button1Mask | Button2Mask | Button3Mask))
1707
terminateScale (false);
1606
1736
state != ScaleScreen::In)
1608
1738
XButtonEvent *button = &event->xbutton;
1609
CompOption::Vector o (0);
1611
o.push_back (CompOption ("root", CompOption::TypeInt));
1612
o[0].value ().set ((int) screen->root ());
1614
1740
/* Button1 terminates scale mode, other buttons can select
1616
if (selectWindowAt (button->x_root, button->y_root, true) &&
1617
event->xbutton.button == Button1)
1619
scaleTerminate (&optionGetInitiateEdge (), 0, o);
1620
scaleTerminate (&optionGetInitiateKey (), 0, o);
1622
else if (optionGetClickOnDesktop () == 1 &&
1623
event->xbutton.button == Button1)
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 ());
1630
if (workArea.contains (pointer))
1632
scaleTerminate (&optionGetInitiateEdge (), 0, o);
1633
scaleTerminate (&optionGetInitiateKey (), 0, o);
1634
screen->enterShowDesktopMode ();
1637
else if (optionGetClickOnDesktop () == 2 &&
1638
event->xbutton.button == Button1)
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 ());
1645
if (workArea.contains (pointer))
1647
scaleTerminate (&optionGetInitiateEdge (), 0, o);
1648
scaleTerminate (&optionGetInitiateKey (), 0, o);
1742
if (event->xbutton.button != Button1)
1745
if (selectWindowAt (button->x_root, button->y_root, true))
1747
terminateScale (true);
1749
else if (optionGetClickOnDesktop () != ScaleOptions::ClickOnDesktopNone)
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 ());
1756
if (workArea.contains (pointer))
1758
terminateScale (false);
1760
if (optionGetClickOnDesktop () == ScaleOptions::ClickOnDesktopShowDesktop)
1761
screen->enterShowDesktopMode ();
1669
1782
w = screen->findWindow (event->xdestroywindow.window);
1671
1784
case UnmapNotify:
1673
1785
w = screen->findWindow (event->xunmap.window);
1675
1787
case ClientMessage:
1676
1788
if (event->xclient.message_type == Atoms::xdndPosition)
1678
w = screen->findWindow (event->xclient.window);
1790
if (event->xclient.window == dndTarget)
1681
if (w->id () == dndTarget)
1682
sendDndStatusMessage (event->xclient.data.l[0]);
1792
bool acceptsDnd = false;
1685
state != ScaleScreen::In &&
1686
w->id () == dndTarget)
1794
if (grab && state != ScaleScreen::In)
1688
1798
ScaleWindow *sw = checkForWindowAt (pointerX, pointerY);
1689
1799
if (sw && sw->priv->isScaleWin ())
1693
1803
time = optionGetHoverTime ();
1695
1806
if (hover.active ())
1697
1808
int lastMotion = sqrt (pow (pointerX - lastPointerX, 2) + pow (pointerY - lastPointerY, 2));
1699
1810
if (sw->window->id () != selectedWindow || lastMotion > optionGetDndDistance ())
1718
else if (event->xclient.message_type == Atoms::xdndDrop ||
1719
event->xclient.message_type == Atoms::xdndLeave)
1721
w = screen->findWindow (event->xclient.window);
1725
state != ScaleScreen::In &&
1726
w->id () == dndTarget)
1828
sendDndStatusMessage (event->xclient.data.l[0], acceptsDnd);
1831
else if (event->xclient.message_type == Atoms::xdndEnter)
1833
if (event->xclient.window == dndTarget &&
1834
grab && state != ScaleScreen::In)
1839
else if (event->xclient.message_type == Atoms::xdndLeave)
1841
if (event->xclient.window == dndTarget &&
1842
grab && state != ScaleScreen::In)
1847
else if (event->xclient.message_type == Atoms::xdndDrop)
1849
if (event->xclient.window == dndTarget)
1851
sendDndFinishedMessage (event->xclient.data.l[0]);
1853
if (grab && state != ScaleScreen::In)
1728
CompOption::Vector o (0);
1729
o.push_back (CompOption ("root", CompOption::TypeInt));
1730
o[0].value ().set ((int) screen->root ());
1732
scaleTerminate (&optionGetInitiateEdge (), 0, o);
1733
scaleTerminate (&optionGetInitiateKey (), 0, o);
1855
terminateScale (true);
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),
1840
1965
leftKeyCode = XKeysymToKeycode (screen->dpy (), XStringToKeysym ("Left"));
1842
1967
upKeyCode = XKeysymToKeycode (screen->dpy (), XStringToKeysym ("Up"));
1843
1968
downKeyCode = XKeysymToKeycode (screen->dpy (), XStringToKeysym ("Down"));
1845
cursor = XCreateFontCursor (screen->dpy (), XC_left_ptr);
1847
1970
opacity = (OPAQUE * optionGetOpacity ()) / 100;
1849
1972
hover.setCallback (boost::bind (&PrivateScaleScreen::hoverTimeout, this));
1973
dndCheck.setCallback (boost::bind (&PrivateScaleScreen::dndCheckTimeout, this));
1974
dndCheck.setTimes (200);
1851
1976
optionSetOpacityNotify (boost::bind (&PrivateScaleScreen::updateOpacity, this));
1884
2009
#undef SCALEBIND
2011
CompString pluginName("scale");
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));
1886
2032
ScreenInterface::setHandler (s);
1887
2033
CompositeScreenInterface::setHandler (cScreen, false);
1888
2034
GLScreenInterface::setHandler (gScreen, false);
1891
PrivateScaleScreen::~PrivateScaleScreen ()
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);