~darkxst/ubuntu/saucy/gnome-shell/upstart_log

« back to all changes in this revision

Viewing changes to src/shell-screenshot.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-05-31 12:01:12 UTC
  • mfrom: (1.1.49) (19.1.36 experimental)
  • Revision ID: package-import@ubuntu.com-20130531120112-ew91khxf051x9i2r
Tags: 3.8.2-1ubuntu1
* Merge with Debian (LP: #1185869, #1185721). Remaining changes:
  - debian/control.in:
    + Build-depend on libsystemd-login-dev & libsystemd-daemon-dev
    + Depend on gdm instead of gdm3
    + Don't recommend gnome-session-fallback
  - debian/patches/40_change-pam-name-to-match-gdm.patch:
  - debian/patches/revert-suspend-break.patch:
    + Disabled, not needed on Ubuntu
  - debian/patches/ubuntu-lightdm-user-switching.patch:
    + Allow user switching when using LightDM. Thanks Gerhard Stein
      for rebasing against gnome-shell 3.8!
  - debian/patches/ubuntu_lock_on_suspend.patch
    + Respect Ubuntu's lock-on-suspend setting.
      Disabled until it can be rewritten.
  - debian/patches/git_relock_screen_after_crash.patch:
    + Add Upstream fix for unlocked session after crash (LP: #1064584)
* Note that the new GNOME Classic mode (which requires installing
  gnome-shell-extensions) won't work until gnome-session 3.8 is
  available in Ubuntu

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
2
 
 
3
#define COGL_ENABLE_EXPERIMENTAL_API
 
4
#define CLUTTER_ENABLE_EXPERIMENTAL_API
 
5
 
3
6
#include <X11/extensions/Xfixes.h>
4
7
#include <clutter/x11/clutter-x11.h>
5
8
#include <clutter/clutter.h>
10
13
#include <meta/meta-shaped-texture.h>
11
14
 
12
15
#include "shell-global.h"
13
 
#include "shell-screen-grabber.h"
14
16
#include "shell-screenshot.h"
15
17
 
16
18
struct _ShellScreenshotClass
30
32
  ShellScreenshot  *screenshot;
31
33
 
32
34
  char *filename;
 
35
  char *filename_used;
33
36
 
34
37
  cairo_surface_t *image;
35
38
  cairo_rectangle_int_t screenshot_area;
62
65
  if (screenshot_data->callback)
63
66
    screenshot_data->callback (screenshot_data->screenshot,
64
67
                               g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (result)),
65
 
                               &screenshot_data->screenshot_area);
 
68
                               &screenshot_data->screenshot_area,
 
69
                               screenshot_data->filename_used);
66
70
 
67
71
  cairo_surface_destroy (screenshot_data->image);
68
72
  g_object_unref (screenshot_data->screenshot);
69
73
  g_free (screenshot_data->filename);
 
74
  g_free (screenshot_data->filename_used);
70
75
  g_free (screenshot_data);
71
76
}
72
77
 
 
78
/* called in an I/O thread */
 
79
static GOutputStream *
 
80
get_stream_for_unique_path (const gchar *path,
 
81
                            const gchar *filename,
 
82
                            gchar **filename_used)
 
83
{
 
84
  GOutputStream *stream;
 
85
  GFile *file;
 
86
  gchar *real_path, *real_filename, *name, *ptr;
 
87
  gint idx;
 
88
 
 
89
  ptr = g_strrstr (filename, ".png");
 
90
 
 
91
  if (ptr != NULL)
 
92
    real_filename = g_strndup (filename, ptr - filename);
 
93
  else
 
94
    real_filename = g_strdup (filename);
 
95
 
 
96
  idx = 0;
 
97
  real_path = NULL;
 
98
 
 
99
  do
 
100
    {
 
101
      if (idx == 0)
 
102
        name = g_strdup_printf ("%s.png", real_filename);
 
103
      else
 
104
        name = g_strdup_printf ("%s - %d.png", real_filename, idx);
 
105
 
 
106
      real_path = g_build_filename (path, name, NULL);
 
107
      g_free (name);
 
108
 
 
109
      file = g_file_new_for_path (real_path);
 
110
      stream = G_OUTPUT_STREAM (g_file_create (file, G_FILE_CREATE_NONE, NULL, NULL));
 
111
      g_object_unref (file);
 
112
 
 
113
      if (stream != NULL)
 
114
        *filename_used = real_path;
 
115
      else
 
116
        g_free (real_path);
 
117
 
 
118
      idx++;
 
119
    }
 
120
  while (stream == NULL);
 
121
 
 
122
  g_free (real_filename);
 
123
 
 
124
  return stream;
 
125
}
 
126
 
 
127
/* called in an I/O thread */
 
128
static GOutputStream *
 
129
get_stream_for_filename (const gchar *filename,
 
130
                         gchar **filename_used)
 
131
{
 
132
  const gchar *path;
 
133
 
 
134
  path = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES);
 
