Skip to content

Commit 4af7ab3

Browse files
committed
cinnamon-screenshot.c: Disable unredirection when taking a
screenshot. We rely entirely on the composited stage for capturing, but fullscreen windows may not be composited ('unredirected'), so temporarily disable this, take the shot, then re-enable. Fixes #11127
1 parent 3779122 commit 4af7ab3

File tree

1 file changed

+92
-55
lines changed

1 file changed

+92
-55
lines changed

src/cinnamon-screenshot.c

Lines changed: 92 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,15 @@ struct _CinnamonScreenshot
2828
/* Used for async screenshot grabbing */
2929
typedef struct _screenshot_data {
3030
CinnamonScreenshot *screenshot;
31+
MetaWindow *window;
3132

3233
char *filename;
3334

3435
cairo_surface_t *image;
3536
cairo_rectangle_int_t screenshot_area;
3637

3738
gboolean include_cursor;
39+
gboolean include_frame;
3840

3941
CinnamonScreenshotCallback callback;
4042
} _screenshot_data;
@@ -205,15 +207,16 @@ grab_screenshot (ClutterActor *stage,
205207
ClutterPaintContext *paint_context,
206208
_screenshot_data *screenshot_data)
207209
{
208-
CinnamonScreen *screen = cinnamon_global_get_screen (screenshot_data->screenshot->global);
209-
int width, height;
210+
MetaDisplay *display = cinnamon_global_get_display (screenshot_data->screenshot->global);
211+
int width, height, n_monitors;
210212
GSimpleAsyncResult *result;
211213

212-
cinnamon_screen_get_size (screen, &width, &height);
214+
meta_display_get_size (display, &width, &height);
213215

214216
do_grab_screenshot (screenshot_data, paint_context, 0, 0, width, height);
215217

216-
if (cinnamon_screen_get_n_monitors (screen) > 1)
218+
n_monitors = meta_display_get_n_monitors (display);
219+
if (n_monitors > 1)
217220
{
218221
cairo_region_t *screen_region = cairo_region_create ();
219222
cairo_region_t *stage_region;
@@ -222,9 +225,9 @@ grab_screenshot (ClutterActor *stage,
222225
int i;
223226
cairo_t *cr;
224227

225-
for (i = cinnamon_screen_get_n_monitors (screen) - 1; i >= 0; i--)
228+
for (i = n_monitors - 1; i >= 0; i--)
226229
{
227-
cinnamon_screen_get_monitor_geometry (screen, i, &monitor_rect);
230+
meta_display_get_monitor_geometry (display, i, &monitor_rect);
228231
cairo_region_union_rectangle (screen_region, (const cairo_rectangle_int_t *) &monitor_rect);
229232
}
230233

@@ -261,6 +264,8 @@ grab_screenshot (ClutterActor *stage,
261264

262265
g_signal_handlers_disconnect_by_func (stage, (void *)grab_screenshot, (gpointer)screenshot_data);
263266

267+
meta_enable_unredirect_for_display (display);
268+
264269
result = g_simple_async_result_new (NULL, on_screenshot_written, (gpointer)screenshot_data, grab_screenshot);
265270
g_simple_async_result_run_in_thread (result, write_screenshot_thread, G_PRIORITY_DEFAULT, NULL);
266271
g_object_unref (result);
@@ -271,6 +276,7 @@ grab_area_screenshot (ClutterActor *stage,
271276
ClutterPaintContext *paint_context,
272277
_screenshot_data *screenshot_data)
273278
{
279+
MetaDisplay *display = cinnamon_global_get_display (screenshot_data->screenshot->global);
274280
GSimpleAsyncResult *result;
275281

276282
do_grab_screenshot (screenshot_data,
@@ -284,11 +290,71 @@ grab_area_screenshot (ClutterActor *stage,
284290
_draw_cursor_image (screenshot_data->image, screenshot_data->screenshot_area);
285291

286292
g_signal_handlers_disconnect_by_func (stage, (void *)grab_area_screenshot, (gpointer)screenshot_data);
293+
294+
meta_enable_unredirect_for_display (display);
295+
287296
result = g_simple_async_result_new (NULL, on_screenshot_written, (gpointer)screenshot_data, grab_area_screenshot);
288297
g_simple_async_result_run_in_thread (result, write_screenshot_thread, G_PRIORITY_DEFAULT, NULL);
289298
g_object_unref (result);
290299
}
291300

301+
static void
302+
grab_window_screenshot (ClutterActor *stage,
303+
ClutterPaintContext *paint_context,
304+
_screenshot_data *screenshot_data)
305+
{
306+
MetaDisplay *display = cinnamon_global_get_display (screenshot_data->screenshot->global);
307+
GSimpleAsyncResult *result;
308+
ClutterActor *window_actor;
309+
gfloat actor_x, actor_y;
310+
MetaShapedTexture *stex;
311+
MetaRectangle rect;
312+
cairo_rectangle_int_t clip;
313+
314+
g_return_if_fail (META_IS_WINDOW (screenshot_data->window));
315+
316+
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (screenshot_data->window));
317+
clutter_actor_get_position (window_actor, &actor_x, &actor_y);
318+
319+
if (screenshot_data->include_frame || !meta_window_get_frame (screenshot_data->window))
320+
{
321+
meta_window_get_frame_rect (screenshot_data->window, &rect);
322+
323+
screenshot_data->screenshot_area.x = rect.x;
324+
screenshot_data->screenshot_area.y = rect.y;
325+
326+
clip.x = rect.x - (gint) actor_x;
327+
clip.y = rect.y - (gint) actor_y;
328+
}
329+
else
330+
{
331+
meta_window_get_buffer_rect (screenshot_data->window, &rect);
332+
333+
screenshot_data->screenshot_area.x = (gint) actor_x + rect.x;
334+
screenshot_data->screenshot_area.y = (gint) actor_y + rect.y;
335+
336+
clip.x = rect.x;
337+
clip.y = rect.y;
338+
}
339+
340+
clip.width = screenshot_data->screenshot_area.width = rect.width;
341+
clip.height = screenshot_data->screenshot_area.height = rect.height;
342+
343+
stex = META_SHAPED_TEXTURE (meta_window_actor_get_texture (META_WINDOW_ACTOR (window_actor)));
344+
screenshot_data->image = meta_shaped_texture_get_image (stex, &clip);
345+
346+
if (screenshot_data->include_cursor)
347+
_draw_cursor_image (screenshot_data->image, screenshot_data->screenshot_area);
348+
349+
g_signal_handlers_disconnect_by_func (stage, (void *)grab_window_screenshot, (gpointer) screenshot_data);
350+
351+
meta_enable_unredirect_for_display (display);
352+
353+
result = g_simple_async_result_new (NULL, on_screenshot_written, (gpointer)screenshot_data, cinnamon_screenshot_screenshot_window);
354+
g_simple_async_result_run_in_thread (result, write_screenshot_thread, G_PRIORITY_DEFAULT, NULL);
355+
g_object_unref (result);
356+
}
357+
292358
/**
293359
* cinnamon_screenshot_screenshot:
294360
* @screenshot: the #CinnamonScreenshot
@@ -307,6 +373,7 @@ cinnamon_screenshot_screenshot (CinnamonScreenshot *screenshot,
307373
const char *filename,
308374
CinnamonScreenshotCallback callback)
309375
{
376+
MetaDisplay *display;
310377
ClutterActor *stage;
311378
_screenshot_data *data = g_new0 (_screenshot_data, 1);
312379

@@ -315,10 +382,11 @@ cinnamon_screenshot_screenshot (CinnamonScreenshot *screenshot,
315382
data->callback = callback;
316383
data->include_cursor = include_cursor;
317384

385+
display = cinnamon_global_get_display (screenshot->global);
318386
stage = CLUTTER_ACTOR (cinnamon_global_get_stage (screenshot->global));
319387

388+
meta_disable_unredirect_for_display (display);
320389
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_screenshot), (gpointer)data);
321-
322390
clutter_actor_queue_redraw (stage);
323391
}
324392

@@ -347,6 +415,7 @@ cinnamon_screenshot_screenshot_area (CinnamonScreenshot *screenshot,
347415
const char *filename,
348416
CinnamonScreenshotCallback callback)
349417
{
418+
MetaDisplay *display;
350419
ClutterActor *stage;
351420
_screenshot_data *data = g_new0 (_screenshot_data, 1);
352421

@@ -359,8 +428,10 @@ cinnamon_screenshot_screenshot_area (CinnamonScreenshot *screenshot,
359428
data->callback = callback;
360429
data->include_cursor = include_cursor;
361430

431+
display = cinnamon_global_get_display (screenshot->global);
362432
stage = CLUTTER_ACTOR (cinnamon_global_get_stage (screenshot->global));
363433

434+
meta_disable_unredirect_for_display (display);
364435
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_area_screenshot), (gpointer)data);
365436

366437
clutter_actor_queue_redraw (stage);
@@ -386,66 +457,32 @@ cinnamon_screenshot_screenshot_window (CinnamonScreenshot *screenshot,
386457
const char *filename,
387458
CinnamonScreenshotCallback callback)
388459
{
389-
GSimpleAsyncResult *result;
390-
391-
CinnamonScreen *screen = cinnamon_global_get_screen (screenshot->global);
392-
MetaDisplay *display = cinnamon_screen_get_display (screen);
460+
MetaDisplay *display = cinnamon_global_get_display (screenshot->global);
393461
MetaWindow *window = meta_display_get_focus_window (display);
462+
ClutterActor *stage;
394463

395464
if (window == NULL || g_strcmp0 (meta_window_get_title (window), "Desktop") == 0)
396465
{
397466
cinnamon_screenshot_screenshot (screenshot, include_cursor, filename, callback);
398467
return;
399468
}
400469

401-
_screenshot_data *screenshot_data = g_new0 (_screenshot_data, 1);
402-
403-
ClutterActor *window_actor;
404-
gfloat actor_x, actor_y;
405-
MetaShapedTexture *stex;
406-
MetaRectangle rect;
407-
cairo_rectangle_int_t clip;
408-
409-
screenshot_data->screenshot = g_object_ref (screenshot);
410-
screenshot_data->filename = g_strdup (filename);
411-
screenshot_data->callback = callback;
412-
413-
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
414-
clutter_actor_get_position (window_actor, &actor_x, &actor_y);
415-
416-
if (include_frame || !meta_window_get_frame (window))
417-
{
418-
meta_window_get_frame_rect (window, &rect);
419-
420-
screenshot_data->screenshot_area.x = rect.x;
421-
screenshot_data->screenshot_area.y = rect.y;
422-
423-
clip.x = rect.x - (gint) actor_x;
424-
clip.y = rect.y - (gint) actor_y;
425-
}
426-
else
427-
{
428-
meta_window_get_buffer_rect (window, &rect);
429-
430-
screenshot_data->screenshot_area.x = (gint) actor_x + rect.x;
431-
screenshot_data->screenshot_area.y = (gint) actor_y + rect.y;
432-
433-
clip.x = rect.x;
434-
clip.y = rect.y;
435-
}
470+
_screenshot_data *data = g_new0 (_screenshot_data, 1);
436471

437-
clip.width = screenshot_data->screenshot_area.width = rect.width;
438-
clip.height = screenshot_data->screenshot_area.height = rect.height;
472+
data->window = window;
473+
data->screenshot = g_object_ref (screenshot);
474+
data->filename = g_strdup (filename);
475+
data->callback = callback;
476+
data->include_cursor = include_cursor;
477+
data->include_frame = include_frame;
439478

440-
stex = META_SHAPED_TEXTURE (meta_window_actor_get_texture (META_WINDOW_ACTOR (window_actor)));
441-
screenshot_data->image = meta_shaped_texture_get_image (stex, &clip);
479+
display = cinnamon_global_get_display (screenshot->global);
480+
stage = CLUTTER_ACTOR (cinnamon_global_get_stage (screenshot->global));
442481

443-
if (include_cursor)
444-
_draw_cursor_image (screenshot_data->image, screenshot_data->screenshot_area);
482+
meta_disable_unredirect_for_display (display);
483+
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_window_screenshot), (gpointer) data);
445484

446-
result = g_simple_async_result_new (NULL, on_screenshot_written, (gpointer)screenshot_data, cinnamon_screenshot_screenshot_window);
447-
g_simple_async_result_run_in_thread (result, write_screenshot_thread, G_PRIORITY_DEFAULT, NULL);
448-
g_object_unref (result);
485+
clutter_actor_queue_redraw (stage);
449486
}
450487

451488
CinnamonScreenshot *

0 commit comments

Comments
 (0)