diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2011-12-05 09:40:43 -0500 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2011-12-07 10:13:05 -0500 |
commit | 9ed7635ed78218771e71f1a12da7487243639d73 (patch) | |
tree | 39a7d46c0350033ab29be3f22f083baff5492e2d | |
parent | 7172d9e22d49507db158994129672772f4a60a46 (diff) |
menumenu
-rw-r--r-- | clients/resizor.c | 11 | ||||
-rw-r--r-- | clients/window.c | 152 | ||||
-rw-r--r-- | clients/window.h | 3 | ||||
-rw-r--r-- | compositor/compositor.c | 215 | ||||
-rw-r--r-- | compositor/compositor.h | 14 | ||||
-rw-r--r-- | compositor/data-device.c | 88 | ||||
-rw-r--r-- | compositor/shell.c | 219 |
7 files changed, 565 insertions, 137 deletions
diff --git a/clients/resizor.c b/clients/resizor.c index c3d0327a..fa55f97c 100644 --- a/clients/resizor.c +++ b/clients/resizor.c @@ -159,12 +159,11 @@ show_menu(struct resizor *resizor, struct input *input) int32_t x, y, width = 200, height = 200; input_get_position(input, &x, &y); - resizor->menu = window_create_transient(resizor->display, - resizor->window, - x - 10, y - 10, width, height); + resizor->menu = window_create_menu(resizor->display, + resizor->window, + x - 10, y - 10, width, height); - window_draw(resizor->menu); - window_flush(resizor->menu); + window_schedule_redraw(resizor->menu); } static void @@ -178,8 +177,6 @@ button_handler(struct window *window, case 274: if (state) show_menu(resizor, input); - else - window_destroy(resizor->menu); break; } } diff --git a/clients/window.c b/clients/window.c index e0693da1..be62d1f4 100644 --- a/clients/window.c +++ b/clients/window.c @@ -96,6 +96,7 @@ enum { TYPE_TOPLEVEL, TYPE_FULLSCREEN, TYPE_TRANSIENT, + TYPE_MENU, TYPE_CUSTOM }; @@ -765,6 +766,8 @@ window_set_type(struct window *window) window->parent->shell_surface, window->x, window->y, 0); break; + case TYPE_MENU: + break; case TYPE_CUSTOM: break; } @@ -923,28 +926,6 @@ window_create_surface(struct window *window) } static void -window_draw_menu(struct window *window) -{ - cairo_t *cr; - int width, height, r = 5; - - window_create_surface(window); - - cr = cairo_create(window->cairo_surface); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); - cairo_paint(cr); - - width = window->allocation.width; - height = window->allocation.height; - rounded_rect(cr, r, r, width - r, height - r, r); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); - cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 0.5); - cairo_fill(cr); - cairo_destroy(cr); -} - -static void window_draw_decorations(struct window *window) { cairo_t *cr; @@ -1088,9 +1069,7 @@ item_get_user_data(struct item *item) void window_draw(struct window *window) { - if (window->parent) - window_draw_menu(window); - else if (!window->decoration) + if (!window->decoration) window_create_surface(window); else window_draw_decorations(window); @@ -1738,8 +1717,17 @@ handle_configure(void *data, struct wl_shell_surface *shell_surface, } } +static void +handle_menu_done(void *data, struct wl_shell_surface *shell_surface) +{ + struct window *window = data; + + window_destroy(window); +} + static const struct wl_shell_surface_listener shell_surface_listener = { handle_configure, + handle_menu_done }; void @@ -2044,6 +2032,120 @@ window_create_transient(struct display *display, struct window *parent, return window; } +struct menu { + int current; + int count; +}; + +static int +menu_motion_handler(struct window *window, + struct input *input, uint32_t time, + int32_t x, int32_t y, + int32_t sx, int32_t sy, void *data) +{ + struct menu *menu = data; + int next; + + next = (sy - 8) / 20; + if (menu->current != next) { + menu->current = next; + window_schedule_redraw(window); + } + + return POINTER_LEFT_PTR; +} + +static void +menu_button_handler(struct window *window, + struct input *input, uint32_t time, + int button, int state, void *data) + +{ + struct menu *menu = data; + + fprintf(stderr, "menu_redraw_handler\n"); + + /* Either relase after press-drag-release or click-motion-click. */ + if (state == 0 && 0 <= menu->current && menu->current < menu->count) + window_destroy(window); +} + +static void +menu_redraw_handler(struct window *window, void *data) +{ + cairo_t *cr; + int width, height, r = 5, i; + struct menu *menu = data; + static const char *entries[] = { + "Roy", "Pris", "Leon", "Zhora" + }; + + window_create_surface(window); + + cr = cairo_create(window->cairo_surface); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); + cairo_paint(cr); + + width = window->allocation.width; + height = window->allocation.height; + rounded_rect(cr, r, r, width - r, height - r, r); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 0.5); + cairo_fill(cr); + + for (i = 0; i < ARRAY_LENGTH(entries); i++) { + if (i == menu->current) { + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_rectangle(cr, 0, i * 20 + 8, width, 20); + cairo_fill(cr); + cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); + cairo_move_to(cr, 10, i * 20 + 20); + cairo_show_text(cr, entries[i]); + } else { + cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); + cairo_move_to(cr, 10, i * 20 + 20); + cairo_show_text(cr, entries[i]); + } + } + + cairo_destroy(cr); + window_flush(window); +} + +struct window * +window_create_menu(struct display *display, struct window *parent, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + struct window *window; + struct menu *menu; + + window = window_create_internal(parent->display, + parent, width, height); + if (!window) + return NULL; + menu = malloc(sizeof *menu); + if (!menu) + return NULL; + + menu->count = 4; + window->decoration = 0; + window->type = TYPE_MENU; + window->x = x; + window->y = y; + + wl_shell_surface_set_menu(window->shell_surface, + window->parent->shell_surface, + window->x, window->y, 0); + + window_set_motion_handler(window, menu_motion_handler); + window_set_button_handler(window, menu_button_handler); + window_set_redraw_handler(window, menu_redraw_handler); + window_set_user_data(window, menu); + + return window; +} + void window_set_buffer_type(struct window *window, enum window_buffer_type type) { diff --git a/clients/window.h b/clients/window.h index 8d17340f..63b16e5d 100644 --- a/clients/window.h +++ b/clients/window.h @@ -177,6 +177,9 @@ window_create(struct display *display, int32_t width, int32_t height); struct window * window_create_transient(struct display *display, struct window *parent, int32_t x, int32_t y, int32_t width, int32_t height); +struct window * +window_create_menu(struct display *display, struct window *parent, + int32_t x, int32_t y, int32_t width, int32_t height); void window_destroy(struct window *window); diff --git a/compositor/compositor.c b/compositor/compositor.c index 2c04c3b4..33b896a6 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -242,28 +242,41 @@ wlsc_compositor_get_time(void) } WL_EXPORT void +wlsc_device_repick(struct wl_input_device *device, uint32_t time) +{ + const struct wl_grab_interface *interface; + struct wlsc_surface *surface; + int32_t x, y; + + surface = pick_surface(device, &x, &y); + if (&surface->surface == device->grab->focus) + return; + + interface = device->grab->interface; + if (device->grab->focus) { + interface->leave(device->grab, time, device->grab->focus); + device->grab->focus = NULL; + } + + interface = device->grab->interface; + if (surface) { + interface->enter(device->grab, time, &surface->surface, x, y); + device->grab->focus = &surface->surface; + } +} + +WL_EXPORT void wlsc_compositor_repick(struct wlsc_compositor *compositor) { struct wlsc_input_device *device; - struct wlsc_surface *surface; - int32_t sx, sy; uint32_t time; if (!compositor->focus) return; time = wlsc_compositor_get_time(); - wl_list_for_each(device, &compositor->input_device_list, link) { - if (device->input_device.grab) - continue; - surface = pick_surface(&device->input_device, &sx, &sy); - wl_input_device_set_pointer_focus(&device->input_device, - &surface->surface, - time, - device->input_device.x, - device->input_device.y, - sx, sy); - } + wl_list_for_each(device, &compositor->input_device_list, link) + wlsc_device_repick(&device->input_device, time); } static void @@ -1146,7 +1159,7 @@ const static struct wl_compositor_interface compositor_interface = { compositor_create_surface, }; -static void +WL_EXPORT void wlsc_surface_transform(struct wlsc_surface *surface, int32_t x, int32_t y, int32_t *sx, int32_t *sy) { @@ -1173,10 +1186,56 @@ pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy) return NULL; } +static void +default_grab_enter(struct wl_grab *grab, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y) +{ + struct wl_input_device *device = grab->input_device; + struct wl_resource *resource; + + wl_list_for_each(resource, &device->resource_list, link) { + if (resource->client == surface->resource.client) + break; + } + + if (&resource->link != &device->resource_list) { + wl_resource_post_event(resource, + WL_INPUT_DEVICE_POINTER_FOCUS, + time, surface, + device->x, device->y, x, y); + wl_list_insert(resource->destroy_listener_list.prev, + &device->pointer_focus_listener.link); + + device->pointer_focus_resource = resource; + } else { + device->pointer_focus_resource = NULL; + } + + device->pointer_focus = surface; + device->pointer_focus_time = time; +} + +static void +default_grab_leave(struct wl_grab *grab, + uint32_t time, struct wl_surface *surface) +{ + struct wl_input_device *device = grab->input_device; + + if (device->pointer_focus_resource) { + wl_resource_post_event(device->pointer_focus_resource, + WL_INPUT_DEVICE_POINTER_FOCUS, + time, NULL, 0, 0, 0, 0); + wl_list_remove(&device->pointer_focus_listener.link); + } + + device->pointer_focus_resource = NULL; + device->pointer_focus = NULL; +} static void -implicit_grab_motion(struct wl_grab *grab, - uint32_t time, int32_t x, int32_t y) +default_grab_motion(struct wl_grab *grab, + uint32_t time, int32_t x, int32_t y) { struct wlsc_input_device *device = (struct wlsc_input_device *) grab->input_device; @@ -1194,8 +1253,8 @@ implicit_grab_motion(struct wl_grab *grab, } static void -implicit_grab_button(struct wl_grab *grab, - uint32_t time, int32_t button, int32_t state) +default_grab_button(struct wl_grab *grab, + uint32_t time, int32_t button, int32_t state) { struct wl_resource *resource; @@ -1206,16 +1265,90 @@ implicit_grab_button(struct wl_grab *grab, } static void -implicit_grab_end(struct wl_grab *grab, uint32_t time) +default_grab_end(struct wl_grab *grab, uint32_t time) +{ +} + +static const struct wl_grab_interface default_grab_interface = { + default_grab_enter, + default_grab_leave, + default_grab_motion, + default_grab_button, + default_grab_end +}; + +static void +implicit_grab_enter(struct wl_grab *grab, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y) +{ +} + +static void +implicit_grab_leave(struct wl_grab *grab, + uint32_t time, struct wl_surface *surface) { } static const struct wl_grab_interface implicit_grab_interface = { - implicit_grab_motion, - implicit_grab_button, - implicit_grab_end + implicit_grab_enter, + implicit_grab_leave, + default_grab_motion, + default_grab_button, + default_grab_end }; +WL_EXPORT int +wlsc_input_device_update_grab(struct wl_input_device *device, + struct wl_grab *grab, + struct wl_surface *surface, uint32_t time) +{ + const struct wl_grab_interface *interface; + int32_t x, y; + +#if 0 + if (device->grab != &device->implicit_grab || + device->grab_time != time || + device->pointer_focus != surface) + return -1; +#endif + + interface = device->grab->interface; + if (device->default_grab.focus) + default_grab_leave(device->grab, time, + device->default_grab.focus); + + device->grab = grab; + interface = device->grab->interface; + grab->input_device = device; + grab->focus = (struct wl_surface *) pick_surface(device, &x, &y); + if (grab->focus) + interface->enter(device->grab, time, grab->focus, x, y); + + return 0; +} + +WL_EXPORT void +wlsc_input_device_end_grab(struct wl_input_device *device, uint32_t time) +{ + const struct wl_grab_interface *interface; + int32_t x, y; + + interface = device->grab->interface; + if (device->grab->focus) + interface->leave(device->grab, time, device->grab->focus); + interface->end(device->grab, time); + + device->grab = &device->default_grab; + device->grab->focus = + (struct wl_surface *) pick_surface(device, &x, &y); + if (device->grab->focus) + default_grab_enter(device->grab, + time, device->grab->focus, x, y); + + wl_list_remove(&device->grab_listener.link); +} + WL_EXPORT void wlsc_compositor_wake(struct wlsc_compositor *compositor) { @@ -1266,12 +1399,10 @@ idle_handler(void *data) WL_EXPORT void notify_motion(struct wl_input_device *device, uint32_t time, int x, int y) { - struct wlsc_surface *es; struct wlsc_output *output; const struct wl_grab_interface *interface; struct wlsc_input_device *wd = (struct wlsc_input_device *) device; struct wlsc_compositor *ec = wd->compositor; - int32_t sx, sy; int x_valid = 0, y_valid = 0; int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN; @@ -1312,19 +1443,9 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y) device->x = x; device->y = y; - if (device->grab) { - interface = device->grab->interface; - interface->motion(device->grab, time, x, y); - } else { - es = pick_surface(device, &sx, &sy); - wl_input_device_set_pointer_focus(device, - &es->surface, - time, x, y, sx, sy); - if (device->pointer_focus_resource) - wl_resource_post_event(device->pointer_focus_resource, - WL_INPUT_DEVICE_MOTION, - time, x, y, sx, sy); - } + wlsc_device_repick(device, time); + interface = device->grab->interface; + interface->motion(device->grab, time, x, y); wlsc_surface_damage_below(wd->sprite); @@ -1362,14 +1483,13 @@ notify_button(struct wl_input_device *device, struct wlsc_binding *b; struct wlsc_surface *surface = (struct wlsc_surface *) device->pointer_focus; - int32_t sx, sy; if (state) wlsc_compositor_idle_inhibit(compositor); else wlsc_compositor_idle_release(compositor); - if (state && surface && device->grab == NULL) { + if (state && surface && device->grab == &device->default_grab) { compositor->shell->activate(compositor->shell, surface, wd, time); wl_input_device_start_grab(device, @@ -1386,17 +1506,10 @@ notify_button(struct wl_input_device *device, } } - if (device->grab) - device->grab->interface->button(device->grab, time, - button, state); + device->grab->interface->button(device->grab, time, button, state); - if (!state && device->grab && device->grab_button == button) { - wl_input_device_end_grab(device, time); - surface = pick_surface(device, &sx, &sy); - wl_input_device_set_pointer_focus(device, &surface->surface, - time, device->x, device->y, - sx, sy); - } + if (!state && device->grab && device->grab_button == button) + wlsc_input_device_end_grab(device, time); } static void @@ -1653,7 +1766,11 @@ wlsc_input_device_init(struct wlsc_input_device *device, device->hotspot_y = 16; device->modifier_state = 0; + device->input_device.default_grab.interface = &default_grab_interface; + device->input_device.default_grab.input_device = &device->input_device; device->input_device.implicit_grab.interface = &implicit_grab_interface; + device->input_device.grab = &device->input_device.default_grab; + wl_list_insert(ec->input_device_list.prev, &device->link); diff --git a/compositor/compositor.h b/compositor/compositor.h index 1d551584..62c93cf0 100644 --- a/compositor/compositor.h +++ b/compositor/compositor.h @@ -124,10 +124,10 @@ struct wlsc_input_device { struct wl_surface *drag_focus; struct wl_resource *drag_focus_resource; struct wl_listener drag_focus_listener; + struct wl_grab drag_grab; struct wlsc_data_source *selection_data_source; struct wl_listener selection_data_source_listener; - struct wl_grab grab; }; enum wlsc_visual { @@ -292,6 +292,9 @@ wlsc_surface_activate(struct wlsc_surface *surface, struct wlsc_input_device *device, uint32_t time); void +wlsc_surface_transform(struct wlsc_surface *surface, + int32_t x, int32_t y, int32_t *sx, int32_t *sy); +void notify_motion(struct wl_input_device *device, uint32_t time, int x, int y); void @@ -368,6 +371,15 @@ wlsc_surface_damage_rectangle(struct wlsc_surface *surface, void wlsc_input_device_set_pointer_image(struct wlsc_input_device *device, enum wlsc_pointer_type type); +void +wlsc_device_repick(struct wl_input_device *device, uint32_t time); + +int +wlsc_input_device_update_grab(struct wl_input_device *device, + struct wl_grab *grab, + struct wl_surface *surface, uint32_t time); +void +wlsc_input_device_end_grab(struct wl_input_device *device, uint32_t time); struct wlsc_surface * pick_surface(struct wl_input_device *device, int32_t *sx, int32_t *sy); diff --git a/compositor/data-device.c b/compositor/data-device.c index c39465f0..f42441f7 100644 --- a/compositor/data-device.c +++ b/compositor/data-device.c @@ -167,27 +167,20 @@ destroy_drag_focus(struct wl_listener *listener, } static void -drag_set_focus(struct wlsc_input_device *device, - struct wl_surface *surface, uint32_t time, - int32_t x, int32_t y) +drag_grab_enter(struct wl_grab *grab, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y) { + struct wlsc_input_device *device = + container_of(grab, struct wlsc_input_device, drag_grab); struct wl_resource *resource, *offer; - if (device->drag_focus == surface) - return; - - if (device->drag_focus_resource) { - wl_resource_post_event(device->drag_focus_resource, - WL_DATA_DEVICE_LEAVE); - wl_list_remove(&device->drag_focus_listener.link); - device->drag_focus_resource = NULL; - device->drag_focus = NULL; - } + resource = find_resource(&device->drag_resource_list, + surface->resource.client); + fprintf(stderr, "drag enter, resource %p, id %d\n", + resource, resource ? resource->object.id : 0); - if (surface) - resource = find_resource(&device->drag_resource_list, - surface->resource.client); - if (surface && resource) { + if (resource) { offer = wlsc_data_source_send_offer(device->drag_data_source, resource); @@ -204,43 +197,65 @@ drag_set_focus(struct wlsc_input_device *device, } static void +drag_grab_leave(struct wl_grab *grab, + uint32_t time, struct wl_surface *surface) +{ + struct wlsc_input_device *device = + container_of(grab, struct wlsc_input_device, drag_grab); + + if (device->drag_focus_resource) { + wl_resource_post_event(device->drag_focus_resource, + WL_DATA_DEVICE_LEAVE); + wl_list_remove(&device->drag_focus_listener.link); + device->drag_focus_resource = NULL; + device->drag_focus = NULL; + } +} + +static void drag_grab_motion(struct wl_grab *grab, uint32_t time, int32_t x, int32_t y) { struct wlsc_input_device *device = - container_of(grab, struct wlsc_input_device, grab); + container_of(grab, struct wlsc_input_device, drag_grab); struct wlsc_surface *es; + int32_t sx, sy; - es = pick_surface(&device->input_device, &x, &y); - drag_set_focus(device, &es->surface, time, x, y); + if (device->drag_focus_resource) { + es = (struct wlsc_surface *) grab->focus; + wlsc_surface_transform(es, x, y, &sx, &sy); - if (es && device->drag_focus_resource) wl_resource_post_event(device->drag_focus_resource, - WL_DATA_DEVICE_MOTION, time, x, y); + WL_DATA_DEVICE_MOTION, time, sx, sy); + } } static void drag_grab_button(struct wl_grab *grab, uint32_t time, int32_t button, int32_t state) { + struct wlsc_input_device *device = + container_of(grab, struct wlsc_input_device, drag_grab); + + if (device->drag_focus_resource && + device->input_device.grab_button == button && state == 0) + wl_resource_post_event(device->drag_focus_resource, + WL_DATA_DEVICE_DROP); } static void drag_grab_end(struct wl_grab *grab, uint32_t time) { struct wlsc_input_device *device = - container_of(grab, struct wlsc_input_device, grab); + container_of(grab, struct wlsc_input_device, drag_grab); - if (device->drag_focus_resource) - wl_resource_post_event(device->drag_focus_resource, - WL_DATA_DEVICE_DROP); - - drag_set_focus(device, NULL, time, 0, 0); wlsc_data_source_unref(device->drag_data_source); device->drag_data_source = NULL; } static const struct wl_grab_interface drag_grab_interface = { + drag_grab_enter, + drag_grab_leave, drag_grab_motion, drag_grab_button, drag_grab_end @@ -253,26 +268,21 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource, { struct wlsc_input_device *device = resource->data; struct wlsc_surface *surface = surface_resource->data; - struct wlsc_surface *target; - int32_t sx, sy; /* FIXME: Check that client has implicit grab on the surface * that matches the given time. */ /* FIXME: Check that the data source type array isn't empty. */ - if (wl_input_device_update_grab(&device->input_device, &device->grab, - &surface->surface, time) < 0) - return; - - device->grab.interface = &drag_grab_interface; + device->drag_grab.interface = &drag_grab_interface; device->drag_data_source = source_resource->data; device->drag_data_source->refcount++; - target = pick_surface(&device->input_device, &sx, &sy); - wl_input_device_set_pointer_focus(&device->input_device, - NULL, time, 0, 0, 0, 0); - drag_set_focus(device, &target->surface, time, sx, sy); + if (wlsc_input_device_update_grab(&device->input_device, + &device->drag_grab, + &surface->surface, time) < 0) + return; + } static void diff --git a/compositor/shell.c b/compositor/shell.c index b7cfdd33..0bf26f96 100644 --- a/compositor/shell.c +++ b/compositor/shell.c @@ -68,7 +68,8 @@ enum shell_surface_type { SHELL_SURFACE_TOPLEVEL, SHELL_SURFACE_TRANSIENT, - SHELL_SURFACE_FULLSCREEN + SHELL_SURFACE_FULLSCREEN, + SHELL_SURFACE_MENU }; struct shell_surface { @@ -76,10 +77,17 @@ struct shell_surface { struct wlsc_surface *surface; struct wl_listener surface_destroy_listener; + struct shell_surface *parent; enum shell_surface_type type; int32_t saved_x, saved_y; + struct { + struct wl_grab grab; + uint32_t time; + int32_t x, y; + } menu; + struct wlsc_output *output; struct wl_list link; }; @@ -91,6 +99,19 @@ struct wlsc_move_grab { }; static void +noop_grab_enter(struct wl_grab *grab, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y) +{ +} + +static void +noop_grab_leave(struct wl_grab *grab, + uint32_t time, struct wl_surface *surface) +{ +} + +static void move_grab_motion(struct wl_grab *grab, uint32_t time, int32_t x, int32_t y) { @@ -114,6 +135,8 @@ move_grab_end(struct wl_grab *grab, uint32_t time) } static const struct wl_grab_interface move_grab_interface = { + noop_grab_enter, + noop_grab_leave, move_grab_motion, move_grab_button, move_grab_end @@ -134,13 +157,11 @@ wlsc_surface_move(struct wlsc_surface *es, move->dy = es->y - wd->input_device.grab_y; move->surface = es; - if (wl_input_device_update_grab(&wd->input_device, - &move->grab, &es->surface, time) < 0) + if (wlsc_input_device_update_grab(&wd->input_device, + &move->grab, &es->surface, time) < 0) return 0; wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING); - wl_input_device_set_pointer_focus(&wd->input_device, - NULL, time, 0, 0, 0, 0); return 0; } @@ -205,6 +226,8 @@ resize_grab_end(struct wl_grab *grab, uint32_t time) } static const struct wl_grab_interface resize_grab_interface = { + noop_grab_enter, + noop_grab_leave, resize_grab_motion, resize_grab_button, resize_grab_end @@ -264,13 +287,11 @@ wlsc_surface_resize(struct shell_surface *shsurf, break; } - if (wl_input_device_update_grab(&wd->input_device, - &resize->grab, &es->surface, time) < 0) + if (wlsc_input_device_update_grab(&wd->input_device, + &resize->grab, &es->surface, time) < 0) return 0; wlsc_input_device_set_pointer_image(wd, pointer); - wl_input_device_set_pointer_focus(&wd->input_device, - NULL, time, 0, 0, 0, 0); return 0; } @@ -351,12 +372,161 @@ shell_surface_set_fullscreen(struct wl_client *client, shsurf->type = SHELL_SURFACE_FULLSCREEN; } + +static void +menu_grab_enter(struct wl_grab *grab, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y) +{ + struct wl_input_device *device = grab->input_device; + struct wl_resource *resource; + struct shell_surface *priv = + container_of(grab, struct shell_surface, menu.grab); + + wl_list_for_each(resource, &device->resource_list, link) { + if (resource->client == surface->resource.client) + break; + } + + if (&resource->link != &device->resource_list && + resource->client == priv->surface->surface.resource.client) { + wl_resource_post_event(resource, + WL_INPUT_DEVICE_POINTER_FOCUS, + time, surface, + device->x, device->y, x, y); + wl_list_insert(resource->destroy_listener_list.prev, + &device->pointer_focus_listener.link); + + device->pointer_focus_resource = resource; + } else { + device->pointer_focus_resource = NULL; + } + + device->pointer_focus = surface; + device->pointer_focus_time = time; +} + +static void +menu_grab_leave(struct wl_grab *grab, + uint32_t time, struct wl_surface *surface) +{ + struct wl_input_device *device = grab->input_device; + + if (device->pointer_focus_resource) { + wl_resource_post_event(device->pointer_focus_resource, + WL_INPUT_DEVICE_POINTER_FOCUS, + time, NULL, 0, 0, 0, 0); + wl_list_remove(&device->pointer_focus_listener.link); + } + + device->pointer_focus_resource = NULL; + device->pointer_focus = NULL; +} + +static void +menu_grab_motion(struct wl_grab *grab, + uint32_t time, int32_t x, int32_t y) +{ + struct wlsc_input_device *device = + (struct wlsc_input_device *) grab->input_device; + struct wlsc_surface *es = + (struct wlsc_surface *) device->input_device.pointer_focus; + int32_t sx, sy; + struct wl_resource *resource; + + resource = grab->input_device->pointer_focus_resource; + if (resource) { + wlsc_surface_transform(es, x, y, &sx, &sy); + wl_resource_post_event(resource, WL_INPUT_DEVICE_MOTION, + time, x, y, sx, sy); + } +} + +static void +menu_grab_button(struct wl_grab *grab, + uint32_t time, int32_t button, int32_t state) +{ + struct wl_resource *resource; + struct shell_surface *shsurf = + container_of(grab, struct shell_surface, menu.grab); + + resource = grab->input_device->pointer_focus_resource; + if (resource) { + wl_resource_post_event(resource, WL_INPUT_DEVICE_BUTTON, + time, button, state); + } else { + wl_resource_post_event(&shsurf->resource, + WL_SHELL_SURFACE_MENU_DONE); + wlsc_input_device_end_grab(grab->input_device, time); + shsurf->menu.grab.input_device = NULL; + } +} + +static void +menu_grab_end(struct wl_grab *grab, uint32_t time) +{ +} + +static const struct wl_grab_interface menu_grab_interface = { + menu_grab_enter, + menu_grab_leave, + menu_grab_motion, + menu_grab_button, + menu_grab_end +}; + +static void +shell_map_menu(struct shell_surface *shsurf, uint32_t time) +{ + struct wl_input_device *device; + struct wlsc_surface *es = shsurf->surface; + struct wlsc_surface *parent = shsurf->parent->surface; + + es->output = parent->output; + + shsurf->menu.grab.interface = &menu_grab_interface; + device = es->compositor->input_device; + + es->x = shsurf->parent->surface->x + shsurf->menu.x; + es->y = shsurf->parent->surface->y + shsurf->menu.y; + + shsurf->menu.grab.input_device = device; + shsurf->menu.time = device->grab_time; + + if (wlsc_input_device_update_grab(shsurf->menu.grab.input_device, + &shsurf->menu.grab, + &shsurf->parent->surface->surface, + shsurf->menu.time)) { + fprintf(stderr, "update grab failed\n"); + } + + /* FIXME: Hack to prevent button release from ending the grab */ + device->grab_button = 0; +} + +static void +shell_surface_set_menu(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *parent_resource, + int32_t x, int32_t y, uint32_t flags) +{ + struct shell_surface *shsurf = resource->data; + struct wlsc_surface *es = shsurf->surface; + + wlsc_surface_damage(es); + shsurf->type = SHELL_SURFACE_MENU; + shsurf->parent = parent_resource->data; + shsurf->menu.x = x; + shsurf->menu.y = y; +} + static const struct wl_shell_surface_interface shell_surface_implementation = { shell_surface_move, shell_surface_resize, shell_surface_set_toplevel, shell_surface_set_transient, - shell_surface_set_fullscreen + shell_surface_set_fullscreen, + shell_surface_set_menu }; static void @@ -364,6 +534,9 @@ destroy_shell_surface(struct wl_resource *resource) { struct shell_surface *shsurf = resource->data; + if (shsurf->menu.grab.input_device) + wlsc_input_device_end_grab(shsurf->menu.grab.input_device, 0); + /* in case cleaning up a dead client destroys shell_surface first */ if (shsurf->surface) wl_list_remove(&shsurf->surface_destroy_listener.link); @@ -376,9 +549,9 @@ static void shell_handle_surface_destroy(struct wl_listener *listener, struct wl_resource *resource, uint32_t time) { - struct shell_surface *shsurf = container_of(listener, - struct shell_surface, - surface_destroy_listener); + struct shell_surface *shsurf = + container_of(listener, + struct shell_surface, surface_destroy_listener); shsurf->surface = NULL; wl_resource_destroy(&shsurf->resource, time); @@ -795,8 +968,13 @@ map(struct wlsc_shell *base, struct wlsc_compositor *compositor = shell->compositor; struct wl_list *list; enum shell_surface_type surface_type; + struct shell_surface *shsurf; - surface_type = get_shell_surface_type(surface); + shsurf = get_shell_surface(surface); + if (shsurf) + surface_type = shsurf->type; + else + surface_type = SHELL_SURFACE_NORMAL; if (shell->locked) list = &shell->hidden_surface_list; @@ -832,16 +1010,25 @@ map(struct wlsc_shell *base, } } - if (surface_type == SHELL_SURFACE_TOPLEVEL) { + switch (surface_type) { + case SHELL_SURFACE_TOPLEVEL: surface->x = 10 + random() % 400; surface->y = 10 + random() % 400; + break; + case SHELL_SURFACE_MENU: + shell_map_menu(shsurf, shsurf->menu.time); + break; + default: + break; } surface->width = width; surface->height = height; - if (!shell->locked || surface_type == SHELL_SURFACE_LOCK) + if (!shell->locked || surface_type == SHELL_SURFACE_LOCK) { wlsc_surface_configure(surface, surface->x, surface->y, width, height); + wlsc_compositor_repick(compositor); + } if (surface_type == SHELL_SURFACE_TOPLEVEL) wlsc_zoom_run(surface, 0.8, 1.0, NULL, NULL); |