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;
+}
+}
|