git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit2dde1b8cd8bec345f2810de7abb829ddee9f3c42
parent72aaef25e1
authorIsaac Freund <[email protected]>
date2020-04-18 16:21
Send surface enter/leave events

 src/command/send_to_output.zig | 17 ++++++-----------
 src/output.zig                 |  5 ++---
 src/view.zig                   | 16 ++++++++++++++++
 3 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/src/command/send_to_output.zig b/src/command/send_to_output.zig
index 09ce7ad..b626f93 100644
--- a/src/command/send_to_output.zig
+++ b/src/command/send_to_output.zig
@@ -4,8 +4,6 @@ const std = @import("std");
 const Arg = @import("../command.zig").Arg;
 const Output = @import("../output.zig").Output;
 const Seat = @import("../seat.zig").Seat;
-const ViewStack = @import("../view_stack.zig").ViewStack;
-const View = @import("../view.zig").View;
 
 /// Send the focused view to the the next or the previous output, depending on
 /// the bool passed. Does nothing if there is only one output.
@@ -17,23 +15,20 @@ pub fn sendToOutput(seat: *Seat, arg: Arg) void {
 
     if (seat.focused_view) |view| {
         // If the noop output is focused, there is nowhere to send the view
-        if (seat.focused_output == &root.noop_output) {
+        if (view.output == &root.noop_output) {
             std.debug.assert(root.outputs.len == 0);
             return;
         }
 
         // Send to the next/preg output in the list if there is one, else wrap
-        const focused_node = @fieldParentPtr(std.TailQueue(Output).Node, "data", seat.focused_output);
-        const target_output = switch (direction) {
-            .Next => if (focused_node.next) |node| &node.data else &root.outputs.first.?.data,
-            .Prev => if (focused_node.prev) |node| &node.data else &root.outputs.last.?.data,
+        const current_node = @fieldParentPtr(std.TailQueue(Output).Node, "data", view.output);
+        const destination_output = switch (direction) {
+            .Next => if (current_node.next) |node| &node.data else &root.outputs.first.?.data,
+            .Prev => if (current_node.prev) |node| &node.data else &root.outputs.last.?.data,
         };
 
         // Move the view to the target output
-        const view_node = @fieldParentPtr(ViewStack(View).Node, "view", view);
-        seat.focused_output.views.remove(view_node);
-        target_output.views.push(view_node);
-        view.output = target_output;
+        view.sendToOutput(destination_output);
 
         // Handle the change and focus whatever's next in the focus stack
         root.arrange();
diff --git a/src/output.zig b/src/output.zig
index bb88156..4baf8a8 100644
--- a/src/output.zig
+++ b/src/output.zig
@@ -406,9 +406,8 @@ pub const Output = struct {
 
         // Move all views from the destroyed output to the fallback one
         while (destroyed_output.views.last) |node| {
-            destroyed_output.views.remove(node);
-            fallback_output.views.push(node);
-            node.view.output = fallback_output;
+            const view = &node.view;
+            view.sendToOutput(fallback_output);
         }
 
         // Close all layer surfaces on the destroyed output
diff --git a/src/view.zig b/src/view.zig
index ea6fdc0..f805acc 100644
--- a/src/view.zig
+++ b/src/view.zig
@@ -122,6 +122,20 @@ pub const View = struct {
         }
     }
 
+    /// Move a view from one output to another, sending the required enter/leave
+    /// events.
+    pub fn sendToOutput(self: *Self, destination_output: *Output) void {
+        const node = @fieldParentPtr(ViewStack(View).Node, "view", self);
+
+        self.output.views.remove(node);
+        destination_output.views.push(node);
+
+        c.wlr_surface_send_leave(self.wlr_xdg_surface.surface, self.output.wlr_output);
+        c.wlr_surface_send_enter(self.wlr_xdg_surface.surface, destination_output.wlr_output);
+
+        self.output = destination_output;
+    }
+
     /// Send a close event to the view's client
     pub fn close(self: Self) void {
         // Note: we don't call arrange() here as it will be called
@@ -162,6 +176,8 @@ pub const View = struct {
             seat_node.data.focus(view);
         }
 
+        c.wlr_surface_send_enter(view.wlr_xdg_surface.surface, view.output.wlr_output);
+
         view.output.root.arrange();
     }