1 #ifndef VIEW_IMPL_HPP
2 #define VIEW_IMPL_HPP
3 
4 #include <wayfire/nonstd/safe-list.hpp>
5 #include <wayfire/view.hpp>
6 #include <wayfire/opengl.hpp>
7 
8 #include "surface-impl.hpp"
9 #include <wayfire/nonstd/wlroots-full.hpp>
10 
11 // for emit_map_*()
12 #include <wayfire/compositor-view.hpp>
13 #include <wayfire/compositor-surface.hpp>
14 
15 struct wlr_seat;
16 namespace wf
17 {
18 struct sublayer_t;
19 struct view_transform_block_t : public noncopyable_t
20 {
21     std::string plugin_name = "";
22     std::unique_ptr<wf::view_transformer_t> transform;
23     wf::framebuffer_t fb;
24 
25     view_transform_block_t();
26     ~view_transform_block_t();
27 };
28 
29 /** Private data used by the default view_interface_t implementation */
30 class view_interface_t::view_priv_impl
31 {
32   public:
33     /**
34      * A view is alive as long as it is possible for it to become mapped in the
35      * future. For wlr views, this means that their role object hasn't been
36      * destroyed and they still have the internal surface reference.
37      */
38     bool is_alive = true;
39     /** Reference count to the view */
40     int ref_cnt = 0;
41 
42     bool keyboard_focus_enabled = true;
43 
44     /**
45      * Calculate the windowed geometry relative to the output's workarea.
46      */
47     wf::geometry_t calculate_windowed_geometry(wf::output_t *output);
48 
49     /**
50      * Update the stored window geometry and workarea, if the current view
51      * state is not-tiled and not-moving.
52      */
53     void update_windowed_geometry(wayfire_view self, wf::geometry_t geometry);
54 
55     /* those two point to the same object. Two fields are used to avoid
56      * constant casting to and from types */
57     surface_interface_t *decoration = NULL;
58     wf::decorator_frame_t_t *frame  = NULL;
59 
60     uint32_t edges = 0;
61     int in_continuous_move   = 0;
62     int in_continuous_resize = 0;
63     int visibility_counter   = 1;
64 
65     wf::safe_list_t<std::shared_ptr<view_transform_block_t>> transforms;
66 
67     struct offscreen_buffer_t : public wf::framebuffer_t
68     {
69         wf::region_t cached_damage;
validwf::view_interface_t::view_priv_impl::offscreen_buffer_t70         bool valid()
71         {
72             return this->fb != (uint32_t)-1;
73         }
74     } offscreen_buffer;
75 
76     wlr_box minimize_hint = {0, 0, 0, 0};
77 
78     /** The sublayer of the view. For workspace-manager. */
79     nonstd::observer_ptr<sublayer_t> sublayer;
80     /* Promoted to the fullscreen layer? For workspace-manager. */
81     bool is_promoted = false;
82 
83   private:
84     /** Last geometry the view has had in non-tiled and non-fullscreen state.
85      * -1 as width/height means that no such geometry has been stored. */
86     wf::geometry_t last_windowed_geometry = {0, 0, -1, -1};
87 
88     /**
89      * The workarea when last_windowed_geometry was stored. This is used
90      * for ex. when untiling a view to determine its geometry relative to the
91      * (potentially changed) workarea of its output.
92      */
93     wf::geometry_t windowed_geometry_workarea = {0, 0, -1, -1};
94 };
95 
96 /**
97  * Damage the given box, assuming the damage belongs to the given view.
98  * The given box is assumed to have been transformed with the view's
99  * transformers.
100  *
101  * The main difference with directly damaging the output is that this will
102  * add the damage to all workspaces the view is visible on, in case of shell
103  * views.
104  */
105 void view_damage_raw(wayfire_view view, const wlr_box& box);
106 
107 /**
108  * Implementation of a view backed by a wlr_* shell struct.
109  */
110 class wlr_view_t :
111     public wlr_surface_base_t,
112     public view_interface_t
113 {
114   public:
115     wlr_view_t();
~wlr_view_t()116     virtual ~wlr_view_t()
117     {}
118 
119     /* Functions which are shell-independent */
120     virtual void set_role(view_role_t new_role) override final;
121 
122     virtual std::string get_app_id() override final;
123     virtual std::string get_title() override final;
124     virtual wf::region_t get_transformed_opaque_region() override;
125 
126     /* Functions which are further specialized for the different shells */
127     virtual void move(int x, int y) override;
128     virtual wf::geometry_t get_wm_geometry() override;
129     virtual wf::geometry_t get_output_geometry() override;
130 
131     virtual wlr_surface *get_keyboard_focus_surface() override;
132 
133     virtual bool should_be_decorated() override;
134     virtual void set_decoration_mode(bool use_csd);
135     virtual void set_output(wf::output_t*) override;
136     bool has_client_decoration = true;
137 
138   protected:
139     std::string title, app_id;
140     /** Used by view implementations when the app id changes */
141     void handle_app_id_changed(std::string new_app_id);
142     /** Used by view implementations when the title changes */
143     void handle_title_changed(std::string new_title);
144     /* Update the minimize hint */
145     void handle_minimize_hint(wf::surface_interface_t *relative_to,
146         const wlr_box& hint);
147 
148     /**
149      * The bounding box of the view the last time it was rendered.
150      *
151      * This is used to damage the view when it is resized, because when a
152      * transformer changes because the view is resized, we can't reliably
153      * calculate the old view region to damage.
154      */
155     wf::geometry_t last_bounding_box{0, 0, 0, 0};
156 
157     /**
158      * Adjust the view position when resizing the view so that its apparent
159      * position doesn't change when resizing.
160      */
161     void adjust_anchored_edge(wf::dimensions_t new_size);
162 
163     /** The output geometry of the view */
164     wf::geometry_t geometry{100, 100, 0, 0};
165 
166     /** Set the view position and optionally send the geometry changed signal
167      * @param old_geometry The geometry to report as previous, in case the
168      * signal is sent. */
169     virtual void set_position(int x, int y, wf::geometry_t old_geometry,
170         bool send_geometry_signal);
171     /** Update the view size to the actual dimensions of its surface */
172     virtual void update_size();
173 
174     /** Last request to the client */
175     wf::dimensions_t last_size_request = {0, 0};
176     virtual bool should_resize_client(wf::dimensions_t request,
177         wf::dimensions_t current_size);
178 
179     virtual void commit() override;
180     virtual void map(wlr_surface *surface) override;
181     virtual void unmap() override;
182 
183     /* Handle the destruction of the underlying wlroots object */
184     virtual void destroy();
185 
186     /*
187      * wlr_foreign_toplevel_v1 implementation functions
188      */
189 
190     /* The toplevel is created by the individual view's mapping functions,
191      * i.e in xdg-shell, xwayland, etc.
192      * The handle is automatically destroyed when the view is unmapped */
193     wlr_foreign_toplevel_handle_v1 *toplevel_handle = NULL;
194 
195     wf::wl_listener_wrapper toplevel_handle_v1_maximize_request,
196         toplevel_handle_v1_activate_request,
197         toplevel_handle_v1_minimize_request,
198         toplevel_handle_v1_set_rectangle_request,
199         toplevel_handle_v1_close_request;
200 
201     /* Create/destroy the toplevel_handle */
202     virtual void create_toplevel();
203     virtual void destroy_toplevel();
204 
205     /* The following are no-op if toplevel_handle == NULL */
206     virtual void toplevel_send_title();
207     virtual void toplevel_send_app_id();
208     virtual void toplevel_send_state();
209     virtual void toplevel_update_output(wf::output_t *output, bool enter);
210 
211     virtual void desktop_state_updated() override;
212 
213   public:
214     /* Just pass to the default wlr surface implementation */
is_mapped() const215     virtual bool is_mapped() const override
216     {
217         return _is_mapped();
218     }
219 
get_size() const220     virtual wf::dimensions_t get_size() const override
221     {
222         return _get_size();
223     }
224 
simple_render(const wf::framebuffer_t & fb,int x,int y,const wf::region_t & damage)225     virtual void simple_render(const wf::framebuffer_t& fb, int x, int y,
226         const wf::region_t& damage) override
227     {
228         _simple_render(fb, x, y, damage);
229     }
230 };
231 
232 /** Emit the map signal for the given view */
233 void emit_view_map_signal(wayfire_view view, bool has_position);
234 void emit_ping_timeout_signal(wayfire_view view);
235 
236 wf::surface_interface_t *wf_surface_from_void(void *handle);
237 wf::view_interface_t *wf_view_from_void(void *handle);
238 
239 void init_xdg_shell();
240 void init_xwayland();
241 void init_layer_shell();
242 
243 std::string xwayland_get_display();
244 void xwayland_update_default_cursor();
245 
246 /* Ensure that the given surface is on top of the Xwayland stack order. */
247 void xwayland_bring_to_front(wlr_surface *surface);
248 
249 /* Get the current Xwayland drag icon, if it exists. */
250 wayfire_view get_xwayland_drag_icon();
251 
252 void init_desktop_apis();
253 }
254 
255 #endif /* end of include guard: VIEW_IMPL_HPP */
256