Directory: | ./ |
---|---|
File: | server/selection_pool.h |
Date: | 2024-01-22 17:25:27 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 60 | 61 | 98.4% |
Branches: | 36 | 46 | 78.3% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | SPDX-FileCopyrightText: 2020, 2021 Roman Gilg <subdiff@gmail.com> | ||
3 | SPDX-FileCopyrightText: 2021 Francesco Sorrentino <francesco.sorr@gmail.com> | ||
4 | |||
5 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only | ||
6 | */ | ||
7 | #pragma once | ||
8 | |||
9 | #include "seat.h" | ||
10 | #include "surface.h" | ||
11 | #include "utils.h" | ||
12 | |||
13 | #include <vector> | ||
14 | |||
15 | namespace Wrapland::Server | ||
16 | { | ||
17 | |||
18 | template<typename Device, typename Source, void (Seat::*signal)(Source*)> | ||
19 | struct selection_pool { | ||
20 | 618 | explicit selection_pool(Seat* seat); | |
21 | |||
22 | void register_device(Device* device); | ||
23 | void set_focused_surface(Surface* surface); | ||
24 | |||
25 | void set_selection(Source* source); | ||
26 | |||
27 |
2/4✓ Branch 0 taken 309 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 309 times.
✗ Branch 3 not taken.
|
618 | struct { |
28 | std::vector<Device*> devices; | ||
29 | 618 | Source* source{nullptr}; | |
30 | QMetaObject::Connection source_destroy_notifier; | ||
31 | } focus; | ||
32 | |||
33 | std::vector<Device*> devices; | ||
34 | |||
35 | private: | ||
36 | void transmit(Source* source); | ||
37 | |||
38 | Seat* seat; | ||
39 | }; | ||
40 | |||
41 | template<typename Device, typename Source, void (Seat::*signal)(Source*)> | ||
42 | 618 | selection_pool<Device, Source, signal>::selection_pool(Seat* seat) | |
43 | 618 | : seat{seat} | |
44 | { | ||
45 | 618 | } | |
46 | |||
47 | template<typename Device, typename Source, void (Seat::*signal)(Source*)> | ||
48 | 39 | void selection_pool<Device, Source, signal>::register_device(Device* device) | |
49 | { | ||
50 | 39 | devices.push_back(device); | |
51 | |||
52 | 78 | QObject::connect(device, &Device::resourceDestroyed, seat, [this, device] { | |
53 | 39 | remove_one(devices, device); | |
54 | 39 | remove_one(focus.devices, device); | |
55 | 39 | }); | |
56 | |||
57 | 68 | QObject::connect(device, &Device::selection_changed, seat, [this, device] { | |
58 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 22 times.
|
29 | if (has_keyboard_focus(device, seat)) { |
59 | 22 | set_selection(device->selection()); | |
60 | 22 | } | |
61 | 29 | }); | |
62 | |||
63 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 4 times.
|
39 | if (has_keyboard_focus(device, seat)) { |
64 | 4 | focus.devices.push_back(device); | |
65 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | if (focus.source) { |
66 | 2 | device->send_selection(focus.source); | |
67 | 2 | } | |
68 | 4 | } | |
69 | 39 | } | |
70 | |||
71 | template<typename Device, typename Source, void (Seat::*signal)(Source*)> | ||
72 | 224 | void selection_pool<Device, Source, signal>::set_focused_surface(Surface* surface) | |
73 | { | ||
74 |
4/4✓ Branch 0 taken 101 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 101 times.
✓ Branch 3 taken 11 times.
|
224 | if (!surface) { |
75 | // No surface set. Per protocol we just won't send future selection events to the client. | ||
76 | 22 | focus.devices = {}; | |
77 | 22 | return; | |
78 | } | ||
79 | |||
80 |
4/8✓ Branch 0 taken 2 times.
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 101 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
202 | if (focus.devices.size() && focus.devices.front()->client() == surface->client()) { |
81 | // No client change. Selection must not be resent. | ||
82 | ✗ | return; | |
83 | } | ||
84 | |||
85 | 202 | focus.devices = interfacesForSurface(surface, devices); | |
86 |
4/4✓ Branch 0 taken 98 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 2 times.
|
202 | if (focus.source) { |
87 | 5 | transmit(focus.source); | |
88 | 5 | } | |
89 | 224 | } | |
90 | |||
91 | template<typename Device, typename Source, void (Seat::*signal)(Source*)> | ||
92 | 38 | void selection_pool<Device, Source, signal>::set_selection(Source* source) | |
93 | { | ||
94 |
4/4✓ Branch 0 taken 19 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 2 times.
|
38 | if (focus.source == source) { |
95 | 9 | return; | |
96 | } | ||
97 | |||
98 | 29 | auto old_source = focus.source; | |
99 | 29 | focus.source = source; | |
100 | |||
101 | 29 | QObject::disconnect(focus.source_destroy_notifier); | |
102 | 29 | focus.source_destroy_notifier = QMetaObject::Connection(); | |
103 | |||
104 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
|
29 | if (source) { |
105 | 44 | focus.source_destroy_notifier | |
106 | 53 | = QObject::connect(source, &Source::resourceDestroyed, seat, [this] { | |
107 | 9 | focus.source = nullptr; | |
108 | 9 | transmit(nullptr); | |
109 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
9 | Q_EMIT(seat->*signal)(nullptr); |
110 | 9 | }); | |
111 | 22 | } | |
112 | |||
113 | 29 | transmit(source); | |
114 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
29 | Q_EMIT(seat->*signal)(source); |
115 | |||
116 |
4/4✓ Branch 0 taken 10 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 4 times.
|
29 | if (old_source) { |
117 | 13 | old_source->cancel(); | |
118 | 13 | } | |
119 | 38 | } | |
120 | |||
121 | template<typename Device, typename Source, void (Seat::*signal)(Source*)> | ||
122 | 43 | void selection_pool<Device, Source, signal>::transmit(Source* source) | |
123 | { | ||
124 | 88 | std::for_each(focus.devices.begin(), focus.devices.end(), [source](Device* dev) { | |
125 | 45 | dev->send_selection(source); | |
126 | 45 | }); | |
127 | 43 | } | |
128 | |||
129 | } | ||
130 |