7
* Copyright (c) 2006 Robert Carr <racarr@beryl-project.org>
10
* Robert Carr <racarr@beryl-project.org>
11
* Dennis Kasprzyk <onestone@opencompositing.org>
13
* This program is free software; you can redistribute it and/or
14
* modify it under the terms of the GNU General Public License
15
* as published by the Free Software Foundation; either version 2
16
* of the License, or (at your option) any later version.
18
* This program is distributed in the hope that it will be useful,
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
* GNU General Public License for more details.
33
#include <core/atoms.h>
37
#define PI 3.14159265359f
38
#define VIEWPORT_SWITCHER_SIZE 100
41
#define getColorRGBA(name) \
42
r = optionGet##name##Red() / 65535.0f;\
43
g = optionGet##name##Green() / 65535.0f; \
44
b = optionGet##name##Blue() / 65535.0f; \
45
a = optionGet##name##Alpha() / 65535.0f
47
#define sigmoid(x) (1.0f / (1.0f + exp (-5.5f * 2 * ((x) - 0.5))))
48
#define sigmoidProgress(x) ((sigmoid (x) - sigmoid (0)) / \
49
(sigmoid (1) - sigmoid (0)))
51
COMPIZ_PLUGIN_20090315 (wall, WallPluginVTable);
54
WallScreen::clearCairoLayer (cairo_t *cr)
57
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
63
WallScreen::drawSwitcherBackground ()
66
cairo_pattern_t *pattern;
68
int width, height, radius;
72
destroyCairoContext (switcherContext);
73
setupCairoContext (switcherContext);
75
cr = switcherContext.cr;
78
width = switcherContext.width - outline;
79
height = switcherContext.height - outline;
82
cairo_translate (cr, outline / 2.0f, outline / 2.0f);
84
/* set the pattern for the switcher's background */
85
pattern = cairo_pattern_create_linear (0, 0, width, height);
86
getColorRGBA (BackgroundGradientBaseColor);
87
cairo_pattern_add_color_stop_rgba (pattern, 0.00f, r, g, b, a);
88
getColorRGBA (BackgroundGradientHighlightColor);
89
cairo_pattern_add_color_stop_rgba (pattern, 0.65f, r, g, b, a);
90
getColorRGBA (BackgroundGradientShadowColor);
91
cairo_pattern_add_color_stop_rgba (pattern, 0.85f, r, g, b, a);
92
cairo_set_source (cr, pattern);
94
/* draw the border's shape */
95
radius = optionGetEdgeRadius ();
98
cairo_arc (cr, radius, radius, radius, PI, 1.5f * PI);
99
cairo_arc (cr, radius + width - 2 * radius,
100
radius, radius, 1.5f * PI, 2.0 * PI);
101
cairo_arc (cr, width - radius, height - radius, radius, 0, PI / 2.0f);
102
cairo_arc (cr, radius, height - radius, radius, PI / 2.0f, PI);
106
cairo_rectangle (cr, 0, 0, width, height);
109
cairo_close_path (cr);
111
/* apply pattern to background... */
112
cairo_fill_preserve (cr);
114
/* ... and draw an outline */
115
cairo_set_line_width (cr, outline);
116
getColorRGBA (OutlineColor);
117
cairo_set_source_rgba (cr, r, g, b, a);
120
cairo_pattern_destroy (pattern);
124
for (i = 0; i < (unsigned int) screen->vpSize ().height (); i++)
126
cairo_translate (cr, 0.0, viewportBorder);
128
for (j = 0; j < (unsigned int) screen->vpSize ().width (); j++)
130
cairo_translate (cr, viewportBorder, 0.0);
132
/* this cuts a hole into our background */
133
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
134
cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
135
cairo_rectangle (cr, 0, 0, viewportWidth, viewportHeight);
137
cairo_fill_preserve (cr);
138
cairo_set_operator (cr, CAIRO_OPERATOR_XOR);
141
cairo_translate (cr, viewportWidth, 0.0);
145
cairo_translate (cr, 0.0, viewportHeight);
151
WallScreen::drawThumb ()
154
cairo_pattern_t *pattern;
156
float outline = 2.0f;
159
destroyCairoContext (thumbContext);
160
setupCairoContext (thumbContext);
162
cr = thumbContext.cr;
163
clearCairoLayer (cr);
165
width = thumbContext.width - outline;
166
height = thumbContext.height - outline;
168
cairo_translate (cr, outline / 2.0f, outline / 2.0f);
170
pattern = cairo_pattern_create_linear (0, 0, width, height);
171
getColorRGBA (ThumbGradientBaseColor);
172
cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);
173
getColorRGBA (ThumbGradientHighlightColor);
174
cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);
176
/* apply the pattern for thumb background */
177
cairo_set_source (cr, pattern);
178
cairo_rectangle (cr, 0, 0, width, height);
179
cairo_fill_preserve (cr);
181
cairo_set_line_width (cr, outline);
182
getColorRGBA (OutlineColor);
183
cairo_set_source_rgba (cr, r, g, b, a);
186
cairo_pattern_destroy (pattern);
192
WallScreen::drawHighlight ()
195
cairo_pattern_t *pattern;
198
float outline = 2.0f;
200
destroyCairoContext (highlightContext);
201
setupCairoContext (highlightContext);
203
cr = highlightContext.cr;
204
clearCairoLayer (cr);
206
width = highlightContext.width - outline;
207
height = highlightContext.height - outline;
209
cairo_translate (cr, outline / 2.0f, outline / 2.0f);
211
pattern = cairo_pattern_create_linear (0, 0, width, height);
212
getColorRGBA (ThumbHighlightGradientBaseColor);
213
cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a);
214
getColorRGBA (ThumbHighlightGradientShadowColor);
215
cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a);
217
/* apply the pattern for thumb background */
218
cairo_set_source (cr, pattern);
219
cairo_rectangle (cr, 0, 0, width, height);
220
cairo_fill_preserve (cr);
222
cairo_set_line_width (cr, outline);
223
getColorRGBA (OutlineColor);
224
cairo_set_source_rgba (cr, r, g, b, a);
227
cairo_pattern_destroy (pattern);
233
WallScreen::drawArrow ()
236
float outline = 2.0f;
239
destroyCairoContext (arrowContext);
240
setupCairoContext (arrowContext);
242
cr = arrowContext.cr;
243
clearCairoLayer (cr);
245
cairo_translate (cr, outline / 2.0f, outline / 2.0f);
247
/* apply the pattern for thumb background */
248
cairo_set_line_width (cr, outline);
250
/* draw top part of the arrow */
251
getColorRGBA (ArrowBaseColor);
252
cairo_set_source_rgba (cr, r, g, b, a);
253
cairo_move_to (cr, 15, 0);
254
cairo_line_to (cr, 30, 30);
255
cairo_line_to (cr, 15, 24.5);
256
cairo_line_to (cr, 15, 0);
259
/* draw bottom part of the arrow */
260
getColorRGBA (ArrowShadowColor);
261
cairo_set_source_rgba (cr, r, g, b, a);
262
cairo_move_to (cr, 15, 0);
263
cairo_line_to (cr, 0, 30);
264
cairo_line_to (cr, 15, 24.5);
265
cairo_line_to (cr, 15, 0);
268
/* draw the arrow outline */
269
getColorRGBA (OutlineColor);
270
cairo_set_source_rgba (cr, r, g, b, a);
271
cairo_move_to (cr, 15, 0);
272
cairo_line_to (cr, 30, 30);
273
cairo_line_to (cr, 15, 24.5);
274
cairo_line_to (cr, 0, 30);
275
cairo_line_to (cr, 15, 0);
282
WallScreen::setupCairoContext (WallCairoContext &context)
284
XRenderPictFormat *format;
288
xScreen = ScreenOfDisplay (screen->dpy (), screen->screenNum ());
290
width = context.width;
291
height = context.height;
293
format = XRenderFindStandardFormat (screen->dpy (), PictStandardARGB32);
295
context.pixmap = XCreatePixmap (screen->dpy (), screen->root (),
298
context.texture = GLTexture::bindPixmapToTexture (context.pixmap,
300
if (context.texture.empty ())
302
screen->logMessage ("wall", CompLogLevelError,
303
"Couldn't create cairo context for switcher");
307
cairo_xlib_surface_create_with_xrender_format (screen->dpy (),
312
context.cr = cairo_create (context.surface);
313
clearCairoLayer (context.cr);
317
WallScreen::destroyCairoContext (WallCairoContext &context)
320
cairo_destroy (context.cr);
323
cairo_surface_destroy (context.surface);
325
context.texture.clear ();
328
XFreePixmap (screen->dpy (), context.pixmap);
332
WallScreen::checkDestination (unsigned int destX,
338
point = screen->vp ();
339
size = screen->vpSize ();
341
if (point.x () - destX < 0)
344
if (point.x () - destX >= (unsigned int) size.width ())
347
if (point.y () - destY >= (unsigned int) size.height ())
350
if (point.y () - destY < 0)
357
WallScreen::releaseMoveWindow ()
361
window = screen->findWindow (moveWindow);
363
window->syncPosition ();
369
WallScreen::computeTranslation (float &x,
372
float elapsed, duration;
374
duration = optionGetSlideDuration () * 1000.0;
376
elapsed = 1.0 - (timer / duration);
385
/* Use temporary variables to you can pass in &ps->cur_x */
386
x = (gotoX - curPosX) * elapsed + curPosX;
387
y = (gotoY - curPosY) * elapsed + curPosY;
390
/* movement remainder that gets ignored for direction calculation */
391
#define IGNORE_REMAINDER 0.05
394
WallScreen::determineMovementAngle ()
399
dx = gotoX - curPosX;
400
dy = gotoY - curPosY;
402
if (dy > IGNORE_REMAINDER)
403
angle = (dx > IGNORE_REMAINDER) ? 135 :
404
(dx < -IGNORE_REMAINDER) ? 225 : 180;
405
else if (dy < -IGNORE_REMAINDER)
406
angle = (dx > IGNORE_REMAINDER) ? 45 :
407
(dx < -IGNORE_REMAINDER) ? 315 : 0;
409
angle = (dx > IGNORE_REMAINDER) ? 90 :
410
(dx < -IGNORE_REMAINDER) ? 270 : -1;
416
WallScreen::moveViewport (int x,
420
CompOption::Vector o(0);
425
if (screen->otherGrabExist ("move", "switcher", "group-drag", "wall", 0))
428
if (!checkDestination (x, y))
431
if (moveWindow != moveWin)
435
releaseMoveWindow ();
436
w = screen->findWindow (moveWin);
439
if (!(w->type () & (CompWindowTypeDesktopMask |
440
CompWindowTypeDockMask)))
442
if (!(w->state () & CompWindowStateStickyMask))
444
moveWindow = w->id ();
445
moveWindowX = w->x ();
446
moveWindowY = w->y ();
455
curPosX = screen->vp ().x ();
456
curPosY = screen->vp ().y ();
458
gotoX = screen->vp ().x () - x;
459
gotoY = screen->vp ().y () - y;
461
determineMovementAngle ();
463
screen->handleCompizEvent ("wall", "start_viewport_switch", o);
466
grabIndex = screen->pushGrab (screen->invisibleCursor (), "wall");
468
screen->moveViewport (x, y, true);
472
boxOutputDevice = screen->outputDeviceForPoint (pointerX, pointerY);
474
if (optionGetShowSwitcher ())
475
boxTimeout = optionGetPreviewTimeout () * 1000;
479
timer = optionGetSlideDuration () * 1000;
481
cScreen->damageScreen ();
487
WallScreen::handleEvent (XEvent *event)
489
switch (event->type) {
491
if (event->xclient.message_type == Atoms::desktopViewport)
495
if (screen->otherGrabExist ("switcher", "wall", 0))
498
dx = event->xclient.data.l[0] / screen->width();
499
dx -= screen->vp ().x ();
500
dy = event->xclient.data.l[1] / screen->height();
501
dy -= screen->vp ().y ();
506
moveViewport (-dx, -dy, None);
508
if (event->xclient.message_type == Atoms::xdndEnter)
513
else if (event->xclient.message_type == Atoms::xdndLeave)
520
if (event->xfocus.mode == NotifyGrab)
522
else if (event->xfocus.mode == NotifyUngrab)
526
case ConfigureNotify:
528
if (event->xconfigure.window == screen->root ())
529
updateScreenEdgeRegions ();
534
screen->handleEvent (event);
538
* Borrowed this from PrivateScreen::updateScreenEdges
542
#define SCREEN_EDGE_NUM 8
545
WallScreen::updateScreenEdgeRegions ()
547
edgeRegion = CompRegion (0, 0, screen->width (), screen->height ());
548
noEdgeRegion = CompRegion (0, 0, screen->width (), screen->height ());
550
struct screenEdgeGeometry {
555
} geometry[SCREEN_EDGE_NUM] = {
556
{ 0, 0, 0, 2, 0, 2, 1, -4 }, /* left */
557
{ 1, -2, 0, 2, 0, 2, 1, -4 }, /* right */
558
{ 0, 2, 0, 0, 1, -4, 0, 2 }, /* top */
559
{ 0, 2, 1, -2, 1, -4, 0, 2 }, /* bottom */
560
{ 0, 0, 0, 0, 0, 2, 0, 2 }, /* top-left */
561
{ 1, -2, 0, 0, 0, 2, 0, 2 }, /* top-right */
562
{ 0, 0, 1, -2, 0, 2, 0, 2 }, /* bottom-left */
563
{ 1, -2, 1, -2, 0, 2, 0, 2 } /* bottom-right */
566
for (unsigned int i = 0; i < SCREEN_EDGE_NUM; i++)
568
CompRegion edge (geometry[i].xw * screen->width () +
570
geometry[i].yh * screen->height () +
572
geometry[i].ww * screen->width () +
574
geometry[i].hh * screen->height () +
577
noEdgeRegion -= edgeRegion;
580
edgeRegion -= noEdgeRegion;
583
#undef SCREEN_EDGE_NUM
586
WallScreen::positionUpdate (const CompPoint &pos)
591
if (edgeRegion.contains (pos))
593
else if (noEdgeRegion.contains (pos))
595
if (!screen->grabbed ())
602
WallWindow::activate ()
604
WALL_SCREEN (screen);
606
if (window->placed () && !screen->otherGrabExist ("wall", "switcher", 0))
611
viewport = window->defaultViewport ();
615
dx -= screen->vp ().x ();
616
dy -= screen->vp ().y ();
620
ws->moveViewport (-dx, -dy, None);
621
ws->focusDefault = false;
629
WallWindow::grabNotify (int x,
634
WallScreen::get (screen)->toggleEdges (true);
635
WallScreen::get (screen)->edgeDrag = true;
637
window->grabNotify (x, y, width, height);
641
WallWindow::ungrabNotify ()
643
WallScreen::get (screen)->edgeDrag = false;
645
window->ungrabNotify ();
649
WallScreen::checkAmount (int dx,
657
point = screen->vp ();
658
size = screen->vpSize ();
663
if (optionGetAllowWraparound ())
665
if ((point.x () + dx) < 0)
666
amountX = -(size.width () + dx);
667
else if ((point.x () + dx) >= size.width ())
668
amountX = size.width () - dx;
670
if ((point.y () + dy) < 0)
671
amountY = -(size.height () + dy);
672
else if ((point.y () + dy) >= size.height ())
673
amountY = size.height () - dy;
678
WallScreen::initiate (CompAction *action,
679
CompAction::State state,
680
CompOption::Vector &options,
684
int dx = 0, dy = 0, amountX, amountY;
685
unsigned int vpX, vpY;
689
vpX = screen->vp ().x ();
690
vpY = screen->vp ().y ();
691
size = screen->vpSize ();
696
checkAmount (dx, dy, amountX, amountY);
700
checkAmount (dx, dy, amountX, amountY);
704
checkAmount (dx, dy, amountX, amountY);
708
checkAmount (dx, dy, amountX, amountY);
711
if ((vpX == (unsigned int) size.width () - 1) &&
712
(vpY == (unsigned int) size.height () - 1))
714
amountX = -(size.width () - 1);
715
amountY = -(size.height () - 1);
717
else if (vpX == (unsigned int) size.width () - 1)
719
amountX = -(size.width () - 1);
730
if (vpX == 0 && vpY == 0)
732
amountX = size.width () - 1;
733
amountY = size.height () - 1;
737
amountX = size.width () - 1;
749
win = CompOption::getIntOptionNamed (options, "window", 0);
751
if (!moveViewport (amountX, amountY, win))
754
if (state & CompAction::StateInitKey)
755
action->setState (action->state () | CompAction::StateTermKey);
757
if (state & CompAction::StateInitButton)
758
action->setState (action->state () | CompAction::StateTermButton);
760
showPreview = optionGetShowSwitcher ();
766
WallScreen::terminate (CompAction *action,
767
CompAction::State state,
768
CompOption::Vector &options)
773
cScreen->damageScreen ();
777
action->setState (action->state () & ~(CompAction::StateTermKey |
778
CompAction::StateTermButton));
784
WallScreen::initiateFlip (Direction direction,
785
CompAction::State state)
788
int amountX, amountY;
790
if (screen->otherGrabExist ("wall", "move", "group-drag", 0))
793
if (state & CompAction::StateInitEdgeDnd)
795
if (!optionGetEdgeflipDnd ())
798
if (screen->otherGrabExist ("wall", 0))
801
else if (screen->grabExist ("move"))
803
if (!optionGetEdgeflipMove ())
806
else if (screen->grabExist ("group-drag"))
808
if (!optionGetEdgeflipDnd ())
811
else if (!optionGetEdgeflipPointer ())
836
checkAmount (dx, dy, amountX, amountY);
837
if (moveViewport (amountX, amountY, None))
839
int offsetX, offsetY;
844
offsetX = screen->width () - 10;
845
warpX = pointerX + screen->width ();
849
offsetX = 1- screen->width ();
850
warpX = pointerX - screen->width ();
855
warpX = lastPointerX;
860
offsetY = screen->height () - 10;
861
warpY = pointerY + screen->height ();
865
offsetY = 1- screen->height ();
866
warpY = pointerY - screen->height ();
871
warpY = lastPointerY;
874
screen->warpPointer (offsetX, offsetY);
875
lastPointerX = warpX;
876
lastPointerY = warpY;
883
wallDrawQuad (GLTexture::Matrix *matrix,
886
glTexCoord2f (COMP_TEX_COORD_X (*matrix, box->x1),
887
COMP_TEX_COORD_Y (*matrix, box->y2));
888
glVertex2i (box->x1, box->y2);
889
glTexCoord2f (COMP_TEX_COORD_X (*matrix, box->x2),
890
COMP_TEX_COORD_Y (*matrix, box->y2));
891
glVertex2i (box->x2, box->y2);
892
glTexCoord2f (COMP_TEX_COORD_X (*matrix, box->x2),
893
COMP_TEX_COORD_Y (*matrix, box->y1));
894
glVertex2i (box->x2, box->y1);
895
glTexCoord2f (COMP_TEX_COORD_X (*matrix, box->x1),
896
COMP_TEX_COORD_Y (*matrix, box->y1));
897
glVertex2i (box->x1, box->y1);
901
WallScreen::drawCairoTextureOnScreen ()
903
float centerX, centerY;
905
float topLeftX, topLeftY;
908
GLTexture::Matrix matrix;
911
CompOutput::vector &outputDevs = screen->outputDevs ();
912
CompOutput output = outputDevs[boxOutputDevice];
914
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
917
centerX = output.x1 () + (output.width () / 2.0f);
918
centerY = output.y1 () + (output.height () / 2.0f);
920
border = (float) viewportBorder;
921
width = (float) switcherContext.width;
922
height = (float) switcherContext.height;
924
topLeftX = centerX - floor (width / 2.0f);
925
topLeftY = centerY - floor (height / 2.0f);
927
firstViewportX = topLeftX + border;
928
firstViewportY = topLeftY + border;
932
double left, timeout;
934
timeout = optionGetPreviewTimeout () * 1000.0f;
935
left = (timeout > 0) ? (float) boxTimeout / timeout : 1.0f;
944
glScreen->setTexEnvMode (GL_MODULATE);
946
glColor4f (left, left, left, left);
947
glTranslatef (0.0f, 0.0f, -(1 - left));
949
mSzCamera = -(1 - left);
956
/* draw background */
958
matrix = switcherContext.texture[0]->matrix ();
959
matrix.x0 -= topLeftX * matrix.xx;
960
matrix.y0 -= topLeftY * matrix.yy;
963
box.x2 = box.x1 + width;
965
box.y2 = box.y1 + height;
967
switcherContext.texture[0]->enable (GLTexture::Fast);
969
wallDrawQuad (&matrix, &box);
971
switcherContext.texture[0]->disable ();
974
width = (float) thumbContext.width;
975
height = (float) thumbContext.height;
977
thumbContext.texture[0]->enable (GLTexture::Fast);
979
for (i = 0; i < (unsigned int) screen->vpSize ().width (); i++)
981
for (j = 0; j < (unsigned int) screen->vpSize ().height (); j++)
983
if (i == gotoX && j == gotoY && moving)
986
box.x1 = i * (width + border);
987
box.x1 += topLeftX + border;
988
box.x2 = box.x1 + width;
989
box.y1 = j * (height + border);
990
box.y1 += topLeftY + border;
991
box.y2 = box.y1 + height;
993
matrix = thumbContext.texture[0]->matrix ();
994
matrix.x0 -= box.x1 * matrix.xx;
995
matrix.y0 -= box.y1 * matrix.yy;
997
wallDrawQuad (&matrix, &box);
1001
thumbContext.texture[0]->disable ();
1003
if (moving || showPreview)
1005
/* draw highlight */
1007
box.x1 = screen->vp ().x () * (width + border) + topLeftX + border;
1008
box.x2 = box.x1 + width;
1009
box.y1 = screen->vp ().y () * (height + border) + topLeftY + border;
1010
box.y2 = box.y1 + height;
1012
matrix = highlightContext.texture[0]->matrix ();
1013
matrix.x0 -= box.x1 * matrix.xx;
1014
matrix.y0 -= box.y1 * matrix.yy;
1016
highlightContext.texture[0]->enable (GLTexture::Fast);
1018
wallDrawQuad (&matrix, &box);
1020
highlightContext.texture[0]->disable ();
1025
arrowContext.texture[0]->enable (GLTexture::Fast);
1026
int aW = arrowContext.width;
1027
int aH = arrowContext.height;
1029
/* if we have a viewport preview we just paint the
1030
arrow outside the switcher */
1031
if (optionGetMiniscreen ())
1033
width = (float) switcherContext.width;
1034
height = (float) switcherContext.height;
1040
box.x1 = topLeftX - aW - border;
1041
box.y1 = topLeftY - aH - border;
1045
box.x1 = topLeftX + width / 2.0f - aW / 2.0f;
1046
box.y1 = topLeftY - aH - border;
1050
box.x1 = topLeftX + width + border;
1051
box.y1 = topLeftY - aH - border;
1055
box.x1 = topLeftX + width + border;
1056
box.y1 = topLeftY + height / 2.0f - aH / 2.0f;
1060
box.x1 = topLeftX + width + border;
1061
box.y1 = topLeftY + height + border;
1065
box.x1 = topLeftX + width / 2.0f - aW / 2.0f;
1066
box.y1 = topLeftY + height + border;
1070
box.x1 = topLeftX - aW - border;
1071
box.y1 = topLeftY + height + border;
1075
box.x1 = topLeftX - aW - border;
1076
box.y1 = topLeftY + height / 2.0f - aH / 2.0f;
1084
/* arrow is visible (no preview is painted over it) */
1085
box.x1 = screen->vp().x() * (width + border) +
1087
box.x1 += width / 2 - aW / 2;
1088
box.y1 = screen->vp().y() * (height + border) +
1090
box.y1 += height / 2 - aH / 2;
1093
box.x2 = box.x1 + aW;
1094
box.y2 = box.y1 + aH;
1096
glTranslatef (box.x1 + aW / 2, box.y1 + aH / 2, 0.0f);
1097
glRotatef (direction, 0.0f, 0.0f, 1.0f);
1098
glTranslatef (-box.x1 - aW / 2, -box.y1 - aH / 2, 0.0f);
1100
matrix = arrowContext.texture[0]->matrix ();
1101
matrix.x0 -= box.x1 * matrix.xx;
1102
matrix.y0 -= box.y1 * matrix.yy;
1105
wallDrawQuad (&matrix, &box);
1108
arrowContext.texture[0]->disable ();
1112
glDisable (GL_BLEND);
1113
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1114
glScreen->setTexEnvMode (GL_REPLACE);
1115
glColor4usv (defaultColor);
1119
WallScreen::paint (CompOutput::ptrList& outputs,
1122
if (moving && outputs.size () > 1 && optionGetMmmode() == MmmodeSwitchAll)
1125
outputs.push_back (&screen->fullscreenOutput ());
1128
cScreen->paint (outputs, mask);
1132
WallScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
1133
const GLMatrix &matrix,
1134
const CompRegion ®ion,
1140
transform = NoTransformation;
1143
mask |= PAINT_SCREEN_TRANSFORMED_MASK |
1144
PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS_MASK;
1146
status = glScreen->glPaintOutput (attrib, matrix, region, output, mask);
1148
if (optionGetShowSwitcher () &&
1149
(moving || showPreview || boxTimeout) &&
1150
(output->id () == boxOutputDevice ||
1151
output == &screen->fullscreenOutput ()))
1153
GLMatrix sMatrix (matrix);
1155
sMatrix.toScreenSpace (output, -DEFAULT_Z_CAMERA);
1158
glLoadMatrixf (sMatrix.getMatrix ());
1160
drawCairoTextureOnScreen ();
1164
if (optionGetMiniscreen ())
1170
mh = viewportHeight;
1172
transform = MiniScreen;
1173
mSAttribs.xScale = mw / screen->width ();
1174
mSAttribs.yScale = mh / screen->height ();
1175
mSAttribs.opacity = OPAQUE * (1.0 + mSzCamera);
1176
mSAttribs.saturation = COLOR;
1178
for (j = 0; j < (unsigned int) screen->vpSize ().height (); j++)
1180
for (i = 0; i < (unsigned int) screen->vpSize ().width (); i++)
1183
unsigned int msMask;
1184
CompPoint vp (i, j);
1186
mx = firstViewportX +
1187
(i * (viewportWidth + viewportBorder));
1188
my = firstViewportY +
1189
(j * (viewportHeight + viewportBorder));
1191
mSAttribs.xTranslate = mx / output->width ();
1192
mSAttribs.yTranslate = -my / output->height ();
1194
mSAttribs.brightness = 0.4f * BRIGHT;
1196
if (vp == screen->vp () &&
1197
(moving || boxTimeout || showPreview))
1199
mSAttribs.brightness = BRIGHT;
1202
cScreen->setWindowPaintOffset ((screen->vp ().x () - i) *
1204
(screen->vp ().y () - j) *
1207
msMask = mask | PAINT_SCREEN_TRANSFORMED_MASK;
1209
glScreen->glPaintTransformedOutput (attrib, matrix,
1210
region, output, msMask);
1214
transform = NoTransformation;
1215
cScreen->setWindowPaintOffset (0, 0);
1223
WallScreen::preparePaint (int msSinceLastPaint)
1225
if (!moving && !showPreview && boxTimeout)
1226
boxTimeout -= msSinceLastPaint;
1229
timer -= msSinceLastPaint;
1233
computeTranslation (curPosX, curPosY);
1239
window = screen->findWindow (moveWindow);
1244
dx = (gotoX - curPosX) * screen->width ();
1245
dy = (gotoY - curPosY) * screen->height ();
1247
window->moveToViewportPosition (moveWindowX - dx,
1254
if (moving && curPosX == gotoX && curPosY == gotoY)
1256
CompOption::Vector o (0);
1261
releaseMoveWindow ();
1262
else if (focusDefault)
1264
/* only focus default window if switcher is not active */
1265
if (!screen->grabExist ("switcher"))
1266
screen->focusDefaultWindow ();
1269
screen->handleCompizEvent ("wall", "end_viewport_switch", o);
1272
cScreen->preparePaint (msSinceLastPaint);
1276
WallScreen::glPaintTransformedOutput (const GLScreenPaintAttrib &attrib,
1277
const GLMatrix &matrix,
1278
const CompRegion ®ion,
1282
bool clear = (mask & PAINT_SCREEN_CLEAR_MASK);
1284
if (transform == MiniScreen)
1286
GLMatrix sMatrix (matrix);
1288
mask &= ~PAINT_SCREEN_CLEAR_MASK;
1290
/* move each screen to the correct output position */
1291
sMatrix.translate (-(float) output->x1 () / (float) output->width (),
1292
(float) output->y1 () / (float) output->height (),
1294
sMatrix.translate (0.0f, 0.0f, -DEFAULT_Z_CAMERA);
1296
sMatrix.translate (mSAttribs.xTranslate,
1297
mSAttribs.yTranslate,
1300
/* move origin to top left */
1301
sMatrix.translate (-0.5f, 0.5f, 0.0f);
1302
sMatrix.scale (mSAttribs.xScale, mSAttribs.yScale, 1.0);
1304
/* revert prepareXCoords region shift.
1305
Now all screens display the same */
1306
sMatrix.translate (0.5f, 0.5f, DEFAULT_Z_CAMERA);
1307
sMatrix.translate ((float) output->x1 () / (float) output->width (),
1308
-(float) output->y2 () / (float) output->height (),
1311
glScreen->glPaintTransformedOutput (attrib, sMatrix,
1312
screen->region (), output, mask);
1317
glScreen->glPaintTransformedOutput (attrib, matrix,
1318
region, output, mask);
1320
mask &= ~PAINT_SCREEN_CLEAR_MASK;
1324
ScreenTransformation oldTransform = transform;
1325
GLMatrix sMatrix (matrix);
1326
float xTranslate, yTranslate;
1328
bool movingX, movingY;
1329
CompPoint point (screen->vp ());
1330
CompRegion outputRegion (*output);
1333
glScreen->clearTargetOutput (GL_COLOR_BUFFER_BIT);
1335
transform = Sliding;
1336
currOutput = output;
1341
movingX = ((int) floor (px)) != ((int) ceil (px));
1342
movingY = ((int) floor (py)) != ((int) ceil (py));
1346
yTranslate = fmod (py, 1) - 1;
1348
sMatrix.translate (0.0f, yTranslate, 0.0f);
1352
xTranslate = 1 - fmod (px, 1);
1354
cScreen->setWindowPaintOffset ((point.x () - ceil (px)) *
1356
(point.y () - ceil (py)) *
1359
sMatrix.translate (xTranslate, 0.0f, 0.0f);
1361
glScreen->glPaintTransformedOutput (attrib, sMatrix,
1362
outputRegion, output, mask);
1364
sMatrix.translate (-xTranslate, 0.0f, 0.0f);
1366
xTranslate = -fmod (px, 1);
1368
cScreen->setWindowPaintOffset ((point.x () - floor (px)) *
1370
(point.y () - ceil (py)) *
1373
sMatrix.translate (xTranslate, 0.0f, 0.0f);
1375
glScreen->glPaintTransformedOutput (attrib, sMatrix,
1376
outputRegion, output, mask);
1377
sMatrix.translate (-xTranslate, -yTranslate, 0.0f);
1380
yTranslate = fmod (py, 1);
1382
sMatrix.translate (0.0f, yTranslate, 0.0f);
1386
xTranslate = 1 - fmod (px, 1);
1388
cScreen->setWindowPaintOffset ((point.x () - ceil (px)) *
1390
(point.y () - floor (py)) *
1393
sMatrix.translate (xTranslate, 0.0f, 0.0f);
1395
glScreen->glPaintTransformedOutput (attrib, sMatrix,
1396
outputRegion, output, mask);
1398
sMatrix.translate (-xTranslate, 0.0f, 0.0f);
1401
xTranslate = -fmod (px, 1);
1403
cScreen->setWindowPaintOffset ((point.x () - floor (px)) *
1405
(point.y () - floor (py)) *
1408
sMatrix.translate (xTranslate, 0.0f, 0.0f);
1409
glScreen->glPaintTransformedOutput (attrib, sMatrix, outputRegion,
1412
cScreen->setWindowPaintOffset (0, 0);
1413
transform = oldTransform;
1418
WallWindow::glPaint (const GLWindowPaintAttrib &attrib,
1419
const GLMatrix &matrix,
1420
const CompRegion ®ion,
1425
WALL_SCREEN (screen);
1427
if (ws->transform == MiniScreen)
1429
GLWindowPaintAttrib pA (attrib);
1431
pA.opacity = attrib.opacity *
1432
((float) ws->mSAttribs.opacity / OPAQUE);
1433
pA.brightness = attrib.brightness *
1434
((float) ws->mSAttribs.brightness / BRIGHT);
1435
pA.saturation = attrib.saturation *
1436
((float) ws->mSAttribs.saturation / COLOR);
1438
if (!pA.opacity || !pA.brightness)
1439
mask |= PAINT_WINDOW_NO_CORE_INSTANCE_MASK;
1441
status = glWindow->glPaint (pA, matrix, region, mask);
1443
else if (ws->transform == Sliding && !isSliding)
1447
wMatrix.toScreenSpace (ws->currOutput, -DEFAULT_Z_CAMERA);
1448
mask |= PAINT_WINDOW_TRANSFORMED_MASK;
1450
status = glWindow->glPaint (attrib, wMatrix, region, mask);
1454
status = glWindow->glPaint (attrib, matrix, region, mask);
1461
WallScreen::donePaint ()
1463
if (moving || showPreview || boxTimeout)
1465
boxTimeout = MAX (0, boxTimeout);
1466
cScreen->damageScreen ();
1469
if (!moving && !showPreview && grabIndex)
1471
screen->removeGrab (grabIndex, NULL);
1475
cScreen->donePaint ();
1479
WallScreen::createCairoContexts (bool initial)
1483
viewportWidth = VIEWPORT_SWITCHER_SIZE *
1484
(float) optionGetPreviewScale () / 100.0f;
1485
viewportHeight = viewportWidth * (float) screen->height () /
1486
(float) screen->width ();
1487
viewportBorder = optionGetBorderWidth ();
1489
width = screen->vpSize ().width () * (viewportWidth + viewportBorder) +
1491
height = screen->vpSize ().height () * (viewportHeight + viewportBorder) +
1494
destroyCairoContext (switcherContext);
1495
switcherContext.width = width;
1496
switcherContext.height = height;
1497
setupCairoContext (switcherContext);
1498
drawSwitcherBackground ();
1500
destroyCairoContext (thumbContext);
1501
thumbContext.width = viewportWidth;
1502
thumbContext.height = viewportHeight;
1503
setupCairoContext (thumbContext);
1506
destroyCairoContext (highlightContext);
1507
highlightContext.width = viewportWidth;
1508
highlightContext.height = viewportHeight;
1509
setupCairoContext (highlightContext);
1514
arrowContext.width = ARROW_SIZE;
1515
arrowContext.height = ARROW_SIZE;
1516
setupCairoContext (arrowContext);
1522
WallScreen::toggleEdges (bool enabled)
1524
WALL_SCREEN (screen);
1528
screen->removeAction (&ws->optionGetFlipLeftEdge ());
1529
screen->removeAction (&ws->optionGetFlipUpEdge ());
1530
screen->removeAction (&ws->optionGetFlipRightEdge ());
1531
screen->removeAction (&ws->optionGetFlipDownEdge ());
1535
screen->addAction (&ws->optionGetFlipLeftEdge ());
1536
screen->addAction (&ws->optionGetFlipUpEdge ());
1537
screen->addAction (&ws->optionGetFlipRightEdge ());
1538
screen->addAction (&ws->optionGetFlipDownEdge ());
1543
WallScreen::optionChanged (CompOption *opt,
1544
WallOptions::Options num)
1547
case WallOptions::OutlineColor:
1548
drawSwitcherBackground ();
1553
case WallOptions::EdgeRadius:
1554
case WallOptions::BackgroundGradientBaseColor:
1555
case WallOptions::BackgroundGradientHighlightColor:
1556
case WallOptions::BackgroundGradientShadowColor:
1557
drawSwitcherBackground ();
1560
case WallOptions::BorderWidth:
1561
case WallOptions::PreviewScale:
1562
createCairoContexts (false);
1565
case WallOptions::ThumbGradientBaseColor:
1566
case WallOptions::ThumbGradientHighlightColor:
1570
case WallOptions::ThumbHighlightGradientBaseColor:
1571
case WallOptions::ThumbHighlightGradientShadowColor:
1575
case WallOptions::ArrowBaseColor:
1576
case WallOptions::ArrowShadowColor:
1580
case WallOptions::NoSlideMatch:
1581
foreach (CompWindow *w, screen->windows ())
1584
ww->isSliding = !optionGetNoSlideMatch ().evaluate (w);
1594
WallScreen::setOptionForPlugin (const char *plugin,
1596
CompOption::Value &value)
1598
bool status = screen->setOptionForPlugin (plugin, name, value);
1600
if (strcmp (plugin, "core") == 0)
1602
if (strcmp (name, "hsize") == 0 || strcmp (name, "vsize") == 0)
1604
createCairoContexts (false);
1612
WallScreen::matchExpHandlerChanged ()
1614
screen->matchExpHandlerChanged ();
1616
foreach (CompWindow *w, screen->windows ())
1619
ww->isSliding = !optionGetNoSlideMatch ().evaluate (w);
1624
WallScreen::matchPropertyChanged (CompWindow *window)
1626
WALL_WINDOW (window);
1628
screen->matchPropertyChanged (window);
1630
ww->isSliding = !optionGetNoSlideMatch ().evaluate (window);
1633
WallScreen::WallScreen (CompScreen *screen) :
1634
PluginClassHandler <WallScreen, CompScreen> (screen),
1636
cScreen (CompositeScreen::get (screen)),
1637
glScreen (GLScreen::get (screen)),
1639
showPreview (false),
1645
focusDefault (true),
1646
transform (NoTransformation)
1648
ScreenInterface::setHandler (screen);
1649
CompositeScreenInterface::setHandler (cScreen);
1650
GLScreenInterface::setHandler (glScreen);
1652
// HACK: we have to keep libcairo loaded even if wall gets unloaded
1653
// to prevent crashes in XCloseDisplay
1654
dlopen ("libcairo.so.2", RTLD_LAZY);
1656
memset (&switcherContext, 0, sizeof (WallCairoContext));
1657
memset (&thumbContext, 0, sizeof (WallCairoContext));
1658
memset (&highlightContext, 0, sizeof (WallCairoContext));
1659
memset (&arrowContext, 0, sizeof (WallCairoContext));
1660
createCairoContexts (true);
1662
#define setAction(action, dir, win) \
1663
optionSet##action##Initiate (boost::bind (&WallScreen::initiate, this, \
1664
_1, _2, _3, dir, win)); \
1665
optionSet##action##Terminate (boost::bind (&WallScreen::terminate, this, \
1668
#define setFlipAction(action, dir) \
1669
optionSet##action##Initiate (boost::bind (&WallScreen::initiateFlip, \
1672
setAction (LeftKey, Left, false);
1673
setAction (RightKey, Right, false);
1674
setAction (UpKey, Up, false);
1675
setAction (DownKey, Down, false);
1676
setAction (NextKey, Next, false);
1677
setAction (PrevKey, Prev, false);
1678
setAction (LeftButton, Left, false);
1679
setAction (RightButton, Right, false);
1680
setAction (UpButton, Up, false);
1681
setAction (DownButton, Down, false);
1682
setAction (NextButton, Next, false);
1683
setAction (PrevButton, Prev, false);
1684
setAction (LeftWindowKey, Left, true);
1685
setAction (RightWindowKey, Right, true);
1686
setAction (UpWindowKey, Up, true);
1687
setAction (DownWindowKey, Down, true);
1689
setFlipAction (FlipLeftEdge, Left);
1690
setFlipAction (FlipRightEdge, Right);
1691
setFlipAction (FlipUpEdge, Up);
1692
setFlipAction (FlipDownEdge, Down);
1694
#define setNotify(func) \
1695
optionSet##func##Notify (boost::bind (&WallScreen::optionChanged, \
1698
setNotify (EdgeRadius);
1699
setNotify (BorderWidth);
1700
setNotify (PreviewScale);
1701
setNotify (OutlineColor);
1702
setNotify (BackgroundGradientBaseColor);
1703
setNotify (BackgroundGradientHighlightColor);
1704
setNotify (BackgroundGradientShadowColor);
1705
setNotify (ThumbGradientBaseColor);
1706
setNotify (ThumbGradientHighlightColor);
1707
setNotify (ThumbHighlightGradientBaseColor);
1708
setNotify (ThumbHighlightGradientShadowColor);
1709
setNotify (ArrowBaseColor);
1710
setNotify (ArrowShadowColor);
1711
setNotify (NoSlideMatch);
1712
setNotify (EdgeflipPointer);
1714
updateScreenEdgeRegions ();
1716
poller.setCallback (boost::bind (&WallScreen::positionUpdate, this,
1720
WallScreen::~WallScreen ()
1722
destroyCairoContext (switcherContext);
1723
destroyCairoContext (thumbContext);
1724
destroyCairoContext (highlightContext);
1725
destroyCairoContext (arrowContext);
1728
WallWindow::WallWindow (CompWindow *window) :
1729
PluginClassHandler <WallWindow, CompWindow> (window),
1731
glWindow (GLWindow::get (window))
1733
WALL_SCREEN (screen);
1735
isSliding = !ws->optionGetNoSlideMatch ().evaluate (window);
1737
GLWindowInterface::setHandler (glWindow);
1738
WindowInterface::setHandler (window);
1742
WallPluginVTable::init ()
1744
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
1746
if (!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI))
1748
if (!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
1750
if (!CompPlugin::checkPluginABI ("mousepoll", COMPIZ_MOUSEPOLL_ABI))