diff options
Diffstat (limited to 'rootston')
-rw-r--r-- | rootston/config.c | 15 | ||||
-rw-r--r-- | rootston/cursor.c | 19 | ||||
-rw-r--r-- | rootston/desktop.c | 32 | ||||
-rw-r--r-- | rootston/input.c | 15 | ||||
-rw-r--r-- | rootston/keyboard.c | 57 | ||||
-rw-r--r-- | rootston/layer_shell.c | 82 | ||||
-rw-r--r-- | rootston/meson.build | 13 | ||||
-rw-r--r-- | rootston/output.c | 26 | ||||
-rw-r--r-- | rootston/seat.c | 25 | ||||
-rw-r--r-- | rootston/xdg_shell.c | 72 | ||||
-rw-r--r-- | rootston/xdg_shell_v6.c | 1 |
11 files changed, 296 insertions, 61 deletions
diff --git a/rootston/config.c b/rootston/config.c index 0c0ad055..92d90de1 100644 --- a/rootston/config.c +++ b/rootston/config.c @@ -26,7 +26,10 @@ static void usage(const char *name, int ret) { " See `rootston.ini.example` for config\n" " file documentation.\n" " -E <COMMAND> Command that will be ran at startup.\n" - " -D Enable damage tracking debugging.\n", + " -D Enable damage tracking debugging.\n" + " -l <LEVEL> Set log verbosity, where,\n" + " 0:SILENT, 1:ERROR, 2:INFO, 3+:DEBUG\n" + " (default: DEBUG)\n", name); exit(ret); @@ -455,7 +458,8 @@ struct roots_config *roots_config_create_from_args(int argc, char *argv[]) { wl_list_init(&config->bindings); int c; - while ((c = getopt(argc, argv, "C:E:hD")) != -1) { + unsigned int log_verbosity = WLR_DEBUG; + while ((c = getopt(argc, argv, "C:E:hDl:")) != -1) { switch (c) { case 'C': config->config_path = strdup(optarg); @@ -466,11 +470,18 @@ struct roots_config *roots_config_create_from_args(int argc, char *argv[]) { case 'D': config->debug_damage_tracking = true; break; + case 'l': + log_verbosity = strtoul(optarg, NULL, 10); + if (log_verbosity >= WLR_LOG_IMPORTANCE_LAST) { + log_verbosity = WLR_LOG_IMPORTANCE_LAST - 1; + } + break; case 'h': case '?': usage(argv[0], c != 'h'); } } + wlr_log_init(log_verbosity, NULL); if (!config->config_path) { // get the config path from the current directory diff --git a/rootston/cursor.c b/rootston/cursor.c index 94f5520e..9a9f9af6 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -101,6 +101,7 @@ static void seat_view_deco_button(struct roots_seat_view *view, double sx, static void roots_passthrough_cursor(struct roots_cursor *cursor, uint32_t time) { + bool focus_changed; double sx, sy; struct roots_view *view = NULL; struct roots_seat *seat = cursor->seat; @@ -136,8 +137,11 @@ static void roots_passthrough_cursor(struct roots_cursor *cursor, } if (surface) { + focus_changed = (seat->seat->pointer_state.focused_surface != surface); wlr_seat_pointer_notify_enter(seat->seat, surface, sx, sy); - wlr_seat_pointer_notify_motion(seat->seat, time, sx, sy); + if (!focus_changed) { + wlr_seat_pointer_notify_motion(seat->seat, time, sx, sy); + } } else { wlr_seat_pointer_clear_focus(seat->seat); } @@ -148,8 +152,8 @@ static void roots_passthrough_cursor(struct roots_cursor *cursor, } } -static void roots_cursor_update_position( - struct roots_cursor *cursor, uint32_t time) { +void roots_cursor_update_position(struct roots_cursor *cursor, + uint32_t time) { struct roots_seat *seat = cursor->seat; struct roots_view *view; switch (cursor->mode) { @@ -266,13 +270,7 @@ static void roots_cursor_press_button(struct roots_cursor *cursor, cursor->mode = ROOTS_CURSOR_PASSTHROUGH; } - switch (state) { - case WLR_BUTTON_RELEASED: - if (!is_touch) { - roots_cursor_update_position(cursor, time); - } - break; - case WLR_BUTTON_PRESSED: + if (state == WLR_BUTTON_PRESSED) { if (view) { roots_seat_set_focus(seat, view); } @@ -283,7 +281,6 @@ static void roots_cursor_press_button(struct roots_cursor *cursor, roots_seat_set_focus_layer(seat, layer); } } - break; } } diff --git a/rootston/desktop.c b/rootston/desktop.c index 3f9faf24..efb7581a 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -9,11 +9,11 @@ #include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_export_dmabuf_v1.h> #include <wlr/types/wlr_gamma_control.h> +#include <wlr/types/wlr_gamma_control_v1.h> #include <wlr/types/wlr_idle_inhibit_v1.h> #include <wlr/types/wlr_idle.h> #include <wlr/types/wlr_input_inhibitor.h> #include <wlr/types/wlr_layer_shell.h> -#include <wlr/types/wlr_linux_dmabuf.h> #include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_primary_selection.h> #include <wlr/types/wlr_server_decoration.h> @@ -423,6 +423,7 @@ struct roots_subsurface *subsurface_create(struct roots_view *view, view_child_init(&subsurface->view_child, view, wlr_subsurface->surface); subsurface->destroy.notify = subsurface_handle_destroy; wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); + input_update_cursor_focus(view->desktop->server->input); return subsurface; } @@ -468,6 +469,7 @@ void view_map(struct roots_view *view, struct wlr_surface *surface) { wl_list_insert(&view->desktop->views, &view->link); view_damage_whole(view); + input_update_cursor_focus(view->desktop->server->input); } void view_unmap(struct roots_view *view) { @@ -550,6 +552,23 @@ void view_update_size(struct roots_view *view, uint32_t width, uint32_t height) view_damage_whole(view); } +void view_update_decorated(struct roots_view *view, bool decorated) { + if (view->decorated == decorated) { + return; + } + + view_damage_whole(view); + view->decorated = decorated; + if (decorated) { + view->border_width = 4; + view->titlebar_height = 12; + } else { + view->border_width = 0; + view->titlebar_height = 0; + } + view_damage_whole(view); +} + static bool view_at(struct roots_view *view, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) { if (view->type == ROOTS_WL_SHELL_VIEW && @@ -849,6 +868,8 @@ struct roots_desktop *desktop_create(struct roots_server *server, desktop->gamma_control_manager = wlr_gamma_control_manager_create( server->wl_display); + desktop->gamma_control_manager_v1 = wlr_gamma_control_manager_v1_create( + server->wl_display); desktop->screenshooter = wlr_screenshooter_create(server->wl_display); desktop->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display); @@ -871,9 +892,6 @@ struct roots_desktop *desktop_create(struct roots_server *server, wl_signal_add(&desktop->input_inhibit->events.deactivate, &desktop->input_inhibit_deactivate); - desktop->linux_dmabuf = wlr_linux_dmabuf_create(server->wl_display, - server->renderer); - desktop->virtual_keyboard = wlr_virtual_keyboard_manager_v1_create( server->wl_display); wl_signal_add(&desktop->virtual_keyboard->events.new_virtual_keyboard, @@ -882,6 +900,12 @@ struct roots_desktop *desktop_create(struct roots_server *server, desktop->screencopy = wlr_screencopy_manager_v1_create(server->wl_display); + desktop->xdg_decoration_manager = + wlr_xdg_decoration_manager_v1_create(server->wl_display); + wl_signal_add(&desktop->xdg_decoration_manager->events.new_toplevel_decoration, + &desktop->xdg_toplevel_decoration); + desktop->xdg_toplevel_decoration.notify = handle_xdg_toplevel_decoration; + return desktop; } diff --git a/rootston/input.c b/rootston/input.c index 84b5acae..b7a5f1ba 100644 --- a/rootston/input.c +++ b/rootston/input.c @@ -1,5 +1,7 @@ +#define _POSIX_C_SOURCE 200112L #include <assert.h> #include <stdlib.h> +#include <time.h> #include <wayland-server.h> #include <wlr/backend/libinput.h> #include <wlr/config.h> @@ -126,3 +128,16 @@ bool input_view_has_focus(struct roots_input *input, struct roots_view *view) { return false; } + +static inline int64_t timespec_to_msec(const struct timespec *a) { + return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000; +} + +void input_update_cursor_focus(struct roots_input *input) { + struct roots_seat *seat; + struct timespec now; + wl_list_for_each(seat, &input->seats, link) { + clock_gettime(CLOCK_MONOTONIC, &now); + roots_cursor_update_position(seat->cursor, timespec_to_msec(&now)); + } +} diff --git a/rootston/keyboard.c b/rootston/keyboard.c index 6697ca83..b5a8093b 100644 --- a/rootston/keyboard.c +++ b/rootston/keyboard.c @@ -2,6 +2,7 @@ #include <stdbool.h> #include <stdint.h> #include <stdlib.h> +#include <sys/wait.h> #include <unistd.h> #include <wayland-server.h> #include <wlr/backend/multi.h> @@ -84,6 +85,39 @@ static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms, } } +static void double_fork_shell_cmd(const char *shell_cmd) { + pid_t pid = fork(); + if (pid < 0) { + wlr_log(WLR_ERROR, "cannot execute binding command: fork() failed"); + return; + } + + if (pid == 0) { + pid = fork(); + if (pid == 0) { + execl("/bin/sh", "/bin/sh", "-c", shell_cmd, NULL); + _exit(EXIT_FAILURE); + } else { + _exit(pid == -1); + } + } + + int status; + while (waitpid(pid, &status, 0) < 0) { + if (errno == EINTR) { + continue; + } + wlr_log_errno(WLR_ERROR, "waitpid() on first child failed"); + return; + } + + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + return; + } + + wlr_log(WLR_ERROR, "first child failed to fork command"); +} + static const char *exec_prefix = "exec "; static bool outputs_enabled = true; @@ -113,13 +147,7 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard, } } else if (strncmp(exec_prefix, command, strlen(exec_prefix)) == 0) { const char *shell_cmd = command + strlen(exec_prefix); - pid_t pid = fork(); - if (pid < 0) { - wlr_log(WLR_ERROR, "cannot execute binding command: fork() failed"); - return; - } else if (pid == 0) { - execl("/bin/sh", "/bin/sh", "-c", shell_cmd, (void *)NULL); - } + double_fork_shell_cmd(shell_cmd); } else if (strcmp(command, "maximize") == 0) { struct roots_view *focus = roots_seat_get_focus(seat); if (focus != NULL) { @@ -133,6 +161,21 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard, wl_list_for_each(output, &keyboard->input->server->desktop->outputs, link) { wlr_output_enable(output->wlr_output, outputs_enabled); } + } else if (strcmp(command, "toggle_decoration_mode") == 0) { + struct roots_view *focus = roots_seat_get_focus(seat); + if (focus != NULL && focus->type == ROOTS_XDG_SHELL_VIEW) { + struct roots_xdg_toplevel_decoration *decoration = + focus->roots_xdg_surface->xdg_toplevel_decoration; + if (decoration != NULL) { + enum wlr_xdg_toplevel_decoration_v1_mode mode = + decoration->wlr_decoration->current_mode; + mode = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE + ? WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE + : WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; + wlr_xdg_toplevel_decoration_v1_set_mode( + decoration->wlr_decoration, mode); + } + } } else { wlr_log(WLR_ERROR, "unknown binding command: %s", command); } diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c index ba69c3db..39054079 100644 --- a/rootston/layer_shell.c +++ b/rootston/layer_shell.c @@ -1,6 +1,12 @@ +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112L +#endif #include <assert.h> +#include <errno.h> #include <stdbool.h> #include <stdlib.h> +#include <string.h> +#include <time.h> #include <wayland-server.h> #include <wlr/types/wlr_box.h> #include <wlr/types/wlr_surface.h> @@ -73,13 +79,38 @@ static void apply_exclusive(struct wlr_box *usable_area, } } -static void arrange_layer(struct wlr_output *output, struct wl_list *list, +static void update_cursors(struct roots_layer_surface *roots_surface, + struct wl_list *seats /* struct roots_seat */) { + struct roots_seat *seat; + wl_list_for_each(seat, seats, link) { + double sx, sy; + + struct wlr_surface *surface = desktop_surface_at( + seat->input->server->desktop, + seat->cursor->cursor->x, seat->cursor->cursor->y, &sx, &sy, NULL); + + if (surface == roots_surface->layer_surface->surface) { + struct timespec time; + if (clock_gettime(CLOCK_MONOTONIC, &time) == 0) { + roots_cursor_update_position(seat->cursor, + time.tv_sec * 1000 + time.tv_nsec / 1000000); + } else { + wlr_log(WLR_ERROR, "Failed to get time, not updating" + "position. Errno: %s\n", strerror(errno)); + } + } + } +} + +static void arrange_layer(struct wlr_output *output, + struct wl_list *seats /* struct *roots_seat */, + struct wl_list *list /* struct *roots_layer_surface */, struct wlr_box *usable_area, bool exclusive) { struct roots_layer_surface *roots_surface; struct wlr_box full_area = { 0 }; wlr_output_effective_resolution(output, &full_area.width, &full_area.height); - wl_list_for_each(roots_surface, list, link) { + wl_list_for_each_reverse(roots_surface, list, link) { struct wlr_layer_surface *layer = roots_surface->layer_surface; struct wlr_layer_surface_state *state = &layer->current; if (exclusive != (state->exclusive_zone > 0)) { @@ -143,12 +174,25 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list, wlr_layer_surface_close(layer); continue; } + // Apply + struct wlr_box old_geo = roots_surface->geo; roots_surface->geo = box; apply_exclusive(usable_area, state->anchor, state->exclusive_zone, state->margin.top, state->margin.right, state->margin.bottom, state->margin.left); wlr_layer_surface_configure(layer, box.width, box.height); + + // Having a cursor newly end up over the moved layer will not + // automatically send a motion event to the surface. The event needs to + // be synthesized. + // Only update layer surfaces which kept their size (and so buffers) the + // same, because those with resized buffers will be handled separately. + + if (roots_surface->geo.x != old_geo.x + || roots_surface->geo.y != old_geo.y) { + update_cursors(roots_surface, seats); + } } } @@ -158,16 +202,16 @@ void arrange_layers(struct roots_output *output) { &usable_area.width, &usable_area.height); // Arrange exclusive surfaces from top->bottom - arrange_layer(output->wlr_output, + arrange_layer(output->wlr_output, &output->desktop->server->input->seats, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &usable_area, true); - arrange_layer(output->wlr_output, + arrange_layer(output->wlr_output, &output->desktop->server->input->seats, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &usable_area, true); - arrange_layer(output->wlr_output, + arrange_layer(output->wlr_output, &output->desktop->server->input->seats, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &usable_area, true); - arrange_layer(output->wlr_output, + arrange_layer(output->wlr_output, &output->desktop->server->input->seats, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &usable_area, true); memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box)); @@ -180,16 +224,16 @@ void arrange_layers(struct roots_output *output) { } // Arrange non-exlusive surfaces from top->bottom - arrange_layer(output->wlr_output, + arrange_layer(output->wlr_output, &output->desktop->server->input->seats, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &usable_area, false); - arrange_layer(output->wlr_output, + arrange_layer(output->wlr_output, &output->desktop->server->input->seats, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &usable_area, false); - arrange_layer(output->wlr_output, + arrange_layer(output->wlr_output, &output->desktop->server->input->seats, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &usable_area, false); - arrange_layer(output->wlr_output, + arrange_layer(output->wlr_output, &output->desktop->server->input->seats, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &usable_area, false); @@ -238,6 +282,20 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { struct roots_output *output = wlr_output->data; struct wlr_box old_geo = layer->geo; arrange_layers(output); + + // Cursor changes which happen as a consequence of resizing a layer + // surface are applied in arrange_layers. Because the resize happens + // before the underlying surface changes, it will only receive a cursor + // update if the new cursor position crosses the *old* sized surface in + // the *new* layer surface. + // Another cursor move event is needed when the surface actually + // changes. + struct wlr_surface *surface = layer_surface->surface; + if (surface->previous.width != surface->current.width || + surface->previous.height != surface->current.height) { + update_cursors(layer, &output->desktop->server->input->seats); + } + if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) { output_damage_whole_local_surface(output, layer_surface->surface, old_geo.x, old_geo.y, 0); @@ -291,7 +349,10 @@ static void handle_map(struct wl_listener *listener, void *data) { static void handle_unmap(struct wl_listener *listener, void *data) { struct roots_layer_surface *layer = wl_container_of( listener, layer, unmap); + struct wlr_output *wlr_output = layer->layer_surface->output; + struct roots_output *output = wlr_output->data; unmap(layer->layer_surface); + input_update_cursor_focus(output->desktop->server->input); } static void popup_handle_map(struct wl_listener *listener, void *data) { @@ -303,6 +364,7 @@ static void popup_handle_map(struct wl_listener *listener, void *data) { int oy = popup->wlr_popup->geometry.y + layer->geo.y; output_damage_whole_local_surface(output, popup->wlr_popup->base->surface, ox, oy, 0); + input_update_cursor_focus(output->desktop->server->input); } static void popup_handle_unmap(struct wl_listener *listener, void *data) { diff --git a/rootston/meson.build b/rootston/meson.build index 8ab872b5..9d1decce 100644 --- a/rootston/meson.build +++ b/rootston/meson.build @@ -11,12 +11,17 @@ sources = [ 'seat.c', 'virtual_keyboard.c', 'wl_shell.c', - 'xdg_shell_v6.c', 'xdg_shell.c', + 'xdg_shell_v6.c', ] -if get_option('enable-xwayland') - sources += ['xwayland.c'] + +if conf_data.get('WLR_HAS_XWAYLAND', false) + sources += 'xwayland.c' endif + executable( - 'rootston', sources, dependencies: [wlroots, wlr_protos, pixman] + 'rootston', + sources, + dependencies: [wlroots, wlr_protos, pixman], + build_by_default: get_option('rootston'), ) diff --git a/rootston/output.c b/rootston/output.c index 71ccf8bc..8677f491 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -3,6 +3,7 @@ #include <stdbool.h> #include <stdlib.h> #include <time.h> +#include <wlr/backend/drm.h> #include <wlr/config.h> #include <wlr/types/wlr_matrix.h> #include <wlr/types/wlr_compositor.h> @@ -16,7 +17,6 @@ #include "rootston/layers.h" #include "rootston/output.h" #include "rootston/server.h" -#include "backend/drm/drm.h" /** * Rotate a child's position relative to a parent. The parent size is (pw, ph), @@ -822,12 +822,6 @@ void handle_new_output(struct wl_listener *listener, void *data) { wlr_output->model, wlr_output->serial, wlr_output->phys_width, wlr_output->phys_height); - if (!wl_list_empty(&wlr_output->modes)) { - struct wlr_output_mode *mode = - wl_container_of((&wlr_output->modes)->prev, mode, link); - wlr_output_set_mode(wlr_output, mode); - } - struct roots_output *output = calloc(1, sizeof(struct roots_output)); clock_gettime(CLOCK_MONOTONIC, &output->last_frame); output->desktop = desktop; @@ -856,22 +850,28 @@ void handle_new_output(struct wl_listener *listener, void *data) { struct roots_output_config *output_config = roots_config_get_output(config, wlr_output); + + if ((!output_config || output_config->enable) && !wl_list_empty(&wlr_output->modes)) { + struct wlr_output_mode *mode = + wl_container_of(wlr_output->modes.prev, mode, link); + wlr_output_set_mode(wlr_output, mode); + } + if (output_config) { if (output_config->enable) { - struct roots_output_mode_config *mode_config; - if (wlr_output_is_drm(wlr_output)) { + struct roots_output_mode_config *mode_config; wl_list_for_each(mode_config, &output_config->modes, link) { wlr_drm_connector_add_mode(wlr_output, &mode_config->info); } - } else { - if (!wl_list_empty(&output_config->modes)) { - wlr_log(WLR_ERROR, "Can only add modes for DRM backend"); - } + } else if (!wl_list_empty(&output_config->modes)) { + wlr_log(WLR_ERROR, "Can only add modes for DRM backend"); } + if (output_config->mode.width) { set_mode(wlr_output, output_config); } + wlr_output_set_scale(wlr_output, output_config->scale); wlr_output_set_transform(wlr_output, output_config->transform); wlr_output_layout_add(desktop->layout, wlr_output, output_config->x, diff --git a/rootston/seat.c b/rootston/seat.c index f308da52..1ae098bc 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -1,4 +1,4 @@ -#define _POSIX_C_SOURCE 199309L +#define _POSIX_C_SOURCE 200112L #include <assert.h> #include <libinput.h> #include <stdlib.h> @@ -127,13 +127,13 @@ static void handle_tablet_tool_position(struct roots_cursor *cursor, struct wlr_surface *surface = desktop_surface_at(desktop, cursor->cursor->x, cursor->cursor->y, &sx, &sy, &view); struct roots_tablet_tool *roots_tool = tool->data; - + if (!surface) { wlr_tablet_v2_tablet_tool_notify_proximity_out(roots_tool->tablet_v2_tool); /* XXX: TODO: Fallback pointer semantics */ return; } - + if (!wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) { wlr_tablet_v2_tablet_tool_notify_proximity_out(roots_tool->tablet_v2_tool); /* XXX: TODO: Fallback pointer semantics */ @@ -218,7 +218,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) { static void handle_tablet_tool_destroy(struct wl_listener *listener, void *data) { struct roots_tablet_tool *tool = wl_container_of(listener, tool, tool_destroy); - + wl_list_remove(&tool->link); wl_list_remove(&tool->tool_link); @@ -503,16 +503,16 @@ void roots_drag_icon_update_position(struct roots_drag_icon *icon) { struct roots_seat *seat = icon->seat; struct wlr_cursor *cursor = seat->cursor->cursor; if (wlr_icon->is_pointer) { - icon->x = cursor->x + wlr_icon->sx; - icon->y = cursor->y + wlr_icon->sy; + icon->x = cursor->x; + icon->y = cursor->y; } else { struct wlr_touch_point *point = wlr_seat_touch_get_point(seat->seat, wlr_icon->touch_id); if (point == NULL) { return; } - icon->x = seat->touch_x + wlr_icon->sx; - icon->y = seat->touch_y + wlr_icon->sy; + icon->x = seat->touch_x; + icon->y = seat->touch_y; } roots_drag_icon_damage_whole(icon); @@ -746,6 +746,7 @@ static void attach_tablet_pad(struct roots_tablet_pad *pad, pad->tablet = tool; + wl_list_remove(&pad->tablet_destroy.link); pad->tablet_destroy.notify = handle_pad_tool_destroy; wl_signal_add(&tool->device->events.destroy, &pad->tablet_destroy); } @@ -813,7 +814,8 @@ static void seat_add_tablet_pad(struct roots_seat *seat, &tablet_pad->device_destroy); tablet_pad->attach.notify = handle_tablet_pad_attach; - wl_signal_add(&tablet_pad->device->tablet_pad->events.attach_tablet, &tablet_pad->attach); + wl_signal_add(&tablet_pad->device->tablet_pad->events.attach_tablet, + &tablet_pad->attach); tablet_pad->button.notify = handle_tablet_pad_button; wl_signal_add(&tablet_pad->device->tablet_pad->events.button, &tablet_pad->button); @@ -824,6 +826,8 @@ static void seat_add_tablet_pad(struct roots_seat *seat, tablet_pad->ring.notify = handle_tablet_pad_ring; wl_signal_add(&tablet_pad->device->tablet_pad->events.ring, &tablet_pad->ring); + wl_list_init(&tablet_pad->tablet_destroy.link); + struct roots_desktop *desktop = seat->input->server->desktop; tablet_pad->tablet_v2_pad = wlr_tablet_pad_create(desktop->tablet_v2, seat->seat, device); @@ -1125,7 +1129,8 @@ void roots_seat_set_focus(struct roots_seat *seat, struct roots_view *view) { #ifdef WLR_HAS_XWAYLAND if (view && view->type == ROOTS_XWAYLAND_VIEW && - wlr_xwayland_surface_is_unmanaged(view->xwayland_surface)) { + !wlr_xwayland_or_surface_wants_focus( + view->xwayland_surface)) { return; } #endif diff --git a/rootston/xdg_shell.c b/rootston/xdg_shell.c index d04d37e1..2cf2081e 100644 --- a/rootston/xdg_shell.c +++ b/rootston/xdg_shell.c @@ -6,6 +6,7 @@ #include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_xdg_shell.h> #include <wlr/util/log.h> +#include "rootston/cursor.h" #include "rootston/desktop.h" #include "rootston/input.h" #include "rootston/server.h" @@ -33,6 +34,7 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) { static void popup_handle_map(struct wl_listener *listener, void *data) { struct roots_xdg_popup *popup = wl_container_of(listener, popup, map); view_damage_whole(popup->view_child.view); + input_update_cursor_focus(popup->view_child.view->desktop->server->input); } static void popup_handle_unmap(struct wl_listener *listener, void *data) { @@ -263,6 +265,7 @@ static void destroy(struct roots_view *view) { wl_list_remove(&roots_xdg_surface->request_resize.link); wl_list_remove(&roots_xdg_surface->request_maximize.link); wl_list_remove(&roots_xdg_surface->request_fullscreen.link); + roots_xdg_surface->view->xdg_surface->data = NULL; free(roots_xdg_surface); } @@ -437,6 +440,7 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { &roots_surface->request_fullscreen); roots_surface->new_popup.notify = handle_new_popup; wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup); + surface->data = roots_surface; struct roots_view *view = view_create(desktop); if (!view) { @@ -463,3 +467,71 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { view_set_fullscreen(view, true, NULL); } } + + + +static void decoration_handle_destroy(struct wl_listener *listener, + void *data) { + struct roots_xdg_toplevel_decoration *decoration = + wl_container_of(listener, decoration, destroy); + + decoration->surface->xdg_toplevel_decoration = NULL; + view_update_decorated(decoration->surface->view, false); + wl_list_remove(&decoration->destroy.link); + wl_list_remove(&decoration->request_mode.link); + wl_list_remove(&decoration->surface_commit.link); + free(decoration); +} + +static void decoration_handle_request_mode(struct wl_listener *listener, + void *data) { + struct roots_xdg_toplevel_decoration *decoration = + wl_container_of(listener, decoration, request_mode); + + enum wlr_xdg_toplevel_decoration_v1_mode mode = + decoration->wlr_decoration->client_pending_mode; + if (mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_NONE) { + mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; + } + wlr_xdg_toplevel_decoration_v1_set_mode(decoration->wlr_decoration, mode); +} + +static void decoration_handle_surface_commit(struct wl_listener *listener, + void *data) { + struct roots_xdg_toplevel_decoration *decoration = + wl_container_of(listener, decoration, surface_commit); + + bool decorated = decoration->wlr_decoration->current_mode == + WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; + view_update_decorated(decoration->surface->view, decorated); +} + +void handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data) { + struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration = data; + + wlr_log(WLR_DEBUG, "new xdg toplevel decoration"); + + struct roots_xdg_surface *xdg_surface = wlr_decoration->surface->data; + assert(xdg_surface != NULL); + struct wlr_xdg_surface *wlr_xdg_surface = xdg_surface->view->xdg_surface; + + struct roots_xdg_toplevel_decoration *decoration = + calloc(1, sizeof(struct roots_xdg_toplevel_decoration)); + if (decoration == NULL) { + return; + } + decoration->wlr_decoration = wlr_decoration; + decoration->surface = xdg_surface; + xdg_surface->xdg_toplevel_decoration = decoration; + + decoration->destroy.notify = decoration_handle_destroy; + wl_signal_add(&wlr_decoration->events.destroy, &decoration->destroy); + decoration->request_mode.notify = decoration_handle_request_mode; + wl_signal_add(&wlr_decoration->events.request_mode, + &decoration->request_mode); + decoration->surface_commit.notify = decoration_handle_surface_commit; + wl_signal_add(&wlr_xdg_surface->surface->events.commit, + &decoration->surface_commit); + + decoration_handle_request_mode(&decoration->request_mode, wlr_decoration); +} diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c index 219be2b0..1201ba68 100644 --- a/rootston/xdg_shell_v6.c +++ b/rootston/xdg_shell_v6.c @@ -34,6 +34,7 @@ static void popup_handle_map(struct wl_listener *listener, void *data) { struct roots_xdg_popup_v6 *popup = wl_container_of(listener, popup, map); view_damage_whole(popup->view_child.view); + input_update_cursor_focus(popup->view_child.view->desktop->server->input); } static void popup_handle_unmap(struct wl_listener *listener, void *data) { |