river: update for wlroots 0.13.0
This commit is contained in:
parent
3c1f1df0c0
commit
9e3e92050e
10 changed files with 104 additions and 59 deletions
|
@ -33,7 +33,7 @@ installed:
|
||||||
- [zig](https://ziglang.org/download/) 0.7.1
|
- [zig](https://ziglang.org/download/) 0.7.1
|
||||||
- wayland
|
- wayland
|
||||||
- wayland-protocols
|
- wayland-protocols
|
||||||
- [wlroots](https://github.com/swaywm/wlroots) 0.12.0
|
- [wlroots](https://github.com/swaywm/wlroots) 0.13.0
|
||||||
- xkbcommon
|
- xkbcommon
|
||||||
- libevdev
|
- libevdev
|
||||||
- pixman
|
- pixman
|
||||||
|
|
2
deps/zig-wlroots
vendored
2
deps/zig-wlroots
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 35e5676b1a77b2a44f370280b78b0d38598d97ee
|
Subproject commit 6c62568adfe92a1852566b7d091e99f4b28cbabb
|
|
@ -25,7 +25,7 @@
|
||||||
THIS SOFTWARE.
|
THIS SOFTWARE.
|
||||||
</copyright>
|
</copyright>
|
||||||
|
|
||||||
<interface name="zwlr_layer_shell_v1" version="3">
|
<interface name="zwlr_layer_shell_v1" version="4">
|
||||||
<description summary="create surfaces that are layers of the desktop">
|
<description summary="create surfaces that are layers of the desktop">
|
||||||
Clients can use this interface to assign the surface_layer role to
|
Clients can use this interface to assign the surface_layer role to
|
||||||
wl_surfaces. Such surfaces are assigned to a "layer" of the output and
|
wl_surfaces. Such surfaces are assigned to a "layer" of the output and
|
||||||
|
@ -47,6 +47,12 @@
|
||||||
or manipulate a buffer prior to the first layer_surface.configure call
|
or manipulate a buffer prior to the first layer_surface.configure call
|
||||||
must also be treated as errors.
|
must also be treated as errors.
|
||||||
|
|
||||||
|
After creating a layer_surface object and setting it up, the client
|
||||||
|
must perform an initial commit without any buffer attached.
|
||||||
|
The compositor will reply with a layer_surface.configure event.
|
||||||
|
The client must acknowledge it and is then allowed to attach a buffer
|
||||||
|
to map the surface.
|
||||||
|
|
||||||
You may pass NULL for output to allow the compositor to decide which
|
You may pass NULL for output to allow the compositor to decide which
|
||||||
output to use. Generally this will be the one that the user most
|
output to use. Generally this will be the one that the user most
|
||||||
recently interacted with.
|
recently interacted with.
|
||||||
|
@ -94,7 +100,7 @@
|
||||||
</request>
|
</request>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="zwlr_layer_surface_v1" version="3">
|
<interface name="zwlr_layer_surface_v1" version="4">
|
||||||
<description summary="layer metadata interface">
|
<description summary="layer metadata interface">
|
||||||
An interface that may be implemented by a wl_surface, for surfaces that
|
An interface that may be implemented by a wl_surface, for surfaces that
|
||||||
are designed to be rendered as a layer of a stacked desktop-like
|
are designed to be rendered as a layer of a stacked desktop-like
|
||||||
|
@ -103,6 +109,14 @@
|
||||||
Layer surface state (layer, size, anchor, exclusive zone,
|
Layer surface state (layer, size, anchor, exclusive zone,
|
||||||
margin, interactivity) is double-buffered, and will be applied at the
|
margin, interactivity) is double-buffered, and will be applied at the
|
||||||
time wl_surface.commit of the corresponding wl_surface is called.
|
time wl_surface.commit of the corresponding wl_surface is called.
|
||||||
|
|
||||||
|
Attaching a null buffer to a layer surface unmaps it.
|
||||||
|
|
||||||
|
Unmapping a layer_surface means that the surface cannot be shown by the
|
||||||
|
compositor until it is explicitly mapped again. The layer_surface
|
||||||
|
returns to the state it had right after layer_shell.get_layer_surface.
|
||||||
|
The client can re-map the surface by performing a commit without any
|
||||||
|
buffer attached, waiting for a configure event and handling it as usual.
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<request name="set_size">
|
<request name="set_size">
|
||||||
|
@ -189,21 +203,85 @@
|
||||||
<arg name="left" type="int"/>
|
<arg name="left" type="int"/>
|
||||||
</request>
|
</request>
|
||||||
|
|
||||||
|
<enum name="keyboard_interactivity">
|
||||||
|
<description summary="types of keyboard interaction possible for a layer shell surface">
|
||||||
|
Types of keyboard interaction possible for layer shell surfaces. The
|
||||||
|
rationale for this is twofold: (1) some applications are not interested
|
||||||
|
in keyboard events and not allowing them to be focused can improve the
|
||||||
|
desktop experience; (2) some applications will want to take exclusive
|
||||||
|
keyboard focus.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<entry name="none" value="0">
|
||||||
|
<description summary="no keyboard focus is possible">
|
||||||
|
This value indicates that this surface is not interested in keyboard
|
||||||
|
events and the compositor should never assign it the keyboard focus.
|
||||||
|
|
||||||
|
This is the default value, set for newly created layer shell surfaces.
|
||||||
|
|
||||||
|
This is useful for e.g. desktop widgets that display information or
|
||||||
|
only have interaction with non-keyboard input devices.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
<entry name="exclusive" value="1">
|
||||||
|
<description summary="request exclusive keyboard focus">
|
||||||
|
Request exclusive keyboard focus if this surface is above the shell surface layer.
|
||||||
|
|
||||||
|
For the top and overlay layers, the seat will always give
|
||||||
|
exclusive keyboard focus to the top-most layer which has keyboard
|
||||||
|
interactivity set to exclusive. If this layer contains multiple
|
||||||
|
surfaces with keyboard interactivity set to exclusive, the compositor
|
||||||
|
determines the one receiving keyboard events in an implementation-
|
||||||
|
defined manner. In this case, no guarantee is made when this surface
|
||||||
|
will receive keyboard focus (if ever).
|
||||||
|
|
||||||
|
For the bottom and background layers, the compositor is allowed to use
|
||||||
|
normal focus semantics.
|
||||||
|
|
||||||
|
This setting is mainly intended for applications that need to ensure
|
||||||
|
they receive all keyboard events, such as a lock screen or a password
|
||||||
|
prompt.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
<entry name="on_demand" value="2" since="4">
|
||||||
|
<description summary="request regular keyboard focus semantics">
|
||||||
|
This requests the compositor to allow this surface to be focused and
|
||||||
|
unfocused by the user in an implementation-defined manner. The user
|
||||||
|
should be able to unfocus this surface even regardless of the layer
|
||||||
|
it is on.
|
||||||
|
|
||||||
|
Typically, the compositor will want to use its normal mechanism to
|
||||||
|
manage keyboard focus between layer shell surfaces with this setting
|
||||||
|
and regular toplevels on the desktop layer (e.g. click to focus).
|
||||||
|
Nevertheless, it is possible for a compositor to require a special
|
||||||
|
interaction to focus or unfocus layer shell surfaces (e.g. requiring
|
||||||
|
a click even if focus follows the mouse normally, or providing a
|
||||||
|
keybinding to switch focus between layers).
|
||||||
|
|
||||||
|
This setting is mainly intended for desktop shell components (e.g.
|
||||||
|
panels) that allow keyboard interaction. Using this option can allow
|
||||||
|
implementing a desktop shell that can be fully usable without the
|
||||||
|
mouse.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
</enum>
|
||||||
|
|
||||||
<request name="set_keyboard_interactivity">
|
<request name="set_keyboard_interactivity">
|
||||||
<description summary="requests keyboard events">
|
<description summary="requests keyboard events">
|
||||||
Set to 1 to request that the seat send keyboard events to this layer
|
Set how keyboard events are delivered to this surface. By default,
|
||||||
surface. For layers below the shell surface layer, the seat will use
|
layer shell surfaces do not receive keyboard events; this request can
|
||||||
normal focus semantics. For layers above the shell surface layers, the
|
be used to change this.
|
||||||
seat will always give exclusive keyboard focus to the top-most layer
|
|
||||||
which has keyboard interactivity set to true.
|
This setting is inherited by child surfaces set by the get_popup
|
||||||
|
request.
|
||||||
|
|
||||||
Layer surfaces receive pointer, touch, and tablet events normally. If
|
Layer surfaces receive pointer, touch, and tablet events normally. If
|
||||||
you do not want to receive them, set the input region on your surface
|
you do not want to receive them, set the input region on your surface
|
||||||
to an empty region.
|
to an empty region.
|
||||||
|
|
||||||
Events is double-buffered, see wl_surface.commit.
|
Keyboard interactivity is double-buffered, see wl_surface.commit.
|
||||||
</description>
|
</description>
|
||||||
<arg name="keyboard_interactivity" type="uint"/>
|
<arg name="keyboard_interactivity" type="uint" enum="keyboard_interactivity"/>
|
||||||
</request>
|
</request>
|
||||||
|
|
||||||
<request name="get_popup">
|
<request name="get_popup">
|
||||||
|
@ -288,6 +366,7 @@
|
||||||
<entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
|
<entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
|
||||||
<entry name="invalid_size" value="1" summary="size is invalid"/>
|
<entry name="invalid_size" value="1" summary="size is invalid"/>
|
||||||
<entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
|
<entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
|
||||||
|
<entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
<enum name="anchor" bitfield="true">
|
<enum name="anchor" bitfield="true">
|
||||||
|
|
|
@ -239,7 +239,7 @@ fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.P
|
||||||
// give it keyboard focus.
|
// give it keyboard focus.
|
||||||
if (surface.isLayerSurface()) {
|
if (surface.isLayerSurface()) {
|
||||||
const wlr_layer_surface = wlr.LayerSurfaceV1.fromWlrSurface(surface);
|
const wlr_layer_surface = wlr.LayerSurfaceV1.fromWlrSurface(surface);
|
||||||
if (wlr_layer_surface.current.keyboard_interactive) {
|
if (wlr_layer_surface.current.keyboard_interactive == .exclusive) {
|
||||||
const layer_surface = @intToPtr(*LayerSurface, wlr_layer_surface.data);
|
const layer_surface = @intToPtr(*LayerSurface, wlr_layer_surface.data);
|
||||||
self.seat.focusOutput(layer_surface.output);
|
self.seat.focusOutput(layer_surface.output);
|
||||||
self.seat.setFocusRaw(.{ .layer = layer_surface });
|
self.seat.setFocusRaw(.{ .layer = layer_surface });
|
||||||
|
|
|
@ -348,7 +348,7 @@ pub fn arrangeLayers(self: *Self) void {
|
||||||
var it = self.getLayer(layer).last;
|
var it = self.getLayer(layer).last;
|
||||||
while (it) |node| : (it = node.prev) {
|
while (it) |node| : (it = node.prev) {
|
||||||
const layer_surface = &node.data;
|
const layer_surface = &node.data;
|
||||||
if (layer_surface.wlr_layer_surface.current.keyboard_interactive) {
|
if (layer_surface.wlr_layer_surface.current.keyboard_interactive == .exclusive) {
|
||||||
break :outer layer_surface;
|
break :outer layer_surface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,7 +368,7 @@ pub fn arrangeLayers(self: *Self) void {
|
||||||
} else if (seat.focused == .layer) {
|
} else if (seat.focused == .layer) {
|
||||||
// If the seat is currently focusing a layer without keyboard
|
// If the seat is currently focusing a layer without keyboard
|
||||||
// interactivity, stop focusing that layer.
|
// interactivity, stop focusing that layer.
|
||||||
if (!seat.focused.layer.wlr_layer_surface.current.keyboard_interactive) {
|
if (seat.focused.layer.wlr_layer_surface.current.keyboard_interactive != .exclusive) {
|
||||||
seat.setFocusRaw(.{ .none = {} });
|
seat.setFocusRaw(.{ .none = {} });
|
||||||
seat.focus(null);
|
seat.focus(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -517,14 +517,10 @@ fn applyHeadToOutput(head: *wlr.OutputConfigurationV1.Head, wlr_output: *wlr.Out
|
||||||
if (head.state.mode) |mode| {
|
if (head.state.mode) |mode| {
|
||||||
wlr_output.setMode(mode);
|
wlr_output.setMode(mode);
|
||||||
} else {
|
} else {
|
||||||
std.log.scoped(.output_manager).info("custom modes are not supported until the next wlroots release: ignoring", .{});
|
const custom_mode = &head.state.custom_mode;
|
||||||
// TODO(wlroots) uncomment the following lines when wlroots 0.13.0 is released
|
wlr_output.setCustomMode(custom_mode.width, custom_mode.height, custom_mode.refresh);
|
||||||
// See https://github.com/swaywm/wlroots/pull/2517
|
|
||||||
//const custom_mode = &head.state.custom_mode;
|
|
||||||
//wlr_output.setCustomMode(custom_mode.width, custom_mode.height, custom_mode.refresh);
|
|
||||||
}
|
}
|
||||||
// TODO(wlroots) Figure out if this conversion is needed or if that is a bug in wlroots
|
wlr_output.setScale(head.state.scale);
|
||||||
wlr_output.setScale(@floatCast(f32, head.state.scale));
|
|
||||||
wlr_output.setTransform(head.state.transform);
|
wlr_output.setTransform(head.state.transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ pub fn init(self: *Self) !void {
|
||||||
errdefer self.sigterm_source.remove();
|
errdefer self.sigterm_source.remove();
|
||||||
|
|
||||||
// This frees itself when the wl.Server is destroyed
|
// This frees itself when the wl.Server is destroyed
|
||||||
self.backend = try wlr.Backend.autocreate(self.wl_server, null);
|
self.backend = try wlr.Backend.autocreate(self.wl_server);
|
||||||
|
|
||||||
// This backend is used to create a noop output for use when no actual
|
// This backend is used to create a noop output for use when no actual
|
||||||
// outputs are available. This frees itself when the wl.Server is destroyed.
|
// outputs are available. This frees itself when the wl.Server is destroyed.
|
||||||
|
@ -140,7 +140,6 @@ pub fn deinit(self: *Self) void {
|
||||||
|
|
||||||
self.root.deinit();
|
self.root.deinit();
|
||||||
|
|
||||||
self.noop_backend.destroy();
|
|
||||||
self.wl_server.destroy();
|
self.wl_server.destroy();
|
||||||
|
|
||||||
self.input_manager.deinit();
|
self.input_manager.deinit();
|
||||||
|
|
|
@ -333,14 +333,14 @@ pub fn close(self: Self) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn forEachPopup(
|
pub inline fn forEachPopupSurface(
|
||||||
self: Self,
|
self: Self,
|
||||||
comptime T: type,
|
comptime T: type,
|
||||||
iterator: fn (surface: *wlr.Surface, sx: c_int, sy: c_int, data: T) callconv(.C) void,
|
iterator: fn (surface: *wlr.Surface, sx: c_int, sy: c_int, data: T) callconv(.C) void,
|
||||||
user_data: T,
|
user_data: T,
|
||||||
) void {
|
) void {
|
||||||
switch (self.impl) {
|
switch (self.impl) {
|
||||||
.xdg_toplevel => |xdg_toplevel| xdg_toplevel.forEachPopup(T, iterator, user_data),
|
.xdg_toplevel => |xdg_toplevel| xdg_toplevel.forEachPopupSurface(T, iterator, user_data),
|
||||||
.xwayland_view => {},
|
.xwayland_view => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,13 +104,13 @@ pub fn close(self: Self) void {
|
||||||
self.xdg_surface.role_data.toplevel.sendClose();
|
self.xdg_surface.role_data.toplevel.sendClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn forEachPopup(
|
pub inline fn forEachPopupSurface(
|
||||||
self: Self,
|
self: Self,
|
||||||
comptime T: type,
|
comptime T: type,
|
||||||
iterator: fn (surface: *wlr.Surface, sx: c_int, sy: c_int, data: T) callconv(.C) void,
|
iterator: fn (surface: *wlr.Surface, sx: c_int, sy: c_int, data: T) callconv(.C) void,
|
||||||
user_data: T,
|
user_data: T,
|
||||||
) void {
|
) void {
|
||||||
self.xdg_surface.forEachPopup(T, iterator, user_data);
|
self.xdg_surface.forEachPopupSurface(T, iterator, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the surface at output coordinates ox, oy and set sx, sy to the
|
/// Return the surface at output coordinates ox, oy and set sx, sy to the
|
||||||
|
|
|
@ -54,7 +54,7 @@ pub fn renderOutput(output: *Output) void {
|
||||||
|
|
||||||
output.wlr_output.attachRender(null) catch return;
|
output.wlr_output.attachRender(null) catch return;
|
||||||
|
|
||||||
renderer.begin(output.wlr_output.width, output.wlr_output.height);
|
renderer.begin(@intCast(u32, output.wlr_output.width), @intCast(u32, output.wlr_output.height));
|
||||||
|
|
||||||
// Find the first visible fullscreen view in the stack if there is one
|
// Find the first visible fullscreen view in the stack if there is one
|
||||||
var it = ViewStack(View).iter(output.views.first, .forward, output.current.tags, renderFilter);
|
var it = ViewStack(View).iter(output.views.first, .forward, output.current.tags, renderFilter);
|
||||||
|
@ -130,18 +130,6 @@ pub fn renderOutput(output: *Output) void {
|
||||||
// on-screen.
|
// on-screen.
|
||||||
renderer.end();
|
renderer.end();
|
||||||
|
|
||||||
// TODO(wlroots): remove this with the next release. It is here due to
|
|
||||||
// a wlroots bug in the screencopy damage implementation
|
|
||||||
{
|
|
||||||
var w: c_int = undefined;
|
|
||||||
var h: c_int = undefined;
|
|
||||||
output.wlr_output.transformedResolution(&w, &h);
|
|
||||||
var damage: pixman.Region32 = undefined;
|
|
||||||
damage.init();
|
|
||||||
_ = damage.unionRect(&damage, 0, 0, @intCast(c_uint, w), @intCast(c_uint, h));
|
|
||||||
output.wlr_output.setDamage(&damage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: handle failure
|
// TODO: handle failure
|
||||||
output.wlr_output.commit() catch
|
output.wlr_output.commit() catch
|
||||||
log.err("output commit failed for {}", .{output.wlr_output.name});
|
log.err("output commit failed for {}", .{output.wlr_output.name});
|
||||||
|
@ -178,7 +166,7 @@ fn renderLayer(
|
||||||
renderSurfaceIterator,
|
renderSurfaceIterator,
|
||||||
&rdata,
|
&rdata,
|
||||||
),
|
),
|
||||||
.popups => layer_surface.wlr_layer_surface.forEachPopup(
|
.popups => layer_surface.wlr_layer_surface.forEachPopupSurface(
|
||||||
*SurfaceRenderData,
|
*SurfaceRenderData,
|
||||||
renderSurfaceIterator,
|
renderSurfaceIterator,
|
||||||
&rdata,
|
&rdata,
|
||||||
|
@ -227,24 +215,7 @@ fn renderViewPopups(output: *const Output, view: *View, now: *os.timespec) void
|
||||||
.when = now,
|
.when = now,
|
||||||
.opacity = view.opacity,
|
.opacity = view.opacity,
|
||||||
};
|
};
|
||||||
view.forEachPopup(*SurfaceRenderData, renderPopupSurfaceIterator, &rdata);
|
view.forEachPopupSurface(*SurfaceRenderData, renderSurfaceIterator, &rdata);
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(wlroots): replace with wlr_xdg_surface_for_each_popup_surface()
|
|
||||||
fn renderPopupSurfaceIterator(
|
|
||||||
surface: *wlr.Surface,
|
|
||||||
surface_x: c_int,
|
|
||||||
surface_y: c_int,
|
|
||||||
rdata: *SurfaceRenderData,
|
|
||||||
) callconv(.C) void {
|
|
||||||
var new_rdata = SurfaceRenderData{
|
|
||||||
.output = rdata.output,
|
|
||||||
.output_x = rdata.output_x + surface_x,
|
|
||||||
.output_y = rdata.output_y + surface_y,
|
|
||||||
.when = rdata.when,
|
|
||||||
.opacity = rdata.opacity,
|
|
||||||
};
|
|
||||||
surface.forEachSurface(*SurfaceRenderData, renderSurfaceIterator, &new_rdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderDragIcons(output: *const Output, now: *os.timespec) void {
|
fn renderDragIcons(output: *const Output, now: *os.timespec) void {
|
||||||
|
|
Loading…
Reference in a new issue