source: proiecte/PPPP/gdm/utils/gdm-screenshot.c @ 134

Last change on this file since 134 was 134, checked in by (none), 14 years ago

gdm sources with the modifications for webcam

File size: 8.1 KB
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20
21#include "config.h"
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <unistd.h>
26#include <string.h>
27#include <locale.h>
28
29#include <glib/gi18n.h>
30#include <gtk/gtk.h>
31#include <canberra-gtk.h>
32
33#include <X11/Xatom.h>
34#include <gdk/gdkx.h>
35
36#define SELECTION_NAME "_GDM_SCREENSHOT"
37static GtkWidget *selection_window;
38
39static gboolean debug_in;
40
41/* Keep all config options for compatibility even if they are noops */
42GOptionEntry options [] = {
43        { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_in, N_("Debugging output"), NULL },
44        { NULL }
45};
46
47/* To make sure there is only one screenshot taken at a time,
48 * (Imagine key repeat for the print screen key) we hold a selection
49 * until we are done taking the screenshot
50 */
51/*  * Copyright (C) 2001-2006  Jonathan Blandford <jrb@alum.mit.edu> */
52static gboolean
53screenshot_grab_lock (void)
54{
55        Atom       selection_atom;
56        GdkCursor *cursor;
57        gboolean   result = FALSE;
58
59        selection_atom = gdk_x11_get_xatom_by_name (SELECTION_NAME);
60        XGrabServer (GDK_DISPLAY ());
61        if (XGetSelectionOwner (GDK_DISPLAY(), selection_atom) != None) {
62                goto out;
63        }
64
65        selection_window = gtk_invisible_new ();
66        gtk_widget_show (selection_window);
67
68        if (!gtk_selection_owner_set (selection_window,
69                                      gdk_atom_intern (SELECTION_NAME, FALSE),
70                                      GDK_CURRENT_TIME)) {
71                gtk_widget_destroy (selection_window);
72                selection_window = NULL;
73                goto out;
74        }
75
76        cursor = gdk_cursor_new (GDK_WATCH);
77        gdk_pointer_grab (selection_window->window, FALSE, 0, NULL,
78                          cursor, GDK_CURRENT_TIME);
79        gdk_cursor_unref (cursor);
80
81        result = TRUE;
82
83 out:
84        XUngrabServer (GDK_DISPLAY ());
85        gdk_flush ();
86
87        return result;
88}
89
90/*  * Copyright (C) 2001-2006  Jonathan Blandford <jrb@alum.mit.edu> */
91static void
92screenshot_release_lock (void)
93{
94        if (selection_window != NULL) {
95                gtk_widget_destroy (selection_window);
96                selection_window = NULL;
97        }
98        gdk_flush ();
99}
100
101/*  * Copyright (C) 2001-2006  Jonathan Blandford <jrb@alum.mit.edu> */
102static GdkPixbuf *
103screenshot_get_pixbuf (Window w)
104{
105        GdkWindow *window;
106        GdkWindow *root;
107        GdkPixbuf *screenshot;
108        int        x_real_orig;
109        int        y_real_orig;
110        int        x_orig;
111        int        y_orig;
112        int        real_width;
113        int        real_height;
114        int        width;
115        int        height;
116
117        window = gdk_window_foreign_new (w);
118        if (window == NULL) {
119                return NULL;
120        }
121
122        root = gdk_window_foreign_new (GDK_ROOT_WINDOW ());
123        gdk_drawable_get_size (window, &real_width, &real_height);
124        gdk_window_get_origin (window, &x_real_orig, &y_real_orig);
125
126        x_orig = x_real_orig;
127        y_orig = y_real_orig;
128        width = real_width;
129        height = real_height;
130
131        if (x_orig < 0) {
132                width = width + x_orig;
133                x_orig = 0;
134        }
135        if (y_orig < 0) {
136                height = height + y_orig;
137                y_orig = 0;
138        }
139
140        if (x_orig + width > gdk_screen_width ()) {
141                width = gdk_screen_width () - x_orig;
142        }
143        if (y_orig + height > gdk_screen_height ()) {
144                height = gdk_screen_height () - y_orig;
145        }
146
147        screenshot = gdk_pixbuf_get_from_drawable (NULL,
148                                                   root,
149                                                   NULL,
150                                                   x_orig,
151                                                   y_orig,
152                                                   0,
153                                                   0,
154                                                   width,
155                                                   height);
156
157        return screenshot;
158}
159
160static char *
161screenshot_save (GdkPixbuf *pixbuf)
162{
163        char       *filename;
164        gboolean    res;
165        GError     *error;
166        const char *save_dir;
167
168        save_dir = LOCALSTATEDIR "/run/gdm";
169
170        filename = g_build_filename (save_dir,
171                                     "GDM-Screenshot.png",
172                                     NULL);
173
174        error = NULL;
175        res = gdk_pixbuf_save (pixbuf,
176                               filename,
177                               "png",
178                               &error,
179                               "tEXt::CREATOR", "gdm-screenshot",
180                               NULL);
181        if (! res) {
182                g_warning ("Unable to save screenshot: %s", error->message);
183                g_error_free (error);
184                g_free (filename);
185                filename = NULL;
186        }
187
188        return filename;
189}
190
191static void
192sound_effect_finished (ca_context *c,
193                       uint32_t    id,
194                       int         error_code,
195                       void       *userdata)
196{
197}
198
199static void
200play_sound_effect (Window xid)
201{
202        ca_context  *c;
203        ca_proplist *p;
204        int          res;
205
206        c = ca_gtk_context_get ();
207
208        p = NULL;
209        res = ca_proplist_create (&p);
210        if (res < 0) {
211                goto done;
212        }
213
214        res = ca_proplist_sets (p, CA_PROP_EVENT_ID, "screen-capture");
215        if (res < 0) {
216                goto done;
217        }
218
219        res = ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Screenshot taken"));
220        if (res < 0) {
221                goto done;
222        }
223
224        res = ca_proplist_setf (p,
225                                CA_PROP_WINDOW_X11_XID,
226                                "%lu",
227                                (unsigned long) xid);
228        if (res < 0) {
229                goto done;
230        }
231
232        ca_context_play_full (c, 0, p, sound_effect_finished, NULL);
233
234 done:
235        if (p != NULL) {
236                ca_proplist_destroy (p);
237        }
238
239}
240
241static void
242prepare_screenshot (void)
243{
244        Window     win;
245        GdkPixbuf *screenshot;
246        char      *filename;
247
248        if (!screenshot_grab_lock ()) {
249                exit (0);
250        }
251
252        win = GDK_ROOT_WINDOW ();
253
254        screenshot = screenshot_get_pixbuf (win);
255
256        screenshot_release_lock ();
257
258        if (screenshot == NULL) {
259                /* FIXME: dialog? */
260                exit (1);
261        }
262
263        play_sound_effect (win);
264
265        filename = screenshot_save (screenshot);
266        if (filename != NULL) {
267                g_print ("Wrote %s\n", filename);
268                /* FIXME: show a dialog or something */
269                g_free (filename);
270        }
271}
272
273int
274main (int argc, char *argv[])
275{
276        GOptionContext *ctx;
277
278        bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
279        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
280        textdomain (GETTEXT_PACKAGE);
281        setlocale (LC_ALL, "");
282
283        /* Option parsing */
284        ctx = g_option_context_new (_("Take a picture of the screen"));
285        g_option_context_set_translation_domain (ctx, GETTEXT_PACKAGE);
286        g_option_context_add_main_entries (ctx, options, NULL);
287        g_option_context_parse (ctx, &argc, &argv, NULL);
288        g_option_context_free (ctx);
289
290        gtk_init (&argc, &argv);
291
292        prepare_screenshot ();
293
294        return 1;
295}
Note: See TracBrowser for help on using the repository browser.