From f874c3d585163f9346e81cbd45a0866fbd9c4b14 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 18 Oct 2017 22:46:52 +0200 Subject: [PATCH 1/7] Add a default meta key --- rootston/config.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rootston/config.c b/rootston/config.c index 5e911e39..5ed299a7 100644 --- a/rootston/config.c +++ b/rootston/config.c @@ -263,6 +263,10 @@ static int config_ini_handler(void *user, const char *section, const char *name, struct roots_config *parse_args(int argc, char *argv[]) { struct roots_config *config = calloc(1, sizeof(struct roots_config)); + if (config == NULL) { + return NULL; + } + config->xwayland = true; wl_list_init(&config->outputs); wl_list_init(&config->devices); @@ -296,7 +300,8 @@ struct roots_config *parse_args(int argc, char *argv[]) { int result = ini_parse(config->config_path, config_ini_handler, config); if (result == -1) { - wlr_log(L_DEBUG, "No config file found. Using empty config."); + wlr_log(L_DEBUG, "No config file found. Using sensible defaults."); + config->keyboard.meta_key = WLR_MODIFIER_LOGO; add_binding_config(&config->bindings, "Logo+Shift+e", "exit"); add_binding_config(&config->bindings, "Ctrl+q", "close"); add_binding_config(&config->bindings, "Alt+Tab", "next_window"); From ec83d9df58b0a3b31ea24c01f2df16c10dcad936 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Wed, 18 Oct 2017 05:05:21 -0400 Subject: [PATCH 2/7] xdg-shell: send same-as-current configure if needed --- types/wlr_xdg_shell_v6.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index f057025a..b14f5862 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -845,6 +845,10 @@ static bool wlr_xdg_surface_v6_toplevel_state_compare( return false; } + if (!wl_list_empty(&state->base->configure_list)) { + return false; + } + if (state->pending.activated != state->current.activated) { return false; } @@ -947,7 +951,7 @@ static void wlr_xdg_surface_send_configure(void *user_data) { } static void wlr_xdg_surface_v6_schedule_configure( - struct wlr_xdg_surface_v6 *surface, bool force) { + struct wlr_xdg_surface_v6 *surface) { struct wl_display *display = wl_client_get_display(surface->client->client); struct wl_event_loop *loop = wl_display_get_event_loop(display); bool pending_same = false; @@ -957,7 +961,7 @@ static void wlr_xdg_surface_v6_schedule_configure( assert(0 && "not reached"); break; case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL: - pending_same = !force && + pending_same = wlr_xdg_surface_v6_toplevel_state_compare(surface->toplevel_state); break; case WLR_XDG_SURFACE_V6_ROLE_POPUP: @@ -1001,7 +1005,7 @@ static void wlr_xdg_surface_v6_toplevel_committed( if (!surface->surface->texture->valid && !surface->toplevel_state->added) { // on the first commit, send a configure request to tell the client it // is added - wlr_xdg_surface_v6_schedule_configure(surface, true); + wlr_xdg_surface_v6_schedule_configure(surface); surface->toplevel_state->added = true; return; } @@ -1018,7 +1022,7 @@ static void wlr_xdg_surface_v6_popup_committed( assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP); if (!surface->popup_state->committed) { - wlr_xdg_surface_v6_schedule_configure(surface, true); + wlr_xdg_surface_v6_schedule_configure(surface); surface->popup_state->committed = true; } } @@ -1265,49 +1269,42 @@ void wlr_xdg_surface_v6_ping(struct wlr_xdg_surface_v6 *surface) { void wlr_xdg_toplevel_v6_set_size(struct wlr_xdg_surface_v6 *surface, uint32_t width, uint32_t height) { assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); - bool force = - (surface->toplevel_state->pending.width != width || - surface->toplevel_state->pending.height != height); surface->toplevel_state->pending.width = width; surface->toplevel_state->pending.height = height; - wlr_xdg_surface_v6_schedule_configure(surface, force); + wlr_xdg_surface_v6_schedule_configure(surface); } void wlr_xdg_toplevel_v6_set_activated(struct wlr_xdg_surface_v6 *surface, bool activated) { assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); - bool force = surface->toplevel_state->pending.activated != activated; surface->toplevel_state->pending.activated = activated; - wlr_xdg_surface_v6_schedule_configure(surface, force); + wlr_xdg_surface_v6_schedule_configure(surface); } void wlr_xdg_toplevel_v6_set_maximized(struct wlr_xdg_surface_v6 *surface, bool maximized) { assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); - bool force = surface->toplevel_state->pending.maximized != maximized; surface->toplevel_state->pending.maximized = maximized; - wlr_xdg_surface_v6_schedule_configure(surface, force); + wlr_xdg_surface_v6_schedule_configure(surface); } void wlr_xdg_toplevel_v6_set_fullscreen(struct wlr_xdg_surface_v6 *surface, bool fullscreen) { assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); - bool force = surface->toplevel_state->pending.fullscreen != fullscreen; surface->toplevel_state->pending.fullscreen = fullscreen; - wlr_xdg_surface_v6_schedule_configure(surface, force); + wlr_xdg_surface_v6_schedule_configure(surface); } void wlr_xdg_toplevel_v6_set_resizing(struct wlr_xdg_surface_v6 *surface, bool resizing) { assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL); - bool force = surface->toplevel_state->pending.resizing != resizing; surface->toplevel_state->pending.resizing = resizing; - wlr_xdg_surface_v6_schedule_configure(surface, force); + wlr_xdg_surface_v6_schedule_configure(surface); } void wlr_xdg_toplevel_v6_send_close(struct wlr_xdg_surface_v6 *surface) { From fcf4724da94056cfe71f69359f94f39334102fc6 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 19 Oct 2017 10:15:56 -0400 Subject: [PATCH 3/7] xdg-shell: improve configure request change detection --- types/wlr_xdg_shell_v6.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index b14f5862..efa6bb3a 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -840,30 +840,46 @@ static const struct zxdg_surface_v6_interface zxdg_surface_v6_implementation = { static bool wlr_xdg_surface_v6_toplevel_state_compare( struct wlr_xdg_toplevel_v6 *state) { + struct { + struct wlr_xdg_toplevel_v6_state state; + uint32_t width; + uint32_t height; + + } configured; + // is pending state different from current state? if (!state->base->configured) { return false; } - if (!wl_list_empty(&state->base->configure_list)) { - return false; + if (wl_list_empty(&state->base->configure_list)) { + // last configure is actually the current state, just use it + configured.state = state->current; + configured.width = state->base->surface->current->width; + configured.height = state->base->surface->current->width; + } else { + struct wlr_xdg_surface_v6_configure *configure = + wl_container_of(state->base->configure_list.prev, configure, link); + configured.state = configure->state; + configured.width = configure->state.width; + configured.height = configure->state.height; } - if (state->pending.activated != state->current.activated) { + if (state->pending.activated != configured.state.activated) { return false; } - if (state->pending.fullscreen != state->current.fullscreen) { + if (state->pending.fullscreen != configured.state.fullscreen) { return false; } - if (state->pending.maximized != state->current.maximized) { + if (state->pending.maximized != configured.state.maximized) { return false; } - if (state->pending.resizing != state->current.resizing) { + if (state->pending.resizing != configured.state.resizing) { return false; } - if ((uint32_t)state->base->geometry->width == state->pending.width && - (uint32_t)state->base->geometry->height == state->pending.height) { + if (state->pending.width == configured.width && + state->pending.height == configured.height) { return true; } From 169bc216ed1b4909b1635faea1239863416b679e Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 19 Oct 2017 12:33:02 -0400 Subject: [PATCH 4/7] rootston: view set position --- include/rootston/view.h | 2 ++ rootston/cursor.c | 29 +++++++++++++++++++---------- rootston/desktop.c | 10 ++++++++++ rootston/wl_shell.c | 26 +++++++++++++------------- rootston/xwayland.c | 14 ++++++++++++++ 5 files changed, 58 insertions(+), 23 deletions(-) diff --git a/include/rootston/view.h b/include/rootston/view.h index a4fb6f01..ad722225 100644 --- a/include/rootston/view.h +++ b/include/rootston/view.h @@ -73,12 +73,14 @@ struct roots_view { void (*get_size)(struct roots_view *view, struct wlr_box *box); void (*activate)(struct roots_view *view, bool active); void (*resize)(struct roots_view *view, uint32_t width, uint32_t height); + void (*set_position)(struct roots_view *view, double x, double y); void (*close)(struct roots_view *view); }; void view_get_size(struct roots_view *view, struct wlr_box *box); void view_activate(struct roots_view *view, bool active); void view_resize(struct roots_view *view, uint32_t width, uint32_t height); +void view_set_position(struct roots_view *view, double x, double y); void view_close(struct roots_view *view); bool view_center(struct roots_view *view); void view_initialize(struct roots_view *view); diff --git a/rootston/cursor.c b/rootston/cursor.c index 65109534..b312392d 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -14,6 +14,7 @@ #include "rootston/config.h" #include "rootston/input.h" #include "rootston/desktop.h" +#include "rootston/view.h" const struct roots_input_event *get_input_event(struct roots_input *input, uint32_t serial) { @@ -103,32 +104,40 @@ void cursor_update_position(struct roots_input *input, uint32_t time) { break; case ROOTS_CURSOR_MOVE: if (input->active_view) { - int dx = input->cursor->x - input->offs_x, - dy = input->cursor->y - input->offs_y; - input->active_view->x = input->view_x + dx; - input->active_view->y = input->view_y + dy; + double dx = input->cursor->x - input->offs_x; + double dy = input->cursor->y - input->offs_y; + view_set_position(input->active_view, + input->view_x + dx, input->view_y + dy); } break; case ROOTS_CURSOR_RESIZE: if (input->active_view) { - int dx = input->cursor->x - input->offs_x, - dy = input->cursor->y - input->offs_y; - int width = input->view_width, - height = input->view_height; + double dx = input->cursor->x - input->offs_x; + double dy = input->cursor->y - input->offs_y; + double active_x = input->active_view->x; + double active_y = input->active_view->y; + int width = input->view_width; + int height = input->view_height; if (input->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_TOP) { - input->active_view->y = input->view_y + dy; + active_y = input->view_y + dy; height -= dy; } if (input->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_BOTTOM) { height += dy; } if (input->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_LEFT) { - input->active_view->x = input->view_x + dx; + active_x = input->view_x + dx; width -= dx; } if (input->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_RIGHT) { width += dx; } + + // TODO we might need one configure event for this + if (active_x != input->active_view->x || + active_y != input->active_view->y) { + view_set_position(input->active_view, active_x, active_y); + } view_resize(input->active_view, width, height); } break; diff --git a/rootston/desktop.c b/rootston/desktop.c index a7137255..641315a8 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -46,6 +46,16 @@ void view_get_size(struct roots_view *view, struct wlr_box *box) { box->height = view->wlr_surface->current->height; } +void view_set_position(struct roots_view *view, double x, double y) { + if (view->set_position) { + view->set_position(view, x, y); + return; + } + + view->x = x; + view->y = y; +} + void view_activate(struct roots_view *view, bool activate) { if (view->activate) { view->activate(view, activate); diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 33f54a32..2c6047b1 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -109,19 +109,6 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { struct roots_view *view = calloc(1, sizeof(struct roots_view)); view->type = ROOTS_WL_SHELL_VIEW; - if (surface->state == WLR_WL_SHELL_SURFACE_STATE_TRANSIENT) { - // we need to map it relative to the parent - int i = - list_seq_find(desktop->views, - shell_surface_compare_equals, surface->parent); - if (i != -1) { - struct roots_view *parent = desktop->views->items[i]; - view->x = parent->x + surface->transient_state->x; - view->y = parent->y + surface->transient_state->y; - } - } else { - view->x = view->y = 200; - } view->wl_shell_surface = surface; view->roots_wl_shell_surface = roots_surface; view->wlr_surface = surface->surface; @@ -131,4 +118,17 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { roots_surface->view = view; list_add(desktop->views, view); view_initialize(view); + + if (surface->state == WLR_WL_SHELL_SURFACE_STATE_TRANSIENT) { + // we need to map it relative to the parent + int i = + list_seq_find(desktop->views, + shell_surface_compare_equals, surface->parent); + if (i != -1) { + struct roots_view *parent = desktop->views->items[i]; + view_set_position(view, + parent->x + surface->transient_state->x, + parent->y + surface->transient_state->y); + } + } } diff --git a/rootston/xwayland.c b/rootston/xwayland.c index c32ee15b..d7885e94 100644 --- a/rootston/xwayland.c +++ b/rootston/xwayland.c @@ -26,6 +26,15 @@ static void resize(struct roots_view *view, uint32_t width, uint32_t height) { xwayland_surface->x, xwayland_surface->y, width, height); } +static void set_position(struct roots_view *view, double x, double y) { + assert(view->type == ROOTS_XWAYLAND_VIEW); + struct wlr_xwayland_surface *xwayland_surface = view->xwayland_surface; + view->x = x; + view->y = y; + wlr_xwayland_surface_configure(view->desktop->xwayland, xwayland_surface, + x, y, xwayland_surface->width, xwayland_surface->height); +} + static void close(struct roots_view *view) { assert(view->type == ROOTS_XWAYLAND_VIEW); wlr_xwayland_surface_close(view->desktop->xwayland, view->xwayland_surface); @@ -88,7 +97,12 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { view->desktop = desktop; view->activate = activate; view->resize = resize; + view->set_position = set_position; view->close = close; roots_surface->view = view; list_add(desktop->views, view); + + if (!surface->override_redirect) { + view_initialize(view); + } } From eaed6b6d294e82124cd4f7a70387f590e3910552 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 19 Oct 2017 12:57:45 -0400 Subject: [PATCH 5/7] wl-output: send layout position --- include/wlr/types/wlr_output.h | 4 ++++ types/wlr_output.c | 16 +++++++++++++++- types/wlr_output_layout.c | 4 ++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index dc637e26..312b51f8 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -56,6 +56,9 @@ struct wlr_output { struct wl_listener surface_destroy; } cursor; + // the output position in layout space reported to clients + int32_t lx, ly; + void *data; }; @@ -66,6 +69,7 @@ bool wlr_output_set_mode(struct wlr_output *output, struct wlr_output_mode *mode); void wlr_output_transform(struct wlr_output *output, enum wl_output_transform transform); +void wlr_output_set_position(struct wlr_output *output, int32_t lx, int32_t ly); bool wlr_output_set_cursor(struct wlr_output *output, const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y); diff --git a/types/wlr_output.c b/types/wlr_output.c index eb969b9a..5e10509e 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -21,7 +21,7 @@ static void wl_output_send_to_resource(struct wl_resource *resource) { assert(output); const uint32_t version = wl_resource_get_version(resource); if (version >= WL_OUTPUT_GEOMETRY_SINCE_VERSION) { - wl_output_send_geometry(resource, 0, 0, // TODO: get position from layout? + wl_output_send_geometry(resource, output->lx, output->ly, output->phys_width, output->phys_height, output->subpixel, output->make, output->model, output->transform); } @@ -122,6 +122,20 @@ void wlr_output_transform(struct wlr_output *output, wlr_output_update_matrix(output); } +void wlr_output_set_position(struct wlr_output *output, int32_t lx, int32_t ly) { + if (lx == output->lx && ly == output->ly) { + return; + } + + output->lx = lx; + output->ly = ly; + + struct wl_resource *resource; + wl_resource_for_each(resource, &output->wl_resources) { + wl_output_send_to_resource(resource); + } +} + static bool set_cursor(struct wlr_output *output, const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height, int32_t hotspot_x, int32_t hotspot_y) { diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 8c3f1d88..8a50e331 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -115,6 +115,10 @@ static void wlr_output_layout_reconfigure(struct wlr_output_layout *layout) { max_x += box->width; } + wl_list_for_each(l_output, &layout->outputs, link) { + wlr_output_set_position(l_output->output, l_output->x, l_output->y); + } + wl_signal_emit(&layout->events.change, layout); } From 8c759d7abe4ea732fddb2f258d318b32591d1e73 Mon Sep 17 00:00:00 2001 From: "D.B" Date: Fri, 20 Oct 2017 17:49:04 +0200 Subject: [PATCH 6/7] Add startup command option to rootston Allows specifying a command to run at startup. --- include/rootston/config.h | 1 + rootston/config.c | 10 +++++++--- rootston/main.c | 13 +++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/include/rootston/config.h b/include/rootston/config.h index 66347c3c..5fa4890f 100644 --- a/include/rootston/config.h +++ b/include/rootston/config.h @@ -42,6 +42,7 @@ struct roots_config { struct wl_list devices; struct wl_list bindings; char *config_path; + char *startup_cmd; }; struct roots_config *parse_args(int argc, char *argv[]); diff --git a/rootston/config.c b/rootston/config.c index 5ed299a7..71a4731b 100644 --- a/rootston/config.c +++ b/rootston/config.c @@ -16,12 +16,13 @@ static void usage(const char *name, int ret) { fprintf(stderr, - "usage: %s [-C ]\n" + "usage: %s [-C ] [-E ]\n" "\n" " -C Path to the configuration file\n" " (default: rootston.ini).\n" " See `rootston.ini.example` for config\n" - " file documentation.\n", name); + " file documentation.\n" + " -E Command that will be ran at startup.\n" , name); exit(ret); } @@ -273,11 +274,14 @@ struct roots_config *parse_args(int argc, char *argv[]) { wl_list_init(&config->bindings); int c; - while ((c = getopt(argc, argv, "C:h")) != -1) { + while ((c = getopt(argc, argv, "C:E:h")) != -1) { switch (c) { case 'C': config->config_path = strdup(optarg); break; + case 'E': + config->startup_cmd = strdup(optarg); + break; case 'h': case '?': usage(argv[0], c != 'h'); diff --git a/rootston/main.c b/rootston/main.c index 5a60000c..b80c2efd 100644 --- a/rootston/main.c +++ b/rootston/main.c @@ -1,6 +1,7 @@ #define _POSIX_C_SOURCE 200112L #include #include +#include #include #include #include @@ -42,6 +43,18 @@ int main(int argc, char **argv) { } setenv("WAYLAND_DISPLAY", socket, true); + + if (server.config->startup_cmd != NULL) { + const char *cmd = server.config->startup_cmd; + pid_t pid = fork(); + if (pid < 0) { + wlr_log(L_ERROR, "cannot execute binding command: fork() failed"); + return 1; + } else if (pid == 0) { + execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL); + } + } + wl_display_run(server.wl_display); wlr_backend_destroy(server.backend); return 0; From 1782d5e7b7dc5e494cfee72b758d5fa8114aecc8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 20 Oct 2017 23:19:41 -0400 Subject: [PATCH 7/7] Implement simple touch support for rootston --- include/rootston/input.h | 22 +++++++++---- rootston/cursor.c | 70 ++++++++++++++++++++++++++++++++++++++-- rootston/input.c | 4 +-- rootston/meson.build | 1 + rootston/touch.c | 26 +++++++++++++++ 5 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 rootston/touch.c diff --git a/include/rootston/input.h b/include/rootston/input.h index 516104a7..ddd5a05d 100644 --- a/include/rootston/input.h +++ b/include/rootston/input.h @@ -24,18 +24,12 @@ struct roots_keyboard { struct roots_pointer { struct roots_input *input; struct wlr_input_device *device; - // We don't listen to any pointer events directly - they go through - // wlr_cursor struct wl_list link; }; struct roots_touch { struct roots_input *input; struct wlr_input_device *device; - struct wl_listener down; - struct wl_listener up; - struct wl_listener motion; - struct wl_listener cancel; struct wl_list link; }; @@ -70,6 +64,13 @@ struct roots_input_event { struct wlr_input_device *device; }; +struct roots_touch_point { + struct roots_touch *device; + int32_t slot; + double x, y; + struct wl_list link; +}; + struct roots_input { struct roots_config *config; struct roots_server *server; @@ -104,9 +105,16 @@ struct roots_input { struct wl_listener cursor_motion_absolute; struct wl_listener cursor_button; struct wl_listener cursor_axis; + + struct wl_listener cursor_touch_down; + struct wl_listener cursor_touch_up; + struct wl_listener cursor_touch_motion; + struct wl_listener cursor_tool_axis; struct wl_listener cursor_tool_tip; + struct wl_list touch_points; + struct wl_listener pointer_grab_end; struct wl_listener request_set_cursor; @@ -120,6 +128,8 @@ void pointer_add(struct wlr_input_device *device, struct roots_input *input); void pointer_remove(struct wlr_input_device *device, struct roots_input *input); void keyboard_add(struct wlr_input_device *device, struct roots_input *input); void keyboard_remove(struct wlr_input_device *device, struct roots_input *input); +void touch_add(struct wlr_input_device *device, struct roots_input *input); +void touch_remove(struct wlr_input_device *device, struct roots_input *input); void tablet_tool_add(struct wlr_input_device *device, struct roots_input *input); void tablet_tool_remove(struct wlr_input_device *device, struct roots_input *input); diff --git a/rootston/cursor.c b/rootston/cursor.c index b312392d..27a6006b 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 700 +#include #include #include #include @@ -82,8 +83,8 @@ void cursor_update_position(struct roots_input *input, uint32_t time) { double sx, sy; switch (input->mode) { case ROOTS_CURSOR_PASSTHROUGH: - view = view_at(desktop, input->cursor->x, input->cursor->y, &surface, - &sx, &sy); + view = view_at(desktop, input->cursor->x, input->cursor->y, + &surface, &sx, &sy); bool set_compositor_cursor = !view && input->cursor_client; if (view) { struct wl_client *view_client = @@ -286,6 +287,56 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) { (uint32_t)(event->time_usec / 1000), event->button, event->state); } +static void handle_touch_down(struct wl_listener *listener, void *data) { + struct wlr_event_touch_down *event = data; + struct roots_input *input = + wl_container_of(listener, input, cursor_touch_down); + struct roots_touch_point *point = + calloc(1, sizeof(struct roots_touch_point)); + point->device = event->device->data; + point->slot = event->slot; + point->x = event->x_mm / event->width_mm; + point->y = event->y_mm / event->height_mm; + wlr_cursor_warp_absolute(input->cursor, event->device, point->x, point->y); + cursor_update_position(input, (uint32_t)(event->time_usec / 1000)); + wl_list_insert(&input->touch_points, &point->link); + do_cursor_button_press(input, input->cursor, event->device, + (uint32_t)(event->time_usec / 1000), BTN_LEFT, 1); +} + +static void handle_touch_up(struct wl_listener *listener, void *data) { + struct wlr_event_touch_up *event = data; + struct roots_input *input = + wl_container_of(listener, input, cursor_touch_up); + struct roots_touch_point *point; + wl_list_for_each(point, &input->touch_points, link) { + if (point->slot == event->slot) { + wl_list_remove(&point->link); + break; + } + } + do_cursor_button_press(input, input->cursor, event->device, + (uint32_t)(event->time_usec / 1000), BTN_LEFT, 0); +} + +static void handle_touch_motion(struct wl_listener *listener, void *data) { + struct wlr_event_touch_motion *event = data; + struct roots_input *input = + wl_container_of(listener, input, cursor_touch_motion); + struct roots_touch_point *point; + wl_list_for_each(point, &input->touch_points, link) { + if (point->slot == event->slot) { + point->x = event->x_mm / event->width_mm; + point->y = event->y_mm / event->height_mm; + wlr_cursor_warp_absolute(input->cursor, event->device, + point->x, point->y); + cursor_update_position(input, + (uint32_t)(event->time_usec / 1000)); + break; + } + } +} + static void handle_tool_axis(struct wl_listener *listener, void *data) { struct roots_input *input = wl_container_of(listener, input, cursor_tool_axis); struct wlr_event_tablet_tool_axis *event = data; @@ -342,6 +393,9 @@ static void handle_request_set_cursor(struct wl_listener *listener, void cursor_initialize(struct roots_input *input) { struct wlr_cursor *cursor = input->cursor; + + // TODO: Does this belong here + wl_list_init(&input->touch_points); wl_list_init(&input->cursor_motion.link); wl_signal_add(&cursor->events.motion, &input->cursor_motion); @@ -360,6 +414,18 @@ void cursor_initialize(struct roots_input *input) { wl_signal_add(&cursor->events.axis, &input->cursor_axis); input->cursor_axis.notify = handle_cursor_axis; + wl_list_init(&input->cursor_touch_down.link); + wl_signal_add(&cursor->events.touch_down, &input->cursor_touch_down); + input->cursor_touch_down.notify = handle_touch_down; + + wl_list_init(&input->cursor_touch_up.link); + wl_signal_add(&cursor->events.touch_up, &input->cursor_touch_up); + input->cursor_touch_up.notify = handle_touch_up; + + wl_list_init(&input->cursor_touch_motion.link); + wl_signal_add(&cursor->events.touch_motion, &input->cursor_touch_motion); + input->cursor_touch_motion.notify = handle_touch_motion; + wl_list_init(&input->cursor_tool_axis.link); wl_signal_add(&cursor->events.tablet_tool_axis, &input->cursor_tool_axis); input->cursor_tool_axis.notify = handle_tool_axis; diff --git a/rootston/input.c b/rootston/input.c index 86a87e24..1784040c 100644 --- a/rootston/input.c +++ b/rootston/input.c @@ -37,7 +37,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { pointer_add(device, input); break; case WLR_INPUT_DEVICE_TOUCH: - //touch_add(device, input); + touch_add(device, input); break; case WLR_INPUT_DEVICE_TABLET_TOOL: tablet_tool_add(device, input); @@ -58,7 +58,7 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { pointer_remove(device, input); break; case WLR_INPUT_DEVICE_TOUCH: - //touch_remove(device, input); + touch_remove(device, input); break; case WLR_INPUT_DEVICE_TABLET_TOOL: tablet_tool_remove(device, input); diff --git a/rootston/meson.build b/rootston/meson.build index 7ff79f8e..f2621450 100644 --- a/rootston/meson.build +++ b/rootston/meson.build @@ -9,6 +9,7 @@ sources = [ 'output.c', 'pointer.c', 'tablet_tool.c', + 'touch.c', 'xdg_shell_v6.c', 'wl_shell.c', ] diff --git a/rootston/touch.c b/rootston/touch.c new file mode 100644 index 00000000..f6d9b11a --- /dev/null +++ b/rootston/touch.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include "rootston/input.h" + +// TODO: we'll likely want touch events to both control the cursor *and* be +// submitted directly to the seat. + +void touch_add(struct wlr_input_device *device, struct roots_input *input) { + struct roots_touch *touch = calloc(sizeof(struct roots_touch), 1); + device->data = touch; + touch->device = device; + touch->input = input; + wl_list_insert(&input->touch, &touch->link); + wlr_cursor_attach_input_device(input->cursor, device); + cursor_load_config(input->server->config, input->cursor, + input, input->server->desktop); +} + +void touch_remove(struct wlr_input_device *device, struct roots_input *input) { + struct roots_touch *touch = device->data; + wlr_cursor_detach_input_device(input->cursor, device); + wl_list_remove(&touch->link); + free(touch); +}