xwayland-unmanaged: handle focus on map/cursor button
This implements keyboard focus on map for unmanaged Xwayland views using wlroot's heuristic approach as well as keyboard focus on cursor button click.
This commit is contained in:
parent
0dd5ad032c
commit
7b554bde68
@ -315,7 +315,13 @@ fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.P
|
||||
self.seat.focus(null);
|
||||
}
|
||||
},
|
||||
.xwayland_unmanaged => assert(build_options.xwayland),
|
||||
.xwayland_unmanaged => |xwayland_unmanaged| {
|
||||
if (build_options.xwayland) {
|
||||
self.seat.setFocusRaw(.{ .xwayland_unmanaged = xwayland_unmanaged });
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
},
|
||||
}
|
||||
_ = self.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state);
|
||||
|
||||
|
@ -38,12 +38,14 @@ const Output = @import("Output.zig");
|
||||
const SeatStatus = @import("SeatStatus.zig");
|
||||
const View = @import("View.zig");
|
||||
const ViewStack = @import("view_stack.zig").ViewStack;
|
||||
const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig");
|
||||
|
||||
const log = std.log.scoped(.seat);
|
||||
const PointerConstraint = @import("PointerConstraint.zig");
|
||||
|
||||
const FocusTarget = union(enum) {
|
||||
view: *View,
|
||||
xwayland_unmanaged: *XwaylandUnmanaged,
|
||||
layer: *LayerSurface,
|
||||
none: void,
|
||||
};
|
||||
@ -206,7 +208,8 @@ fn pendingFilter(view: *View, filter_tags: u32) bool {
|
||||
}
|
||||
|
||||
/// Switch focus to the target, handling unfocus and input inhibition
|
||||
/// properly. This should only be called directly if dealing with layers.
|
||||
/// properly. This should only be called directly if dealing with layers or
|
||||
/// unmanaged xwayland views.
|
||||
pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
|
||||
// If the target is already focused, do nothing
|
||||
if (std.meta.eql(new_focus, self.focused)) return;
|
||||
@ -214,6 +217,10 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
|
||||
// Obtain the target surface
|
||||
const target_surface = switch (new_focus) {
|
||||
.view => |target_view| target_view.surface.?,
|
||||
.xwayland_unmanaged => |target_xwayland_unmanaged| blk: {
|
||||
assert(build_options.xwayland);
|
||||
break :blk target_xwayland_unmanaged.xwayland_surface.surface;
|
||||
},
|
||||
.layer => |target_layer| target_layer.wlr_layer_surface.surface,
|
||||
.none => null,
|
||||
};
|
||||
@ -228,7 +235,7 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
|
||||
view.pending.focus -= 1;
|
||||
if (view.pending.focus == 0) view.setActivated(false);
|
||||
},
|
||||
.layer, .none => {},
|
||||
.xwayland_unmanaged, .layer, .none => {},
|
||||
}
|
||||
|
||||
// Set the new focus
|
||||
@ -240,7 +247,7 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
|
||||
target_view.pending.urgent = false;
|
||||
},
|
||||
.layer => |target_layer| assert(self.focused_output == target_layer.output),
|
||||
.none => {},
|
||||
.xwayland_unmanaged, .none => {},
|
||||
}
|
||||
self.focused = new_focus;
|
||||
|
||||
|
@ -78,19 +78,32 @@ fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wl
|
||||
|
||||
xwayland_surface.surface.?.events.commit.add(&self.commit);
|
||||
|
||||
// TODO: handle keyboard focus
|
||||
// if (wlr_xwayland_or_surface_wants_focus(self.xwayland_surface)) { ...
|
||||
if (self.xwayland_surface.overrideRedirectWantsFocus()) {
|
||||
server.input_manager.defaultSeat().setFocusRaw(.{ .xwayland_unmanaged = self });
|
||||
}
|
||||
}
|
||||
|
||||
/// Called when the surface is unmapped and will no longer be displayed.
|
||||
fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
|
||||
const self = @fieldParentPtr(Self, "unmap", listener);
|
||||
|
||||
// Remove self from the list of unmanged views in the root
|
||||
// Remove self from the list of unmanaged views in the root
|
||||
const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self);
|
||||
server.root.xwayland_unmanaged_views.remove(node);
|
||||
|
||||
self.commit.link.remove();
|
||||
|
||||
// If the unmapped surface is currently focused, reset focus to the most
|
||||
// appropriate view.
|
||||
var seat_it = server.input_manager.seats.first;
|
||||
while (seat_it) |seat_node| : (seat_it = seat_node.next) {
|
||||
const seat = &seat_node.data;
|
||||
if (seat.focused == .xwayland_unmanaged and seat.focused.xwayland_unmanaged == self) {
|
||||
seat.focus(null);
|
||||
}
|
||||
}
|
||||
|
||||
server.root.startTransaction();
|
||||
}
|
||||
|
||||
fn handleCommit(_: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
|
||||
|
Loading…
Reference in New Issue
Block a user