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
|
--- a/src/api/wayfire/workspace-stream.hpp
+++ b/src/api/wayfire/workspace-stream.hpp
@@ -8,6 +8,27 @@
namespace wf
{
+/** An output-local wallpaper which can render a specific workspace.
+ *
+ * Attach directly to an output's BOTTOM layer, behind its other children.
+ * Normal scene rendering selects the active workspace. Workspace streams call
+ * gen_workspace_instances with their own coordinates, without translating the
+ * wallpaper like a window or duplicating its normal render instance.
+ */
+class workspace_background_node_t : public scene::node_t
+{
+ public:
+ workspace_background_node_t() : scene::node_t(false)
+ {}
+ virtual void gen_workspace_instances(wf::point_t workspace,
+ std::vector<scene::render_instance_uptr>& instances,
+ scene::damage_callback push_damage, wf::output_t *output) = 0;
+};
+
+// Additive API capability; referencing this symbol prevents plugins using the
+// new stream contract from silently loading on a compositor without it.
+uint32_t workspace_background_api_version();
+
/**
* A workspace stream is a special node which displays a workspace of an output.
*/
--- a/src/output/workspace-stream.cpp
+++ b/src/output/workspace-stream.cpp
@@ -12,14 +12,19 @@
namespace wf
{
+uint32_t workspace_background_api_version()
+{
+ return 1;
+}
+
class workspace_stream_node_t::workspace_stream_instance_t : public scene::
render_instance_t
{
workspace_stream_node_t *self;
std::vector<scene::render_instance_uptr> instances;
- // True for each instance generated from a desktop environment view.
- std::vector<bool> is_desktop_environment;
+ // True for output-local instances (desktop surfaces and workspace wallpaper).
+ std::vector<bool> output_local_instances;
wf::pointf_t get_offset()
{
@@ -62,6 +67,20 @@
{
if (ch->is_enabled())
{
+ if (auto wallpaper = dynamic_cast<workspace_background_node_t*>(ch.get()))
+ {
+ if (self->include_workspace_views)
+ {
+ 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);
+ }
+
+ continue;
+ }
+
auto view = node_to_view(ch);
const bool is_de = (view && (view->role == wf::VIEW_ROLE_DESKTOP_ENVIRONMENT));
static wf::option_wrapper_t<std::string> rotate_layer_shell{
@@ -99,18 +118,18 @@
ch->gen_render_instances(this->instances,
is_de ? push_damage : translate_and_push_damage, self->output);
- // Mark whether the instances were generated from a desktop environment view
+ // Mark whether instances use output-local rather than workspace coordinates
num_generated = this->instances.size() - num_generated;
for (size_t i = 0; i < num_generated; i++)
{
// Inclusion in a rotating texture does not make a panel
// workspace-local: keep it visible and damaged on every face.
- is_desktop_environment.push_back(is_de);
+ output_local_instances.push_back(is_de);
}
}
}
- wf::dassert(instances.size() == is_desktop_environment.size(), "Setting de flag is wrong!");
+ wf::dassert(instances.size() == output_local_instances.size(), "Setting de flag is wrong!");
}
}
@@ -128,7 +147,7 @@
our_damage += offset;
for (size_t i = 0; i < instances.size(); i++)
{
- if (is_desktop_environment[i])
+ if (output_local_instances[i])
{
// Special handling: move everything to 'current workspace' so that panels and backgrounds
// render at the correct position.
--- a/plugins/cube/cube.cpp
+++ b/plugins/cube/cube.cpp
@@ -1132,7 +1132,10 @@
* that are on the back, and then we render those at the front, so we
* don't have to use depth testing and we also can support alpha cube. */
GL_CALL(glEnable(GL_BLEND));
- GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
+ // Workspace buffers are composed by wlroots with premultiplied
+ // alpha. Multiplying their RGB by alpha again darkens transparent
+ // wallpapers and windows when the face is blended onto the desktop.
+ GL_CALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
GL_CALL(glEnable(GL_CULL_FACE));
wf::gles::for_each_scissor_rect(data.target, data.damage, [&]
{
|