[Bf-blender-cvs] [870bcf6e1af] master: GHOST/wayland: adapt window and cursor surface scale to support HiDPI screens

Christian Rauch noreply at git.blender.org
Thu Jun 3 19:24:16 CEST 2021


Commit: 870bcf6e1af5a493b2e2583d98b3b12b7ab3a05d
Author: Christian Rauch
Date:   Sat Jul 25 15:58:29 2020 +0100
Branches: master
https://developer.blender.org/rB870bcf6e1af5a493b2e2583d98b3b12b7ab3a05d

GHOST/wayland: adapt window and cursor surface scale to support HiDPI screens

===================================================================

M	intern/ghost/intern/GHOST_SystemWayland.cpp
M	intern/ghost/intern/GHOST_SystemWayland.h
M	intern/ghost/intern/GHOST_WindowWayland.cpp
M	intern/ghost/intern/GHOST_WindowWayland.h

===================================================================

diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index d6e46f27918..1e9a2940c32 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -53,15 +53,6 @@
 
 #include <cstring>
 
-struct output_t {
-  struct wl_output *output;
-  int32_t width, height;
-  int transform;
-  int scale;
-  std::string make;
-  std::string model;
-};
-
 struct buffer_t {
   void *data;
   size_t size;
@@ -73,6 +64,12 @@ struct cursor_t {
   struct wl_buffer *buffer;
   struct wl_cursor_image image;
   struct buffer_t *file_buffer = nullptr;
+  struct wl_cursor_theme *theme = nullptr;
+  int size;
+  std::string theme_name;
+  // outputs on which the cursor is visible
+  std::unordered_set<const output_t *> outputs;
+  int scale = 1;
 };
 
 struct data_offer_t {
@@ -146,7 +143,10 @@ struct display_t {
   struct wl_shm *shm = nullptr;
   std::vector<output_t *> outputs;
   std::vector<input_t *> inputs;
-  struct wl_cursor_theme *cursor_theme = nullptr;
+  struct {
+    std::string theme;
+    int size;
+  } cursor;
   struct wl_data_device_manager *data_device_manager = nullptr;
   struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = nullptr;
   struct zwp_pointer_constraints_v1 *pointer_constraints = nullptr;
@@ -155,6 +155,8 @@ struct display_t {
   std::vector<struct wl_egl_window *> os_egl_windows;
 };
 
+static GHOST_WindowManager *window_manager = nullptr;
+
 static void display_destroy(display_t *d)
 {
   if (d->data_device_manager) {
@@ -189,6 +191,9 @@ static void display_destroy(display_t *d)
       if (input->cursor.surface) {
         wl_surface_destroy(input->cursor.surface);
       }
+      if (input->cursor.theme) {
+        wl_cursor_theme_destroy(input->cursor.theme);
+      }
       if (input->pointer) {
         wl_pointer_destroy(input->pointer);
       }
@@ -211,10 +216,6 @@ static void display_destroy(display_t *d)
     delete input;
   }
 
-  if (d->cursor_theme) {
-    wl_cursor_theme_destroy(d->cursor_theme);
-  }
-
   if (d->shm) {
     wl_shm_destroy(d->shm);
   }
@@ -801,6 +802,69 @@ const struct wl_buffer_listener cursor_buffer_listener = {
     cursor_buffer_release,
 };
 
+static GHOST_IWindow *get_window(struct wl_surface *surface)
+{
+  if (!surface) {
+    return nullptr;
+  }
+
+  for (GHOST_IWindow *win : window_manager->getWindows()) {
+    if (surface == static_cast<const GHOST_WindowWayland *>(win)->surface()) {
+      return win;
+    }
+  }
+  return nullptr;
+}
+
+static bool update_cursor_scale(cursor_t &cursor, wl_shm *shm)
+{
+  int scale = 0;
+  for (const output_t *output : cursor.outputs) {
+    if (output->scale > scale)
+      scale = output->scale;
+  }
+
+  if (scale > 0 && cursor.scale != scale) {
+    cursor.scale = scale;
+    wl_surface_set_buffer_scale(cursor.surface, scale);
+    wl_cursor_theme_destroy(cursor.theme);
+    cursor.theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm);
+    return true;
+  }
+  return false;
+}
+
+static void cursor_surface_enter(void *data,
+                                 struct wl_surface * /*wl_surface*/,
+                                 struct wl_output *output)
+{
+  input_t *input = static_cast<input_t *>(data);
+  for (const output_t *reg_output : input->system->outputs()) {
+    if (reg_output->output == output) {
+      input->cursor.outputs.insert(reg_output);
+    }
+  }
+  update_cursor_scale(input->cursor, input->system->shm());
+}
+
+static void cursor_surface_leave(void *data,
+                                 struct wl_surface * /*wl_surface*/,
+                                 struct wl_output *output)
+{
+  input_t *input = static_cast<input_t *>(data);
+  for (const output_t *reg_output : input->system->outputs()) {
+    if (reg_output->output == output) {
+      input->cursor.outputs.erase(reg_output);
+    }
+  }
+  update_cursor_scale(input->cursor, input->system->shm());
+}
+
+struct wl_surface_listener cursor_surface_listener = {
+    cursor_surface_enter,
+    cursor_surface_leave,
+};
+
 static void pointer_enter(void *data,
                           struct wl_pointer * /*wl_pointer*/,
                           uint32_t serial,
@@ -808,22 +872,28 @@ static void pointer_enter(void *data,
                           wl_fixed_t surface_x,
                           wl_fixed_t surface_y)
 {
-  if (!surface) {
+  GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(get_window(surface));
+
+  if (!win) {
     return;
   }
+
+  win->activate();
+
   input_t *input = static_cast<input_t *>(data);
   input->pointer_serial = serial;
-  input->x = wl_fixed_to_int(surface_x);
-  input->y = wl_fixed_to_int(surface_y);
+  input->x = win->scale() * wl_fixed_to_int(surface_x);
+  input->y = win->scale() * wl_fixed_to_int(surface_y);
   input->focus_pointer = surface;
 
-  input->system->pushEvent(
-      new GHOST_EventCursor(input->system->getMilliSeconds(),
-                            GHOST_kEventCursorMove,
-                            static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface)),
-                            input->x,
-                            input->y,
-                            GHOST_TABLET_DATA_NONE));
+  win->setCursorShape(win->getCursorShape());
+
+  input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
+                                                 GHOST_kEventCursorMove,
+                                                 static_cast<GHOST_WindowWayland *>(win),
+                                                 input->x,
+                                                 input->y,
+                                                 GHOST_TABLET_DATA_NONE));
 }
 
 static void pointer_leave(void *data,
@@ -831,9 +901,14 @@ static void pointer_leave(void *data,
                           uint32_t /*serial*/,
                           struct wl_surface *surface)
 {
-  if (surface != nullptr) {
-    static_cast<input_t *>(data)->focus_pointer = nullptr;
+  GHOST_IWindow *win = get_window(surface);
+
+  if (!win) {
+    return;
   }
+
+  static_cast<input_t *>(data)->focus_pointer = nullptr;
+  static_cast<GHOST_WindowWayland *>(win)->deactivate();
 }
 
 static void pointer_motion(void *data,
@@ -844,21 +919,20 @@ static void pointer_motion(void *data,
 {
   input_t *input = static_cast<input_t *>(data);
 
-  GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
-      wl_surface_get_user_data(input->focus_pointer));
+  GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(get_window(input->focus_pointer));
 
   if (!win) {
     return;
   }
 
-  input->x = wl_fixed_to_int(surface_x);
-  input->y = wl_fixed_to_int(surface_y);
+  input->x = win->scale() * wl_fixed_to_int(surface_x);
+  input->y = win->scale() * wl_fixed_to_int(surface_y);
 
   input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
                                                  GHOST_kEventCursorMove,
                                                  win,
-                                                 wl_fixed_to_int(surface_x),
-                                                 wl_fixed_to_int(surface_y),
+                                                 input->x,
+                                                 input->y,
                                                  GHOST_TABLET_DATA_NONE));
 }
 
@@ -869,6 +943,14 @@ static void pointer_button(void *data,
                            uint32_t button,
                            uint32_t state)
 {
+  input_t *input = static_cast<input_t *>(data);
+
+  GHOST_IWindow *win = get_window(input->focus_pointer);
+
+  if (!win) {
+    return;
+  }
+
   GHOST_TEventType etype = GHOST_kEventUnknown;
   switch (state) {
     case WL_POINTER_BUTTON_STATE_RELEASED:
@@ -892,9 +974,6 @@ static void pointer_button(void *data,
       break;
   }
 
-  input_t *input = static_cast<input_t *>(data);
-  GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
-      wl_surface_get_user_data(input->focus_pointer));
   input->data_source->source_serial = serial;
   input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
   input->system->pushEvent(new GHOST_EventButton(
@@ -907,12 +986,18 @@ static void pointer_axis(void *data,
                          uint32_t axis,
                          wl_fixed_t value)
 {
+  input_t *input = static_cast<input_t *>(data);
+
+  GHOST_IWindow *win = get_window(input->focus_pointer);
+
+  if (!win) {
+    return;
+  }
+
   if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) {
     return;
   }
-  input_t *input = static_cast<input_t *>(data);
-  GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
-      wl_surface_get_user_data(input->focus_pointer));
+
   input->system->pushEvent(
       new GHOST_EventWheel(input->system->getMilliSeconds(), win, std::signbit(value) ? +1 : -1));
 }
@@ -1142,7 +1227,12 @@ static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capa
     input->cursor.visible = true;
     input->cursor.buffer = nullptr;
     input->cursor.file_buffer = new buffer_t;
+    if (!get_cursor_settings(input->cursor.theme_name, input->cursor.size)) {
+      input->cursor.theme_name = std::string();
+      input->cursor.size = default_cursor_size;
+    }
     wl_pointer_add_listener(input->pointer, &pointer_listener, data);
+    wl_surface_add_listener(input->cursor.surface, &cursor_surface_listener, data);
   }
 
   if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
@@ -1165,8 +1255,8 @@ static void output_geometry(void *data,
                             struct wl_output * /*wl_output*/,
                             int32_t /*x*/,
                             int32_t /*y*/,
-                            int32_t /*physical_width*/,
-                            int32_t /*physical_height*/,
+                            int32_t physical_width,
+                            int32_t physical_height,
                             int32_t /*subpixel*/,
                             const char *make,
                             const char *model,
@@ -1176,6 +1266,8 @@ static void output_geometry(void *data,
   output->transform = transform;
  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list