~mc-return/compiz/compiz.merge-src-header-files-cleanup

« back to all changes in this revision

Viewing changes to plugins/screenshot/src/screenshot.cpp

  • Committer: Erkin Bahceci
  • Date: 2009-07-22 04:09:58 UTC
  • Revision ID: git-v1:a8224ec6ea72211303d47059956f9b5fd43263d0
C++ port of screenshot plugin.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2006 Novell, Inc.
 
3
 *
 
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
 
13
 * implied warranty.
 
14
 *
 
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.
 
22
 *
 
23
 * Author: David Reveman <davidr@novell.com>
 
24
 */
 
25
 
 
26
#include "screenshot.h"
 
27
 
 
28
COMPIZ_PLUGIN_20090315 (screenshot, ShotPluginVTable)
 
29
 
 
30
bool
 
31
ShotScreen::initiate (CompAction            *action,
 
32
                      CompAction::State     state,
 
33
                      CompOption::Vector    &options)
 
34
{
 
35
    Window     xid;
 
36
 
 
37
    xid = CompOption::getIntOptionNamed (options, "root");
 
38
 
 
39
    if (xid != ::screen->root ())
 
40
        return false;
 
41
 
 
42
    if (::screen->otherGrabExist ("screenshot", 0))
 
43
        return false;
 
44
 
 
45
    if (!mGrabIndex)
 
46
    {
 
47
        mGrabIndex = ::screen->pushGrab (None, "screenshot");
 
48
        screen->handleEventSetEnabled (this, true);
 
49
    }
 
50
 
 
51
    if (state & CompAction::StateInitButton)
 
52
        action->setState (action->state () | CompAction::StateTermButton);
 
53
 
 
54
    /* start selection screenshot rectangle */
 
55
 
 
56
    mX1 = mX2 = pointerX;
 
57
    mY1 = mY2 = pointerY;
 
58
 
 
59
    mGrab = true;
 
60
 
 
61
    gScreen->glPaintOutputSetEnabled (this, true);
 
62
 
 
63
    return true;
 
64
}
 
65
 
 
66
bool
 
67
ShotScreen::terminate (CompAction            *action,
 
68
                       CompAction::State     state,
 
69
                       CompOption::Vector    &options)
 
70
{
 
71
    Window     xid;
 
72
 
 
73
    xid = CompOption::getIntOptionNamed (options, "root");
 
74
 
 
75
    if (xid && xid != ::screen->root ())
 
76
        return false;
 
77
 
 
78
    if (mGrabIndex)
 
79
    {
 
80
        // Enable screen capture
 
81
        cScreen->paintSetEnabled (this, true);
 
82
        ::screen->removeGrab (mGrabIndex, 0);
 
83
        mGrabIndex = 0;
 
84
 
 
85
        ::screen->handleEventSetEnabled (this, false);
 
86
 
 
87
        if (mX1 != mX2 && mY1 != mY2)
 
88
        {
 
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;
 
93
 
 
94
            cScreen->damageRegion (CompRegion (x1, y1, x2 - x1, y2 - y1));
 
95
        }
 
96
    }
 
97
 
 
98
    action->setState (action->state () & ~(CompAction::StateTermKey |
 
99
                                           CompAction::StateTermButton));
 
100
 
 
101
    gScreen->glPaintOutputSetEnabled (this, false);
 
102
 
 
103
    return false;
 
104
}
 
105
 
 
106
static int
 
107
shotFilter (const struct dirent *d)
 
108
{
 
109
    int number;
 
110
 
 
111
    if (sscanf (d->d_name, "screenshot%d.png", &number))
 
112
        return 1;
 
113
 
 
114
    return 0;
 
115
}
 
116
 
 
117
static int
 
118
shotSort (const void *_a,
 
119
          const void *_b)
 
120
{
 
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);
 
125
 
 
126
    if (al == bl)
 
127
        return strcoll ((*a)->d_name, (*b)->d_name);
 
128
    else
 
129
        return al - bl;
 
130
}
 
131
 
 
132
void
 
133
ShotScreen::paint (CompOutput::ptrList &outputs,
 
134
                   unsigned int        mask)
 
