2
* Compiz Fusion Freewins plugin
6
* Copyright (C) 2007 Rodolfo Granata <warlock.cc@gmail.com>
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License
10
* as published by the Free Software Foundation; either version 2
11
* of the License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
19
* Rodolfo Granata <warlock.cc@gmail.com>
20
* Sam Spilsbury <smspillaz@gmail.com>
22
* Button binding support and Reset added by:
23
* enigma_0Z <enigma.0ZA@gmail.com>
25
* Most of the input handling here is based on
27
* : Kristian Lyngstøl <kristian@bohemians.org>
28
* : Danny Baumann <maniac@opencompositing.org>
32
* This plugin allows you to freely transform the texture of a window,
33
* whether that be rotation or scaling to make better use of screen space
37
* - Fully implement an input redirection system by
38
* finding an inverse matrix, multiplying by it,
39
* translating to the actual window co-ords and
40
* XSendEvent() the co-ords to the actual window.
41
* - Code could be cleaner
42
* - Add timestep and speed options to animation
43
* - Add window hover-over info via paintOutput : i.e
50
/* TODO: Finish porting stuff to actions */
55
/* ------ Actions -------------------------------------------------------*/
57
/* Initiate Mouse Rotation */
59
FWScreen::initiateFWRotate (CompAction *action,
60
CompAction::State state,
61
CompOption::Vector options)
67
xid = CompOption::getIntOptionNamed (options, "window", 0);
69
w = screen->findWindow (xid);
70
useW = screen->findWindow (xid);
75
foreach (FWWindowInputInfo *info, mTransformedWindows)
78
if (w->id () == info->ipw)
79
/* The window we just grabbed was actually
80
* an IPW, get the real window instead
82
useW = getRealWindow (w);
85
mRotateCursor = XCreateFontCursor (screen->dpy (), XC_fleur);
87
if (!screen->otherGrabExist ("freewins", 0))
90
mGrabIndex = screen->pushGrab (0, "freewins");
96
if (true || optionGetShapeWindowTypes ().evaluate (useW))
98
FREEWINS_WINDOW (useW);
100
int x = CompOption::getIntOptionNamed (options, "x",
101
useW->x () + (useW->width () / 2));
102
int y = CompOption::getIntOptionNamed (options, "y",
103
useW->y () + (useW->height () / 2));
105
int mods = CompOption::getIntOptionNamed (options, "modifiers", 0);
109
fww->mGrab = grabRotate;
111
/* Save current scales and angles */
113
fww->mAnimate.oldAngX = fww->mTransform.angX;
114
fww->mAnimate.oldAngY = fww->mTransform.angY;
115
fww->mAnimate.oldAngZ = fww->mTransform.angZ;
116
fww->mAnimate.oldScaleX = fww->mTransform.scaleX;
117
fww->mAnimate.oldScaleY = fww->mTransform.scaleY;
119
if (pointerY > fww->mIMidY)
121
if (pointerX > fww->mIMidX)
122
fww->mCorner = CornerBottomRight;
123
else if (pointerX < fww->mIMidX)
124
fww->mCorner = CornerBottomLeft;
126
else if (pointerY < fww->mIMidY)
128
if (pointerX > fww->mIMidX)
129
fww->mCorner = CornerTopRight;
130
else if (pointerX < fww->mIMidX)
131
fww->mCorner = CornerTopLeft;
134
switch (optionGetZAxisRotation ())
136
case ZAxisRotationAlways3d:
141
case ZAxisRotationAlways2d:
146
case ZAxisRotationDetermineOnClick:
147
case ZAxisRotationSwitch:
148
fww->determineZAxisClick (pointerX, pointerY, FALSE);
151
case ZAxisRotationInterchangeable:
160
/* Set the rotation axis */
162
switch (optionGetRotationAxis ())
164
case RotationAxisAlwaysCentre:
166
fww->calculateInputOrigin (WIN_REAL_X (mGrabWindow) +
167
WIN_REAL_W (mGrabWindow) / 2.0f,
168
WIN_REAL_Y (mGrabWindow) +
169
WIN_REAL_H (mGrabWindow) / 2.0f);
170
fww->calculateOutputOrigin (WIN_OUTPUT_X (mGrabWindow) +
171
WIN_OUTPUT_W (mGrabWindow) / 2.0f,
172
WIN_OUTPUT_Y (mGrabWindow) +
173
WIN_OUTPUT_H (mGrabWindow) / 2.0f);
176
case RotationAxisClickPoint:
177
fww->calculateInputOrigin (mClick_root_x, mClick_root_y);
178
fww->calculateOutputOrigin (mClick_root_x, mClick_root_y);
181
case RotationAxisOppositeToClick:
182
fww->calculateInputOrigin (useW->x () + useW->width () - mClick_root_x,
183
useW->y () + useW->height () - mClick_root_y);
184
fww->calculateOutputOrigin (useW->x () + useW->width () - mClick_root_x,
185
useW->y () + useW->height () - mClick_root_y);
189
/* Announce that we grabbed the window */
190
useW->grabNotify (x, y, mods, CompWindowGrabMoveMask |
191
CompWindowGrabButtonMask);
193
/* Shape the window beforehand and avoid a stale grab */
194
if (fww->canShape ())
195
if (fww->handleWindowInputInfo ())
198
cScreen->damageScreen ();
200
if (state & CompAction::StateInitButton)
201
action->setState (action->state () | CompAction::StateTermButton);
209
FWScreen::terminateFWRotate (CompAction *action,
210
CompAction::State state,
211
CompOption::Vector options)
213
if (mGrabWindow && mGrabIndex)
215
FREEWINS_WINDOW (mGrabWindow);
216
if (fww->mGrab == grabRotate)
220
fww->window->ungrabNotify ();
222
switch (optionGetRotationAxis ())
224
case RotationAxisClickPoint:
225
case RotationAxisOppositeToClick:
227
distX = (fww->mOutputRect.x1 () +
228
(fww->mOutputRect.width ()) / 2.0f) -
229
(WIN_REAL_X (mGrabWindow) +
230
WIN_REAL_W (mGrabWindow) / 2.0f);
231
distY = (fww->mOutputRect.y1 () +
232
(fww->mOutputRect.height ()) / 2.0f) -
233
(WIN_REAL_Y (mGrabWindow) +
234
WIN_REAL_H (mGrabWindow) / 2.0f);
236
mGrabWindow->move (distX, distY, true);
238
fww->calculateInputOrigin (WIN_REAL_X (mGrabWindow) +
239
WIN_REAL_W (mGrabWindow) / 2.0f,
240
WIN_REAL_Y (mGrabWindow) +
241
WIN_REAL_H (mGrabWindow) / 2.0f);
242
fww->calculateOutputOrigin (WIN_OUTPUT_X (mGrabWindow) +
243
WIN_OUTPUT_W (mGrabWindow) / 2.0f,
244
WIN_OUTPUT_Y (mGrabWindow) +
245
WIN_OUTPUT_H (mGrabWindow) / 2.0f);
252
if (fww->canShape ())
253
if (fww->handleWindowInputInfo ())
256
screen->removeGrab (mGrabIndex, 0);
259
fww->mGrab = grabNone;
263
action->setState (action->state () & ~(CompAction::StateTermKey |
264
CompAction::StateTermButton));
269
/*static void FWMoveWindowToCorrectPosition (CompWindow *w, float distX, float distY)
272
FREEWINS_WINDOW (w); action->setState (action->state () & ~(CompAction::StateTermKey |
273
CompAction::StateTermButton));
275
fprintf(stderr, "distX is %f distY is %f midX and midY are %f %f\n", distX, distY, fww->mIMidX, fww->mIMidY);
277
moveWindow (w, distX * (1 + (1 - fww->mTransform.scaleX)), distY * (1 + (1 - fww->mTransform.scaleY)), TRUE, FALSE);
279
syncWindowPosition (w);
282
/* Initiate Scaling */
284
FWScreen::initiateFWScale (CompAction *action,
285
CompAction::State state,
286
CompOption::Vector options)
292
xid = CompOption::getIntOptionNamed (options, "window", 0);
293
w = screen->findWindow (xid);
294
useW = screen->findWindow (xid);
298
foreach (FWWindowInputInfo *info, mTransformedWindows)
301
if (w->id () == info->ipw)
302
/* The window we just grabbed was actually
303
* an IPW, get the real window instead
305
useW = getRealWindow (w);
308
mRotateCursor = XCreateFontCursor (screen->dpy (), XC_fleur);
310
if (!screen->otherGrabExist ("freewins", 0))
312
mGrabIndex = screen->pushGrab (mRotateCursor, "freewins");
317
if (optionGetShapeWindowTypes ().evaluate (useW))
319
FREEWINS_WINDOW (useW);
321
int x = CompOption::getIntOptionNamed (options, "x",
322
useW->x () + (useW->width () / 2));
323
int y = CompOption::getIntOptionNamed (options, "y",
324
useW->y () + (useW->height () / 2));
326
int mods = CompOption::getIntOptionNamed (options, "modifiers", 0);
330
/* Find out the corner we clicked in */
332
float MidX = fww->mInputRect.centerX ();
333
float MidY = fww->mInputRect.centerY ();
335
/* Check for Y axis clicking (Top / Bottom) */
338
/* Check for X axis clicking (Left / Right) */
340
fww->mCorner = CornerBottomRight;
341
else if (pointerX < MidX)
342
fww->mCorner = CornerBottomLeft;
344
else if (pointerY < MidY)
346
/* Check for X axis clicking (Left / Right) */
348
fww->mCorner = CornerTopRight;
349
else if (pointerX < MidX)
350
fww->mCorner = CornerTopLeft;
353
switch (optionGetScaleMode ())
355
case ScaleModeToCentre:
356
fww->calculateInputOrigin(WIN_REAL_X (useW) + WIN_REAL_W (useW) / 2.0f,
357
WIN_REAL_Y (useW) + WIN_REAL_H (useW) / 2.0f);
358
fww->calculateOutputOrigin(WIN_OUTPUT_X (useW) + WIN_OUTPUT_W (useW) / 2.0f,
359
WIN_OUTPUT_Y (useW) + WIN_OUTPUT_H (useW) / 2.0f);
362
*Experimental scale to corners mode
364
case ScaleModeToOppositeCorner:
365
switch (fww->mCorner)
367
case CornerBottomRight:
368
/* Translate origin to the top left of the window */
369
//FWMoveWindowToCorrectPosition (w, fww->inputRect.x1 - WIN_REAL_X (useW), fww->inputRect.y1 - WIN_REAL_Y (useW));
370
fww->calculateInputOrigin (WIN_REAL_X (useW), WIN_REAL_Y (useW));
373
case CornerBottomLeft:
374
/* Translate origin to the top right of the window */
375
//FWMoveWindowToCorrectPosition (w, fww->inputRect.x2 - (WIN_REAL_X (useW) + WIN_REAL_W (useW)), fww->inputRect.y1 - WIN_REAL_Y (useW));
376
fww->calculateInputOrigin (WIN_REAL_X (useW) + (WIN_REAL_W (useW)), WIN_REAL_Y (useW));
380
/* Translate origin to the bottom left of the window */
381
//FWMoveWindowToCorrectPosition (w, fww->inputRect.x1 - WIN_REAL_X (useW) , fww->inputRect.y1 - (WIN_REAL_Y (useW) + WIN_REAL_H (useW)));
382
fww->calculateInputOrigin (WIN_REAL_X (useW), WIN_REAL_Y (useW) + (WIN_REAL_H (useW)));
386
/* Translate origin to the bottom right of the window */
387
//FWMoveWindowToCorrectPosition (w, fww->inputRect.x1 -(WIN_REAL_X (useW) + WIN_REAL_W (useW)) , fww->inputRect.y1 - (WIN_REAL_Y (useW) + WIN_REAL_H (useW)));
388
fww->calculateInputOrigin (WIN_REAL_X (useW) + (WIN_REAL_W (useW)), WIN_REAL_Y (useW) + (WIN_REAL_H (useW)));
394
fww->mGrab = grabScale;
396
/* Announce that we grabbed the window */
397
useW->grabNotify (x, y, mods, CompWindowGrabMoveMask |
398
CompWindowGrabButtonMask);
400
cScreen->damageScreen ();
402
/* Shape the window beforehand and avoid a stale grab */
403
if (fww->canShape ())
404
if (fww->handleWindowInputInfo ())
408
if (state & CompAction::StateInitButton)
409
action->setState (action->state () | CompAction::StateTermButton);
417
FWScreen::terminateFWScale (CompAction *action,
418
CompAction::State state,
419
CompOption::Vector options)
421
if (mGrabWindow && mGrabIndex)
423
FREEWINS_WINDOW (mGrabWindow);
424
if (fww->mGrab == grabScale)
426
fww->window->ungrabNotify ();
428
switch (optionGetScaleMode ())
432
case ScaleModeToOppositeCorner:
433
distX = (fww->mOutputRect.x1 () + (fww->mOutputRect.width () / 2.0f) - (WIN_REAL_X (mGrabWindow) + WIN_REAL_W (mGrabWindow) / 2.0f));
434
distY = (fww->mOutputRect.y1 () + (fww->mOutputRect.width () / 2.0f) - (WIN_REAL_Y (mGrabWindow) + WIN_REAL_H (mGrabWindow) / 2.0f));
436
mGrabWindow->move (distX, distY, true);
438
fww->calculateInputOrigin (WIN_REAL_X (mGrabWindow) +
439
WIN_REAL_W (mGrabWindow) / 2.0f,
440
WIN_REAL_Y (mGrabWindow) +
441
WIN_REAL_H (mGrabWindow) / 2.0f);
442
fww->calculateOutputOrigin (WIN_OUTPUT_X (mGrabWindow) +
443
WIN_OUTPUT_W (mGrabWindow) / 2.0f,
444
WIN_OUTPUT_Y (mGrabWindow) +
445
WIN_OUTPUT_H (mGrabWindow) / 2.0f);
454
screen->removeGrab (mGrabIndex, 0);
457
fww->mGrab = grabNone;
461
action->setState (action->state () & ~(CompAction::StateTermKey |
462
CompAction::StateTermButton));
467
/* Repetitive Stuff */
470
FWWindow::setPrepareRotation (float dx,
476
if (FWScreen::get (screen)->optionGetShapeWindowTypes ().evaluate (window))
478
calculateInputOrigin (WIN_REAL_X (window) +
479
WIN_REAL_W (window) / 2.0f,
480
WIN_REAL_Y (window) +
481
WIN_REAL_H (window) / 2.0f);
482
calculateOutputOrigin (WIN_OUTPUT_X (window) +
483
WIN_OUTPUT_W (window) / 2.0f,
484
WIN_OUTPUT_Y (window) +
485
WIN_OUTPUT_H (window) / 2.0f);
487
mTransform.unsnapAngX += dy;
488
mTransform.unsnapAngY -= dx;
489
mTransform.unsnapAngZ += dz;
491
mTransform.unsnapScaleX += dsu;
492
mTransform.unsnapScaleY += dsd;
494
mAnimate.oldAngX = mTransform.angX;
495
mAnimate.oldAngY = mTransform.angY;
496
mAnimate.oldAngZ = mTransform.angZ;
498
mAnimate.oldScaleX = mTransform.scaleX;
499
mAnimate.oldScaleY = mTransform.scaleY;
501
mAnimate.destAngX = mTransform.angX + dy;
502
mAnimate.destAngY = mTransform.angY - dx;
503
mAnimate.destAngZ = mTransform.angZ + dz;
505
mAnimate.destScaleX = mTransform.scaleX + dsu;
506
mAnimate.destScaleY = mTransform.scaleY + dsd;
511
#define ROTATE_INC freewinsGetRotateIncrementAmount (w->screen)
512
#define NEG_ROTATE_INC freewinsGetRotateIncrementAmount (w->screen) *-1
514
#define SCALE_INC freewinsGetScaleIncrementAmount (w->screen)
515
#define NEG_SCALE_INC freewinsGetScaleIncrementAmount (w->screen) *-1
518
FWScreen::rotate (CompAction *action,
519
CompAction::State state,
520
CompOption::Vector options, int dx, int dy, int dz)
522
CompWindow *w = screen->findWindow (CompOption::getIntOptionNamed (options,
525
foreach (FWWindowInputInfo *info, mTransformedWindows)
527
if (info->ipw == w->id ())
529
w = getRealWindow (w);
535
fww->setPrepareRotation (dx, dy, dz, 0, 0);
537
if (fww->canShape ())
538
if (fww->handleWindowInputInfo ())
545
FWScreen::scale (CompAction *action,
546
CompAction::State state,
547
CompOption::Vector options,
550
CompWindow *w = screen->findWindow (CompOption::getIntOptionNamed (options,
553
foreach (FWWindowInputInfo *info, mTransformedWindows)
555
if (info->ipw == w->id ())
557
w = getRealWindow (w);
563
fww->setPrepareRotation (0, 0, 0, scale, scale);
564
fww->cWindow->addDamage ();
566
if (fww->canShape ())
567
if (fww->handleWindowInputInfo ())
570
if (!optionGetAllowNegative ())
572
float minScale = optionGetMinScale ();
574
if (fww->mAnimate.destScaleX < minScale)
575
fww->mAnimate.destScaleX = minScale;
577
if (fww->mAnimate.destScaleY < minScale)
578
fww->mAnimate.destScaleY = minScale;
584
/* Reset the Rotation and Scale to 0 and 1 */
586
FWScreen::resetFWTransform (CompAction *action,
587
CompAction::State state,
588
CompOption::Vector options)
590
CompWindow *w = screen->findWindow (CompOption::getIntOptionNamed (options,
593
foreach (FWWindowInputInfo *info, mTransformedWindows)
595
if (info->ipw == w->id ())
597
w = getRealWindow (w);
604
fww->setPrepareRotation (fww->mTransform.angY,
605
-fww->mTransform.angX,
606
-fww->mTransform.angZ,
607
(1 - fww->mTransform.scaleX),
608
(1 - fww->mTransform.scaleY));
609
fww->cWindow->addDamage ();
611
fww->mTransformed = FALSE;
613
if (fww->canShape ())
614
if (fww->handleWindowInputInfo ())
617
fww->mResetting = TRUE;
623
/* Callable action to rotate a window to the angle provided
624
* x: Set angle to x degrees
625
* y: Set angle to y degrees
626
* z: Set angle to z degrees
627
* window: The window to apply the transformation to
630
FWScreen::rotateAction (CompAction *action,
631
CompAction::State state,
632
CompOption::Vector options)
636
w = screen->findWindow (CompOption::getIntOptionNamed (options, "window", 0));
642
float x = CompOption::getFloatOptionNamed(options, "x", 0.0f);
643
float y = CompOption::getFloatOptionNamed(options, "y", 0.0f);
644
float z = CompOption::getFloatOptionNamed(options, "z", 0.0f);
646
fww->setPrepareRotation (x - fww->mAnimate.destAngX,
647
y - fww->mAnimate.destAngY,
648
z - fww->mAnimate.destAngZ, 0, 0);
649
fww->cWindow->addDamage ();
660
/* Callable action to increment window rotation by the angles provided
661
* x: Increment angle by x degrees
662
* y: Increment angle by y degrees
663
* z: Increment angle by z degrees
664
* window: The window to apply the transformation to
667
FWScreen::incrementRotateAction (CompAction *action,
668
CompAction::State state,
669
CompOption::Vector options)
673
w = screen->findWindow (CompOption::getIntOptionNamed (options, "window", 0));
679
float x = CompOption::getFloatOptionNamed(options, "x", 0.0f);
680
float y = CompOption::getFloatOptionNamed(options, "y", 0.0f);
681
float z = CompOption::getFloatOptionNamed(options, "z", 0.0f);
683
fww->setPrepareRotation (x,
686
fww->cWindow->addDamage ();
697
/* Callable action to scale a window to the scale provided
698
* x: Set scale to x factor
699
* y: Set scale to y factor
700
* window: The window to apply the transformation to
703
FWScreen::scaleAction (CompAction *action,
704
CompAction::State state,
705
CompOption::Vector options)
709
w = screen->findWindow (CompOption::getIntOptionNamed (options, "window", 0));
715
float x = CompOption::getFloatOptionNamed (options, "x", 0.0f);
716
float y = CompOption::getFloatOptionNamed (options, "y", 0.0f);
718
fww->setPrepareRotation (0, 0, 0,
719
x - fww->mAnimate.destScaleX,
720
y - fww->mAnimate.destScaleY);
721
if (fww->canShape ())
722
if (fww->handleWindowInputInfo ())
725
/* Stop scale at threshold specified */
726
if (!optionGetAllowNegative ())
728
float minScale = optionGetMinScale ();
729
if (fww->mAnimate.destScaleX < minScale)
730
fww->mAnimate.destScaleX = minScale;
732
if (fww->mAnimate.destScaleY < minScale)
733
fww->mAnimate.destScaleY = minScale;
736
fww->cWindow->addDamage ();
738
if (fww->canShape ())
739
fww->handleWindowInputInfo ();
750
/* Toggle Axis-Help Display */
752
FWScreen::toggleFWAxis (CompAction *action,
753
CompAction::State state,
754
CompOption::Vector options)
756
mAxisHelp = !mAxisHelp;
758
cScreen->damageScreen ();