Merge lp:~alan-griffiths/miral/improved-tiling-wm into lp:miral

Proposed by Alan Griffiths on 2016-11-09
Status: Merged
Approved by: Gerry Boland on 2016-11-10
Approved revision: no longer in the source branch.
Merged at revision: 441
Proposed branch: lp:~alan-griffiths/miral/improved-tiling-wm
Merge into: lp:miral
Diff against target: 259 lines (+118/-41)
3 files modified
miral-shell/tiling_window_manager.cpp (+96/-25)
miral-shell/tiling_window_manager.h (+22/-0)
tasks_for_the_interested_reader.md (+0/-16)
To merge this branch: bzr merge lp:~alan-griffiths/miral/improved-tiling-wm
Reviewer Review Type Date Requested Status
Gerry Boland 2016-11-09 Approve on 2016-11-10
Review via email: mp+310421@code.launchpad.net

Commit Message

[miral-shell --window-manager tiling] implement the layout suggested in "Tasks for the interested reader"

To post a comment you must log in.
Gerry Boland (gerboland) wrote :

Works as suggested

review: Approve
441. By Alan Griffiths on 2016-11-10

[miral-shell --window-manager tiling] implement the layout suggested in "Tasks for the interested reader"

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'miral-shell/tiling_window_manager.cpp'
2--- miral-shell/tiling_window_manager.cpp 2016-10-10 10:43:42 +0000
3+++ miral-shell/tiling_window_manager.cpp 2016-11-09 12:42:38 +0000
4@@ -35,17 +35,37 @@
5 struct TilingWindowManagerPolicyData
6 {
7 Rectangle tile;
8+ Rectangle old_tile;
9 };
10
11-inline Rectangle& tile_for(miral::ApplicationInfo& app_info)
12-{
13- return std::static_pointer_cast<TilingWindowManagerPolicyData>(app_info.userdata())->tile;
14-}
15-
16-inline Rectangle const& tile_for(miral::ApplicationInfo const& app_info)
17-{
18- return std::static_pointer_cast<TilingWindowManagerPolicyData>(app_info.userdata())->tile;
19-}
20+template<class Info>
21+inline Rectangle& tile_for(Info& info)
22+{
23+ return std::static_pointer_cast<TilingWindowManagerPolicyData>(info.userdata())->tile;
24+}
25+
26+template<class Info>
27+inline Rectangle const& tile_for(Info const& info)
28+{
29+ return std::static_pointer_cast<TilingWindowManagerPolicyData>(info.userdata())->tile;
30+}
31+}
32+
33+void TilingWindowManagerPolicy::MRUTileList::push(std::shared_ptr<void> const& tile)
34+{
35+ tiles.erase(remove(begin(tiles), end(tiles), tile), end(tiles));
36+ tiles.push_back(tile);
37+}
38+
39+void TilingWindowManagerPolicy::MRUTileList::erase(std::shared_ptr<void> const& tile)
40+{
41+ tiles.erase(remove(begin(tiles), end(tiles), tile), end(tiles));
42+}
43+
44+void TilingWindowManagerPolicy::MRUTileList::enumerate(Enumerator const& enumerator) const
45+{
46+ for (auto i = tiles.rbegin(); i != tiles.rend(); ++i)
47+ enumerator(const_cast<std::shared_ptr<void> const&>(*i));
48 }
49
50 // Demonstrate implementing a simple tiling algorithm
51@@ -95,6 +115,7 @@
52 {
53 auto parameters = request_parameters;
54
55+ parameters.userdata() = app_info.userdata();
56 parameters.state() = parameters.state().is_set() ?
57 transform_set_state(parameters.state().value()) : mir_surface_state_restored;
58
59@@ -126,13 +147,29 @@
60
61 void TilingWindowManagerPolicy::advise_new_window(WindowInfo const& window_info)
62 {
63- if (spinner.session() == window_info.window().application())
64- dirty_tiles = true;
65+ if (window_info.type() == mir_surface_type_normal &&
66+ !window_info.parent() &&
67+ window_info.state() == mir_surface_state_restored)
68+ {
69+ WindowSpecification specification;
70+
71+ specification.state() = mir_surface_state_maximized;
72+
73+ tools.place_and_size_for_state(specification, window_info);
74+ constrain_size_and_place(specification, window_info.window(), tile_for(window_info));
75+ tools.modify_window(window_info.window(), specification);
76+ }
77 }
78
79 void TilingWindowManagerPolicy::handle_window_ready(WindowInfo& window_info)
80 {
81 tools.select_active_window(window_info.window());
82+
83+ if (spinner.session() != window_info.window().application())
84+ {
85+ tiles.push(window_info.userdata());
86+ dirty_tiles = true;
87+ }
88 }
89
90 namespace
91@@ -149,7 +186,7 @@
92 miral::WindowSpecification const& modifications)
93 {
94 auto const window = window_info.window();
95- auto const tile = tile_for(tools.info_for(window.application()));
96+ auto const tile = tile_for(window_info);
97 auto mods = modifications;
98
99 constrain_size_and_place(mods, window, tile);
100@@ -426,24 +463,51 @@
101
102 auto index = 0;
103
104+ if (applications < 3)
105+ {
106+ tiles.enumerate([&](std::shared_ptr<void> const& userdata)
107+ {
108+ auto const tile_data = std::static_pointer_cast<TilingWindowManagerPolicyData>(userdata);
109+ tile_data->old_tile = tile_data->tile;
110+
111+ auto const x = (total_width * index) / applications;
112+ ++index;
113+ auto const dx = (total_width * index) / applications - x;
114+
115+ tile_data->tile = Rectangle{{x, 0}, {dx, total_height}};
116+ });
117+ }
118+ else
119+ {
120+ tiles.enumerate([&](std::shared_ptr<void> const& userdata)
121+ {
122+ auto const tile_data = std::static_pointer_cast<TilingWindowManagerPolicyData>(userdata);
123+ tile_data->old_tile = tile_data->tile;
124+
125+ auto const dx = total_width/2;
126+ if (!index)
127+ {
128+ tile_data->tile = Rectangle{{0, 0}, {dx, total_height}};
129+ }
130+ else
131+ {
132+ auto const x = dx;
133+ auto const y = total_height*(index-1) / (applications-1);
134+ auto const dy = total_height / (applications-1);
135+ tile_data->tile = Rectangle{{x, y}, {dx, dy}};
136+ }
137+
138+ ++index;
139+ });
140+ }
141+
142 tools.for_each_application([&](ApplicationInfo& info)
143 {
144 if (spinner.session() == info.application())
145 return;
146
147- auto& tile = tile_for(info);
148-
149- auto const x = (total_width * index) / applications;
150- ++index;
151- auto const dx = (total_width * index) / applications - x;
152-
153- auto const old_tile = tile;
154- Rectangle const new_tile{{x, 0},
155- {dx, total_height}};
156-
157- update_surfaces(info, old_tile, new_tile);
158-
159- tile = new_tile;
160+ auto const tile_data = std::static_pointer_cast<TilingWindowManagerPolicyData>(info.userdata());
161+ update_surfaces(info, tile_data->old_tile, tile_data->tile);
162 });
163 }
164
165@@ -524,6 +588,11 @@
166 if (spinner_info.windows().size() > 0)
167 tools.raise_tree(spinner_info.windows()[0]);
168 }
169+ else
170+ {
171+ tiles.push(info.userdata());
172+ dirty_tiles = true;
173+ }
174 }
175
176 void TilingWindowManagerPolicy::advise_new_app(miral::ApplicationInfo& application)
177@@ -532,6 +601,7 @@
178 return;
179
180 application.userdata(std::make_shared<TilingWindowManagerPolicyData>());
181+ tiles.push(application.userdata());
182 dirty_tiles = true;
183 }
184
185@@ -540,6 +610,7 @@
186 if (spinner.session() == application.application())
187 return;
188
189+ tiles.erase(application.userdata());
190 dirty_tiles = true;
191 }
192 void TilingWindowManagerPolicy::advise_end()
193
194=== modified file 'miral-shell/tiling_window_manager.h'
195--- miral-shell/tiling_window_manager.h 2016-10-10 10:43:42 +0000
196+++ miral-shell/tiling_window_manager.h 2016-11-09 12:42:38 +0000
197@@ -29,6 +29,10 @@
198 #include <mir/geometry/displacement.h>
199 #include <miral/internal_client.h>
200
201+
202+#include <functional>
203+#include <vector>
204+
205 using namespace mir::geometry;
206
207 // Demonstrate implementing a simple tiling algorithm
208@@ -107,6 +111,24 @@
209 Rectangles displays;
210 bool dirty_tiles = false;
211
212+ class MRUTileList
213+ {
214+ public:
215+
216+ void push(std::shared_ptr<void> const& tile);
217+ void erase(std::shared_ptr<void> const& tile);
218+ auto top() const -> std::shared_ptr<void> const&;
219+
220+ using Enumerator = std::function<void(std::shared_ptr<void> const& tile)>;
221+
222+ void enumerate(Enumerator const& enumerator) const;
223+
224+ private:
225+ std::vector<std::shared_ptr<void>> tiles;
226+ };
227+
228+ MRUTileList tiles;
229+
230 // These two variables are used by the advise_display methods which are
231 // NOT guarded by the usual WM mutex
232 bool dirty_displays = false;
233
234=== modified file 'tasks_for_the_interested_reader.md'
235--- tasks_for_the_interested_reader.md 2016-10-20 20:47:13 +0000
236+++ tasks_for_the_interested_reader.md 2016-11-09 12:42:38 +0000
237@@ -79,22 +79,6 @@
238 possible, without much consideration of being useful. Here are some suggestions
239 for a better approach:
240
241- - top level windows ought to fill the tile when created
242-
243- - the tiling algorithm ought to lay windows out as follows:
244-
245- - Single window: takes up the whole screen
246-
247- - Two windows: The screen is split in two tiles of equal width (half the
248- screen’s width) and full height. Each window is placed in a tile (left
249- or right), with the newest window occupying the left tile.
250-
251- - Three or more windows: The screen is split in two tiles of equal width
252- and full height, as in the previous case. The newest window occupies
253- the left tile. The right part is now further divided vertically into
254- smaller tiles having equal height, to host the remaining windows, with
255- older windows being closer to the bottom.
256-
257 - Add a titlebar to the top of the screen. The titlebar should be split evenly
258 into horizontal blocks, one per tile. Each block containing the title of the
259 top-level window. The focussed tile is highlighted. Clicking on a title

Subscribers

People subscribed via source and target branches