mirror of
https://github.com/labwc/labwc.git
synced 2026-02-07 04:07:42 -05:00
Before this commit, when a normal window is raised, xwayland thought it's above always-on-top (AOT) windows even though it's actually below AOT windows in the scene. This means mouse scroll events may be unexpectedly sent to normal windows below AOT windows even when the cursor is hovering over a AOT window. So this commit fixes it by notifying the correct stacking order (where AOT windows are placed above normal windows) to xwayland every time the stacking order is updated. Other benefits of this commit are: - It makes the code more readable and predictable by aggregating logic about stacking order management in xwayland (e.g. shaded windows or windows in other workspaces should be notified to xwayland as being placed at the bottom). - As server->last_raised_view is removed in the previous commit, we were notifying the stacking order to xwayland every time a window with dialog windows is clicked (not when clicking a topmost window without dialogs, due to some optimization in wlroots). This commit fixes this by caching the window stacking order in xwayland_view->stacking_order and notifying it to xwayland only when it's updated.
107 lines
3 KiB
C
107 lines
3 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/* view-impl-common.c: common code for shell view->impl functions */
|
|
#include <stdio.h>
|
|
#include <strings.h>
|
|
#include "foreign-toplevel.h"
|
|
#include "labwc.h"
|
|
#include "view.h"
|
|
#include "view-impl-common.h"
|
|
#include "window-rules.h"
|
|
|
|
void
|
|
view_impl_map(struct view *view)
|
|
{
|
|
desktop_focus_view(view, /*raise*/ true);
|
|
view_update_title(view);
|
|
view_update_app_id(view);
|
|
if (!view->been_mapped) {
|
|
window_rules_apply(view, LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP);
|
|
}
|
|
|
|
/*
|
|
* It's tempting to just never create the foreign-toplevel handle in the
|
|
* map handlers, but the app_id/title might not have been set at that
|
|
* point, so it's safer to process the property here
|
|
*/
|
|
enum property ret = window_rules_get_property(view, "skipTaskbar");
|
|
if (ret == LAB_PROP_TRUE) {
|
|
if (view->foreign_toplevel) {
|
|
foreign_toplevel_destroy(view->foreign_toplevel);
|
|
view->foreign_toplevel = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Some clients (e.g. Steam's Big Picture Mode window) request
|
|
* fullscreen before mapping.
|
|
*/
|
|
desktop_update_top_layer_visibility(view->server);
|
|
|
|
wlr_log(WLR_DEBUG, "[map] identifier=%s, title=%s",
|
|
view_get_string_prop(view, "app_id"),
|
|
view_get_string_prop(view, "title"));
|
|
}
|
|
|
|
void
|
|
view_impl_unmap(struct view *view)
|
|
{
|
|
struct server *server = view->server;
|
|
if (view == server->active_view) {
|
|
desktop_focus_topmost_view(server);
|
|
}
|
|
}
|
|
|
|
static bool
|
|
resizing_edge(struct view *view, uint32_t edge)
|
|
{
|
|
struct server *server = view->server;
|
|
return server->input_mode == LAB_INPUT_STATE_RESIZE
|
|
&& server->grabbed_view == view
|
|
&& (server->resize_edges & edge);
|
|
}
|
|
|
|
void
|
|
view_impl_apply_geometry(struct view *view, int w, int h)
|
|
{
|
|
struct wlr_box *current = &view->current;
|
|
struct wlr_box *pending = &view->pending;
|
|
struct wlr_box old = *current;
|
|
|
|
/*
|
|
* Anchor right edge if resizing via left edge.
|
|
*
|
|
* Note that answering the question "are we resizing?" is a bit
|
|
* tricky. The most obvious method is to look at the server
|
|
* flags; but that method will not account for any late commits
|
|
* that occur after the mouse button is released, as the client
|
|
* catches up with pending configure requests. So as a fallback,
|
|
* we resort to a geometry-based heuristic -- also not 100%
|
|
* reliable on its own. The combination of the two methods
|
|
* should catch 99% of resize cases that we care about.
|
|
*/
|
|
bool resizing_left_edge = resizing_edge(view, WLR_EDGE_LEFT);
|
|
if (resizing_left_edge || (current->x != pending->x
|
|
&& current->x + current->width ==
|
|
pending->x + pending->width)) {
|
|
current->x = pending->x + pending->width - w;
|
|
} else {
|
|
current->x = pending->x;
|
|
}
|
|
|
|
/* Anchor bottom edge if resizing via top edge */
|
|
bool resizing_top_edge = resizing_edge(view, WLR_EDGE_TOP);
|
|
if (resizing_top_edge || (current->y != pending->y
|
|
&& current->y + current->height ==
|
|
pending->y + pending->height)) {
|
|
current->y = pending->y + pending->height - h;
|
|
} else {
|
|
current->y = pending->y;
|
|
}
|
|
|
|
current->width = w;
|
|
current->height = h;
|
|
|
|
if (!wlr_box_equal(current, &old)) {
|
|
view_moved(view);
|
|
}
|
|
}
|