aboutsummaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
Diffstat (limited to 'sway')
-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
9 files changed, 115 insertions, 17 deletions
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) {