-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Wayland server side decorations (#3425)
Closes #3371
- Loading branch information
Showing
9 changed files
with
432 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
198 changes: 198 additions & 0 deletions
198
src/server/frontend_wayland/xdg_decoration_unstable_v1.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
/* | ||
* Copyright © Canonical Ltd. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 or 3 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include "xdg_decoration_unstable_v1.h" | ||
|
||
#include "mir/log.h" | ||
#include "mir/shell/surface_specification.h" | ||
#include "mir/wayland/client.h" | ||
#include "mir/wayland/protocol_error.h" | ||
|
||
#include "xdg-decoration-unstable-v1_wrapper.h" | ||
#include "xdg_output_v1.h" | ||
#include "xdg_shell_stable.h" | ||
|
||
#include <memory> | ||
#include <unordered_set> | ||
|
||
namespace mir | ||
{ | ||
namespace frontend | ||
{ | ||
class ToplevelsWithDecorations | ||
{ | ||
public: | ||
ToplevelsWithDecorations() = default; | ||
ToplevelsWithDecorations(ToplevelsWithDecorations const&) = delete; | ||
ToplevelsWithDecorations& operator=(ToplevelsWithDecorations const&) = delete; | ||
|
||
/// \return true if no duplicates existed before insertion, false otherwise. | ||
bool register_toplevel(wl_resource* toplevel) | ||
{ | ||
auto [_, inserted] = toplevels_with_decorations.insert(toplevel); | ||
return inserted; | ||
} | ||
|
||
/// \return true if the toplevel was still registered, false otherwise. | ||
bool unregister_toplevel(wl_resource* toplevel) | ||
{ | ||
return toplevels_with_decorations.erase(toplevel) > 0; | ||
} | ||
|
||
private: | ||
std::unordered_set<wl_resource*> toplevels_with_decorations; | ||
}; | ||
|
||
class XdgDecorationManagerV1 : public wayland::XdgDecorationManagerV1 | ||
{ | ||
public: | ||
XdgDecorationManagerV1(wl_resource* resource); | ||
|
||
class Global : public wayland::XdgDecorationManagerV1::Global | ||
{ | ||
public: | ||
Global(wl_display* display); | ||
|
||
private: | ||
void bind(wl_resource* new_zxdg_decoration_manager_v1) override; | ||
}; | ||
|
||
private: | ||
void get_toplevel_decoration(wl_resource* id, wl_resource* toplevel) override; | ||
std::shared_ptr<ToplevelsWithDecorations> const toplevels_with_decorations; | ||
}; | ||
|
||
class XdgToplevelDecorationV1 : public wayland::XdgToplevelDecorationV1 | ||
{ | ||
public: | ||
XdgToplevelDecorationV1(wl_resource* id, mir::frontend::XdgToplevelStable* toplevel); | ||
|
||
void set_mode(uint32_t mode) override; | ||
void unset_mode() override; | ||
|
||
private: | ||
void update_mode(uint32_t new_mode); | ||
|
||
static uint32_t const default_mode = Mode::client_side; | ||
|
||
mir::frontend::XdgToplevelStable* toplevel; | ||
uint32_t mode; | ||
}; | ||
} // namespace frontend | ||
} // namespace mir | ||
|
||
auto mir::frontend::create_xdg_decoration_unstable_v1(wl_display* display) | ||
-> std::shared_ptr<mir::wayland::XdgDecorationManagerV1::Global> | ||
{ | ||
return std::make_shared<XdgDecorationManagerV1::Global>(display); | ||
} | ||
|
||
mir::frontend::XdgDecorationManagerV1::Global::Global(wl_display* display) : | ||
wayland::XdgDecorationManagerV1::Global::Global{display, Version<1>{}} | ||
{ | ||
} | ||
|
||
void mir::frontend::XdgDecorationManagerV1::Global::bind(wl_resource* new_zxdg_decoration_manager_v1) | ||
{ | ||
new XdgDecorationManagerV1{new_zxdg_decoration_manager_v1}; | ||
} | ||
|
||
mir::frontend::XdgDecorationManagerV1::XdgDecorationManagerV1(wl_resource* resource) : | ||
mir::wayland::XdgDecorationManagerV1{resource, Version<1>{}}, | ||
toplevels_with_decorations{std::make_shared<ToplevelsWithDecorations>()} | ||
{ | ||
} | ||
|
||
void mir::frontend::XdgDecorationManagerV1::get_toplevel_decoration(wl_resource* id, wl_resource* toplevel) | ||
{ | ||
using Error = mir::frontend::XdgToplevelDecorationV1::Error; | ||
|
||
auto* tl = mir::frontend::XdgToplevelStable::from(toplevel); | ||
if (!tl) | ||
{ | ||
BOOST_THROW_EXCEPTION(std::runtime_error("Invalid toplevel pointer")); | ||
} | ||
|
||
auto decoration = new XdgToplevelDecorationV1{id, tl}; | ||
if (!toplevels_with_decorations->register_toplevel(toplevel)) | ||
{ | ||
BOOST_THROW_EXCEPTION(mir::wayland::ProtocolError( | ||
resource, Error::already_constructed, "Decoration already constructed for this toplevel")); | ||
} | ||
|
||
decoration->add_destroy_listener( | ||
[toplevels_with_decorations = this->toplevels_with_decorations, toplevel]() | ||
{ | ||
toplevels_with_decorations->unregister_toplevel(toplevel); | ||
}); | ||
|
||
tl->add_destroy_listener( | ||
[toplevels_with_decorations = this->toplevels_with_decorations, client = this->client, toplevel]() | ||
{ | ||
// Under normal conditions, decorations should be destroyed before | ||
// toplevels. Causing `unregister_toplevel` to return false. | ||
// | ||
// If the attached decoration is not destroyed before its toplevel, | ||
// then its a protocol error. This can happen in two cases: A | ||
// protocol violation caused by the client, or another error | ||
// triggering wayland cleanup code which destroys wayland objects | ||
// with no guaranteed order. | ||
const auto orphaned_decoration = toplevels_with_decorations->unregister_toplevel(toplevel); | ||
if (!client->is_being_destroyed() && orphaned_decoration) | ||
{ | ||
mir::log_warning("Toplevel destroyed before attached decoration!"); | ||
// https://github.com/canonical/mir/issues/3452 | ||
/* BOOST_THROW_EXCEPTION(mir::wayland::ProtocolError( */ | ||
/* resource, Error::orphaned, "Toplevel destroyed before its attached decoration")); */ | ||
} | ||
}); | ||
} | ||
|
||
mir::frontend::XdgToplevelDecorationV1::XdgToplevelDecorationV1( | ||
wl_resource* id, mir::frontend::XdgToplevelStable* toplevel) : | ||
wayland::XdgToplevelDecorationV1{id, Version<1>{}}, | ||
toplevel{toplevel} | ||
{ | ||
} | ||
|
||
void mir::frontend::XdgToplevelDecorationV1::update_mode(uint32_t new_mode) | ||
{ | ||
auto spec = shell::SurfaceSpecification{}; | ||
|
||
mode = new_mode; | ||
switch (mode) | ||
{ | ||
case Mode::client_side: | ||
spec.server_side_decorated = false; | ||
break; | ||
case Mode::server_side: | ||
spec.server_side_decorated = true; | ||
break; | ||
} | ||
|
||
this->toplevel->apply_spec(spec); | ||
send_configure_event(mode); | ||
} | ||
|
||
void mir::frontend::XdgToplevelDecorationV1::set_mode(uint32_t mode) | ||
{ | ||
update_mode(mode); | ||
} | ||
|
||
void mir::frontend::XdgToplevelDecorationV1::unset_mode() | ||
{ | ||
update_mode(default_mode); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright © Canonical Ltd. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 or 3 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#ifndef MIR_FRONTEND_XDG_DECORATION_UNSTABLE_V1_H | ||
#define MIR_FRONTEND_XDG_DECORATION_UNSTABLE_V1_H | ||
|
||
#include "xdg-decoration-unstable-v1_wrapper.h" | ||
|
||
namespace mir | ||
{ | ||
namespace frontend | ||
{ | ||
auto create_xdg_decoration_unstable_v1(wl_display* display) -> std::shared_ptr<wayland::XdgDecorationManagerV1::Global>; | ||
} | ||
} // namespace mir | ||
|
||
#endif // MIR_FRONTEND_RELATIVE_POINTER_UNSTABLE_V1_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.