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
51
#include <cairo/cairo-xlib.h>
54
/* ------ Input Prevention -------------------------------------------*/
57
* Thanks to Joel Bosveld (b0le)
58
* for helping me with this section
65
Window xipw = mInput->ipw;
66
CompWindow *ipw = screen->findWindow (xipw);
73
width = mInputRect.width ();
74
height = mInputRect.height ();
76
Pixmap b = XCreatePixmap (screen->dpy (), xipw, width, height, 1);
78
cairo_surface_t *bitmap =
79
cairo_xlib_surface_create_for_bitmap (screen->dpy (),
81
DefaultScreenOfDisplay (screen->dpy ()),
84
cr = cairo_create (bitmap);
87
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
91
/* Move to our first corner (TopLeft) */
94
mOutput.shapex1 - MIN(mInputRect.x1 (), mInputRect.x2 ()),
95
mOutput.shapey1 - MIN(mInputRect.y1 (), mInputRect.y2 ()));
97
/* Line to TopRight */
100
mOutput.shapex2 - MIN(mInputRect.x1 (), mInputRect.x2 ()),
101
mOutput.shapey2 - MIN(mInputRect.y1 (), mInputRect.y2 ()));
103
/* Line to BottomRight */
106
mOutput.shapex4 - MIN(mInputRect.x1 (), mInputRect.x2 ()),
107
mOutput.shapey4 - MIN(mInputRect.y1 (), mInputRect.y2 ()));
109
/* Line to BottomLeft */
112
mOutput.shapex3 - MIN(mInputRect.x1 (), mInputRect.x2 ()),
113
mOutput.shapey3 - MIN(mInputRect.y1 (), mInputRect.y2 ()));
115
/* Line to TopLeft */
118
mOutput.shapex1 - MIN(mInputRect.x1 (), mInputRect.x2 ()),
119
mOutput.shapey1 - MIN(mInputRect.y1 (), mInputRect.y2 ()));
121
/* Ensure it's all closed up */
123
cairo_close_path (cr);
125
/* Fill in the box */
127
cairo_set_source_rgb (cr, 1.0f, 1.0f, 1.0f);
130
/* This takes the bitmap we just drew with cairo
131
* and scans out the white bits (You can see these)
132
* if you uncomment the following line after this
133
* comment. Then, all the bits we drew on are clickable,
134
* leaving us with a nice and neat window shape. Yummy.
137
/* XWriteBitmapFile (ipw->screen->display->display,
138
"/path/to/your/image.bmp",
144
XShapeCombineMask (screen->dpy (), xipw,
151
XFreePixmap (screen->dpy (), b);
152
cairo_surface_destroy (bitmap);
159
FWWindow::saveInputShape (XRectangle **retRects,
164
int count = 0, ordering;
165
Display *dpy = screen->dpy ();
167
rects = XShapeGetRectangles (dpy, window->id (), ShapeInput, &count, &ordering);
169
/* check if the returned shape exactly matches the window shape -
170
if that is true, the window currently has no set input shape */
172
(rects[0].x == -window->geometry ().border ()) &&
173
(rects[0].y == -window->geometry ().border ()) &&
174
(rects[0].width == (window->serverWidth () +
175
window->serverGeometry ().border ())) &&
176
(rects[0].height == (window->serverHeight () +
177
window->serverGeometry (). border ())))
184
*retOrdering = ordering;
188
FWScreen::addWindowToList (FWWindowInputInfo *info)
190
mTransformedWindows.push_back (info);
194
FWScreen::removeWindowFromList (FWWindowInputInfo *info)
196
mTransformedWindows.remove (info);
199
/* Adjust size and location of the input prevention window */
201
FWWindow::adjustIPW ()
204
Display *dpy = screen->dpy ();
205
float f_width, f_height;
207
if (!mInput || !mInput->ipw)
210
f_width = mInputRect.width ();
211
f_height = mInputRect.height ();
213
xwc.x = mInputRect.x ();
214
xwc.y = mInputRect.y ();
215
xwc.width = (int) f_width;
216
xwc.height = (int) f_height;
217
xwc.stack_mode = Below;
218
/* XXX: This causes XConfigureWindow to break */
219
//xwc.sibling = window->id ();
221
XMapWindow (dpy, mInput->ipw);
223
XConfigureWindow (dpy, mInput->ipw,
224
CWStackMode | CWX | CWY | CWWidth | CWHeight,
231
FWScreen::adjustIPWStacking ()
234
foreach (FWWindowInputInfo *run, mTransformedWindows)
236
if (!run->w->prev || run->w->prev->id () != run->ipw)
237
FWWindow::get (run->w)->adjustIPW ();
241
/* Create an input prevention window */
243
FWWindow::createIPW ()
246
XSetWindowAttributes attrib;
249
if (!mInput || mInput->ipw)
252
attrib.override_redirect = true;
253
//attrib.event_mask = 0;
255
xwc.x = mInputRect.x ();
256
xwc.y = mInputRect.y ();
257
xwc.width = mInputRect.width ();
258
xwc.height = mInputRect.height ();
260
ipw = XCreateWindow (screen->dpy (),
262
xwc.x, xwc.y, xwc.width, xwc.height, 0, CopyFromParent, InputOnly,
263
CopyFromParent, CWOverrideRedirect, &attrib);
265
XMapWindow (screen->dpy (), ipw);
267
//XConfigureWindow (screen->dpy (), ipw, CWStackMode | CWX | CWY | CWWidth | CWHeight, &xwc);
274
FWWindowInputInfo::FWWindowInputInfo (CompWindow *window) :
279
inputRectOrdering (0),
280
frameInputRects (NULL),
281
frameNInputRects (0),
282
frameInputRectOrdering (0)
286
FWWindowInputInfo::~FWWindowInputInfo ()
291
FWWindow::handleWindowInputInfo ()
293
FREEWINS_SCREEN (screen);
295
if (!mTransformed && mInput)
298
XDestroyWindow (screen->dpy (), mInput->ipw);
301
fws->removeWindowFromList (mInput);
308
else if (mTransformed && !mInput)
310
mInput = new FWWindowInputInfo (window);
316
fws->addWindowToList (mInput);
322
/* Shape the input of the window when scaled.
323
* Since the IPW will be dealing with the input, removing input
324
* from the window entirely is a perfectly good solution. */
326
FWWindow::shapeInput ()
329
Display *dpy = screen->dpy();
331
saveInputShape (&mInput->inputRects,
332
&mInput->nInputRects,
333
&mInput->inputRectOrdering);
335
frame = window->frame();
338
saveInputShape (&mInput->frameInputRects, &mInput->frameNInputRects,
339
&mInput->frameInputRectOrdering);
343
mInput->frameInputRects = NULL;
344
mInput->frameNInputRects = -1;
345
mInput->frameInputRectOrdering = 0;
349
XShapeSelectInput (dpy, window->id(), NoEventMask);
350
XShapeCombineRectangles (dpy, window->id(), ShapeInput, 0, 0,
351
NULL, 0, ShapeSet, 0);
354
XShapeCombineRectangles (dpy, window->frame(), ShapeInput, 0, 0,
355
NULL, 0, ShapeSet, 0);
357
XShapeSelectInput (dpy, window->id(), ShapeNotify);
360
/* Restores the shape of the window:
361
* If the window had a custom shape defined by inputRects then we restore
362
* that in order with XShapeCombineRectangles.
363
* Most windows have no specific defined shape so we can restore it with
364
* setting the shape to a 0x0 mask
367
FWWindow::unshapeInput ()
369
Display *dpy = screen->dpy ();
371
if (mInput->nInputRects)
373
XShapeCombineRectangles (dpy, window->id(), ShapeInput, 0, 0,
374
mInput->inputRects, mInput->nInputRects,
375
ShapeSet, mInput->inputRectOrdering);
379
XShapeCombineMask (dpy, window->id(), ShapeInput, 0, 0, None, ShapeSet);
382
if (mInput->frameNInputRects >= 0)
384
if (mInput->frameNInputRects)
386
XShapeCombineRectangles (dpy, window->frame(), ShapeInput, 0, 0,
387
mInput->frameInputRects,
388
mInput->frameNInputRects,
390
mInput->frameInputRectOrdering);
394
XShapeCombineMask (dpy, window->frame(), ShapeInput, 0, 0, None, ShapeSet);