135
{
 
136
    cScreen->paint (outputs, mask);
 
137
 
 
138
    if (mGrab)
 
139
    {
 
140
        int x1, x2, y1, y2;
 
141
 
 
142
        x1 = MIN (mX1, mX2);
 
143
        y1 = MIN (mY1, mY2);
 
144
        x2 = MAX (mX1, mX2);
 
145
        y2 = MAX (mY1, mY2);
 
146
 
 
147
        if (!mGrabIndex)
 
148
        {
 
149
            int w = x2 - x1;
 
150
            int h = y2 - y1;
 
151
 
 
152
            if (w && h)
 
153
            {
 
154
                GLubyte *buffer;
 
155
                CompString dir (optionGetDirectory ());
 
156
 
 
157
                buffer = (GLubyte *)malloc (sizeof (GLubyte) * w * h * 4);
 
158
                if (buffer)
 
159
                {
 
160
                    struct dirent **namelist;
 
161
                    int           n;
 
162
 
 
163
                    glReadPixels (x1, ::screen->height () - y2, w, h,
 
164
                                  GL_RGBA, GL_UNSIGNED_BYTE,
 
165
                                  (GLvoid *) buffer);
 
166
 
 
167
                    n = scandir (dir.c_str (), &namelist, shotFilter, shotSort);
 
168
                    if (n >= 0)
 
169
                    {
 
170
                        char name[256];
 
171
                        int  number = 0;
 
172
 
 
173
                        if (n > 0)
 
174
                            sscanf (namelist[n - 1]->d_name,
 
175
                                    "screenshot%d.png",
 
176
                                    &number);
 
177
 
 
178
                        number++;
 
179
 
 
180
                        if (n)
 
181
                            free (namelist);
 
182
 
 
183
                        sprintf (name, "screenshot%d.png", number);
 
184
 
 
185
                        CompString app (optionGetLaunchApp ());
 
186
                        CompString path (dir + "/" + name);
 
187
                        CompSize imageSize (w, h);
 
188
 
 
189
                        if (!::screen->writeImageToFile (path, "png",
 
190
                                                         imageSize, buffer))
 
191
                        {
 
192
                            compLogMessage ("screenshot", CompLogLevelError,
 
193
                                            "failed to write screenshot image");
 
194
                        }
 
195
                        else if (app.length () > 0)
 
196
                        {
 
197
                            ::screen->runCommand (app + " " + path);
 
198
                        }
 
199
                    }
 
200
                    else
 
201
                    {
 
202
                        perror (dir.c_str ());
 
203
                    }
 
204
 
 
205
                    free (buffer);
 
206
                }
 
207
            }
 
208
 
 
209
            // Disable screen capture
 
210
            cScreen->paintSetEnabled (this, false);
 
211
            mGrab = false;
 
212
        }
 
213
    }
 
214
}
 
215
 
 
216
bool
 
217
ShotScreen::glPaintOutput (const GLScreenPaintAttrib &attrib,
 
218
                           const GLMatrix            &matrix,
 
219
                           const CompRegion          &region,
 
220
                           CompOutput                *output,
 
221
                           unsigned int               mask)
 
222
{
 
223
    bool status;
 
224
 
 
225
    status = gScreen->glPaintOutput (attrib, matrix, region, output, mask);
 
226
 
 
227
    if (status && mGrab)
 
228
    {
 
229
        int x1, x2, y1, y2;
 
230
 
 
231
        x1 = MIN (mX1, mX2);
 
232
        y1 = MIN (mY1, mY2);
 
233
        x2 = MAX (mX1, mX2);
 
234
        y2 = MAX (mY1, mY2);
 
235
 
 
236
        if (mGrabIndex)
 
237
        {
 
238
            glPushMatrix ();
 
239
 
 
240
            glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
 
241
            glScalef (1.0f  / output->width (),
 
242
                      -1.0f / output->height (),
 
243
                      1.0f);
 
244
            glTranslatef (-output->region ()->extents.x1,
 
245
                          -output->region ()->extents.y2,
 
246
                          0.0f);
 
247
 
 
248
            glDisableClientState (GL_TEXTURE_COORD_ARRAY);
 
249
            glEnable (GL_BLEND);
 
250
            glColor4us (0x2fff, 0x2fff, 0x4fff, 0x4fff);
 
251
            glRecti (x1, y2, x2, y1);
 
252
            glColor4us (0x2fff, 0x2fff, 0x4fff, 0x9fff);
 
253
            glBegin (GL_LINE_LOOP);
 
254
            glVertex2i (x1, y1);
 
255
            glVertex2i (x2, y1);
 
256
            glVertex2i (x2, y2);
 
257
            glVertex2i (x1, y2);
 
258
            glEnd ();
 
259
            glColor4usv (defaultColor);
 
260
            glDisable (GL_BLEND);
 
261
            glEnableClientState (GL_TEXTURE_COORD_ARRAY);
 
262
            glPopMatrix ();
 
263
        }
 
264
    }
 
265
 
 
266
    return status;
 
267
}
 
