summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorOlivier Fourdan <ofourdan@redhat.com>2020-04-16 12:58:39 +0200
committerOlivier Fourdan <ofourdan@redhat.com>2020-04-16 16:23:57 +0200
commit86f295f929f8ef05b135cfd56a72459808c65392 (patch)
treef9649ec11dd60ed8b1d1163e4c32fea3e30f1f2b /gdk
parent3d988d5fe90b9f9b5f7c136c1a7c214c6ba37c1e (diff)
downloadgtk+-86f295f929f8ef05b135cfd56a72459808c65392.tar.gz
x11: emit ::enter/leave-monitor
For the X11 backend, keep a list of monitors for which the surface intersects the monitor area. Whenever the X11 surface is configured, check against the list of monitors to determine whether it enters a new monitor or if it left a monitor, to emit the corresponding ::enter/leave-monitor signals just like a Wayland compositor would. As monitors can be added, removed or reconfigured at any time, redo those checks whenever any of these events occur.
Diffstat (limited to 'gdk')
-rw-r--r--gdk/x11/gdkdisplay-x11.c1
-rw-r--r--gdk/x11/gdkprivate-x11.h2
-rw-r--r--gdk/x11/gdksurface-x11.c101
-rw-r--r--gdk/x11/gdksurface-x11.h2
4 files changed, 106 insertions, 0 deletions
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 2857869343..7da3255687 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -990,6 +990,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
}
gdk_x11_surface_update_popups (surface);
+ gdk_x11_surface_enter_leave_monitors (surface);
}
}
break;
diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h
index 70c12159d5..667b14a142 100644
--- a/gdk/x11/gdkprivate-x11.h
+++ b/gdk/x11/gdkprivate-x11.h
@@ -217,6 +217,8 @@ void _gdk_x11_surface_register_dnd (GdkSurface *window);
void gdk_x11_surface_update_popups (GdkSurface *surface);
+void gdk_x11_surface_enter_leave_monitors (GdkSurface *surface);
+
GdkDrag * _gdk_x11_surface_drag_begin (GdkSurface *window,
GdkDevice *device,
GdkContentProvider *content,
diff --git a/gdk/x11/gdksurface-x11.c b/gdk/x11/gdksurface-x11.c
index 3607629819..01708cbc85 100644
--- a/gdk/x11/gdksurface-x11.c
+++ b/gdk/x11/gdksurface-x11.c
@@ -110,6 +110,10 @@ static void set_wm_name (GdkDisplay *display,
const gchar *name);
static void move_to_current_desktop (GdkSurface *surface);
static void gdk_x11_toplevel_state_callback (GdkSurface *surface);
+static void gdk_x11_surface_on_monitor_added (GdkSurface *surface,
+ GdkMonitor *monitor);
+static void gdk_x11_surface_on_monitor_removed (GdkSurface *surface,
+ GdkMonitor *monitor);
/* Return whether time1 is considered later than time2 as far as xserver
* time is concerned. Accounts for wraparound.
@@ -134,6 +138,7 @@ gdk_x11_surface_init (GdkX11Surface *impl)
{
impl->surface_scale = 1;
impl->frame_sync_enabled = TRUE;
+ impl->surface_is_on_monitor = NULL;
}
GdkToplevelX11 *
@@ -462,8 +467,17 @@ gdk_x11_surface_finalize (GObject *object)
_gdk_x11_display_remove_window (display, impl->xid);
if (impl->toplevel && impl->toplevel->focus_window)
_gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
+
+ g_signal_handlers_disconnect_by_func (display,
+ gdk_x11_surface_on_monitor_added,
+ GDK_SURFACE (object));
+ g_signal_handlers_disconnect_by_func (display,
+ gdk_x11_surface_on_monitor_removed,
+ GDK_SURFACE (object));
}
+ g_clear_pointer (&impl->surface_is_on_monitor, g_list_free);
+
g_free (impl->toplevel);
if (impl->cursor)
@@ -974,6 +988,13 @@ _gdk_x11_display_create_surface (GdkDisplay *display,
gdk_surface_freeze_updates (surface);
+ g_signal_connect_swapped (surface->display, "monitor-added",
+ G_CALLBACK (gdk_x11_surface_on_monitor_added),
+ surface);
+ g_signal_connect_swapped (surface->display, "monitor-removed",
+ G_CALLBACK (gdk_x11_surface_on_monitor_removed),
+ surface);
+
return surface;
}
@@ -1557,6 +1578,86 @@ gdk_x11_surface_update_popups (GdkSurface *parent)
}
}
+static void
+gdk_x11_surface_set_is_on_monitor (GdkSurface *surface,
+ GdkMonitor *monitor,
+ gboolean is_on_monitor)
+{
+ GdkX11Surface *impl = GDK_X11_SURFACE (surface);
+ GList *was_on_monitor;
+
+ was_on_monitor = g_list_find (impl->surface_is_on_monitor, monitor);
+
+ if (!was_on_monitor && is_on_monitor)
+ {
+ impl->surface_is_on_monitor = g_list_append (impl->surface_is_on_monitor,
+ monitor);
+ gdk_surface_enter_monitor (surface, monitor);
+ }
+ else if (was_on_monitor && !is_on_monitor)
+ {
+ impl->surface_is_on_monitor = g_list_remove (impl->surface_is_on_monitor,
+ monitor);
+ gdk_surface_leave_monitor (surface, monitor);
+ }
+}
+
+static void
+gdk_x11_surface_check_monitor (GdkSurface *surface,
+ GdkMonitor *monitor)
+{
+ GdkRectangle monitor_geometry;
+ GdkRectangle surface_geometry;
+ gboolean is_on_monitor;
+
+ gdk_monitor_get_geometry (monitor, &monitor_geometry);
+ gdk_surface_get_geometry (surface,
+ &surface_geometry.x,
+ &surface_geometry.y,
+ &surface_geometry.width,
+ &surface_geometry.height);
+
+ is_on_monitor = gdk_rectangle_intersect (&surface_geometry,
+ &monitor_geometry,
+ NULL);
+
+ gdk_x11_surface_set_is_on_monitor (surface, monitor, is_on_monitor);
+}
+
+void
+gdk_x11_surface_enter_leave_monitors (GdkSurface *surface)
+{
+ GdkDisplay *display = gdk_surface_get_display (surface);
+ int n_monitors, i;
+
+ n_monitors = gdk_display_get_n_monitors (display);
+ for (i = 0; i < n_monitors; i++)
+ {
+ GdkMonitor *monitor = gdk_display_get_monitor (display, i);
+ gdk_x11_surface_check_monitor (surface, monitor);
+ }
+}
+
+static void
+gdk_x11_surface_on_monitor_added (GdkSurface *surface,
+ GdkMonitor *monitor)
+{
+ gdk_x11_surface_check_monitor (surface, monitor);
+ g_signal_connect_swapped (G_OBJECT (monitor), "notify::geometry",
+ G_CALLBACK (gdk_x11_surface_check_monitor),
+ surface);
+}
+
+static void
+gdk_x11_surface_on_monitor_removed (GdkSurface *surface,
+ GdkMonitor *monitor)
+{
+ gdk_x11_surface_check_monitor (surface, monitor);
+ g_signal_handlers_disconnect_by_func (G_OBJECT (monitor),
+ gdk_x11_surface_check_monitor,
+ monitor);
+}
+
static void gdk_x11_surface_set_geometry_hints (GdkSurface *surface,
const GdkGeometry *geometry,
GdkSurfaceHints geom_mask);
diff --git a/gdk/x11/gdksurface-x11.h b/gdk/x11/gdksurface-x11.h
index 609181f59a..53abd500e5 100644
--- a/gdk/x11/gdksurface-x11.h
+++ b/gdk/x11/gdksurface-x11.h
@@ -80,6 +80,8 @@ struct _GdkX11Surface
int abs_y;
guint64 map_time;
+
+ GList *surface_is_on_monitor;
};
struct _GdkX11SurfaceClass