File: place.cpp

package info (click to toggle)
wayfire 0.10.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,764 kB
  • sloc: cpp: 52,464; xml: 2,987; ansic: 699; makefile: 161
file content (127 lines) | stat: -rw-r--r-- 3,736 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "wayfire/signal-provider.hpp"
#include "wayfire/toplevel-view.hpp"
#include <wayfire/per-output-plugin.hpp>
#include <wayfire/view.hpp>
#include <wayfire/core.hpp>
#include <wayfire/workarea.hpp>
#include <wayfire/window-manager.hpp>
#include <wayfire/signal-definitions.hpp>

class wayfire_place_window : public wf::per_output_plugin_instance_t
{
    wf::signal::connection_t<wf::view_mapped_signal> on_view_mapped = [=] (wf::view_mapped_signal *ev)
    {
        auto toplevel = wf::toplevel_cast(ev->view);

        if (!toplevel || toplevel->parent || toplevel->pending_fullscreen() ||
            toplevel->pending_tiled_edges() || ev->is_positioned)
        {
            return;
        }

        ev->is_positioned = true;
        auto workarea = output->workarea->get_workarea();

        std::string mode = placement_mode;
        if (mode == "cascade")
        {
            cascade(toplevel, workarea);
        } else if (mode == "maximize")
        {
            maximize(toplevel, workarea);
        } else if (mode == "random")
        {
            random(toplevel, workarea);
        } else
        {
            center(toplevel, workarea);
        }
    };

    wf::signal::connection_t<wf::workarea_changed_signal> workarea_changed_cb = [=] (auto)
    {
        auto workarea = output->workarea->get_workarea();
        if ((cascade_x < workarea.x) ||
            (cascade_x > workarea.x + workarea.width))
        {
            cascade_x = workarea.x;
        }

        if ((cascade_y < workarea.y) ||
            (cascade_y > workarea.y + workarea.height))
        {
            cascade_y = workarea.y;
        }
    };

    wf::option_wrapper_t<std::string> placement_mode{"place/mode"};

    int cascade_x, cascade_y;

  public:
    void init() override
    {
        auto workarea = output->workarea->get_workarea();
        cascade_x = workarea.x;
        cascade_y = workarea.y;

        output->connect(&workarea_changed_cb);
        output->connect(&on_view_mapped);
    }

    void cascade(wayfire_toplevel_view & view, wf::geometry_t workarea)
    {
        wf::geometry_t window = view->get_pending_geometry();

        if ((cascade_x + window.width > workarea.x + workarea.width) ||
            (cascade_y + window.height > workarea.y + workarea.height))
        {
            cascade_x = workarea.x;
            cascade_y = workarea.y;
        }

        view->move(cascade_x, cascade_y);

        cascade_x += workarea.width * .03;
        cascade_y += workarea.height * .03;
    }

    void random(wayfire_toplevel_view & view, wf::geometry_t workarea)
    {
        wf::geometry_t window = view->get_pending_geometry();
        wf::geometry_t area;
        int pos_x, pos_y;

        area.x     = workarea.x;
        area.y     = workarea.y;
        area.width = workarea.width - window.width;
        area.height = workarea.height - window.height;

        if ((area.width <= 0) || (area.height <= 0))
        {
            center(view, workarea);

            return;
        }

        pos_x = rand() % area.width + area.x;
        pos_y = rand() % area.height + area.y;

        view->move(pos_x, pos_y);
    }

    void center(wayfire_toplevel_view & view, wf::geometry_t workarea)
    {
        wf::geometry_t window = view->get_pending_geometry();
        window.x = workarea.x + (workarea.width / 2) - (window.width / 2);
        window.y = workarea.y + (workarea.height / 2) - (window.height / 2);
        view->move(window.x, window.y);
    }

    void maximize(wayfire_toplevel_view & view, wf::geometry_t workarea)
    {
        wf::get_core().default_wm->tile_request(view, wf::TILED_EDGES_ALL);
    }
};

DECLARE_WAYFIRE_PLUGIN(wf::per_output_plugin_t<wayfire_place_window>);