268
 
 
269
void
 
270
ShotScreen::handleMotionEvent (int xRoot,
 
271
                               int yRoot)
 
272
{
 
273
    /* update screenshot rectangle size */
 
274
 
 
275
    if (mGrabIndex)
 
276
    {
 
277
        int x1, x2, y1, y2;
 
278
 
 
279
        x1 = MIN (mX1, mX2) - 1;
 
280
        y1 = MIN (mY1, mY2) - 1;
 
281
        x2 = MAX (mX1, mX2) + 1;
 
282
        y2 = MAX (mY1, mY2) + 1;
 
283
 
 
284
        cScreen->damageRegion (CompRegion (x1, y1, x2 - x1, y2 - y1));
 
285
 
 
286
        mX2 = xRoot;
 
287
        mY2 = yRoot;
 
288
 
 
289
        x1 = MIN (mX1, mX2) - 1;
 
290
        y1 = MIN (mY1, mY2) - 1;
 
291
        x2 = MAX (mX1, mX2) + 1;
 
292
        y2 = MAX (mY1, mY2) + 1;
 
293
 
 
294
        cScreen->damageRegion (CompRegion (x1, y1, x2 - x1, y2 - y1));
 
295
 
 
296
        cScreen->damageScreen ();
 
297
    }
 
298
}
 
299
 
 
300
void
 
301
ShotScreen::handleEvent (XEvent *event)
 
302
{
 
303
    switch (event->type) {
 
304
        case MotionNotify:
 
305
            if (event->xmotion.root == screen->root ())
 
306
                handleMotionEvent (pointerX, pointerY);
 
307
            break;
 
308
        case EnterNotify:
 
309
        case LeaveNotify:
 
310
            if (event->xcrossing.root == screen->root ())
 
311
                handleMotionEvent (pointerX, pointerY);
 
312
        default:
 
313
            break;
 
314
    }
 
315
 
 
316
    ::screen->handleEvent (event);
 
317
}
 
318
 
 
319
ShotScreen::ShotScreen (CompScreen *screen) :
 
320
    PluginClassHandler<ShotScreen, CompScreen> (screen),
 
321
    cScreen (CompositeScreen::get (screen)),
 
322
    gScreen (GLScreen::get (screen)),
 
323
    mGrabIndex (0),
 
324
    mGrab (false)
 
325
{
 
326
    optionSetInitiateButtonInitiate (boost::bind (&ShotScreen::initiate, this,
 
327
                                                  _1, _2, _3));
 
328
    optionSetInitiateButtonTerminate (boost::bind (&ShotScreen::terminate, this,
 
329
                                                   _1, _2, _3));
 
330
 
 
331
    ScreenInterface::setHandler (screen, false);
 
332
    CompositeScreenInterface::setHandler (cScreen, false);
 
333
    GLScreenInterface::setHandler (gScreen, false);
 
334
}
 
335
 
 
336
bool
 
337
ShotPluginVTable::init ()
 
338
{
 
339
    if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION) |
 
340
        !CompPlugin::checkPluginABI ("composite", COMPIZ_COMPOSITE_ABI) |
 
341
        !CompPlugin::checkPluginABI ("opengl", COMPIZ_OPENGL_ABI))
 
342
         return false;
 
343
 
 
344
    return true;
 
345
}
 
346