Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure focus consistency #123

Merged
merged 4 commits into from
Nov 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions include/viv_seat.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ struct viv_seat *viv_seat_create(struct viv_server *server, char *name);

void viv_seat_begin_interactive(struct viv_seat *seat, struct viv_view *view, enum viv_cursor_mode mode, uint32_t edges);

/// Give keyboard focus to the given surface
void viv_seat_focus_surface(struct viv_seat *seat, struct wlr_surface *surface);
/// Give keyboard focus to the given layer_view
void viv_seat_focus_layer_view(struct viv_seat *seat, struct viv_layer_view *view);

/// Give keyboard focus to the given view
void viv_seat_focus_view(struct viv_seat *seat, struct viv_view *view);

/// Clear the focus
void viv_seat_clear_focus(struct viv_seat *seat);

/// Create a new viv_keyboard in the given seat
void viv_seat_create_new_keyboard(struct viv_seat *seat, struct wlr_input_device *device);
Expand Down
1 change: 0 additions & 1 deletion include/viv_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ struct viv_view_implementation {
void (*get_geometry)(struct viv_view *view, struct wlr_box *geo_box);
void (*set_tiled)(struct viv_view *view, uint32_t edges);
void (*get_string_identifier)(struct viv_view *view, char *output, size_t max_len);
void (*set_activated)(struct viv_view *view, bool activated);
struct wlr_surface *(*get_toplevel_surface)(struct viv_view *view);
void (*close)(struct viv_view *view);
bool (*is_at)(struct viv_view *view, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy);
Expand Down
9 changes: 2 additions & 7 deletions include/viv_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ void viv_view_bring_to_front(struct viv_view *view);
/// Clear focus from all views handled by the server;
void viv_view_clear_all_focus(struct viv_server *server);

/// Make the given view and surface the current focus of keyboard input, and the active
/// Make the given view the current focus of keyboard input, and the active
/// view in the current workspace
void viv_view_focus(struct viv_view *view, struct wlr_surface *surface);
void viv_view_focus(struct viv_view *view);

/// Mark the given view as floating, and trigger a workspace layout update if necessary
void viv_view_ensure_floating(struct viv_view *view);
Expand Down Expand Up @@ -46,9 +46,6 @@ bool viv_view_oversized(struct viv_view *view);
/// Mark the view as damaged on every output
void viv_view_damage(struct viv_view *view);

/// Make the given view the active view within its workspace
void viv_view_make_active(struct viv_view *view);

/// Set the size of a view
void viv_view_set_size(struct viv_view *view, uint32_t width, uint32_t height);

Expand All @@ -65,8 +62,6 @@ void viv_view_init(struct viv_view *view, struct viv_server *server);
/// Clear up view state, remove it from its workspace, and free its memory
void viv_view_destroy(struct viv_view *view);

void viv_view_set_activated(struct viv_view *view, bool activated);

/// Get the wlr_surface that is the main/toplevel surface for this view
struct wlr_surface *viv_view_get_toplevel_surface(struct viv_view *view);

Expand Down
2 changes: 0 additions & 2 deletions include/viv_workspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ void viv_workspace_increment_divide(struct viv_workspace *workspace, float incre

void viv_workspace_increment_counter(struct viv_workspace *workspace, uint32_t increment);

void viv_workspace_swap_out(struct viv_output *output, struct wl_list *workspaces);

void viv_workspace_focus_next_window(struct viv_workspace *workspace);
void viv_workspace_focus_prev_window(struct viv_workspace *workspace);

Expand Down
4 changes: 2 additions & 2 deletions src/viv_cursor.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static void process_cursor_pass_through_to_surface(struct viv_seat *seat, uint32
// Act appropriately on whatever view type was found
if (layer_view) {
if (layer_view_wants_keyboard_focus(layer_view)) {
viv_seat_focus_surface(seat, surface);
viv_seat_focus_layer_view(seat, layer_view);
server->active_output->current_workspace->active_view = NULL;
}
} else if (view) {
Expand All @@ -132,7 +132,7 @@ static void process_cursor_pass_through_to_surface(struct viv_seat *seat, uint32
}

if ((view != active_view) && server->config->focus_follows_mouse) {
viv_view_focus(view, surface);
viv_view_focus(view);
}
} else {
// No focusable surface under the cursor => use the default image
Expand Down
4 changes: 2 additions & 2 deletions src/viv_layer_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static void layer_surface_map(struct wl_listener *listener, void *data) {

if (layer_view->layer_surface->current.keyboard_interactive) {
struct viv_seat *seat = viv_server_get_default_seat(layer_view->server);
viv_seat_focus_surface(seat, layer_view->layer_surface->surface);
viv_seat_focus_layer_view(seat, layer_view);
}
}

Expand All @@ -58,7 +58,7 @@ static void layer_surface_unmap(struct wl_listener *listener, void *data) {
}

if (active_view != NULL) {
viv_view_focus(active_view, NULL);
viv_view_focus(active_view);
}

if (layer_view->surface_tree) {
Expand Down
14 changes: 9 additions & 5 deletions src/viv_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ void viv_output_make_active(struct viv_output *output) {
viv_output_damage(output->server->active_output);

if (output->current_workspace->active_view) {
viv_view_focus(output->current_workspace->active_view, NULL);
viv_view_focus(output->current_workspace->active_view);
}
}

Expand Down Expand Up @@ -232,15 +232,19 @@ void viv_output_display_workspace(struct viv_output *output, struct viv_workspac
output->current_workspace->output = NULL;
}

output->current_workspace = workspace;
output->current_workspace->output = output;
viv_output_mark_for_relayout(output);

if (workspace->active_view) {
viv_view_focus(workspace->active_view, NULL);
viv_view_focus(workspace->active_view);
} else {
viv_view_clear_all_focus(output->server);
}

output->current_workspace = workspace;
output->current_workspace->output = output;
viv_output_mark_for_relayout(output);
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
viv_cursor_reset_focus(workspace->server, (int64_t)now.tv_sec * 1000 + now.tv_nsec / 1000000);
}

void viv_output_init(struct viv_output *output, struct viv_server *server, struct wlr_output *wlr_output) {
Expand Down
55 changes: 44 additions & 11 deletions src/viv_seat.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,19 +143,36 @@ void viv_seat_create_new_keyboard(struct viv_seat *seat, struct wlr_input_device
/* And add the keyboard to our list of keyboards */
wl_list_insert(&seat->keyboards, &keyboard->link);
}

void viv_seat_focus_surface(struct viv_seat *seat, struct wlr_surface *surface) {
ASSERT(surface != NULL);
static void focus_surface(struct viv_seat *seat, struct wlr_surface *surface) {
struct wlr_seat *wlr_seat = seat->wlr_seat;
struct wlr_surface *prev_surface = wlr_seat->keyboard_state.focused_surface;
if (prev_surface == surface) {
/* Don't re-focus an already focused surface. */
return;
}

if (!viv_seat_input_allowed(seat, surface)) {
wlr_log(WLR_DEBUG, "Denied focus change to surface %p, surface not owned by the exclusive client", surface);
return;
if (surface) {
if (!viv_seat_input_allowed(seat, surface)) {
wlr_log(WLR_DEBUG, "Denied focus change to surface %p, surface not owned by the exclusive client", surface);
return;
}

if (wlr_surface_is_xdg_surface(surface)) {
struct wlr_xdg_surface *next = wlr_xdg_surface_from_wlr_surface(surface);
wlr_xdg_toplevel_set_activated(next, true);
#ifdef XWAYLAND
} else if (wlr_surface_is_xwayland_surface(surface)) {
struct wlr_xwayland_surface *next = wlr_xwayland_surface_from_wlr_surface(surface);

// Don't change focus for popups
if (next->override_redirect) {
return;
}

wlr_xwayland_surface_activate(next, true);
wlr_xwayland_surface_restack(next, NULL, XCB_STACK_MODE_ABOVE);
#endif
}
}

if (prev_surface) {
Expand All @@ -170,16 +187,20 @@ void viv_seat_focus_surface(struct viv_seat *seat, struct wlr_surface *surface)
wlr_xdg_toplevel_set_activated(previous, false);
#ifdef XWAYLAND
} else if (wlr_surface_is_xwayland_surface(focused_surface)) {
// TODO: Deactivating the previous xwayland surface appears wrong - it makes
// chromium popups disappear. Maybe we have some other logic issue.
/* struct wlr_xwayland_surface *previous = wlr_xwayland_surface_from_wlr_surface(focused_surface); */
/* wlr_xwayland_surface_activate(previous, false); */
struct wlr_xwayland_surface *previous = wlr_xwayland_surface_from_wlr_surface(focused_surface);
wlr_xwayland_surface_activate(previous, false);
#endif
} else {
// Not an error as this could be a layer surface
wlr_log(WLR_DEBUG, "Could not deactivate previous keyboard-focused surface");
}
}

if (!surface) {
wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat);
return;
}

struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(wlr_seat);

/*
Expand All @@ -190,6 +211,18 @@ void viv_seat_focus_surface(struct viv_seat *seat, struct wlr_surface *surface)
wlr_seat_keyboard_notify_enter(wlr_seat, surface, keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
}

void viv_seat_focus_view(struct viv_seat *seat, struct viv_view *view) {
focus_surface(seat, viv_view_get_toplevel_surface(view));
}

void viv_seat_focus_layer_view(struct viv_seat *seat, struct viv_layer_view *view) {
focus_surface(seat, view->layer_surface->surface);
}

void viv_seat_clear_focus(struct viv_seat *seat) {
focus_surface(seat, NULL);
}

void viv_seat_set_exclusive_client(struct viv_seat *seat, struct wl_client *client) {
if (!client) {
seat->exclusive_client = NULL;
Expand Down Expand Up @@ -356,7 +389,7 @@ static void seat_cursor_button(struct wl_listener *listener, void *data) {
}

if (view != active_view) {
viv_view_focus(view, surface);
viv_view_focus(view);
}

// If making a window floating, always bring it to the front
Expand Down
24 changes: 7 additions & 17 deletions src/viv_view.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,13 @@ void viv_view_bring_to_front(struct viv_view *view) {

void viv_view_clear_all_focus(struct viv_server *server) {
struct viv_seat *seat = viv_server_get_default_seat(server);
wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat);
viv_seat_clear_focus(seat);
}

void viv_view_focus(struct viv_view *view, struct wlr_surface *surface) {
void viv_view_focus(struct viv_view *view) {
if (view == NULL) {
return;
}
if (surface == NULL) {
surface = viv_view_get_toplevel_surface(view);
}
struct viv_server *server = view->server;

// Damage both previous and newly-active surface
Expand All @@ -48,8 +45,10 @@ void viv_view_focus(struct viv_view *view, struct wlr_surface *surface) {

/* Activate the new surface */
view->workspace->active_view = view;
viv_seat_focus_surface(viv_server_get_default_seat(server), surface);
viv_view_set_activated(view, true);
if (server->active_output->current_workspace == view->workspace) {
// Prevent focus from leaving current workspace
viv_seat_focus_view(viv_server_get_default_seat(server), view);
}
}

struct wlr_surface *viv_view_get_toplevel_surface(struct viv_view *view) {
Expand Down Expand Up @@ -103,7 +102,7 @@ void viv_view_shift_to_workspace(struct viv_view *view, struct viv_workspace *wo
wl_list_insert(&workspace->views, &view->workspace_link);

if (next_view != NULL) {
viv_view_focus(next_view, NULL);
viv_view_focus(next_view);
} else {
viv_view_clear_all_focus(view->server);
}
Expand Down Expand Up @@ -200,11 +199,6 @@ void viv_view_damage(struct viv_view *view) {
}
}

void viv_view_make_active(struct viv_view *view) {
view->workspace->active_view = view;
viv_view_focus(view, view->xdg_surface->surface);
}

void viv_view_set_size(struct viv_view *view, uint32_t width, uint32_t height) {
ASSERT(view->implementation->set_size != NULL);
view->implementation->set_size(view, width, height);
Expand Down Expand Up @@ -263,10 +257,6 @@ void viv_view_destroy(struct viv_view *view) {
free(view);
}

void viv_view_set_activated(struct viv_view *view, bool activated) {
view->implementation->set_activated(view, activated);
}

bool viv_view_is_at(struct viv_view *view, double lx, double ly, struct wlr_surface **surface, double *sx, double *sy) {
return view->implementation->is_at(view, lx, ly, surface, sx, sy);
}
Expand Down
33 changes: 3 additions & 30 deletions src/viv_workspace.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void viv_workspace_focus_next_window(struct viv_workspace *workspace) {
}

if (next_view) {
viv_view_focus(next_view, viv_view_get_toplevel_surface(next_view));
viv_view_focus(next_view);
} else {
wlr_log(WLR_DEBUG, "Could not get next window, no active view");
}
Expand All @@ -44,7 +44,7 @@ void viv_workspace_focus_prev_window(struct viv_workspace *workspace) {
}

if (prev_view) {
viv_view_focus(prev_view, viv_view_get_toplevel_surface(prev_view));
viv_view_focus(prev_view);
} else {
wlr_log(WLR_DEBUG, "Could not get prev window, no active view");
}
Expand Down Expand Up @@ -113,33 +113,6 @@ void viv_workspace_increment_counter(struct viv_workspace *workspace, uint32_t i
viv_workspace_mark_for_relayout(workspace);
}

void viv_workspace_swap_out(struct viv_output *output, struct wl_list *workspaces) {
if (wl_list_length(workspaces) < 2) {
wlr_log(WLR_DEBUG, "Not switching workspaces as only %d present\n", wl_list_length(workspaces));
return;
}

struct wl_list *new_workspace_link = workspaces->prev;

struct viv_workspace *new_workspace = wl_container_of(new_workspace_link, new_workspace, server_link);
struct viv_workspace *old_workspace = wl_container_of(workspaces->next, old_workspace, server_link);

wl_list_remove(new_workspace_link);
wl_list_insert(workspaces, new_workspace_link);

old_workspace->output = NULL;
new_workspace->output = output;
output->current_workspace = new_workspace;

viv_output_mark_for_relayout(output);

if (new_workspace->active_view != NULL) {
viv_view_focus(new_workspace->active_view, viv_view_get_toplevel_surface(new_workspace->active_view));
}

wlr_log(WLR_INFO, "Workspace changed from %s to %s", old_workspace->name, new_workspace->name);
}

void viv_workspace_next_layout(struct viv_workspace *workspace) {
struct wl_list *next_layout_link = workspace->active_layout->workspace_link.next;
if (next_layout_link == &workspace->layouts) {
Expand Down Expand Up @@ -271,7 +244,7 @@ void viv_workspace_add_view(struct viv_workspace *workspace, struct viv_view *vi
}

if (!workspace->fullscreen_view || (workspace->fullscreen_view == view)) {
viv_view_focus(view, viv_view_get_toplevel_surface(view));
viv_view_focus(view);
}

viv_workspace_mark_for_relayout(workspace);
Expand Down
5 changes: 0 additions & 5 deletions src/viv_xdg_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,6 @@ static void implementation_get_string_identifier(struct viv_view *view, char *ou
view->xdg_surface->toplevel->title);
}

static void implementation_set_activated(struct viv_view *view, bool activated) {
wlr_xdg_toplevel_set_activated(view->xdg_surface, activated);
}

static struct wlr_surface *implementation_get_toplevel_surface(struct viv_view *view) {
return view->xdg_surface->surface;
}
Expand Down Expand Up @@ -390,7 +386,6 @@ static struct viv_view_implementation xdg_view_implementation = {
.get_geometry = &implementation_get_geometry,
.set_tiled = &implementation_set_tiled,
.get_string_identifier = &implementation_get_string_identifier,
.set_activated = &implementation_set_activated,
.get_toplevel_surface = &implementation_get_toplevel_surface,
.close = &implementation_close,
.is_at = &implementation_is_at,
Expand Down
8 changes: 0 additions & 8 deletions src/viv_xwayland_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,13 +300,6 @@ static void implementation_get_string_identifier(struct viv_view *view, char *ou
view->xwayland_surface->class);
}

static void implementation_set_activated(struct viv_view *view, bool activated) {
wlr_xwayland_surface_activate(view->xwayland_surface, activated);
if (activated) {
wlr_xwayland_surface_restack(view->xwayland_surface, NULL, XCB_STACK_MODE_ABOVE);
}
}

static struct wlr_surface *implementation_get_toplevel_surface(struct viv_view *view) {
return view->xwayland_surface->surface;
}
Expand Down Expand Up @@ -392,7 +385,6 @@ static struct viv_view_implementation xwayland_view_implementation = {
.get_geometry = &implementation_get_geometry,
.set_tiled = &implementation_set_tiled,
.get_string_identifier = &implementation_get_string_identifier,
.set_activated = &implementation_set_activated,
.get_toplevel_surface = &implementation_get_toplevel_surface,
.close = &implementation_close,
.is_at = &implementation_is_at,
Expand Down