11#include " wayfire/signal-provider.hpp"
22#include " wayfire/toplevel-view.hpp"
3+ #include " wayfire/txn/transaction-manager.hpp"
34#include < wayfire/per-output-plugin.hpp>
45#include < wayfire/view.hpp>
56#include < wayfire/core.hpp>
67#include < wayfire/workarea.hpp>
78#include < wayfire/window-manager.hpp>
89#include < wayfire/signal-definitions.hpp>
910
10- class wayfire_place_window : public wf ::per_output_plugin_instance_t
11+ class wayfire_place_cascade_data : public wf ::custom_data_t
1112{
12- wf::signal::connection_t <wf::view_mapped_signal> on_view_mapped = [=] (wf::view_mapped_signal *ev)
13+ public:
14+ int x = 0 ;
15+ int y = 0 ;
16+ };
17+
18+ class wayfire_place_window : public wf ::plugin_interface_t
19+ {
20+ wf::signal::connection_t <wf::txn::new_transaction_signal> on_new_tx =
21+ [=] (wf::txn::new_transaction_signal *ev)
1322 {
14- auto toplevel = wf::toplevel_cast (ev->view );
23+ // For each transaction, we need to consider what happens with participating views
24+ for (const auto & obj : ev->tx ->get_objects ())
25+ {
26+ auto toplevel = std::dynamic_pointer_cast<wf::toplevel_t >(obj);
27+ if (!toplevel || !map_pending (toplevel))
28+ {
29+ continue ;
30+ }
31+
32+ auto view = wf::find_view_for_toplevel (toplevel);
33+ if (!view || !should_place (view))
34+ {
35+ continue ;
36+ }
37+ }
38+ };
1539
16- if (!toplevel || toplevel->parent || toplevel->pending_fullscreen () ||
17- toplevel->pending_tiled_edges () || ev->is_positioned )
40+ bool map_pending (std::shared_ptr<wf::toplevel_t > toplevel)
41+ {
42+ return !toplevel->current ().mapped && toplevel->pending ().mapped ;
43+ }
44+
45+ bool should_place (wayfire_toplevel_view toplevel)
46+ {
47+ if (toplevel->parent )
1848 {
19- return ;
49+ return false ;
50+ }
51+
52+ if (toplevel->pending_fullscreen () || toplevel->pending_tiled_edges ())
53+ {
54+ return false ;
55+ }
56+
57+ if (toplevel->has_property (" startup-x" ) || toplevel->has_property (" startup-y" ))
58+ {
59+ return false ;
2060 }
2161
22- ev->is_positioned = true ;
62+ if (!toplevel->get_output ())
63+ {
64+ return false ;
65+ }
66+
67+ return true ;
68+ }
69+
70+ void do_place (wayfire_toplevel_view view)
71+ {
72+ auto output = view->get_output ();
2373 auto workarea = output->workarea ->get_workarea ();
2474
2575 std::string mode = placement_mode;
2676 if (mode == " cascade" )
2777 {
28- cascade (toplevel , workarea);
78+ cascade (view , workarea);
2979 } else if (mode == " maximize" )
3080 {
31- maximize (toplevel , workarea);
81+ maximize (view , workarea);
3282 } else if (mode == " random" )
3383 {
34- random (toplevel , workarea);
84+ random (view , workarea);
3585 } else
3686 {
37- center (toplevel , workarea);
87+ center (view , workarea);
3888 }
39- };
89+ }
4090
41- wf::signal::connection_t <wf::workarea_changed_signal> workarea_changed_cb = [=] (auto )
91+ void adjust_cascade_for_workarea (nonstd::observer_ptr<wayfire_place_cascade_data> cascade,
92+ wf::geometry_t workarea)
4293 {
43- auto workarea = output->workarea ->get_workarea ();
44- if ((cascade_x < workarea.x ) ||
45- (cascade_x > workarea.x + workarea.width ))
94+ if ((cascade->x < workarea.x ) || (cascade->x > workarea.x + workarea.width ))
4695 {
47- cascade_x = workarea.x ;
96+ cascade-> x = workarea.x ;
4897 }
4998
50- if ((cascade_y < workarea.y ) ||
51- (cascade_y > workarea.y + workarea.height ))
99+ if ((cascade->y < workarea.y ) || (cascade->y > workarea.y + workarea.height ))
52100 {
53- cascade_y = workarea.y ;
101+ cascade-> y = workarea.y ;
54102 }
55- };
103+ }
56104
57105 wf::option_wrapper_t <std::string> placement_mode{" place/mode" };
58106
59- int cascade_x, cascade_y;
60-
61107 public:
62108 void init () override
63109 {
64- auto workarea = output->workarea ->get_workarea ();
65- cascade_x = workarea.x ;
66- cascade_y = workarea.y ;
67-
68- output->connect (&workarea_changed_cb);
69- output->connect (&on_view_mapped);
110+ wf::get_core ().tx_manager ->connect (&on_new_tx);
70111 }
71112
72- void cascade (wayfire_toplevel_view & view, wf::geometry_t workarea)
113+ void cascade (wayfire_toplevel_view view, wf::geometry_t workarea)
73114 {
74115 wf::geometry_t window = view->get_pending_geometry ();
116+ auto cascade = view->get_output ()->get_data_safe <wayfire_place_cascade_data>();
117+ adjust_cascade_for_workarea (cascade, workarea);
75118
76- if ((cascade_x + window.width > workarea.x + workarea.width ) ||
77- (cascade_y + window.height > workarea.y + workarea.height ))
119+ if ((cascade-> x + window.width > workarea.x + workarea.width ) ||
120+ (cascade-> y + window.height > workarea.y + workarea.height ))
78121 {
79- cascade_x = workarea.x ;
80- cascade_y = workarea.y ;
122+ cascade-> x = workarea.x ;
123+ cascade-> y = workarea.y ;
81124 }
82125
83- view->move (cascade_x, cascade_y);
126+ view->toplevel ()->pending ().geometry .x = cascade->x ;
127+ view->toplevel ()->pending ().geometry .y = cascade->y ;
84128
85- cascade_x += workarea.width * .03 ;
86- cascade_y += workarea.height * .03 ;
129+ cascade-> x += workarea.width * .03 ;
130+ cascade-> y += workarea.height * .03 ;
87131 }
88132
89133 void random (wayfire_toplevel_view & view, wf::geometry_t workarea)
90134 {
91135 wf::geometry_t window = view->get_pending_geometry ();
92136 wf::geometry_t area;
93- int pos_x, pos_y;
94137
95138 area.x = workarea.x ;
96139 area.y = workarea.y ;
@@ -104,18 +147,15 @@ class wayfire_place_window : public wf::per_output_plugin_instance_t
104147 return ;
105148 }
106149
107- pos_x = rand () % area.width + area.x ;
108- pos_y = rand () % area.height + area.y ;
109-
110- view->move (pos_x, pos_y);
150+ view->toplevel ()->pending ().geometry .x = rand () % area.width + area.x ;
151+ view->toplevel ()->pending ().geometry .y = rand () % area.height + area.y ;
111152 }
112153
113154 void center (wayfire_toplevel_view & view, wf::geometry_t workarea)
114155 {
115156 wf::geometry_t window = view->get_pending_geometry ();
116- window.x = workarea.x + (workarea.width / 2 ) - (window.width / 2 );
117- window.y = workarea.y + (workarea.height / 2 ) - (window.height / 2 );
118- view->move (window.x , window.y );
157+ view->toplevel ()->pending ().geometry .x = workarea.x + (workarea.width / 2 ) - (window.width / 2 );
158+ view->toplevel ()->pending ().geometry .y = workarea.y + (workarea.height / 2 ) - (window.height / 2 );
119159 }
120160
121161 void maximize (wayfire_toplevel_view & view, wf::geometry_t workarea)
0 commit comments