[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