2
* Copyright © 2005 Novell, Inc.
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* Novell, Inc. not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* Novell, Inc. makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Author: David Reveman <davidr@novell.com>
31
#include <X11/Xatom.h>
32
#include <X11/cursorfont.h>
34
#include <core/core.h>
35
#include <core/atoms.h>
38
COMPIZ_PLUGIN_20081216 (resize, ResizePluginVTable)
41
ResizeScreen::getPaintRectangle (BoxPtr pBox)
43
pBox->x1 = geometry.x - w->input ().left;
44
pBox->y1 = geometry.y - w->input ().top;
45
pBox->x2 = geometry.x +
46
geometry.width + w->serverGeometry ().border () * 2 +
51
pBox->y2 = geometry.y + w->size ().height () + w->input ().bottom;
55
pBox->y2 = geometry.y +
56
geometry.height + w->serverGeometry ().border () * 2 +
62
ResizeWindow::getStretchScale (BoxPtr pBox, float *xScale, float *yScale)
66
width = window->size ().width () + window->input ().left +
67
window->input ().right;
68
height = window->size ().height () + window->input ().top +
69
window->input ().bottom;
71
*xScale = (width) ? (pBox->x2 - pBox->x1) / (float) width : 1.0f;
72
*yScale = (height) ? (pBox->y2 - pBox->y1) / (float) height : 1.0f;
76
ResizeScreen::getStretchRectangle (BoxPtr pBox)
81
getPaintRectangle (&box);
82
ResizeWindow::get (w)->getStretchScale (&box, &xScale, &yScale);
84
pBox->x1 = (int)(box.x1 - (w->output ().left - w->input ().left) * xScale);
85
pBox->y1 = (int)(box.y1 - (w->output ().top - w->input ().top) * yScale);
86
pBox->x2 = (int)(box.x2 + w->output ().right * xScale);
87
pBox->y2 = (int)(box.y2 + w->output ().bottom * yScale);
91
ResizeScreen::damageRectangle (BoxPtr pBox)
101
cScreen->damageRegion (CompRegion (CompRect (x1, y1, x2 - x1, y2 - y1)));
105
ResizeScreen::cursorFromResizeMask (unsigned int mask)
109
if (mask & ResizeLeftMask)
111
if (mask & ResizeDownMask)
112
cursor = downLeftCursor;
113
else if (mask & ResizeUpMask)
114
cursor = upLeftCursor;
118
else if (mask & ResizeRightMask)
120
if (mask & ResizeDownMask)
121
cursor = downRightCursor;
122
else if (mask & ResizeUpMask)
123
cursor = upRightCursor;
125
cursor = rightCursor;
127
else if (mask & ResizeUpMask)
140
ResizeScreen::sendResizeNotify ()
144
xev.xclient.type = ClientMessage;
145
xev.xclient.display = screen->dpy ();
146
xev.xclient.format = 32;
148
xev.xclient.message_type = resizeNotifyAtom;
149
xev.xclient.window = w->id ();
151
xev.xclient.data.l[0] = geometry.x;
152
xev.xclient.data.l[1] = geometry.y;
153
xev.xclient.data.l[2] = geometry.width;
154
xev.xclient.data.l[3] = geometry.height;
155
xev.xclient.data.l[4] = 0;
157
XSendEvent (screen->dpy (), screen->root (), FALSE,
158
SubstructureRedirectMask | SubstructureNotifyMask, &xev);
162
ResizeScreen::updateWindowProperty ()
164
unsigned long data[4];
166
data[0] = geometry.x;
167
data[1] = geometry.y;
168
data[2] = geometry.width;
169
data[3] = geometry.height;
171
XChangeProperty (screen->dpy (), w->id (), resizeInformationAtom,
172
XA_CARDINAL, 32, PropModeReplace,
173
(unsigned char*) data, 4);
177
ResizeScreen::finishResizing ()
181
XDeleteProperty (screen->dpy (), w->id (), resizeInformationAtom);
187
resizeInitiate (CompAction *action,
188
CompAction::State state,
189
CompOption::Vector &options)
194
xid = CompOption::getIntOptionNamed (options, "window");
196
w = screen->findWindow (xid);
197
if (w && (w->actions () & CompWindowActionResizeMask))
204
RESIZE_SCREEN (screen);
206
CompWindow::Geometry server = w->serverGeometry ();
208
x = CompOption::getIntOptionNamed (options, "x", pointerX);
209
y = CompOption::getIntOptionNamed (options, "y", pointerY);
211
button = CompOption::getIntOptionNamed (options, "button", -1);
213
mask = CompOption::getIntOptionNamed (options, "direction");
215
/* Initiate the resize in the direction suggested by the
216
* sector of the window the mouse is in, eg drag in top left
217
* will resize up and to the left. Keyboard resize starts out
218
* with the cursor in the middle of the window and then starts
219
* resizing the edge corresponding to the next key press. */
220
if (state & CompAction::StateInitKey)
226
unsigned int sectorSizeX = server.width () / 3;
227
unsigned int sectorSizeY = server.height () / 3;
228
unsigned int posX = x - server.x ();
229
unsigned int posY = y - server.y ();
231
if (posX < sectorSizeX)
232
mask |= ResizeLeftMask;
233
else if (posX > (2 * sectorSizeX))
234
mask |= ResizeRightMask;
236
if (posY < sectorSizeY)
237
mask |= ResizeUpMask;
238
else if (posY > (2 * sectorSizeY))
239
mask |= ResizeDownMask;
241
/* if the pointer was in the middle of the window,
242
just prevent input to the window */
248
if (screen->otherGrabExist ("resize", 0))
254
if (w->type () & (CompWindowTypeDesktopMask |
255
CompWindowTypeDockMask |
256
CompWindowTypeFullscreenMask))
259
if (w->overrideRedirect ())
262
if (state & CompAction::StateInitButton)
263
action->setState (action->state () | CompAction::StateTermButton);
266
mask &= ~(ResizeUpMask | ResizeDownMask);
271
rs->savedGeometry.x = server.x ();
272
rs->savedGeometry.y = server.y ();
273
rs->savedGeometry.width = server.width ();
274
rs->savedGeometry.height = server.height ();
276
rs->geometry = rs->savedGeometry;
278
rs->pointerDx = x - pointerX;
279
rs->pointerDy = y - pointerY;
281
if ((w->state () & MAXIMIZE_STATE) == MAXIMIZE_STATE)
283
/* if the window is fully maximized, showing the outline or
284
rectangle would be visually distracting as the window can't
285
be resized anyway; so we better don't use them in this case */
286
rs->mode = RESIZE_MODE_NORMAL;
290
rs->mode = rs->opt[RESIZE_OPTION_MODE].value ().i ();
291
for (i = 0; i <= RESIZE_MODE_LAST; i++)
293
if (action == &rs->opt[i].value ().action ())
300
if (i > RESIZE_MODE_LAST)
304
for (i = 0; i <= RESIZE_MODE_LAST; i++)
306
index = RESIZE_OPTION_NORMAL_MATCH + i;
307
if (rs->opt[index].value ().match ().evaluate (w))
315
if (!rs->gScreen || !rs->cScreen ||
316
rs->cScreen->compositingActive ())
317
rs->mode = RESIZE_MODE_NORMAL;
320
if (rs->mode != RESIZE_MODE_NORMAL)
323
if (rw->gWindow && rs->mode == RESIZE_MODE_STRETCH)
324
rw->gWindow->glPaintSetEnabled (rw, true);
325
if (rw->cWindow && rs->mode == RESIZE_MODE_STRETCH)
326
rw->cWindow->damageRectSetEnabled (rw, true);
327
rs->gScreen->glPaintOutputSetEnabled (rs, true);
334
if (state & CompAction::StateInitKey)
336
cursor = rs->middleCursor;
340
cursor = rs->cursorFromResizeMask (mask);
343
rs->grabIndex = screen->pushGrab (cursor, "resize");
350
rs->releaseButton = button;
352
w->grabNotify (x, y, state, CompWindowGrabResizeMask |
353
CompWindowGrabButtonMask);
355
/* using the paint rectangle is enough here
356
as we don't have any stretch yet */
357
rs->getPaintRectangle (&box);
358
rs->damageRectangle (&box);
360
if (state & CompAction::StateInitKey)
364
xRoot = server.x () + (server.width () / 2);
365
yRoot = server.y () + (server.height () / 2);
367
screen->warpPointer (xRoot - pointerX, yRoot - pointerY);
376
resizeTerminate (CompAction *action,
377
CompAction::State state,
378
CompOption::Vector &options)
380
RESIZE_SCREEN (screen);
384
CompWindow *w = rs->w;
386
unsigned int mask = 0;
388
if (rs->mode == RESIZE_MODE_NORMAL)
390
if (state & CompAction::StateCancel)
392
xwc.x = rs->savedGeometry.x;
393
xwc.y = rs->savedGeometry.y;
394
xwc.width = rs->savedGeometry.width;
395
xwc.height = rs->savedGeometry.height;
397
mask = CWX | CWY | CWWidth | CWHeight;
404
if (state & CompAction::StateCancel)
405
geometry = rs->savedGeometry;
407
geometry = rs->geometry;
409
if (memcmp (&geometry, &rs->savedGeometry, sizeof (geometry)) == 0)
413
if (rs->mode == RESIZE_MODE_STRETCH)
414
rs->getStretchRectangle (&box);
416
rs->getPaintRectangle (&box);
418
rs->damageRectangle (&box);
424
xwc.width = geometry.width;
425
xwc.height = geometry.height;
427
mask = CWX | CWY | CWWidth | CWHeight;
430
if (rs->mode != RESIZE_MODE_NORMAL)
432
RESIZE_WINDOW (rs->w);
433
if (rw->gWindow && rs->mode == RESIZE_MODE_STRETCH)
434
rw->gWindow->glPaintSetEnabled (rw, false);
435
if (rw->cWindow && rs->mode == RESIZE_MODE_STRETCH)
436
rw->cWindow->damageRectSetEnabled (rw, false);
437
rs->gScreen->glPaintOutputSetEnabled (rs, false);
441
if ((mask & CWWidth) &&
442
xwc.width == (int) w->serverGeometry ().width ())
445
if ((mask & CWHeight) &&
446
xwc.height == (int) w->serverGeometry ().height ())
451
if (mask & (CWWidth | CWHeight))
452
w->sendSyncRequest ();
454
w->configureXWindow (mask, &xwc);
457
if (!(mask & (CWWidth | CWHeight)))
458
rs->finishResizing ();
462
screen->removeGrab (rs->grabIndex, NULL);
466
rs->releaseButton = 0;
469
action->setState (action->state () & ~(CompAction::StateTermKey |
470
CompAction::StateTermButton));
477
ResizeScreen::updateWindowSize ()
482
if (w->serverGeometry ().width () != geometry.width ||
483
w->serverGeometry ().height () != geometry.height)
489
xwc.width = geometry.width;
490
xwc.height = geometry.height;
492
w->sendSyncRequest ();
494
w->configureXWindow (CWX | CWY | CWWidth | CWHeight, &xwc);
499
ResizeScreen::handleKeyEvent (KeyCode keycode)
503
int widthInc, heightInc;
505
widthInc = w->sizeHints ().width_inc;
506
heightInc = w->sizeHints ().height_inc;
508
if (widthInc < MIN_KEY_WIDTH_INC)
509
widthInc = MIN_KEY_WIDTH_INC;
511
if (heightInc < MIN_KEY_HEIGHT_INC)
512
heightInc = MIN_KEY_HEIGHT_INC;
514
for (unsigned int i = 0; i < NUM_KEYS; i++)
516
if (keycode != key[i])
519
if (mask & rKeys[i].warpMask)
521
XWarpPointer (screen->dpy (), None, None, 0, 0, 0, 0,
522
rKeys[i].dx * widthInc, rKeys[i].dy * heightInc);
526
int x, y, left, top, width, height;
528
CompWindow::Geometry server = w->serverGeometry ();
529
CompWindowExtents input = w->input ();
531
left = server.x () - input.left;
532
top = server.y () - input.top;
533
width = input.left + server.width () + input.right;
534
height = input.top + server.height () + input.bottom;
536
x = left + width * (rKeys[i].dx + 1) / 2;
537
y = top + height * (rKeys[i].dy + 1) / 2;
539
screen->warpPointer (x - pointerX, y - pointerY);
541
mask = rKeys[i].resizeMask;
543
screen->updateGrab (grabIndex, cursor[i]);
551
ResizeScreen::handleMotionEvent (int xRoot, int yRoot)
558
wi = savedGeometry.width;
559
he = savedGeometry.height;
564
int minPointerOffsetX, minPointerOffsetY;
566
CompWindow::Geometry server = w->serverGeometry ();
568
xDist = xRoot - (server.x () + (server.width () / 2));
569
yDist = yRoot - (server.y () + (server.height () / 2));
571
/* decision threshold is 10% of window size */
572
minPointerOffsetX = MIN (20, server.width () / 10);
573
minPointerOffsetY = MIN (20, server.height () / 10);
575
/* if we reached the threshold in one direction,
576
make the threshold in the other direction smaller
577
so there is a chance that this threshold also can
578
be reached (by diagonal movement) */
579
if (abs (xDist) > minPointerOffsetX)
580
minPointerOffsetY /= 2;
581
else if (abs (yDist) > minPointerOffsetY)
582
minPointerOffsetX /= 2;
584
if (abs (xDist) > minPointerOffsetX)
587
mask |= ResizeRightMask;
589
mask |= ResizeLeftMask;
592
if (abs (yDist) > minPointerOffsetY)
595
mask |= ResizeDownMask;
597
mask |= ResizeUpMask;
600
/* if the pointer movement was enough to determine a
601
direction, warp the pointer to the appropriate edge
602
and set the right cursor */
607
int pointerAdjustX = 0;
608
int pointerAdjustY = 0;
609
int option = RESIZE_OPTION_INITIATE_KEY;
611
action = &opt[option].value ().action ();
612
action->setState (action->state () |
613
CompAction::StateTermButton);
615
if (mask & ResizeRightMask)
616
pointerAdjustX = server.x () + server.width () +
617
w->input ().right - xRoot;
618
else if (mask & ResizeLeftMask)
619
pointerAdjustX = server.x () - w->input ().left -
622
if (mask & ResizeDownMask)
623
pointerAdjustY = server.x () + server.height () +
624
w->input ().bottom - yRoot;
625
else if (mask & ResizeUpMask)
626
pointerAdjustY = server.y () - w->input ().top - yRoot;
628
screen->warpPointer (pointerAdjustX, pointerAdjustY);
630
cursor = cursorFromResizeMask (mask);
631
screen->updateGrab (grabIndex, cursor);
636
/* only accumulate pointer movement if a mask is
637
already set as we don't have a use for the
638
difference information otherwise */
639
pointerDx += xRoot - lastPointerX;
640
pointerDy += yRoot - lastPointerY;
643
if (mask & ResizeLeftMask)
645
else if (mask & ResizeRightMask)
648
if (mask & ResizeUpMask)
650
else if (mask & ResizeDownMask)
653
if (w->state () & CompWindowStateMaximizedVertMask)
654
he = w->serverGeometry ().height ();
656
if (w->state () & CompWindowStateMaximizedHorzMask)
657
wi = w->serverGeometry ().width ();
659
w->constrainNewWindowSize (wi, he, &wi, &he);
661
if (mode != RESIZE_MODE_NORMAL)
663
if (mode == RESIZE_MODE_STRETCH)
664
getStretchRectangle (&box);
666
getPaintRectangle (&box);
668
damageRectangle (&box);
671
if (mask & ResizeLeftMask)
672
geometry.x -= wi - geometry.width;
674
if (mask & ResizeUpMask)
675
geometry.y -= he - geometry.height;
678
geometry.height = he;
680
if (mode != RESIZE_MODE_NORMAL)
682
if (mode == RESIZE_MODE_STRETCH)
683
getStretchRectangle (&box);
685
getPaintRectangle (&box);
687
damageRectangle (&box);
694
updateWindowProperty ();
700
ResizeScreen::handleEvent (XEvent *event)
702
switch (event->type) {
704
if (event->xkey.root == screen->root ())
705
handleKeyEvent (event->xkey.keycode);
708
if (event->xbutton.root == screen->root ())
712
if (releaseButton == -1 ||
713
(int) event->xbutton.button == releaseButton)
715
int opt = RESIZE_OPTION_INITIATE_BUTTON;
716
CompAction *action = &this->opt[opt].value ().action ();
718
resizeTerminate (action, CompAction::StateTermButton,
725
if (event->xmotion.root == screen->root ())
726
handleMotionEvent (pointerX, pointerY);
730
if (event->xcrossing.root == screen->root ())
731
handleMotionEvent (pointerX, pointerY);
734
if (event->xclient.message_type == Atoms::wmMoveResize)
737
unsigned long type = event->xclient.data.l[2];
739
RESIZE_SCREEN (screen);
741
if (type <= WmMoveResizeSizeLeft ||
742
type == WmMoveResizeSizeKeyboard)
744
w = screen->findWindow (event->xclient.window);
747
CompOption::Vector o (0);
750
o.push_back (CompOption ("window",
751
CompOption::TypeInt));
752
o[0].value ().set ((int) event->xclient.window);
754
if (event->xclient.data.l[2] == WmMoveResizeSizeKeyboard)
756
option = RESIZE_OPTION_INITIATE_KEY;
758
resizeInitiate (&opt[option].value ().action (),
759
CompAction::StateInitKey, o);
763
static unsigned int mask[] = {
764
ResizeUpMask | ResizeLeftMask,
766
ResizeUpMask | ResizeRightMask,
768
ResizeDownMask | ResizeRightMask,
770
ResizeDownMask | ResizeLeftMask,
777
option = RESIZE_OPTION_INITIATE_BUTTON;
779
XQueryPointer (screen->dpy (),
781
&root, &child, &xRoot, &yRoot,
784
/* TODO: not only button 1 */
785
if (mods & Button1Mask)
787
o.push_back (CompOption ("modifiers",
788
CompOption::TypeInt));
789
o.push_back (CompOption ("x",
790
CompOption::TypeInt));
791
o.push_back (CompOption ("y",
792
CompOption::TypeInt));
793
o.push_back (CompOption ("direction",
794
CompOption::TypeInt));
795
o.push_back (CompOption ("button",
796
CompOption::TypeInt));
798
o[1].value ().set ((int) mods);
800
((int) event->xclient.data.l[0]);
802
((int) event->xclient.data.l[1]);
804
((int) mask[event->xclient.data.l[2]]);
806
((int) (event->xclient.data.l[3] ?
807
event->xclient.data.l[3] : -1));
809
resizeInitiate (&opt[option].value ().action (),
810
CompAction::StateInitButton, o);
812
ResizeScreen::get (screen)->
813
handleMotionEvent (xRoot, yRoot);
818
else if (rs->w && type == WmMoveResizeCancel)
820
if (rs->w->id () == event->xclient.window)
824
option = RESIZE_OPTION_INITIATE_BUTTON;
825
resizeTerminate (&opt[option].value ().action (),
826
CompAction::StateCancel, noOptions);
827
option = RESIZE_OPTION_INITIATE_KEY;
828
resizeTerminate (&opt[option].value ().action (),
829
CompAction::StateCancel, noOptions);
835
if (w && w->id () == event->xdestroywindow.window)
839
option = RESIZE_OPTION_INITIATE_BUTTON;
840
resizeTerminate (&opt[option].value ().action (), 0, noOptions);
841
option = RESIZE_OPTION_INITIATE_KEY;
842
resizeTerminate (&opt[option].value ().action (), 0, noOptions);
846
if (w && w->id () == event->xunmap.window)
850
option = RESIZE_OPTION_INITIATE_BUTTON;
851
resizeTerminate (&opt[option].value ().action (), 0, noOptions);
852
option = RESIZE_OPTION_INITIATE_KEY;
853
resizeTerminate (&opt[option].value ().action (), 0, noOptions);
859
screen->handleEvent (event);
861
if (event->type == screen->syncEvent () + XSyncAlarmNotify)
865
XSyncAlarmNotifyEvent *sa;
867
sa = (XSyncAlarmNotifyEvent *) event;
869
if (w->syncAlarm () == sa->alarm)
876
ResizeWindow::resizeNotify (int dx, int dy, int dwidth, int dheight)
878
window->resizeNotify (dx, dy, dwidth, dheight);
880
if (rScreen->w == window && !rScreen->grabIndex)
881
rScreen->finishResizing ();
885
ResizeScreen::glPaintRectangle (const GLScreenPaintAttrib &sAttrib,
886
const GLMatrix &transform,
888
unsigned short *borderColor,
889
unsigned short *fillColor)
892
GLMatrix sTransform (transform);
894
getPaintRectangle (&box);
898
sTransform.toScreenSpace (output, -DEFAULT_Z_CAMERA);
900
glLoadMatrixf (sTransform.getMatrix ());
902
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
908
glColor4usv (fillColor);
909
glRecti (box.x1, box.y2, box.x2, box.y1);
913
glColor4usv (borderColor);
915
glBegin (GL_LINE_LOOP);
916
glVertex2i (box.x1, box.y1);
917
glVertex2i (box.x2, box.y1);
918
glVertex2i (box.x2, box.y2);
919
glVertex2i (box.x1, box.y2);
923
glColor4usv (defaultColor);
924
glDisable (GL_BLEND);
925
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
930
ResizeScreen::glPaintOutput (const GLScreenPaintAttrib &sAttrib,
931
const GLMatrix &transform,
932
const CompRegion ®ion,
940
if (mode == RESIZE_MODE_STRETCH)
941
mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
944
status = gScreen->glPaintOutput (sAttrib, transform, region, output, mask);
948
unsigned short *border, *fill;
950
border = opt[RESIZE_OPTION_BORDER_COLOR].value ().c ();
951
fill = opt[RESIZE_OPTION_FILL_COLOR].value ().c ();
954
case RESIZE_MODE_OUTLINE:
955
glPaintRectangle (sAttrib, transform, output, border, NULL);
957
case RESIZE_MODE_RECTANGLE:
958
glPaintRectangle (sAttrib, transform, output, border, fill);
968
ResizeWindow::glPaint (const GLWindowPaintAttrib &attrib,
969
const GLMatrix &transform,
970
const CompRegion ®ion,
975
if (window == rScreen->w && rScreen->mode == RESIZE_MODE_STRETCH)
977
GLMatrix wTransform (transform);
979
float xOrigin, yOrigin;
980
float xScale, yScale;
983
if (mask & PAINT_WINDOW_OCCLUSION_DETECTION_MASK)
986
status = gWindow->glPaint (attrib, transform, region,
987
mask | PAINT_WINDOW_NO_CORE_INSTANCE_MASK);
989
GLFragment::Attrib fragment (gWindow->lastPaintAttrib ());
991
if (window->alpha () || fragment.getOpacity () != OPAQUE)
992
mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
994
rScreen->getPaintRectangle (&box);
995
getStretchScale (&box, &xScale, &yScale);
997
x = window->geometry (). x ();
998
y = window->geometry (). y ();
1000
xOrigin = x - window->input ().left;
1001
yOrigin = y - window->input ().top;
1003
wTransform.translate (xOrigin, yOrigin, 0.0f);
1004
wTransform.scale (xScale, yScale, 1.0f);
1005
wTransform.translate ((rScreen->geometry.x - x) / xScale - xOrigin,
1006
(rScreen->geometry.y - y) / yScale - yOrigin,
1010
glLoadMatrixf (wTransform.getMatrix ());
1012
gWindow->glDraw (wTransform, fragment, region,
1013
mask | PAINT_WINDOW_TRANSFORMED_MASK);
1019
status = gWindow->glPaint (attrib, transform, region, mask);
1026
ResizeWindow::damageRect (bool initial, const CompRect &rect)
1028
bool status = false;
1030
if (window == rScreen->w && rScreen->mode == RESIZE_MODE_STRETCH)
1034
rScreen->getStretchRectangle (&box);
1035
rScreen->damageRectangle (&box);
1040
status |= cWindow->damageRect (initial, rect);
1045
CompOption::Vector &
1046
ResizeScreen::getOptions ()
1052
ResizeScreen::setOption (const char *name,
1053
CompOption::Value &value)
1058
o = CompOption::findOption (opt, name, &index);
1062
return CompOption::setOption (*o, value);
1066
static const CompMetadata::OptionInfo resizeOptionInfo[] = {
1067
{ "initiate_normal_key", "key", 0, resizeInitiate, resizeTerminate },
1068
{ "initiate_outline_key", "key", 0, resizeInitiate, resizeTerminate },
1069
{ "initiate_rectangle_key", "key", 0, resizeInitiate, resizeTerminate },
1070
{ "initiate_stretch_key", "key", 0, resizeInitiate, resizeTerminate },
1071
{ "initiate_button", "button", 0, resizeInitiate, resizeTerminate },
1072
{ "initiate_key", "key", 0, resizeInitiate, resizeTerminate },
1073
{ "mode", "int", RESTOSTRING (0, RESIZE_MODE_LAST), 0, 0 },
1074
{ "border_color", "color", 0, 0, 0 },
1075
{ "fill_color", "color", 0, 0, 0 },
1076
{ "normal_match", "match", 0, 0, 0 },
1077
{ "outline_match", "match", 0, 0, 0 },
1078
{ "rectangle_match", "match", 0, 0, 0 },
1079
{ "stretch_match", "match", 0, 0, 0 }
1082
ResizeScreen::ResizeScreen (CompScreen *s) :
1083
PrivateHandler<ResizeScreen,CompScreen> (s),
1084
gScreen (GLScreen::get (s)),
1085
cScreen (CompositeScreen::get (s)),
1088
opt (RESIZE_OPTION_NUM)
1091
Display *dpy = s->dpy ();
1093
if (!resizeVTable->getMetadata ()->initOptions (resizeOptionInfo,
1094
RESIZE_OPTION_NUM, opt))
1100
resizeNotifyAtom = XInternAtom (s->dpy (),
1101
"_COMPIZ_RESIZE_NOTIFY", 0);
1102
resizeInformationAtom = XInternAtom (s->dpy (),
1103
"_COMPIZ_RESIZE_INFORMATION", 0);
1105
for (unsigned int i = 0; i < NUM_KEYS; i++)
1106
key[i] = XKeysymToKeycode (s->dpy (), XStringToKeysym (rKeys[i].name));
1110
leftCursor = XCreateFontCursor (dpy, XC_left_side);
1111
rightCursor = XCreateFontCursor (dpy, XC_right_side);
1112
upCursor = XCreateFontCursor (dpy, XC_top_side);
1113
upLeftCursor = XCreateFontCursor (dpy, XC_top_left_corner);
1114
upRightCursor = XCreateFontCursor (dpy, XC_top_right_corner);
1115
downCursor = XCreateFontCursor (dpy, XC_bottom_side);
1116
downLeftCursor = XCreateFontCursor (dpy, XC_bottom_left_corner);
1117
downRightCursor = XCreateFontCursor (dpy, XC_bottom_right_corner);
1118
middleCursor = XCreateFontCursor (dpy, XC_fleur);
1120
cursor[0] = leftCursor;
1121
cursor[1] = rightCursor;
1122
cursor[2] = upCursor;
1123
cursor[3] = downCursor;
1125
ScreenInterface::setHandler (s);
1128
GLScreenInterface::setHandler (gScreen, false);
1131
ResizeScreen::~ResizeScreen ()
1133
Display *dpy = screen->dpy ();
1136
XFreeCursor (dpy, leftCursor);
1138
XFreeCursor (dpy, rightCursor);
1140
XFreeCursor (dpy, upCursor);
1142
XFreeCursor (dpy, downCursor);
1144
XFreeCursor (dpy, middleCursor);
1146
XFreeCursor (dpy, upLeftCursor);
1148
XFreeCursor (dpy, upRightCursor);
1150
XFreeCursor (dpy, downLeftCursor);
1151
if (downRightCursor)
1152
XFreeCursor (dpy, downRightCursor);
1155
ResizeWindow::ResizeWindow (CompWindow *w) :
1156
PrivateHandler<ResizeWindow,CompWindow> (w),
1158
gWindow (GLWindow::get (w)),
1159
cWindow (CompositeWindow::get (w)),
1160
rScreen (ResizeScreen::get (screen))
1162
WindowInterface::setHandler (window);
1165
CompositeWindowInterface::setHandler (cWindow, false);
1168
GLWindowInterface::setHandler (gWindow, false);
1172
ResizeWindow::~ResizeWindow ()
1178
ResizePluginVTable::init ()
1180
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
1183
getMetadata ()->addFromOptionInfo (resizeOptionInfo, RESIZE_OPTION_NUM);
1184
getMetadata ()->addFromFile (name ());