Merge lp:~alan-griffiths/miral/workspaces-example into lp:miral

Proposed by Alan Griffiths
Status: Merged
Approved by: Alan Griffiths
Approved revision: 531
Merged at revision: 516
Proposed branch: lp:~alan-griffiths/miral/workspaces-example
Merge into: lp:miral
Prerequisite: lp:~alan-griffiths/miral/workspace-examples-prerequisites
Diff against target: 338 lines (+212/-8)
4 files modified
miral-shell/decoration_provider.cpp (+3/-3)
miral-shell/titlebar_window_manager.cpp (+184/-3)
miral-shell/titlebar_window_manager.h (+24/-1)
miral/window_management_trace.cpp (+1/-1)
To merge this branch: bzr merge lp:~alan-griffiths/miral/workspaces-example
Reviewer Review Type Date Requested Status
Brandon Schaefer (community) Approve
Gerry Boland Pending
Alan Griffiths Pending
Review via email: mp+317630@code.launchpad.net

This proposal supersedes a proposal from 2017-02-17.

Commit message

[miral-shell] Example workspaces implementation

Description of the change

[miral-shell] Example workspaces implementation

Provides four workspaces:

  o Switch workspace . . . . . . . . . . : Meta-Alt-[F1|F2|F3|F4]
  o Switch workspace taking active window: Meta-Ctrl-[F1|F2|F3|F4]

~~~

Note: the "prerequisite" branch lp:~alan-griffiths/miral/workspace-examples-prerequisites only exists to workaround the launchpad limitation of a single prerequisite.

To post a comment you must log in.
Revision history for this message
Gerry Boland (gerboland) wrote : Posted in a previous version of this proposal

Looks quite ok. The old state save/restore and window_state_hidden updates are a bit repetitive, but more belong in the policy implementation, so is ok

review: Approve
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

The active window tracking gets confused here.

Start miral-app

Start an app from the command line (e.g. mir_demo_client_eglplasma)

Move that app to another workspace (e.g. Ctrl-Meta-F4)

Switch back to first workspace (Alt-Meta-F4)

Move the terminal too (e.g. Ctrl-Meta-F4)

Now
1. Both apps show a "focussed" toolbar
2. Alt-Tab doesn't switch between apps

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

If a window in a hidden sets the state from the client then it overrides the hidden state imposed by the workspace.

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> If a window in a hidden sets the state from the client then it overrides the
> hidden state imposed by the workspace.

Fixed

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> 1. Both apps show a "focussed" toolbar
> 2. Alt-Tab doesn't switch between apps

Fixed

review: Abstain
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote : Posted in a previous version of this proposal

An issues I can reproduce:
1) Open egl plasma demo
2) Open egl triangle demo
3) egl triangle should be on top
4) switch work spaces to 2, meta + alt + f2
5) switch back to work space 1, meta + alt + f1
6) (note that egl triangle is ontop still but no window appears to be focused, ie. toolbars are greyed out)
7) switch back to work space 2, meta + alt + f2
8) switch back to work space 1, meta + alt + f1

Expected:
  egl triangle to still be on top and focused

Result:
  egl triangle is below egl plasma and plasma has focus

You can test this by alt+tabbing to get triangle back on top.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> An issues I can reproduce:
> 1) Open egl plasma demo
> 2) Open egl triangle demo
> 3) egl triangle should be on top
> 4) switch work spaces to 2, meta + alt + f2
> 5) switch back to work space 1, meta + alt + f1
> 6) (note that egl triangle is ontop still but no window appears to be focused,
> ie. toolbars are greyed out)
> 7) switch back to work space 2, meta + alt + f2
> 8) switch back to work space 1, meta + alt + f1
>
> Expected:
> egl triangle to still be on top and focused
>
> Result:
> egl triangle is below egl plasma and plasma has focus
>
> You can test this by alt+tabbing to get triangle back on top.

Fixed

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote : Posted in a previous version of this proposal

Randomly seem to be getting garbage for window addresses:
[2017-02-17 07:26:25.497852] miral::Window Management: for_each_workspace_containing window=<80><81>^GÄX^?

522. By Alan Griffiths

Add workspace keys

523. By Alan Griffiths

merge lp:~alan-griffiths/miral/workspace-examples-prerequisites

524. By Alan Griffiths

Fix logging

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> Randomly seem to be getting garbage for window addresses:
> [2017-02-17 07:26:25.497852] miral::Window Management: for_each_workspace_containing window=<80><81>^GÄX^?

