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
127
128
129
130
131
132
133
|
--- a/plugins/cube/cube.cpp
+++ b/plugins/cube/cube.cpp
@@ -390,7 +390,8 @@
/* the Z camera distance so that (-1, 1) is mapped to the whole screen
* for the given FOV */
- float identity_z_offset;
+ float identity_z_offset = 0.0f;
+ int geometry_faces = 0;
OpenGL::program_t program;
@@ -452,6 +453,31 @@
int get_num_faces()
{
return output->wset()->get_workspace_grid_size().width;
+ }
+
+ bool refresh_cube_geometry()
+ {
+ int faces = get_num_faces();
+ if (faces == geometry_faces)
+ {
+ return false;
+ }
+
+ float old_offset = identity_z_offset;
+ animation.side_angle = 2 * M_PI / float(faces);
+ identity_z_offset = faces == 1 ? 0.0f :
+ 0.5 / std::tan(animation.side_angle / 2);
+ if (geometry_faces)
+ {
+ // Preserve the camera's distance from the cube when a new
+ // workspace count changes its radius.
+ float offset = animation.cube_animation.offset_z +
+ identity_z_offset - old_offset;
+ animation.cube_animation.offset_z.set(offset, offset);
+ }
+
+ geometry_faces = faces;
+ return true;
}
wf::plugin_activation_data_t grab_interface{
@@ -888,8 +914,15 @@
/* Tries to initialize renderer, activate plugin, etc. */
bool activate()
{
+ const bool geometry_changed = refresh_cube_geometry();
if (output->is_plugin_active(grab_interface.name))
{
+ if (geometry_changed)
+ {
+ rebuild_cube_render_node();
+ output->render->damage_whole();
+ }
+
return true;
}
@@ -903,15 +936,6 @@
output->render->add_effect(&pre_hook, wf::OUTPUT_EFFECT_PRE);
output->render->set_require_depth_buffer(true);
- auto wsize = output->wset()->get_workspace_grid_size();
- animation.side_angle = 2 * M_PI / float(wsize.width);
- identity_z_offset = 0.5 / std::tan(animation.side_angle / 2);
- if (wsize.width == 1)
- {
- // tan(M_PI) is 0, so identity_z_offset is invalid
- identity_z_offset = 0.0f;
- }
-
reload_background();
animation.cube_animation.offset_z.set(identity_z_offset + Z_OFFSET_NEAR,
identity_z_offset + Z_OFFSET_NEAR);
@@ -940,14 +964,17 @@
output->render->rem_effect(&pre_hook);
output->render->set_require_depth_buffer(false);
- /* Figure out how much we have rotated and switch workspace */
- int size = get_num_faces();
- int dvx = calculate_viewport_dx_from_rotation();
-
- auto cws = workspace_animation_anchor.value_or(
- output->wset()->get_current_workspace());
- int nvx = (cws.x + (dvx % size) + size) % size;
- output->wset()->set_workspace({nvx, cws.y});
+ // Vswitch already committed its destination before starting this
+ // animation. Cancelling it must retain that workspace. Interactive
+ // cube rotations still select the face nearest the current angle.
+ if (!workspace_animation_anchor)
+ {
+ int size = get_num_faces();
+ int dvx = calculate_viewport_dx_from_rotation();
+ auto cws = output->wset()->get_current_workspace();
+ int nvx = (cws.x + (dvx % size) + size) % size;
+ output->wset()->set_workspace({nvx, cws.y});
+ }
fixed_workspace_view = nullptr;
workspace_animation_anchor.reset();
@@ -1272,6 +1299,12 @@
bool animation_was_running = false;
wf::effect_hook_t pre_hook = [=] ()
{
+ if (refresh_cube_geometry())
+ {
+ rebuild_cube_render_node();
+ output->render->damage_whole();
+ }
+
update_view_matrix();
const bool running = animation.cube_animation.running();
if (render_node && (running || animation_was_running))
@@ -1289,7 +1322,7 @@
{
deactivate();
} else {
- if (fixed_workspace_view)
+ if (workspace_animation_anchor)
{
fixed_workspace_view = nullptr;
workspace_animation_anchor.reset();
@@ -1404,7 +1437,7 @@
(view == fixed_workspace_view))
{
fixed_workspace_view = nullptr;
- workspace_animation_anchor.reset();
+ // Losing the carried view does not cancel the workspace transition.
clear_post_move_window_dim();
clear_fixed_workspace_overlay(false);
rebuild_cube_render_node();
|