mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
desktop: give focus to a modal dialog rather than its parent
Fixes: #2722
This commit is contained in:
parent
ea1df930e9
commit
9782ffa868
4 changed files with 73 additions and 15 deletions
|
|
@ -156,6 +156,7 @@ struct view_impl {
|
|||
void (*minimize)(struct view *view, bool minimize);
|
||||
struct view *(*get_root)(struct view *self);
|
||||
void (*append_children)(struct view *self, struct wl_array *children);
|
||||
bool (*is_modal_dialog)(struct view *self);
|
||||
struct view_size_hints (*get_size_hints)(struct view *self);
|
||||
/* if not implemented, VIEW_WANTS_FOCUS_ALWAYS is assumed */
|
||||
enum view_wants_focus (*wants_focus)(struct view *self);
|
||||
|
|
@ -612,6 +613,14 @@ void view_move_to_front(struct view *view);
|
|||
void view_move_to_back(struct view *view);
|
||||
struct view *view_get_root(struct view *view);
|
||||
void view_append_children(struct view *view, struct wl_array *children);
|
||||
|
||||
/**
|
||||
* view_get_modal_dialog() - returns any modal dialog found among this
|
||||
* view's children or siblings (or possibly this view itself). Applies
|
||||
* only to xwayland views and always returns NULL for xdg-shell views.
|
||||
*/
|
||||
struct view *view_get_modal_dialog(struct view *view);
|
||||
|
||||
bool view_on_output(struct view *view, struct output *output);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -39,6 +39,25 @@ desktop_arrange_all_views(struct server *server)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_or_offer_focus(struct view *view)
|
||||
{
|
||||
struct seat *seat = &view->server->seat;
|
||||
switch (view_wants_focus(view)) {
|
||||
case VIEW_WANTS_FOCUS_ALWAYS:
|
||||
if (view->surface != seat->seat->keyboard_state.focused_surface) {
|
||||
seat_focus_surface(seat, view->surface);
|
||||
}
|
||||
break;
|
||||
case VIEW_WANTS_FOCUS_LIKELY:
|
||||
case VIEW_WANTS_FOCUS_UNLIKELY:
|
||||
view_offer_focus(view);
|
||||
break;
|
||||
case VIEW_WANTS_FOCUS_NEVER:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
desktop_focus_view(struct view *view, bool raise)
|
||||
{
|
||||
|
|
@ -77,24 +96,17 @@ desktop_focus_view(struct view *view, bool raise)
|
|||
workspaces_switch_to(view->workspace, /*update_focus*/ false);
|
||||
}
|
||||
|
||||
struct seat *seat = &view->server->seat;
|
||||
switch (view_wants_focus(view)) {
|
||||
case VIEW_WANTS_FOCUS_ALWAYS:
|
||||
if (view->surface != seat->seat->keyboard_state.focused_surface) {
|
||||
seat_focus_surface(seat, view->surface);
|
||||
}
|
||||
break;
|
||||
case VIEW_WANTS_FOCUS_LIKELY:
|
||||
case VIEW_WANTS_FOCUS_UNLIKELY:
|
||||
view_offer_focus(view);
|
||||
break;
|
||||
case VIEW_WANTS_FOCUS_NEVER:
|
||||
break;
|
||||
}
|
||||
|
||||
if (raise) {
|
||||
view_move_to_front(view);
|
||||
}
|
||||
|
||||
/*
|
||||
* If any child/sibling of the view is a modal dialog, focus
|
||||
* the dialog instead. It does not need to be raised separately
|
||||
* since view_move_to_front() raises all sibling views together.
|
||||
*/
|
||||
struct view *dialog = view_get_modal_dialog(view);
|
||||
set_or_offer_focus(dialog ? dialog : view);
|
||||
}
|
||||
|
||||
/* TODO: focus layer-shell surfaces also? */
|
||||
|
|
|
|||
30
src/view.c
30
src/view.c
|
|
@ -2343,6 +2343,36 @@ view_append_children(struct view *view, struct wl_array *children)
|
|||
}
|
||||
}
|
||||
|
||||
struct view *
|
||||
view_get_modal_dialog(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
if (!view->impl->is_modal_dialog) {
|
||||
return NULL;
|
||||
}
|
||||
/* check view itself first */
|
||||
if (view->impl->is_modal_dialog(view)) {
|
||||
return view;
|
||||
}
|
||||
|
||||
/* check sibling views */
|
||||
struct view *dialog = NULL;
|
||||
struct view *root = view_get_root(view);
|
||||
struct wl_array children;
|
||||
struct view **child;
|
||||
|
||||
wl_array_init(&children);
|
||||
view_append_children(root, &children);
|
||||
wl_array_for_each(child, &children) {
|
||||
if (view->impl->is_modal_dialog(*child)) {
|
||||
dialog = *child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
wl_array_release(&children);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
bool
|
||||
view_has_strut_partial(struct view *view)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -933,6 +933,12 @@ xwayland_view_append_children(struct view *self, struct wl_array *children)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
xwayland_view_is_modal_dialog(struct view *self)
|
||||
{
|
||||
return xwayland_surface_from_view(self)->modal;
|
||||
}
|
||||
|
||||
static void
|
||||
xwayland_view_set_activated(struct view *view, bool activated)
|
||||
{
|
||||
|
|
@ -978,6 +984,7 @@ static const struct view_impl xwayland_view_impl = {
|
|||
.minimize = xwayland_view_minimize,
|
||||
.get_root = xwayland_view_get_root,
|
||||
.append_children = xwayland_view_append_children,
|
||||
.is_modal_dialog = xwayland_view_is_modal_dialog,
|
||||
.get_size_hints = xwayland_view_get_size_hints,
|
||||
.wants_focus = xwayland_view_wants_focus,
|
||||
.offer_focus = xwayland_view_offer_focus,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue