diff options
| author | Isaac Freund <ifreund@ifreund.xyz> | 2020-05-08 14:51:10 +0200 |
|---|---|---|
| committer | Isaac Freund <ifreund@ifreund.xyz> | 2020-05-08 14:51:10 +0200 |
| commit | ac735719cfc086c54ff939786823b29de2c24c0a (patch) | |
| tree | c8ee87c720b067bbf8a757e8ea098d2b87393141 /src/XwaylandView.zig | |
| parent | 71d580b81173c6e6f93354c6e783972a6aa37b27 (diff) | |
| download | river-ac735719cfc086c54ff939786823b29de2c24c0a.tar.gz river-ac735719cfc086c54ff939786823b29de2c24c0a.tar.xz | |
Implement initial Xwayland support
Diffstat (limited to 'src/XwaylandView.zig')
| -rw-r--r-- | src/XwaylandView.zig | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/src/XwaylandView.zig b/src/XwaylandView.zig new file mode 100644 index 0000000..56beec8 --- /dev/null +++ b/src/XwaylandView.zig @@ -0,0 +1,151 @@ +// This file is part of river, a dynamic tiling wayland compositor. +// +// Copyright 2020 Isaac Freund +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +const Self = @This(); + +const std = @import("std"); + +const c = @import("c.zig"); + +const Box = @import("Box.zig"); +const Log = @import("log.zig").Log; +const View = @import("View.zig"); +const ViewStack = @import("view_stack.zig").ViewStack; +const XdgPopup = @import("XdgPopup.zig"); + +/// The view this xwayland view implements +view: *View, + +/// The corresponding wlroots object +wlr_xwayland_surface: *c.wlr_xwayland_surface, + +// Listeners that are always active over the view's lifetime +listen_destroy: c.wl_listener, +listen_map: c.wl_listener, +listen_unmap: c.wl_listener, + +// Listeners that are only active while the view is mapped +listen_commit: c.wl_listener, + +pub fn init(self: *Self, view: *View, wlr_xwayland_surface: *c.wlr_xwayland_surface) void { + self.view = view; + self.wlr_xwayland_surface = wlr_xwayland_surface; + wlr_xwayland_surface.data = self; + + // Add listeners that are active over the view's entire lifetime + self.listen_destroy.notify = handleDestroy; + c.wl_signal_add(&self.wlr_xwayland_surface.events.destroy, &self.listen_destroy); + + self.listen_map.notify = handleMap; + c.wl_signal_add(&self.wlr_xwayland_surface.events.map, &self.listen_map); + + self.listen_unmap.notify = handleUnmap; + c.wl_signal_add(&self.wlr_xwayland_surface.events.unmap, &self.listen_unmap); +} + +/// TODO: real output layout coords +pub fn configure(self: Self, pending_box: Box) void { + c.wlr_xwayland_surface_configure( + self.wlr_xwayland_surface, + 0, + 0, + @intCast(u16, pending_box.width), + @intCast(u16, pending_box.height), + ); +} + +/// Inform the xwayland surface that it has gained focus +pub fn setActivated(self: Self, activated: bool) void { + c.wlr_xwayland_surface_activate(self.wlr_xwayland_surface, activated); +} + +/// Close the view. This will lead to the unmap and destroy events being sent +pub fn close(self: Self) void { + c.wlr_xwayland_surface_close(self.wlr_xwayland_surface); +} + +/// Iterate over all surfaces of the xwayland view. +pub fn forEachSurface( + self: Self, + iterator: c.wlr_surface_iterator_func_t, + user_data: ?*c_void, +) void { + c.wlr_surface_for_each_surface(self.wlr_xwayland_surface.surface, iterator, user_data); +} + +/// Return the surface at output coordinates ox, oy and set sx, sy to the +/// corresponding surface-relative coordinates, if there is a surface. +pub fn surfaceAt(self: Self, ox: f64, oy: f64, sx: *f64, sy: *f64) ?*c.wlr_surface { + return c.wlr_surface_surface_at( + self.wlr_xwayland_surface.surface, + ox - @intToFloat(f64, self.view.current_box.x), + oy - @intToFloat(f64, self.view.current_box.y), + sx, + sy, + ); +} + +/// Called when the xwayland surface is destroyed +fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { + const self = @fieldParentPtr(Self, "listen_destroy", listener.?); + const output = self.view.output; + + // Remove listeners that are active for the entire lifetime of the view + c.wl_list_remove(&self.listen_destroy.link); + c.wl_list_remove(&self.listen_map.link); + c.wl_list_remove(&self.listen_unmap.link); + + // Remove the view from the stack + const node = @fieldParentPtr(ViewStack(View).Node, "view", self.view); + output.views.remove(node); + output.root.server.allocator.destroy(node); +} + +/// Called when the xwayland surface is mapped, or ready to display on-screen. +fn handleMap(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { + const self = @fieldParentPtr(Self, "listen_map", listener.?); + const view = self.view; + const root = view.output.root; + + // Add listeners that are only active while mapped + self.listen_commit.notify = handleCommit; + c.wl_signal_add(&self.wlr_xwayland_surface.surface.*.events.commit, &self.listen_commit); + + view.wlr_surface = self.wlr_xwayland_surface.surface; + view.floating = false; + + view.natural_width = self.wlr_xwayland_surface.width; + view.natural_height = self.wlr_xwayland_surface.height; + + view.map(); +} + +/// Called when the surface is unmapped and will no longer be displayed. +fn handleUnmap(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { + const self = @fieldParentPtr(Self, "listen_unmap", listener.?); + + self.view.unmap(); + + // Remove listeners that are only active while mapped + c.wl_list_remove(&self.listen_commit.link); +} + +/// Called when the surface is comitted +fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { + const self = @fieldParentPtr(Self, "listen_commit", listener.?); + // TODO: check for unexpected change in size and react as needed +} |
