[PATCH 2/2] window: Use probe area to position popup window so it always visible

Rob Bradford robert.bradford at intel.com
Mon Jan 28 09:19:27 PST 2013


From: Rob Bradford <rob at linux.intel.com>

With this change the popup menu will not go beyond the borders of the output.
---
 clients/window.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 50 insertions(+), 8 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index 2baf4d9..28d0bd6 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -359,6 +359,8 @@ struct menu {
 	int count;
 	int release_count;
 	menu_func_t func;
+	int width;
+	int height;
 };
 
 struct tooltip {
@@ -3747,6 +3749,46 @@ menu_redraw_handler(struct widget *widget, void *data)
 	cairo_destroy(cr);
 }
 
+static void
+probe_result_visible_area (void *data,
+			   struct wl_probe_result *wl_probe_result,
+			   int32_t x, int32_t y,
+			   int32_t w, int32_t h)
+{
+	struct menu *menu = data;
+	struct window *window = menu->window;
+	struct input *input = menu->input;
+
+	/* Clipped to the left */
+	if (x != window->x)
+		window->x = x;
+
+	/* Clipped to the top */
+	if (y != window->y)
+		window->y = y;
+
+	/* Clipped to the right */
+	if (x == window->x && w < menu->width)
+		window->x = window->x - (menu->width - w);
+
+	/* Clipped to the bottom */
+	if (y == window->y && h < menu->height)
+		window->y = y - (menu->height - h);
+
+	input_ungrab(input);
+	wl_shell_surface_set_popup(window->shell_surface, input->seat,
+				   display_get_serial(window->display),
+				   window->parent->surface,
+				   window->x, window->y, 0);
+
+	input_grab(input, menu->widget, 0);
+	window_schedule_resize(window, menu->width, menu->height);
+}
+
+struct wl_probe_result_listener probe_result_listener = {
+    probe_result_visible_area,
+};
+
 void
 window_show_menu(struct display *display,
 		 struct input *input, uint32_t time, struct window *parent,
@@ -3756,6 +3798,7 @@ window_show_menu(struct display *display,
 	struct window *window;
 	struct menu *menu;
 	const int32_t margin = 3;
+	struct wl_probe_result *result;
 
 	menu = malloc(sizeof *menu);
 	if (!menu)
@@ -3776,24 +3819,23 @@ window_show_menu(struct display *display,
 	menu->time = time;
 	menu->func = func;
 	menu->input = input;
+	menu->width = 200;
+	menu->height = menu->count * 20 + margin * 2;
 	window->type = TYPE_MENU;
 	window->x = x;
 	window->y = y;
 
-	input_ungrab(input);
-	wl_shell_surface_set_popup(window->shell_surface, input->seat,
-				   display_get_serial(window->display),
-				   window->parent->surface,
-				   window->x, window->y, 0);
-
 	widget_set_redraw_handler(menu->widget, menu_redraw_handler);
 	widget_set_enter_handler(menu->widget, menu_enter_handler);
 	widget_set_leave_handler(menu->widget, menu_leave_handler);
 	widget_set_motion_handler(menu->widget, menu_motion_handler);
 	widget_set_button_handler(menu->widget, menu_button_handler);
 
-	input_grab(input, menu->widget, 0);
-	window_schedule_resize(window, 200, count * 20 + margin * 2);
+	result = wl_shell_surface_probe_area(window->parent->shell_surface,
+					     window->x, window->y,
+					     menu->width, menu->height);
+
+	wl_probe_result_add_listener(result, &probe_result_listener, menu);
 }
 
 void
-- 
1.8.0.2



More information about the wayland-devel mailing list