seat: always add view to focus stack on map
Currently if a view is mapped while some other view is fullscreen, it will not be added to the focus stack, which means that if the fullscreen view is then closed the view which was not added to the focus stack will not be focused. To fix this, always add views to the focus stack on map.
This commit is contained in:
parent
e752555969
commit
1baf3bf462
5 changed files with 31 additions and 41 deletions
|
@ -161,15 +161,6 @@ pub fn defaultSeat(self: Self) *Seat {
|
||||||
return &self.seats.first.?.data;
|
return &self.seats.first.?.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Must be called whenever a view is unmapped.
|
|
||||||
pub fn handleViewUnmap(self: Self, view: *View) void {
|
|
||||||
var it = self.seats.first;
|
|
||||||
while (it) |node| : (it = node.next) {
|
|
||||||
const seat = &node.data;
|
|
||||||
seat.handleViewUnmap(view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if input is currently allowed on the passed surface.
|
/// Returns true if input is currently allowed on the passed surface.
|
||||||
pub fn inputAllowed(self: Self, wlr_surface: *wlr.Surface) bool {
|
pub fn inputAllowed(self: Self, wlr_surface: *wlr.Surface) bool {
|
||||||
return if (self.exclusive_client) |exclusive_client|
|
return if (self.exclusive_client) |exclusive_client|
|
||||||
|
|
|
@ -149,27 +149,22 @@ pub fn focus(self: *Self, _target: ?*View) void {
|
||||||
} else null;
|
} else null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Focus the target view or clear the focus if target is null
|
||||||
if (target) |view| {
|
if (target) |view| {
|
||||||
// Find or allocate a new node in the focus stack for the target view
|
// Find the node for this view in the focus stack and move it to the top.
|
||||||
var it = self.focus_stack.first;
|
var it = self.focus_stack.first;
|
||||||
while (it) |node| : (it = node.next) {
|
while (it) |node| : (it = node.next) {
|
||||||
// If the view is found, move it to the top of the stack
|
|
||||||
if (node.view == view) {
|
if (node.view == view) {
|
||||||
const new_focus_node = self.focus_stack.remove(node);
|
const new_focus_node = self.focus_stack.remove(node);
|
||||||
self.focus_stack.push(node);
|
self.focus_stack.push(node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The view is not in the stack, so allocate a new node and prepend it
|
// A node is added when new Views are mapped in Seat.handleViewMap()
|
||||||
const new_focus_node = util.gpa.create(ViewStack(*View).Node) catch return;
|
unreachable;
|
||||||
new_focus_node.view = view;
|
|
||||||
self.focus_stack.push(new_focus_node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focus the target view
|
|
||||||
self.setFocusRaw(.{ .view = view });
|
self.setFocusRaw(.{ .view = view });
|
||||||
} else {
|
} else {
|
||||||
// Otherwise clear the focus
|
|
||||||
self.setFocusRaw(.{ .none = {} });
|
self.setFocusRaw(.{ .none = {} });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,6 +283,13 @@ pub fn handleActivity(self: Self) void {
|
||||||
server.input_manager.idle.notifyActivity(self.wlr_seat);
|
server.input_manager.idle.notifyActivity(self.wlr_seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handleViewMap(self: *Self, view: *View) !void {
|
||||||
|
const new_focus_node = try util.gpa.create(ViewStack(*View).Node);
|
||||||
|
new_focus_node.view = view;
|
||||||
|
self.focus_stack.append(new_focus_node);
|
||||||
|
self.focus(view);
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle the unmapping of a view, removing it from the focus stack and
|
/// Handle the unmapping of a view, removing it from the focus stack and
|
||||||
/// setting the focus if needed.
|
/// setting the focus if needed.
|
||||||
pub fn handleViewUnmap(self: *Self, view: *View) void {
|
pub fn handleViewUnmap(self: *Self, view: *View) void {
|
||||||
|
|
|
@ -429,36 +429,30 @@ pub fn shouldTrackConfigure(self: Self) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called by the impl when the surface is ready to be displayed
|
/// Called by the impl when the surface is ready to be displayed
|
||||||
pub fn map(self: *Self) void {
|
pub fn map(self: *Self) !void {
|
||||||
log.debug("view '{s}' mapped", .{self.getTitle()});
|
log.debug("view '{s}' mapped", .{self.getTitle()});
|
||||||
|
|
||||||
if (self.foreign_toplevel_handle == null) {
|
if (self.foreign_toplevel_handle == null) {
|
||||||
self.foreign_toplevel_handle = wlr.ForeignToplevelHandleV1.create(
|
const handle = try wlr.ForeignToplevelHandleV1.create(server.foreign_toplevel_manager);
|
||||||
server.foreign_toplevel_manager,
|
self.foreign_toplevel_handle = handle;
|
||||||
) catch {
|
|
||||||
log.crit("out of memory", .{});
|
|
||||||
self.surface.?.resource.getClient().postNoMemory();
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.foreign_toplevel_handle.?.events.request_activate.add(&self.foreign_activate);
|
handle.events.request_activate.add(&self.foreign_activate);
|
||||||
self.foreign_toplevel_handle.?.events.request_fullscreen.add(&self.foreign_fullscreen);
|
handle.events.request_fullscreen.add(&self.foreign_fullscreen);
|
||||||
self.foreign_toplevel_handle.?.events.request_close.add(&self.foreign_close);
|
handle.events.request_close.add(&self.foreign_close);
|
||||||
|
|
||||||
if (self.getTitle()) |s| self.foreign_toplevel_handle.?.setTitle(s);
|
if (self.getTitle()) |s| handle.setTitle(s);
|
||||||
if (self.getAppId()) |s| self.foreign_toplevel_handle.?.setAppId(s);
|
if (self.getAppId()) |s| handle.setAppId(s);
|
||||||
|
|
||||||
self.foreign_toplevel_handle.?.outputEnter(self.output.wlr_output);
|
handle.outputEnter(self.output.wlr_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the view to the stack of its output
|
// Add the view to the stack of its output
|
||||||
const node = @fieldParentPtr(ViewStack(Self).Node, "view", self);
|
const node = @fieldParentPtr(ViewStack(Self).Node, "view", self);
|
||||||
self.output.views.attach(node, server.config.attach_mode);
|
self.output.views.attach(node, server.config.attach_mode);
|
||||||
|
|
||||||
// Focus the new view, assuming the seat is focusing the proper output
|
// Inform all seats that the view has been mapped so they can handle focus
|
||||||
// and there isn't something else like a fullscreen view grabbing focus.
|
|
||||||
var it = server.input_manager.seats.first;
|
var it = server.input_manager.seats.first;
|
||||||
while (it) |seat_node| : (it = seat_node.next) seat_node.data.focus(self);
|
while (it) |seat_node| : (it = seat_node.next) try seat_node.data.handleViewMap(self);
|
||||||
|
|
||||||
self.surface.?.sendEnter(self.output.wlr_output);
|
self.surface.?.sendEnter(self.output.wlr_output);
|
||||||
|
|
||||||
|
@ -480,10 +474,7 @@ pub fn unmap(self: *Self) void {
|
||||||
|
|
||||||
// Inform all seats that the view has been unmapped so they can handle focus
|
// Inform all seats that the view has been unmapped so they can handle focus
|
||||||
var it = server.input_manager.seats.first;
|
var it = server.input_manager.seats.first;
|
||||||
while (it) |node| : (it = node.next) {
|
while (it) |seat_node| : (it = seat_node.next) seat_node.data.handleViewUnmap(self);
|
||||||
const seat = &node.data;
|
|
||||||
seat.handleViewUnmap(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.output.sendViewTags();
|
self.output.sendViewTags();
|
||||||
|
|
||||||
|
|
|
@ -231,7 +231,10 @@ fn handleMap(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurfa
|
||||||
_ = toplevel.setTiled(.{ .top = true, .bottom = true, .left = true, .right = true });
|
_ = toplevel.setTiled(.{ .top = true, .bottom = true, .left = true, .right = true });
|
||||||
}
|
}
|
||||||
|
|
||||||
view.map();
|
view.map() catch {
|
||||||
|
log.crit("out of memory", .{});
|
||||||
|
xdg_surface.resource.getClient().postNoMemory();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the surface is unmapped and will no longer be displayed.
|
/// Called when the surface is unmapped and will no longer be displayed.
|
||||||
|
|
|
@ -207,7 +207,10 @@ fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
view.map();
|
view.map() catch {
|
||||||
|
std.log.crit("out of memory", .{});
|
||||||
|
surface.resource.getClient().postNoMemory();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the surface is unmapped and will no longer be displayed.
|
/// Called when the surface is unmapped and will no longer be displayed.
|
||||||
|
|
Loading…
Reference in a new issue