diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/compositor.c | 144 |
1 files changed, 109 insertions, 35 deletions
diff --git a/examples/compositor.c b/examples/compositor.c index ad3dd995..56974486 100644 --- a/examples/compositor.c +++ b/examples/compositor.c @@ -35,6 +35,37 @@ // TODO: move to common header? int os_create_anonymous_file(off_t size); +struct sample_state; + +struct example_xdg_surface_v6 { + struct wlr_xdg_surface_v6 *surface; + struct sample_state *sample; + + // position of the wlr_surface in the layout + struct { + int lx; + int ly; + } position; + + struct wl_listener destroy_listener; + struct wl_listener ping_timeout_listener; + struct wl_listener request_minimize_listener; + struct wl_listener request_move_listener; + struct wl_listener request_resize_listener; + struct wl_listener request_show_window_menu_listener; +}; + +struct input_event_cache { + uint32_t serial; + struct wlr_cursor *cursor; + struct wlr_input_device *device; +}; + +struct motion_context { + struct example_xdg_surface_v6 *surface; + int off_x, off_y; +}; + struct sample_state { struct wlr_renderer *renderer; struct compositor_state *compositor; @@ -47,15 +78,22 @@ struct sample_state { struct wl_listener keyboard_bound; struct wlr_xwayland *xwayland; struct wlr_gamma_control_manager *gamma_control_manager; + bool mod_down; int keymap_fd; size_t keymap_size; uint32_t serial; + struct motion_context motion_context; + struct example_config *config; struct wlr_output_layout *layout; struct wlr_cursor *cursor; struct wlr_xcursor *xcursor; + // Ring buffer + int input_cache_idx; + struct input_event_cache input_cache[16]; + struct wl_listener cursor_motion; struct wl_listener cursor_motion_absolute; struct wl_listener cursor_button; @@ -70,23 +108,6 @@ struct sample_state { struct wlr_xdg_surface_v6 *focused_surface; }; -struct example_xdg_surface_v6 { - struct wlr_xdg_surface_v6 *surface; - - // position of the wlr_surface in the layout - struct { - int lx; - int ly; - } position; - - struct wl_listener destroy_listener; - struct wl_listener ping_timeout_listener; - struct wl_listener request_minimize_listener; - struct wl_listener request_move_listener; - struct wl_listener request_resize_listener; - struct wl_listener request_show_window_menu_listener; -}; - static void example_set_focused_surface(struct sample_state *sample, struct wlr_xdg_surface_v6 *surface) { if (sample->focused_surface == surface) { @@ -159,10 +180,27 @@ static void handle_xdg_surface_v6_destroy(struct wl_listener *listener, static void handle_xdg_surface_v6_request_move(struct wl_listener *listener, void *data) { - struct example_xdg_surface_v6 *example_surface = - wl_container_of(listener, example_surface, request_move_listener); + struct example_xdg_surface_v6 *esurface = + wl_container_of(listener, esurface, request_move_listener); struct wlr_xdg_toplevel_v6_move_event *e = data; - wlr_log(L_DEBUG, "TODO: surface requested move: %s", e->surface->title); + struct sample_state *sample = esurface->sample; + struct input_event_cache *event = NULL; + for (size_t i = 0; + i < sizeof(sample->input_cache) / sizeof(sample->input_cache[0]); + ++i) { + if (sample->input_cache[i].cursor + && sample->input_cache[i].serial == e->serial) { + event = &sample->input_cache[i]; + break; + } + } + if (!event || sample->motion_context.surface) { + return; + } + sample->motion_context.surface = esurface; + sample->motion_context.off_x = sample->cursor->x - esurface->position.lx; + sample->motion_context.off_y = sample->cursor->y - esurface->position.ly; + wlr_seat_pointer_clear_focus(sample->wl_seat); } static void handle_xdg_surface_v6_request_resize(struct wl_listener *listener, @@ -193,6 +231,8 @@ static void handle_xdg_surface_v6_request_minimize( static void handle_new_xdg_surface_v6(struct wl_listener *listener, void *data) { + struct sample_state *sample_state = + wl_container_of(listener, sample_state, new_xdg_surface_v6); struct wlr_xdg_surface_v6 *surface = data; wlr_log(L_DEBUG, "new xdg surface: title=%s, app_id=%s", surface->title, surface->app_id); @@ -205,6 +245,7 @@ static void handle_new_xdg_surface_v6(struct wl_listener *listener, return; } + esurface->sample = sample_state; esurface->surface = surface; // TODO sensible default position esurface->position.lx = 300; @@ -328,6 +369,10 @@ static void handle_keyboard_key(struct keyboard_state *keyboard, wl_keyboard_send_key(seat_handle->keyboard, ++sample->serial, 0, keycode, key_state); } + + if (sym == XKB_KEY_Super_L || sym == XKB_KEY_Super_R) { + sample->mod_down = key_state == WLR_KEY_PRESSED; + } } static void handle_keyboard_bound(struct wl_listener *listener, void *data) { @@ -373,9 +418,17 @@ static struct wlr_xdg_surface_v6 *example_xdg_surface_at( } static void update_pointer_position(struct sample_state *sample, - uint32_t time_sec) { - struct wlr_xdg_surface_v6 *surface = - example_xdg_surface_at(sample, sample->cursor->x, sample->cursor->y); + uint32_t serial) { + if (sample->motion_context.surface) { + struct example_xdg_surface_v6 *surface; + surface = sample->motion_context.surface; + surface->position.lx = sample->cursor->x - sample->motion_context.off_x; + surface->position.ly = sample->cursor->y - sample->motion_context.off_y; + return; + } + + struct wlr_xdg_surface_v6 *surface = example_xdg_surface_at(sample, + sample->cursor->x, sample->cursor->y); if (surface) { struct example_xdg_surface_v6 *esurface = surface->data; @@ -384,10 +437,8 @@ static void update_pointer_position(struct sample_state *sample, double sy = sample->cursor->y - esurface->position.ly; // TODO z-order - wlr_seat_pointer_enter(sample->wl_seat, surface->surface, - sx, sy); - wlr_seat_pointer_send_motion(sample->wl_seat, time_sec, - sx, sy); + wlr_seat_pointer_enter(sample->wl_seat, surface->surface, sx, sy); + wlr_seat_pointer_send_motion(sample->wl_seat, serial, sx, sy); } else { wlr_seat_pointer_clear_focus(sample->wl_seat); } @@ -401,7 +452,7 @@ static void handle_cursor_motion(struct wl_listener *listener, void *data) { wlr_cursor_move(sample->cursor, event->device, event->delta_x, event->delta_y); - update_pointer_position(sample, event->time_sec); + update_pointer_position(sample, (uint32_t)event->time_usec); } static void handle_cursor_motion_absolute(struct wl_listener *listener, @@ -413,7 +464,7 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener, wlr_cursor_warp_absolute(sample->cursor, event->device, event->x_mm / event->width_mm, event->y_mm / event->height_mm); - update_pointer_position(sample, event->time_sec); + update_pointer_position(sample, (uint32_t)event->time_usec); } static void handle_cursor_axis(struct wl_listener *listener, void *data) { @@ -426,15 +477,38 @@ static void handle_cursor_axis(struct wl_listener *listener, void *data) { static void handle_cursor_button(struct wl_listener *listener, void *data) { struct sample_state *sample = - wl_container_of(listener, sample, cursor_button); + wl_container_of(listener, sample, cursor_button); struct wlr_event_pointer_button *event = data; struct wlr_xdg_surface_v6 *surface = example_xdg_surface_at(sample, sample->cursor->x, sample->cursor->y); - example_set_focused_surface(sample, surface); + int i; + switch (event->state) { + case WLR_BUTTON_RELEASED: + if (sample->motion_context.surface) { + sample->motion_context.surface = NULL; + } + break; + case WLR_BUTTON_PRESSED: + i = sample->input_cache_idx; + sample->input_cache[i].serial = (uint32_t)event->time_usec; + sample->input_cache[i].cursor = sample->cursor; + sample->input_cache[i].device = event->device; + sample->input_cache_idx = (i + 1) + % (sizeof(sample->input_cache) / sizeof(sample->input_cache[0])); + example_set_focused_surface(sample, surface); + if (sample->mod_down && event->button == BTN_LEFT) { + struct example_xdg_surface_v6 *esurface = surface->data; + sample->motion_context.surface = esurface; + sample->motion_context.off_x = sample->cursor->x - esurface->position.lx; + sample->motion_context.off_y = sample->cursor->y - esurface->position.ly; + wlr_seat_pointer_clear_focus(sample->wl_seat); + } + break; + } - wlr_seat_pointer_send_button(sample->wl_seat, event->time_sec, + wlr_seat_pointer_send_button(sample->wl_seat, (uint32_t)event->time_usec, event->button, event->state); } @@ -446,7 +520,7 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) { (event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) { wlr_cursor_warp_absolute(sample->cursor, event->device, event->x_mm / event->width_mm, event->y_mm / event->height_mm); - update_pointer_position(sample, event->time_sec); + update_pointer_position(sample, (uint32_t)event->time_usec); } } @@ -459,8 +533,8 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { example_xdg_surface_at(sample, sample->cursor->x, sample->cursor->y); example_set_focused_surface(sample, surface); - wlr_seat_pointer_send_button(sample->wl_seat, event->time_sec, - BTN_MOUSE, event->state); + wlr_seat_pointer_send_button(sample->wl_seat, (uint32_t)event->time_usec, + BTN_LEFT, event->state); } static void handle_input_add(struct compositor_state *state, |