Fixed

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

1) Open egl plasma
2) Open egl triangle
3) Switch back and forth from f1 <---> f2 a few times with meta + alt
4) Switch to f1 with meta + alt, then using meta + ctrl moving the egl triangle to f2 then back to f1 with out letting go of the hot key
5) Switch to f2 using meta + alt

Expected:
  An emtpy workspace

Result:
  Egl triangle on this workspace, note if you switch to any other workspaces the egl triangle will still be there

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Ok easier way:

1) Open egl plasma and egl triangle
2) meta + ctrl + f2
3) meta + ctrl + f1
4) meta + alt + f2

Expected:
  An emtpy workspace

Result:
  App on all workspaces

525. By Alan Griffiths

Fix

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> Ok easier way:
>
> 1) Open egl plasma and egl triangle
> 2) meta + ctrl + f2
> 3) meta + ctrl + f1
> 4) meta + alt + f2
>
> Expected:
> An emtpy workspace
>
> Result:
> App on all workspaces

Fixed

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> > Ok easier way:
> >
> > 1) Open egl plasma and egl triangle
> > 2) meta + ctrl + f2
> > 3) meta + ctrl + f1
> > 4) meta + alt + f2
> >
> > Expected:
> > An emtpy workspace
> >
> > Result:
> > App on all workspaces
>
> Fixed

Well, mostly fixed. There are some related scenarios I'm still qualifying that are not quite there yet.

But possibly good enough?

526. By Alan Griffiths

Fix logging

527. By Alan Griffiths

Better solution

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

OK now?

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Yup, looking good to me!

review: Approve
528. By Alan Griffiths

Comments to clarify code I can't simplify

529. By Alan Griffiths

DRY - reduce repetitive workspace visible/hidden code

530. By Alan Griffiths

merge :parent

531. By Alan Griffiths

