Merge lp:~woodrow-shen/gnome-screenshot/fix-hidpi.trusty into lp:ubuntu/trusty/gnome-screenshot
- fix-hidpi.trusty
- Merge into trusty
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Iain Lane | Approve | ||
Sebastien Bacher | Needs Fixing | ||
Review via email: mp+248486@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
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:/
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 | } |
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