mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
desktop: switch workspaces and optionally raise in desktop_focus_view()
Make desktop_focus_view() always switch to the workspace containing the view being focused. It doesn't make much sense for an invisible view to have the keyboard focus. Also add an optional "raise" parameter to desktop_focus_view(). This allows the common pattern of desktop_focus_view() + view_move_to_front() to be reduced to a single function call.
This commit is contained in:
parent
e77330bc3f
commit
e5aef03319
11 changed files with 44 additions and 43 deletions
|
|
@ -377,7 +377,7 @@ void foreign_toplevel_update_outputs(struct view *view);
|
||||||
* cannot assume this means that the window actually has keyboard
|
* cannot assume this means that the window actually has keyboard
|
||||||
* or pointer focus, in this compositor are they called together.
|
* 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_arrange_all_views(struct server *server);
|
||||||
void desktop_focus_output(struct output *output);
|
void desktop_focus_output(struct output *output);
|
||||||
struct view *desktop_topmost_mapped_view(struct server *server);
|
struct view *desktop_topmost_mapped_view(struct server *server);
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@
|
||||||
#ifndef LABWC_WORKSPACES_H
|
#ifndef LABWC_WORKSPACES_H
|
||||||
#define LABWC_WORKSPACES_H
|
#define LABWC_WORKSPACES_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
|
||||||
struct seat;
|
struct seat;
|
||||||
struct view;
|
|
||||||
struct server;
|
struct server;
|
||||||
struct wl_list;
|
struct wlr_scene_tree;
|
||||||
|
|
||||||
/* Double use: as config in config/rcxml.c and as instance in workspaces.c */
|
/* Double use: as config in config/rcxml.c and as instance in workspaces.c */
|
||||||
struct workspace {
|
struct workspace {
|
||||||
|
|
@ -20,7 +22,7 @@ struct workspace {
|
||||||
};
|
};
|
||||||
|
|
||||||
void workspaces_init(struct server *server);
|
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_destroy(struct server *server);
|
||||||
void workspaces_osd_hide(struct seat *seat);
|
void workspaces_osd_hide(struct seat *seat);
|
||||||
struct workspace *workspaces_find(struct workspace *anchor, const char *name,
|
struct workspace *workspaces_find(struct workspace *anchor, const char *name,
|
||||||
|
|
|
||||||
|
|
@ -634,7 +634,7 @@ actions_run(struct view *activator, struct server *server,
|
||||||
break;
|
break;
|
||||||
case ACTION_TYPE_FOCUS:
|
case ACTION_TYPE_FOCUS:
|
||||||
if (view) {
|
if (view) {
|
||||||
desktop_focus_view(view);
|
desktop_focus_view(view, /*raise*/ false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ACTION_TYPE_ICONIFY:
|
case ACTION_TYPE_ICONIFY:
|
||||||
|
|
@ -711,7 +711,8 @@ actions_run(struct view *activator, struct server *server,
|
||||||
follow = get_arg_value_bool(action, "follow", true);
|
follow = get_arg_value_bool(action, "follow", true);
|
||||||
}
|
}
|
||||||
if (follow) {
|
if (follow) {
|
||||||
workspaces_switch_to(target);
|
workspaces_switch_to(target,
|
||||||
|
/*update_focus*/ true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
10
src/cursor.c
10
src/cursor.c
|
|
@ -478,10 +478,7 @@ process_cursor_motion(struct server *server, uint32_t time)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.view && rc.focus_follow_mouse) {
|
if (ctx.view && rc.focus_follow_mouse) {
|
||||||
desktop_focus_view(ctx.view);
|
desktop_focus_view(ctx.view, rc.raise_on_focus);
|
||||||
if (rc.raise_on_focus) {
|
|
||||||
view_move_to_front(ctx.view);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mousebind *mousebind;
|
struct mousebind *mousebind;
|
||||||
|
|
@ -522,10 +519,7 @@ _cursor_update_focus(struct server *server)
|
||||||
&& !rc.focus_follow_mouse_requires_movement
|
&& !rc.focus_follow_mouse_requires_movement
|
||||||
&& !server->osd_state.cycle_view) {
|
&& !server->osd_state.cycle_view) {
|
||||||
/* Prevents changing keyboard focus during A-Tab */
|
/* Prevents changing keyboard focus during A-Tab */
|
||||||
desktop_focus_view(ctx.view);
|
desktop_focus_view(ctx.view, rc.raise_on_focus);
|
||||||
if (rc.raise_on_focus) {
|
|
||||||
view_move_to_front(ctx.view);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor_update_common(server, &ctx, msec(&now),
|
cursor_update_common(server, &ctx, msec(&now),
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ desktop_arrange_all_views(struct server *server)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
desktop_focus_view(struct view *view)
|
desktop_focus_view(struct view *view, bool raise)
|
||||||
{
|
{
|
||||||
assert(view);
|
assert(view);
|
||||||
/*
|
/*
|
||||||
|
|
@ -56,7 +56,7 @@ desktop_focus_view(struct view *view)
|
||||||
if (view->minimized) {
|
if (view->minimized) {
|
||||||
/*
|
/*
|
||||||
* Unminimizing will map the view which triggers a call to this
|
* Unminimizing will map the view which triggers a call to this
|
||||||
* function again.
|
* function again (with raise=true).
|
||||||
*/
|
*/
|
||||||
view_minimize(view, false);
|
view_minimize(view, false);
|
||||||
return;
|
return;
|
||||||
|
|
@ -66,7 +66,19 @@ desktop_focus_view(struct view *view)
|
||||||
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);
|
view_focus(view);
|
||||||
|
|
||||||
|
if (raise) {
|
||||||
|
view_move_to_front(view);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wl_list *
|
static struct wl_list *
|
||||||
|
|
@ -225,8 +237,7 @@ desktop_focus_topmost_mapped_view(struct server *server)
|
||||||
{
|
{
|
||||||
struct view *view = desktop_topmost_mapped_view(server);
|
struct view *view = desktop_topmost_mapped_view(server);
|
||||||
if (view) {
|
if (view) {
|
||||||
desktop_focus_view(view);
|
desktop_focus_view(view, /*raise*/ true);
|
||||||
view_move_to_front(view);
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Defocus previous focused surface/view if no longer
|
* Defocus previous focused surface/view if no longer
|
||||||
|
|
@ -262,7 +273,7 @@ desktop_focus_output(struct output *output)
|
||||||
}
|
}
|
||||||
if (wlr_output_layout_intersects(layout,
|
if (wlr_output_layout_intersects(layout,
|
||||||
output->wlr_output, &view->current)) {
|
output->wlr_output, &view->current)) {
|
||||||
desktop_focus_view(view);
|
desktop_focus_view(view, /*raise*/ false);
|
||||||
wlr_cursor_warp(output->server->seat.cursor, NULL,
|
wlr_cursor_warp(output->server->seat.cursor, NULL,
|
||||||
view->current.x + view->current.width / 2,
|
view->current.x + view->current.width / 2,
|
||||||
view->current.y + view->current.height / 2);
|
view->current.y + view->current.height / 2);
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,7 @@ handle_request_activate(struct wl_listener *listener, void *data)
|
||||||
struct view *view = wl_container_of(listener, view, toplevel.activate);
|
struct view *view = wl_container_of(listener, view, toplevel.activate);
|
||||||
// struct wlr_foreign_toplevel_handle_v1_activated_event *event = data;
|
// struct wlr_foreign_toplevel_handle_v1_activated_event *event = data;
|
||||||
/* In a multi-seat world we would select seat based on event->seat here. */
|
/* In a multi-seat world we would select seat based on event->seat here. */
|
||||||
if (view->workspace != view->server->workspace_current) {
|
desktop_focus_view(view, /*raise*/ true);
|
||||||
workspaces_switch_to(view->workspace);
|
|
||||||
}
|
|
||||||
desktop_focus_view(view);
|
|
||||||
view_move_to_front(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,8 @@ static void
|
||||||
end_cycling(struct server *server)
|
end_cycling(struct server *server)
|
||||||
{
|
{
|
||||||
if (server->osd_state.cycle_view) {
|
if (server->osd_state.cycle_view) {
|
||||||
desktop_focus_view(server->osd_state.cycle_view);
|
desktop_focus_view(server->osd_state.cycle_view,
|
||||||
view_move_to_front(server->osd_state.cycle_view);
|
/*raise*/ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* osd_finish() additionally resets cycle_view to NULL */
|
/* osd_finish() additionally resets cycle_view to NULL */
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,7 @@ view_impl_move_sub_views(struct view *parent, enum z_direction z_direction)
|
||||||
void
|
void
|
||||||
view_impl_map(struct view *view)
|
view_impl_map(struct view *view)
|
||||||
{
|
{
|
||||||
desktop_focus_view(view);
|
desktop_focus_view(view, /*raise*/ true);
|
||||||
view_move_to_front(view);
|
|
||||||
view_update_title(view);
|
view_update_title(view);
|
||||||
view_update_app_id(view);
|
view_update_app_id(view);
|
||||||
if (!view->been_mapped) {
|
if (!view->been_mapped) {
|
||||||
|
|
|
||||||
|
|
@ -255,8 +255,13 @@ workspaces_init(struct server *server)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
void
|
||||||
workspaces_switch_to(struct workspace *target)
|
workspaces_switch_to(struct workspace *target, bool update_focus)
|
||||||
{
|
{
|
||||||
assert(target);
|
assert(target);
|
||||||
struct server *server = target->server;
|
struct server *server = target->server;
|
||||||
|
|
@ -281,10 +286,12 @@ workspaces_switch_to(struct workspace *target)
|
||||||
* Make sure we are focusing what the user sees.
|
* Make sure we are focusing what the user sees.
|
||||||
* Only refocus if the focus is not already on an always-on-top view.
|
* Only refocus if the focus is not already on an always-on-top view.
|
||||||
*/
|
*/
|
||||||
|
if (update_focus) {
|
||||||
struct view *view = desktop_focused_view(server);
|
struct view *view = desktop_focused_view(server);
|
||||||
if (!view || !view_is_always_on_top(view)) {
|
if (!view || !view_is_always_on_top(view)) {
|
||||||
desktop_focus_topmost_mapped_view(server);
|
desktop_focus_topmost_mapped_view(server);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* And finally show the OSD */
|
/* And finally show the OSD */
|
||||||
_osd_show(server);
|
_osd_show(server);
|
||||||
|
|
|
||||||
10
src/xdg.c
10
src/xdg.c
|
|
@ -607,16 +607,8 @@ xdg_activation_handle_request(struct wl_listener *listener, void *data)
|
||||||
return;
|
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");
|
wlr_log(WLR_DEBUG, "Activating surface");
|
||||||
if (view->workspace != view->server->workspace_current) {
|
desktop_focus_view(view, /*raise*/ true);
|
||||||
workspaces_switch_to(view->workspace);
|
|
||||||
}
|
|
||||||
desktop_focus_view(view);
|
|
||||||
view_move_to_front(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -256,8 +256,7 @@ handle_request_activate(struct wl_listener *listener, void *data)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
desktop_focus_view(view);
|
desktop_focus_view(view, /*raise*/ true);
|
||||||
view_move_to_front(view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue