Merge lp:~woodrow-shen/gnome-screenshot/fix-hidpi.trusty into lp:ubuntu/trusty/gnome-screenshot

Proposed by Woodrow Shen
Status: Merged
Merge reported by: Iain Lane
Merged at revision: not available
Proposed branch: lp:~woodrow-shen/gnome-screenshot/fix-hidpi.trusty
Merge into: lp:ubuntu/trusty/gnome-screenshot
Diff against target: 916 lines (+830/-6)
6 files modified
.pc/applied-patches (+1/-0)
.pc/ubuntu_fix_hidpi.patch/src/screenshot-utils.c (+732/-0)
debian/changelog (+7/-0)
debian/patches/series (+1/-0)
debian/patches/ubuntu_fix_hidpi.patch (+75/-0)
src/screenshot-utils.c (+14/-6)
To merge this branch: bzr merge lp:~woodrow-shen/gnome-screenshot/fix-hidpi.trusty
Reviewer Review Type Date Requested Status
Iain Lane Approve
Sebastien Bacher Needs Fixing
Review via email: mp+248486@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Sebastien Bacher (seb128) wrote :

Hey Woodrow, thanks for your work on that, some comments:

- is that work coming from upstream? if not could we forward them the change, it's not Ubuntu specific and we would benefit to see it reviewed/commited to the official vcs

- could you describe the change and add urls to the bugs in the patch for reference

- the bug should be fixed in vivid before being SRUed

review: Needs Fixing
Revision history for this message
Woodrow Shen (woodrow-shen) wrote :

Hi Sebastien,

This work isn't from upstream, however I file a bug to bugzilla (see https://bugzilla.gnome.org/show_bug.cgi?id=743957).

So do you mean that basically we always would merge the updates into our package from upstream ?

Revision history for this message
Sebastien Bacher (seb128) wrote :

It's better to have the change reviewed and commited upstream if we can, but it's not a blocker. Thanks for sending it to GNOME

25. By Woodrow Shen

* debian/patches/ubuntu_fix_hidpi:
 - add the header for patch

26. By Woodrow Shen

* debian/patches/ubuntu_fix_hidpi:
 - fix the header for patch

Revision history for this message
Woodrow Shen (woodrow-shen) wrote :

Got it, so let the upstream review this patch, thanks your help.

Revision history for this message
Iain Lane (laney) wrote :

