Skip to content

Commit 434d509

Browse files
author
Ómar Högni Guðmarsson
authored
Multiple seats (#417)
Added the ability to have multiple seats, this allows f.e. weston screenshare and a local touch input to work at the same time. Signed-off-by: Ómar Högni Guðmarsson <ohg@skaginn3x.com>
1 parent 9743862 commit 434d509

File tree

3 files changed

+107
-77
lines changed

3 files changed

+107
-77
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ Yunhao Tian (t123yh@outlook.com)
1414
Luke Howard <lukeh@padl.com>
1515
Stanislav Shmarov <github@snarpix.com>
1616
Sebastian Urban <surban@surban.net>
17+
Ómar Högni Guðmarsson <ohg@skaginn3x.com>

src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.cc

Lines changed: 98 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -289,29 +289,32 @@ const wl_seat_listener ELinuxWindowWayland::kWlSeatListener = {
289289
ELINUX_LOG(TRACE) << "wl_seat_listener.capabilities";
290290

291291
auto self = reinterpret_cast<ELinuxWindowWayland*>(data);
292-
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !self->wl_pointer_) {
293-
self->wl_pointer_ = wl_seat_get_pointer(seat);
294-
wl_pointer_add_listener(self->wl_pointer_, &kWlPointerListener, self);
295-
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && self->wl_pointer_) {
296-
wl_pointer_destroy(self->wl_pointer_);
297-
self->wl_pointer_ = nullptr;
292+
auto [iter_inputs, _] =
293+
self->seat_inputs_map_.emplace(seat, seat_inputs());
294+
auto& inputs = iter_inputs->second;
295+
296+
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !inputs.pointer) {
297+
inputs.pointer = wl_seat_get_pointer(seat);
298+
wl_pointer_add_listener(inputs.pointer, &kWlPointerListener, self);
299+
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && inputs.pointer) {
300+
wl_pointer_destroy(inputs.pointer);
301+
inputs.pointer = nullptr;
298302
}
299303

300-
if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !self->wl_touch_) {
301-
self->wl_touch_ = wl_seat_get_touch(seat);
302-
wl_touch_add_listener(self->wl_touch_, &kWlTouchListener, self);
303-
} else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && self->wl_touch_) {
304-
wl_touch_destroy(self->wl_touch_);
305-
self->wl_touch_ = nullptr;
304+
if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !inputs.touch) {
305+
inputs.touch = wl_seat_get_touch(seat);
306+
wl_touch_add_listener(inputs.touch, &kWlTouchListener, self);
307+
} else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && inputs.touch) {
308+
wl_touch_destroy(inputs.touch);
309+
inputs.touch = nullptr;
306310
}
307311

