commit 4bc4980e3d28a1df5b35963d426e20d820138477
parent 7b3b1a777a817f8eaae3c527de4473239f667d9f
Author: deurzen <max@deurzen.net>
Date: Sat, 28 May 2022 01:18:08 +0200
restructures view {,de}registration processes
Diffstat:
12 files changed, 734 insertions(+), 443 deletions(-)
diff --git a/include/kranewl/cycle.t.hh b/include/kranewl/cycle.t.hh
@@ -108,6 +108,8 @@ Cycle<T>::next_will_wrap(Direction direction) const
case Direction::Backward: return m_index == 0;
case Direction::Forward: return m_index == Util::last_index(m_elements);
}
+
+ return false;
}
template <typename T>
diff --git a/include/kranewl/model.hh b/include/kranewl/model.hh
@@ -146,6 +146,10 @@ public:
void spawn_external(std::string&&) const;
+ Output_ptr mp_output;
+ Context_ptr mp_context;
+ Workspace_ptr mp_workspace;
+
private:
Server_ptr mp_server;
Config const& m_config;
@@ -156,11 +160,6 @@ private:
Cycle<Context_ptr> m_contexts;
Cycle<Workspace_ptr> m_workspaces;
- Output_ptr mp_output;
- Output_ptr mp_fallback_output;
- Context_ptr mp_context;
- Workspace_ptr mp_workspace;
-
Output_ptr mp_prev_output;
Context_ptr mp_prev_context;
Workspace_ptr mp_prev_workspace;
diff --git a/include/kranewl/tree/view.hh b/include/kranewl/tree/view.hh
@@ -30,6 +30,16 @@ typedef struct View {
static constexpr Dim MIN_VIEW_DIM = Dim{25, 10};
static constexpr Dim PREFERRED_INIT_VIEW_DIM = Dim{480, 260};
+ enum class OutsideState {
+ Focused,
+ FocusedDisowned,
+ FocusedSticky,
+ Unfocused,
+ UnfocusedDisowned,
+ UnfocusedSticky,
+ Urgent
+ };
+
enum class Type {
XDGShell,
#ifdef XWAYLAND
@@ -43,12 +53,7 @@ typedef struct View {
Server_ptr,
Model_ptr,
Seat_ptr,
- struct wlr_surface*,
- void(*)(wl_listener*, void*),
- void(*)(wl_listener*, void*),
- void(*)(wl_listener*, void*),
- void(*)(wl_listener*, void*),
- void(*)(wl_listener*, void*)
+ struct wlr_surface*
);
#ifdef XWAYLAND
View(
@@ -57,42 +62,87 @@ typedef struct View {
Server_ptr,
Model_ptr,
Seat_ptr,
- struct wlr_surface*,
- void(*)(wl_listener*, void*),
- void(*)(wl_listener*, void*),
- void(*)(wl_listener*, void*),
- void(*)(wl_listener*, void*),
- void(*)(wl_listener*, void*)
+ struct wlr_surface*
);
#endif
virtual ~View();
- void map(struct wlr_surface*, bool, struct wlr_output*, bool);
- void unmap();
+ virtual Region constraints() = 0;
+ virtual pid_t pid() = 0;
+ virtual bool prefers_floating() = 0;
+ virtual View_ptr is_transient_for() = 0;
+
+ virtual void map() = 0;
+ virtual void unmap() = 0;
+ virtual void activate(Toggle) = 0;
+ virtual void set_tiled(Toggle) = 0;
+ virtual void set_fullscreen(Toggle) = 0;
+ virtual void set_resizing(Toggle) = 0;
+
+ virtual void configure(Region const&, Extents const&, bool) = 0;
+ virtual void close() = 0;
+ virtual void close_popups() = 0;
+ virtual void destroy() = 0;
+
+ void render_decoration();
+
+ bool focused() const { return m_focused; }
+ bool mapped() const { return m_mapped; }
+ bool managed() const { return m_managed; }
+ bool urgent() const { return m_urgent; }
+ bool floating() const { return m_floating; }
+ bool fullscreen() const { return m_fullscreen; }
+ bool scratchpad() const { return m_scratchpad; }
+ bool contained() const { return m_contained; }
+ bool invincible() const { return m_invincible; }
+ bool sticky() const { return m_sticky; }
+ bool iconifyable() const { return m_iconifyable; }
+ bool iconified() const { return m_iconified; }
+ bool disowned() const { return m_disowned; }
+ void set_focused(bool);
+ void set_mapped(bool);
+ void set_managed(bool);
+ void set_urgent(bool);
+ void set_floating(bool);
+ void set_fullscreen(bool);
+ void set_scratchpad(bool);
+ void set_contained(bool);
+ void set_invincible(bool);
+ void set_sticky(bool);
+ void set_iconifyable(bool);
+ void set_iconified(bool);
+ void set_disowned(bool);
- void touch();
+ uint32_t free_decoration_to_wlr_edges() const;
+ uint32_t tile_decoration_to_wlr_edges() const;
+ Region const& free_region() const { return m_free_region; }
+ Region const& tile_region() const { return m_tile_region; }
+ Region const& active_region() const { return m_active_region; }
+ void set_free_region(Region const&);
+ void set_tile_region(Region const&);
+ Dim const& minimum_dim() const { return m_minimum_dim; }
+ Dim const& preferred_dim() const { return m_preferred_dim; }
+ void set_minimum_dim(Dim const& minimum_dim) { m_minimum_dim = minimum_dim; }
+ void set_preferred_dim(Dim const& preferred_dim) { m_preferred_dim = preferred_dim; }
+
+ Decoration const& free_decoration() const { return m_free_decoration; }
+ Decoration const& tile_decoration() const { return m_tile_decoration; }
+ Decoration const& active_decoration() const { return m_active_decoration; }
+ void set_free_decoration(Decoration const&);
+ void set_tile_decoration(Decoration const&);
- virtual void focus(bool) = 0;
- virtual void moveresize(Region const&, Extents const&, bool) = 0;
- virtual void kill() = 0;
+ void touch() { m_last_touched = std::chrono::steady_clock::now(); }
static bool
is_free(View_ptr view)
{
return (view->m_floating && (!view->m_fullscreen || view->m_contained))
- || !view->m_managed
- || view->m_disowned;
+ || view->m_disowned
+ || !view->m_managed;
}
- uint32_t free_decoration_to_wlr_edges() const;
- uint32_t tile_decoration_to_wlr_edges() const;
-
- void set_free_region(Region const&);
- void set_tile_region(Region const&);
-
- void set_free_decoration(Decoration const&);
- void set_tile_decoration(Decoration const&);
+ OutsideState outside_state() const;
Uid m_uid;
Type m_type;
@@ -119,6 +169,17 @@ typedef struct View {
pid_t m_pid;
+ std::chrono::time_point<std::chrono::steady_clock> m_last_focused;
+ std::chrono::time_point<std::chrono::steady_clock> m_last_touched;
+ std::chrono::time_point<std::chrono::steady_clock> m_managed_since;
+
+protected:
+
+ struct {
+ struct wl_signal unmap;
+ } m_events;
+
+private:
Decoration m_tile_decoration;
Decoration m_free_decoration;
Decoration m_active_decoration;
@@ -145,26 +206,11 @@ typedef struct View {
bool m_iconified;
bool m_disowned;
- std::chrono::time_point<std::chrono::steady_clock> m_last_focused;
- std::chrono::time_point<std::chrono::steady_clock> m_last_touched;
- std::chrono::time_point<std::chrono::steady_clock> m_managed_since;
+ OutsideState m_outside_state;
-protected:
void set_inner_region(Region const&);
void set_active_region(Region const&);
- struct wlr_foreign_toplevel_handle_v1* foreign_toplevel;
-
- struct wl_listener ml_foreign_activate_request;
- struct wl_listener ml_foreign_fullscreen_request;
- struct wl_listener ml_foreign_close_request;
- struct wl_listener ml_foreign_destroy;
- struct wl_listener ml_surface_new_subsurface;
-
- struct {
- struct wl_signal unmap;
- } m_events;
-
}* View_ptr;
typedef struct ViewChild* ViewChild_ptr;
diff --git a/include/kranewl/tree/xdg_view.hh b/include/kranewl/tree/xdg_view.hh
@@ -22,15 +22,23 @@ typedef struct XDGView final : public View {
~XDGView();
- void focus(bool) override;
- void moveresize(Region const&, Extents const&, bool) override;
- void kill() override;
-
- static void handle_foreign_activate_request(struct wl_listener*, void*);
- static void handle_foreign_fullscreen_request(struct wl_listener*, void*);
- static void handle_foreign_close_request(struct wl_listener*, void*);
- static void handle_foreign_destroy(struct wl_listener*, void*);
- static void handle_surface_new_subsurface(struct wl_listener*, void*);
+ Region constraints() override;
+ pid_t pid() override;
+ bool prefers_floating() override;
+ View_ptr is_transient_for() override;
+
+ void map() override;
+ void unmap() override;
+ void activate(Toggle) override;
+ void set_tiled(Toggle) override;
+ void set_fullscreen(Toggle) override;
+ void set_resizing(Toggle) override;
+
+ void configure(Region const&, Extents const&, bool) override;
+ void close() override;
+ void close_popups() override;
+ void destroy() override;
+
static void handle_commit(struct wl_listener*, void*);
static void handle_request_move(struct wl_listener*, void*);
static void handle_request_resize(struct wl_listener*, void*);
diff --git a/include/kranewl/tree/xwayland_view.hh b/include/kranewl/tree/xwayland_view.hh
@@ -21,15 +21,23 @@ typedef struct XWaylandView final : public View {
~XWaylandView();
- void focus(bool) override;
- void moveresize(Region const&, Extents const&, bool) override;
- void kill() override;
-
- static void handle_foreign_activate_request(struct wl_listener*, void*);
- static void handle_foreign_fullscreen_request(struct wl_listener*, void*);
- static void handle_foreign_close_request(struct wl_listener*, void*);
- static void handle_foreign_destroy(struct wl_listener*, void*);
- static void handle_surface_new_subsurface(struct wl_listener*, void*);
+ Region constraints() override;
+ pid_t pid() override;
+ bool prefers_floating() override;
+ View_ptr is_transient_for() override;
+
+ void map() override;
+ void unmap() override;
+ void activate(Toggle) override;
+ void set_tiled(Toggle) override;
+ void set_fullscreen(Toggle) override;
+ void set_resizing(Toggle) override;
+
+ void configure(Region const&, Extents const&, bool) override;
+ void close() override;
+ void close_popups() override;
+ void destroy() override;
+
static void handle_commit(struct wl_listener*, void*);
static void handle_request_move(struct wl_listener*, void*);
static void handle_request_resize(struct wl_listener*, void*);
diff --git a/src/kranewl/layout.cc b/src/kranewl/layout.cc
@@ -522,7 +522,7 @@ LayoutHandler::arrange_float(
mp_layout->config.method,
view,
mp_layout->config.decoration,
- view->m_free_region
+ view->free_region()
};
}
);
@@ -560,7 +560,7 @@ LayoutHandler::arrange_single_float(
mp_layout->config.method,
view,
mp_layout->config.decoration,
- view->m_focused ? std::optional(view->m_free_region) : std::nullopt
+ view->focused() ? std::optional(view->free_region()) : std::nullopt
};
}
);
@@ -963,10 +963,10 @@ LayoutHandler::arrange_paper(
begin,
end,
[&contains_active](const View_ptr lhs, const View_ptr rhs) {
- if (lhs->m_focused) {
+ if (lhs->focused()) {
contains_active = true;
return false;
- } else if (rhs->m_focused) {
+ } else if (rhs->focused()) {
contains_active = true;
return true;
}
@@ -985,7 +985,7 @@ LayoutHandler::arrange_paper(
[=,this,&after_active,&i](View_ptr view) -> Placement {
int x = screen_region.pos.x + static_cast<int>(i++ * w);
- if ((!contains_active && *last_active == view) || view->m_focused) {
+ if ((!contains_active && *last_active == view) || view->focused()) {
after_active = true;
return Placement {
diff --git a/src/kranewl/model.cc b/src/kranewl/model.cc
@@ -44,7 +44,6 @@ Model::Model(
m_contexts{{}, true},
m_workspaces{{}, true},
mp_output{nullptr},
- mp_fallback_output{nullptr},
mp_context{nullptr},
mp_workspace{nullptr},
mp_prev_output{nullptr},
@@ -195,15 +194,17 @@ Model::unregister_output(Output_ptr output)
}
void
-Model::map_view(View_ptr view)
+Model::map_view(View_ptr)
{
TRACE();
+
}
void
-Model::unmap_view(View_ptr view)
+Model::unmap_view(View_ptr)
{
TRACE();
+
}
void
@@ -240,7 +241,7 @@ Model::focus_view(View_ptr view)
if (!output)
return;
- if (!view->m_sticky) {
+ if (!view->sticky()) {
activate_workspace(view->mp_workspace);
mp_workspace->activate_view(view);
}
@@ -248,7 +249,7 @@ Model::focus_view(View_ptr view)
if (mp_focus && mp_focus != view)
unfocus_view(mp_focus);
- view->m_urgent = false;
+ view->set_urgent(false);
mp_focus = view;
if (mp_workspace->layout_is_persistent() || mp_workspace->layout_is_single())
@@ -304,12 +305,12 @@ Model::place_view(Placement& placement)
}
}
- spdlog::info("Placing view {} at {}", view->m_uid, std::to_string(view->m_active_region));
+ spdlog::info("Placing view {} at {}", view->m_uid, std::to_string(view->active_region()));
map_view(view);
- view->moveresize(
- view->m_active_region,
- view->m_active_decoration.extents(),
+ view->configure(
+ view->active_region(),
+ view->active_decoration().extents(),
false
);
}
@@ -322,7 +323,7 @@ Model::sync_focus()
View_ptr active = mp_workspace->active();
if (active && active != mp_focus)
- active->focus(true);
+ active->activate(Toggle::On);
else if (mp_workspace->empty()) {
mp_server->relinquish_focus();
mp_focus = nullptr;
@@ -364,7 +365,7 @@ Model::reverse_views()
return;
mp_workspace->reverse();
- mp_workspace->active()->focus(true);
+ /* mp_workspace->active()->focus(true); */
sync_focus();
apply_layout(mp_workspace);
@@ -379,7 +380,7 @@ Model::rotate_views(Direction direction)
return;
mp_workspace->rotate(direction);
- mp_workspace->active()->focus(true);
+ /* mp_workspace->active()->focus(true); */
sync_focus();
apply_layout(mp_workspace);
@@ -413,7 +414,6 @@ Model::shuffle_main(Direction direction)
}
mp_workspace->shuffle_main(direction);
- mp_workspace->active()->focus(true);
sync_focus();
if (last_touched_index)
@@ -450,7 +450,6 @@ Model::shuffle_stack(Direction direction)
}
mp_workspace->shuffle_stack(direction);
- mp_workspace->active()->focus(true);
sync_focus();
if (last_touched_index)
@@ -480,26 +479,27 @@ Model::move_view_to_workspace(View_ptr view, Workspace_ptr workspace_to)
view->mp_workspace = workspace_to;
- Context_ptr context_from = workspace_from->context();
- Output_ptr output_from = context_from->output();
+ if (workspace_from) {
+ Context_ptr context_from = workspace_from->context();
+ Output_ptr output_from = context_from->output();
+
+ workspace_from->remove_view(view);
+ apply_layout(workspace_from);
+ }
Context_ptr context_to = workspace_to->context();
Output_ptr output_to = context_to->output();
view->mp_context = context_to;
- if (output_to != output_from)
- view->mp_output = output_to;
+ view->mp_output = output_to;
workspace_to->add_view(view);
- workspace_from->remove_view(view);
-
apply_layout(workspace_to);
- apply_layout(workspace_from);
- if (!output_to)
- unmap_view(view);
- else
+ if (output_to)
map_view(view);
+ else
+ unmap_view(view);
sync_focus();
}
@@ -518,15 +518,17 @@ Model::move_view_to_context(View_ptr view, Context_ptr context_to)
{
TRACE();
- Context_ptr context_from = view->mp_context;
+ Workspace_ptr workspace_from = view->mp_workspace;
- if (!context_to || context_to == context_from)
- return;
+ if (workspace_from) {
+ Context_ptr context_from = workspace_from->context();
+ Output_ptr output_from = context_from->output();
- view->mp_context = context_to;
+ workspace_from->remove_view(view);
+ apply_layout(workspace_from);
+ }
- Workspace_ptr workspace_from = view->mp_workspace;
- Output_ptr output_from = context_from->output();
+ view->mp_context = context_to;
Workspace_ptr workspace_to = context_to->workspace();
Output_ptr output_to = context_to->output();
@@ -535,15 +537,12 @@ Model::move_view_to_context(View_ptr view, Context_ptr context_to)
view->mp_output = output_to;
workspace_to->add_view(view);
- workspace_from->remove_view(view);
-
apply_layout(workspace_to);
- apply_layout(workspace_from);
- if (!output_to)
- unmap_view(view);
- else
+ if (output_to)
map_view(view);
+ else
+ unmap_view(view);
sync_focus();
}
@@ -562,18 +561,22 @@ Model::move_view_to_output(View_ptr view, Output_ptr output_to)
{
TRACE();
- Output_ptr output_from = view->mp_output;
+ Workspace_ptr workspace_from = view->mp_workspace;
- if (!output_to || output_to == output_from)
- return;
+ if (workspace_from) {
+ Context_ptr context_from = workspace_from->context();
+ Output_ptr output_from = context_from->output();
- if (output_from) {
- Workspace_ptr workspace_from = view->mp_workspace;
+ workspace_from->remove_view(view);
+ apply_layout(workspace_from);
+ wlr_surface_send_leave(view->mp_wlr_surface, output_from->mp_wlr_output);
+ }
- if (workspace_from) {
- workspace_from->remove_view(view);
- apply_layout(workspace_from);
- }
+ if (!output_to || !output_to->context()) {
+ view->mp_output = nullptr;
+ view->mp_context = nullptr;
+ view->mp_workspace = nullptr;
+ return;
}
Context_ptr context_to = output_to->context();
@@ -586,9 +589,6 @@ Model::move_view_to_output(View_ptr view, Output_ptr output_to)
workspace_to->add_view(view);
apply_layout(workspace_to);
- if (output_from)
- wlr_surface_send_leave(view->mp_wlr_surface, output_from->mp_wlr_output);
-
if (output_to) {
wlr_surface_send_enter(view->mp_wlr_surface, output_to->mp_wlr_output);
map_view(view);
@@ -684,9 +684,9 @@ Model::set_layout_retain_region(LayoutHandler::LayoutKind layout)
std::back_inserter(regions),
[=,this](View_ptr view) -> Region {
if (is_free(view))
- return view->m_free_region;
+ return view->free_region();
else
- return view->m_tile_region;
+ return view->tile_region();
}
);
}
@@ -854,8 +854,8 @@ Model::kill_view(View_ptr view)
{
TRACE();
- if (!view->m_invincible)
- view->kill();
+ if (!view->invincible())
+ view->close();
}
void
@@ -873,9 +873,9 @@ Model::set_floating_view(Toggle toggle, View_ptr view)
TRACE();
switch (toggle) {
- case Toggle::On: view->m_floating = true; break;
- case Toggle::Off: view->m_floating = false; break;
- case Toggle::Reverse: view->m_floating = !view->m_floating; break;
+ case Toggle::On: view->set_floating(true); break;
+ case Toggle::Off: view->set_floating(false); break;
+ case Toggle::Reverse: view->set_floating(!view->floating()); break;
default: return;
}
@@ -899,29 +899,29 @@ Model::set_fullscreen_view(Toggle toggle, View_ptr view)
switch (toggle) {
case Toggle::On:
{
- if (view->m_fullscreen)
+ if (view->fullscreen())
return;
- view->m_fullscreen = true;
+ view->set_fullscreen(true);
// TODO: set fullscreen state
Workspace_ptr workspace = view->mp_workspace;
apply_layout(workspace);
- m_fullscreen_map[view] = view->m_free_region;
+ m_fullscreen_map[view] = view->free_region();
return;
}
case Toggle::Off:
{
- if (!view->m_fullscreen)
+ if (!view->fullscreen())
return;
- if (!view->m_contained)
+ if (!view->contained())
view->set_free_region(m_fullscreen_map.at(view));
- view->m_fullscreen = false;
+ view->set_fullscreen(false);
// TODO: unset fullscreen state
@@ -935,7 +935,7 @@ Model::set_fullscreen_view(Toggle toggle, View_ptr view)
case Toggle::Reverse:
{
set_fullscreen_view(
- view->m_fullscreen
+ view->fullscreen()
? Toggle::Off
: Toggle::On,
view
@@ -964,10 +964,10 @@ Model::set_sticky_view(Toggle toggle, View_ptr view)
switch (toggle) {
case Toggle::On:
{
- if (view->m_sticky)
+ if (view->sticky())
return;
- if (view->m_iconified)
+ if (view->iconified())
set_iconify_view(Toggle::Off, view);
std::for_each(
@@ -990,7 +990,7 @@ Model::set_sticky_view(Toggle toggle, View_ptr view)
}
case Toggle::Off:
{
- if (!view->m_sticky)
+ if (!view->sticky())
return;
std::for_each(
@@ -1016,7 +1016,7 @@ Model::set_sticky_view(Toggle toggle, View_ptr view)
case Toggle::Reverse:
{
set_sticky_view(
- view->m_sticky
+ view->sticky()
? Toggle::Off
: Toggle::On,
view
@@ -1045,7 +1045,7 @@ Model::set_contained_view(Toggle toggle, View_ptr view)
switch (toggle) {
case Toggle::On:
{
- view->m_contained = true;
+ view->set_contained(true);
Workspace_ptr workspace = view->mp_workspace;
@@ -1054,7 +1054,7 @@ Model::set_contained_view(Toggle toggle, View_ptr view)
}
case Toggle::Off:
{
- view->m_contained = false;
+ view->set_contained(false);
Workspace_ptr workspace = view->mp_workspace;
@@ -1064,7 +1064,7 @@ Model::set_contained_view(Toggle toggle, View_ptr view)
case Toggle::Reverse:
{
set_contained_view(
- view->m_contained
+ view->contained()
? Toggle::Off
: Toggle::On,
view
@@ -1092,14 +1092,17 @@ Model::set_invincible_view(Toggle toggle, View_ptr view)
if (toggle == Toggle::Reverse)
set_invincible_view(
- view->m_invincible
+ view->invincible()
? Toggle::Off
: Toggle::On,
view
);
else
- view->m_invincible
- = toggle == Toggle::On ? true : false;
+ view->set_invincible(
+ toggle == Toggle::On
+ ? true
+ : false
+ );
}
void
@@ -1118,14 +1121,17 @@ Model::set_iconifyable_view(Toggle toggle, View_ptr view)
if (toggle == Toggle::Reverse)
set_iconifyable_view(
- view->m_iconifyable
+ view->iconifyable()
? Toggle::Off
: Toggle::On,
view
);
else
- view->m_iconifyable
- = toggle == Toggle::On ? true : false;
+ view->set_iconifyable(
+ toggle == Toggle::On
+ ? true
+ : false
+ );
}
void
@@ -1145,7 +1151,7 @@ Model::set_iconify_view(Toggle toggle, View_ptr view)
switch (toggle) {
case Toggle::On:
{
- if (view->m_iconified || view->m_sticky)
+ if (view->iconified() || view->sticky())
return;
Workspace_ptr workspace = view->mp_workspace;
@@ -1158,13 +1164,13 @@ Model::set_iconify_view(Toggle toggle, View_ptr view)
apply_layout(workspace);
sync_focus();
- view->m_iconified = true;
+ view->set_iconified(true);
return;
}
case Toggle::Off:
{
- if (!view->m_iconified)
+ if (!view->iconified())
return;
Workspace_ptr workspace = view->mp_workspace;
@@ -1172,7 +1178,7 @@ Model::set_iconify_view(Toggle toggle, View_ptr view)
// TODO: unset iconify state
- view->m_iconified = false;
+ view->set_iconified(false);
apply_layout(workspace);
sync_focus();
@@ -1182,7 +1188,7 @@ Model::set_iconify_view(Toggle toggle, View_ptr view)
case Toggle::Reverse:
{
set_iconify_view(
- view->m_iconified
+ view->iconified()
? Toggle::Off
: Toggle::On,
view
@@ -1211,7 +1217,7 @@ Model::center_view(View_ptr view)
if (!is_free(view))
return;
- Region region = view->m_free_region;
+ Region region = view->free_region();
const Region screen_region
= view->mp_context->output()->placeable_region();
@@ -1224,7 +1230,7 @@ Model::center_view(View_ptr view)
Placement placement = Placement {
Placement::PlacementMethod::Free,
view,
- view->m_free_decoration,
+ view->free_decoration(),
region
};
@@ -1248,7 +1254,7 @@ Model::nudge_view(Edge edge, Util::Change<std::size_t> change, View_ptr view)
if (!is_free(view))
return;
- Region region = view->m_free_region;
+ Region region = view->free_region();
switch (edge) {
case Edge::Left:
@@ -1277,7 +1283,7 @@ Model::nudge_view(Edge edge, Util::Change<std::size_t> change, View_ptr view)
Placement placement = Placement {
Placement::PlacementMethod::Free,
view,
- view->m_free_decoration,
+ view->free_decoration(),
region
};
@@ -1299,7 +1305,7 @@ Model::stretch_view(Edge edge, Util::Change<int> change, View_ptr view)
if (!is_free(view))
return;
- Decoration decoration = view->m_free_decoration;
+ Decoration decoration = view->free_decoration();
Extents extents = Extents { 0, 0, 0, 0 };
if (decoration.frame) {
@@ -1309,7 +1315,7 @@ Model::stretch_view(Edge edge, Util::Change<int> change, View_ptr view)
extents.bottom += decoration.frame->extents.bottom;
}
- Region region = view->m_free_region;
+ Region region = view->free_region();
region.remove_extents(extents);
switch (edge) {
@@ -1371,7 +1377,7 @@ Model::stretch_view(Edge edge, Util::Change<int> change, View_ptr view)
Placement placement = Placement {
Placement::PlacementMethod::Free,
view,
- view->m_free_decoration,
+ view->free_decoration(),
region
};
@@ -1395,7 +1401,7 @@ Model::inflate_view(Util::Change<int> change, View_ptr view)
if (!is_free(view))
return;
- Decoration decoration = view->m_free_decoration;
+ Decoration decoration = view->free_decoration();
Extents extents = Extents { 0, 0, 0, 0 };
if (decoration.frame) {
@@ -1405,7 +1411,7 @@ Model::inflate_view(Util::Change<int> change, View_ptr view)
extents.bottom += decoration.frame->extents.bottom;
}
- Region region = view->m_free_region;
+ Region region = view->free_region();
region.remove_extents(extents);
double ratio = static_cast<double>(region.dim.w)
@@ -1430,8 +1436,8 @@ Model::inflate_view(Util::Change<int> change, View_ptr view)
region.apply_extents(extents);
- int dx = region.dim.w - view->m_free_region.dim.w;
- int dy = region.dim.h - view->m_free_region.dim.h;
+ int dx = region.dim.w - view->free_region().dim.w;
+ int dy = region.dim.h - view->free_region().dim.h;
dx = std::lround(dx / static_cast<double>(2));
dy = std::lround(dy / static_cast<double>(2));
@@ -1444,7 +1450,7 @@ Model::inflate_view(Util::Change<int> change, View_ptr view)
Placement placement = Placement {
Placement::PlacementMethod::Free,
view,
- view->m_free_decoration,
+ view->free_decoration(),
region
};
@@ -1468,7 +1474,7 @@ Model::snap_view(Edge edge, View_ptr view)
if (!is_free(view))
return;
- Region region = view->m_free_region;
+ Region region = view->free_region();
const Region screen_region
= view->mp_context->output()->placeable_region();
@@ -1508,7 +1514,7 @@ Model::snap_view(Edge edge, View_ptr view)
Placement placement = Placement {
Placement::PlacementMethod::Free,
view,
- view->m_free_decoration,
+ view->free_decoration(),
region
};
@@ -1550,11 +1556,12 @@ Model::create_xdg_shell_view(
seat
);
- register_view(view);
+ m_view_map[view->m_uid] = view;
return view;
}
+#ifdef XWAYLAND
XWaylandView_ptr
Model::create_xwayland_view(
struct wlr_xwayland_surface* wlr_xwayland_surface,
@@ -1570,21 +1577,30 @@ Model::create_xwayland_view(
seat
);
- register_view(view);
+ m_view_map[view->m_uid] = view;
return view;
}
+#endif
void
Model::register_view(View_ptr view)
{
TRACE();
- m_view_map[view->m_uid] = view;
+ if (view->mp_workspace)
+ view->mp_workspace->add_view(view);
+
+ std::stringstream uid_ss;
+ uid_ss << std::hex << view->m_uid;
+ spdlog::info(
+ "Registered view 0x{} [{}, PID {}]",
+ uid_ss.str(),
+ view->m_title,
+ view->m_pid
+ );
- std::stringstream uid_stream;
- uid_stream << std::hex << view->m_uid;
- spdlog::info("Registered view 0x{}", uid_stream.str());
+ sync_focus();
}
void
@@ -1595,9 +1611,15 @@ Model::unregister_view(View_ptr view)
if (view->mp_workspace)
view->mp_workspace->remove_view(view);
- std::stringstream uid_stream;
- uid_stream << std::hex << view->m_uid;
- spdlog::info("Unegistered view 0x{}", uid_stream.str());
+ std::stringstream uid_ss;
+ uid_ss << std::hex << view->m_uid;
+ spdlog::info(
+ "Unregistered view 0x{} [{}, PID {}]",
+ uid_ss.str(),
+ view->m_title,
+ view->m_pid
+ );
+
sync_focus();
}
@@ -1606,21 +1628,26 @@ Model::destroy_view(View_ptr view)
{
TRACE();
- std::stringstream uid_stream;
- uid_stream << std::hex << view->m_uid;
-
m_view_map.erase(view->m_uid);
- delete view;
- spdlog::info("Destroyed view 0x{}", uid_stream.str());
+ std::stringstream uid_ss;
+ uid_ss << std::hex << view->m_uid;
+ spdlog::info(
+ "Destroyed view 0x{} [{}, PID {}]",
+ uid_ss.str(),
+ view->m_title,
+ view->m_pid
+ );
+
+ delete view;
}
bool
Model::is_free(View_ptr view) const
{
return View::is_free(view)
- || ((!view->m_fullscreen || view->m_contained)
- && (view->m_sticky
+ || ((!view->fullscreen() || view->contained())
+ && (view->sticky()
? mp_workspace
: view->mp_workspace
)->layout_is_free());
diff --git a/src/kranewl/server.cc b/src/kranewl/server.cc
@@ -385,9 +385,10 @@ Server::handle_new_xdg_surface(struct wl_listener* listener, void* data)
if (!(view = view_from_popup(xdg_surface->popup)) || !view->mp_output)
return;
+ Region const& active_region = view->active_region();
mappable_box = view->mp_output->placeable_region();
- mappable_box.x -= view->m_active_region.pos.x;
- mappable_box.y -= view->m_active_region.pos.y;
+ mappable_box.x -= active_region.pos.x;
+ mappable_box.y -= active_region.pos.y;
wlr_xdg_popup_unconstrain_from_box(xdg_surface->popup, &mappable_box);
diff --git a/src/kranewl/tree/view.cc b/src/kranewl/tree/view.cc
@@ -28,12 +28,7 @@ View::View(
Server_ptr server,
Model_ptr model,
Seat_ptr seat,
- struct wlr_surface* wlr_surface,
- void(*handle_foreign_activate_request)(wl_listener*, void*),
- void(*handle_foreign_fullscreen_request)(wl_listener*, void*),
- void(*handle_foreign_close_request)(wl_listener*, void*),
- void(*handle_foreign_destroy)(wl_listener*, void*),
- void(*handle_surface_new_subsurface)(wl_listener*, void*)
+ struct wlr_surface* wlr_surface
)
: m_uid(uid),
m_type(Type::XDGShell),
@@ -45,6 +40,7 @@ View::View(
mp_workspace(nullptr),
mp_wlr_surface(wlr_surface),
m_alpha(1.f),
+ m_resize(0),
m_tile_decoration(FREE_DECORATION),
m_free_decoration(FREE_DECORATION),
m_active_decoration(FREE_DECORATION),
@@ -71,11 +67,7 @@ View::View(
m_last_focused(std::chrono::steady_clock::now()),
m_last_touched(std::chrono::steady_clock::now()),
m_managed_since(std::chrono::steady_clock::now()),
- ml_foreign_activate_request({ .notify = handle_foreign_activate_request }),
- ml_foreign_fullscreen_request({ .notify = handle_foreign_fullscreen_request }),
- ml_foreign_close_request({ .notify = handle_foreign_close_request }),
- ml_foreign_destroy({ .notify = handle_foreign_destroy }),
- ml_surface_new_subsurface({ .notify = handle_surface_new_subsurface })
+ m_outside_state(OutsideState::Unfocused)
{
wl_signal_init(&m_events.unmap);
}
@@ -87,128 +79,248 @@ View::View(
Server_ptr server,
Model_ptr model,
Seat_ptr seat,
- struct wlr_surface* wlr_surface,
- void(*handle_foreign_activate_request)(wl_listener*, void*),
- void(*handle_foreign_fullscreen_request)(wl_listener*, void*),
- void(*handle_foreign_close_request)(wl_listener*, void*),
- void(*handle_foreign_destroy)(wl_listener*, void*),
- void(*handle_surface_new_subsurface)(wl_listener*, void*)
+ struct wlr_surface* wlr_surface
)
: m_uid(uid),
m_type(Type::XWayland),
mp_server(server),
mp_model(model),
mp_seat(seat),
+ mp_output(nullptr),
+ mp_context(nullptr),
+ mp_workspace(nullptr),
mp_wlr_surface(wlr_surface),
- m_tile_decoration({}, DEFAULT_COLOR_SCHEME),
- m_free_decoration({}, DEFAULT_COLOR_SCHEME),
- m_active_decoration({}, DEFAULT_COLOR_SCHEME),
- ml_foreign_activate_request({ .notify = handle_foreign_activate_request }),
- ml_foreign_fullscreen_request({ .notify = handle_foreign_fullscreen_request }),
- ml_foreign_close_request({ .notify = handle_foreign_close_request }),
- ml_foreign_destroy({ .notify = handle_foreign_destroy }),
- ml_surface_new_subsurface({ .notify = handle_surface_new_subsurface })
-{}
+ m_alpha(1.f),
+ m_resize(0),
+ m_tile_decoration(FREE_DECORATION),
+ m_free_decoration(FREE_DECORATION),
+ m_active_decoration(FREE_DECORATION),
+ m_minimum_dim({}),
+ m_preferred_dim({}),
+ m_free_region({}),
+ m_tile_region({}),
+ m_active_region({}),
+ m_previous_region({}),
+ m_inner_region({}),
+ m_focused(false),
+ m_mapped(false),
+ m_managed(true),
+ m_urgent(false),
+ m_floating(false),
+ m_fullscreen(false),
+ m_scratchpad(false),
+ m_contained(false),
+ m_invincible(false),
+ m_sticky(false),
+ m_iconifyable(true),
+ m_iconified(false),
+ m_disowned(false),
+ m_last_focused(std::chrono::steady_clock::now()),
+ m_last_touched(std::chrono::steady_clock::now()),
+ m_managed_since(std::chrono::steady_clock::now())
+{
+ wl_signal_init(&m_events.unmap);
+}
#endif
View::~View()
{}
-static inline void
-set_view_pid(View_ptr view)
+void
+View::set_focused(bool focused)
{
- switch (view->m_type) {
- case View::Type::XDGShell:
- {
- pid_t pid;
- struct wl_client* client
- = wl_resource_get_client(view->mp_wlr_surface->resource);
+ auto now = std::chrono::steady_clock::now();
+ m_last_touched = now;
+ m_last_focused = now;
+ m_focused = focused;
+
+ switch (focused) {
+ case true:
+ switch (m_outside_state) {
+ case OutsideState::Unfocused: m_outside_state = OutsideState::Focused; return;
+ case OutsideState::UnfocusedDisowned: m_outside_state = OutsideState::FocusedDisowned; return;
+ case OutsideState::UnfocusedSticky: m_outside_state = OutsideState::FocusedSticky; return;
+ default: return;
+ }
+ case false:
+ switch (m_outside_state) {
+ case OutsideState::Focused: m_outside_state = OutsideState::Unfocused; return;
+ case OutsideState::FocusedDisowned: m_outside_state = OutsideState::UnfocusedDisowned; return;
+ case OutsideState::FocusedSticky: m_outside_state = OutsideState::UnfocusedSticky; return;
+ default: return;
+ }
+ }
+}
- wl_client_get_credentials(client, &pid, nullptr, nullptr);
- view->m_pid = pid;
+void
+View::set_mapped(bool mapped)
+{
+ m_mapped = mapped;
+}
- break;
- }
-#if HAVE_XWAYLAND
- case View::Type::XWayland:
- {
- struct wlr_xwayland_surface* wlr_xwayland_surface
- = wlr_xwayland_surface_from_wlr_surface(view->mp_wlr_surface);
- view->m_pid = wlr_xwayland_surface->pid;
+void
+View::set_managed(bool managed)
+{
+ m_managed = managed;
+}
- break;
- }
-#endif
- default: break;
- }
+void
+View::set_urgent(bool urgent)
+{
+ m_urgent = urgent;
}
void
-View::map(
- struct wlr_surface* wlr_surface,
- bool fullscreen,
- struct wlr_output* fullscreen_output,
- bool decorations
-)
+View::set_floating(bool floating)
{
- TRACE();
+ m_floating = floating;
+}
- Server_ptr server = mp_server;
- Model_ptr model = mp_model;
-
- mp_wlr_surface = wlr_surface;
- set_view_pid(this);
-
- mp_scene = &wlr_scene_tree_create(mp_server->m_layers[Layer::Tile])->node;
- mp_wlr_surface->data = mp_scene_surface = m_type == View::Type::XDGShell
- ? wlr_scene_xdg_surface_create(
- mp_scene,
- reinterpret_cast<XDGView_ptr>(this)->mp_wlr_xdg_surface
- )
- : wlr_scene_subsurface_tree_create(mp_scene, mp_wlr_surface);
- mp_scene_surface->data = this;
-
- wlr_scene_node_reparent(
- mp_scene,
- server->m_layers[m_floating ? Layer::Free : Layer::Tile]
- );
-
- for (std::size_t i = 0; i < 4; ++i) {
- m_protrusions[i] = wlr_scene_rect_create(
- mp_scene,
- 0,
- 0,
- m_active_decoration.colorscheme.unfocused.values
- );
- m_protrusions[i]->node.data = this;
- wlr_scene_rect_set_color(
- m_protrusions[i],
- m_active_decoration.colorscheme.unfocused.values
- );
- wlr_scene_node_lower_to_bottom(&m_protrusions[i]->node);
- }
+void
+View::set_fullscreen(bool fullscreen)
+{
+ m_fullscreen = fullscreen;
+}
- if (fullscreen_output && fullscreen_output->data) {
- Output_ptr output = reinterpret_cast<Output_ptr>(fullscreen_output->data);
+void
+View::set_scratchpad(bool scratchpad)
+{
+ m_scratchpad = scratchpad;
+}
+
+void
+View::set_contained(bool contained)
+{
+ m_contained = contained;
+}
+
+void
+View::set_invincible(bool invincible)
+{
+ m_invincible = invincible;
+}
+
+void
+View::set_sticky(bool sticky)
+{
+ m_sticky = sticky;
+
+ switch (sticky) {
+ case true:
+ switch (m_outside_state) {
+ case OutsideState::Focused: m_outside_state = OutsideState::FocusedSticky; return;
+ case OutsideState::Unfocused: m_outside_state = OutsideState::UnfocusedSticky; return;
+ default: return;
+ }
+ case false:
+ switch (m_outside_state) {
+ case OutsideState::FocusedSticky: m_outside_state = OutsideState::Focused; return;
+ case OutsideState::UnfocusedSticky: m_outside_state = OutsideState::Unfocused; return;
+ default: return;
+ }
}
+}
- model->move_view_to_focused_output(this);
- focus(true);
+void
+View::set_iconifyable(bool iconifyable)
+{
+ m_iconifyable = iconifyable;
}
void
-View::unmap()
+View::set_iconified(bool iconified)
{
- TRACE();
+ m_iconified = iconified;
+}
- wlr_scene_node_destroy(mp_scene);
- mp_wlr_surface = nullptr;
+void
+View::set_disowned(bool disowned)
+{
+ m_disowned = disowned;
+
+ switch (disowned) {
+ case true:
+ switch (m_outside_state) {
+ case OutsideState::Focused: m_outside_state = OutsideState::FocusedDisowned; return;
+ case OutsideState::Unfocused: m_outside_state = OutsideState::UnfocusedDisowned; return;
+ default: return;
+ }
+ case false:
+ switch (m_outside_state) {
+ case OutsideState::FocusedDisowned: m_outside_state = OutsideState::Focused; return;
+ case OutsideState::UnfocusedDisowned: m_outside_state = OutsideState::Unfocused; return;
+ default: return;
+ }
+ }
}
void
-View::touch()
+View::render_decoration()
{
- m_last_touched = std::chrono::steady_clock::now();
+ TRACE();
+
+ Decoration const& decoration = m_active_decoration;
+ ColorScheme const& colorscheme = decoration.colorscheme;
+ const float* colors = nullptr;
+
+ switch (outside_state()) {
+ case OutsideState::Focused:
+ {
+ if (decoration.frame)
+ colors = colorscheme.focused.values;
+
+ break;
+ }
+ case OutsideState::FocusedDisowned:
+ {
+ if (decoration.frame)
+ colors = colorscheme.fdisowned.values;
+
+ break;
+ }
+ case OutsideState::FocusedSticky:
+ {
+ if (decoration.frame)
+ colors = colorscheme.fsticky.values;
+
+ break;
+ }
+ case OutsideState::Unfocused:
+ {
+ if (decoration.frame)
+ colors = colorscheme.unfocused.values;
+
+ break;
+ }
+ case OutsideState::UnfocusedDisowned:
+ {
+ if (decoration.frame)
+ colors = colorscheme.udisowned.values;
+
+ break;
+ }
+ case OutsideState::UnfocusedSticky:
+ {
+ if (decoration.frame)
+ colors = colorscheme.usticky.values;
+
+ break;
+ }
+ case OutsideState::Urgent:
+ {
+ if (decoration.frame)
+ colors = colorscheme.urgent.values;
+
+ break;
+ }
+ }
+
+ if (decoration.frame)
+ for (std::size_t i = 0; i < 4; ++i)
+ wlr_scene_rect_set_color(
+ m_protrusions[i],
+ colors
+ );
}
static uint32_t
@@ -271,6 +383,15 @@ View::set_tile_decoration(Decoration const& decoration)
m_active_decoration = decoration;
}
+View::OutsideState
+View::outside_state() const
+{
+ if (m_urgent)
+ return OutsideState::Urgent;
+
+ return m_outside_state;
+}
+
void
View::set_active_region(Region const& region)
{
diff --git a/src/kranewl/tree/xdg_view.cc b/src/kranewl/tree/xdg_view.cc
@@ -1,9 +1,13 @@
#include <trace.hh>
+#include <kranewl/context.hh>
#include <kranewl/layers.hh>
+#include <kranewl/model.hh>
#include <kranewl/server.hh>
+#include <kranewl/tree/output.hh>
#include <kranewl/tree/view.hh>
#include <kranewl/tree/xdg_view.hh>
+#include <kranewl/workspace.hh>
// https://github.com/swaywm/wlroots/issues/682
#include <pthread.h>
@@ -33,12 +37,7 @@ XDGView::XDGView(
server,
model,
seat,
- wlr_xdg_surface->surface,
- XDGView::handle_foreign_activate_request,
- XDGView::handle_foreign_fullscreen_request,
- XDGView::handle_foreign_close_request,
- XDGView::handle_foreign_destroy,
- XDGView::handle_surface_new_subsurface
+ wlr_xdg_surface->toplevel->base->surface
),
mp_wlr_xdg_surface(wlr_xdg_surface),
mp_wlr_xdg_toplevel(wlr_xdg_surface->toplevel),
@@ -61,147 +60,148 @@ XDGView::XDGView(
XDGView::~XDGView()
{}
-void
-XDGView::focus(bool raise)
+Region
+XDGView::constraints()
{
TRACE();
- struct wlr_surface* prev_focus
- = mp_seat->mp_wlr_seat->keyboard_state.focused_surface;
+}
- if (raise)
- wlr_scene_node_raise_to_top(mp_scene);
+pid_t
+XDGView::pid()
+{
+ TRACE();
- if (prev_focus == mp_wlr_surface)
- return;
+ pid_t pid;
+ struct wl_client* client
+ = wl_resource_get_client(mp_wlr_surface->resource);
- mp_model->focus_view(this);
+ wl_client_get_credentials(client, &pid, nullptr, nullptr);
+ return pid;
+}
- for (std::size_t i = 0; i < 4; ++i)
- wlr_scene_rect_set_color(
- m_protrusions[i],
- m_active_decoration.colorscheme.focused.values
- );
+bool
+XDGView::prefers_floating()
+{
+ TRACE();
- if (prev_focus && prev_focus != mp_wlr_surface) {
- if (wlr_surface_is_layer_surface(prev_focus)) {
- struct wlr_layer_surface_v1* wlr_layer_surface
- = wlr_layer_surface_v1_from_wlr_surface(prev_focus);
-
- if (wlr_layer_surface->mapped && (
- wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP ||
- wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY))
- {
- return;
- }
- } else {
- View_ptr prev_view;
- struct wlr_scene_node* node
- = reinterpret_cast<struct wlr_scene_node*>(prev_focus->data);
-
- if (prev_focus->role_data && (prev_view = reinterpret_cast<View_ptr>(node->data)))
- for (std::size_t i = 0; i < 4; ++i)
- wlr_scene_rect_set_color(
- prev_view->m_protrusions[i],
- m_active_decoration.colorscheme.unfocused.values
- );
-
- struct wlr_xdg_surface* wlr_xdg_surface;
- if (wlr_surface_is_xdg_surface(prev_focus)
- && (wlr_xdg_surface = wlr_xdg_surface_from_wlr_surface(prev_focus))
- && wlr_xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL)
- {
- wlr_xdg_toplevel_set_activated(wlr_xdg_surface, false);
- }
- }
- }
+ struct wlr_xdg_toplevel_state *state = &mp_wlr_xdg_toplevel->current;
+ return mp_wlr_xdg_toplevel->parent || (state->min_width != 0 && state->min_height != 0
+ && (state->min_width == state->max_width || state->min_height == state->max_height));
+}
- wlr_idle_set_enabled(
- mp_seat->mp_idle,
- mp_seat->mp_wlr_seat,
- wl_list_empty(&mp_seat->mp_idle_inhibit_manager->inhibitors)
- );
+View_ptr
+XDGView::is_transient_for()
+{
+ TRACE();
- struct wlr_keyboard* keyboard = wlr_seat_get_keyboard(mp_seat->mp_wlr_seat);
- if (keyboard)
- wlr_seat_keyboard_notify_enter(
- mp_seat->mp_wlr_seat,
- mp_wlr_surface,
- keyboard->keycodes,
- keyboard->num_keycodes,
- &keyboard->modifiers
- );
- else
- wlr_seat_keyboard_notify_enter(
- mp_seat->mp_wlr_seat,
- mp_wlr_surface,
- nullptr,
- 0,
- nullptr
- );
+}
+
+void
+XDGView::map()
+{
+ TRACE();
- wlr_xdg_toplevel_set_activated(mp_wlr_xdg_surface, true);
}
void
-XDGView::moveresize(Region const& region, Extents const& extents, bool interactive)
+XDGView::unmap()
{
TRACE();
- wlr_scene_node_set_position(mp_scene, region.pos.x, region.pos.y);
- wlr_scene_node_set_position(mp_scene_surface, extents.left, extents.top);
- wlr_scene_rect_set_size(m_protrusions[0], region.dim.w, extents.top);
- wlr_scene_rect_set_size(m_protrusions[1], region.dim.w, extents.bottom);
- wlr_scene_rect_set_size(m_protrusions[2], extents.left, region.dim.h - extents.top - extents.bottom);
- wlr_scene_rect_set_size(m_protrusions[3], extents.right, region.dim.h - extents.top - extents.bottom);
- wlr_scene_node_set_position(&m_protrusions[0]->node, 0, 0);
- wlr_scene_node_set_position(&m_protrusions[1]->node, 0, region.dim.h - extents.bottom);
- wlr_scene_node_set_position(&m_protrusions[2]->node, 0, extents.top);
- wlr_scene_node_set_position(&m_protrusions[3]->node, region.dim.w - extents.right, extents.top);
+}
- m_resize = wlr_xdg_toplevel_set_size(
- mp_wlr_xdg_surface,
- region.dim.w - extents.left - extents.right,
- region.dim.h - extents.top - extents.bottom
- );
+void
+XDGView::activate(Toggle toggle)
+{
+ TRACE();
+
+ switch (toggle) {
+ case Toggle::On:
+ {
+ wlr_xdg_toplevel_set_activated(mp_wlr_xdg_surface, true);
+ set_focused(true);
+ break;
+ }
+ case Toggle::Off:
+ {
+ wlr_xdg_toplevel_set_activated(mp_wlr_xdg_surface, false);
+ set_focused(false);
+ break;
+ }
+ case Toggle::Reverse:
+ {
+ activate(
+ focused()
+ ? Toggle::Off
+ : Toggle::On
+ );
+ return;
+ }
+ default: break;
+ }
}
void
-XDGView::kill()
+XDGView::set_tiled(Toggle)
{
- wlr_xdg_toplevel_send_close(mp_wlr_xdg_surface);
+ TRACE();
+
}
void
-XDGView::handle_foreign_activate_request(struct wl_listener* listener, void* data)
+XDGView::set_fullscreen(Toggle)
{
TRACE();
}
void
-XDGView::handle_foreign_fullscreen_request(struct wl_listener* listener, void* data)
+XDGView::set_resizing(Toggle)
{
TRACE();
}
void
-XDGView::handle_foreign_close_request(struct wl_listener* listener, void* data)
+XDGView::configure(Region const& region, Extents const& extents, bool interactive)
{
TRACE();
+ wlr_scene_node_set_position(mp_scene, region.pos.x, region.pos.y);
+ wlr_scene_node_set_position(mp_scene_surface, extents.left, extents.top);
+ wlr_scene_rect_set_size(m_protrusions[0], region.dim.w, extents.top);
+ wlr_scene_rect_set_size(m_protrusions[1], region.dim.w, extents.bottom);
+ wlr_scene_rect_set_size(m_protrusions[2], extents.left, region.dim.h - extents.top - extents.bottom);
+ wlr_scene_rect_set_size(m_protrusions[3], extents.right, region.dim.h - extents.top - extents.bottom);
+ wlr_scene_node_set_position(&m_protrusions[0]->node, 0, 0);
+ wlr_scene_node_set_position(&m_protrusions[1]->node, 0, region.dim.h - extents.bottom);
+ wlr_scene_node_set_position(&m_protrusions[2]->node, 0, extents.top);
+ wlr_scene_node_set_position(&m_protrusions[3]->node, region.dim.w - extents.right, extents.top);
+
+ m_resize = wlr_xdg_toplevel_set_size(
+ mp_wlr_xdg_surface,
+ region.dim.w - extents.left - extents.right,
+ region.dim.h - extents.top - extents.bottom
+ );
+}
+
+void
+XDGView::close()
+{
+ TRACE();
+ wlr_xdg_toplevel_send_close(mp_wlr_xdg_surface);
}
void
-XDGView::handle_foreign_destroy(struct wl_listener* listener, void* data)
+XDGView::close_popups()
{
TRACE();
}
void
-XDGView::handle_surface_new_subsurface(struct wl_listener* listener, void* data)
+XDGView::destroy()
{
TRACE();
@@ -271,36 +271,44 @@ XDGView::handle_map(struct wl_listener* listener, void* data)
TRACE();
XDGView_ptr view = wl_container_of(listener, view, ml_map);
+ Server_ptr server = view->mp_server;
+ Model_ptr model = view->mp_model;
+
+ view->m_pid = view->pid();
+ view->set_floating(view->prefers_floating());
+
struct wlr_xdg_surface* wlr_xdg_surface = view->mp_wlr_xdg_surface;
struct wlr_xdg_toplevel* wlr_xdg_toplevel = view->mp_wlr_xdg_toplevel;
- view->m_mapped = true;
- view->m_preferred_dim = Dim{
+ Dim preferred_dim = Dim{
.w = wlr_xdg_toplevel->base->current.geometry.width,
.h = wlr_xdg_toplevel->base->current.geometry.height,
};
- if (!view->m_preferred_dim.w && !view->m_preferred_dim.h) {
- view->m_preferred_dim.w = wlr_xdg_toplevel->base->surface->current.width;
- view->m_preferred_dim.h = wlr_xdg_toplevel->base->surface->current.height;
+ if (!preferred_dim.w && !preferred_dim.h) {
+ preferred_dim.w = wlr_xdg_toplevel->base->surface->current.width;
+ preferred_dim.h = wlr_xdg_toplevel->base->surface->current.height;
}
- view->mp_wlr_surface = wlr_xdg_toplevel->base->surface;
+ Extents const& extents = view->free_decoration().extents();
+ preferred_dim.w += extents.left + extents.right;
+ preferred_dim.h += extents.top + extents.bottom;
+ view->set_preferred_dim(preferred_dim);
- Extents const& extents = view->m_free_decoration.extents();
- struct wlr_box geometry;
- wlr_xdg_surface_get_geometry(wlr_xdg_surface, &geometry);
- view->m_preferred_dim.w = extents.left + extents.right + geometry.width;
- view->m_preferred_dim.h = extents.top + extents.bottom + geometry.height;
+ struct wlr_xdg_toplevel_state* state = &wlr_xdg_toplevel->current;
+ view->set_minimum_dim(Dim{
+ .w = state->min_width,
+ .h = state->min_height
+ });
view->set_free_region(Region{
- .pos = {0, 0},
- .dim = view->m_preferred_dim
+ .pos = Pos{0, 0},
+ .dim = preferred_dim
});
view->set_tile_region(Region{
- .pos = {0, 0},
- .dim = view->m_preferred_dim
+ .pos = Pos{0, 0},
+ .dim = preferred_dim
});
view->m_app_id = wlr_xdg_toplevel->app_id
@@ -311,29 +319,37 @@ XDGView::handle_map(struct wl_listener* listener, void* data)
: "N/a";
view->m_title_formatted = view->m_title; // TODO: format title
- struct wlr_xdg_toplevel_state state = wlr_xdg_toplevel->current;
- view->m_floating = wlr_xdg_toplevel->parent
- || (state.min_width != 0 && state.min_height != 0
- && (state.min_width == state.max_width || state.min_height == state.max_height));
-
- view->m_minimum_dim = Dim{
- .w = state.min_width,
- .h = state.min_height
- };
-
- view->map(
- wlr_xdg_toplevel->base->surface,
- wlr_xdg_toplevel->requested.fullscreen,
- wlr_xdg_toplevel->requested.fullscreen_output,
- false // TODO: determine if client has decorations
- );
-
wlr_xdg_toplevel_set_tiled(
wlr_xdg_surface,
- // TODO: determine from view decorations
view->free_decoration_to_wlr_edges()
);
+ view->mp_scene = &wlr_scene_tree_create(server->m_layers[Layer::Tile])->node;
+ view->mp_wlr_surface->data = view->mp_scene_surface = wlr_scene_xdg_surface_create(
+ view->mp_scene,
+ view->mp_wlr_xdg_surface
+ );
+ view->mp_scene_surface->data = view;
+
+ wlr_scene_node_reparent(
+ view->mp_scene,
+ server->m_layers[view->floating() ? Layer::Free : Layer::Tile]
+ );
+
+ for (std::size_t i = 0; i < 4; ++i) {
+ view->m_protrusions[i] = wlr_scene_rect_create(
+ view->mp_scene,
+ 0, 0,
+ view->active_decoration().colorscheme.unfocused.values
+ );
+ view->m_protrusions[i]->node.data = view;
+ wlr_scene_rect_set_color(
+ view->m_protrusions[i],
+ view->active_decoration().colorscheme.unfocused.values
+ );
+ wlr_scene_node_lower_to_bottom(&view->m_protrusions[i]->node);
+ }
+
wl_signal_add(&wlr_xdg_toplevel->base->surface->events.commit, &view->ml_commit);
wl_signal_add(&wlr_xdg_toplevel->base->events.new_popup, &view->ml_new_popup);
wl_signal_add(&wlr_xdg_toplevel->events.request_fullscreen, &view->ml_request_fullscreen);
@@ -341,6 +357,26 @@ XDGView::handle_map(struct wl_listener* listener, void* data)
wl_signal_add(&wlr_xdg_toplevel->events.request_resize, &view->ml_request_resize);
wl_signal_add(&wlr_xdg_toplevel->events.set_title, &view->ml_set_title);
wl_signal_add(&wlr_xdg_toplevel->events.set_app_id, &view->ml_set_app_id);
+
+ Workspace_ptr workspace;
+
+ if (wlr_xdg_toplevel->requested.fullscreen
+ && wlr_xdg_toplevel->requested.fullscreen_output->data)
+ {
+ Output_ptr output = reinterpret_cast<Output_ptr>(
+ wlr_xdg_toplevel->requested.fullscreen_output->data
+ );
+
+ Context_ptr context = output->context();
+ workspace = context->workspace();
+ } else
+ workspace = model->mp_workspace;
+
+ model->move_view_to_workspace(view, workspace);
+
+ view->set_mapped(true);
+ view->render_decoration();
+ model->register_view(view);
}
void
@@ -350,8 +386,6 @@ XDGView::handle_unmap(struct wl_listener* listener, void* data)
XDGView_ptr view = wl_container_of(listener, view, ml_unmap);
- view->mp_model->unmap_view(view);
-
wl_list_remove(&view->ml_commit.link);
wl_list_remove(&view->ml_new_popup.link);
wl_list_remove(&view->ml_request_fullscreen.link);
@@ -360,8 +394,11 @@ XDGView::handle_unmap(struct wl_listener* listener, void* data)
wl_list_remove(&view->ml_set_title.link);
wl_list_remove(&view->ml_set_app_id.link);
- view->unmap();
view->mp_model->unregister_view(view);
+
+ wlr_scene_node_destroy(view->mp_scene);
+ view->mp_wlr_surface = nullptr;
+ view->set_managed(false);
}
void
@@ -374,10 +411,9 @@ XDGView::handle_destroy(struct wl_listener* listener, void* data)
wl_list_remove(&view->ml_map.link);
wl_list_remove(&view->ml_unmap.link);
wl_list_remove(&view->ml_destroy.link);
+ wl_list_remove(&view->m_events.unmap.listener_list);
view->mp_wlr_xdg_toplevel = nullptr;
view->mp_wlr_xdg_surface = nullptr;
view->mp_model->destroy_view(view);
-
- wl_list_remove(&view->m_events.unmap.listener_list);
}
diff --git a/src/kranewl/tree/xwayland_view.cc b/src/kranewl/tree/xwayland_view.cc
@@ -28,12 +28,7 @@ XWaylandView::XWaylandView(
server,
model,
seat,
- wlr_xwayland_surface->surface,
- XWaylandView::handle_foreign_activate_request,
- XWaylandView::handle_foreign_fullscreen_request,
- XWaylandView::handle_foreign_close_request,
- XWaylandView::handle_foreign_destroy,
- XWaylandView::handle_surface_new_subsurface
+ wlr_xwayland_surface->surface
),
mp_wlr_xwayland_surface(wlr_xwayland_surface),
ml_commit({ .notify = XWaylandView::handle_commit }),
@@ -59,61 +54,102 @@ XWaylandView::XWaylandView(
XWaylandView::~XWaylandView()
{}
+Region
+XWaylandView::constraints()
+{
+ TRACE();
+
+}
+
+pid_t
+XWaylandView::pid()
+{
+ TRACE();
+
+ struct wlr_xwayland_surface* wlr_xwayland_surface
+ = wlr_xwayland_surface_from_wlr_surface(mp_wlr_surface);
+ return wlr_xwayland_surface->pid;
+}
+
+bool
+XWaylandView::prefers_floating()
+{
+ TRACE();
+
+}
+
+View_ptr
+XWaylandView::is_transient_for()
+{
+ TRACE();
+
+}
+
void
-XWaylandView::focus(bool raise)
-{}
+XWaylandView::map()
+{
+ TRACE();
+
+}
void
-XWaylandView::moveresize(Region const& region, Extents const& extents, bool interactive)
+XWaylandView::unmap()
{
TRACE();
}
void
-XWaylandView::kill()
+XWaylandView::activate(Toggle)
{
TRACE();
}
-XWaylandUnmanaged::XWaylandUnmanaged(struct wlr_xwayland_surface* wlr_xwayland_surface)
- : mp_wlr_xwayland_surface(wlr_xwayland_surface)
-{}
+void
+XWaylandView::set_tiled(Toggle)
+{
+ TRACE();
-XWaylandUnmanaged::~XWaylandUnmanaged()
-{}
+}
void
-XWaylandView::handle_foreign_activate_request(struct wl_listener* listener, void* data)
+XWaylandView::set_fullscreen(Toggle)
{
TRACE();
}
void
-XWaylandView::handle_foreign_fullscreen_request(struct wl_listener* listener, void* data)
+XWaylandView::set_resizing(Toggle)
{
TRACE();
}
void
-XWaylandView::handle_foreign_close_request(struct wl_listener* listener, void* data)
+XWaylandView::configure(Region const& region, Extents const& extents, bool interactive)
{
TRACE();
}
void
-XWaylandView::handle_foreign_destroy(struct wl_listener* listener, void* data)
+XWaylandView::close()
{
TRACE();
}
void
-XWaylandView::handle_surface_new_subsurface(struct wl_listener* listener, void* data)
+XWaylandView::close_popups()
+{
+ TRACE();
+
+}
+
+void
+XWaylandView::destroy()
{
TRACE();
@@ -244,4 +280,11 @@ XWaylandView::handle_override_redirect(struct wl_listener* listener, void* data)
TRACE();
}
+
+XWaylandUnmanaged::XWaylandUnmanaged(struct wlr_xwayland_surface* wlr_xwayland_surface)
+ : mp_wlr_xwayland_surface(wlr_xwayland_surface)
+{}
+
+XWaylandUnmanaged::~XWaylandUnmanaged()
+{}
#endif
diff --git a/src/kranewl/workspace.cc b/src/kranewl/workspace.cc
@@ -476,7 +476,7 @@ Workspace::arrange(Region region) const
views.begin(),
views.end(),
[](const View_ptr view) -> bool {
- return view->m_fullscreen && !view->m_contained;
+ return view->fullscreen() && !view->contained();
}
);
@@ -511,7 +511,7 @@ Workspace::arrange(Region region) const
Placement::PlacementMethod::Free,
view,
FREE_DECORATION,
- view->m_free_region
+ view->free_region()
};
}
);
@@ -528,7 +528,7 @@ Workspace::arrange(Region region) const
placements.begin(),
placements.end(),
[](Placement& placement) {
- if (!placement.view->m_focused)
+ if (!placement.view->focused())
placement.region = std::nullopt;
}
);