Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
OutputManager: reject coordinates too large for X11
We already reject negative coordinates when Xwayland is enabled but
do not yet reject coordinates too large for Xwayland to handle.
river/Output.zig | 26 +++++++++++++++++++++
river/OutputManager.zig | 61 ++++++++++++++++++++++---------------------------
2 files changed, 53 insertions(+), 34 deletions(-)
diff --git a/river/Output.zig b/river/Output.zig
index f2f9530..7ede781 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -57,6 +57,32 @@ pub const State = struct {
adaptive_sync: bool,
auto_layout: bool,
+ pub fn fromHeadState(state: *const wlr.OutputHeadV1.State) State {
+ assert(state.enabled);
+ return .{
+ .state = .enabled,
+ .mode = blk: {
+ if (state.mode) |mode| {
+ break :blk .{ .standard = mode };
+ } else {
+ break :blk .{ .custom = .{
+ .width = state.custom_mode.width,
+ .height = state.custom_mode.height,
+ .refresh = state.custom_mode.refresh,
+ } };
+ }
+ },
+ .x = state.x,
+ .y = state.y,
+ // Round to nearest 1/120 to ensure the scale is exactly represented
+ // in the fractional-scale-v1 protocol.
+ .scale = @round(state.scale * 120) / 120,
+ .transform = state.transform,
+ .adaptive_sync = state.adaptive_sync_enabled,
+ .auto_layout = false,
+ };
+ }
+
/// Width/height in the logical coordinate space
pub fn dimensions(state: *const State) struct { u31, u31 } {
var w: i32, var h: i32 = switch (state.mode) {
diff --git a/river/OutputManager.zig b/river/OutputManager.zig
index 1d8a1c2..9db205a 100644
--- a/river/OutputManager.zig
+++ b/river/OutputManager.zig
@@ -6,6 +6,7 @@ const OutputManager = @This();
const build_options = @import("build_options");
const std = @import("std");
const assert = std.debug.assert;
+const math = std.math;
const mem = std.mem;
const wlr = @import("wlroots");
const wl = @import("wayland").server.wl;
@@ -134,33 +135,12 @@ fn handleManagerApply(_: *wl.Listener(*wlr.OutputConfigurationV1), config: *wlr.
var it = config.heads.iterator(.forward);
while (it.next()) |head| {
const output: *Output = @ptrCast(@alignCast(head.state.output.data));
- if (!head.state.enabled) {
+ if (head.state.enabled) {
+ output.scheduled = .fromHeadState(&head.state);
+ } else {
// Avoid overwriting and losing all other output state on disable.
output.scheduled.state = .disabled_hard;
- continue;
}
- output.scheduled = .{
- .state = .enabled,
- .mode = blk: {
- if (head.state.mode) |mode| {
- break :blk .{ .standard = mode };
- } else {
- break :blk .{ .custom = .{
- .width = head.state.custom_mode.width,
- .height = head.state.custom_mode.height,
- .refresh = head.state.custom_mode.refresh,
- } };
- }
- },
- .x = head.state.x,
- .y = head.state.y,
- // Round to nearest 1/120 to ensure the scale is exactly represented
- // in the fractional-scale-v1 protocol.
- .scale = @round(head.state.scale * 120) / 120,
- .transform = head.state.transform,
- .adaptive_sync = head.state.adaptive_sync_enabled,
- .auto_layout = false,
- };
}
if (server.wm.scheduled.output_config) |old| {
@@ -175,16 +155,29 @@ fn handleManagerApply(_: *wl.Listener(*wlr.OutputConfigurationV1), config: *wlr.
fn validateConfigCoordinates(config: *wlr.OutputConfigurationV1) bool {
var it = config.heads.iterator(.forward);
while (it.next()) |head| {
- // Negative output coordinates currently cause Xwayland clients to not receive click events.
- // See: https://gitlab.freedesktop.org/xorg/xserver/-/issues/899
- if (build_options.xwayland and server.xwayland != null and
- (head.state.x < 0 or head.state.y < 0))
- {
- log.err(
- \\Attempted to set negative coordinates for output {s}.
- \\Negative output coordinates are disallowed if Xwayland is enabled due to a limitation of Xwayland.
- , .{head.state.output.name});
- return false;
+ if (!head.state.enabled) continue;
+
+ const proposed: Output.State = .fromHeadState(&head.state);
+ if (build_options.xwayland and server.xwayland != null) {
+ // Negative output coordinates currently cause Xwayland clients to not receive click events.
+ // See: https://gitlab.freedesktop.org/xorg/xserver/-/issues/899
+ if (proposed.x < 0 or proposed.y < 0) {
+ log.err(
+ \\Attempted to set negative coordinates for output {s}.
+ \\Negative output coordinates are disallowed if Xwayland is enabled due to a limitation of Xwayland.
+ , .{head.state.output.name});
+ return false;
+ }
+ const width, const height = proposed.dimensions();
+ if (proposed.x + width > math.maxInt(i16) or
+ proposed.y + height > math.maxInt(i16))
+ {
+ log.err(
+ \\Attempted to set too-large coordinates for output {s}.
+ \\Coordinates greater than {d} are disallowed if Xwayland is enabled due to a limitation of X11.
+ , .{ head.state.output.name, math.maxInt(i16) });
+ return false;
+ }
}
}
return true;