diff options
-rw-r--r-- | include/sway/desktop/transaction.h | 7 | ||||
-rw-r--r-- | include/sway/tree/view.h | 3 | ||||
-rw-r--r-- | include/swaylock/seat.h | 6 | ||||
-rw-r--r-- | include/swaylock/swaylock.h | 2 | ||||
-rw-r--r-- | sway/commands/focus.c | 1 | ||||
-rw-r--r-- | sway/desktop/transaction.c | 40 | ||||
-rw-r--r-- | sway/desktop/xdg_shell.c | 9 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 9 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 14 | ||||
-rw-r--r-- | sway/input/cursor.c | 19 | ||||
-rw-r--r-- | sway/ipc-json.c | 23 | ||||
-rw-r--r-- | sway/sway-output.5.scd | 7 | ||||
-rw-r--r-- | sway/tree/root.c | 4 | ||||
-rw-r--r-- | sway/tree/view.c | 7 | ||||
-rw-r--r-- | swaybar/bar.c | 5 | ||||
-rw-r--r-- | swaylock/main.c | 20 | ||||
-rw-r--r-- | swaylock/password.c | 6 | ||||
-rw-r--r-- | swaylock/seat.c | 22 |
18 files changed, 169 insertions, 35 deletions
diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h index 66e8c9a2..f38f033c 100644 --- a/include/sway/desktop/transaction.h +++ b/include/sway/desktop/transaction.h @@ -29,6 +29,13 @@ struct sway_view; void transaction_commit_dirty(void); /** + * Same as above, but runs the specific callback when the transaction is + * applied. + */ +void transaction_commit_dirty_with_callback( + void (*callback)(void *data), void *data); + +/** * Notify the transaction system that a view is ready for the new layout. * * When all views in the transaction are ready, the layout will be applied. diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index a0b4dd46..0240f294 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -30,6 +30,7 @@ enum sway_view_prop { VIEW_PROP_WINDOW_ROLE, #ifdef HAVE_XWAYLAND VIEW_PROP_X11_WINDOW_ID, + VIEW_PROP_X11_PARENT_ID, #endif }; @@ -256,6 +257,8 @@ const char *view_get_instance(struct sway_view *view); uint32_t view_get_x11_window_id(struct sway_view *view); +uint32_t view_get_x11_parent_id(struct sway_view *view); + const char *view_get_window_role(struct sway_view *view); uint32_t view_get_window_type(struct sway_view *view); diff --git a/include/swaylock/seat.h b/include/swaylock/seat.h index 4bcf40c0..c79afcd0 100644 --- a/include/swaylock/seat.h +++ b/include/swaylock/seat.h @@ -10,6 +10,12 @@ struct swaylock_xkb { struct xkb_keymap *keymap; }; +struct swaylock_seat { + struct swaylock_state *state; + struct wl_pointer *pointer; + struct wl_keyboard *keyboard; +}; + extern const struct wl_seat_listener seat_listener; #endif diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index 25b41a71..18af7ab4 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -62,8 +62,6 @@ struct swaylock_state { struct wl_compositor *compositor; struct zwlr_layer_shell_v1 *layer_shell; struct zwlr_input_inhibit_manager_v1 *input_inhibit_manager; - struct wl_pointer *pointer; - struct wl_keyboard *keyboard; struct wl_shm *shm; struct wl_list surfaces; struct wl_list images; diff --git a/sway/commands/focus.c b/sway/commands/focus.c index 7dfa8814..81af8e0f 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -294,6 +294,7 @@ struct cmd_results *cmd_focus(int argc, char **argv) { if (next_focus) { seat_set_focus(seat, next_focus); seat_consider_warp_to_focus(seat); + cursor_rebase(seat->cursor); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c index 5dec279d..b2f7f922 100644 --- a/sway/desktop/transaction.c +++ b/sway/desktop/transaction.c @@ -25,6 +25,8 @@ struct sway_transaction { size_t num_waiting; size_t num_configures; struct timespec commit_time; + void (*callback)(void *data); + void *callback_data; }; struct sway_transaction_instruction { @@ -295,6 +297,10 @@ static void transaction_apply(struct sway_transaction *transaction) { node->instruction = NULL; } + + if (transaction->callback) { + transaction->callback(transaction->callback_data); + } } static void transaction_commit(struct sway_transaction *transaction); @@ -499,14 +505,7 @@ void transaction_notify_view_ready_by_size(struct sway_view *view, } } -void transaction_commit_dirty(void) { - if (!server.dirty_nodes->length) { - return; - } - struct sway_transaction *transaction = transaction_create(); - if (!transaction) { - return; - } +static void do_commit_dirty(struct sway_transaction *transaction) { for (int i = 0; i < server.dirty_nodes->length; ++i) { struct sway_node *node = server.dirty_nodes->items[i]; transaction_add_node(transaction, node); @@ -525,3 +524,28 @@ void transaction_commit_dirty(void) { transaction_progress_queue(); } } + +void transaction_commit_dirty(void) { + if (!server.dirty_nodes->length) { + return; + } + struct sway_transaction *transaction = transaction_create(); + if (!transaction) { + return; + } + do_commit_dirty(transaction); +} + +void transaction_commit_dirty_with_callback( + void (*callback)(void *data), void *data) { + if (!server.dirty_nodes->length) { + return; + } + struct sway_transaction *transaction = transaction_create(); + if (!transaction) { + return; + } + transaction->callback = callback; + transaction->callback_data = data; + do_commit_dirty(transaction); +} diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index fda1bdef..064e2707 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -9,6 +9,7 @@ #include "sway/decoration.h" #include "sway/desktop.h" #include "sway/desktop/transaction.h" +#include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/output.h" @@ -396,6 +397,11 @@ static void handle_unmap(struct wl_listener *listener, void *data) { wl_list_remove(&xdg_shell_view->set_app_id.link); } +static void do_rebase(void *data) { + struct sway_cursor *cursor = data; + cursor_rebase(cursor); +} + static void handle_map(struct wl_listener *listener, void *data) { struct sway_xdg_shell_view *xdg_shell_view = wl_container_of(listener, xdg_shell_view, map); @@ -422,7 +428,8 @@ static void handle_map(struct wl_listener *listener, void *data) { view_map(view, view->wlr_xdg_surface->surface, xdg_surface->toplevel->client_pending.fullscreen, csd); - transaction_commit_dirty(); + struct sway_seat *seat = input_manager_current_seat(); + transaction_commit_dirty_with_callback(do_rebase, seat->cursor); xdg_shell_view->commit.notify = handle_commit; wl_signal_add(&xdg_surface->surface->events.commit, diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 7159f1ed..90bf55b2 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -8,6 +8,7 @@ #include "sway/decoration.h" #include "sway/desktop.h" #include "sway/desktop/transaction.h" +#include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/output.h" @@ -393,6 +394,11 @@ static void handle_unmap(struct wl_listener *listener, void *data) { wl_list_remove(&xdg_shell_v6_view->set_app_id.link); } +static void do_rebase(void *data) { + struct sway_cursor *cursor = data; + cursor_rebase(cursor); +} + static void handle_map(struct wl_listener *listener, void *data) { struct sway_xdg_shell_v6_view *xdg_shell_v6_view = wl_container_of(listener, xdg_shell_v6_view, map); @@ -413,7 +419,8 @@ static void handle_map(struct wl_listener *listener, void *data) { view_map(view, view->wlr_xdg_surface_v6->surface, xdg_surface->toplevel->client_pending.fullscreen, csd); - transaction_commit_dirty(); + struct sway_seat *seat = input_manager_current_seat(); + transaction_commit_dirty_with_callback(do_rebase, seat->cursor); xdg_shell_v6_view->commit.notify = handle_commit; wl_signal_add(&xdg_surface->surface->events.commit, diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 5305ce12..95275937 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -8,6 +8,7 @@ #include "log.h" #include "sway/desktop.h" #include "sway/desktop/transaction.h" +#include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "sway/output.h" @@ -171,6 +172,11 @@ static uint32_t get_int_prop(struct sway_view *view, enum sway_view_prop prop) { switch (prop) { case VIEW_PROP_X11_WINDOW_ID: return view->wlr_xwayland_surface->window_id; + case VIEW_PROP_X11_PARENT_ID: + if (view->wlr_xwayland_surface->parent) { + return view->wlr_xwayland_surface->parent->window_id; + } + return 0; case VIEW_PROP_WINDOW_TYPE: return *view->wlr_xwayland_surface->window_type; default: @@ -385,6 +391,11 @@ static void handle_unmap(struct wl_listener *listener, void *data) { wl_list_remove(&xwayland_view->commit.link); } +static void do_rebase(void *data) { + struct sway_cursor *cursor = data; + cursor_rebase(cursor); +} + static void handle_map(struct wl_listener *listener, void *data) { struct sway_xwayland_view *xwayland_view = wl_container_of(listener, xwayland_view, map); @@ -411,7 +422,8 @@ static void handle_map(struct wl_listener *listener, void *data) { // Put it back into the tree view_map(view, xsurface->surface, xsurface->fullscreen, false); - transaction_commit_dirty(); + struct sway_seat *seat = input_manager_current_seat(); + transaction_commit_dirty_with_callback(do_rebase, seat->cursor); } static void handle_request_configure(struct wl_listener *listener, void *data) { diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 60d4bf5d..3942b64f 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -996,8 +996,9 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor, if (on_titlebar) { enum sway_container_layout layout = container_parent_layout(cont); if (layout == L_TABBED || layout == L_STACKED) { + struct sway_node *tabcontainer = node_get_parent(node); struct sway_node *active = - seat_get_active_tiling_child(seat, node_get_parent(node)); + seat_get_active_tiling_child(seat, tabcontainer); list_t *siblings = container_get_siblings(cont); int desired = list_find(siblings, active->sway_container) + event->delta_discrete; @@ -1006,9 +1007,19 @@ static void dispatch_cursor_axis(struct sway_cursor *cursor, } else if (desired >= siblings->length) { desired = siblings->length - 1; } - struct sway_container *new_focus = siblings->items[desired]; - node = seat_get_focus_inactive(seat, &new_focus->node); - seat_set_focus(seat, node); + struct sway_node *old_focus = seat_get_focus(seat); + struct sway_container *new_sibling_con = siblings->items[desired]; + struct sway_node *new_sibling = &new_sibling_con->node; + struct sway_node *new_focus = + seat_get_focus_inactive(seat, new_sibling); + if (node_has_ancestor(old_focus, tabcontainer)) { + seat_set_focus(seat, new_focus); + } else { + // Scrolling when focus is not in the tabbed container at all + seat_set_raw_focus(seat, new_sibling); + seat_set_raw_focus(seat, new_focus); + seat_set_raw_focus(seat, old_focus); + } return; } } diff --git a/sway/ipc-json.c b/sway/ipc-json.c index a29647ed..2cd0cb2d 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -266,6 +266,29 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object if (c->view->type == SWAY_VIEW_XWAYLAND) { json_object_object_add(object, "window", json_object_new_int(view_get_x11_window_id(c->view))); + + json_object *window_props = json_object_new_object(); + + json_object_object_add(window_props, "class", + class ? json_object_new_string(class) : NULL); + const char *instance = view_get_instance(c->view); + json_object_object_add(window_props, "instance", + instance ? json_object_new_string(instance) : NULL); + json_object_object_add(window_props, "title", + c->title ? json_object_new_string(c->title) : NULL); + + // the transient_for key is always present in i3's output + uint32_t parent_id = view_get_x11_parent_id(c->view); + json_object_object_add(window_props, "transient_for", + parent_id ? json_object_new_int(parent_id) : NULL); + + const char *role = view_get_window_role(c->view); + if (role) { + json_object_object_add(window_props, "window_role", + json_object_new_string(role)); + } + + json_object_object_add(object, "window_properties", window_props); } #endif } diff --git a/sway/sway-output.5.scd b/sway/sway-output.5.scd index fe5b33bc..1b456008 100644 --- a/sway/sway-output.5.scd +++ b/sway/sway-output.5.scd @@ -13,6 +13,13 @@ You may combine output commands into one, like so: You can get a list of output names with *swaymsg -t get\_outputs*. You may also match any output by using the output name "\*". +Some outputs may have different names when disconnecting and reconnecting. To +identify these, the name can be substituted for a string consisting of the make, +model and serial which you can get from *swaymsg -t get\_outputs*. Each value +must be separated by one space. For example: + + output "Some Company ABC123 0x00000000" pos 1920,0 + # COMMANDS *output* <name> mode|resolution|res <WIDTHxHEIGHT>[@<RATE>[Hz]] diff --git a/sway/tree/root.c b/sway/tree/root.c index e5eb8f2a..9bda7c28 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -59,13 +59,13 @@ void root_scratchpad_add_container(struct sway_container *con) { if (!sway_assert(!con->scratchpad, "Container is already in scratchpad")) { return; } - con->scratchpad = true; - list_add(root->scratchpad, con); struct sway_container *parent = con->parent; struct sway_workspace *workspace = con->workspace; container_set_floating(con, true); container_detach(con); + con->scratchpad = true; + list_add(root->scratchpad, con); struct sway_seat *seat = input_manager_current_seat(); if (parent) { diff --git a/sway/tree/view.c b/sway/tree/view.c index a8486dd7..20babf7b 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -116,6 +116,13 @@ uint32_t view_get_x11_window_id(struct sway_view *view) { } return 0; } + +uint32_t view_get_x11_parent_id(struct sway_view *view) { + if (view->impl->get_int_prop) { + return view->impl->get_int_prop(view, VIEW_PROP_X11_PARENT_ID); + } + return 0; +} #endif const char *view_get_window_role(struct sway_view *view) { if (view->impl->get_string_prop) { diff --git a/swaybar/bar.c b/swaybar/bar.c index 88de8c04..08c386a7 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -415,7 +415,10 @@ void bar_run(struct swaybar *bar) { status_in, bar); } while (1) { - wl_display_flush(bar->display); + errno = 0; + if (wl_display_flush(bar->display) == -1 && errno != EAGAIN) { + break; + } loop_poll(bar->eventloop); } } diff --git a/swaylock/main.c b/swaylock/main.c index f2bb5c3e..9b74b671 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -2,6 +2,7 @@ #define _POSIX_C_SOURCE 200112L #include <assert.h> #include <ctype.h> +#include <errno.h> #include <fcntl.h> #include <getopt.h> #include <stdbool.h> @@ -279,7 +280,10 @@ static void handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, wl_seat_interface.name) == 0) { struct wl_seat *seat = wl_registry_bind( registry, name, &wl_seat_interface, 3); - wl_seat_add_listener(seat, &seat_listener, state); + struct swaylock_seat *swaylock_seat = + calloc(1, sizeof(struct swaylock_seat)); + swaylock_seat->state = state; + wl_seat_add_listener(seat, &seat_listener, swaylock_seat); } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { state->layer_shell = wl_registry_bind( registry, name, &zwlr_layer_shell_v1_interface, 1); @@ -841,7 +845,9 @@ static int load_config(char *path, struct swaylock_state *state, static struct swaylock_state state; static void display_in(int fd, short mask, void *data) { - wl_display_dispatch(state.display); + if (wl_display_dispatch(state.display) == -1) { + state.run_display = false; + } } int main(int argc, char **argv) { @@ -925,6 +931,11 @@ int main(int argc, char **argv) { } zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager); + if (wl_display_roundtrip(state.display) == -1) { + wlr_log(WLR_ERROR, "Exiting - failed to inhibit input:" + " is another lockscreen already running?"); + return 2; + } if (state.zxdg_output_manager) { struct swaylock_surface *surface; @@ -956,7 +967,10 @@ int main(int argc, char **argv) { state.run_display = true; while (state.run_display) { - wl_display_flush(state.display); + errno = 0; + if (wl_display_flush(state.display) == -1 && errno != EAGAIN) { + break; + } loop_poll(state.eventloop); } diff --git a/swaylock/password.c b/swaylock/password.c index fecaecbf..6138e1fe 100644 --- a/swaylock/password.c +++ b/swaylock/password.c @@ -1,5 +1,6 @@ #define _XOPEN_SOURCE 500 #include <assert.h> +#include <errno.h> #include <pwd.h> #include <stdlib.h> #include <string.h> @@ -97,7 +98,10 @@ void swaylock_handle_key(struct swaylock_state *state, state->eventloop, 50, handle_preverify_timeout, state); while (state->run_display && state->verify_password_timer) { - wl_display_flush(state->display); + errno = 0; + if (wl_display_flush(state->display) == -1 && errno != EAGAIN) { + break; + } loop_poll(state->eventloop); bool ok = 1; diff --git a/swaylock/seat.c b/swaylock/seat.c index 22dd9360..7b72114f 100644 --- a/swaylock/seat.c +++ b/swaylock/seat.c @@ -144,22 +144,22 @@ static const struct wl_pointer_listener pointer_listener = { static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { - struct swaylock_state *state = data; - if (state->pointer) { - wl_pointer_release(state->pointer); - state->pointer = NULL; + struct swaylock_seat *seat = data; + if (seat->pointer) { + wl_pointer_release(seat->pointer); + seat->pointer = NULL; } - if (state->keyboard) { - wl_keyboard_release(state->keyboard); - state->keyboard = NULL; + if (seat->keyboard) { + wl_keyboard_release(seat->keyboard); + seat->keyboard = NULL; } if ((caps & WL_SEAT_CAPABILITY_POINTER)) { - state->pointer = wl_seat_get_pointer(wl_seat); - wl_pointer_add_listener(state->pointer, &pointer_listener, NULL); + seat->pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(seat->pointer, &pointer_listener, NULL); } if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) { - state->keyboard = wl_seat_get_keyboard(wl_seat); - wl_keyboard_add_listener(state->keyboard, &keyboard_listener, state); + seat->keyboard = wl_seat_get_keyboard(wl_seat); + wl_keyboard_add_listener(seat->keyboard, &keyboard_listener, seat->state); } } |