aboutsummaryrefslogtreecommitdiff
path: root/rootston
diff options
context:
space:
mode:
Diffstat (limited to 'rootston')
-rw-r--r--rootston/config.c15
-rw-r--r--rootston/cursor.c19
-rw-r--r--rootston/desktop.c32
-rw-r--r--rootston/input.c15
-rw-r--r--rootston/keyboard.c57
-rw-r--r--rootston/layer_shell.c82
-rw-r--r--rootston/meson.build13
-rw-r--r--rootston/output.c26
-rw-r--r--rootston/seat.c25
-rw-r--r--rootston/xdg_shell.c72
-rw-r--r--rootston/xdg_shell_v6.c1
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) {