-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add APIs to override decoration managers and customize decorations #3604
Conversation
4072e84
to
8ec208b
Compare
4e519ba
to
21e5c3e
Compare
a8c7835
to
a23ecff
Compare
protected: | ||
std::unordered_map<scene::Surface*, std::unique_ptr<Decoration>> decorations; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not enthusiastic about making member data public (protected
is public in disguise).
In this case the only use is in tests, which manipulate decorations
directly. That seems fragile and suggests there's an abstraction missing.
I'll try to come up with a concrete suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks mostly sensible, but I'd like to see an example using this API. Can we add something to miral-shell?
Sure thing. Anything quick in mind? The first thing that comes to mind for me is a variant of |
That sounds bizarre. How about "light mode"? |
Hmm, that should do too. But first things first, let's make |
Here's your first problem then: |
Ok, should be easy to fix. I propose |
I think that's for APIs supported by mircommon |
What about |
|
I went around and implemented "light mode" in the laziest/easiest way possible (i.e. just paramterizing PS: At some point when I was hooking up |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are trying to provide a way for users to customise decorations themselves.
Instead, miral::LigtMode
provides an option to select a customisation we wrote, not the capability to write it as a user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs cleaning up:
- Examples the user can adapt (
UserDecorationManagerExample
et alia) do not belong in themiral
namespace nor library. - The example files
user_decoration_example/...
belong inexamples
notinclude/miral
andsrc/miral
- The example code should be used in an example shell
- There is no need for
miral::decoration::LightMode
, nor for the changes introduced to support it.
|
Remove `msd::Decoration::redraw`. Since it's only really an internal implementation detail, it's up to the decoration author to do it in whichever way they see fit. `BasicDecoration` can be used as a template/example. Remove `WindowSurfaceObserverManager`, move its observer to `Decoration` Fix `DecorationBasicManager` tests (again...) Move `msd::Decoration` notification logic to `msd::DecorationNotifier`
Inititalizing the decoration manager in the pre_init callbacks caused extra windows to be opened due to `the_display` being called (which creates "Mir on X" windows) during the decoration manager creation, but not cached, which causes later calls during initialization to launch extra windows.
58c44e0
to
977ef38
Compare
This comment was marked as resolved.
This comment was marked as resolved.
auto init_button_drawing_functions(msd::ButtonTheme button_icons) | ||
{ | ||
using namespace msd; | ||
|
||
std::map<ButtonFunction, std::pair<msd::Icon const, msd::Icon::DrawingFunction const>> buttons; | ||
|
||
for(auto const& [button_function, icon]: button_icons) | ||
{ | ||
// A little lookup table, more legible than a switch case? | ||
static auto const drawing_functions = std::map<ButtonFunction, msd::Icon::DrawingFunction>{ | ||
{ButtonFunction::Close, render_close_icon}, | ||
{ButtonFunction::Maximize, render_maximize_icon}, | ||
{ButtonFunction::Minimize, render_minimize_icon}, | ||
}; | ||
|
||
buttons.emplace(button_function, std::make_pair(icon, drawing_functions.at(button_function))); | ||
} | ||
|
||
return buttons; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see no reason to have the icon, button function, and icon drawing function split. A list of tuples should do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This (46ec605) and its friends should probably be split into their own commit
Update mirserver symbols Bump mirserver symbol stanza to 2.19 since we're breaking ABI Fix header ordering in `decoration_notifier.h` Move `BasicDecoration::redraw` to be private. Wrap the contents of `Decoration::set_scale` with `ThreadSafeAccess::spawn`
`src/include/server/mir/decoration`
These are meant to isolate miral client code from unstable/internal mir code so that we can change stuff without breaking client code. Move `decoration_wrapper` (now `decoration_notifier`) to `DecorationAdapter` Additionally, expose `window_surface` and `decoration_surface` through getters to pass them to the adapter. Co-authored-by: Alan Griffiths <[email protected]>
Move custom decorations to their own examples. Remove custom decoration code from the `miral::decoration` namespace Make `UserDecorationExample` light by default to help differentiate it from Mir's built-in decorations.
`src/server/shell/decoration`
Added `InputResolverAdapter` to expose a more stable(?) interface. It allows users to point to their implementation of `process_{enter,leave,up,down,motion, drag}`. Remove ununsed `DeviceEvent&` parameter from `process_{leave,up,down}`.
977ef38
to
d96e5f9
Compare
#include <mir/graphics/display_configuration.h> | ||
#include <mir/graphics/null_display_configuration_observer.h> | ||
/* #include <bffoost/throw_exception.hpp> */ | ||
#include "mirserver-internal/mir/observer_registrar.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this okay, or should observer_registrar.h
be exposed / I should access it some other way?
5f6a0ff
to
9548497
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This iteration of the API is leaking implementation details
#ifndef MIRAL_DECORATION_DECORATION_ADAPTER_H | ||
#define MIRAL_DECORATION_DECORATION_ADAPTER_H | ||
|
||
#include "mir/shell/decoration_notifier.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be used by a public libmiral header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, like, create a miral::*
version of the class, with the header file completely isolating the internal symbols from the user, and the source file using/including the header?
Does this also apply to similar cases in this review? (input_resolver.h
, adapters, etc...)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it should just be internal and unavailable to the shell author
#include <memory> | ||
|
||
|
||
namespace miral::decoration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I doubt we need a nested decoration
namespace
#ifndef MIRAL_DECORATION_DECORATION_INPUT_MANAGER_ADAPTER_H | ||
#define MIRAL_DECORATION_DECORATION_INPUT_MANAGER_ADAPTER_H | ||
|
||
#include "mir/shell/input_resolver.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be used by a public libmiral header.
namespace miral::decoration | ||
{ | ||
class InputResolverBuilder; | ||
class InputResolverAdapter : public mir::shell::decoration::InputResolver | ||
{ | ||
protected: | ||
void process_enter(DeviceEvent& device) override; | ||
void process_leave() override; | ||
void process_down() override; | ||
void process_up() override; | ||
void process_move(DeviceEvent& device) override; | ||
void process_drag(DeviceEvent& device) override; | ||
|
||
private: | ||
friend InputResolverBuilder; | ||
InputResolverAdapter(); | ||
|
||
std::function<void(DeviceEvent& device)> on_process_enter; | ||
std::function<void()> on_process_leave; | ||
std::function<void()> on_process_down; | ||
std::function<void()> on_process_up; | ||
std::function<void(DeviceEvent& device)> on_process_move; | ||
std::function<void(DeviceEvent& device)> on_process_drag; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Builder exists because this class doesn't belong in a public header. Users of libmiral should be isolated from such details.
class DecorationAdapter : public mir::shell::decoration::Decoration | ||
{ | ||
public: | ||
|
||
void handle_input_event(std::shared_ptr<MirEvent const> const& /*event*/) final override; | ||
void set_scale(float new_scale) final override; | ||
void attrib_changed(mir::scene::Surface const* window_surface, MirWindowAttrib attrib, int value) final override; | ||
void window_resized_to( | ||
mir::scene::Surface const* window_surface, mir::geometry::Size const& window_size) final override; | ||
void window_renamed(mir::scene::Surface const* window_surface, std::string const& name) final override; | ||
|
||
private: | ||
friend DecorationBuilder; | ||
DecorationAdapter( | ||
std::shared_ptr<mir::scene::Surface> decoration_surface, std::shared_ptr<mir::scene::Surface> window_surface); | ||
|
||
std::function<void(std::shared_ptr<MirEvent const> const&)> on_handle_input_event; | ||
std::function<void(float new_scale)> on_set_scale; | ||
std::function<void(mir::scene::Surface const* window_surface, MirWindowAttrib attrib, int value)> on_attrib_changed; | ||
std::function<void(mir::scene::Surface const* window_surface, mir::geometry::Size const& window_size)> | ||
on_window_resized_to; | ||
std::function<void(mir::scene::Surface const* window_surface, std::string const& name)> on_window_renamed; | ||
|
||
mir::shell::decoration::DecorationNotifier decoration_notifier; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Builder exists because this class doesn't belong in a public header. Users of libmiral should be isolated from such details.
class DecorationManagerAdapter : public mir::shell::decoration::Manager | ||
{ | ||
public: | ||
void init(std::weak_ptr<mir::shell::Shell> const& shell) override; | ||
void decorate(std::shared_ptr<mir::scene::Surface> const& surface) override; | ||
void undecorate(std::shared_ptr<mir::scene::Surface> const& surface) override; | ||
void undecorate_all() override; | ||
|
||
private: | ||
friend DecorationManagerBuilder; | ||
DecorationManagerAdapter(); | ||
|
||
std::function<void(std::weak_ptr<mir::shell::Shell> const& shell)> on_init; | ||
std::function<void(std::shared_ptr<mir::scene::Surface> const& surface)> on_decorate; | ||
std::function<void(std::shared_ptr<mir::scene::Surface> const& surface)> on_undecorate; | ||
std::function<void()> on_undecorate_all; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Builder exists because this class doesn't belong in a public header. Users of libmiral should be isolated from such details.
@@ -5,5 +5,6 @@ add_subdirectory(miral-kiosk) | |||
add_subdirectory(miral-system-compositor) | |||
add_subdirectory(mir_demo_server) | |||
add_subdirectory(mir-x11-kiosk) | |||
add_subdirectory(miral-custom-decorations) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think custom decorations need their own example. Adding them as a miral-shell option would be fine
|
||
|
||
#include "mir/server.h" | ||
#include "mir/main_loop.h" // Needed for the conversion of `the_main_loop` to an executor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is needed, then something is wrong with the proposed API
|
||
void operator()(mir::Server& s) const | ||
{ | ||
s.add_pre_init_callback( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
User code should not be accessing the Server in this way (it isn't a public header)
/* [&external_client_launcher](mir::Server& s) */ | ||
/* { */ | ||
/* s.add_init_callback( */ | ||
/* [&external_client_launcher] */ | ||
/* { */ | ||
/* external_client_launcher.launch("xeyes"); */ | ||
/* }); */ | ||
/* }, */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/* [&external_client_launcher](mir::Server& s) */ | |
/* { */ | |
/* s.add_init_callback( */ | |
/* [&external_client_launcher] */ | |
/* { */ | |
/* external_client_launcher.launch("xeyes"); */ | |
/* }); */ | |
/* }, */ |
|
Worked on my machine™
9548497
to
38b971a
Compare
${PROJECT_SOURCE_DIR}/src/include/server | ||
${PROJECT_SOURCE_DIR}/include/platform | ||
${PROJECT_SOURCE_DIR}/include/wayland |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example code should not depend on any of these include paths
No description provided.