Upstream seems to be mostly inactive, uploaded to Ubuntu now. Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.pc/applied-patches'
2--- .pc/applied-patches 2013-12-19 11:25:38 +0000
3+++ .pc/applied-patches 2015-02-04 10:34:12 +0000
4@@ -3,3 +3,4 @@
5 ubuntu_unity_no_gnomeshell.patch
6 update_unity_list.patch
7 uri.patch
8+ubuntu_fix_hidpi.patch
9
10=== added directory '.pc/ubuntu_fix_hidpi.patch'
11=== added directory '.pc/ubuntu_fix_hidpi.patch/src'
12=== added file '.pc/ubuntu_fix_hidpi.patch/src/screenshot-utils.c'
13--- .pc/ubuntu_fix_hidpi.patch/src/screenshot-utils.c 1970-01-01 00:00:00 +0000
14+++ .pc/ubuntu_fix_hidpi.patch/src/screenshot-utils.c 2015-02-04 10:34:12 +0000
15@@ -0,0 +1,732 @@
16+/* screenshot-utils.c - common functions for GNOME Screenshot
17+ *
18+ * Copyright (C) 2001-2006 Jonathan Blandford <jrb@alum.mit.edu>
19+ * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
20+ *
21+ * This program is free software; you can redistribute it and/or
22+ * modify it under the terms of the GNU General Public
23+ * License as published by the Free Software Foundation; either
24+ * version 2 of the License, or (at your option) any later version.
25+ *
26+ * This program is distributed in the hope that it will be useful,
27+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29+ * General Public License for more details.
30+ *
31+ * You should have received a copy of the GNU General Public
32+ * License along with this program; if not, write to the
33+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
34+ */
35+
36+#include <config.h>
37+#include <gdk/gdkkeysyms.h>
38+#include <gtk/gtk.h>
39+#include <glib.h>
40+#include <glib/gi18n.h>
41+#include <glib/gstdio.h>
42+#include <canberra-gtk.h>
43+#include <stdlib.h>
44+
45+#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
46+#include <X11/extensions/shape.h>
47+#endif
48+
49+#include "cheese-flash.h"
50+#include "screenshot-application.h"
51+#include "screenshot-config.h"
52+#include "screenshot-utils.h"
53+
54+static GdkWindow *
55+screenshot_find_active_window (void)
56+{
57+ GdkWindow *window;
58+ GdkScreen *default_screen;
59+
60+ default_screen = gdk_screen_get_default ();
61+ window = gdk_screen_get_active_window (default_screen);
62+
63+ return window;
64+}
65+
66+static gboolean
67+screenshot_window_is_desktop (GdkWindow *window)
68+{
69+ GdkWindow *root_window = gdk_get_default_root_window ();
70+ GdkWindowTypeHint window_type_hint;
71+
72+ if (window == root_window)
73+ return TRUE;
74+
75+ window_type_hint = gdk_window_get_type_hint (window);
76+ if (window_type_hint == GDK_WINDOW_TYPE_HINT_DESKTOP)
77+ return TRUE;
78+
79+ return FALSE;
80+
81+}
82+
83+static Window
84+find_wm_window (GdkWindow *window)
85+{
86+ Window xid, root, parent, *children;
87+ unsigned int nchildren;
88+
89+ if (window == gdk_get_default_root_window ())
90+ return None;
91+
92+ xid = GDK_WINDOW_XID (window);
93+
94+ do
95+ {
96+ if (XQueryTree (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
97+ xid, &root, &parent, &children, &nchildren) == 0)
98+ {
99+ g_warning ("Couldn't find window manager window");
100+ return None;
101+ }
102+
103+ if (root == parent)
104+ return xid;
105+
106+ xid = parent;
107+ }
108+ while (TRUE);
109+}
110+
111+static cairo_region_t *
112+make_region_with_monitors (GdkScreen *screen)
113+{
114+ cairo_region_t *region;
115+ int num_monitors;
116+ int i;
117+
118+ num_monitors = gdk_screen_get_n_monitors (screen);
119+
120+ region = cairo_region_create ();
121+
122+ for (i = 0; i < num_monitors; i++)
123+ {
124+ GdkRectangle rect;
125+
126+ gdk_screen_get_monitor_geometry (screen, i, &rect);
127+ cairo_region_union_rectangle (region, &rect);
128+ }
129+
130+ return region;
131+}
132+
133+static void
134+blank_rectangle_in_pixbuf (GdkPixbuf *pixbuf, GdkRectangle *rect)
135+{
136+ int x, y;
137+ int x2, y2;
138+ guchar *pixels;
139+ int rowstride;
140+ int n_channels;
141+ guchar *row;
142+ gboolean has_alpha;
143+
144+ g_assert (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
145+
146+ x2 = rect->x + rect->width;
147+ y2 = rect->y + rect->height;
148+
149+ pixels = gdk_pixbuf_get_pixels (pixbuf);
150+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
151+ has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
152+ n_channels = gdk_pixbuf_get_n_channels (pixbuf);
153+
154+ for (y = rect->y; y < y2; y++)
155+ {
156+ guchar *p;
157+
158+ row = pixels + y * rowstride;
159+ p = row + rect->x * n_channels;
160+
161+ for (x = rect->x; x < x2; x++)
162+ {
163+ *p++ = 0;
164+ *p++ = 0;
165+ *p++ = 0;
166+
167+ if (has_alpha)
168+ *p++ = 255; /* opaque black */
169+ }
170+ }
171+}
172+
173+static void
174+blank_region_in_pixbuf (GdkPixbuf *pixbuf, cairo_region_t *region)
175+{
176+ int n_rects;
177+ int i;
178+ int width, height;
179+ cairo_rectangle_int_t pixbuf_rect;
180+
181+ n_rects = cairo_region_num_rectangles (region);
182+
183+ width = gdk_pixbuf_get_width (pixbuf);
184+ height = gdk_pixbuf_get_height (pixbuf);
185+
186+ pixbuf_rect.x = 0;
187+ pixbuf_rect.y = 0;
188+ pixbuf_rect.width = width;
189+ pixbuf_rect.height = height;
190+
191+ for (i = 0; i < n_rects; i++)
192+ {
193+ cairo_rectangle_int_t rect, dest;
194+
195+ cairo_region_get_rectangle (region, i, &rect);
196+ if (gdk_rectangle_intersect (&rect, &pixbuf_rect, &dest))
197+ blank_rectangle_in_pixbuf (pixbuf, &dest);
198+ }
199+}
200+
201+/* When there are multiple monitors with different resolutions, the visible area
202+ * within the root window may not be rectangular (it may have an L-shape, for
203+ * example). In that case, mask out the areas of the root window which would
204+ * not be visible in the monitors, so that screenshot do not end up with content
205+ * that the user won't ever see.
206+ */
207+static void
208+mask_monitors (GdkPixbuf *pixbuf, GdkWindow *root_window)
209+{
210+ GdkScreen *screen;
211+ cairo_region_t *region_with_monitors;
212+ cairo_region_t *invisible_region;
213+ cairo_rectangle_int_t rect;
214+
215+ screen = gdk_window_get_screen (root_window);
216+
217+ region_with_monitors = make_region_with_monitors (screen);
218+
219+ rect.x = 0;
220+ rect.y = 0;
221+ rect.width = gdk_screen_get_width (screen);
222+ rect.height = gdk_screen_get_height (screen);
223+
224+ invisible_region = cairo_region_create_rectangle (&rect);
225+ cairo_region_subtract (invisible_region, region_with_monitors);
226+
227+ blank_region_in_pixbuf (pixbuf, invisible_region);
228+
229+ cairo_region_destroy (region_with_monitors);
230+ cairo_region_destroy (invisible_region);
231+}
232+
233+static void
234+screenshot_fallback_get_window_rect_coords (GdkWindow *window,
235+ gboolean include_border,
236+ GdkRectangle *real_coordinates_out,
237+ GdkRectangle *screenshot_coordinates_out)
238+{
239+ gint x_orig, y_orig;
240+ gint width, height;
241+ GdkRectangle real_coordinates;
242+
243+ if (include_border)
244+ {
245+ gdk_window_get_frame_extents (window, &real_coordinates);
246+ }
247+ else
248+ {
249+ real_coordinates.width = gdk_window_get_width (window);
250+ real_coordinates.height = gdk_window_get_height (window);
251+
252+ gdk_window_get_origin (window, &real_coordinates.x, &real_coordinates.y);
253+ }
254+
255+ x_orig = real_coordinates.x;
256+ y_orig = real_coordinates.y;
257+ width = real_coordinates.width;
258+ height = real_coordinates.height;
259+
260+ if (real_coordinates_out != NULL)
261+ *real_coordinates_out = real_coordinates;
262+
263+ if (x_orig < 0)
264+ {
265+ width = width + x_orig;
266+ x_orig = 0;
267+ }
268+
269+ if (y_orig < 0)
270+ {
271+ height = height + y_orig;
272+ y_orig = 0;
273+ }
274+
275+ if (x_orig + width > gdk_screen_width ())
276+ width = gdk_screen_width () - x_orig;
277+
278+ if (y_orig + height > gdk_screen_height ())
279+ height = gdk_screen_height () - y_orig;
280+
281+ if (screenshot_coordinates_out != NULL)
282+ {
283+ screenshot_coordinates_out->x = x_orig;
284+ screenshot_coordinates_out->y = y_orig;
285+ screenshot_coordinates_out->width = width;
286+ screenshot_coordinates_out->height = height;
287+ }
288+}
289+
290+void
291+screenshot_play_sound_effect (const gchar *event_id,
292+ const gchar *event_desc)
293+{
294+ ca_context *c;
295+ ca_proplist *p = NULL;
296+ int res;
297+
298+ c = ca_gtk_context_get ();
299+
300+ res = ca_proplist_create (&p);
301+ if (res < 0)
302+ goto done;
303+
304+ res = ca_proplist_sets (p, CA_PROP_EVENT_ID, event_id);
305+ if (res < 0)
306+ goto done;
307+
308+ res = ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, event_desc);
309+ if (res < 0)
310+ goto done;
311+
312+ res = ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
313+ if (res < 0)
314+ goto done;
315+
316+ ca_context_play_full (c, 0, p, NULL, NULL);
317+
318+ done:
319+ if (p != NULL)
320+ ca_proplist_destroy (p);
321+
322+}
323+
324+static void
325+screenshot_fallback_fire_flash (GdkWindow *window,
326+ GdkRectangle *rectangle)
327+{
328+ GdkRectangle rect;
329+ CheeseFlash *flash = NULL;
330+
331+ if (rectangle != NULL)
332+ rect = *rectangle;
333+ else
334+ screenshot_fallback_get_window_rect_coords (window,
335+ screenshot_config->include_border,
336+ NULL,
337+ &rect);
338+
339+ flash = cheese_flash_new ();
340+ cheese_flash_fire (flash, &rect);
341+
342+ g_object_unref (flash);
343+}
344+
345+GdkWindow *
346+do_find_current_window (void)
347+{
348+ GdkWindow *current_window;
349+ GdkDeviceManager *manager;
350+ GdkDevice *device;
351+
352+ current_window = screenshot_find_active_window ();
353+ manager = gdk_display_get_device_manager (gdk_display_get_default ());
354+ device = gdk_device_manager_get_client_pointer (manager);
355+
356+ /* If there's no active window, we fall back to returning the
357+ * window that the cursor is in.
358+ */
359+ if (!current_window)
360+ current_window = gdk_device_get_window_at_position (device, NULL, NULL);
361+
362+ if (current_window)
363+ {
364+ if (screenshot_window_is_desktop (current_window))
365+ /* if the current window is the desktop (e.g. nautilus), we
366+ * return NULL, as getting the whole screen makes more sense.
367+ */
368+ return NULL;
369+
370+ /* Once we have a window, we take the toplevel ancestor. */
371+ current_window = gdk_window_get_toplevel (current_window);
372+ }
373+
374+ return current_window;
375+}
376+
377+static GdkWindow *
378+screenshot_fallback_find_current_window (void)
379+{
380+ GdkWindow *window = NULL;
381+
382+ if (screenshot_config->take_window_shot)
383+ {
384+ window = do_find_current_window ();
385+
386+ if (window == NULL)
387+ screenshot_config->take_window_shot = FALSE;
388+ }
389+
390+ if (window == NULL)
391+ window = gdk_get_default_root_window ();
392+
393+ return window;
394+}
395+
396+static GdkPixbuf *
397+screenshot_fallback_get_pixbuf (GdkRectangle *rectangle)
398+{
399+ GdkWindow *root, *wm_window = NULL;
400+ GdkPixbuf *screenshot;
401+ GdkRectangle real_coords, screenshot_coords;
402+ Window wm;
403+ GtkBorder frame_offset = { 0, 0, 0, 0 };
404+ GdkWindow *window;
405+
406+ window = screenshot_fallback_find_current_window ();
407+
408+ screenshot_fallback_get_window_rect_coords (window,
409+ screenshot_config->include_border,
410+ &real_coords,
411+ &screenshot_coords);
412+
413+ wm = find_wm_window (window);
414+ if (wm != None)
415+ {
416+ GdkRectangle wm_real_coords;
417+
418+ wm_window = gdk_x11_window_foreign_new_for_display
419+ (gdk_window_get_display (window), wm);
420+
421+ screenshot_fallback_get_window_rect_coords (wm_window,
422+ FALSE,
423+ &wm_real_coords,
424+ NULL);
425+
426+ frame_offset.left = (gdouble) (real_coords.x - wm_real_coords.x);
427+ frame_offset.top = (gdouble) (real_coords.y - wm_real_coords.y);
428+ frame_offset.right = (gdouble) (wm_real_coords.width - real_coords.width - frame_offset.left);
429+ frame_offset.bottom = (gdouble) (wm_real_coords.height - real_coords.height - frame_offset.top);
430+ }
431+
432+ if (rectangle)
433+ {
434+ screenshot_coords.x = rectangle->x - screenshot_coords.x;
435+ screenshot_coords.y = rectangle->y - screenshot_coords.y;
436+ screenshot_coords.width = rectangle->width;
437+ screenshot_coords.height = rectangle->height;
438+ }
439+
440+ root = gdk_get_default_root_window ();
441+ screenshot = gdk_pixbuf_get_from_window (root,
442+ screenshot_coords.x, screenshot_coords.y,
443+ screenshot_coords.width, screenshot_coords.height);
444+
445+ if (!screenshot_config->take_window_shot &&
446+ !screenshot_config->take_area_shot)
447+ mask_monitors (screenshot, root);
448+
449+#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
450+ if (screenshot_config->include_border && (wm != None))
451+ {
452+ XRectangle *rectangles;
453+ GdkPixbuf *tmp;
454+ int rectangle_count, rectangle_order, i;
455+
456+ /* we must use XShape to avoid showing what's under the rounder corners
457+ * of the WM decoration.
458+ */
459+ rectangles = XShapeGetRectangles (GDK_DISPLAY_XDISPLAY (gdk_display_get_default()),
460+ wm,
461+ ShapeBounding,
462+ &rectangle_count,
463+ &rectangle_order);
464+ if (rectangles && rectangle_count > 0)
465+ {
466+ gboolean has_alpha = gdk_pixbuf_get_has_alpha (screenshot);
467+
468+ tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
469+ screenshot_coords.width, screenshot_coords.height);
470+ gdk_pixbuf_fill (tmp, 0);
471+
472+ for (i = 0; i < rectangle_count; i++)
473+ {
474+ gint rec_x, rec_y;
475+ gint rec_width, rec_height;
476+ gint y;
477+
478+ /* If we're using invisible borders, the ShapeBounding might not
479+ * have the same size as the frame extents, as it would include the
480+ * areas for the invisible borders themselves.
481+ * In that case, trim every rectangle we get by the offset between the
482+ * WM window size and the frame extents.
483+ */
484+ rec_x = rectangles[i].x;
485+ rec_y = rectangles[i].y;
486+ rec_width = rectangles[i].width - (frame_offset.left + frame_offset.right);
487+ rec_height = rectangles[i].height - (frame_offset.top + frame_offset.bottom);
488+
489+ if (real_coords.x < 0)
490+ {
491+ rec_x += real_coords.x;
492+ rec_x = MAX(rec_x, 0);
493+ rec_width += real_coords.x;
494+ }
495+
496+ if (real_coords.y < 0)
497+ {
498+ rec_y += real_coords.y;
499+ rec_y = MAX(rec_y, 0);
500+ rec_height += real_coords.y;
501+ }
502+
503+ if (screenshot_coords.x + rec_x + rec_width > gdk_screen_width ())
504+ rec_width = gdk_screen_width () - screenshot_coords.x - rec_x;
505+
506+ if (screenshot_coords.y + rec_y + rec_height > gdk_screen_height ())
507+ rec_height = gdk_screen_height () - screenshot_coords.y - rec_y;
508+
509+ for (y = rec_y; y < rec_y + rec_height; y++)
510+ {
511+ guchar *src_pixels, *dest_pixels;
512+ gint x;
513+
514+ src_pixels = gdk_pixbuf_get_pixels (screenshot)
515+ + y * gdk_pixbuf_get_rowstride(screenshot)
516+ + rec_x * (has_alpha ? 4 : 3);
517+ dest_pixels = gdk_pixbuf_get_pixels (tmp)
518+ + y * gdk_pixbuf_get_rowstride (tmp)
519+ + rec_x * 4;
520+
521+ for (x = 0; x < rec_width; x++)
522+ {
523+ *dest_pixels++ = *src_pixels++;
524+ *dest_pixels++ = *src_pixels++;
525+ *dest_pixels++ = *src_pixels++;
526+
527+ if (has_alpha)
528+ *dest_pixels++ = *src_pixels++;
529+ else
530+ *dest_pixels++ = 255;
531+ }
532+ }
533+ }
534+
535+ g_object_unref (screenshot);
536+ screenshot = tmp;
537+
538+ XFree (rectangles);
539+ }
540+ }
541+#endif /* HAVE_X11_EXTENSIONS_SHAPE_H */
542+
543+ /* if we have a selected area, there were by definition no cursor in the
544+ * screenshot */
545+ if (screenshot_config->include_pointer && !rectangle)
546+ {
547+ GdkCursor *cursor;
548+ GdkPixbuf *cursor_pixbuf;
549+
550+ cursor = gdk_cursor_new_for_display (gdk_display_get_default (), GDK_LEFT_PTR);
551+ cursor_pixbuf = gdk_cursor_get_image (cursor);
552+
553+ if (cursor_pixbuf != NULL)
554+ {
555+ GdkDeviceManager *manager;
556+ GdkDevice *device;
557+ GdkRectangle rect;
558+ gint cx, cy, xhot, yhot;
559+
560+ manager = gdk_display_get_device_manager (gdk_display_get_default ());
561+ device = gdk_device_manager_get_client_pointer (manager);
562+
563+ if (wm_window != NULL)
564+ gdk_window_get_device_position (wm_window, device,
565+ &cx, &cy, NULL);
566+ else
567+ gdk_window_get_device_position (window, device,
568+ &cx, &cy, NULL);
569+
570+ sscanf (gdk_pixbuf_get_option (cursor_pixbuf, "x_hot"), "%d", &xhot);
571+ sscanf (gdk_pixbuf_get_option (cursor_pixbuf, "y_hot"), "%d", &yhot);
572+
573+ /* in rect we have the cursor window coordinates */
574+ rect.x = cx + real_coords.x;
575+ rect.y = cy + real_coords.y;
576+ rect.width = gdk_pixbuf_get_width (cursor_pixbuf);
577+ rect.height = gdk_pixbuf_get_height (cursor_pixbuf);
578+
579+ /* see if the pointer is inside the window */
580+ if (gdk_rectangle_intersect (&real_coords, &rect, &rect))
581+ {
582+ gint cursor_x, cursor_y;
583+
584+ cursor_x = cx - xhot - frame_offset.left;
585+ cursor_y = cy - yhot - frame_offset.top;
586+ gdk_pixbuf_composite (cursor_pixbuf, screenshot,
587+ cursor_x, cursor_y,
588+ rect.width, rect.height,
589+ cursor_x, cursor_y,
590+ 1.0, 1.0,
591+ GDK_INTERP_BILINEAR,
592+ 255);
593+ }
594+
595+ g_object_unref (cursor_pixbuf);
596+ g_object_unref (cursor);
597+ }
598+ }
599+
600+ screenshot_fallback_fire_flash (window, rectangle);
601+
602+ return screenshot;
603+}
604+
605+GdkPixbuf *
606+screenshot_get_pixbuf (GdkRectangle *rectangle)
607+{
608+ GdkPixbuf *screenshot = NULL;
609+ gchar *path, *filename, *tmpname;
610+ const gchar *method_name;
611+ GVariant *method_params;
612+ GError *error = NULL;
613+ GDBusConnection *connection;
614+
615+ path = g_build_filename (g_get_user_cache_dir (), "gnome-screenshot", NULL);
616+ g_mkdir_with_parents (path, 0700);
617+
618+ tmpname = g_strdup_printf ("scr-%d.png", g_random_int ());
619+ filename = g_build_filename (path, tmpname, NULL);
620+
621+ if (screenshot_config->take_window_shot)
622+ {
623+ method_name = "ScreenshotWindow";
624+ method_params = g_variant_new ("(bbbs)",
625+ screenshot_config->include_border,
626+ screenshot_config->include_pointer,
627+ TRUE, /* flash */
628+ filename);
629+ }
630+ else if (rectangle != NULL)
631+ {
632+ method_name = "ScreenshotArea";
633+ method_params = g_variant_new ("(iiiibs)",
634+ rectangle->x, rectangle->y,
635+ rectangle->width, rectangle->height,
636+ TRUE, /* flash */
637+ filename);
638+ }
639+ else
640+ {
641+ method_name = "Screenshot";
642+ method_params = g_variant_new ("(bbs)",
643+ screenshot_config->include_pointer,
644+ TRUE, /* flash */
645+ filename);
646+ }
647+
648+ if (!g_strcmp0 (g_getenv ("XDG_CURRENT_DESKTOP"), "Unity"))
649+ screenshot = screenshot_fallback_get_pixbuf(rectangle);
650+ else {
651+ connection = g_application_get_dbus_connection (g_application_get_default ());
652+ g_dbus_connection_call_sync (connection,
653+ "org.gnome.Shell.Screenshot",
654+ "/org/gnome/Shell/Screenshot",
655+ "org.gnome.Shell.Screenshot",
656+ method_name,
657+ method_params,
658+ NULL,
659+ G_DBUS_CALL_FLAGS_NONE,
660+ -1,
661+ NULL,
662+ &error);
663+
664+ if (error == NULL)
665+ {
666+ screenshot = gdk_pixbuf_new_from_file (filename, &error);
667+
668+ /* remove the temporary file created by the shell */
669+ g_unlink (filename);
670+ }
671+
672+ if (error != NULL)
673+ {
674+ g_message ("Unable to use GNOME Shell's builtin screenshot interface, "
675+ "resorting to fallback X11.");
676+ g_error_free (error);
677+
678+ screenshot = screenshot_fallback_get_pixbuf (rectangle);
679+ }
680+ }
681+
682+ g_free (path);
683+ g_free (tmpname);
684+ g_free (filename);
685+
686+ return screenshot;
687+}
688+
689+gint
690+screenshot_show_dialog (GtkWindow *parent,
691+ GtkMessageType message_type,
692+ GtkButtonsType buttons_type,
693+ const gchar *message,
694+ const gchar *detail)
695+{
696+ GtkWidget *dialog;
697+ GtkWindowGroup *group;
698+ gint response;
699+
700+ g_return_val_if_fail ((parent == NULL) || (GTK_IS_WINDOW (parent)),
701+ GTK_RESPONSE_NONE);
702+ g_return_val_if_fail (message != NULL, GTK_RESPONSE_NONE);
703+
704+ dialog = gtk_message_dialog_new (parent,
705+ GTK_DIALOG_DESTROY_WITH_PARENT,
706+ message_type,
707+ buttons_type,
708+ "%s", message);
709+ gtk_window_set_title (GTK_WINDOW (dialog), "");
710+
711+ if (detail)
712+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
713+ "%s", detail);
714+
715+ if (parent)
716+ {
717+ group = gtk_window_get_group (parent);
718+ if (group != NULL)
719+ gtk_window_group_add_window (group, GTK_WINDOW (dialog));
720+ }
721+
722+ response = gtk_dialog_run (GTK_DIALOG (dialog));
723+
724+ gtk_widget_destroy (dialog);
725+
726+ return response;
727+}
728+
729+void
730+screenshot_display_help (GtkWindow *parent)
731+{
732+ GError *error = NULL;
733+
734+ gtk_show_uri (gtk_window_get_screen (parent),
735+ "help:ubuntu-help/screen-shot-record",
736+ gtk_get_current_event_time (), &error);
737+
738+ if (error)
739+ {
740+ screenshot_show_dialog (parent,
741+ GTK_MESSAGE_ERROR,
742+ GTK_BUTTONS_OK,
743+ _("Error loading the help page"),
744+ error->message);
745+ g_error_free (error);
746+ }
747+}
748
749=== modified file 'debian/changelog'
750--- debian/changelog 2014-01-16 11:16:23 +0000
751+++ debian/changelog 2015-02-04 10:34:12 +0000
752@@ -1,3 +1,10 @@
753+gnome-screenshot (3.10.1-0ubuntu2) trusty; urgency=medium
754+
755+ * debian/patches/ubuntu_fix_hidpi:
756+ - support hidpi scale factor when rendering preview.
757+
758+ -- Woodrow Shen (Shye-Tzeng Shen) <woodrow.shen@canonical.com> Wed, 04 Feb 2015 15:03:32 +0800
759+
760 gnome-screenshot (3.10.1-0ubuntu1) trusty; urgency=medium
761
762 * New upstream version
763
764=== modified file 'debian/patches/series'
765--- debian/patches/series 2013-03-15 17:08:12 +0000
766+++ debian/patches/series 2015-02-04 10:34:12 +0000
767@@ -3,3 +3,4 @@
768 ubuntu_unity_no_gnomeshell.patch
769 update_unity_list.patch
770 uri.patch
771+ubuntu_fix_hidpi.patch
772
773=== added file 'debian/patches/ubuntu_fix_hidpi.patch'
774--- debian/patches/ubuntu_fix_hidpi.patch 1970-01-01 00:00:00 +0000
775+++ debian/patches/ubuntu_fix_hidpi.patch 2015-02-04 10:34:12 +0000
776@@ -0,0 +1,75 @@
777+Description:
778+ For Hi-DPI display case, such as the resolution 3840x2160, the scale factor is 2
779+ and gnome-screenshot generates screenshot image wihtout considering the scale factor.
780+ So this patch will use this factor to correct the screenshot for Hi-DPI case.
781+
782+Origin: upstream
783+Bug: https://bugzilla.gnome.org/show_bug.cgi?id=743957
784+Last-Update: 2015-02-04
785+---
786+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
787+Index: b/src/screenshot-utils.c
788+===================================================================
789+--- a/src/screenshot-utils.c 2015-02-04 14:57:06.590766000 +0800
790++++ b/src/screenshot-utils.c 2015-02-04 15:53:09.856279594 +0800
791+@@ -383,10 +383,12 @@
792+ {
793+ GdkWindow *root, *wm_window = NULL;
794+ GdkPixbuf *screenshot;
795++ GdkPixbuf *screenshot_scale;
796+ GdkRectangle real_coords, screenshot_coords;
797+ Window wm;
798+ GtkBorder frame_offset = { 0, 0, 0, 0 };
799+ GdkWindow *window;
800++ gint scale_factor;
801+
802+ window = screenshot_fallback_find_current_window ();
803+
804+@@ -427,9 +429,15 @@
805+ screenshot_coords.x, screenshot_coords.y,
806+ screenshot_coords.width, screenshot_coords.height);
807+
808++ scale_factor = gdk_window_get_scale_factor (root);
809++ screenshot_scale = gdk_pixbuf_scale_simple(screenshot,
810++ screenshot_coords.width * scale_factor,
811++ screenshot_coords.height * scale_factor,
812++ GDK_INTERP_BILINEAR);
813++
814+ if (!screenshot_config->take_window_shot &&
815+ !screenshot_config->take_area_shot)
816+- mask_monitors (screenshot, root);
817++ mask_monitors (screenshot_scale, root);
818+
819+ #ifdef HAVE_X11_EXTENSIONS_SHAPE_H
820+ if (screenshot_config->include_border && (wm != None))
821+@@ -448,7 +456,7 @@
822+ &rectangle_order);
823+ if (rectangles && rectangle_count > 0)
824+ {
825+- gboolean has_alpha = gdk_pixbuf_get_has_alpha (screenshot);
826++ gboolean has_alpha = gdk_pixbuf_get_has_alpha (screenshot_scale);
827+
828+ tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
829+ screenshot_coords.width, screenshot_coords.height);
830+@@ -496,8 +504,8 @@
831+ guchar *src_pixels, *dest_pixels;
832+ gint x;
833+
834+- src_pixels = gdk_pixbuf_get_pixels (screenshot)
835+- + y * gdk_pixbuf_get_rowstride(screenshot)
836++ src_pixels = gdk_pixbuf_get_pixels (screenshot_scale)
837++ + y * gdk_pixbuf_get_rowstride(screenshot_scale)
838+ + rec_x * (has_alpha ? 4 : 3);
839+ dest_pixels = gdk_pixbuf_get_pixels (tmp)
840+ + y * gdk_pixbuf_get_rowstride (tmp)
841+@@ -517,8 +525,8 @@
842+ }
843+ }
844+
845+- g_object_unref (screenshot);
846+- screenshot = tmp;
847++ g_object_unref (screenshot_scale);
848++ screenshot_scale = tmp;
849+
850+ XFree (rectangles);
851+ }
852
853=== modified file 'src/screenshot-utils.c'
854--- src/screenshot-utils.c 2013-05-15 12:01:25 +0000
855+++ src/screenshot-utils.c 2015-02-04 10:34:12 +0000
856@@ -383,10 +383,12 @@
857 {
858 GdkWindow *root, *wm_window = NULL;
859 GdkPixbuf *screenshot;
860+ GdkPixbuf *screenshot_scale;
861 GdkRectangle real_coords, screenshot_coords;
862 Window wm;
863 GtkBorder frame_offset = { 0, 0, 0, 0 };
864 GdkWindow *window;
865+ gint scale_factor;
866
867 window = screenshot_fallback_find_current_window ();
868
869@@ -427,9 +429,15 @@
870 screenshot_coords.x, screenshot_coords.y,
871 screenshot_coords.width, screenshot_coords.height);
872
873+ scale_factor = gdk_window_get_scale_factor (root);
874+ screenshot_scale = gdk_pixbuf_scale_simple(screenshot,
875+ screenshot_coords.width * scale_factor,
876+ screenshot_coords.height * scale_factor,
877+ GDK_INTERP_BILINEAR);
878+
879 if (!screenshot_config->take_window_shot &&
880 !screenshot_config->take_area_shot)
881- mask_monitors (screenshot, root);
882+ mask_monitors (screenshot_scale, root);
883
884 #ifdef HAVE_X11_EXTENSIONS_SHAPE_H
885 if (screenshot_config->include_border && (wm != None))
886@@ -448,7 +456,7 @@
887 &rectangle_order);
888 if (rectangles && rectangle_count > 0)
889 {
890- gboolean has_alpha = gdk_pixbuf_get_has_alpha (screenshot);
891+ gboolean has_alpha = gdk_pixbuf_get_has_alpha (screenshot_scale);
892
893 tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
894 screenshot_coords.width, screenshot_coords.height);
895@@ -496,8 +504,8 @@
896 guchar *src_pixels, *dest_pixels;
897 gint x;
898
899- src_pixels = gdk_pixbuf_get_pixels (screenshot)
900- + y * gdk_pixbuf_get_rowstride(screenshot)
901+ src_pixels = gdk_pixbuf_get_pixels (screenshot_scale)
902+ + y * gdk_pixbuf_get_rowstride(screenshot_scale)
903 + rec_x * (has_alpha ? 4 : 3);
904 dest_pixels = gdk_pixbuf_get_pixels (tmp)
905 + y * gdk_pixbuf_get_rowstride (tmp)
906@@ -517,8 +525,8 @@
907 }
908 }
909
910- g_object_unref (screenshot);
911- screenshot = tmp;
912+ g_object_unref (screenshot_scale);
913+ screenshot_scale = tmp;
914
915 XFree (rectangles);
916 }

Subscribers

People subscribed via source and target branches

to all changes: