[RFC 2/2] window: Use wl_probe_visible when positioning menus
Jonas Ådahl
jadahl at gmail.com
Wed Sep 30 23:51:46 PDT 2015
To avoid positioning the menu offscreen, probe the visibility of the
intended rectangle and adapt it before showing the popup. This patch is
based by a patch[0] by Rob Bradford from 2013.
[0] http://lists.freedesktop.org/archives/wayland-devel/2013-April/008667.html
Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
---
Makefile.am | 2 ++
clients/window.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+)
diff --git a/Makefile.am b/Makefile.am
index 00f3ad2..71a5763 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -553,6 +553,8 @@ nodist_libtoytoolkit_la_SOURCES = \
protocol/workspaces-client-protocol.h \
protocol/presentation_timing-protocol.c \
protocol/presentation_timing-client-protocol.h \
+ protocol/probe-visible-protocol.c \
+ protocol/probe-visible-client-protocol.h \
protocol/xdg-shell-protocol.c \
protocol/xdg-shell-client-protocol.h \
protocol/ivi-application-protocol.c \
diff --git a/clients/window.c b/clients/window.c
index 47a79aa..ab561a4 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -71,6 +71,7 @@ typedef void *EGLContext;
#include "xdg-shell-client-protocol.h"
#include "text-cursor-position-client-protocol.h"
#include "workspaces-client-protocol.h"
+#include "probe-visible-client-protocol.h"
#include "shared/os-compatibility.h"
#include "window.h"
@@ -99,6 +100,7 @@ struct display {
struct workspace_manager *workspace_manager;
struct xdg_shell *xdg_shell;
struct ivi_application *ivi_application; /* ivi style shell */
+ struct _wl_probe_visible *probe_visible;
EGLDisplay dpy;
EGLConfig argb_config;
EGLContext argb_ctx;
@@ -401,6 +403,8 @@ struct menu {
int count;
int release_count;
menu_func_t func;
+ int width;
+ int height;
};
struct tooltip {
@@ -4813,6 +4817,46 @@ static const struct xdg_popup_listener xdg_popup_listener = {
handle_popup_popup_done,
};
+static void
+probe_visible_visible_rectangle (void *data,
+ struct _wl_probe_visible_result *result,
+ int32_t x, int32_t y,
+ int32_t w, int32_t h)
+{
+ struct menu *menu = data;
+ struct window *window = menu->window;
+
+ /* Clipped to the left */
+ if (x != window->x)
+ window->x = x;
+ /* Clipped to the right */
+ else if (x == window->x && w < menu->width)
+ window->x = window->x - (menu->width - w);
+ /* Spans the output ? */
+ else {
+ window->x = x;
+ menu->width = w;
+ }
+
+ /* Clipped to the top */
+ if (y != window->y)
+ window->y = y;
+ /* Clipped to the bottom */
+ else if (y == window->y && h < menu->height)
+ window->y = y - (menu->height - h);
+ /* Spans the output */
+ else {
+ window->y = y;
+ menu->height = h;
+ }
+
+ _wl_probe_visible_result_destroy(result);
+}
+
+struct _wl_probe_visible_result_listener probe_result_listener = {
+ probe_visible_visible_rectangle,
+};
+
static struct menu *
create_menu(struct display *display,
struct input *input, uint32_t time,
@@ -4888,6 +4932,8 @@ window_show_menu(struct display *display,
struct menu *menu;
struct window *window;
int32_t ix, iy;
+ struct _wl_probe_visible_result *result;
+ int margin;
menu = create_menu(display, input, time, func, entries, count, parent);
@@ -4901,12 +4947,23 @@ window_show_menu(struct display *display,
window->x = x;
window->y = y;
+ margin = window_get_shadow_margin(window);
+ menu->width = 200;
+ menu->height = menu->count * 20 + margin * 2;
frame_interior(menu->frame, &ix, &iy, NULL, NULL);
if (!display->xdg_shell)
return;
+ result = _wl_probe_visible_probe_rectangle(display->probe_visible,
+ parent->main_surface->surface,
+ window->x, window->y,
+ menu->width, menu->height);
+
+ _wl_probe_visible_result_add_listener(result, &probe_result_listener, menu);
+ wl_display_roundtrip(display->display);
+
window->xdg_popup = xdg_shell_get_xdg_popup(display->xdg_shell,
window->main_surface->surface,
parent->main_surface->surface,
@@ -5378,6 +5435,10 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
d->ivi_application =
wl_registry_bind(registry, id,
&ivi_application_interface, 1);
+ } else if (strcmp(interface, "_wl_probe_visible") == 0) {
+ d->probe_visible =
+ wl_registry_bind(registry, id,
+ &_wl_probe_visible_interface, 1);
}
if (d->global_handler)
--
2.4.3
More information about the wayland-devel
mailing list