diff --git a/include/miroil/miroil/surface.h b/include/miroil/miroil/surface.h
new file mode 100644
index 00000000000..d3dcd0e52f5
--- /dev/null
+++ b/include/miroil/miroil/surface.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License version 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 warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+#ifndef MIROIL_SURFACE_H
+#define MIROIL_SURFACE_H
+#include
+#include
+#include
+#include
+#include
+
+namespace mir {
+ namespace scene { class Surface; }
+ namespace shell { class InputTargeter; }
+ namespace geometry { struct Rectangle; }
+ namespace graphics { class CursorImage; }
+ namespace compositor { class BufferStream; }
+}
+
+namespace miroil {
+
+class SurfaceObserver;
+class SurfaceObserverImpl;
+
+using CompositorID = void const*;
+
+class Surface
+{
+public:
+ Surface(std::shared_ptr wrapped);
+ ~Surface() = default;
+
+ auto getWrapped() const -> mir::scene::Surface*;
+ void add_observer(std::shared_ptr const& observer);
+ void remove_observer(std::shared_ptr const& observer);
+
+ int buffers_ready_for_compositor(void const* compositor_id) const;
+ auto generate_renderables(miroil::CompositorID id) const -> mir::graphics::RenderableList;
+
+ bool is_confined_to_window();
+ void set_orientation(MirOrientation orientation);
+ void set_keymap(MirInputDeviceId id, std::string const& model, std::string const& layout,
+ std::string const& variant, std::string const& options);
+
+ void set_confine_pointer_state(MirPointerConfinementState state);
+ auto parent() const -> std::shared_ptr;
+
+ /// Top-left corner (of the window frame if present)
+ mir::geometry::Point top_left() const;
+ bool visible() const;
+
+ // TODO a legacy of old interactions and needs removing
+ int configure(MirWindowAttrib attrib, int value);
+ // TODO a legacy of old interactions and needs removing
+ int query(MirWindowAttrib attrib) const;
+
+private:
+ std::shared_ptr wrapped;
+ std::unordered_map, std::shared_ptr> observers;
+};
+
+}
+
+#endif
diff --git a/include/miroil/miroil/surface_observer.h b/include/miroil/miroil/surface_observer.h
new file mode 100644
index 00000000000..322e4f26a44
--- /dev/null
+++ b/include/miroil/miroil/surface_observer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2021 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 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 .
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace mir { namespace scene { class SurfaceObserver; } }
+namespace mir { namespace scene { class Surface; } }
+namespace mir { namespace input { enum class InputReceptionMode; } }
+
+struct MirEvent;
+struct MirInputEvent;
+
+namespace miroil
+{
+
+class SurfaceObserver
+{
+public:
+ SurfaceObserver() = default;
+ SurfaceObserver(SurfaceObserver const&) = delete;
+ SurfaceObserver& operator=(SurfaceObserver const&) = delete;
+ virtual ~SurfaceObserver();
+
+ virtual void attrib_changed(mir::scene::Surface const* surf, MirWindowAttrib attrib, int value) = 0;
+ virtual void window_resized_to(mir::scene::Surface const* surf, mir::geometry::Size const& window_size) = 0;
+ virtual void content_resized_to(mir::scene::Surface const* surf, mir::geometry::Size const& content_size) = 0;
+ virtual void moved_to(mir::scene::Surface const* surf, mir::geometry::Point const& top_left) = 0;
+ virtual void hidden_set_to(mir::scene::Surface const* surf, bool hide) = 0;
+ virtual void frame_posted(mir::scene::Surface const* surf, int frames_available, mir::geometry::Size const& size) = 0;
+ virtual void alpha_set_to(mir::scene::Surface const* surf, float alpha) = 0;
+ virtual void orientation_set_to(mir::scene::Surface const* surf, MirOrientation orientation) = 0;
+ virtual void transformation_set_to(mir::scene::Surface const* surf, glm::mat4 const& t) = 0;
+ virtual void reception_mode_set_to(mir::scene::Surface const* surf, mir::input::InputReceptionMode mode) = 0;
+ virtual void cursor_image_set_to(mir::scene::Surface const* surf, mir::graphics::CursorImage const& image) = 0;
+ virtual void client_surface_close_requested(mir::scene::Surface const* surf) = 0;
+ virtual void keymap_changed(mir::scene::Surface const* surf, MirInputDeviceId id, std::string const& model,
+ std::string const& layout, std::string const& variant, std::string const& options) = 0;
+ virtual void renamed(mir::scene::Surface const* surf, char const* name) = 0;
+ virtual void cursor_image_removed(mir::scene::Surface const* surf) = 0;
+ virtual void placed_relative(mir::scene::Surface const* surf, mir::geometry::Rectangle const& placement) = 0;
+ virtual void input_consumed(mir::scene::Surface const* surf, MirEvent const* event) = 0;
+ virtual void start_drag_and_drop(mir::scene::Surface const* surf, std::vector const& handle) = 0;
+ virtual void depth_layer_set_to(mir::scene::Surface const* surf, MirDepthLayer depth_layer) = 0;
+ virtual void application_id_set_to(mir::scene::Surface const* surf, std::string const& application_id) = 0;
+};
+
+}
diff --git a/src/miroil/CMakeLists.txt b/src/miroil/CMakeLists.txt
index cbd0e32ab0c..46d17fda6e8 100644
--- a/src/miroil/CMakeLists.txt
+++ b/src/miroil/CMakeLists.txt
@@ -25,6 +25,8 @@ add_library(miroil SHARED
prompt_session_listener.cpp ${miroil_include}/miroil/prompt_session_listener.h
prompt_session_manager.cpp ${miroil_include}/miroil/prompt_session_manager.h
set_compositor.cpp ${miroil_include}/miroil/set_compositor.h
+ surface.cpp ${miroil_include}/miroil/surface.h
+ surface_observer.cpp ${miroil_include}/miroil/surface_observer.h
${miroil_include}/miroil/display_configuration_storage.h
${miroil_include}/miroil/display_id.h
)
diff --git a/src/miroil/surface.cpp b/src/miroil/surface.cpp
new file mode 100644
index 00000000000..9cb6c4a07c4
--- /dev/null
+++ b/src/miroil/surface.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2021 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License version 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 warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+#include
+#include
+#include "mir/scene/surface.h"
+#include "mir/scene/surface_observer.h"
+
+namespace miroil {
+
+class SurfaceObserverImpl : public mir::scene::SurfaceObserver
+{
+public:
+ SurfaceObserverImpl(std::shared_ptr const & wrapped);
+ virtual ~SurfaceObserverImpl();
+
+ void alpha_set_to(mir::scene::Surface const* surf, float alpha) override;
+ void application_id_set_to(mir::scene::Surface const* surf, std::string const& application_id) override;
+ void attrib_changed(mir::scene::Surface const* surf, MirWindowAttrib attrib, int value) override;
+ void client_surface_close_requested(mir::scene::Surface const* surf) override;
+ void content_resized_to(mir::scene::Surface const* surf, mir::geometry::Size const& content_size) override;
+ void cursor_image_removed(mir::scene::Surface const* surf) override;
+ void cursor_image_set_to(mir::scene::Surface const* surf, mir::graphics::CursorImage const& image) override;
+ void depth_layer_set_to(mir::scene::Surface const* surf, MirDepthLayer depth_layer) override;
+ void frame_posted(mir::scene::Surface const* surf, int frames_available, mir::geometry::Size const& size) override;
+ void hidden_set_to(mir::scene::Surface const* surf, bool hide) override;
+ void input_consumed(mir::scene::Surface const* surf, MirEvent const* event) override;
+ void keymap_changed(mir::scene::Surface const* surf, MirInputDeviceId id, std::string const& model,
+ std::string const& layout, std::string const& variant, std::string const& options) override;
+ void moved_to(mir::scene::Surface const* surf, mir::geometry::Point const& top_left) override;
+ void orientation_set_to(mir::scene::Surface const* surf, MirOrientation orientation) override;
+ void placed_relative(mir::scene::Surface const* surf, mir::geometry::Rectangle const& placement) override;
+ void reception_mode_set_to(mir::scene::Surface const* surf, mir::input::InputReceptionMode mode) override;
+ void renamed(mir::scene::Surface const* surf, char const* name);
+ void start_drag_and_drop(mir::scene::Surface const* surf, std::vector const& handle) override;
+ void transformation_set_to(mir::scene::Surface const* surf, glm::mat4 const& t) override;
+ void window_resized_to(mir::scene::Surface const* surf, mir::geometry::Size const& window_size) override;
+
+private:
+ std::shared_ptr listener;
+};
+
+}
+
+miroil::SurfaceObserverImpl::SurfaceObserverImpl(std::shared_ptr const & wrapped)
+: listener(wrapped)
+{
+}
+
+miroil::SurfaceObserverImpl::~SurfaceObserverImpl() = default;
+
+void miroil::SurfaceObserverImpl::alpha_set_to(mir::scene::Surface const* surf, float alpha)
+{
+ listener->alpha_set_to(surf, alpha);
+}
+
+void miroil::SurfaceObserverImpl::application_id_set_to(mir::scene::Surface const* surf, std::string const& application_id)
+{
+ listener->application_id_set_to(surf, application_id);
+}
+
+void miroil::SurfaceObserverImpl::attrib_changed(mir::scene::Surface const* surf, MirWindowAttrib attrib, int value)
+{
+ listener->attrib_changed(surf, attrib, value);
+}
+
+void miroil::SurfaceObserverImpl::client_surface_close_requested(mir::scene::Surface const* surf)
+{
+ listener->client_surface_close_requested(surf);
+}
+
+void miroil::SurfaceObserverImpl::content_resized_to(mir::scene::Surface const* surf, mir::geometry::Size const& content_size)
+{
+ listener->content_resized_to(surf, content_size);
+}
+
+void miroil::SurfaceObserverImpl::cursor_image_removed(mir::scene::Surface const* surf)
+{
+ listener->cursor_image_removed(surf);
+}
+
+void miroil::SurfaceObserverImpl::cursor_image_set_to(mir::scene::Surface const* surf, mir::graphics::CursorImage const& image)
+{
+ listener->cursor_image_set_to(surf, image);
+}
+
+void miroil::SurfaceObserverImpl::depth_layer_set_to(mir::scene::Surface const* surf, MirDepthLayer depth_layer)
+{
+ listener->depth_layer_set_to(surf, depth_layer);
+}
+
+void miroil::SurfaceObserverImpl::frame_posted(mir::scene::Surface const* surf, int frames_available, mir::geometry::Size const& size)
+{
+ listener->frame_posted(surf, frames_available, size);
+}
+
+void miroil::SurfaceObserverImpl::hidden_set_to(mir::scene::Surface const* surf, bool hide)
+{
+ listener->hidden_set_to(surf, hide);
+}
+
+void miroil::SurfaceObserverImpl::input_consumed(mir::scene::Surface const* surf, MirEvent const* event)
+{
+ listener->input_consumed(surf, event);
+}
+
+void miroil::SurfaceObserverImpl::keymap_changed(mir::scene::Surface const* surf, MirInputDeviceId id, std::string const& model,
+ std::string const& layout, std::string const& variant, std::string const& options)
+{
+ listener->keymap_changed(surf, id, model, layout, variant, options);
+}
+
+void miroil::SurfaceObserverImpl::moved_to(mir::scene::Surface const* surf, mir::geometry::Point const& top_left)
+{
+ listener->moved_to(surf, top_left);
+}
+
+void miroil::SurfaceObserverImpl::orientation_set_to(mir::scene::Surface const* surf, MirOrientation orientation)
+{
+ listener->orientation_set_to(surf, orientation);
+}
+
+void miroil::SurfaceObserverImpl::placed_relative(mir::scene::Surface const* surf, mir::geometry::Rectangle const& placement)
+{
+ listener->placed_relative(surf, placement);
+}
+
+void miroil::SurfaceObserverImpl::renamed(mir::scene::Surface const* surf, char const* name)
+{
+ listener->renamed(surf, name);
+}
+
+void miroil::SurfaceObserverImpl::start_drag_and_drop(mir::scene::Surface const* surf, std::vector const& handle)
+{
+ listener->start_drag_and_drop(surf, handle);
+}
+
+void miroil::SurfaceObserverImpl::transformation_set_to(mir::scene::Surface const* surf, glm::mat4 const& t)
+{
+ listener->transformation_set_to(surf, t);
+}
+
+void miroil::SurfaceObserverImpl::window_resized_to(mir::scene::Surface const* surf, mir::geometry::Size const& window_size)
+{
+ listener->window_resized_to(surf, window_size);
+}
+
+void miroil::SurfaceObserverImpl::reception_mode_set_to(mir::scene::Surface const* surf, mir::input::InputReceptionMode mode)
+{
+ listener->reception_mode_set_to(surf, mode);
+}
+
+miroil::Surface::Surface(std::shared_ptr wrapped)
+: wrapped(wrapped)
+{
+}
+
+void miroil::Surface::add_observer(std::shared_ptr const& observer)
+{
+ auto it = observers.find(observer);
+ if (it == observers.end()) {
+ std::shared_ptr impl = std::make_shared(observer);
+
+ wrapped->add_observer(impl);
+ observers.insert({observer, impl});
+ }
+}
+
+bool miroil::Surface::is_confined_to_window()
+{
+ // Code for Mir < 2.3
+ return (wrapped->confine_pointer_state() == mir_pointer_confined_to_window);
+
+ // Code for Mir >= 2.3
+ // return (wrapped->confine_pointer_state() == mir_pointer_confined_oneshot || wrapped->confine_pointer_state() == mir_pointer_confined_persistent);
+}
+
+void miroil::Surface::remove_observer(std::shared_ptr const& observer)
+{
+ auto it = observers.find(observer);
+ if (it != observers.end()) {
+ wrapped->remove_observer(it->second);
+ observers.erase(it);
+ }
+}
+
+auto miroil::Surface::getWrapped() const
+-> mir::scene::Surface *
+{
+ return wrapped.get();
+}
+
+int miroil::Surface::buffers_ready_for_compositor(void const* compositor_id) const
+{
+ return wrapped->buffers_ready_for_compositor(compositor_id);
+}
+
+auto miroil::Surface::generate_renderables(miroil::CompositorID id) const
+-> mir::graphics::RenderableList
+{
+ return wrapped->generate_renderables(id);
+}
+
+void miroil::Surface::set_orientation(MirOrientation orientation)
+{
+ wrapped->set_orientation(orientation);
+}
+
+void miroil::Surface::set_keymap(MirInputDeviceId id, std::string const& model, std::string const& layout,
+ std::string const& variant, std::string const& options)
+{
+ wrapped->set_keymap(id, model, layout, variant, options);
+}
+
+void miroil::Surface::set_confine_pointer_state(MirPointerConfinementState state)
+{
+ wrapped->set_confine_pointer_state(state);
+}
+
+auto miroil::Surface::parent() const
+-> std::shared_ptr
+{
+ return wrapped->parent();
+}
+
+auto miroil::Surface::top_left() const
+-> mir::geometry::Point
+{
+ return wrapped->top_left();
+}
+
+bool miroil::Surface::visible() const
+{
+ return wrapped->visible();
+}
+
+int miroil::Surface::configure(MirWindowAttrib attrib, int value)
+{
+ return wrapped->configure(attrib, value);
+}
+
+int miroil::Surface::query(MirWindowAttrib attrib) const
+{
+ return wrapped->query(attrib);
+}
diff --git a/src/miroil/surface_observer.cpp b/src/miroil/surface_observer.cpp
new file mode 100644
index 00000000000..215630eceeb
--- /dev/null
+++ b/src/miroil/surface_observer.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2021 Canonical, Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License version 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 warranties of MERCHANTABILITY,
+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+miroil::SurfaceObserver::~SurfaceObserver() = default;
diff --git a/src/miroil/symbols.map b/src/miroil/symbols.map
index 4d386ffe5c7..4e510778ef1 100644
--- a/src/miroil/symbols.map
+++ b/src/miroil/symbols.map
@@ -22,6 +22,7 @@ global:
miroil::GLBuffer::?GLBuffer*;
miroil::GLBuffer::GLBuffer*;
miroil::GLBuffer::bind*;
+ miroil::GLBuffer::has_alpha_channel*;
miroil::GLBuffer::operator*;
miroil::GLBuffer::reset*;
miroil::GLBuffer::size*;
@@ -63,6 +64,25 @@ global:
miroil::PromptSessionManager::suspend_prompt_session*;
miroil::SetCompositor::SetCompositor*;
miroil::SetCompositor::operator*;
+ miroil::Surface::?Surface*;
+ miroil::Surface::Surface*;
+ miroil::Surface::add_observer*;
+ miroil::Surface::buffers_ready_for_compositor*;
+ miroil::Surface::configure*;
+ miroil::Surface::generate_renderables*;
+ miroil::Surface::getWrapped*;
+ miroil::Surface::is_confined_to_window*;
+ miroil::Surface::parent*;
+ miroil::Surface::query*;
+ miroil::Surface::remove_observer*;
+ miroil::Surface::set_confine_pointer_state*;
+ miroil::Surface::set_keymap*;
+ miroil::Surface::set_orientation*;
+ miroil::Surface::top_left*;
+ miroil::Surface::visible*;
+ miroil::SurfaceObserver::?SurfaceObserver*;
+ miroil::SurfaceObserver::SurfaceObserver*;
+ miroil::SurfaceObserver::operator*;
miroil::dispatch_input_event*;
non-virtual?thunk?to?miroil::Compositor::?Compositor*;
non-virtual?thunk?to?miroil::DisplayConfigurationPolicy::?DisplayConfigurationPolicy*;
@@ -70,6 +90,7 @@ global:
non-virtual?thunk?to?miroil::EventBuilder::?EventBuilder*;
non-virtual?thunk?to?miroil::InputDeviceObserver::?InputDeviceObserver*;
non-virtual?thunk?to?miroil::PromptSessionListener::?PromptSessionListener*;
+ non-virtual?thunk?to?miroil::SurfaceObserver::?SurfaceObserver*;
typeinfo?for?miroil::Compositor;
typeinfo?for?miroil::DisplayConfigurationOptions;
typeinfo?for?miroil::DisplayConfigurationOptions::DisplayMode;
@@ -90,6 +111,8 @@ global:
typeinfo?for?miroil::PromptSessionListener;
typeinfo?for?miroil::PromptSessionManager;
typeinfo?for?miroil::SetCompositor;
+ typeinfo?for?miroil::Surface;
+ typeinfo?for?miroil::SurfaceObserver;
vtable?for?miroil::Compositor;
vtable?for?miroil::DisplayConfigurationOptions;
vtable?for?miroil::DisplayConfigurationOptions::DisplayMode;
@@ -110,6 +133,8 @@ global:
vtable?for?miroil::PromptSessionListener;
vtable?for?miroil::PromptSessionManager;
vtable?for?miroil::SetCompositor;
+ vtable?for?miroil::Surface;
+ vtable?for?miroil::SurfaceObserver;
};
local: *;