[PATCH 2/2] window: Use probing mechanism to position popup so it is always visible

Rob Bradford rob at robster.org.uk
Wed Feb 29 11:15:21 PST 2012


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

---
 clients/window.c |   65 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 57 insertions(+), 8 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index 04692c0..5fda221 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -141,6 +141,11 @@ struct window {
 
 	void *user_data;
 	struct wl_list link;
+
+	/* Used for probing */
+	int requested_w, requested_h;
+	struct window *popup_window;
+	uint32_t popup_time;
 };
 
 struct widget {
@@ -2146,9 +2151,49 @@ handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
 	menu_destroy(menu);
 }
 
+static void
+handle_visible_area(void *data, struct wl_shell_surface *shell_surface,
+		    int x, int y, int w, int h)
+{
+	/* The event gets called on the toplevel window not the child surface
+	 * so we must store that on the toplevel and retrieve it. Yuk?
+	 */
+	struct window *toplevel_window = data;
+	struct window *window = toplevel_window->popup_window;
+
+	struct menu *menu = window->widget->user_data;
+
+	fprintf (stderr, "Got area %d %d %d %d on %p for %p\n",
+		 x, y, w, h, toplevel_window, window);
+
+	/* 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 < window->requested_w)
+		window->x = window->x - (window->requested_w - w);
+
+	/* Clipped to the bottom */
+	if (y == window->y && h < window->requested_h)
+		window->y = y - (window->requested_h - h);
+
+	wl_shell_surface_set_popup(window->shell_surface,
+				   menu->input->input_device, window->popup_time,
+				   window->parent->shell_surface,
+				   window->x, window->y, 0);
+	input_grab(menu->input, menu->widget, 0);
+	window_schedule_resize(window, window->requested_w, window->requested_h);
+}
+
 static const struct wl_shell_surface_listener shell_surface_listener = {
 	handle_configure,
-	handle_popup_done
+	handle_popup_done,
+	handle_visible_area,
 };
 
 void
@@ -2543,19 +2588,23 @@ window_show_menu(struct display *display,
 	window->x = x;
 	window->y = y;
 
-	wl_shell_surface_set_popup(window->shell_surface,
-				   input->input_device, time,
-				   window->parent->shell_surface,
-				   window->x, window->y, 0);
+
+	window->requested_w = 200;
+	window->requested_h = count * 20 + margin * 2;
+	window->parent->popup_window = window;
+	wl_shell_surface_probe_area (window->parent->shell_surface,
+				     window->x, window->y,
+				     window->requested_w, window->requested_h);
+	fprintf (stderr, "Probing %d %d %d %d for %p on %p\n",
+		 window->x, window->y,
+		 window->requested_w, window->requested_h,
+		 window, window->parent);
 
 	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);
 }
 
 void
-- 
1.7.7.6



More information about the wayland-devel mailing list