summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Mikhaylenko <alexm@gnome.org>2020-10-03 15:49:15 +0500
committerAlexander Mikhaylenko <exalm7659@gmail.com>2020-10-27 22:01:27 +0500
commit0ba61788b4a10eb040d2d4e0814123cc95a4c677 (patch)
tree36f574e8bbf965f4c8f254961e55d7c04b1359d1
parent42d3ef0bcdeea322c2ba3b1b0ad181649923a261 (diff)
downloadgnome-screenshot-wip/exalm/gtk4.tar.gz
Drop X11 supportwip/exalm/gtk4
-rw-r--r--meson.build11
-rw-r--r--meson_options.txt6
-rw-r--r--src/cheese-flash.c226
-rw-r--r--src/cheese-flash.h46
-rw-r--r--src/meson.build5
-rw-r--r--src/screenshot-area-selection.c231
-rw-r--r--src/screenshot-backend-x11.c579
-rw-r--r--src/screenshot-backend-x11.h33
-rw-r--r--src/screenshot-utils.c33
9 files changed, 4 insertions, 1166 deletions
diff --git a/meson.build b/meson.build
index 3bfb619..bdc4332 100644
--- a/meson.build
+++ b/meson.build
@@ -34,8 +34,6 @@ gtk_req_version = '>= 3.12.0'
libhandy_req_version = '>= 0.90.0'
mathlib_dep = cc.find_library('m', required: false)
-x11_dep = dependency('x11', required: get_option ('x11'))
-xext_dep = dependency('xext', required: get_option ('x11'))
glib_dep = dependency('glib-2.0', version: glib_req_version)
gtk_dep = dependency('gtk+-3.0', version: gtk_req_version)
libhandy_dep = dependency('libhandy-1', version: libhandy_req_version)
@@ -45,15 +43,6 @@ config_h = configuration_data()
config_h.set_quoted('VERSION', meson.project_version())
config_h.set_quoted('GETTEXT_PACKAGE', meson.project_name())
-has_x11 = x11_dep.found() and xext_dep.found()
-if has_x11
- config_h.set('HAVE_X11', 1)
-
- if cc.has_header('X11/extensions/shape.h')
- config_h.set('HAVE_X11_EXTENSIONS_SHAPE_H', 1)
- endif
-endif
-
configure_file(output: 'config.h', configuration: config_h)
root_inc = include_directories('.')
diff --git a/meson_options.txt b/meson_options.txt
deleted file mode 100644
index 7228d35..0000000
--- a/meson_options.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-option (
- 'x11',
- type: 'feature',
- description: 'Enable fallback X11 backend',
- value: 'auto'
-)
diff --git a/src/cheese-flash.c b/src/cheese-flash.c
deleted file mode 100644
index 3f6e399..0000000
--- a/src/cheese-flash.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright © 2008 Alexander “weej” Jones <alex@weej.com>
- * Copyright © 2008 Thomas Perl <thp@thpinfo.com>
- * Copyright © 2009 daniel g. siegel <dgsiegel@gnome.org>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#ifdef HAVE_X11
-
-#include <gtk/gtk.h>
-
-#include "cheese-flash.h"
-
-/**
- * SECTION:cheese-flash
- * @short_description: Flash the screen, like a real camera flash
- * @stability: Unstable
- * @include: cheese/cheese-flash.h
- *
- * #CheeseFlash is a window that you can create and invoke a method "flash" on
- * to temporarily flood the screen with white.
- */
-
-/* How long to hold the flash for, in milliseconds. */
-static const guint FLASH_DURATION = 150;
-
-/* The factor which defines how much the flash fades per frame */
-static const gdouble FLASH_FADE_FACTOR = 0.95;
-
-/* How many frames per second */
-static const guint FLASH_ANIMATION_RATE = 120;
-
-/* When to consider the flash finished so we can stop fading */
-static const gdouble FLASH_LOW_THRESHOLD = 0.01;
-
-/*
- * CheeseFlashPrivate:
- * @flash_timeout_tag: signal ID of the timeout to start fading in the flash
- * @fade_timeout_tag: signal ID of the timeout to start fading out the flash
- *
- * Private data for #CheeseFlash.
- */
-typedef struct
-{
- /*< private >*/
- guint flash_timeout_tag;
- guint fade_timeout_tag;
- gdouble opacity;
-} CheeseFlashPrivate;
-
-G_DEFINE_TYPE_WITH_PRIVATE (CheeseFlash, cheese_flash, GTK_TYPE_WINDOW)
-
-static void
-cheese_flash_init (CheeseFlash *self)
-{
- CheeseFlashPrivate *priv = cheese_flash_get_instance_private (self);
- cairo_region_t *input_region;
- GtkWindow *window = GTK_WINDOW (self);
- const GdkRGBA white = { 1.0, 1.0, 1.0, 1.0 };
-
- priv->flash_timeout_tag = 0;
- priv->fade_timeout_tag = 0;
- priv->opacity = 1.0;
-
- /* make it so it doesn't look like a window on the desktop (+fullscreen) */
- gtk_window_set_decorated (window, FALSE);
- gtk_window_set_skip_taskbar_hint (window, TRUE);
- gtk_window_set_skip_pager_hint (window, TRUE);
- gtk_window_set_keep_above (window, TRUE);
-
- /* Don't take focus */
- gtk_window_set_accept_focus (window, FALSE);
- gtk_window_set_focus_on_map (window, FALSE);
-
- /* Make it white */
- gtk_widget_override_background_color (GTK_WIDGET (window), GTK_STATE_NORMAL,
- &white);
-
- /* Don't consume input */
- gtk_widget_realize (GTK_WIDGET (window));
- input_region = cairo_region_create ();
- gdk_window_input_shape_combine_region (gtk_widget_get_window (GTK_WIDGET (window)), input_region, 0, 0);
- cairo_region_destroy (input_region);
-}
-
-static void
-cheese_flash_class_init (CheeseFlashClass *klass)
-{
-}
-
-/*
- * cheese_flash_opacity_fade:
- * @data: the #CheeseFlash
- *
- * Fade the flash out.
- *
- * Returns: %TRUE if the fade was completed, %FALSE if the flash must continue
- * to fade
- */
-static gboolean
-cheese_flash_opacity_fade (gpointer data)
-{
- CheeseFlashPrivate *priv;
- GtkWidget *flash_window;
-
- flash_window = GTK_WIDGET (data);
- priv = cheese_flash_get_instance_private (CHEESE_FLASH (data));
-
- /* exponentially decrease */
- priv->opacity *= FLASH_FADE_FACTOR;
-
- if (priv->opacity <= FLASH_LOW_THRESHOLD)
- {
- /* the flasher has finished when we reach the quit value */
- priv->fade_timeout_tag = 0;
- gtk_widget_destroy (flash_window);
- return G_SOURCE_REMOVE;
- }
- else
- {
- gtk_widget_set_opacity (flash_window, priv->opacity);
- }
-
- return G_SOURCE_CONTINUE;
-}
-
-/*
- * cheese_flash_start_fade:
- * @data: the #CheeseFlash
- *
- * Add a timeout to start the fade animation.
- *
- * Returns: %FALSE
- */
-static gboolean
-cheese_flash_start_fade (gpointer data)
-{
- CheeseFlashPrivate *priv = cheese_flash_get_instance_private (CHEESE_FLASH (data));
- GtkWindow *flash_window = GTK_WINDOW (data);
-
- /* If the screen is non-composited, just destroy and finish up */
- if (!gdk_screen_is_composited (gtk_window_get_screen (flash_window)))
- {
- gtk_widget_destroy (GTK_WIDGET (flash_window));
- return G_SOURCE_REMOVE;
- }
-
- priv->fade_timeout_tag = g_timeout_add (1000.0 / FLASH_ANIMATION_RATE, cheese_flash_opacity_fade, data);
- priv->flash_timeout_tag = 0;
- return G_SOURCE_REMOVE;
-}
-
-/**
- * cheese_flash_fire:
- * @flash: a #CheeseFlash
- * @rect: a #GdkRectangle
- *
- * Fire the flash.
- */
-void
-cheese_flash_fire (CheeseFlash *flash,
- GdkRectangle *rect)
-{
- CheeseFlashPrivate *priv;
- GtkWindow *flash_window;
-
- g_return_if_fail (CHEESE_IS_FLASH (flash));
- g_return_if_fail (rect != NULL);
-
- priv = cheese_flash_get_instance_private (flash);
- flash_window = GTK_WINDOW (flash);
-
- if (priv->flash_timeout_tag > 0)
- {
- g_source_remove (priv->flash_timeout_tag);
- priv->flash_timeout_tag = 0;
- }
-
- if (priv->fade_timeout_tag > 0)
- {
- g_source_remove (priv->fade_timeout_tag);
- priv->fade_timeout_tag = 0;
- }
-
- priv->opacity = 1.0;
-
- gtk_window_resize (flash_window, rect->width, rect->height);
- gtk_window_move (flash_window, rect->x, rect->y);
-
- gtk_widget_set_opacity (GTK_WIDGET (flash_window), 1);
- gtk_widget_show_all (GTK_WIDGET (flash_window));
- priv->flash_timeout_tag = g_timeout_add (FLASH_DURATION, cheese_flash_start_fade, (gpointer) flash);
-}
-
-/**
- * cheese_flash_new:
- *
- * Create a new #CheeseFlash.
- *
- * Returns: a new #CheeseFlash
- */
-CheeseFlash *
-cheese_flash_new (void)
-{
- return g_object_new (CHEESE_TYPE_FLASH,
- "type", GTK_WINDOW_POPUP,
- NULL);
-}
-
-#endif
diff --git a/src/cheese-flash.h b/src/cheese-flash.h
deleted file mode 100644
index 09385fb..0000000
--- a/src/cheese-flash.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright © 2008 Alexander “weej” Jones <alex@weej.com>
- *
- * Licensed under the GNU General Public License Version 2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <gtk/gtk.h>
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-/**
- * CheeseFlash:
- *
- * Use the accessor functions below.
- */
-struct _CheeseFlash
-{
- /*< private >*/
- GtkWindow parent_instance;
- void *unused;
-};
-
-#define CHEESE_TYPE_FLASH (cheese_flash_get_type ())
-G_DECLARE_FINAL_TYPE (CheeseFlash, cheese_flash, CHEESE, FLASH, GtkWindow)
-
-CheeseFlash *cheese_flash_new (void);
-void cheese_flash_fire (CheeseFlash *flash,
- GdkRectangle *rect);
-
-G_END_DECLS
diff --git a/src/meson.build b/src/meson.build
index 91b97e7..212e9bf 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,13 +1,10 @@
sources = [
'gnome-screenshot.c',
- 'cheese-flash.c',
-
'screenshot-application.c',
'screenshot-area-selection.c',
'screenshot-backend.c',
'screenshot-backend-shell.c',
- 'screenshot-backend-x11.c',
'screenshot-config.c',
'screenshot-dialog.c',
'screenshot-filename-builder.c',
@@ -22,8 +19,6 @@ include_directories = [
dependencies = [
mathlib_dep,
- x11_dep,
- xext_dep,
glib_dep,
gtk_dep,
libhandy_dep,
diff --git a/src/screenshot-area-selection.c b/src/screenshot-area-selection.c
index 224d93d..eae754f 100644
--- a/src/screenshot-area-selection.c
+++ b/src/screenshot-area-selection.c
@@ -25,183 +25,6 @@
#include "screenshot-area-selection.h"
typedef struct {
- GdkRectangle rect;
- gboolean button_pressed;
- GtkWidget *window;
-
- gboolean aborted;
-} select_area_filter_data;
-
-static gboolean
-select_area_button_press (GtkWidget *window,
- GdkEventButton *event,
- select_area_filter_data *data)
-{
- if (data->button_pressed)
- return TRUE;
-
- data->button_pressed = TRUE;
- data->rect.x = event->x_root;
- data->rect.y = event->y_root;
-
- return TRUE;
-}
-
-static gboolean
-select_area_motion_notify (GtkWidget *window,
- GdkEventMotion *event,
- select_area_filter_data *data)
-{
- GdkRectangle draw_rect;
-
- if (!data->button_pressed)
- return TRUE;
-
- draw_rect.width = ABS (data->rect.x - event->x_root);
- draw_rect.height = ABS (data->rect.y - event->y_root);
- draw_rect.x = MIN (data->rect.x, event->x_root);
- draw_rect.y = MIN (data->rect.y, event->y_root);
-
- if (draw_rect.width <= 0 || draw_rect.height <= 0)
- {
- gtk_window_move (GTK_WINDOW (window), -100, -100);
- gtk_window_resize (GTK_WINDOW (window), 10, 10);
- return TRUE;
- }
-
- gtk_window_move (GTK_WINDOW (window), draw_rect.x, draw_rect.y);
- gtk_window_resize (GTK_WINDOW (window), draw_rect.width, draw_rect.height);
-
- /* We (ab)use app-paintable to indicate if we have an RGBA window */
- if (!gtk_widget_get_app_paintable (window))
- {
- GdkWindow *gdkwindow = gtk_widget_get_window (window);
-
- /* Shape the window to make only the outline visible */
- if (draw_rect.width > 2 && draw_rect.height > 2)
- {
- cairo_region_t *region;
- cairo_rectangle_int_t region_rect = {
- 0, 0,
- draw_rect.width, draw_rect.height
- };
-
- region = cairo_region_create_rectangle (&region_rect);
- region_rect.x++;
- region_rect.y++;
- region_rect.width -= 2;
- region_rect.height -= 2;
- cairo_region_subtract_rectangle (region, &region_rect);
-
- gdk_window_shape_combine_region (gdkwindow, region, 0, 0);
-
- cairo_region_destroy (region);
- }
- else
- gdk_window_shape_combine_region (gdkwindow, NULL, 0, 0);
- }
-
- return TRUE;
-}
-
-static gboolean
-select_area_button_release (GtkWidget *window,
- GdkEventButton *event,
- select_area_filter_data *data)
-{
- if (!data->button_pressed)
- return TRUE;
-
- data->rect.width = ABS (data->rect.x - event->x_root);
- data->rect.height = ABS (data->rect.y - event->y_root);
- data->rect.x = MIN (data->rect.x, event->x_root);
- data->rect.y = MIN (data->rect.y, event->y_root);
-
- if (data->rect.width == 0 || data->rect.height == 0)
- data->aborted = TRUE;
-
- gtk_main_quit ();
-
- return TRUE;
-}
-
-static gboolean
-select_area_key_press (GtkWidget *window,
- GdkEventKey *event,
- select_area_filter_data *data)
-{
- if (event->keyval == GDK_KEY_Escape)
- {
- data->rect.x = 0;
- data->rect.y = 0;
- data->rect.width = 0;
- data->rect.height = 0;
- data->aborted = TRUE;
-
- gtk_main_quit ();
- }
-
- return TRUE;
-}
-
-static gboolean
-select_window_draw (GtkWidget *window, cairo_t *cr, gpointer unused)
-{
- GtkStyleContext *style;
-
- style = gtk_widget_get_style_context (window);
-
- if (gtk_widget_get_app_paintable (window))
- {
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- cairo_set_source_rgba (cr, 0, 0, 0, 0);
- cairo_paint (cr);
-
- gtk_style_context_save (style);
- gtk_style_context_add_class (style, GTK_STYLE_CLASS_RUBBERBAND);
-
- gtk_render_background (style, cr,
- 0, 0,
- gtk_widget_get_allocated_width (window),
- gtk_widget_get_allocated_height (window));
- gtk_render_frame (style, cr,
- 0, 0,
- gtk_widget_get_allocated_width (window),
- gtk_widget_get_allocated_height (window));
-
- gtk_style_context_restore (style);
- }
-
- return TRUE;
-}
-
-static GtkWidget *
-create_select_window (void)
-{
- GtkWidget *window;
- GdkScreen *screen;
- GdkVisual *visual;
-
- screen = gdk_screen_get_default ();
- visual = gdk_screen_get_rgba_visual (screen);
-
- window = gtk_window_new (GTK_WINDOW_POPUP);
- if (gdk_screen_is_composited (screen) && visual)
- {
- gtk_widget_set_visual (window, visual);
- gtk_widget_set_app_paintable (window, TRUE);
- }
-
- g_signal_connect (window, "draw", G_CALLBACK (select_window_draw), NULL);
-
- gtk_window_move (GTK_WINDOW (window), -100, -100);
- gtk_window_resize (GTK_WINDOW (window), 10, 10);
- gtk_widget_show (window);
-
- return window;
-}
-
-typedef struct {
GdkRectangle rectangle;
SelectAreaCallback callback;
gpointer callback_data;
@@ -224,56 +47,6 @@ emit_select_callback_in_idle (gpointer user_data)
}
static void
-screenshot_select_area_x11_async (CallbackData *cb_data)
-{
- g_autoptr(GdkCursor) cursor = NULL;
- GdkDisplay *display;
- select_area_filter_data data;
- GdkSeat *seat;
-
- data.rect.x = 0;
- data.rect.y = 0;
- data.rect.width = 0;
- data.rect.height = 0;
- data.button_pressed = FALSE;
- data.aborted = FALSE;
- data.window = create_select_window();
-
- g_signal_connect (data.window, "key-press-event", G_CALLBACK (select_area_key_press), &data);
- g_signal_connect (data.window, "button-press-event", G_CALLBACK (select_area_button_press), &data);
- g_signal_connect (data.window, "button-release-event", G_CALLBACK (select_area_button_release), &data);
- g_signal_connect (data.window, "motion-notify-event", G_CALLBACK (select_area_motion_notify), &data);
-
- display = gtk_widget_get_display (data.window);
- cursor = gdk_cursor_new_for_display (display, GDK_CROSSHAIR);
- seat = gdk_display_get_default_seat (display);
-
- gdk_seat_grab (seat,
- gtk_widget_get_window (data.window),
- GDK_SEAT_CAPABILITY_ALL,
- FALSE,
- cursor,
- NULL,
- NULL,
- NULL);
-
- gtk_main ();
-
- gdk_seat_ungrab (seat);
-
- gtk_widget_destroy (data.window);
-
- cb_data->aborted = data.aborted;
- cb_data->rectangle = data.rect;
-
- /* FIXME: we should actually be emitting the callback When
- * the compositor has finished re-drawing, but there seems to be no easy
- * way to know that.
- */
- g_timeout_add (200, emit_select_callback_in_idle, cb_data);
-}
-
-static void
select_area_done (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
@@ -292,10 +65,8 @@ select_area_done (GObject *source_object,
return;
}
- g_message ("Unable to select area using GNOME Shell's builtin screenshot "
- "interface, resorting to fallback X11.");
+ g_message ("Unable to select area.");
- screenshot_select_area_x11_async (cb_data);
return;
}
diff --git a/src/screenshot-backend-x11.c b/src/screenshot-backend-x11.c
deleted file mode 100644
index 990e715..0000000
--- a/src/screenshot-backend-x11.c
+++ /dev/null
@@ -1,579 +0,0 @@
-/* screenshot-backend-x11.c - Fallback X11 backend
- *
- * Copyright (C) 2001-2006 Jonathan Blandford <jrb@alum.mit.edu>
- * Copyright (C) 2008 Cosimo Cecchi <cosimoc@gnome.org>
- * Copyright (C) 2020 Alexander Mikhaylenko <alexm@gnome.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- */
-
-#include "config.h"
-
-#ifdef HAVE_X11
-
-#include "screenshot-backend-x11.h"
-
-#include "screenshot-config.h"
-
-#include "cheese-flash.h"
-
-#include <gdk/gdkx.h>
-
-#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
-#include <X11/extensions/shape.h>
-#endif
-
-struct _ScreenshotBackendX11
-{
- GObject parent_instance;
-};
-
-static void screenshot_backend_x11_backend_init (ScreenshotBackendInterface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (ScreenshotBackendX11, screenshot_backend_x11, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (SCREENSHOT_TYPE_BACKEND, screenshot_backend_x11_backend_init))
-
-static GdkWindow *
-screenshot_find_active_window (void)
-{
- GdkWindow *window;
- GdkScreen *default_screen;
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- default_screen = gdk_screen_get_default ();
- window = gdk_screen_get_active_window (default_screen);
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- return window;
-}
-
-static gboolean
-screenshot_window_is_desktop (GdkWindow *window)
-{
- GdkWindow *root_window = gdk_get_default_root_window ();
- GdkWindowTypeHint window_type_hint;
-
- if (window == root_window)
- return TRUE;
-
- window_type_hint = gdk_window_get_type_hint (window);
- if (window_type_hint == GDK_WINDOW_TYPE_HINT_DESKTOP)
- return TRUE;
-
- return FALSE;
-}
-
-static Window
-find_wm_window (GdkWindow *window)
-{
- Window xid, root, parent, *children;
- unsigned int nchildren;
-
- if (window == gdk_get_default_root_window ())
- return None;
-
- xid = GDK_WINDOW_XID (window);
-
- do
- {
- if (XQueryTree (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
- xid, &root, &parent, &children, &nchildren) == 0)
- {
- g_warning ("Couldn't find window manager window");
- return None;
- }
-
- if (root == parent)
- return xid;
-
- xid = parent;
- }
- while (TRUE);
-}
-
-static cairo_region_t *
-make_region_with_monitors (GdkDisplay *display)
-{
- cairo_region_t *region;
- int num_monitors;
- int i;
-
- num_monitors = gdk_display_get_n_monitors (display);
-
- region = cairo_region_create ();
-
- for (i = 0; i < num_monitors; i++)
- {
- GdkMonitor *monitor;
- GdkRectangle rect;
-
- monitor = gdk_display_get_monitor (display, i);
- gdk_monitor_get_geometry (monitor, &rect);
- cairo_region_union_rectangle (region, &rect);
- }
-
- return region;
-}
-
-static void
-blank_rectangle_in_pixbuf (GdkPixbuf *pixbuf, GdkRectangle *rect)
-{
- int x, y;
- int x2, y2;
- guchar *pixels;
- int rowstride;
- int n_channels;
- guchar *row;
- gboolean has_alpha;
-
- g_assert (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
-
- x2 = rect->x + rect->width;
- y2 = rect->y + rect->height;
-
- pixels = gdk_pixbuf_get_pixels (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
- n_channels = gdk_pixbuf_get_n_channels (pixbuf);
-
- for (y = rect->y; y < y2; y++)
- {
- guchar *p;
-
- row = pixels + y * rowstride;
- p = row + rect->x * n_channels;
-
- for (x = rect->x; x < x2; x++)
- {
- *p++ = 0;
- *p++ = 0;
- *p++ = 0;
-
- if (has_alpha)
- *p++ = 255; /* opaque black */
- }
- }
-}
-
-static void
-blank_region_in_pixbuf (GdkPixbuf *pixbuf, cairo_region_t *region)
-{
- int n_rects;
- int i;
- int width, height;
- cairo_rectangle_int_t pixbuf_rect;
-
- n_rects = cairo_region_num_rectangles (region);
-
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
-
- pixbuf_rect.x = 0;
- pixbuf_rect.y = 0;
- pixbuf_rect.width = width;
- pixbuf_rect.height = height;
-
- for (i = 0; i < n_rects; i++)
- {
- cairo_rectangle_int_t rect, dest;
-
- cairo_region_get_rectangle (region, i, &rect);
- if (gdk_rectangle_intersect (&rect, &pixbuf_rect, &dest))
- blank_rectangle_in_pixbuf (pixbuf, &dest);
- }
-}
-
-/* When there are multiple monitors with different resolutions, the visible area
- * within the root window may not be rectangular (it may have an L-shape, for
- * example). In that case, mask out the areas of the root window which would
- * not be visible in the monitors, so that screenshot do not end up with content
- * that the user won't ever see.
- */
-static void
-mask_monitors (GdkPixbuf *pixbuf,
- GdkWindow *root_window)
-{
- GdkDisplay *display;
- cairo_region_t *region_with_monitors;
- cairo_region_t *invisible_region;
- cairo_rectangle_int_t rect;
-
- display = gdk_window_get_display (root_window);
-
- region_with_monitors = make_region_with_monitors (display);
-
- rect.x = 0;
- rect.y = 0;
- rect.width = gdk_pixbuf_get_width (pixbuf);
- rect.height = gdk_pixbuf_get_height (pixbuf);
-
- invisible_region = cairo_region_create_rectangle (&rect);
- cairo_region_subtract (invisible_region, region_with_monitors);
-
- blank_region_in_pixbuf (pixbuf, invisible_region);
-
- cairo_region_destroy (region_with_monitors);
- cairo_region_destroy (invisible_region);
-}
-
-static void
-screenshot_fallback_get_window_rect_coords (GdkWindow *window,
- GdkRectangle *real_coordinates_out,
- GdkRectangle *screenshot_coordinates_out)
-{
- gint x_orig, y_orig;
- gint width, height;
- GdkRectangle real_coordinates;
-
- gdk_window_get_frame_extents (window, &real_coordinates);
-
- x_orig = real_coordinates.x;
- y_orig = real_coordinates.y;
- width = real_coordinates.width;
- height = real_coordinates.height;
-
- if (real_coordinates_out != NULL)
- *real_coordinates_out = real_coordinates;
-
- if (x_orig < 0)
- {
- width = width + x_orig;
- x_orig = 0;
- }
-
- if (y_orig < 0)
- {
- height = height + y_orig;
- y_orig = 0;
- }
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- if (x_orig + width > gdk_screen_width ())
- width = gdk_screen_width () - x_orig;
-
- if (y_orig + height > gdk_screen_height ())
- height = gdk_screen_height () - y_orig;
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- if (screenshot_coordinates_out != NULL)
- {
- screenshot_coordinates_out->x = x_orig;
- screenshot_coordinates_out->y = y_orig;
- screenshot_coordinates_out->width = width;
- screenshot_coordinates_out->height = height;
- }
-}
-
-static void
-screenshot_fallback_fire_flash (GdkWindow *window,
- GdkRectangle *rectangle)
-{
- GdkRectangle rect;
- CheeseFlash *flash = NULL;
-
- if (rectangle != NULL)
- rect = *rectangle;
- else
- screenshot_fallback_get_window_rect_coords (window, NULL, &rect);
-
- flash = cheese_flash_new ();
- cheese_flash_fire (flash, &rect);
-}
-
-GdkWindow *
-do_find_current_window (void)
-{
- GdkWindow *current_window;
- GdkDevice *device;
- GdkSeat *seat;
-
- current_window = screenshot_find_active_window ();
- seat = gdk_display_get_default_seat (gdk_display_get_default ());
- device = gdk_seat_get_pointer (seat);
-
- /* If there's no active window, we fall back to returning the
- * window that the cursor is in.
- */
- if (!current_window)
- current_window = gdk_device_get_window_at_position (device, NULL, NULL);
-
- if (current_window)
- {
- if (screenshot_window_is_desktop (current_window))
- /* if the current window is the desktop (e.g. nautilus), we
- * return NULL, as getting the whole screen makes more sense.
- */
- return NULL;
-
- /* Once we have a window, we take the toplevel ancestor. */
- current_window = gdk_window_get_toplevel (current_window);
- }
-
- return current_window;
-}
-
-static GdkWindow *
-screenshot_fallback_find_current_window (void)
-{
- GdkWindow *window = NULL;
-
- if (screenshot_config->take_window_shot)
- {
- window = do_find_current_window ();
-
- if (window == NULL)
- screenshot_config->take_window_shot = FALSE;
- }
-
- if (window == NULL)
- window = gdk_get_default_root_window ();
-
- return window;
-}
-
-static GdkPixbuf *
-screenshot_backend_x11_get_pixbuf (ScreenshotBackend *backend,
- GdkRectangle *rectangle)
-{
- GdkWindow *root, *wm_window = NULL;
- GdkPixbuf *screenshot = NULL;
- GdkRectangle real_coords, screenshot_coords;
- Window wm;
- GtkBorder frame_offset = { 0, 0, 0, 0 };
- GdkWindow *window;
-
- window = screenshot_fallback_find_current_window ();
-
- screenshot_fallback_get_window_rect_coords (window,
- &real_coords,
- &screenshot_coords);
-
- wm = find_wm_window (window);
- if (wm != None)
- {
- GdkRectangle wm_real_coords;
-
- wm_window = gdk_x11_window_foreign_new_for_display
- (gdk_window_get_display (window), wm);
-
- screenshot_fallback_get_window_rect_coords (wm_window,
- &wm_real_coords,
- NULL);
-
- frame_offset.left = (gdouble) (real_coords.x - wm_real_coords.x);
- frame_offset.top = (gdouble) (real_coords.y - wm_real_coords.y);
- frame_offset.right = (gdouble) (wm_real_coords.width - real_coords.width - frame_offset.left);
- frame_offset.bottom = (gdouble) (wm_real_coords.height - real_coords.height - frame_offset.top);
- }
-
- if (rectangle)
- {
- screenshot_coords.x = rectangle->x - screenshot_coords.x;
- screenshot_coords.y = rectangle->y - screenshot_coords.y;
- screenshot_coords.width = rectangle->width;
- screenshot_coords.height = rectangle->height;
- }
-
- root = gdk_get_default_root_window ();
- screenshot = gdk_pixbuf_get_from_window (root,
- screenshot_coords.x, screenshot_coords.y,
- screenshot_coords.width, screenshot_coords.height);
-
- if (!screenshot_config->take_window_shot &&
- !screenshot_config->take_area_shot)
- mask_monitors (screenshot, root);
-
-#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
- if (wm != None)
- {
- XRectangle *rectangles;
- int rectangle_count, rectangle_order, i;
-
- /* we must use XShape to avoid showing what's under the rounder corners
- * of the WM decoration.
- */
- rectangles = XShapeGetRectangles (GDK_DISPLAY_XDISPLAY (gdk_display_get_default()),
- wm,
- ShapeBounding,
- &rectangle_count,
- &rectangle_order);
- if (rectangles && rectangle_count > 0)
- {
- int scale_factor = gdk_window_get_scale_factor (wm_window);
- gboolean has_alpha = gdk_pixbuf_get_has_alpha (screenshot);
- GdkPixbuf *tmp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
- gdk_pixbuf_get_width (screenshot),
- gdk_pixbuf_get_height (screenshot));
- gdk_pixbuf_fill (tmp, 0);
-
- for (i = 0; i < rectangle_count; i++)
- {
- gint rec_x, rec_y;
- gint rec_width, rec_height;
- gint y;
-
- /* If we're using invisible borders, the ShapeBounding might not
- * have the same size as the frame extents, as it would include the
- * areas for the invisible borders themselves.
- * In that case, trim every rectangle we get by the offset between the
- * WM window size and the frame extents.
- *
- * Note that the XShape values are in actual pixels, whereas the GDK
- * ones are in display pixels (i.e. scaled), so we need to apply the
- * scale factor to the former to use display pixels for all our math.
- */
- rec_x = rectangles[i].x / scale_factor;
- rec_y = rectangles[i].y / scale_factor;
- rec_width = rectangles[i].width / scale_factor - (frame_offset.left + frame_offset.right);
- rec_height = rectangles[i].height / scale_factor - (frame_offset.top + frame_offset.bottom);
-
- if (real_coords.x < 0)
- {
- rec_x += real_coords.x;
- rec_x = MAX(rec_x, 0);
- rec_width += real_coords.x;
- }
-
- if (real_coords.y < 0)
- {
- rec_y += real_coords.y;
- rec_y = MAX(rec_y, 0);
- rec_height += real_coords.y;
- }
-
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- if (screenshot_coords.x + rec_x + rec_width > gdk_screen_width ())
- rec_width = gdk_screen_width () - screenshot_coords.x - rec_x;
-
- if (screenshot_coords.y + rec_y + rec_height > gdk_screen_height ())
- rec_height = gdk_screen_height () - screenshot_coords.y - rec_y;
-G_GNUC_END_IGNORE_DEPRECATIONS
-
- /* Undo the scale factor in order to copy the pixbuf data pixel-wise */
- for (y = rec_y * scale_factor; y < (rec_y + rec_height) * scale_factor; y++)
- {
- guchar *src_pixels, *dest_pixels;
- gint x;
-
- src_pixels = gdk_pixbuf_get_pixels (screenshot)
- + y * gdk_pixbuf_get_rowstride(screenshot)
- + rec_x * scale_factor * (has_alpha ? 4 : 3);
- dest_pixels = gdk_pixbuf_get_pixels (tmp)
- + y * gdk_pixbuf_get_rowstride (tmp)
- + rec_x * scale_factor * 4;
-
- for (x = 0; x < rec_width * scale_factor; x++)
- {
- *dest_pixels++ = *src_pixels++;
- *dest_pixels++ = *src_pixels++;
- *dest_pixels++ = *src_pixels++;
-
- if (has_alpha)
- *dest_pixels++ = *src_pixels++;
- else
- *dest_pixels++ = 255;
- }
- }
- }
-
- g_set_object (&screenshot, tmp);
-
- XFree (rectangles);
- }
- }
-#endif /* HAVE_X11_EXTENSIONS_SHAPE_H */
-
- /* if we have a selected area, there were by definition no cursor in the
- * screenshot */
- if (screenshot_config->include_pointer && !rectangle)
- {
- g_autoptr(GdkCursor) cursor = NULL;
- g_autoptr(GdkPixbuf) cursor_pixbuf = NULL;
-
- cursor = gdk_cursor_new_for_display (gdk_display_get_default (), GDK_LEFT_PTR);
- cursor_pixbuf = gdk_cursor_get_image (cursor);
-
- if (cursor_pixbuf != NULL)
- {
- GdkSeat *seat;
- GdkDevice *device;
- GdkRectangle rect;
- gint cx, cy, xhot, yhot;
-
- seat = gdk_display_get_default_seat (gdk_display_get_default ());
- device = gdk_seat_get_pointer (seat);
-
- if (wm_window != NULL)
- gdk_window_get_device_position (wm_window, device,
- &cx, &cy, NULL);
- else
- gdk_window_get_device_position (window, device,
- &cx, &cy, NULL);
-
- sscanf (gdk_pixbuf_get_option (cursor_pixbuf, "x_hot"), "%d", &xhot);
- sscanf (gdk_pixbuf_get_option (cursor_pixbuf, "y_hot"), "%d", &yhot);
-
- /* in rect we have the cursor window coordinates */
- rect.x = cx + real_coords.x;
- rect.y = cy + real_coords.y;
- rect.width = gdk_pixbuf_get_width (cursor_pixbuf);
- rect.height = gdk_pixbuf_get_height (cursor_pixbuf);
-
- /* see if the pointer is inside the window */
- if (gdk_rectangle_intersect (&real_coords, &rect, &rect))
- {
- gint cursor_x, cursor_y;
-
- cursor_x = cx - xhot - frame_offset.left;
- cursor_y = cy - yhot - frame_offset.top;
- gdk_pixbuf_composite (cursor_pixbuf, screenshot,
- cursor_x, cursor_y,
- rect.width, rect.height,
- cursor_x, cursor_y,
- 1.0, 1.0,
- GDK_INTERP_BILINEAR,
- 255);
- }
- }
- }
-
- screenshot_fallback_fire_flash (window, rectangle);
-
- return screenshot;
-}
-
-static void
-screenshot_backend_x11_class_init (ScreenshotBackendX11Class *klass)
-{
-}
-
-static void
-screenshot_backend_x11_init (ScreenshotBackendX11 *self)
-{
-}
-
-static void
-screenshot_backend_x11_backend_init (ScreenshotBackendInterface *iface)
-{
- iface->get_pixbuf = screenshot_backend_x11_get_pixbuf;
-}
-
-ScreenshotBackend *
-screenshot_backend_x11_new (void)
-{
- return g_object_new (SCREENSHOT_TYPE_BACKEND_X11, NULL);
-}
-
-#endif /* HAVE_X11 */
diff --git a/src/screenshot-backend-x11.h b/src/screenshot-backend-x11.h
deleted file mode 100644
index 3b52b1e..0000000
--- a/src/screenshot-backend-x11.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* screenshot-backend-x11.h - Fallback X11 backend
- *
- * Copyright (C) 2020 Alexander Mikhaylenko <alexm@gnome.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- */
-
-#pragma once
-
-#include <glib-object.h>
-#include "screenshot-backend.h"
-
-G_BEGIN_DECLS
-
-#define SCREENSHOT_TYPE_BACKEND_X11 (screenshot_backend_x11_get_type())
-
-G_DECLARE_FINAL_TYPE (ScreenshotBackendX11, screenshot_backend_x11, SCREENSHOT, BACKEND_X11, GObject)
-
-ScreenshotBackend *screenshot_backend_x11_new (void);
-
-G_END_DECLS
diff --git a/src/screenshot-utils.c b/src/screenshot-utils.c
index 09ff4af..9279e94 100644
--- a/src/screenshot-utils.c
+++ b/src/screenshot-utils.c
@@ -29,10 +29,6 @@
#include "screenshot-backend-shell.h"
-#ifdef HAVE_X11
-#include "screenshot-backend-x11.h"
-#endif
-
void
screenshot_play_sound_effect (const gchar *event_id,
const gchar *event_desc)
@@ -69,36 +65,13 @@ GdkPixbuf *
screenshot_get_pixbuf (GdkRectangle *rectangle)
{
GdkPixbuf *screenshot = NULL;
- gboolean force_fallback = FALSE;
g_autoptr (ScreenshotBackend) backend = NULL;
-#ifdef HAVE_X11
- force_fallback = g_getenv ("GNOME_SCREENSHOT_FORCE_FALLBACK") != NULL;
-#endif
-
- if (!force_fallback)
- {
- backend = screenshot_backend_shell_new ();
- screenshot = screenshot_backend_get_pixbuf (backend, rectangle);
- if (!screenshot)
-#ifdef HAVE_X11
- g_message ("Unable to use GNOME Shell's builtin screenshot interface, "
- "resorting to fallback X11.");
-#else
- g_message ("Unable to use GNOME Shell's builtin screenshot interface.");
-#endif
- }
- else
- g_message ("Using fallback X11 as requested");
+ backend = screenshot_backend_shell_new ();
+ screenshot = screenshot_backend_get_pixbuf (backend, rectangle);
-#ifdef HAVE_X11
if (!screenshot)
- {
- g_clear_object (&backend);
- backend = screenshot_backend_x11_new ();
- screenshot = screenshot_backend_get_pixbuf (backend, rectangle);
- }
-#endif
+ g_message ("Unable to use GNOME Shell's builtin screenshot interface.");
return screenshot;
}