2
* Copyright © 2006 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>
26
#include "screenshot.h"
28
COMPIZ_PLUGIN_20090315 (screenshot, ShotPluginVTable)
31
ShotScreen::initiate (CompAction *action,
32
CompAction::State state,
33
CompOption::Vector &options)
37
xid = CompOption::getIntOptionNamed (options, "root");
39
if (xid != ::screen->root ())
42
if (::screen->otherGrabExist ("screenshot", 0))
47
mGrabIndex = ::screen->pushGrab (None, "screenshot");
48
screen->handleEventSetEnabled (this, true);
51
if (state & CompAction::StateInitButton)
52
action->setState (action->state () | CompAction::StateTermButton);
54
/* start selection screenshot rectangle */
61
gScreen->glPaintOutputSetEnabled (this, true);
67
ShotScreen::terminate (CompAction *action,
68
CompAction::State state,
69
CompOption::Vector &options)
73
xid = CompOption::getIntOptionNamed (options, "root");
75
if (xid && xid != ::screen->root ())
80
// Enable screen capture
81
cScreen->paintSetEnabled (this, true);
82
::screen->removeGrab (mGrabIndex, 0);
85
::screen->handleEventSetEnabled (this, false);
87
if (mX1 != mX2 && mY1 != mY2)
89
int x1 = MIN (mX1, mX2) - 1;
90
int y1 = MIN (mY1, mY2) - 1;
91
int x2 = MAX (mX1, mX2) + 1;
92
int y2 = MAX (mY1, mY2) + 1;
94
cScreen->damageRegion (CompRegion (x1, y1, x2 - x1, y2 - y1));
98
action->setState (action->state () & ~(CompAction::StateTermKey |
99
CompAction::StateTermButton));
101
gScreen->glPaintOutputSetEnabled (this, false);
107
shotFilter (const struct dirent *d)
111
if (sscanf (d->d_name, "screenshot%d.png", &number))
118
shotSort (const void *_a,
121
struct dirent **a = (struct dirent **) _a;
122
struct dirent **b = (struct dirent **) _b;
123
int al = strlen ((*a)->d_name);
124
int bl = strlen ((*b)->d_name);
127
return strcoll ((*a)->d_name, (*b)->d_name);
133
ShotScreen::paint (CompOutput::ptrList &outputs,
136
cScreen->paint (outputs, mask);
155
CompString dir (optionGetDirectory ());
157
buffer = (GLubyte *)malloc (sizeof (GLubyte) * w * h * 4);
160
struct dirent **namelist;
163
glReadPixels (x1, ::screen->height () - y2, w, h,
164
GL_RGBA, GL_UNSIGNED_BYTE,
167
n = scandir (dir.c_str (), &namelist, shotFilter, shotSort);
174
sscanf (namelist[n - 1]->d_name,
183
sprintf (name, "screenshot%d.png", number);
185
CompString app (optionGetLaunchApp ());
186
CompString path (dir + "/" + name);
187
CompSize imageSize (w, h);
189
if (!::screen->writeImageToFile (path, "png",
192
compLogMessage ("screenshot", CompLogLevelError,
193
"failed to write screenshot image");
195
else if (app.length () > 0)
197
::screen->runCommand (app + " " + path);
202
perror (dir.c_str ());
209
// Disable screen capture
210
cScreen->paintSetEnabled (this, false);
217
ShotScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
218
const GLMatrix &matrix,
219
const CompRegion ®ion,
225
status = gScreen->glPaintOutput (attrib, matrix, region, output, mask);
240
glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
241
glScalef (1.0f / output->width (),
242
-1.0f / output->height (),
244
glTranslatef (-output->region ()->extents.x1,
245
-output->region ()->extents.y2,
248
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
250
glColor4us (0x2fff, 0x2fff, 0x4fff, 0x4fff);
251
glRecti (x1, y2, x2, y1);
252
glColor4us (0x2fff, 0x2fff, 0x4fff, 0x9fff);
253
glBegin (GL_LINE_LOOP);
259
glColor4usv (defaultColor);
260
glDisable (GL_BLEND);
261
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
270
ShotScreen::handleMotionEvent (int xRoot,
273
/* update screenshot rectangle size */
279
x1 = MIN (mX1, mX2) - 1;
280
y1 = MIN (mY1, mY2) - 1;
281
x2 = MAX (mX1, mX2) + 1;
282
y2 = MAX (mY1, mY2) + 1;
284
cScreen->damageRegion (CompRegion (x1, y1, x2 - x1, y2 - y1));
289
x1 = MIN (mX1, mX2) - 1;
290
y1 = MIN (mY1, mY2) - 1;
291
x2 = MAX (mX1, mX2) + 1;
292
y2 = MAX (mY1, mY2) + 1;
294
cScreen->damageRegion (CompRegion (x1, y1, x2 - x1, y2 - y1));
296
cScreen->damageScreen ();
301
ShotScreen::handleEvent (XEvent *event)
303
switch (event->type) {
305
if (event->xmotion.root == screen->root ())
306
handleMotionEvent (pointerX, pointerY);
310
if (event->xcrossing.root == screen->root ())
311
handleMotionEvent (pointerX, pointerY);
316
::screen->handleEvent (event);
319
ShotScreen::ShotScreen (CompScreen *screen) :
320
PluginClassHandler<ShotScreen, CompScreen> (screen),
321
cScreen (CompositeScreen::get (screen)),
322
gScreen (GLScreen::get (screen)),
326
optionSetInitiateButtonInitiate (boost::bind (&ShotScreen::initiate, this,
328
optionSetInitiateButtonTerminate (boost::bind (&ShotScreen::terminate, this,
331
ScreenInterface::setHandler (screen, false);
332
CompositeScreenInterface::setHandler (cScreen, false);
333
GLScreenInterface::setHandler (gScreen, false);
337
ShotPluginVTable::init ()
339
if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) |
340
!CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) |
341
!CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))