File: oswitch.cpp

package info (click to toggle)
wayfire 0.9.0-5
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 4,732 kB
  • sloc: cpp: 49,708; xml: 2,783; ansic: 699; makefile: 161
file content (114 lines) | stat: -rw-r--r-- 3,794 bytes parent folder | download
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
#include "wayfire/plugin.hpp"
#include "wayfire/toplevel-view.hpp"
#include "wayfire/view-helpers.hpp"
#include <wayfire/output.hpp>
#include <wayfire/core.hpp>
#include <wayfire/view.hpp>
#include <wayfire/output-layout.hpp>
#include <wayfire/bindings-repository.hpp>
#include <wayfire/seat.hpp>

class wayfire_oswitch : public wf::plugin_interface_t
{
    wf::wl_idle_call idle_switch_output;

    wf::output_t *get_output_relative(int step)
    {
        /* get the target output n steps after current output
         * if current output's index is i, and if there're n monitors
         * then return the (i + step) mod n th monitor */
        auto current_output = wf::get_core().seat->get_active_output();
        auto os = wf::get_core().output_layout->get_outputs();
        auto it = std::find(os.begin(), os.end(), current_output);
        if (it == os.end())
        {
            LOGI("Current output not found in output list");
            return current_output;
        }

        int size = os.size();
        int current_index = it - os.begin();
        int target_index  = ((current_index + step) % size + size) % size;
        return os[target_index];
    }

    void switch_to_output(wf::output_t *target_output)
    {
        /* when we switch the output, the oswitch keybinding
         * may be activated for the next output, which we don't want,
         * so we postpone the switch */
        idle_switch_output.run_once([=] ()
        {
            wf::get_core().seat->focus_output(target_output);
            target_output->ensure_pointer(true);
        });
    }

    void switch_to_output_with_window(wf::output_t *target_output)
    {
        auto current_output = wf::get_core().seat->get_active_output();
        auto view =
            wf::find_topmost_parent(wf::toplevel_cast(wf::get_active_view_for_output(current_output)));

        if (view)
        {
            move_view_to_output(view, target_output, true);
        }

        switch_to_output(target_output);
    }

    wf::activator_callback next_output = [=] (auto)
    {
        auto target_output = get_output_relative(1);
        switch_to_output(target_output);
        return true;
    };

    wf::activator_callback next_output_with_window = [=] (auto)
    {
        auto target_output = get_output_relative(1);
        switch_to_output_with_window(target_output);
        return true;
    };

    wf::activator_callback prev_output = [=] (auto)
    {
        auto target_output = get_output_relative(-1);
        switch_to_output(target_output);
        return true;
    };

    wf::activator_callback prev_output_with_window = [=] (auto)
    {
        auto target_output = get_output_relative(-1);
        switch_to_output_with_window(target_output);
        return true;
    };

  public:
    void init()
    {
        auto& bindings = wf::get_core().bindings;
        bindings->add_activator(wf::option_wrapper_t<wf::activatorbinding_t>{"oswitch/next_output"},
            &next_output);
        bindings->add_activator(wf::option_wrapper_t<wf::activatorbinding_t>{"oswitch/next_output_with_win"},
            &next_output_with_window);
        bindings->add_activator(wf::option_wrapper_t<wf::activatorbinding_t>{"oswitch/prev_output"},
            &prev_output);
        bindings->add_activator(wf::option_wrapper_t<wf::activatorbinding_t>{"oswitch/prev_output_with_win"},
            &prev_output_with_window);
    }

    void fini()
    {
        auto& bindings = wf::get_core().bindings;
        bindings->rem_binding(&next_output);
        bindings->rem_binding(&next_output_with_window);
        bindings->rem_binding(&prev_output);
        bindings->rem_binding(&prev_output_with_window);
        idle_switch_output.disconnect();
    }
};

DECLARE_WAYFIRE_PLUGIN(wayfire_oswitch);