diff options
author | Matthias Clasen <mclasen@redhat.com> | 2016-04-03 00:12:39 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2016-04-27 23:18:16 -0400 |
commit | d92fda2103bc79043465b5218323a14edd05183e (patch) | |
tree | c839dee9536ecca9915912dbfdec371e9d7a5ada /gdk | |
parent | 79a0286ab13efd63cadfd2345d09d17387697592 (diff) | |
download | gtk+-d92fda2103bc79043465b5218323a14edd05183e.tar.gz |
x11: Port to new monitor api
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/x11/Makefile.am | 3 | ||||
-rw-r--r-- | gdk/x11/gdkdisplay-x11.c | 39 | ||||
-rw-r--r-- | gdk/x11/gdkdisplay-x11.h | 3 | ||||
-rw-r--r-- | gdk/x11/gdkmonitor-x11.c | 102 | ||||
-rw-r--r-- | gdk/x11/gdkmonitor-x11.h | 43 | ||||
-rw-r--r-- | gdk/x11/gdkscreen-x11.c | 774 | ||||
-rw-r--r-- | gdk/x11/gdkscreen-x11.h | 8 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 5 | ||||
-rw-r--r-- | gdk/x11/gdkx.h | 1 | ||||
-rw-r--r-- | gdk/x11/gdkx11monitor.h | 48 |
10 files changed, 620 insertions, 406 deletions
diff --git a/gdk/x11/Makefile.am b/gdk/x11/Makefile.am index c488a31724..6223e7e3fa 100644 --- a/gdk/x11/Makefile.am +++ b/gdk/x11/Makefile.am @@ -43,6 +43,8 @@ libgdk_x11_la_SOURCES = \ gdkglcontext-x11.h \ gdkkeys-x11.c \ gdkmain-x11.c \ + gdkmonitor-x11.c \ + gdkmonitor-x11.h \ gdkproperty-x11.c \ gdkscreen-x11.c \ gdkscreen-x11.h \ @@ -76,6 +78,7 @@ libgdkx11include_HEADERS = \ gdkx11dnd.h \ gdkx11glcontext.h \ gdkx11keys.h \ + gdkx11monitor.h \ gdkx11property.h \ gdkx11screen.h \ gdkx11selection.h \ diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index 6804ed2006..f7c79c4559 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -180,6 +180,7 @@ G_DEFINE_TYPE_WITH_CODE (GdkX11Display, gdk_x11_display, GDK_TYPE_DISPLAY, static void gdk_x11_display_init (GdkX11Display *display) { + display->monitors = g_ptr_array_new_with_free_func (g_object_unref); } static void @@ -1903,6 +1904,8 @@ gdk_x11_display_finalize (GObject *object) g_object_unref (display_x11->screen); g_list_free_full (display_x11->screens, g_object_unref); + g_ptr_array_free (display_x11->monitors, TRUE); + g_free (display_x11->startup_notification_id); /* X ID hashtable */ @@ -2903,6 +2906,38 @@ gdk_x11_display_get_default_seat (GdkDisplay *display) return NULL; } +static int +gdk_x11_display_get_n_monitors (GdkDisplay *display) +{ + GdkX11Display *x11_display = GDK_X11_DISPLAY (display); + + return x11_display->monitors->len; +} + + +static GdkMonitor * +gdk_x11_display_get_monitor (GdkDisplay *display, + int monitor_num) +{ + GdkX11Display *x11_display = GDK_X11_DISPLAY (display); + + if (0 <= monitor_num || monitor_num < x11_display->monitors->len) + return (GdkMonitor *)x11_display->monitors->pdata[monitor_num]; + + return NULL; +} + +static GdkMonitor * +gdk_x11_display_get_primary_monitor (GdkDisplay *display) +{ + GdkX11Display *x11_display = GDK_X11_DISPLAY (display); + + if (0 <= x11_display->primary_monitor && x11_display->primary_monitor < x11_display->monitors->len) + return x11_display->monitors->pdata[x11_display->primary_monitor]; + + return NULL; +} + static void gdk_x11_display_class_init (GdkX11DisplayClass * class) { @@ -2959,5 +2994,9 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class) display_class->get_default_seat = gdk_x11_display_get_default_seat; + display_class->get_n_monitors = gdk_x11_display_get_n_monitors; + display_class->get_monitor = gdk_x11_display_get_monitor; + display_class->get_primary_monitor = gdk_x11_display_get_primary_monitor; + _gdk_x11_windowing_init (); } diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h index eb43feb09a..48100dc052 100644 --- a/gdk/x11/gdkdisplay-x11.h +++ b/gdk/x11/gdkdisplay-x11.h @@ -100,6 +100,9 @@ struct _GdkX11Display /* input GdkWindow list */ GList *input_windows; + GPtrArray *monitors; + int primary_monitor; + /* Startup notification */ gchar *startup_notification_id; diff --git a/gdk/x11/gdkmonitor-x11.c b/gdk/x11/gdkmonitor-x11.c new file mode 100644 index 0000000000..899511afcd --- /dev/null +++ b/gdk/x11/gdkmonitor-x11.c @@ -0,0 +1,102 @@ +/* + * Copyright © 2016 Red Hat, Inc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <glib.h> +#include <gio/gio.h> + +#include "gdkmonitor-x11.h" +#include "gdkscreen-x11.h" + + +G_DEFINE_TYPE (GdkX11Monitor, gdk_x11_monitor, GDK_TYPE_MONITOR) + +static gboolean +gdk_monitor_has_fullscreen_window (GdkMonitor *monitor) +{ + GdkScreen *screen = gdk_display_get_default_screen (monitor->display); + GList *toplevels, *l; + GdkWindow *window; + gboolean has_fullscreen; + + toplevels = gdk_screen_get_toplevel_windows (screen); + + has_fullscreen = FALSE; + for (l = toplevels; l; l = l->next) + { + window = l->data; + + if ((gdk_window_get_state (window) & GDK_WINDOW_STATE_FULLSCREEN) == 0) + continue; + + if (gdk_window_get_fullscreen_mode (window) == GDK_FULLSCREEN_ON_ALL_MONITORS || + gdk_display_get_monitor_at_window (monitor->display, window) == monitor) + { + has_fullscreen = TRUE; + break; + } + } + + g_list_free (toplevels); + + return has_fullscreen; +} + +static void +gdk_x11_monitor_get_workarea (GdkMonitor *monitor, + GdkRectangle *dest) +{ + GdkScreen *screen = gdk_display_get_default_screen (monitor->display); + GdkRectangle workarea; + + gdk_monitor_get_geometry (monitor, dest); + + /* The EWMH constrains workarea to be a rectangle, so it + * can't adequately deal with L-shaped monitor arrangements. + * As a workaround, we ignore the workarea for anything + * but the primary monitor. Since that is where the 'desktop + * chrome' usually lives, this works ok in practice. + */ + if (gdk_monitor_is_primary (monitor) && + !gdk_monitor_has_fullscreen_window (monitor)) + { + gdk_x11_screen_get_work_area (screen, &workarea); + if (gdk_rectangle_intersect (dest, &workarea, &workarea)) + *dest = workarea; + } +} + +static void +gdk_x11_monitor_init (GdkX11Monitor *monitor) +{ +} + +static void +gdk_x11_monitor_class_init (GdkX11MonitorClass *class) +{ + GDK_MONITOR_CLASS (class)->get_workarea = gdk_x11_monitor_get_workarea; +} + +XID +gdk_x11_monitor_get_output (GdkMonitor *monitor) +{ + g_return_val_if_fail (GDK_IS_X11_MONITOR (monitor), 0); + + return GDK_X11_MONITOR (monitor)->output; +} + diff --git a/gdk/x11/gdkmonitor-x11.h b/gdk/x11/gdkmonitor-x11.h new file mode 100644 index 0000000000..de8b1dc4bb --- /dev/null +++ b/gdk/x11/gdkmonitor-x11.h @@ -0,0 +1,43 @@ +/* + * Copyright © 2016 Red Hat, Inc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GDK_X11_MONITOR_PRIVATE_H__ +#define __GDK_X11_MONITOR_PRIVATE_H__ + +#include <glib.h> +#include <gio/gio.h> +#include <X11/Xlib.h> + +#include "gdkmonitorprivate.h" + +#include "gdkx11monitor.h" + + +struct _GdkX11Monitor +{ + GdkMonitor parent; + + XID output; + guint add : 1; + guint remove : 1; +}; + +struct _GdkX11MonitorClass { + GdkMonitorClass parent_class; +}; + +#endif diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c index 2cb62ffa4d..7dfe373645 100644 --- a/gdk/x11/gdkscreen-x11.c +++ b/gdk/x11/gdkscreen-x11.c @@ -25,6 +25,7 @@ #include "gdkdisplay-x11.h" #include "gdkprivate-x11.h" #include "xsettings-client.h" +#include "gdkmonitor-x11.h" #include <glib.h> @@ -44,7 +45,6 @@ static void gdk_x11_screen_dispose (GObject *object); static void gdk_x11_screen_finalize (GObject *object); static void init_randr_support (GdkScreen *screen); -static void deinit_multihead (GdkScreen *screen); enum { @@ -64,17 +64,6 @@ struct _NetWmSupportedAtoms gulong n_atoms; }; -struct _GdkX11Monitor -{ - GdkRectangle geometry; - XID output; - int width_mm; - int height_mm; - char * output_name; - char * manufacturer; -}; - - static void gdk_x11_screen_init (GdkX11Screen *screen) { @@ -171,50 +160,9 @@ gdk_x11_screen_finalize (GObject *object) g_free (x11_screen->window_manager_name); - deinit_multihead (GDK_SCREEN (object)); - G_OBJECT_CLASS (gdk_x11_screen_parent_class)->finalize (object); } -static gint -gdk_x11_screen_get_n_monitors (GdkScreen *screen) -{ - return GDK_X11_SCREEN (screen)->n_monitors; -} - -static gint -gdk_x11_screen_get_primary_monitor (GdkScreen *screen) -{ - return GDK_X11_SCREEN (screen)->primary_monitor; -} - -static gint -gdk_x11_screen_get_monitor_width_mm (GdkScreen *screen, - gint monitor_num) -{ - GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); - - return x11_screen->monitors[monitor_num].width_mm; -} - -static gint -gdk_x11_screen_get_monitor_height_mm (GdkScreen *screen, - gint monitor_num) -{ - GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); - - return x11_screen->monitors[monitor_num].height_mm; -} - -static gchar * -gdk_x11_screen_get_monitor_plug_name (GdkScreen *screen, - gint monitor_num) -{ - GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); - - return g_strdup (x11_screen->monitors[monitor_num].output_name); -} - /** * gdk_x11_screen_get_monitor_output: * @screen: (type GdkX11Screen): a #GdkScreen @@ -233,29 +181,15 @@ gdk_x11_screen_get_monitor_output (GdkScreen *screen, gint monitor_num) { GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); + GdkX11Display *x11_display = GDK_X11_DISPLAY (x11_screen->display); + GdkX11Monitor *monitor; g_return_val_if_fail (GDK_IS_SCREEN (screen), None); g_return_val_if_fail (monitor_num >= 0, None); - g_return_val_if_fail (monitor_num < x11_screen->n_monitors, None); + g_return_val_if_fail (monitor_num < x11_display->monitors->len, None); - return x11_screen->monitors[monitor_num].output; -} - -static void -gdk_x11_screen_get_monitor_geometry (GdkScreen *screen, - gint monitor_num, - GdkRectangle *dest) -{ - GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); - - if (dest) - { - *dest = x11_screen->monitors[monitor_num].geometry; - dest->x /= x11_screen->window_scale; - dest->y /= x11_screen->window_scale; - dest->width /= x11_screen->window_scale; - dest->height /= x11_screen->window_scale; - } + monitor = x11_display->monitors->pdata[monitor_num]; + return monitor->output; } static int @@ -295,9 +229,9 @@ get_current_desktop (GdkScreen *screen) return workspace; } -static void -get_work_area (GdkScreen *screen, - GdkRectangle *area) +void +gdk_x11_screen_get_work_area (GdkScreen *screen, + GdkRectangle *area) { GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); Atom workarea; @@ -371,71 +305,6 @@ out: XFree (ret_workarea); } -static gboolean -gdk_x11_screen_monitor_has_fullscreen_window (GdkScreen *screen, - gint monitor) -{ - GList *toplevels, *l; - GdkWindow *window; - gboolean has_fullscreen; - - toplevels = gdk_screen_get_toplevel_windows (screen); - - has_fullscreen = FALSE; - - for (l = toplevels; l; l = l->next) - { - window = l->data; - - if ((gdk_window_get_state (window) & GDK_WINDOW_STATE_FULLSCREEN) == 0) - continue; - - if (gdk_window_get_fullscreen_mode (window) == GDK_FULLSCREEN_ON_ALL_MONITORS || - gdk_screen_get_monitor_at_window (screen, window) == monitor) - { - has_fullscreen = TRUE; - break; - } - } - - g_list_free (toplevels); - - return has_fullscreen; -} - -static void -gdk_x11_screen_get_monitor_workarea (GdkScreen *screen, - gint monitor_num, - GdkRectangle *dest) -{ - GdkRectangle workarea; - - gdk_x11_screen_get_monitor_geometry (screen, monitor_num, dest); - - /* The EWMH constrains workarea to be a rectangle, so it - * can't adequately deal with L-shaped monitor arrangements. - * As a workaround, we ignore the workarea for anything - * but the primary monitor. Since that is where the 'desktop - * chrome' usually lives, this works ok in practice. - */ - if (monitor_num == GDK_X11_SCREEN (screen)->primary_monitor && - !gdk_x11_screen_monitor_has_fullscreen_window (screen, monitor_num)) - { - get_work_area (screen, &workarea); - if (gdk_rectangle_intersect (dest, &workarea, &workarea)) - *dest = workarea; - } -} - -static gint -gdk_x11_screen_get_monitor_scale_factor (GdkScreen *screen, - gint monitor_num) -{ - GdkX11Screen *screen_x11 = GDK_X11_SCREEN (screen); - - return screen_x11->window_scale; -} - static GdkVisual * gdk_x11_screen_get_rgba_visual (GdkScreen *screen) { @@ -494,81 +363,52 @@ check_is_composited (GdkDisplay *display, return xwindow != None; } -static void -init_monitor_geometry (GdkX11Monitor *monitor, - int x, int y, int width, int height) -{ - monitor->geometry.x = x; - monitor->geometry.y = y; - monitor->geometry.width = width; - monitor->geometry.height = height; - - monitor->output = None; - monitor->width_mm = -1; - monitor->height_mm = -1; - monitor->output_name = NULL; - monitor->manufacturer = NULL; -} - -static void -free_monitors (GdkX11Monitor *monitors, - gint n_monitors) +static GdkX11Monitor * +find_monitor_by_output (GdkX11Display *x11_display, RROutput output) { int i; - for (i = 0; i < n_monitors; ++i) + for (i = 0; i < x11_display->monitors->len; i++) { - g_free (monitors[i].output_name); - g_free (monitors[i].manufacturer); + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + if (monitor->output == output) + return monitor; } - g_free (monitors); + return NULL; } -#ifdef HAVE_RANDR -static int -monitor_compare_function (GdkX11Monitor *monitor1, - GdkX11Monitor *monitor2) +static GdkSubpixelLayout +translate_subpixel_order (int subpixel) { - /* Sort the leftmost/topmost monitors first. - * For "cloned" monitors, sort the bigger ones first - * (giving preference to taller monitors over wider - * monitors) - */ - - if (monitor1->geometry.x != monitor2->geometry.x) - return monitor1->geometry.x - monitor2->geometry.x; - - if (monitor1->geometry.y != monitor2->geometry.y) - return monitor1->geometry.y - monitor2->geometry.y; - - if (monitor1->geometry.height != monitor2->geometry.height) - return - (monitor1->geometry.height - monitor2->geometry.height); - - if (monitor1->geometry.width != monitor2->geometry.width) - return - (monitor1->geometry.width - monitor2->geometry.width); - - return 0; + switch (subpixel) + { + case 1: return GDK_SUBPIXEL_LAYOUT_HORIZONTAL_RGB; + case 2: return GDK_SUBPIXEL_LAYOUT_HORIZONTAL_BGR; + case 3: return GDK_SUBPIXEL_LAYOUT_VERTICAL_RGB; + case 4: return GDK_SUBPIXEL_LAYOUT_VERTICAL_BGR; + case 5: return GDK_SUBPIXEL_LAYOUT_NONE; + default: return GDK_SUBPIXEL_LAYOUT_UNKNOWN; + } } -#endif static gboolean -init_randr15 (GdkScreen *screen) +init_randr15 (GdkScreen *screen, gboolean *changed) { #ifdef HAVE_RANDR15 GdkDisplay *display = gdk_screen_get_display (screen); - GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); + GdkX11Display *x11_display = GDK_X11_DISPLAY (display); GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); XRRScreenResources *resources; RROutput primary_output = None; RROutput first_output = None; int i; - GArray *monitors; gboolean randr12_compat = FALSE; XRRMonitorInfo *rr_monitors; int num_rr_monitors; + int old_primary; - if (!display_x11->have_randr15) + if (!x11_display->have_randr15) return FALSE; resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay, @@ -583,13 +423,22 @@ init_randr15 (GdkScreen *screen) if (!rr_monitors) return FALSE; - monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor), num_rr_monitors); + for (i = 0; i < x11_display->monitors->len; i++) + { + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + monitor->add = FALSE; + monitor->remove = TRUE; + } for (i = 0; i < num_rr_monitors; i++) { RROutput output = rr_monitors[i].outputs[0]; XRROutputInfo *output_info; - GdkX11Monitor monitor; + GdkX11Monitor *monitor; + GdkRectangle geometry; + GdkRectangle newgeo; + char *name; + int refresh_rate = 0; gdk_x11_display_error_trap_push (display); output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output); @@ -611,21 +460,69 @@ init_randr15 (GdkScreen *screen) if (first_output == None) first_output = output; - init_monitor_geometry (&monitor, - rr_monitors[i].x, - rr_monitors[i].y, - rr_monitors[i].width, - rr_monitors[i].height); + if (output_info->crtc) + { + XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc); + int j; + + for (j = 0; j < resources->nmode; j++) + { + XRRModeInfo *xmode = &resources->modes[j]; + if (xmode->id == crtc->mode) + { + refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal *xmode->vTotal); + break; + } + } + + XRRFreeCrtcInfo (crtc); + } + + monitor = find_monitor_by_output (x11_display, output); + if (monitor) + monitor->remove = FALSE; + else + { + monitor = g_object_new (GDK_TYPE_X11_MONITOR, + "display", display, + NULL); + monitor->output = output; + monitor->add = TRUE; + g_ptr_array_add (x11_display->monitors, monitor); + } - monitor.width_mm = rr_monitors[i].mwidth; - monitor.height_mm = rr_monitors[i].mheight; - monitor.output = output; - monitor.output_name = g_strndup (output_info->name, output_info->nameLen); + gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); + name = g_strndup (output_info->name, output_info->nameLen); + + newgeo.x = rr_monitors[i].x / x11_screen->window_scale; + newgeo.y = rr_monitors[i].y / x11_screen->window_scale; + newgeo.width = rr_monitors[i].width / x11_screen->window_scale; + newgeo.height = rr_monitors[i].height / x11_screen->window_scale; + if (newgeo.x != geometry.x || + newgeo.y != geometry.y || + newgeo.width != geometry.width || + newgeo.height != geometry.height || + rr_monitors[i].mwidth != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) || + rr_monitors[i].mheight != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) || + g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor)))) + *changed = TRUE; + + gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y); + gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height); + g_object_notify (G_OBJECT (monitor), "workarea"); + gdk_monitor_set_physical_size (GDK_MONITOR (monitor), + rr_monitors[i].mwidth, + rr_monitors[i].mheight); + gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), + translate_subpixel_order (output_info->subpixel_order)); + gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate); + gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale); + gdk_monitor_set_model (GDK_MONITOR (monitor), name); + g_free (name); if (rr_monitors[i].primary) - primary_output = monitor.output; + primary_output = monitor->output; - g_array_append_val (monitors, monitor); XRRFreeOutputInfo (output_info); } @@ -635,61 +532,82 @@ init_randr15 (GdkScreen *screen) /* non RandR 1.2+ X driver doesn't return any usable multihead data */ if (randr12_compat) { - guint n_monitors = monitors->len; - - free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE), n_monitors); + for (i = 0; i < x11_display->monitors->len; i++) + { + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + if (monitor->remove) + gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); + } + g_ptr_array_remove_range (x11_display->monitors, 0, x11_display->monitors->len); return FALSE; } - g_array_sort (monitors, (GCompareFunc) monitor_compare_function); - - x11_screen->n_monitors = monitors->len; - x11_screen->monitors = (GdkX11Monitor *) g_array_free (monitors, FALSE); - - x11_screen->primary_monitor = 0; + for (i = x11_display->monitors->len - 1; i >= 0; i--) + { + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + if (monitor->add) + { + gdk_display_monitor_added (display, GDK_MONITOR (monitor)); + *changed = TRUE; + } + else if (monitor->remove) + { + g_object_ref (monitor); + g_ptr_array_remove (x11_display->monitors, monitor); + gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); + g_object_unref (monitor); + *changed = TRUE; + } + } - for (i = 0; i < x11_screen->n_monitors; ++i) + old_primary = x11_display->primary_monitor; + x11_display->primary_monitor = 0; + for (i = 0; i < x11_display->monitors->len; ++i) { - if (x11_screen->monitors[i].output == primary_output) + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + if (monitor->output == primary_output) { - x11_screen->primary_monitor = i; + x11_display->primary_monitor = i; break; } /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */ if (primary_output == None && - g_ascii_strncasecmp (x11_screen->monitors[i].output_name, "LVDS", 4) == 0) + g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0) { - x11_screen->primary_monitor = i; + x11_display->primary_monitor = i; break; } /* No primary specified and no LVDS found */ - if (x11_screen->monitors[i].output == first_output) - x11_screen->primary_monitor = i; + if (monitor->output == first_output) + x11_display->primary_monitor = i; } - return x11_screen->n_monitors > 0; + if (x11_display->primary_monitor != old_primary) + *changed = TRUE; + + return x11_display->monitors->len > 0; #endif return FALSE; } static gboolean -init_randr13 (GdkScreen *screen) +init_randr13 (GdkScreen *screen, gboolean *changed) { #ifdef HAVE_RANDR GdkDisplay *display = gdk_screen_get_display (screen); - GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); + GdkX11Display *x11_display = GDK_X11_DISPLAY (display); GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); XRRScreenResources *resources; RROutput primary_output = None; RROutput first_output = None; int i; - GArray *monitors; gboolean randr12_compat = FALSE; + int old_primary; - if (!display_x11->have_randr13) + if (!x11_display->have_randr13) return FALSE; resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay, @@ -697,7 +615,12 @@ init_randr13 (GdkScreen *screen) if (!resources) return FALSE; - monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor), resources->noutput); + for (i = 0; i < x11_display->monitors->len; i++) + { + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + monitor->add = FALSE; + monitor->remove = TRUE; + } for (i = 0; i < resources->noutput; ++i) { @@ -716,16 +639,66 @@ init_randr13 (GdkScreen *screen) if (output_info->crtc) { - GdkX11Monitor monitor; + GdkX11Monitor *monitor; XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc); + char *name; + GdkRectangle geometry; + GdkRectangle newgeo; + int j; + int refresh_rate = 0; - init_monitor_geometry (&monitor, crtc->x, crtc->y, crtc->width, crtc->height); - monitor.output = output; - monitor.width_mm = output_info->mm_width; - monitor.height_mm = output_info->mm_height; - monitor.output_name = g_strndup (output_info->name, output_info->nameLen); + for (j = 0; j < resources->nmode; j++) + { + XRRModeInfo *xmode = &resources->modes[j]; + if (xmode->id == crtc->mode) + { + refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal *xmode->vTotal); + break; + } + } - g_array_append_val (monitors, monitor); + monitor = find_monitor_by_output (x11_display, output); + if (monitor) + monitor->remove = FALSE; + else + { + monitor = g_object_new (gdk_x11_monitor_get_type (), + "display", display, + NULL); + monitor->output = output; + monitor->add = TRUE; + g_ptr_array_add (x11_display->monitors, monitor); + } + + gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); + name = g_strndup (output_info->name, output_info->nameLen); + + newgeo.x = crtc->x / x11_screen->window_scale; + newgeo.y = crtc->y / x11_screen->window_scale; + newgeo.width = crtc->width / x11_screen->window_scale; + newgeo.height = crtc->height / x11_screen->window_scale; + if (newgeo.x != geometry.x || + newgeo.y != geometry.y || + newgeo.width != geometry.width || + newgeo.height != geometry.height || + output_info->mm_width != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) || + output_info->mm_height != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) || + g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor))) != 0) + *changed = TRUE; + + gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y); + gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height); + g_object_notify (G_OBJECT (monitor), "workarea"); + gdk_monitor_set_physical_size (GDK_MONITOR (monitor), + output_info->mm_width, + output_info->mm_height); + gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor), + translate_subpixel_order (output_info->subpixel_order)); + gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate); + gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale); + gdk_monitor_set_model (GDK_MONITOR (monitor), name); + + g_free (name); XRRFreeCrtcInfo (crtc); } @@ -738,193 +711,175 @@ init_randr13 (GdkScreen *screen) XRRFreeScreenResources (resources); - /* non RandR 1.2+ X driver doesn't return any usable multihead data */ if (randr12_compat) { - guint n_monitors = monitors->len; - - free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE), n_monitors); - + for (i = 0; i < x11_display->monitors->len; i++) + { + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + if (monitor->remove) + gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); + } + g_ptr_array_remove_range (x11_display->monitors, 0, x11_display->monitors->len); return FALSE; } - g_array_sort (monitors, (GCompareFunc) monitor_compare_function); - - x11_screen->n_monitors = monitors->len; - x11_screen->monitors = (GdkX11Monitor *)g_array_free (monitors, FALSE); - - x11_screen->primary_monitor = 0; + for (i = x11_display->monitors->len - 1; i >= 0; i--) + { + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + if (monitor->add) + { + gdk_display_monitor_added (display, GDK_MONITOR (monitor)); + *changed = TRUE; + } + else if (monitor->remove) + { + g_object_ref (monitor); + g_ptr_array_remove (x11_display->monitors, monitor); + gdk_display_monitor_removed (display, GDK_MONITOR (monitor)); + g_object_unref (monitor); + *changed = TRUE; + } + } + old_primary = x11_display->primary_monitor; + x11_display->primary_monitor = 0; primary_output = XRRGetOutputPrimary (x11_screen->xdisplay, x11_screen->xroot_window); - for (i = 0; i < x11_screen->n_monitors; ++i) + for (i = 0; i < x11_display->monitors->len; ++i) { - if (x11_screen->monitors[i].output == primary_output) + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + if (monitor->output == primary_output) { - x11_screen->primary_monitor = i; + x11_display->primary_monitor = i; break; } /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */ if (primary_output == None && - g_ascii_strncasecmp (x11_screen->monitors[i].output_name, "LVDS", 4) == 0) + g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0) { - x11_screen->primary_monitor = i; + x11_display->primary_monitor = i; break; } /* No primary specified and no LVDS found */ - if (x11_screen->monitors[i].output == first_output) - x11_screen->primary_monitor = i; + if (monitor->output == first_output) + x11_display->primary_monitor = i; } - return x11_screen->n_monitors > 0; + if (x11_display->primary_monitor != old_primary) + *changed = TRUE; + + return x11_display->monitors->len > 0; #endif return FALSE; } -void -_gdk_x11_screen_get_edge_monitors (GdkScreen *screen, - gint *top, - gint *bottom, - gint *left, - gint *right) +static void +init_no_multihead (GdkScreen *screen, gboolean *changed) { GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); - gint top_most_pos = x11_screen->height; - gint left_most_pos = x11_screen->width; - gint bottom_most_pos = 0; - gint right_most_pos = 0; - gint monitor_num; + GdkX11Display *x11_display = GDK_X11_DISPLAY (x11_screen->display); + GdkX11Monitor *monitor; + GdkRectangle geometry; + int i; - for (monitor_num = 0; monitor_num < x11_screen->n_monitors; monitor_num++) + for (i = 0; i < x11_display->monitors->len; i++) { - gint monitor_x = x11_screen->monitors[monitor_num].geometry.x; - gint monitor_y = x11_screen->monitors[monitor_num].geometry.y; - gint monitor_max_x = monitor_x + x11_screen->monitors[monitor_num].geometry.width; - gint monitor_max_y = monitor_y + x11_screen->monitors[monitor_num].geometry.height; - - if (left && left_most_pos > monitor_x) - { - left_most_pos = monitor_x; - *left = monitor_num; - } - if (right && right_most_pos < monitor_max_x) - { - right_most_pos = monitor_max_x; - *right = monitor_num; - } - if (top && top_most_pos > monitor_y) - { - top_most_pos = monitor_y; - *top = monitor_num; - } - if (bottom && bottom_most_pos < monitor_max_y) - { - bottom_most_pos = monitor_max_y; - *bottom = monitor_num; - } + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + monitor->add = FALSE; + monitor->remove = TRUE; } -} - -static void -deinit_multihead (GdkScreen *screen) -{ - GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); - - free_monitors (x11_screen->monitors, x11_screen->n_monitors); - - x11_screen->n_monitors = 0; - x11_screen->monitors = NULL; -} - -static gboolean -compare_monitor (GdkX11Monitor *m1, - GdkX11Monitor *m2) -{ - if (m1->geometry.x != m2->geometry.x || - m1->geometry.y != m2->geometry.y || - m1->geometry.width != m2->geometry.width || - m1->geometry.height != m2->geometry.height) - return FALSE; - - if (m1->width_mm != m2->width_mm || - m1->height_mm != m2->height_mm) - return FALSE; - - if (g_strcmp0 (m1->output_name, m2->output_name) != 0) - return FALSE; - if (g_strcmp0 (m1->manufacturer, m2->manufacturer) != 0) - return FALSE; - - return TRUE; -} - -static gboolean -compare_monitors (GdkX11Monitor *monitors1, gint n_monitors1, - GdkX11Monitor *monitors2, gint n_monitors2) -{ - gint i; - - if (n_monitors1 != n_monitors2) - return FALSE; - - for (i = 0; i < n_monitors1; i++) + monitor = find_monitor_by_output (x11_display, 0); + if (monitor) + monitor->remove = FALSE; + else { - if (!compare_monitor (monitors1 + i, monitors2 + i)) - return FALSE; + monitor = g_object_new (gdk_x11_monitor_get_type (), + "display", x11_display, + NULL); + monitor->output = 0; + monitor->add = TRUE; + g_ptr_array_add (x11_display->monitors, monitor); } - return TRUE; -} - -static void -init_no_multihead (GdkScreen *screen) -{ - GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); - - x11_screen->n_monitors = 1; - x11_screen->monitors = g_new0 (GdkX11Monitor, 1); - x11_screen->primary_monitor = 0; - - init_monitor_geometry (x11_screen->monitors, 0, 0, - WidthOfScreen (x11_screen->xscreen), - HeightOfScreen (x11_screen->xscreen)); + gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); + if (0 != geometry.x || + 0 != geometry.y || + gdk_screen_get_width (screen) != geometry.width || + gdk_screen_get_height (screen) != geometry.height || + gdk_screen_get_width_mm (screen) != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) || + gdk_screen_get_height_mm (screen) != gdk_monitor_get_height_mm (GDK_MONITOR (monitor))) + *changed = TRUE; + + gdk_monitor_set_position (GDK_MONITOR (monitor), 0, 0); + gdk_monitor_set_size (GDK_MONITOR (monitor), + gdk_screen_get_width (screen), + gdk_screen_get_height (screen)); + g_object_notify (G_OBJECT (monitor), "workarea"); + gdk_monitor_set_physical_size (GDK_MONITOR (monitor), + gdk_screen_get_height_mm (screen), + gdk_screen_get_height_mm (screen)); + gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale); + + if (x11_display->primary_monitor != 0) + *changed = TRUE; + x11_display->primary_monitor = 0; + + for (i = x11_display->monitors->len - 1; i >= 0; i--) + { + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + if (monitor->add) + { + gdk_display_monitor_added (GDK_DISPLAY (x11_display), GDK_MONITOR (monitor)); + *changed = TRUE; + } + else if (monitor->remove) + { + g_object_ref (monitor); + g_ptr_array_remove (x11_display->monitors, monitor); + gdk_display_monitor_removed (GDK_DISPLAY (x11_display), GDK_MONITOR (monitor)); + g_object_unref (monitor); + *changed = TRUE; + } + } } -static void +static gboolean init_multihead (GdkScreen *screen) { - if (init_randr15 (screen)) - return; + gboolean any_changed = FALSE; - if (init_randr13 (screen)) - return; + if (!init_randr15 (screen, &any_changed) && + !init_randr13 (screen, &any_changed)) + init_no_multihead (screen, &any_changed); - init_no_multihead (screen); + return any_changed; } static void update_bounding_box (GdkScreen *screen) { GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); + GdkX11Display *x11_display = GDK_X11_DISPLAY (x11_screen->display); gint i, x1, y1, x2, y2; x1 = y1 = G_MAXINT; x2 = y2 = G_MININT; - for (i = 0; i < x11_screen->n_monitors; i++) + for (i = 0; i < x11_display->monitors->len; i++) { - GdkX11Monitor *monitor; - - monitor = &x11_screen->monitors[i]; - x1 = MIN (x1, monitor->geometry.x); - y1 = MIN (y1, monitor->geometry.y); - x2 = MAX (x2, monitor->geometry.x + monitor->geometry.width); - y2 = MAX (y2, monitor->geometry.y + monitor->geometry.height); + GdkX11Monitor *monitor = x11_display->monitors->pdata[i]; + GdkRectangle geometry; + + gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry); + x1 = MIN (x1, geometry.x); + y1 = MIN (y1, geometry.y); + x2 = MAX (x2, geometry.x + geometry.width); + y2 = MAX (y2, geometry.y + geometry.height); } x11_screen->width = x2 - x1; @@ -963,9 +918,9 @@ _gdk_x11_screen_new (GdkDisplay *display, else x11_screen->window_scale = 1; - init_multihead (screen); init_randr_support (screen); - + init_multihead (screen); + _gdk_x11_screen_init_visuals (screen); _gdk_x11_screen_init_root_window (screen); update_bounding_box (screen); @@ -977,8 +932,10 @@ void _gdk_x11_screen_set_window_scale (GdkX11Screen *x11_screen, gint scale) { + GdkX11Display *x11_display = GDK_X11_DISPLAY (x11_screen->display); GList *toplevels, *l; GdkWindow *root; + int i; if (x11_screen->window_scale == scale) return; @@ -997,6 +954,13 @@ _gdk_x11_screen_set_window_scale (GdkX11Screen *x11_screen, _gdk_x11_window_set_window_scale (window, scale); } + for (i = 0; i < x11_display->monitors->len; i++) + { + GdkMonitor *monitor = GDK_MONITOR (x11_display->monitors->pdata[i]); + + gdk_monitor_set_scale_factor (monitor, scale); + } + g_signal_emit_by_name (GDK_SCREEN (x11_screen), "monitors-changed"); } @@ -1048,29 +1012,7 @@ init_randr_support (GdkScreen *screen) static void process_monitors_change (GdkScreen *screen) { - GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); - gint n_monitors; - gint primary_monitor; - GdkX11Monitor *monitors; - gboolean changed; - - primary_monitor = x11_screen->primary_monitor; - n_monitors = x11_screen->n_monitors; - monitors = x11_screen->monitors; - - x11_screen->n_monitors = 0; - x11_screen->monitors = NULL; - - init_multihead (screen); - - changed = - !compare_monitors (monitors, n_monitors, - x11_screen->monitors, x11_screen->n_monitors) || - x11_screen->primary_monitor != primary_monitor; - - free_monitors (monitors, n_monitors); - - if (changed) + if (init_multihead (screen)) { update_bounding_box (screen); g_signal_emit_by_name (screen, "monitors-changed"); @@ -1117,6 +1059,50 @@ _gdk_x11_screen_size_changed (GdkScreen *screen, } void +_gdk_x11_screen_get_edge_monitors (GdkScreen *screen, + gint *top, + gint *bottom, + gint *left, + gint *right) +{ + GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen); + gint top_most_pos = x11_screen->height; + gint left_most_pos = x11_screen->width; + gint bottom_most_pos = 0; + gint right_most_pos = 0; + gint i; + + for (i = 0; i < x11_screen->monitors->len; i++) + { + GdkMonitor *monitor = x11_screen->monitors->pdata[i]; + GdkRectangle geometry; + + gdk_monitor_get_geometry (monitor, &geometry); + + if (left && left_most_pos > geometry.x) + { + left_most_pos = geometry.x; + *left = i; + } + if (right && right_most_pos < geometry.x + geometry.width) + { + right_most_pos = geometry.x + geometry.width; + *right = i; + } + if (top && top_most_pos > geometry.y) + { + top_most_pos = geometry.y; + *top = i; + } + if (bottom && bottom_most_pos < geometry.y + geometry.height) + { + bottom_most_pos = geometry.y + geometry.height; + *bottom = i; + } + } +} + +void _gdk_x11_screen_window_manager_changed (GdkScreen *screen) { g_signal_emit (screen, signals[WINDOW_MANAGER_CHANGED], 0); @@ -1567,14 +1553,6 @@ gdk_x11_screen_class_init (GdkX11ScreenClass *klass) screen_class->get_height_mm = gdk_x11_screen_get_height_mm; screen_class->get_number = gdk_x11_screen_get_number; screen_class->get_root_window = gdk_x11_screen_get_root_window; - screen_class->get_n_monitors = gdk_x11_screen_get_n_monitors; - screen_class->get_primary_monitor = gdk_x11_screen_get_primary_monitor; - screen_class->get_monitor_width_mm = gdk_x11_screen_get_monitor_width_mm; - screen_class->get_monitor_height_mm = gdk_x11_screen_get_monitor_height_mm; - screen_class->get_monitor_plug_name = gdk_x11_screen_get_monitor_plug_name; - screen_class->get_monitor_geometry = gdk_x11_screen_get_monitor_geometry; - screen_class->get_monitor_workarea = gdk_x11_screen_get_monitor_workarea; - screen_class->get_monitor_scale_factor = gdk_x11_screen_get_monitor_scale_factor; screen_class->get_system_visual = _gdk_x11_screen_get_system_visual; screen_class->get_rgba_visual = gdk_x11_screen_get_rgba_visual; screen_class->is_composited = gdk_x11_screen_is_composited; diff --git a/gdk/x11/gdkscreen-x11.h b/gdk/x11/gdkscreen-x11.h index db827358be..3b0fb35d44 100644 --- a/gdk/x11/gdkscreen-x11.h +++ b/gdk/x11/gdkscreen-x11.h @@ -42,10 +42,6 @@ struct _GdkX11Screen Window xroot_window; GdkWindow *root_window; gint screen_num; - /* Xinerama/RandR 1.2 */ - gint n_monitors; - GdkX11Monitor *monitors; - gint primary_monitor; gint width; gint height; @@ -116,8 +112,6 @@ void _gdk_x11_screen_size_changed (GdkScreen *screen, XEvent *event); void _gdk_x11_screen_process_owner_change (GdkScreen *screen, XEvent *event); -gint _gdk_x11_screen_get_xinerama_index (GdkScreen *screen, - gint monitor_num); void _gdk_x11_screen_get_edge_monitors (GdkScreen *screen, gint *top, gint *bottom, @@ -125,6 +119,8 @@ void _gdk_x11_screen_get_edge_monitors (GdkScreen *screen, gint *right); void _gdk_x11_screen_set_window_scale (GdkX11Screen *x11_screen, int scale); +void gdk_x11_screen_get_work_area (GdkScreen *screen, + GdkRectangle *area); G_END_DECLS diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 9ed087ac54..3aa40387ec 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -4215,8 +4215,9 @@ gdk_x11_window_apply_fullscreen_mode (GdkWindow *window) /* Translate all 4 monitors from the GDK set into XINERAMA indices */ for (i = 0; i < 4; ++i) { - xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window), - gdk_monitors[i]); + /* FIXME + xclient.data.l[i] = _gdk_x11_screen_ge_xinerama_index (GDK_WINDOW_SCREEN (window), gdk_monitors[i]); */ + xclient.data.l[i] = 0; /* Sanity check, if XINERAMA is not available, we could have invalid * negative values for the XINERAMA indices. */ diff --git a/gdk/x11/gdkx.h b/gdk/x11/gdkx.h index ae05fa6b1f..1f64bccb6d 100644 --- a/gdk/x11/gdkx.h +++ b/gdk/x11/gdkx.h @@ -45,6 +45,7 @@ #include <gdk/x11/gdkx11dnd.h> #include <gdk/x11/gdkx11glcontext.h> #include <gdk/x11/gdkx11keys.h> +#include <gdk/x11/gdkx11monitor.h> #include <gdk/x11/gdkx11property.h> #include <gdk/x11/gdkx11screen.h> #include <gdk/x11/gdkx11selection.h> diff --git a/gdk/x11/gdkx11monitor.h b/gdk/x11/gdkx11monitor.h new file mode 100644 index 0000000000..98717e81a0 --- /dev/null +++ b/gdk/x11/gdkx11monitor.h @@ -0,0 +1,48 @@ +/* + * gdkx11monitor.h + * + * Copyright 2016 Red Hat, Inc. + * + * Matthias Clasen <mclasen@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GDK_X11_MONITOR_H__ +#define __GDK_X11_MONITOR_H__ + +#if !defined (__GDKX_H_INSIDE__) && !defined (GDK_COMPILATION) +#error "Only <gdk/gdkx.h> can be included directly." +#endif + +#include <gdk/gdkmonitor.h> + +G_BEGIN_DECLS + +#define GDK_TYPE_X11_MONITOR (gdk_x11_monitor_get_type ()) +#define GDK_X11_MONITOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_X11_MONITOR, GdkX11Monitor)) +#define GDK_IS_X11_MONITOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_X11_MONITOR)) + +typedef struct _GdkX11Monitor GdkX11Monitor; +typedef struct _GdkX11MonitorClass GdkX11MonitorClass; + +GDK_AVAILABLE_IN_3_22 +GType gdk_x11_monitor_get_type (void) G_GNUC_CONST; + +GDK_AVAILABLE_IN_3_22 +XID gdk_x11_monitor_get_output (GdkMonitor *monitor); + +G_END_DECLS + +#endif /* __GDK_X11_MONITOR_H__ */ |