2
* Copyright (c) 2006 Darryll Truchan <moppsy@comcast.net>
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24
COMPIZ_PLUGIN_20090315 (put, PutPluginVTable);
26
#define PUT_ONLY_EMPTY(type) (type >= PutEmptyBottomLeft && \
27
type <= PutEmptyTopRight)
29
#define TOP_BORDER(w) ((w)->border ().top)
30
#define LEFT_BORDER(w) ((w)->border ().left)
31
#define RIGHT_BORDER(w) ((w)->border ().right + 2 * (w)->serverGeometry ().border ())
32
#define BOTTOM_BORDER(w) ((w)->border ().bottom + 2 * (w)->serverGeometry ().border ())
34
#define HALF_WIDTH(w) ((w)->serverWidth () / 2 + (w)->serverGeometry ().border ())
35
#define HALF_HEIGHT(w) ((w)->serverHeight () / 2 + (w)->serverGeometry ().border ())
38
* Maximumize functions
39
* Functions are from Maximumize plugin
40
* (Author:Kristian Lyngstøl <kristian@bohemians.org>)
43
/* Generates a region containing free space (here the
44
* active window counts as free space). The region argument
45
* is the start-region (ie: the output dev).
46
* Logic borrowed from opacify (courtesy of myself).
49
PutScreen::emptyRegion (CompWindow *window,
50
const CompRect& outputRect)
54
newRegion += outputRect;
56
foreach(CompWindow *w, screen->windows ())
58
if (w->id () == window->id ())
61
if (w->invisible () || /*w->hidden () ||*/ w->minimized ())
64
if (w->wmType () & CompWindowTypeDesktopMask)
67
if (w->wmType () & CompWindowTypeDockMask)
73
tmpRegion += w->struts ()->left;
74
tmpRegion += w->struts ()->right;
75
tmpRegion += w->struts ()->top;
76
tmpRegion += w->struts ()->bottom;
78
newRegion -= tmpRegion;
83
newRegion -= w->serverBorderRect ();
89
/* Returns true if box a has a larger area than box b.
92
PutScreen::boxCompare (const CompRect& a,
97
areaA = a.width () * a.height ();
98
areaB = b.width () * b.height ();
100
return (areaA > areaB);
103
/* Extends the given box for Window w to fit as much space in region r.
104
* If XFirst is true, it will first expand in the X direction,
105
* then Y. This is because it gives different results.
106
* PS: Decorations are icky.
115
addToCorner (CompRect& rect,
121
rect.setX (rect.x () + inc);
124
rect.setWidth (rect.width () + inc);
127
rect.setY (rect.y () + inc);
130
rect.setHeight (rect.height () + inc);
136
expandCorner (CompWindow *w,
145
r.contains (CompRect (tmp.x () - LEFT_BORDER (w), \
146
tmp.y () - TOP_BORDER (w), \
147
tmp.width () + LEFT_BORDER (w) + RIGHT_BORDER (w), \
148
tmp.height () + TOP_BORDER (w) + BOTTOM_BORDER (w)))
151
addToCorner (tmp, corner, direction);
156
addToCorner (tmp, corner, -direction);
162
PutScreen::extendBox (CompWindow *w,
171
short int counter = 0;
172
CompRect result = tmp;
176
if ((xFirst && counter == 0) || (!xFirst && counter == 1))
179
expandCorner (w, result, r, LEFT, -1);
182
expandCorner (w, result, r, RIGHT, 1);
187
if ((xFirst && counter == 1) || (!xFirst && counter == 0))
190
expandCorner (w, result, r, BOTTOM, 1);
193
expandCorner (w, result, r, TOP, -1);
202
/* Create a box for resizing in the given region
203
* Also shrinks the window box in case of minor overlaps.
204
* FIXME: should be somewhat cleaner.
207
PutScreen::findRect (CompWindow *w,
214
CompRect windowBox, ansA, ansB, orig;
216
windowBox.setGeometry (w->serverX (), w->serverY (),
217
w->serverWidth (), w->serverHeight ());
221
ansA = extendBox (w, windowBox, r, true, left, right, up, down);
222
ansB = extendBox (w, windowBox, r, false, left, right, up, down);
224
if (boxCompare (orig, ansA) && boxCompare (orig, ansB))
227
if (boxCompare (ansA, ansB))
234
/* Calls out to compute the resize */
236
PutScreen::computeResize (CompWindow *w,
243
unsigned int mask = 0;
246
int outputDevice = w->outputDevice ();
248
region = emptyRegion (w, screen->outputDevs ()[outputDevice]);
249
box = findRect (w, region, left, right, up, down);
251
if (box.x () != w->serverX ())
254
if (box.y () != w->serverY ())
257
if (box.width () != w->serverWidth ())
260
if (box.height () != w->height ())
265
xwc->width = box.width ();
266
xwc->height = box.height ();
272
* End of Maximumize functions
276
* calculate the velocity for the moving window
279
PutScreen::adjustVelocity (CompWindow *w)
281
float dx, dy, adjust, amount;
289
dx = x1 - (w->x () + pw->tx);
290
dy = y1 - (w->y () + pw->ty);
293
amount = fabs (dx) * 1.5;
296
else if (amount > 5.0f)
299
pw->xVelocity = (amount * pw->xVelocity + adjust) / (amount + 1.0f);
302
amount = fabs (dy) * 1.5f;
305
else if (amount > 5.0f)
308
pw->yVelocity = (amount * pw->yVelocity + adjust) / (amount + 1.0f);
310
if (fabs (dx) < 0.1f && fabs (pw->xVelocity) < 0.2f &&
311
fabs (dy) < 0.1f && fabs (pw->yVelocity) < 0.2f)
314
pw->xVelocity = pw->yVelocity = 0.0f;
316
pw->tx = x1 - w->x ();
317
pw->ty = y1 - w->y ();
324
PutScreen::finishWindowMovement (CompWindow *w)
328
w->move (pw->targetX - w->x (),
329
pw->targetY - w->y (),
333
if (w->state () & (MAXIMIZE_STATE | CompWindowStateFullscreenMask))
334
w->updateAttributes (CompStackingUpdateModeNone);
338
PutScreen::getOutputForWindow (CompWindow *w)
343
return w->outputDevice ();
345
/* outputDeviceForWindow uses the server geometry,
346
so specialcase a running animation, which didn't
347
apply the server geometry yet */
348
CompWindow::Geometry geom;
350
geom.set (w->x () + pw->tx, w->y () + pw->ty,
351
w->width (), w->height (), w->geometry ().border ());
353
return screen->outputDeviceForGeometry (geom);
357
PutScreen::getDistance (CompWindow *w,
359
CompOption::Vector &option)
361
CompScreen *s = screen;
362
int x, y, dx, dy, posX, posY;
363
int viewport, output;
370
posX = CompOption::getIntOptionNamed (option,"x", 0);
371
posY = CompOption::getIntOptionNamed (option,"y", 0);
373
/* get the output device number from the options list */
374
output = CompOption::getIntOptionNamed (option,"output", -1);
375
/* no output in options list -> use the current output */
378
/* no output given, so use the current output if
379
this wasn't a double tap */
381
if (ps->lastType != type || ps->lastWindow != w->id ())
382
output = getOutputForWindow (w);
386
/* make sure the output number is not out of bounds */
387
output = MIN (output, (int) s->outputDevs ().size () - 1);
392
/* user double-tapped the key, so use the screen work area */
393
workArea = s->workArea ();
394
/* set the type to unknown to have a toggle-type behaviour
395
between 'use output work area' and 'use screen work area' */
396
ps->lastType = PutUnknown;
400
/* single tap or output provided via options list,
401
use the output work area */
402
workArea = s->getWorkareaForOutput (output);
406
if (PUT_ONLY_EMPTY (type))
410
bool left, right, up, down;
412
left = right = up = down = false;
415
case PutEmptyBottomLeft:
421
case PutEmptyBottomRight:
428
left = right = up = down = true;
433
case PutEmptyTopLeft:
439
case PutEmptyTopRight:
446
mask = computeResize (w, &xwc, left,right,up,down);
449
if (w->constrainNewWindowSize (xwc.width, xwc.height,
450
&xwc.width, &xwc.height))
451
mask |= CWWidth | CWHeight;
454
workArea.setGeometry (xwc.x, xwc.y, xwc.width, xwc.height);
456
/* the windows location */
457
x = w->x () + pw->tx;
458
y = w->y () + pw->ty;
463
/* center of the screen */
464
dx = (workArea.width () / 2) - HALF_WIDTH (w) -
465
w->serverGeometry ().border () - (x - workArea.x ());
466
dy = (workArea.height () / 2) - HALF_HEIGHT (w) -
467
w->serverGeometry ().border () - (y - workArea.y ());
470
/* center of the left edge */
471
dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
472
dy = (workArea.height () / 2) - HALF_HEIGHT (w) -
476
/* center of the left edge */
477
workArea.setX (workArea.x () - LEFT_BORDER (w));
478
dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
479
dy = (workArea.height () / 2) - HALF_HEIGHT (w) -
483
/* top left corner */
484
dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
485
dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
487
case PutEmptyTopLeft:
488
/* top left corner */
489
workArea.setX (workArea.x () - LEFT_BORDER (w));
490
workArea.setY (workArea.y () - TOP_BORDER (w));
491
dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
492
dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
495
/* center of top edge */
496
dx = (workArea.width () / 2) - HALF_WIDTH (w) -
498
dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
501
/* center of top edge */
502
workArea.setY (workArea.x () - TOP_BORDER (w));
503
dx = (workArea.width () / 2) - HALF_WIDTH (w) -
505
dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
508
/* top right corner */
509
dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
510
RIGHT_BORDER (w) - ps->optionGetPadRight ();
511
dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
513
case PutEmptyTopRight:
514
/* top right corner */
515
workArea.setX (workArea.x () + RIGHT_BORDER (w));
516
workArea.setY (workArea.y () - TOP_BORDER (w));
517
dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
518
RIGHT_BORDER (w) - ps->optionGetPadRight ();
519
dy = -(y - workArea.y ()) + TOP_BORDER (w) + ps->optionGetPadTop ();
522
/* center of right edge */
523
dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
524
RIGHT_BORDER (w) - ps->optionGetPadRight ();
525
dy = (workArea.height () / 2) - HALF_HEIGHT (w) -
529
/* center of right edge */
530
workArea.setX (workArea.x () + RIGHT_BORDER (w));
531
dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
532
RIGHT_BORDER (w) - ps->optionGetPadRight ();
533
dy = (workArea.height () / 2) - HALF_HEIGHT (w) -
537
/* bottom right corner */
538
dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
539
RIGHT_BORDER (w) - ps->optionGetPadRight ();
540
dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
541
BOTTOM_BORDER (w) - ps->optionGetPadBottom ();
543
case PutEmptyBottomRight:
544
/* bottom right corner */
545
workArea.setX (workArea.x () + RIGHT_BORDER (w));
546
workArea.setY (workArea.y () + BOTTOM_BORDER (w));
547
dx = workArea.width () - w->serverWidth () - (x - workArea.x ()) -
548
RIGHT_BORDER (w) - ps->optionGetPadRight ();
549
dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
550
BOTTOM_BORDER (w)- ps->optionGetPadBottom ();
553
/* center of bottom edge */
554
dx = (workArea.width () / 2) - HALF_WIDTH (w) -
556
dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
557
BOTTOM_BORDER (w) - ps->optionGetPadBottom ();
560
/* center of bottom edge */
561
workArea.setY (workArea.y () + BOTTOM_BORDER (w));
562
dx = (workArea.width () / 2) - HALF_WIDTH (w) -
564
dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
565
BOTTOM_BORDER (w) - ps->optionGetPadBottom ();
568
/* bottom left corner */
569
dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
570
dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
571
BOTTOM_BORDER (w) - ps->optionGetPadBottom ();
573
case PutEmptyBottomLeft:
574
/* bottom left corner */
575
workArea.setX (workArea.x () - LEFT_BORDER (w));
576
workArea.setY (workArea.y () + BOTTOM_BORDER (w));
577
dx = -(x - workArea.x ()) + LEFT_BORDER (w) + ps->optionGetPadLeft ();
578
dy = workArea.height () - w->serverHeight () - (y - workArea.y ()) -
579
BOTTOM_BORDER (w) - ps->optionGetPadBottom ();
582
/* back to last position */
588
int vpX, vpY, hDirection, vDirection;
590
/* get the viewport to move to from the options list */
591
viewport = CompOption::getIntOptionNamed (option, "viewport", -1);
593
/* if viewport wasn't supplied, bail out */
597
/* split 1D viewport value into 2D x and y viewport */
598
vpX = viewport % s->vpSize ().width ();
599
vpY = viewport / s->vpSize ().width ();
600
if (vpY > (int) s->vpSize ().height ())
601
vpY = s->vpSize ().height () - 1;
603
/* take the shortest horizontal path to the destination viewport */
604
hDirection = (vpX - s->vp ().x ());
605
if (hDirection > (int) s->vpSize ().width () / 2)
606
hDirection = (hDirection - s->vpSize ().width ());
607
else if (hDirection < - ((int) s->vpSize ().width ()) / 2)
608
hDirection = (hDirection + s->vpSize ().width ());
610
/* we need to do this for the vertical destination viewport too */
611
vDirection = (vpY - s->vp ().y ());
612
if (vDirection > (int) s->vpSize ().height () / 2)
613
vDirection = (vDirection - s->vpSize ().height ());
614
else if (vDirection < -((int) s->vpSize ().height ()) / 2)
615
vDirection = (vDirection + s->vpSize ().height ());
617
dx = s->width () * hDirection;
618
dy = s->height () * vDirection;
621
case PutViewportLeft:
622
/* move to the viewport on the left */
623
dx = (s->vp ().x () >= 1) ? -s->width () : 0;
626
case PutViewportRight:
627
/* move to the viewport on the right */
628
dx = (s->vp ().x () < s->vpSize ().width ()-1) ? s->width () : 0;
632
/* move to the viewport above */
634
dy = (s->vp ().y () >= 1) ? -s->height () : 0;
636
case PutViewportDown:
637
/* move to the viewport below */
639
dy = (s->vp ().y () < s->vpSize ().height ()-1) ? s->height () : 0;
643
int outputNum, currentNum;
644
int nOutputDev = s->outputDevs ().size ();
645
CompOutput *currentOutput, *newOutput;
650
currentNum = getOutputForWindow (w);
651
outputNum = (currentNum + 1) % nOutputDev;
652
outputNum = CompOption::getIntOptionNamed (option,"output",
655
if (outputNum >= nOutputDev)
658
currentOutput = &s->outputDevs ().at(currentNum);
659
newOutput = &s->outputDevs ().at(outputNum);
661
/* move by the distance of the output center points */
662
dx = (newOutput->x1 () + newOutput->width () / 2) -
663
(currentOutput->x1 () + currentOutput->width () / 2);
664
dy = (newOutput->y1 () + newOutput->height () / 2) -
665
(currentOutput->y1 () + currentOutput->height () / 2);
667
/* update work area for new output */
668
workArea = newOutput->workArea ();
672
/* move the window to an exact position */
674
/* account for a specified negative position,
675
like geometry without (-0) */
676
dx = posX + s->width () - w->serverWidth () - x - RIGHT_BORDER (w);
678
dx = posX - x + LEFT_BORDER (w);
681
/* account for a specified negative position,
682
like geometry without (-0) */
683
dy = posY + s->height () - w->height () - y - BOTTOM_BORDER (w);
685
dy = posY - y + TOP_BORDER (w);
688
/* move window by offset */
694
/* move the window to the pointers position
695
* using the current quad of the screen to determine
696
* which corner to move to the pointer
703
/* get the pointers position from the X server */
704
if (XQueryPointer (s->dpy (), w->id (), &root, &child,
705
&rx, &ry, &winX, &winY, &pMask))
707
if (ps->optionGetWindowCenter ())
710
dx = rx - HALF_WIDTH (w) - x;
711
dy = ry - HALF_HEIGHT (w) - y;
713
else if (rx < (int) s->workArea ().width () / 2 &&
714
ry < (int) s->workArea ().height () / 2)
717
dx = rx - x + LEFT_BORDER (w);
718
dy = ry - y + TOP_BORDER (w);
720
else if (rx < (int) s->workArea ().width () / 2 &&
721
ry >= (int) s->workArea ().height () / 2)
723
/* bottom left quad */
724
dx = rx - x + LEFT_BORDER (w);
725
dy = ry - w->height () - y - BOTTOM_BORDER (w);
727
else if (rx >= (int) s->workArea ().width () / 2 &&
728
ry < (int) s->workArea ().height () / 2)
731
dx = rx - w->width () - x - RIGHT_BORDER (w);
732
dy = ry - y + TOP_BORDER (w);
736
/* bottom right quad */
737
dx = rx - w->width () - x - RIGHT_BORDER (w);
738
dy = ry - w->height () - y - BOTTOM_BORDER (w);
748
/* if an unknown type is specified, do nothing */
753
if ((dx || dy) && ps->optionGetAvoidOffscreen () &&
754
!(w->type () & CompWindowTypeFullscreenMask))
756
/* avoids window borders offscreen, but allow full
757
viewport movements */
760
CompWindowExtents extents, area;
762
inDx = dxBefore = dx % s->width ();
763
inDy = dyBefore = dy % s->height ();
765
extents.left = x + inDx - LEFT_BORDER (w);
766
extents.top = y + inDy - TOP_BORDER (w);
767
extents.right = x + inDx + w->serverWidth () + RIGHT_BORDER (w);
768
extents.bottom = y + inDy + w->serverHeight () + BOTTOM_BORDER (w);
770
area.left = workArea.left () + ps->optionGetPadLeft ();
771
area.top = workArea.top () + ps->optionGetPadTop ();
772
area.right = workArea.right () - ps->optionGetPadRight ();
773
area.bottom = workArea.bottom () - ps->optionGetPadBottom ();
775
if (extents.left < area.left)
777
inDx += area.left - extents.left;
779
else if (w->serverWidth () <= workArea.width () &&
780
extents.right > area.right)
782
inDx += area.right - extents.right;
785
if (extents.top < area.top)
787
inDy += area.top - extents.top;
789
else if (w->serverHeight () <= workArea.height () &&
790
extents.bottom > area.bottom)
792
inDy += area.bottom - extents.bottom;
795
/* apply the change */
796
dx += inDx - dxBefore;
797
dy += inDy - dyBefore;
806
PutScreen::preparePaint (int ms)
811
if (ps->moreAdjust && ps->grabIndex)
816
amount = ms * 0.025f * ps->optionGetSpeed ();
817
steps = amount / (0.5f * ps->optionGetTimestep ());
820
chunk = amount / (float)steps;
824
Window endAnimationWindow = None;
827
foreach(CompWindow *w, screen->windows ())
833
pw->adjust = adjustVelocity (w);
834
ps->moreAdjust |= pw->adjust;
836
pw->tx += pw->xVelocity * chunk;
837
pw->ty += pw->yVelocity * chunk;
842
finishWindowMovement (w);
844
if (w->id () == screen->activeWindow ())
845
endAnimationWindow = w->id ();
853
/* unfocus moved window if enabled */
854
if (ps->optionGetUnfocusWindow ())
855
screen->focusDefaultWindow ();
856
else if (endAnimationWindow)
857
screen->sendWindowActivationRequest (endAnimationWindow);
863
cScreen->preparePaint (ms);
866
/* This is the guts of the paint function. You can transform the way the
867
* entire output is painted or you can just draw things on screen with openGL.
868
* The unsigned int here is a mask for painting the screen, see opengl/opengl.h
869
* on how you can change it
873
PutScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
874
const GLMatrix &transform,
875
const CompRegion ®ion,
884
mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
886
status = gScreen->glPaintOutput (attrib, transform, region, output, mask);
892
PutScreen::donePaint ()
896
if (ps->moreAdjust && ps->grabIndex)
898
cScreen->damageScreen (); // FIXME
904
/* release the screen grab */
905
screen->removeGrab (ps->grabIndex, NULL);
910
cScreen->donePaint ();
913
/* This is our event handler. It directly hooks into the screen's X Event handler and allows us to handle
918
PutScreen::handleEvent (XEvent *event)
920
switch (event->type) {
921
/* handle client events */
923
/* accept the custom atom for putting windows */
924
if (event->xclient.message_type == compizPutWindowAtom)
928
w = screen->findWindow (event->xclient.window);
932
* get the values from the xclientmessage event and populate
933
* the options for put initiate
937
* l[0] = x position - unused (for future PutExact)
938
* l[1] = y position - unused (for future PutExact)
939
* l[2] = viewport number
940
* l[3] = put type, int value from enum
941
* l[4] = output number
943
CompOption::Vector opt (5);
945
CompOption::Value value0 = (int) event->xclient.window;
946
opt.push_back (CompOption ( "window",CompOption::TypeInt));
949
CompOption::Value value1 = (int) event->xclient.data.l[0];
950
opt.push_back (CompOption ( "x",CompOption::TypeInt));
953
CompOption::Value value2 = (int) event->xclient.data.l[1];
954
opt.push_back (CompOption ( "y",CompOption::TypeInt));
957
CompOption::Value value3 = (int) event->xclient.data.l[2];
958
opt.push_back (CompOption ( "viewport",CompOption::TypeInt));
961
CompOption::Value value4 = (int) event->xclient.data.l[4];
962
opt.push_back (CompOption ( "output",CompOption::TypeInt));
965
initiateCommon (NULL, 0, opt,
966
(PutType) event->xclient.data.l[3]);
973
screen->handleEvent (event);
976
/* This gets called whenever the window needs to be repainted.
977
* WindowPaintAttrib gives you some attributes like brightness/saturation etc
978
* to play around with. GLMatrix is the window's transformation matrix. The
979
* unsigned int is the mask, have a look at opengl.h on what you can do
982
PutWindow::glPaint (const GLWindowPaintAttrib &attrib,
983
const GLMatrix &transform,
984
const CompRegion ®ion,
987
GLMatrix wTransform (transform);
991
wTransform.translate (tx, ty, 0.0f);
992
mask |= PAINT_WINDOW_TRANSFORMED_MASK;
995
return gWindow->glPaint (attrib, wTransform, region, mask);
999
* initiate action callback
1002
PutScreen::initiateCommon (CompAction *action,
1003
CompAction::State state,
1004
CompOption::Vector &option,
1010
xid = CompOption::getIntOptionNamed (option, "window", 0);
1012
xid = screen->activeWindow ();
1014
w = screen->findWindow (xid);
1017
CompScreen *s = screen;
1020
/* we don't want to do anything with override redirect windows */
1021
if (w->overrideRedirect ())
1024
/* we don't want to be moving the desktop and docks */
1025
if (w->type () & (CompWindowTypeDesktopMask |
1026
CompWindowTypeDockMask))
1029
/* don't move windows without move action */
1030
if (!(w->actions () & CompWindowActionMoveMask))
1033
/* only allow movement of fullscreen windows to next output */
1034
if (type != PutNextOutput &&
1035
(w->type () & CompWindowTypeFullscreenMask))
1041
* handle the put types
1043
delta = getDistance (w, type, option);
1045
/* don't do anything if there is nothing to do */
1046
if (!delta.x () && !delta.y ())
1051
/* this will keep put from working while something
1052
else has a screen grab */
1053
if (s->otherGrabExist ("put", NULL))
1056
/* we are ok, so grab the screen */
1057
grabIndex = s->pushGrab (s->invisibleCursor (), "put");
1064
lastWindow = w->id ();
1066
/* save the windows position in the saveMask
1067
* this is used when unmaximizing the window
1069
if (w->saveMask () & CWX)
1070
w->saveWc ().x += delta.x ();
1072
if (w->saveMask () & CWY)
1073
w->saveWc ().y += delta.y ();
1075
/* Make sure everyting starts out at the windows
1077
pw->lastX = w->x () + pw->tx;
1078
pw->lastY = w->y () + pw->ty;
1080
pw->targetX = pw->lastX + delta.x ();
1081
pw->targetY = pw->lastY + delta.y ();
1083
/* mark for animation */
1087
/* cause repainting */
1088
pw->cWindow->addDamage ();
1092
/* tell event.c handleEvent to not call XAllowEvents */
1097
PutScreen::typeFromString (const CompString &type)
1099
if (type == "absolute")
1101
else if (type == "relative")
1103
else if (type == "pointer")
1105
else if (type == "viewport")
1106
return (PutType) PutViewport;
1107
else if (type == "viewportleft")
1108
return PutViewportLeft;
1109
else if (type == "viewportright")
1110
return PutViewportRight;
1111
else if (type == "viewportup")
1112
return PutViewportUp;
1113
else if (type == "viewportdown")
1114
return PutViewportDown;
1115
else if (type == "nextoutput")
1116
return PutNextOutput;
1117
else if (type == "restore")
1119
else if (type == "bottomleft")
1120
return PutBottomLeft;
1121
else if (type == "emptybottomleft")
1122
return PutEmptyBottomLeft;
1123
else if (type == "left")
1125
else if (type == "emptyleft")
1126
return PutEmptyLeft;
1127
else if (type == "topleft")
1129
else if (type == "emptytopleft")
1130
return PutEmptyTopLeft;
1131
else if (type == "top")
1133
else if (type == "emptytop")
1135
else if (type == "topright")
1137
else if (type == "emptytopright")
1138
return PutEmptyTopRight;
1139
else if (type == "right")
1141
else if (type == "emptyright")
1142
return PutEmptyRight;
1143
else if (type == "bottomright")
1144
return PutBottomRight;
1145
else if (type == "emptybottomright")
1146
return PutEmptyBottomRight;
1147
else if (type == "bottom")
1149
else if (type == "emptybottom")
1150
return PutEmptyBottom;
1151
else if (type == "center")
1153
else if (type == "emptycenter")
1154
return PutEmptyCenter;
1161
PutScreen::initiate (CompAction *action,
1162
CompAction::State state,
1163
CompOption::Vector &option)
1165
PutType type = PutUnknown;
1166
CompString typeString;
1168
typeString = CompOption::getStringOptionNamed (option, "type");
1169
if (!typeString.empty ())
1170
type = typeFromString (typeString);
1172
/* if (type == (PutType) PutViewport)
1173
return toViewport (action, state, option);
1175
return initiateCommon (action, state, option,type);
1179
PutScreen::toViewport (CompAction *action,
1180
CompAction::State state,
1181
CompOption::Vector &option,
1184
int last = option.size ();
1185
option.resize(last+1);
1186
option[last].setName ("viewport",CompOption::TypeInt);
1187
option[last].value ().set (vp-1);
1189
return initiateCommon (action, state, option, (PutType) PutViewport);
1193
PutScreen::PutScreen (CompScreen *screen) :
1194
PluginClassHandler <PutScreen, CompScreen> (screen),
1197
cScreen (CompositeScreen::get (screen)),
1198
gScreen (GLScreen::get (screen)),
1200
lastType (PutUnknown),
1204
ScreenInterface::setHandler (screen);
1205
CompositeScreenInterface::setHandler (cScreen);
1206
GLScreenInterface::setHandler (gScreen);
1208
compizPutWindowAtom = XInternAtom(screen->dpy (),
1209
"_COMPIZ_PUT_WINDOW", 0);
1211
optionSetPutPutInitiate (boost::bind (&PutScreen::initiate, this,
1214
#define setAction(action, type) \
1215
optionSet##action##KeyInitiate (boost::bind (&PutScreen::initiateCommon, \
1216
this, _1,_2,_3,type)); \
1217
optionSet##action##ButtonInitiate (boost::bind (&PutScreen::initiateCommon,\
1218
this, _1,_2,_3,type))
1220
setAction (PutRestore, PutRestore);
1221
setAction (PutPointer, PutPointer);
1222
setAction (PutNextOutput, PutNextOutput);
1223
setAction (PutCenter, PutCenter);
1224
setAction (PutEmptyCenter, PutEmptyCenter);
1225
setAction (PutLeft, PutLeft);
1226
setAction (PutEmptyLeft, PutEmptyLeft);
1227
setAction (PutRight, PutRight);
1228
setAction (PutEmptyRight, PutEmptyRight);
1229
setAction (PutTop, PutTop);
1230
setAction (PutEmptyTop, PutEmptyTop);
1231
setAction (PutBottom, PutBottom);
1232
setAction (PutEmptyBottom, PutEmptyBottom);
1233
setAction (PutTopleft, PutTopLeft);
1234
setAction (PutEmptyTopleft, PutEmptyTopLeft);
1235
setAction (PutTopright, PutTopRight);
1236
setAction (PutEmptyTopright, PutEmptyTopRight);
1237
setAction (PutBottomleft, PutBottomLeft);
1238
setAction (PutEmptyBottomleft, PutEmptyBottomLeft);
1239
setAction (PutBottomright, PutBottomRight);
1240
setAction (PutEmptyBottomright, PutEmptyBottomRight);
1242
#define setViewportAction(num) \
1243
optionSetPutViewport##num##KeyInitiate(boost::bind (&PutScreen::toViewport,\
1244
this, _1,_2,_3,num));
1246
setViewportAction(1);
1247
setViewportAction(2);
1248
setViewportAction(3);
1249
setViewportAction(4);
1250
setViewportAction(5);
1251
setViewportAction(6);
1252
setViewportAction(7);
1253
setViewportAction(8);
1254
setViewportAction(9);
1255
setViewportAction(10);
1256
setViewportAction(11);
1257
setViewportAction(12);
1259
#define setDirectionAction(action) \
1260
optionSet##action##KeyInitiate(boost::bind (&PutScreen::initiateCommon, \
1261
this, _1,_2,_3,action))
1263
setDirectionAction(PutViewportLeft);
1264
setDirectionAction(PutViewportRight);
1265
setDirectionAction(PutViewportUp);
1266
setDirectionAction(PutViewportDown);
1269
PutWindow::PutWindow (CompWindow *window) :
1270
PluginClassHandler <PutWindow, CompWindow> (window),
1272
cWindow (CompositeWindow::get (window)),
1273
gWindow (GLWindow::get (window)),
1278
lastX (window->serverX ()),
1279
lastY (window->serverY ()),
1282
WindowInterface::setHandler (window);
1283
CompositeWindowInterface::setHandler (cWindow);
1284
GLWindowInterface::setHandler (gWindow);
1288
PutPluginVTable::init ()
1290
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
1292
if (!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI))
1294
if (!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))