308-
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !self->wl_keyboard_) {
309-
self->wl_keyboard_ = wl_seat_get_keyboard(seat);
310-
wl_keyboard_add_listener(self->wl_keyboard_, &kWlKeyboardListener,
311-
self);
312-
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && self->wl_keyboard_) {
313-
wl_keyboard_destroy(self->wl_keyboard_);
314-
self->wl_keyboard_ = nullptr;
312+
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !inputs.keyboard) {
313+
inputs.keyboard = wl_seat_get_keyboard(seat);
314+
wl_keyboard_add_listener(inputs.keyboard, &kWlKeyboardListener, self);
315+
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && inputs.keyboard) {
316+
wl_keyboard_destroy(inputs.keyboard);
317+
inputs.keyboard = nullptr;
315318
}
316319
},
317320
.name = [](void* data, struct wl_seat* wl_seat, const char* name) -> void {
@@ -333,7 +336,7 @@ const wl_pointer_listener ELinuxWindowWayland::kWlPointerListener = {
333336
self->serial_ = serial;
334337

335338
if (self->view_properties_.use_mouse_cursor) {
336-
self->cursor_info_.pointer = self->wl_pointer_;
339+
self->cursor_info_.pointer = wl_pointer;
337340
self->cursor_info_.serial = serial;
338341
}
339342

@@ -399,7 +402,14 @@ const wl_pointer_listener ELinuxWindowWayland::kWlPointerListener = {
399402
self->window_decorations_->IsMatched(
400403
self->wl_current_surface_,
401404
WindowDecoration::DecorationType::TITLE_BAR)) {
402-
xdg_toplevel_move(self->xdg_toplevel_, self->wl_seat_, serial);
405+
for (auto& [seat, inputs] : self->seat_inputs_map_) {
406+
if (inputs.pointer == pointer) {
407+
xdg_toplevel_move(self->xdg_toplevel_, seat, serial);
408+
return;
409+
}
410+
}
411+
ELINUX_LOG(TRACE)
412+
<< "Failed to find the pointer for moving the window";
403413
return;
404414
}
405415

@@ -1043,11 +1053,8 @@ ELinuxWindowWayland::ELinuxWindowWayland(
10431053
wl_compositor_(nullptr),
10441054
wl_subcompositor_(nullptr),
10451055
wl_current_surface_(nullptr),
1046-
wl_seat_(nullptr),
1047-
wl_pointer_(nullptr),
1048-
wl_touch_(nullptr),
1049-
wl_keyboard_(nullptr),
10501056
wl_shm_(nullptr),
1057+
seat_inputs_map_(),
10511058
wl_data_device_manager_(nullptr),
10521059
wl_data_device_(nullptr),
10531060
wl_data_offer_(nullptr),
@@ -1087,34 +1094,37 @@ ELinuxWindowWayland::ELinuxWindowWayland(
10871094
wl_registry_add_listener(wl_registry_, &kWlRegistryListener, this);
10881095
wl_display_roundtrip(wl_display_);
10891096

1090-
if (wl_data_device_manager_ && wl_seat_) {
1091-
wl_data_device_ = wl_data_device_manager_get_data_device(
1092-
wl_data_device_manager_, wl_seat_);
1093-
wl_data_device_add_listener(wl_data_device_, &kWlDataDeviceListener, this);
1094-
}
1097+
for (auto& [seat, _] : seat_inputs_map_) {
1098+
if (wl_data_device_manager_ && seat) {
1099+
wl_data_device_ =
1100+
wl_data_device_manager_get_data_device(wl_data_device_manager_, seat);
1101+
wl_data_device_add_listener(wl_data_device_, &kWlDataDeviceListener,
1102+
this);
1103+
}
10951104

1096-
// Setup text-input protocol for onscreen keyboard inputs.
1097-
{
1098-
if (zwp_text_input_manager_v3_ && wl_seat_) {
1099-
zwp_text_input_v3_ = zwp_text_input_manager_v3_get_text_input(
1100-
zwp_text_input_manager_v3_, wl_seat_);
1101-
if (!zwp_text_input_v3_) {
1102-
ELINUX_LOG(ERROR) << "Failed to create the text input manager v3.";
1103-
return;
1104-
}
1105-
zwp_text_input_v3_add_listener(zwp_text_input_v3_,
1106-
&kZwpTextInputV3Listener, this);
1107-
} else if (zwp_text_input_manager_v1_) {
1108-
zwp_text_input_v1_ = zwp_text_input_manager_v1_create_text_input(
1109-
zwp_text_input_manager_v1_);
1110-
if (!zwp_text_input_v1_) {
1111-
ELINUX_LOG(ERROR) << "Failed to create text input manager v1.";
1112-
return;
1105+
// Setup text-input protocol for onscreen keyboard inputs.
1106+
{
1107+
if (zwp_text_input_manager_v3_ && seat) {
1108+
zwp_text_input_v3_ = zwp_text_input_manager_v3_get_text_input(
1109+
zwp_text_input_manager_v3_, seat);
1110+
if (!zwp_text_input_v3_) {
1111+
ELINUX_LOG(ERROR) << "Failed to create the text input manager v3.";
1112+
return;
1113+
}
1114+
zwp_text_input_v3_add_listener(zwp_text_input_v3_,
1115+
&kZwpTextInputV3Listener, this);
1116+
} else if (zwp_text_input_manager_v1_) {
1117+
zwp_text_input_v1_ = zwp_text_input_manager_v1_create_text_input(
1118+
zwp_text_input_manager_v1_);
1119+
if (!zwp_text_input_v1_) {
1120+
ELINUX_LOG(ERROR) << "Failed to create text input manager v1.";
1121+
return;
1122+
}
1123+
zwp_text_input_v1_add_listener(zwp_text_input_v1_,
1124+
&kZwpTextInputV1Listener, this);
1125+
} else {
1126+
// do nothing.
11131127
}
1114-
zwp_text_input_v1_add_listener(zwp_text_input_v1_,
1115-
&kZwpTextInputV1Listener, this);
1116-
} else {
1117-
// do nothing.
11181128
}
11191129
}
11201130

@@ -1190,26 +1200,29 @@ ELinuxWindowWayland::~ELinuxWindowWayland() {
11901200
wl_data_device_manager_ = nullptr;
11911201
}
11921202

1193-
if (wl_pointer_) {
1194-
wl_pointer_destroy(wl_pointer_);
1195-
wl_pointer_ = nullptr;
1196-
}
1203+
for (auto& [seat, inputs] : seat_inputs_map_) {
1204+
if (inputs.pointer) {
1205+
wl_pointer_destroy(inputs.pointer);
1206+
inputs.pointer = nullptr;
1207+
}
11971208

1198-
if (wl_touch_) {
1199-
wl_touch_destroy(wl_touch_);
1200-
wl_touch_ = nullptr;
1201-
}
1209+
if (inputs.touch) {
1210+
wl_touch_destroy(inputs.touch);
1211+
inputs.touch = nullptr;
1212+
}
12021213

1203-
if (wl_keyboard_) {
1204-
wl_keyboard_destroy(wl_keyboard_);
1205-
wl_keyboard_ = nullptr;
1206-
}
1214+
if (inputs.keyboard) {
1215+
wl_keyboard_destroy(inputs.keyboard);
1216+
inputs.keyboard = nullptr;
1217+
}
12071218

1208-
if (wl_seat_) {
1209-
wl_seat_destroy(wl_seat_);
1210-
wl_seat_ = nullptr;
1219+
if (seat) {
1220+
wl_seat_destroy(seat);
1221+
}
12111222
}
12121223

1224+
seat_inputs_map_.clear();
1225+
12131226
if (wl_output_) {
12141227
wl_output_destroy(wl_output_);
12151228
wl_output_ = nullptr;
@@ -1486,7 +1499,7 @@ void ELinuxWindowWayland::DestroyRenderSurface() {
14861499

14871500
void ELinuxWindowWayland::UpdateVirtualKeyboardStatus(const bool show) {
14881501
// Not supported virtual keyboard.
1489-
if (!(zwp_text_input_v1_ || zwp_text_input_v3_) || !wl_seat_) {
1502+
if (!(zwp_text_input_v1_ || zwp_text_input_v3_) || seat_inputs_map_.empty()) {
14901503
return;
14911504
}
14921505

@@ -1500,7 +1513,14 @@ void ELinuxWindowWayland::UpdateVirtualKeyboardStatus(const bool show) {
15001513

15011514
void ELinuxWindowWayland::UpdateFlutterCursor(const std::string& cursor_name) {
15021515
if (view_properties_.use_mouse_cursor) {
1503-
if (!wl_pointer_) {
1516+
wl_pointer* pointer = nullptr;
1517+
for (auto& [_, inputs] : seat_inputs_map_) {
1518+
if (inputs.pointer != nullptr) {
1519+
pointer = inputs.pointer;
1520+
break;
1521+
}
1522+
}
1523+
if (!pointer) {
15041524
return;
15051525
}
15061526
if (cursor_name.compare(cursor_info_.cursor_name) == 0) {
@@ -1619,9 +1639,12 @@ void ELinuxWindowWayland::WlRegistryHandler(wl_registry* wl_registry,
16191639

16201640
if (!strcmp(interface, wl_seat_interface.name)) {
16211641
constexpr uint32_t kMaxVersion = 4;
1622-
wl_seat_ = static_cast<decltype(wl_seat_)>(wl_registry_bind(
1623-
wl_registry, name, &wl_seat_interface, std::min(kMaxVersion, version)));
1624-
wl_seat_add_listener(wl_seat_, &kWlSeatListener, this);
1642+
auto [inserted, _] =
1643+
seat_inputs_map_.emplace(static_cast<wl_seat*>(wl_registry_bind(
1644+
wl_registry, name, &wl_seat_interface,
1645+
std::min(kMaxVersion, version))),
1646+
seat_inputs());
1647+
wl_seat_add_listener(inserted->first, &kWlSeatListener, this);
16251648
return;
16261649
}
16271650

@@ -1826,7 +1849,8 @@ void ELinuxWindowWayland::ShowVirtualKeyboard() {
18261849
} else {
18271850
if (native_window_) {
18281851
zwp_text_input_v1_show_input_panel(zwp_text_input_v1_);
1829-
zwp_text_input_v1_activate(zwp_text_input_v1_, wl_seat_,
1852+
zwp_text_input_v1_activate(zwp_text_input_v1_,
1853+
seat_inputs_map_.begin()->first,
18301854
native_window_->Surface());
18311855
}
18321856
}
@@ -1837,7 +1861,8 @@ void ELinuxWindowWayland::DismissVirtualKeybaord() {
18371861
zwp_text_input_v3_disable(zwp_text_input_v3_);
18381862
zwp_text_input_v3_commit(zwp_text_input_v3_);
18391863
} else {
1840-
zwp_text_input_v1_deactivate(zwp_text_input_v1_, wl_seat_);
1864+
zwp_text_input_v1_deactivate(zwp_text_input_v1_,
1865+
seat_inputs_map_.begin()->first);
18411866
}
18421867
}
18431868

src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ namespace {
3434
constexpr char kXcursorSizeEnvironmentKey[] = "XCURSOR_SIZE";
3535
} // namespace
3636

37+
// Track input devices for each seat
38+
struct seat_inputs {
39+
wl_pointer* pointer = nullptr;
40+
wl_touch* touch = nullptr;
41+
wl_keyboard* keyboard = nullptr;
42+
};
43+
3744
class ELinuxWindowWayland : public ELinuxWindow, public WindowBindingHandler {
3845
public:
3946
ELinuxWindowWayland(FlutterDesktopViewProperties view_properties);
@@ -161,12 +168,9 @@ class ELinuxWindowWayland : public ELinuxWindow, public WindowBindingHandler {
161168
wl_display* wl_display_;
162169
wl_registry* wl_registry_;
163170
wl_compositor* wl_compositor_;
164-
wl_seat* wl_seat_;
165171
wl_output* wl_output_;
166172
wl_shm* wl_shm_;
167-
wl_pointer* wl_pointer_;
168-
wl_touch* wl_touch_;
169-
wl_keyboard* wl_keyboard_;
173+
std::unordered_map<wl_seat*, seat_inputs> seat_inputs_map_;
170174
wl_surface* wl_cursor_surface_;
171175
xdg_wm_base* xdg_wm_base_;
172176
xdg_surface* xdg_surface_;

0 commit comments

Comments
 (0)