135
  if (!g_file_test (path, G_FILE_TEST_EXISTS))
 
136
    {
 
137
      path = g_get_home_dir ();
 
138
      if (!g_file_test (path, G_FILE_TEST_EXISTS))
 
139
        return NULL;
 
140
    }
 
141
 
 
142
  return get_stream_for_unique_path (path, filename, filename_used);
 
143
}
 
144
 
 
145
static GOutputStream *
 
146
prepare_write_stream (const gchar *filename,
 
147
                      gchar **filename_used)
 
148
{
 
149
  GOutputStream *stream;
 
150
  GFile *file;
 
151
 
 
152
  if (g_path_is_absolute (filename))
 
153
    {
 
154
      file = g_file_new_for_path (filename);
 
155
      *filename_used = g_strdup (filename);
 
156
      stream = G_OUTPUT_STREAM (g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
 
157
      g_object_unref (file);
 
158
    }
 
159
  else
 
160
    {
 
161
      stream = get_stream_for_filename (filename, filename_used);
 
162
    }
 
163
 
 
164
  return stream;
 
165
}
 
166
 
73
167
static void
74
168
write_screenshot_thread (GSimpleAsyncResult *result,
75
169
                         GObject *object,
76
170
                         GCancellable *cancellable)
77
171
{
78
172
  cairo_status_t status;
 
173
  GOutputStream *stream;
79
174
  _screenshot_data *screenshot_data = g_async_result_get_user_data (G_ASYNC_RESULT (result));
 
175
 
80
176
  g_assert (screenshot_data != NULL);
81
177
 
82
 
  status = cairo_surface_write_to_png (screenshot_data->image, screenshot_data->filename);
 
178
  stream = prepare_write_stream (screenshot_data->filename,
 
179
                                 &screenshot_data->filename_used);
 
180
 
 
181
  if (stream == NULL)
 
182
    status = CAIRO_STATUS_FILE_NOT_FOUND;
 
183
  else
 
184
    {
 
185
      GdkPixbuf *pixbuf;
 
186
 
 
187
      pixbuf = gdk_pixbuf_get_from_surface (screenshot_data->image,
 
188
                                            0, 0,
 
189
                                            cairo_image_surface_get_width (screenshot_data->image),
 
190
                                            cairo_image_surface_get_height (screenshot_data->image));
 
191
 
 
192
      if (gdk_pixbuf_save_to_stream (pixbuf, stream, "png", NULL, NULL,
 
193
                                    "tEXt::Software", "gnome-screenshot", NULL))
 
194
        status = CAIRO_STATUS_SUCCESS;
 
195
      else
 
196
        status = CAIRO_STATUS_WRITE_ERROR;
 
197
 
 
198
      g_object_unref (pixbuf);
 
199
    }
 
200
 
 
201
 
83
202
  g_simple_async_result_set_op_res_gboolean (result, status == CAIRO_STATUS_SUCCESS);
 
203
 
 
204
  g_clear_object (&stream);
84
205
}
85
206
 
86
207
static void
90
211
                    int               width,
91
212
                    int               height)
92
213
{
93
 
  ShellScreenGrabber *grabber;
94
 
  static const cairo_user_data_key_t key;
 
214
  CoglBitmap *bitmap;
 
215
  ClutterBackend *backend;
 
216
  CoglContext *context;
 
217
  int stride;
95
218
  guchar *data;
96
219
 
97
 
  grabber = shell_screen_grabber_new ();
98
 
  data = shell_screen_grabber_grab (grabber, x, y, width, height);
99
 
  g_object_unref (grabber);
100
 
 
101
 
  screenshot_data->image = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_RGB24,
102
 
                                                               width, height, width * 4);
103
 
  cairo_surface_set_user_data (screenshot_data->image, &key,
104
 
                               data, (cairo_destroy_func_t)g_free);
 
220
  backend = clutter_get_default_backend ();
 
221
  context = clutter_backend_get_cogl_context (backend);
 
222
 
 
223
  screenshot_data->image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
 
224
                                                       width, height);
 
225
 
 
226
 
 
227
  data = cairo_image_surface_get_data (screenshot_data->image);
 
228
  stride = cairo_image_surface_get_stride (screenshot_data->image);
 
229
 
 
230
  bitmap = cogl_bitmap_new_for_data (context,
 
231
                                     width,
 
232
                                     height,
 
233
                                     CLUTTER_CAIRO_FORMAT_ARGB32,
 
234
                                     stride,
 
235
                                     data);
 
236
  cogl_framebuffer_read_pixels_into_bitmap (cogl_get_draw_framebuffer (),
 
237
                                            x, y,
 
238
                                            COGL_READ_PIXELS_COLOR_BUFFER,
 
239
                                            bitmap);
 
240
 
 
241
  cairo_surface_mark_dirty (screenshot_data->image);
 
242
  cogl_object_unref (bitmap);
105
243
}
106
244
 
107
245
static void