seat: set focus before starting transactions
Focus was made double-buffered in96a91fd
. However, much of the code still behaved as if focus was separate from the transaction system. This commit completes the work started in96a91fd
and ensures that focus is applied consistently in a single transaction.
This commit is contained in:
parent
bd99428766
commit
7a6ac8eb6e
9 changed files with 36 additions and 29 deletions
|
@ -48,9 +48,14 @@ const Mode = union(enum) {
|
|||
fn enter(self: *Self, mode: @TagType(Mode), event: *c.wlr_event_pointer_button, view: *View) void {
|
||||
log.debug(.cursor, "enter {} mode", .{@tagName(mode)});
|
||||
|
||||
self.seat.focus(view);
|
||||
|
||||
switch (mode) {
|
||||
.passthrough => unreachable,
|
||||
.down => self.mode = .{ .down = view },
|
||||
.down => {
|
||||
self.mode = .{ .down = view };
|
||||
view.output.root.startTransaction();
|
||||
},
|
||||
.move, .resize => {
|
||||
const cur_box = &view.current.box;
|
||||
self.mode = switch (mode) {
|
||||
|
@ -366,8 +371,6 @@ fn handleButton(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
|||
// If the target surface has a view, give that view keyboard focus and
|
||||
// perhaps enter move/resize mode.
|
||||
if (View.fromWlrSurface(wlr_surface)) |view| {
|
||||
self.seat.focus(view);
|
||||
|
||||
if (event.state == .WLR_BUTTON_PRESSED and self.pressed_count == 1) {
|
||||
// If the button is pressed and the pointer modifier is
|
||||
// active, enter cursor mode or close view and return.
|
||||
|
|
|
@ -149,6 +149,8 @@ fn handleInhibitDeactivate(listener: ?*c.wl_listener, data: ?*c_void) callconv(.
|
|||
while (seat_it) |seat_node| : (seat_it = seat_node.next) {
|
||||
seat_node.data.focus(null);
|
||||
}
|
||||
|
||||
self.server.root.startTransaction();
|
||||
}
|
||||
|
||||
/// This event is raised by the backend when a new input device becomes available.
|
||||
|
|
|
@ -154,6 +154,8 @@ fn handleUnmap(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
|||
const seat = &node.data;
|
||||
seat.focus(null);
|
||||
}
|
||||
|
||||
self.output.root.startTransaction();
|
||||
}
|
||||
|
||||
fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
|
@ -181,6 +183,7 @@ fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
|||
// TODO: only reconfigure if things haven't changed
|
||||
// https://github.com/swaywm/wlroots/issues/1079
|
||||
self.output.arrangeLayers();
|
||||
self.output.root.startTransaction();
|
||||
}
|
||||
|
||||
fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
||||
|
|
|
@ -304,7 +304,7 @@ pub fn arrangeViews(self: *Self) void {
|
|||
var it = ViewStack(View).pendingIterator(self.views.first, self.pending.tags);
|
||||
while (it.next()) |node| {
|
||||
const view = &node.view;
|
||||
if (!view.pending.float) layout_count += 1;
|
||||
if (!view.pending.float and !view.pending.fullscreen) layout_count += 1;
|
||||
}
|
||||
|
||||
// If the usable area has a zero dimension, trying to arrange the layout
|
||||
|
@ -394,8 +394,6 @@ pub fn arrangeLayers(self: *Self) void {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.root.startTransaction();
|
||||
}
|
||||
|
||||
/// Arrange the layer surfaces of a given layer
|
||||
|
@ -585,7 +583,7 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
|||
while (seat_it) |seat_node| : (seat_it = seat_node.next) {
|
||||
const seat = &seat_node.data;
|
||||
if (seat.focused_output == self) {
|
||||
seat.focusOutput(self);
|
||||
seat.focusOutput(fallback_output);
|
||||
seat.focus(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,8 +241,4 @@ fn commitTransaction(self: *Self) void {
|
|||
|
||||
if (view_tags_changed) output.sendViewTags();
|
||||
}
|
||||
|
||||
// Iterate over all seats and update focus
|
||||
var it = self.server.input_manager.seats.first;
|
||||
while (it) |seat_node| : (it = seat_node.next) seat_node.data.focus(null);
|
||||
}
|
||||
|
|
|
@ -120,21 +120,21 @@ pub fn focus(self: *Self, _view: ?*View) void {
|
|||
// If the view is not currently visible, behave as if null was passed
|
||||
if (view) |v| {
|
||||
if (v.output != self.focused_output or
|
||||
v.current.tags & self.focused_output.current.tags == 0) view = null;
|
||||
v.pending.tags & self.focused_output.pending.tags == 0) view = null;
|
||||
}
|
||||
|
||||
// If the target view is not fullscreen or null, then a fullscreen view
|
||||
// will grab focus if visible.
|
||||
if (if (view) |v| !v.current.fullscreen else true) {
|
||||
var it = ViewStack(*View).iterator(self.focus_stack.first, self.focused_output.current.tags);
|
||||
if (if (view) |v| !v.pending.fullscreen else true) {
|
||||
var it = ViewStack(*View).pendingIterator(self.focus_stack.first, self.focused_output.pending.tags);
|
||||
view = while (it.next()) |node| {
|
||||
if (node.view.output == self.focused_output and node.view.current.fullscreen) break node.view;
|
||||
if (node.view.output == self.focused_output and node.view.pending.fullscreen) break node.view;
|
||||
} else view;
|
||||
}
|
||||
|
||||
if (view == null) {
|
||||
// Set view to the first currently visible view in the focus stack if any
|
||||
var it = ViewStack(*View).iterator(self.focus_stack.first, self.focused_output.current.tags);
|
||||
var it = ViewStack(*View).pendingIterator(self.focus_stack.first, self.focused_output.pending.tags);
|
||||
view = while (it.next()) |node| {
|
||||
if (node.view.output == self.focused_output) break node.view;
|
||||
} else null;
|
||||
|
@ -223,9 +223,6 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
|
|||
// Inform any clients tracking status of the change
|
||||
var it = self.status_trackers.first;
|
||||
while (it) |node| : (it = node.next) node.data.sendFocusedView();
|
||||
|
||||
// Start a transaction to apply the pending focus state
|
||||
self.input_manager.server.root.startTransaction();
|
||||
}
|
||||
|
||||
/// Focus the given output, notifying any listening clients of the change.
|
||||
|
|
|
@ -351,7 +351,8 @@ pub fn map(self: *Self) void {
|
|||
|
||||
self.output.sendViewTags();
|
||||
|
||||
self.output.arrangeViews();
|
||||
if (!self.current.float) self.output.arrangeViews();
|
||||
|
||||
self.output.root.startTransaction();
|
||||
}
|
||||
|
||||
|
@ -377,11 +378,10 @@ pub fn unmap(self: *Self) void {
|
|||
self.output.sendViewTags();
|
||||
|
||||
// Still need to arrange if fullscreened from the layout
|
||||
if (!self.current.float) {
|
||||
self.output.arrangeViews();
|
||||
if (!self.current.float) self.output.arrangeViews();
|
||||
|
||||
root.startTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
/// Destory the view and free the ViewStack node holding it.
|
||||
pub fn destroy(self: *const Self) void {
|
||||
|
|
|
@ -53,6 +53,7 @@ pub fn focusView(
|
|||
// Focus the next visible node if there is one
|
||||
if (it.next()) |node| {
|
||||
seat.focus(&node.view);
|
||||
output.root.startTransaction();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -65,4 +66,5 @@ pub fn focusView(
|
|||
};
|
||||
|
||||
seat.focus(if (it.next()) |node| &node.view else null);
|
||||
output.root.startTransaction();
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ pub fn setFocusedTags(
|
|||
if (seat.focused_output.pending.tags != tags) {
|
||||
seat.focused_output.pending.tags = tags;
|
||||
seat.focused_output.arrangeViews();
|
||||
seat.focus(null);
|
||||
seat.focused_output.root.startTransaction();
|
||||
}
|
||||
}
|
||||
|
@ -44,8 +45,10 @@ pub fn setViewTags(
|
|||
) Error!void {
|
||||
const tags = try parseTags(allocator, args, out);
|
||||
if (seat.focused == .view) {
|
||||
seat.focused.view.pending.tags = tags;
|
||||
seat.focused.view.applyPending();
|
||||
const view = seat.focused.view;
|
||||
view.pending.tags = tags;
|
||||
seat.focus(null);
|
||||
view.applyPending();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +65,7 @@ pub fn toggleFocusedTags(
|
|||
if (new_focused_tags != 0) {
|
||||
output.pending.tags = new_focused_tags;
|
||||
output.arrangeViews();
|
||||
seat.focus(null);
|
||||
output.root.startTransaction();
|
||||
}
|
||||
}
|
||||
|
@ -75,10 +79,12 @@ pub fn toggleViewTags(
|
|||
) Error!void {
|
||||
const tags = try parseTags(allocator, args, out);
|
||||
if (seat.focused == .view) {
|
||||
const new_tags = seat.focused.view.current.tags ^ tags;
|
||||
const new_tags = seat.focused.view.pending.tags ^ tags;
|
||||
if (new_tags != 0) {
|
||||
seat.focused.view.pending.tags = new_tags;
|
||||
seat.focused.view.applyPending();
|
||||
const view = seat.focused.view;
|
||||
view.pending.tags = new_tags;
|
||||
seat.focus(null);
|
||||
view.applyPending();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue