From d8bc318151aa81cbf572d55034ffab250dc8a9e9 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Sat, 14 Dec 2002 05:27:23 +0000 Subject: [PATCH] gdk/gdkscreen.c (gdk_screen_get_monitor_at_point) Provide a useful Fri Dec 13 23:58:06 2002 Owen Taylor * gdk/gdkscreen.c (gdk_screen_get_monitor_at_point) * gdk/gdkscreen.c (gdk_screen_get_monitor_at_window): Provide a useful fallback on failure - return a monitor close to the point or window. (#79991) * gtk/gtkmenu.c (gtk_menu_position): Remove a now unneeded check for failure of gdk_screen_get_monitor_at_point() --- gdk/gdkscreen.c | 72 ++++++++++++++++++++++++++++++++++++++++++------- gtk/gtkmenu.c | 2 -- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/gdk/gdkscreen.c b/gdk/gdkscreen.c index f7160ecbc..114dc49df 100644 --- a/gdk/gdkscreen.c +++ b/gdk/gdkscreen.c @@ -90,6 +90,53 @@ _gdk_screen_close (GdkScreen *screen) } } +/* Fallback used when the monitor "at" a point or window + * doesn't exist. + */ +static gint +get_nearest_monitor (GdkScreen *screen, + gint x, + gint y) +{ + gint num_monitors, i; + gint nearest_dist = G_MAXINT; + gint nearest_monitor = 0; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), -1); + + num_monitors = gdk_screen_get_n_monitors (screen); + + for (i = 0; i < num_monitors; i++) + { + GdkRectangle monitor; + gint dist_x, dist_y; + + gdk_screen_get_monitor_geometry (screen, i, &monitor); + + if (x < monitor.x) + dist_x = monitor.x - x; + else if (x >= monitor.x + monitor.width) + dist_x = x - (monitor.x + monitor.width) + 1; + else + dist_x = 0; + + if (y < monitor.y) + dist_y = monitor.y - y; + else if (y >= monitor.y + monitor.height) + dist_y = y - (monitor.y + monitor.height) + 1; + else + dist_y = 0; + + if (MIN (dist_x, dist_y) < nearest_dist) + { + nearest_dist = MIN (dist_x, dist_y); + nearest_monitor = i; + } + } + + return nearest_monitor; +} + /** * gdk_screen_get_monitor_at_point: * @screen: a #GdkScreen. @@ -98,8 +145,8 @@ _gdk_screen_close (GdkScreen *screen) * * Returns the monitor number in which the point (@x,@y) is located. * - * Returns: the monitor number in which the point (@x,@y) belong, or - * -1 if the point is not in any monitor. + * Returns: the monitor number in which the point (@x,@y) lies, or + * a monitor close to (@x,@y) if the point is not in any monitor. * * Since: 2.2 **/ @@ -127,17 +174,19 @@ gdk_screen_get_monitor_at_point (GdkScreen *screen, return i; } - return -1; + return get_nearest_monitor (screen, x, y); } /** * gdk_screen_get_monitor_at_window: * @screen: a #GdkScreen. * @window: a #GdkWindow - * @returns: the monitor number in which most of @window is located. + * @returns: the monitor number in which most of @window is located, + * or if @window does not intersect any monitors, a monitor, + * close to @window. * * Returns the number of the monitor in which the largest area of the - * bounding rectangle of @window resides. + * bounding rectangle of @window resides. * * Since: 2.2 **/ @@ -145,7 +194,7 @@ gint gdk_screen_get_monitor_at_window (GdkScreen *screen, GdkWindow *window) { - gint num_monitors, i, sum = 0, screen_num = 0; + gint num_monitors, i, area = 0, screen_num = -1; GdkRectangle win_rect; g_return_val_if_fail (GDK_IS_SCREEN (screen), -1); @@ -161,13 +210,18 @@ gdk_screen_get_monitor_at_window (GdkScreen *screen, gdk_screen_get_monitor_geometry (screen, i, &tmp_monitor); gdk_rectangle_intersect (&win_rect, &tmp_monitor, &intersect); - if (intersect.width * intersect.height > sum) + if (intersect.width * intersect.height > area) { - sum = intersect.width * intersect.height; + area = intersect.width * intersect.height; screen_num = i; } } - return screen_num; + if (screen_num >= 0) + return screen_num; + else + return get_nearest_monitor (screen, + win_rect.x + win_rect.width / 2, + win_rect.y + win_rect.height / 2); } /** diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index 3e93a8e5c..0af02b613 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -2607,8 +2607,6 @@ gtk_menu_position (GtkMenu *menu) screen = gtk_widget_get_screen (widget); monitor_num = gdk_screen_get_monitor_at_point (screen, x, y); - if (monitor_num < 0) - monitor_num = 0; gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); /* We need the requisition to figure out the right place to