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 {
|
fn enter(self: *Self, mode: @TagType(Mode), event: *c.wlr_event_pointer_button, view: *View) void {
|
||||||
log.debug(.cursor, "enter {} mode", .{@tagName(mode)});
|
log.debug(.cursor, "enter {} mode", .{@tagName(mode)});
|
||||||
|
|
||||||
|
self.seat.focus(view);
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
.passthrough => unreachable,
|
.passthrough => unreachable,
|
||||||
.down => self.mode = .{ .down = view },
|
.down => {
|
||||||
|
self.mode = .{ .down = view };
|
||||||
|
view.output.root.startTransaction();
|
||||||
|
},
|
||||||
.move, .resize => {
|
.move, .resize => {
|
||||||
const cur_box = &view.current.box;
|
const cur_box = &view.current.box;
|
||||||
self.mode = switch (mode) {
|
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
|
// If the target surface has a view, give that view keyboard focus and
|
||||||
// perhaps enter move/resize mode.
|
// perhaps enter move/resize mode.
|
||||||
if (View.fromWlrSurface(wlr_surface)) |view| {
|
if (View.fromWlrSurface(wlr_surface)) |view| {
|
||||||
self.seat.focus(view);
|
|
||||||
|
|
||||||
if (event.state == .WLR_BUTTON_PRESSED and self.pressed_count == 1) {
|
if (event.state == .WLR_BUTTON_PRESSED and self.pressed_count == 1) {
|
||||||
// If the button is pressed and the pointer modifier is
|
// If the button is pressed and the pointer modifier is
|
||||||
// active, enter cursor mode or close view and return.
|
// 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) {
|
while (seat_it) |seat_node| : (seat_it = seat_node.next) {
|
||||||
seat_node.data.focus(null);
|
seat_node.data.focus(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.server.root.startTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This event is raised by the backend when a new input device becomes available.
|
/// 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;
|
const seat = &node.data;
|
||||||
seat.focus(null);
|
seat.focus(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.output.root.startTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
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
|
// TODO: only reconfigure if things haven't changed
|
||||||
// https://github.com/swaywm/wlroots/issues/1079
|
// https://github.com/swaywm/wlroots/issues/1079
|
||||||
self.output.arrangeLayers();
|
self.output.arrangeLayers();
|
||||||
|
self.output.root.startTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
|
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);
|
var it = ViewStack(View).pendingIterator(self.views.first, self.pending.tags);
|
||||||
while (it.next()) |node| {
|
while (it.next()) |node| {
|
||||||
const view = &node.view;
|
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
|
// 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
|
/// 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) {
|
while (seat_it) |seat_node| : (seat_it = seat_node.next) {
|
||||||
const seat = &seat_node.data;
|
const seat = &seat_node.data;
|
||||||
if (seat.focused_output == self) {
|
if (seat.focused_output == self) {
|
||||||
seat.focusOutput(self);
|
seat.focusOutput(fallback_output);
|
||||||
seat.focus(null);
|
seat.focus(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,8 +241,4 @@ fn commitTransaction(self: *Self) void {
|
||||||
|
|
||||||
if (view_tags_changed) output.sendViewTags();
|
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 the view is not currently visible, behave as if null was passed
|
||||||
if (view) |v| {
|
if (view) |v| {
|
||||||
if (v.output != self.focused_output or
|
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
|
// If the target view is not fullscreen or null, then a fullscreen view
|
||||||
// will grab focus if visible.
|
// will grab focus if visible.
|
||||||
if (if (view) |v| !v.current.fullscreen else true) {
|
if (if (view) |v| !v.pending.fullscreen else true) {
|
||||||
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| {
|
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;
|
} else view;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
// Set view to the first currently visible view in the focus stack if any
|
// 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| {
|
view = while (it.next()) |node| {
|
||||||
if (node.view.output == self.focused_output) break node.view;
|
if (node.view.output == self.focused_output) break node.view;
|
||||||
} else null;
|
} else null;
|
||||||
|
@ -223,9 +223,6 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
|
||||||
// Inform any clients tracking status of the change
|
// Inform any clients tracking status of the change
|
||||||
var it = self.status_trackers.first;
|
var it = self.status_trackers.first;
|
||||||
while (it) |node| : (it = node.next) node.data.sendFocusedView();
|
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.
|
/// 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.sendViewTags();
|
||||||
|
|
||||||
self.output.arrangeViews();
|
if (!self.current.float) self.output.arrangeViews();
|
||||||
|
|
||||||
self.output.root.startTransaction();
|
self.output.root.startTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,10 +378,9 @@ pub fn unmap(self: *Self) void {
|
||||||
self.output.sendViewTags();
|
self.output.sendViewTags();
|
||||||
|
|
||||||
// Still need to arrange if fullscreened from the layout
|
// Still need to arrange if fullscreened from the layout
|
||||||
if (!self.current.float) {
|
if (!self.current.float) self.output.arrangeViews();
|
||||||
self.output.arrangeViews();
|
|
||||||
root.startTransaction();
|
root.startTransaction();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Destory the view and free the ViewStack node holding it.
|
/// Destory the view and free the ViewStack node holding it.
|
||||||
|
|
|
@ -53,6 +53,7 @@ pub fn focusView(
|
||||||
// Focus the next visible node if there is one
|
// Focus the next visible node if there is one
|
||||||
if (it.next()) |node| {
|
if (it.next()) |node| {
|
||||||
seat.focus(&node.view);
|
seat.focus(&node.view);
|
||||||
|
output.root.startTransaction();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,4 +66,5 @@ pub fn focusView(
|
||||||
};
|
};
|
||||||
|
|
||||||
seat.focus(if (it.next()) |node| &node.view else null);
|
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) {
|
if (seat.focused_output.pending.tags != tags) {
|
||||||
seat.focused_output.pending.tags = tags;
|
seat.focused_output.pending.tags = tags;
|
||||||
seat.focused_output.arrangeViews();
|
seat.focused_output.arrangeViews();
|
||||||
|
seat.focus(null);
|
||||||
seat.focused_output.root.startTransaction();
|
seat.focused_output.root.startTransaction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,8 +45,10 @@ pub fn setViewTags(
|
||||||
) Error!void {
|
) Error!void {
|
||||||
const tags = try parseTags(allocator, args, out);
|
const tags = try parseTags(allocator, args, out);
|
||||||
if (seat.focused == .view) {
|
if (seat.focused == .view) {
|
||||||
seat.focused.view.pending.tags = tags;
|
const view = seat.focused.view;
|
||||||
seat.focused.view.applyPending();
|
view.pending.tags = tags;
|
||||||
|
seat.focus(null);
|
||||||
|
view.applyPending();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +65,7 @@ pub fn toggleFocusedTags(
|
||||||
if (new_focused_tags != 0) {
|
if (new_focused_tags != 0) {
|
||||||
output.pending.tags = new_focused_tags;
|
output.pending.tags = new_focused_tags;
|
||||||
output.arrangeViews();
|
output.arrangeViews();
|
||||||
|
seat.focus(null);
|
||||||
output.root.startTransaction();
|
output.root.startTransaction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,10 +79,12 @@ pub fn toggleViewTags(
|
||||||
) Error!void {
|
) Error!void {
|
||||||
const tags = try parseTags(allocator, args, out);
|
const tags = try parseTags(allocator, args, out);
|
||||||
if (seat.focused == .view) {
|
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) {
|
if (new_tags != 0) {
|
||||||
seat.focused.view.pending.tags = new_tags;
|
const view = seat.focused.view;
|
||||||
seat.focused.view.applyPending();
|
view.pending.tags = new_tags;
|
||||||
|
seat.focus(null);
|
||||||
|
view.applyPending();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue