* cannot assume this means that the window actually has keyboard
* or pointer focus, in this compositor are they called together.
*/
-void desktop_focus_view(struct view *view);
+void desktop_focus_view(struct view *view, bool raise);
void desktop_arrange_all_views(struct server *server);
void desktop_focus_output(struct output *output);
struct view *desktop_topmost_mapped_view(struct server *server);
#ifndef LABWC_WORKSPACES_H
#define LABWC_WORKSPACES_H
+#include <stdbool.h>
+#include <wayland-util.h>
+
struct seat;
-struct view;
struct server;
-struct wl_list;
+struct wlr_scene_tree;
/* Double use: as config in config/rcxml.c and as instance in workspaces.c */
struct workspace {
};
void workspaces_init(struct server *server);
-void workspaces_switch_to(struct workspace *target);
+void workspaces_switch_to(struct workspace *target, bool update_focus);
void workspaces_destroy(struct server *server);
void workspaces_osd_hide(struct seat *seat);
struct workspace *workspaces_find(struct workspace *anchor, const char *name,
break;
case ACTION_TYPE_FOCUS:
if (view) {
- desktop_focus_view(view);
+ desktop_focus_view(view, /*raise*/ false);
}
break;
case ACTION_TYPE_ICONIFY:
follow = get_arg_value_bool(action, "follow", true);
}
if (follow) {
- workspaces_switch_to(target);
+ workspaces_switch_to(target,
+ /*update_focus*/ true);
}
}
break;
}
if (ctx.view && rc.focus_follow_mouse) {
- desktop_focus_view(ctx.view);
- if (rc.raise_on_focus) {
- view_move_to_front(ctx.view);
- }
+ desktop_focus_view(ctx.view, rc.raise_on_focus);
}
struct mousebind *mousebind;
&& !rc.focus_follow_mouse_requires_movement
&& !server->osd_state.cycle_view) {
/* Prevents changing keyboard focus during A-Tab */
- desktop_focus_view(ctx.view);
- if (rc.raise_on_focus) {
- view_move_to_front(ctx.view);
- }
+ desktop_focus_view(ctx.view, rc.raise_on_focus);
}
cursor_update_common(server, &ctx, msec(&now),
}
void
-desktop_focus_view(struct view *view)
+desktop_focus_view(struct view *view, bool raise)
{
assert(view);
/*
if (view->minimized) {
/*
* Unminimizing will map the view which triggers a call to this
- * function again.
+ * function again (with raise=true).
*/
view_minimize(view, false);
return;
return;
}
+ /*
+ * Switch workspace if necessary to make the view visible
+ * (unnecessary for "always on top" views).
+ */
+ if (!view_is_always_on_top(view)) {
+ workspaces_switch_to(view->workspace, /*update_focus*/ false);
+ }
+
view_focus(view);
+
+ if (raise) {
+ view_move_to_front(view);
+ }
}
static struct wl_list *
{
struct view *view = desktop_topmost_mapped_view(server);
if (view) {
- desktop_focus_view(view);
- view_move_to_front(view);
+ desktop_focus_view(view, /*raise*/ true);
} else {
/*
* Defocus previous focused surface/view if no longer
}
if (wlr_output_layout_intersects(layout,
output->wlr_output, &view->current)) {
- desktop_focus_view(view);
+ desktop_focus_view(view, /*raise*/ false);
wlr_cursor_warp(output->server->seat.cursor, NULL,
view->current.x + view->current.width / 2,
view->current.y + view->current.height / 2);
struct view *view = wl_container_of(listener, view, toplevel.activate);
// struct wlr_foreign_toplevel_handle_v1_activated_event *event = data;
/* In a multi-seat world we would select seat based on event->seat here. */
- if (view->workspace != view->server->workspace_current) {
- workspaces_switch_to(view->workspace);
- }
- desktop_focus_view(view);
- view_move_to_front(view);
+ desktop_focus_view(view, /*raise*/ true);
}
static void
end_cycling(struct server *server)
{
if (server->osd_state.cycle_view) {
- desktop_focus_view(server->osd_state.cycle_view);
- view_move_to_front(server->osd_state.cycle_view);
+ desktop_focus_view(server->osd_state.cycle_view,
+ /*raise*/ true);
}
/* osd_finish() additionally resets cycle_view to NULL */
void
view_impl_map(struct view *view)
{
- desktop_focus_view(view);
- view_move_to_front(view);
+ desktop_focus_view(view, /*raise*/ true);
view_update_title(view);
view_update_app_id(view);
if (!view->been_mapped) {
}
}
+/*
+ * update_focus should normally be set to true. It is set to false only
+ * when this function is called from desktop_focus_view(), in order to
+ * avoid unnecessary extra focus changes and possible recursion.
+ */
void
-workspaces_switch_to(struct workspace *target)
+workspaces_switch_to(struct workspace *target, bool update_focus)
{
assert(target);
struct server *server = target->server;
* Make sure we are focusing what the user sees.
* Only refocus if the focus is not already on an always-on-top view.
*/
- struct view *view = desktop_focused_view(server);
- if (!view || !view_is_always_on_top(view)) {
- desktop_focus_topmost_mapped_view(server);
+ if (update_focus) {
+ struct view *view = desktop_focused_view(server);
+ if (!view || !view_is_always_on_top(view)) {
+ desktop_focus_topmost_mapped_view(server);
+ }
}
/* And finally show the OSD */
return;
}
- /*
- * TODO: This is the exact same code as used in foreign.c.
- * Refactor it into a public helper function somewhere.
- */
wlr_log(WLR_DEBUG, "Activating surface");
- if (view->workspace != view->server->workspace_current) {
- workspaces_switch_to(view->workspace);
- }
- desktop_focus_view(view);
- view_move_to_front(view);
+ desktop_focus_view(view, /*raise*/ true);
}
/*
return;
}
- desktop_focus_view(view);
- view_move_to_front(view);
+ desktop_focus_view(view, /*raise*/ true);
}
static void