summaryrefslogtreecommitdiff
path: root/gui-wm/wayfire/files/wayfire-0.11.0-r35-fullscreen-subpasses.patch
blob: feb4b36e2bc5f88e0b36bde2ad93eaa3a7e7b75b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
--- a/src/output/workspace-stream.cpp
+++ b/src/output/workspace-stream.cpp
@@ -9,6 +9,7 @@
 #include <wayfire/output.hpp>
 #include <wayfire/render-manager.hpp>
 #include <wayfire/workspace-set.hpp>
+#include "fullscreen-regions.hpp"
 
 namespace wf
 {
@@ -25,6 +26,7 @@
     std::vector<scene::render_instance_uptr> instances;
     // True for output-local instances (desktop surfaces and workspace wallpaper).
     std::vector<bool> output_local_instances;
+    std::vector<bool> is_top_layer;
 
     wf::pointf_t get_offset()
     {
@@ -74,8 +76,10 @@
                             size_t count = this->instances.size();
                             wallpaper->gen_workspace_instances(self->ws, this->instances,
                                 push_damage, self->output);
-                            output_local_instances.insert(output_local_instances.end(),
-                                this->instances.size() - count, true);
+                            count = this->instances.size() - count;
+                            output_local_instances.insert(output_local_instances.end(), count, true);
+                            is_top_layer.insert(is_top_layer.end(), count,
+                                output_node == self->output->node_for_layer(scene::layer::TOP));
                         }
 
                         continue;
@@ -125,11 +129,13 @@
                         // Inclusion in a rotating texture does not make a panel
                         // workspace-local: keep it visible and damaged on every face.
                         output_local_instances.push_back(is_de);
+                        is_top_layer.push_back(output_node == self->output->node_for_layer(scene::layer::TOP));
                     }
                 }
             }
 
             wf::dassert(instances.size() == output_local_instances.size(), "Setting de flag is wrong!");
+            wf::dassert(instances.size() == is_top_layer.size(), "Setting TOP flag is wrong!");
         }
     }
 
@@ -145,6 +151,7 @@
             wf::render_target_t subtarget = target.translated(offset);
 
             our_damage += offset;
+            auto fullscreen = workspace_fullscreen_regions(self->output, self->ws);
             for (size_t i = 0; i < instances.size(); i++)
             {
                 if (output_local_instances[i])
@@ -152,7 +159,10 @@
                     // Special handling: move everything to 'current workspace' so that panels and backgrounds
                     // render at the correct position.
                     our_damage -= offset;
+                    auto excluded = is_top_layer[i] ? our_damage & fullscreen : wf::regionf_t{};
+                    our_damage ^= excluded;
                     instances[i]->schedule_instructions(instructions, target, our_damage);
+                    our_damage |= excluded;
                     our_damage += offset;
                 } else
                 {
@@ -193,8 +203,17 @@
 
     void compute_visibility(wf::output_t *output, wf::regionf_t& visible) override
     {
-        scene::compute_visibility_from_list(instances, output, visible,
-            -get_offset());
+        auto offset = get_offset();
+        auto fullscreen = workspace_fullscreen_regions(self->output, self->ws);
+        for (size_t i = 0; i < instances.size(); ++i)
+        {
+            if (!output_local_instances[i]) visible += offset;
+            auto excluded = is_top_layer[i] ? visible & fullscreen : wf::regionf_t{};
+            visible ^= excluded;
+            instances[i]->compute_visibility(output, visible);
+            visible |= excluded;
+            if (!output_local_instances[i]) visible -= offset;
+        }
     }
 };
 
--- /dev/null
+++ b/src/output/fullscreen-regions.hpp
@@ -0,0 +1,39 @@
+#pragma once
+#include <wayfire/window-scope.hpp>
+#include <wayfire/output.hpp>
+#include <wayfire/workspace-set.hpp>
+
+namespace wf
+{
+// Workspace subpasses generate children directly, bypassing the TOP output
+// node's render mask. Compute their mask in the sampled workspace's coordinates,
+// not from the current viewport (which would hide bars on the wrong cube face).
+inline regionf_t workspace_fullscreen_regions(output_t *output, point_t workspace)
+{
+    auto size = output->get_relative_geometry();
+    auto delta = workspace - output->wset()->get_current_workspace();
+    pointf_t offset{delta.x * size.width, delta.y * size.height};
+    auto top_in_region = [&] (auto&& visit, const scene::node_ptr& node,
+        const geometry_t& region) -> wayfire_toplevel_view
+    {
+        if (auto top = toplevel_cast(node_to_view(node)); top && top->is_mapped() && !top->minimized &&
+            output->wset()->view_visible_on(top, workspace))
+        {
+            auto overlap = geometry_intersection(top->get_geometry(), region);
+            if (overlap.width > 0 && overlap.height > 0) return top;
+        }
+        for (const auto& child : node->get_children())
+            if (child->is_enabled())
+                if (auto top = visit(visit, child, region)) return top;
+        return nullptr;
+    };
+    std::vector<output_stitch_zone_t> zones{{output->to_string(), size}};
+    if (auto stitch = output->get_data<output_stitch_layout_t>()) zones = stitch->zones;
+    regionf_t hidden;
+    for (const auto& zone : zones)
+        if (auto top = top_in_region(top_in_region, output->wset()->get_node(), zone.geometry + offset);
+            top && top->toplevel()->current().fullscreen)
+            hidden |= geometry_intersection(top->get_geometry() - offset, zone.geometry);
+    return hidden;
+}
+}