aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/desktop/transaction.h7
-rw-r--r--include/sway/tree/view.h3
-rw-r--r--include/swaylock/seat.h6
-rw-r--r--include/swaylock/swaylock.h2
-rw-r--r--sway/commands/focus.c1
-rw-r--r--sway/desktop/transaction.c40
-rw-r--r--sway/desktop/xdg_shell.c9
-rw-r--r--sway/desktop/xdg_shell_v6.c9
-rw-r--r--sway/desktop/xwayland.c14
-rw-r--r--sway/input/cursor.c22
-rw-r--r--sway/input/seat.c7
-rw-r--r--sway/ipc-json.c23
-rw-r--r--sway/tree/view.c7
-rw-r--r--swaybar/bar.c10
-rw-r--r--swaylock/main.c5
-rw-r--r--swaylock/seat.c22
16 files changed, 149 insertions, 38 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 a07bc53b..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;
}
}
@@ -1220,6 +1231,9 @@ static void handle_request_set_cursor(struct wl_listener *listener,
void cursor_set_image(struct sway_cursor *cursor, const char *image,
struct wl_client *client) {
+ if (!(cursor->seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER)) {
+ return;
+ }
if (!image) {
wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
} else if (!cursor->image || strcmp(cursor->image, image) != 0) {
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 16acc8a5..89d841bb 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -389,12 +389,15 @@ static void seat_update_capabilities(struct sway_seat *seat) {
break;
}
}
- wlr_seat_set_capabilities(seat->wlr_seat, caps);
- // Hide cursor if seat doesn't have pointer capability
+ // Hide cursor if seat doesn't have pointer capability.
+ // We must call cursor_set_image while the wlr_seat has the capabilities
+ // otherwise it's a no op.
if ((caps & WL_SEAT_CAPABILITY_POINTER) == 0) {
cursor_set_image(seat->cursor, NULL, NULL);
+ wlr_seat_set_capabilities(seat->wlr_seat, caps);
} else {
+ wlr_seat_set_capabilities(seat->wlr_seat, caps);
cursor_set_image(seat->cursor, "left_ptr", NULL);
}
}
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/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 3661c637..08c386a7 100644
--- a/swaybar/bar.c
+++ b/swaybar/bar.c
@@ -26,11 +26,6 @@
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
-static void bar_init(struct swaybar *bar) {
- bar->config = init_config();
- wl_list_init(&bar->outputs);
-}
-
void free_workspaces(struct wl_list *list) {
struct swaybar_workspace *ws, *tmp;
wl_list_for_each_safe(ws, tmp, list, link) {
@@ -327,7 +322,9 @@ static const struct wl_registry_listener registry_listener = {
};
bool bar_setup(struct swaybar *bar, const char *socket_path) {
- bar_init(bar);
+ bar->visible = true;
+ bar->config = init_config();
+ wl_list_init(&bar->outputs);
bar->eventloop = loop_create();
bar->ipc_socketfd = ipc_open_socket(socket_path);
@@ -376,7 +373,6 @@ bool bar_setup(struct swaybar *bar, const char *socket_path) {
pointer->cursor_surface = wl_compositor_create_surface(bar->compositor);
assert(pointer->cursor_surface);
- bar->visible = true;
if (bar->config->workspace_buttons) {
ipc_get_workspaces(bar);
}
diff --git a/swaylock/main.c b/swaylock/main.c
index ebc2b263..9b74b671 100644
--- a/swaylock/main.c
+++ b/swaylock/main.c
@@ -280,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);
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);
}
}