[Bf-blender-cvs] [409070e0d48] master: GHOST/Wayland: support for multiple seats (one active seat at a time)
Campbell Barton
noreply at git.blender.org
Tue Nov 1 01:48:18 CET 2022
Commit: 409070e0d480df99948e36bf2e48f123d9285aa0
Author: Campbell Barton
Date: Tue Nov 1 10:41:06 2022 +1100
Branches: master
https://developer.blender.org/rB409070e0d480df99948e36bf2e48f123d9285aa0
GHOST/Wayland: support for multiple seats (one active seat at a time)
This isn't full multi-seat support, instead set the active seat using
pointer/tablet & keyboard enter handlers.
This means that seats beside the first aren't prevented from having
their events handled.
===================================================================
M intern/ghost/intern/GHOST_SystemWayland.cpp
M intern/ghost/intern/GHOST_SystemWayland.h
===================================================================
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index f3dc1609e69..f713ddced27 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -776,6 +776,18 @@ struct GWL_Display {
struct wl_shm *wl_shm = nullptr;
std::vector<GWL_Output *> outputs;
std::vector<GWL_Seat *> seats;
+ /**
+ * Support a single active seat at once, this isn't an exact or correct mapping from WAYLAND.
+ * Only allow input from different seats, not full concurrent multi-seat support.
+ *
+ * The main purpose of having an active seat is an alternative from always using the first
+ * seat which prevents events from any other seat.
+ *
+ * NOTE(@campbellbarton): This could be extended and developed further extended to support
+ * an active seat per window (for e.g.), basic support is sufficient for now as currently isn't
+ * a widely used feature.
+ */
+ int seats_active_index = 0;
/* Managers. */
struct wl_data_device_manager *wl_data_device_manager = nullptr;
@@ -830,6 +842,37 @@ static void gwl_display_destroy(GWL_Display *display)
delete display;
}
+static int gwl_display_seat_index(GWL_Display *display, const GWL_Seat *seat)
+{
+ std::vector<GWL_Seat *>::iterator iter = std::find(
+ display->seats.begin(), display->seats.end(), seat);
+ const int index = (iter != display->seats.cend()) ? std::distance(display->seats.begin(), iter) :
+ -1;
+ GHOST_ASSERT(index != -1, "invalid internal state");
+ return index;
+}
+
+static GWL_Seat *gwl_display_seat_active_get(const GWL_Display *display)
+{
+ if (UNLIKELY(display->seats.empty())) {
+ return nullptr;
+ }
+ return display->seats[display->seats_active_index];
+}
+
+static bool gwl_display_seat_active_set(GWL_Display *display, const GWL_Seat *seat)
+{
+ if (UNLIKELY(display->seats.empty())) {
+ return false;
+ }
+ const int index = gwl_display_seat_index(display, seat);
+ if (index == display->seats_active_index) {
+ return false;
+ }
+ display->seats_active_index = index;
+ return true;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1925,6 +1968,9 @@ static void data_device_handle_enter(void *data,
}
seat->wl_surface_focus_dnd = wl_surface;
+
+ seat->system->seat_active_set(seat);
+
dnd_events(seat, GHOST_kEventDraggingEntered);
}
@@ -2256,6 +2302,8 @@ static void pointer_handle_enter(void *data,
seat->pointer.wl_surface = wl_surface;
+ seat->system->seat_active_set(seat);
+
win->setCursorShape(win->getCursorShape());
const wl_fixed_t scale = win->scale();
@@ -2900,6 +2948,8 @@ static void tablet_tool_handle_proximity_in(void *data,
seat->data_source_serial = serial;
+ seat->system->seat_active_set(seat);
+
/* Update #GHOST_TabletData. */
GHOST_TabletData &td = tablet_tool->data;
/* Reset, to avoid using stale tilt/pressure. */
@@ -3286,6 +3336,8 @@ static void keyboard_handle_enter(void *data,
seat->keyboard.serial = serial;
seat->keyboard.wl_surface = wl_surface;
+ seat->system->seat_active_set(seat);
+
/* If there are any keys held when activating the window,
* modifiers will be compared against the seat state,
* only enabling modifiers that were previously disabled. */
@@ -4472,6 +4524,9 @@ static void gwl_registry_wl_seat_remove(GWL_Display *display, void *user_data, c
GHOST_ASSERT(index != -1, "invalid internal state");
if (!on_exit) {
+ if (display->seats_active_index >= index) {
+ display->seats_active_index -= 1;
+ }
display->seats.erase(display->seats.begin() + index);
}
delete seat;
@@ -4980,12 +5035,11 @@ bool GHOST_SystemWayland::setConsoleWindowState(GHOST_TConsoleWindowState /*acti
GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) const
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
-
const xkb_mod_mask_t state = xkb_state_serialize_mods(seat->xkb_state, XKB_STATE_MODS_DEPRESSED);
bool show_warning = true;
@@ -5042,10 +5096,10 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co
GHOST_TSuccess GHOST_SystemWayland::getButtons(GHOST_Buttons &buttons) const
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat);
if (!seat_state_pointer) {
return GHOST_kFailure;
@@ -5073,7 +5127,10 @@ static const char *system_clipboard_text_mime_type(
static char *system_clipboard_get_primary_selection(GWL_Display *display)
{
- GWL_Seat *seat = display->seats[0];
+ GWL_Seat *seat = gwl_display_seat_active_get(display);
+ if (UNLIKELY(!seat)) {
+ return nullptr;
+ }
GWL_PrimarySelection *primary = &seat->primary_selection;
std::mutex &mutex = primary->data_offer_mutex;
@@ -5120,7 +5177,10 @@ static char *system_clipboard_get_primary_selection(GWL_Display *display)
static char *system_clipboard_get(GWL_Display *display)
{
- GWL_Seat *seat = display->seats[0];
+ GWL_Seat *seat = gwl_display_seat_active_get(display);
+ if (UNLIKELY(!seat)) {
+ return nullptr;
+ }
std::mutex &mutex = seat->data_offer_copy_paste_mutex;
mutex.lock();
@@ -5166,10 +5226,6 @@ static char *system_clipboard_get(GWL_Display *display)
char *GHOST_SystemWayland::getClipboard(bool selection) const
{
- if (UNLIKELY(display_->seats.empty())) {
- return nullptr;
- }
-
char *data = nullptr;
if (selection) {
data = system_clipboard_get_primary_selection(display_);
@@ -5185,7 +5241,10 @@ static void system_clipboard_put_primary_selection(GWL_Display *display, const c
if (!display->wp_primary_selection_device_manager) {
return;
}
- GWL_Seat *seat = display->seats[0];
+ GWL_Seat *seat = gwl_display_seat_active_get(display);
+ if (UNLIKELY(!seat)) {
+ return;
+ }
GWL_PrimarySelection *primary = &seat->primary_selection;
std::lock_guard lock{primary->data_source_mutex};
@@ -5219,8 +5278,10 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer)
if (!display->wl_data_device_manager) {
return;
}
- GWL_Seat *seat = display->seats[0];
-
+ GWL_Seat *seat = gwl_display_seat_active_get(display);
+ if (UNLIKELY(!seat)) {
+ return;
+ }
std::lock_guard lock{seat->data_source_mutex};
GWL_DataSource *data_source = seat->data_source;
@@ -5245,10 +5306,6 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer)
void GHOST_SystemWayland::putClipboard(const char *buffer, bool selection) const
{
- if (UNLIKELY(display_->seats.empty())) {
- return;
- }
-
if (selection) {
system_clipboard_put_primary_selection(display_, buffer);
}
@@ -5301,10 +5358,10 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPositionClientRelative(const GHOST_
int32_t &x,
int32_t &y) const
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat);
if (!seat_state_pointer || !seat_state_pointer->wl_surface) {
return GHOST_kFailure;
@@ -5317,20 +5374,20 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorPositionClientRelative(GHOST_IWindo
const int32_t x,
const int32_t y)
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(window);
return setCursorPositionClientRelative_impl(seat, win, x, y);
}
GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) const
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
GWL_SeatStatePointer *seat_state_pointer = gwl_seat_state_pointer_active(seat);
if (!seat_state_pointer) {
return GHOST_kFailure;
@@ -5345,10 +5402,10 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) co
GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(const int32_t x, const int32_t y)
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
- GWL_Seat *seat = display_->seats[0];
/* Intentionally different from `getCursorPosition` which supports both tablet & pointer.
* In the case of setting the cursor location, tablets don't support this. */
@@ -5699,7 +5756,8 @@ static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_
GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor shape)
{
- if (UNLIKELY(display_->seats.empty())) {
+ GWL_Seat *seat = gwl_display_seat_active_get(display_);
+ if (UNLIKELY(!seat)) {
return GHOST_kFailure;
}
auto cursor_find = ghost_wl_cursors.find(shape);
@@ -5707,7 +5765,6 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s
ghost_wl_cursors.at(GHOST_kStandardCursorDefault) :
(*cursor_find).second;
- GWL_Seat *seat = display_->seats[0];
GWL_Cursor *cursor = &seat->cursor;
if (!cursor->wl_theme) {
@@ -5760,12 +5817,12 @@ GHOST_TSuccess GHOST_SystemWayland::set
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list