merge lp:~alan-griffiths/miral/workspace-examples-prerequisites

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'miral-shell/decoration_provider.cpp'
--- miral-shell/decoration_provider.cpp 2017-02-17 11:00:17 +0000
+++ miral-shell/decoration_provider.cpp 2017-02-20 17:31:27 +0000
@@ -169,9 +169,9 @@
169 " o Maximize/restore current window (to display size). : Alt-F11",169 " o Maximize/restore current window (to display size). : Alt-F11",
170 " o Maximize/restore current window (to display height): Shift-F11",170 " o Maximize/restore current window (to display height): Shift-F11",
171 " o Maximize/restore current window (to display width) : Ctrl-F11",171 " o Maximize/restore current window (to display width) : Ctrl-F11",
172// "",172 "",
173// " o Switch workspace: Meta-Alt-[F1|F2|F3|F4]",173 " o Switch workspace: Meta-Alt-[F1|F2|F3|F4]",
174// " o Switch workspace taking active window: Meta-Ctrl-[F1|F2|F3|F4]",174 " o Switch workspace taking active window: Meta-Ctrl-[F1|F2|F3|F4]",
175 "",175 "",
176 " o To exit: Ctrl-Alt-BkSp",176 " o To exit: Ctrl-Alt-BkSp",
177 };177 };
178178
=== modified file 'miral-shell/titlebar_window_manager.cpp'
--- miral-shell/titlebar_window_manager.cpp 2017-02-20 15:47:49 +0000
+++ miral-shell/titlebar_window_manager.cpp 2017-02-20 17:31:27 +0000
@@ -32,6 +32,18 @@
32namespace32namespace
33{33{
34int const title_bar_height = 12;34int const title_bar_height = 12;
35
36struct PolicyData
37{
38 bool in_hidden_workspace{false};
39
40 MirWindowState old_state;
41};
42
43inline PolicyData& policy_data_for(WindowInfo const& info)
44{
45 return *std::static_pointer_cast<PolicyData>(info.userdata());
46}
35}47}
3648
37TitlebarWindowManagerPolicy::TitlebarWindowManagerPolicy(49TitlebarWindowManagerPolicy::TitlebarWindowManagerPolicy(
@@ -43,6 +55,11 @@
43 decoration_provider{std::make_unique<DecorationProvider>(tools)}55 decoration_provider{std::make_unique<DecorationProvider>(tools)}
44{56{
45 launcher.launch("decorations", *decoration_provider);57 launcher.launch("decorations", *decoration_provider);
58
59 for (auto key : {KEY_F1, KEY_F2, KEY_F3, KEY_F4})
60 key_to_workspace[key] = this->tools.create_workspace();
61
62 active_workspace = key_to_workspace[KEY_F1];
46}63}
4764
48TitlebarWindowManagerPolicy::~TitlebarWindowManagerPolicy() = default;65TitlebarWindowManagerPolicy::~TitlebarWindowManagerPolicy() = default;
@@ -266,17 +283,25 @@
266{283{
267 CanonicalWindowManagerPolicy::advise_new_window(window_info);284 CanonicalWindowManagerPolicy::advise_new_window(window_info);
268285
286 auto const parent = window_info.parent();
287
269 if (decoration_provider->is_titlebar(window_info))288 if (decoration_provider->is_titlebar(window_info))
270 {289 {
271 decoration_provider->advise_new_titlebar(window_info);290 decoration_provider->advise_new_titlebar(window_info);
272291
273 auto const parent = window_info.parent();
274
275 if (tools.active_window() == parent)292 if (tools.active_window() == parent)
276 decoration_provider->paint_titlebar_for(tools.info_for(parent), 0xFF);293 decoration_provider->paint_titlebar_for(tools.info_for(parent), 0xFF);
277 else294 else
278 decoration_provider->paint_titlebar_for(tools.info_for(parent), 0x3F);295 decoration_provider->paint_titlebar_for(tools.info_for(parent), 0x3F);
279 }296 }
297
298 if (!parent)
299 tools.add_tree_to_workspace(window_info.window(), active_workspace);
300 else
301 {
302 if (policy_data_for(tools.info_for(parent)).in_hidden_workspace)
303 apply_workspace_hidden_to(window_info.window());
304 }
280}305}
281306
282void TitlebarWindowManagerPolicy::handle_window_ready(WindowInfo& window_info)307void TitlebarWindowManagerPolicy::handle_window_ready(WindowInfo& window_info)
@@ -337,6 +362,36 @@
337 auto const scan_code = mir_keyboard_event_scan_code(event);362 auto const scan_code = mir_keyboard_event_scan_code(event);
338 auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask;363 auto const modifiers = mir_keyboard_event_modifiers(event) & modifier_mask;
339364
365 // Switch workspaces
366 if (action == mir_keyboard_action_down &&
367 modifiers == (mir_input_event_modifier_alt | mir_input_event_modifier_meta))
368 {
369 switch (scan_code)
370 {
371 case KEY_F1:
372 case KEY_F2:
373 case KEY_F3:
374 case KEY_F4:
375 switch_workspace_to(key_to_workspace[scan_code]);
376 return true;
377 }
378 }
379
380 // Switch workspace taking the active window
381 if (action == mir_keyboard_action_down &&
382 modifiers == (mir_input_event_modifier_ctrl | mir_input_event_modifier_meta))
383 {
384 switch (scan_code)
385 {
386 case KEY_F1:
387 case KEY_F2:
388 case KEY_F3:
389 case KEY_F4:
390 switch_workspace_to(key_to_workspace[scan_code], tools.active_window());
391 return true;
392 }
393 }
394
340 if (action != mir_keyboard_action_repeat)395 if (action != mir_keyboard_action_repeat)
341 end_resize();396 end_resize();
342397
@@ -362,7 +417,7 @@
362 }417 }
363 else if (action == mir_keyboard_action_down && scan_code == KEY_F4)418 else if (action == mir_keyboard_action_down && scan_code == KEY_F4)
364 {419 {
365 switch (modifiers & modifier_mask)420 switch (modifiers)
366 {421 {
367 case mir_input_event_modifier_alt|mir_input_event_modifier_shift:422 case mir_input_event_modifier_alt|mir_input_event_modifier_shift:
368 if (auto const& window = tools.active_window())423 if (auto const& window = tools.active_window())
@@ -569,5 +624,131 @@
569 if (app_info.application() == decoration_provider->session())624 if (app_info.application() == decoration_provider->session())
570 decoration_provider->place_new_decoration(parameters);625 decoration_provider->place_new_decoration(parameters);
571626
627 parameters.userdata() = std::make_shared<PolicyData>();
572 return parameters;628 return parameters;
573}629}
630
631void TitlebarWindowManagerPolicy::advise_adding_to_workspace(
632 std::shared_ptr<Workspace> const& workspace, std::vector<Window> const& windows)
633{
634 if (windows.empty())
635 return;
636
637 for (auto const& window : windows)
638 {
639 if (workspace == active_workspace)
640 {
641 apply_workspace_visible_to(window);
642 }
643 else
644 {
645 apply_workspace_hidden_to(window);
646 }
647 }
648}
649
650void TitlebarWindowManagerPolicy::switch_workspace_to(
651 std::shared_ptr<Workspace> const& workspace,
652 Window const& window)
653{
654 if (workspace == active_workspace)
655 return;
656
657 auto const old_active = active_workspace;
658 active_workspace = workspace;
659
660 auto const old_active_window = tools.active_window();
661
662 if (!old_active_window)
663 {
664 // If there's no active window, the first shown grabs focus: get the right one
665 if (auto const ww = workspace_to_active[workspace])
666 {
667 tools.for_each_workspace_containing(ww, [&](std::shared_ptr<miral::Workspace> const& ws)
668 {
669 if (ws == workspace)
670 {
671 apply_workspace_visible_to(ww);
672 }
673 });
674 }
675 }
676
677 tools.remove_tree_from_workspace(window, old_active);
678 tools.add_tree_to_workspace(window, active_workspace);
679
680 tools.for_each_window_in_workspace(active_workspace, [&](Window const& window)
681 {
682 if (decoration_provider->is_decoration(window))
683 return; // decorations are taken care of automatically
684
685 apply_workspace_visible_to(window);
686 });
687
688 bool hide_old_active = false;
689 tools.for_each_window_in_workspace(old_active, [&](Window const& window)
690 {
691 if (decoration_provider->is_decoration(window))
692 return; // decorations are taken care of automatically
693
694 if (window == old_active_window)
695 {
696 // If we hide the active window focus will shift: do that last
697 hide_old_active = true;
698 return;
699 }
700
701 apply_workspace_hidden_to(window);
702 });
703
704 if (hide_old_active)
705 {
706 apply_workspace_hidden_to(old_active_window);
707
708 // Remember the old active_window when we switch away
709 workspace_to_active[old_active] = old_active_window;
710 }
711}
712
713void TitlebarWindowManagerPolicy::apply_workspace_hidden_to(Window const& window)
714{
715 auto const& window_info = tools.info_for(window);
716 auto& pdata = policy_data_for(window_info);
717 if (!pdata.in_hidden_workspace)
718 {
719 pdata.in_hidden_workspace = true;
720 pdata.old_state = window_info.state();
721
722 WindowSpecification modifications;
723 modifications.state() = mir_window_state_hidden;
724 tools.place_and_size_for_state(modifications, window_info);
725 tools.modify_window(window_info.window(), modifications);
726 }
727}
728
729void TitlebarWindowManagerPolicy::apply_workspace_visible_to(Window const& window)
730{
731 auto const& window_info = tools.info_for(window);
732 auto& pdata = policy_data_for(window_info);
733 if (pdata.in_hidden_workspace)
734 {
735 pdata.in_hidden_workspace = false;
736 WindowSpecification modifications;
737 modifications.state() = pdata.old_state;
738 tools.place_and_size_for_state(modifications, window_info);
739 tools.modify_window(window_info.window(), modifications);
740 }
741}
742
743void TitlebarWindowManagerPolicy::handle_modify_window(WindowInfo& window_info, WindowSpecification const& modifications)
744{
745 auto mods = modifications;
746
747 auto& pdata = policy_data_for(window_info);
748
749 if (pdata.in_hidden_workspace && mods.state().is_set())
750 pdata.old_state = mods.state().consume();
751
752 CanonicalWindowManagerPolicy::handle_modify_window(window_info, mods);
753}
754
574755
=== modified file 'miral-shell/titlebar_window_manager.h'
--- miral-shell/titlebar_window_manager.h 2017-02-20 15:47:49 +0000
+++ miral-shell/titlebar_window_manager.h 2017-02-20 17:31:27 +0000
@@ -20,10 +20,12 @@
20#define MIRAL_SHELL_TITLEBAR_WINDOW_MANAGER_H20#define MIRAL_SHELL_TITLEBAR_WINDOW_MANAGER_H
2121
22#include <miral/canonical_window_manager.h>22#include <miral/canonical_window_manager.h>
23#include <miral/workspace_policy.h>
2324
24#include "spinner/splash.h"25#include "spinner/splash.h"
2526
26#include <chrono>27#include <chrono>
28#include <map>
2729
28namespace miral { class InternalClientLauncher; }30namespace miral { class InternalClientLauncher; }
2931
@@ -31,7 +33,7 @@
3133
32class DecorationProvider;34class DecorationProvider;
3335
34class TitlebarWindowManagerPolicy : public miral::CanonicalWindowManagerPolicy36class TitlebarWindowManagerPolicy : public miral::CanonicalWindowManagerPolicy, miral::WorkspacePolicy
35{37{
36public:38public:
37 TitlebarWindowManagerPolicy(miral::WindowManagerTools const& tools, SpinnerSplash const& spinner, miral::InternalClientLauncher const& launcher);39 TitlebarWindowManagerPolicy(miral::WindowManagerTools const& tools, SpinnerSplash const& spinner, miral::InternalClientLauncher const& launcher);
@@ -48,6 +50,8 @@
48 * o Maximize/restore current window (to display size): Alt-F1150 * o Maximize/restore current window (to display size): Alt-F11
49 * o Maximize/restore current window (to display height): Shift-F1151 * o Maximize/restore current window (to display height): Shift-F11
50 * o Maximize/restore current window (to display width): Ctrl-F1152 * o Maximize/restore current window (to display width): Ctrl-F11
53 * o Switch workspace . . . . . . . . . . : Meta-Alt-[F1|F2|F3|F4]
54 * o Switch workspace taking active window: Meta-Ctrl-[F1|F2|F3|F4]
51 * @{ */55 * @{ */
52 bool handle_pointer_event(MirPointerEvent const* event) override;56 bool handle_pointer_event(MirPointerEvent const* event) override;
53 bool handle_touch_event(MirTouchEvent const* event) override;57 bool handle_touch_event(MirTouchEvent const* event) override;
@@ -63,6 +67,8 @@
63 void advise_state_change(miral::WindowInfo const& window_info, MirWindowState state) override;67 void advise_state_change(miral::WindowInfo const& window_info, MirWindowState state) override;
64 void advise_resize(miral::WindowInfo const& window_info, Size const& new_size) override;68 void advise_resize(miral::WindowInfo const& window_info, Size const& new_size) override;
65 void advise_delete_window(miral::WindowInfo const& window_info) override;69 void advise_delete_window(miral::WindowInfo const& window_info) override;
70
71 void handle_modify_window(miral::WindowInfo& window_info, miral::WindowSpecification const& modifications) override;
66 /** @} */72 /** @} */
6773
68protected:74protected:
@@ -104,6 +110,23 @@
104110
105 // Workaround for lp:1627697111 // Workaround for lp:1627697
106 std::chrono::steady_clock::time_point last_resize;112 std::chrono::steady_clock::time_point last_resize;
113
114 void advise_adding_to_workspace(
115 std::shared_ptr<miral::Workspace> const& workspace,
116 std::vector<miral::Window> const& windows) override;
117
118 // Switch workspace, taking window (if not null)
119 void switch_workspace_to(
120 std::shared_ptr<miral::Workspace> const& workspace,
121 miral::Window const& window = miral::Window{});
122
123 std::shared_ptr<miral::Workspace> active_workspace;
124 std::map<int, std::shared_ptr<miral::Workspace>> key_to_workspace;
125 std::map<std::shared_ptr<miral::Workspace>, miral::Window> workspace_to_active;
126
127 void apply_workspace_visible_to(miral::Window const& window);
128
129 void apply_workspace_hidden_to(miral::Window const& window);
107};130};
108131
109#endif //MIRAL_SHELL_TITLEBAR_WINDOW_MANAGER_H132#endif //MIRAL_SHELL_TITLEBAR_WINDOW_MANAGER_H
110133
=== modified file 'miral/window_management_trace.cpp'
--- miral/window_management_trace.cpp 2017-02-10 15:22:37 +0000
+++ miral/window_management_trace.cpp 2017-02-20 17:31:27 +0000
@@ -558,7 +558,7 @@
558void miral::WindowManagementTrace::for_each_workspace_containing(558void miral::WindowManagementTrace::for_each_workspace_containing(
559 miral::Window const& window, std::function<void(std::shared_ptr<miral::Workspace> const&)> const& callback)559 miral::Window const& window, std::function<void(std::shared_ptr<miral::Workspace> const&)> const& callback)
560try {560try {
561 mir::log_info("%s window=%s", __func__, dump_of(window));561 mir::log_info("%s window=%s", __func__, dump_of(window).c_str());
562 wrapped.for_each_workspace_containing(window, callback);562 wrapped.for_each_workspace_containing(window, callback);
563}563}
564MIRAL_TRACE_EXCEPTION564MIRAL_TRACE_EXCEPTION

Subscribers

People subscribed via source and target branches