[Bf-blender-cvs] [6e8217d35e0] master: GHOST/Wayland: refactor cursor handling & fix errors hiding the cursor
Campbell Barton
noreply at git.blender.org
Mon Jun 20 04:12:41 CEST 2022
Commit: 6e8217d35e0ba920abf423f3e442c33c36ed1bef
Author: Campbell Barton
Date: Mon Jun 20 11:18:40 2022 +1000
Branches: master
https://developer.blender.org/rB6e8217d35e0ba920abf423f3e442c33c36ed1bef
GHOST/Wayland: refactor cursor handling & fix errors hiding the cursor
- Support showing & hiding the cursor without setting the buffer,
needed to switch between software and hardware cursor.
- Track the state of the software/hardware cursor.
This resolves glitches switching between cursors sometimes hiding the
cursor.
===================================================================
M intern/ghost/intern/GHOST_SystemWayland.cpp
===================================================================
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index db8bfceda9b..6a4d1827a80 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -96,6 +96,13 @@ struct buffer_t {
struct cursor_t {
bool visible = false;
+ /**
+ * When false, hide the hardware cursor, while the cursor is still considered to be `visible`,
+ * since the grab-mode determines the state of the software cursor,
+ * this may change - removing the need for a software cursor and in this case it's important
+ * the hardware cursor is used.
+ */
+ bool is_hardware = true;
bool is_custom = false;
struct wl_surface *wl_surface = nullptr;
struct wl_buffer *wl_buffer = nullptr;
@@ -144,6 +151,12 @@ struct key_repeat_payload_t {
GHOST_TEventKeyData key_data = {GHOST_kKeyUnknown};
};
+/** Internal variables used to track grab-state. */
+struct input_grab_state_t {
+ bool use_lock = false;
+ bool use_confine = false;
+};
+
struct input_t {
GHOST_SystemWayland *system = nullptr;
@@ -2528,11 +2541,48 @@ void GHOST_SystemWayland::setSelection(const std::string &selection)
this->selection = selection;
}
-static void set_cursor_buffer(input_t *input, wl_buffer *buffer)
+/**
+ * Show the buffer defined by #cursor_buffer_set without changing anything else,
+ * so #cursor_buffer_hide can be used to display it again.
+ *
+ * The caller is responsible for setting `input->cursor.visible`.
+ */
+static void cursor_buffer_show(const input_t *input)
{
- cursor_t *c = &input->cursor;
+ const cursor_t *c = &input->cursor;
+ const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / c->scale;
+ const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / c->scale;
+ wl_pointer_set_cursor(
+ input->wl_pointer, input->pointer_serial, c->wl_surface, hotspot_x, hotspot_y);
+ for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) {
+ tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(
+ zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
+ zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
+ input->tablet_serial,
+ tool_input->cursor_surface,
+ hotspot_x,
+ hotspot_y);
+ }
+}
- c->visible = (buffer != nullptr);
+/**
+ * Hide the buffer defined by #cursor_buffer_set without changing anything else,
+ * so #cursor_buffer_show can be used to display it again.
+ *
+ * The caller is responsible for setting `input->cursor.visible`.
+ */
+static void cursor_buffer_hide(const input_t *input)
+{
+ wl_pointer_set_cursor(input->wl_pointer, input->pointer_serial, nullptr, 0, 0);
+ for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : input->tablet_tools) {
+ zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, input->tablet_serial, nullptr, 0, 0);
+ }
+}
+
+static void cursor_buffer_set(const input_t *input, wl_buffer *buffer)
+{
+ const cursor_t *c = &input->cursor;
+ const bool visible = (c->visible && c->is_hardware);
const int32_t image_size_x = int32_t(c->wl_image.width);
const int32_t image_size_y = int32_t(c->wl_image.height);
@@ -2540,16 +2590,14 @@ static void set_cursor_buffer(input_t *input, wl_buffer *buffer)
const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / c->scale;
const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / c->scale;
- if (buffer) {
- wl_surface_set_buffer_scale(c->wl_surface, c->scale);
- wl_surface_attach(c->wl_surface, buffer, 0, 0);
- wl_surface_damage(c->wl_surface, 0, 0, image_size_x, image_size_y);
- wl_surface_commit(c->wl_surface);
- }
+ wl_surface_set_buffer_scale(c->wl_surface, c->scale);
+ wl_surface_attach(c->wl_surface, buffer, 0, 0);
+ wl_surface_damage(c->wl_surface, 0, 0, image_size_x, image_size_y);
+ wl_surface_commit(c->wl_surface);
wl_pointer_set_cursor(input->wl_pointer,
input->pointer_serial,
- c->visible ? c->wl_surface : nullptr,
+ visible ? c->wl_surface : nullptr,
hotspot_x,
hotspot_y);
@@ -2558,23 +2606,81 @@ static void set_cursor_buffer(input_t *input, wl_buffer *buffer)
tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
- if (buffer) {
- /* FIXME: for some reason cursor scale is applied twice (when the scale isn't 1x),
- * this happens both in gnome-shell & KDE. Setting the surface scale here doesn't help. */
- wl_surface_set_buffer_scale(tool_input->cursor_surface, c->scale);
- wl_surface_attach(tool_input->cursor_surface, buffer, 0, 0);
- wl_surface_damage(tool_input->cursor_surface, 0, 0, image_size_x, image_size_y);
- wl_surface_commit(tool_input->cursor_surface);
- }
+ /* FIXME: for some reason cursor scale is applied twice (when the scale isn't 1x),
+ * this happens both in gnome-shell & KDE. Setting the surface scale here doesn't help. */
+ wl_surface_set_buffer_scale(tool_input->cursor_surface, c->scale);
+ wl_surface_attach(tool_input->cursor_surface, buffer, 0, 0);
+ wl_surface_damage(tool_input->cursor_surface, 0, 0, image_size_x, image_size_y);
+ wl_surface_commit(tool_input->cursor_surface);
zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
input->tablet_serial,
- c->visible ? tool_input->cursor_surface : nullptr,
+ visible ? tool_input->cursor_surface : nullptr,
hotspot_x,
hotspot_y);
}
}
+enum eCursorSetMode {
+ CURSOR_VISIBLE_ALWAYS_SET = 1,
+ CURSOR_VISIBLE_ONLY_HIDE,
+ CURSOR_VISIBLE_ONLY_SHOW,
+};
+
+static void cursor_visible_set(input_t *input,
+ const bool visible,
+ const bool is_hardware,
+ const enum eCursorSetMode set_mode)
+{
+ cursor_t *cursor = &input->cursor;
+ const bool was_visible = cursor->is_hardware && cursor->visible;
+ const bool use_visible = is_hardware && visible;
+
+ if (set_mode == CURSOR_VISIBLE_ALWAYS_SET) {
+ /* Pass. */
+ }
+ else if ((set_mode == CURSOR_VISIBLE_ONLY_SHOW)) {
+ if (!use_visible) {
+ return;
+ }
+ }
+ else if ((set_mode == CURSOR_VISIBLE_ONLY_HIDE)) {
+ if (use_visible) {
+ return;
+ }
+ }
+
+ if (use_visible) {
+ if (!was_visible) {
+ cursor_buffer_show(input);
+ }
+ }
+ else {
+ if (was_visible) {
+ cursor_buffer_hide(input);
+ }
+ }
+ cursor->visible = visible;
+ cursor->is_hardware = is_hardware;
+}
+
+static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_software_confine)
+{
+ if (mode == GHOST_kGrabWrap) {
+ return true;
+ }
+#ifdef USE_GNOME_CONFINE_HACK
+ if (mode == GHOST_kGrabNormal) {
+ if (use_software_confine) {
+ return true;
+ }
+ }
+#else
+ (void)use_software_confine;
+#endif
+ return false;
+}
+
GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape)
{
if (d->inputs.empty()) {
@@ -2605,11 +2711,12 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(GHOST_TStandardCursor shape)
return GHOST_kFailure;
}
+ c->visible = true;
c->is_custom = false;
c->wl_buffer = buffer;
c->wl_image = *image;
- set_cursor_buffer(input, buffer);
+ cursor_buffer_set(input, buffer);
return GHOST_kSuccess;
}
@@ -2714,6 +2821,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
}
}
+ cursor->visible = true;
cursor->is_custom = true;
cursor->wl_buffer = buffer;
cursor->wl_image.width = uint32_t(sizex);
@@ -2721,7 +2829,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
cursor->wl_image.hotspot_x = uint32_t(hotX);
cursor->wl_image.hotspot_y = uint32_t(hotY);
- set_cursor_buffer(d->inputs[0], buffer);
+ cursor_buffer_set(d->inputs[0], buffer);
return GHOST_kSuccess;
}
@@ -2754,19 +2862,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible)
}
input_t *input = d->inputs[0];
-
- cursor_t *cursor = &input->cursor;
- if (visible) {
- if (!cursor->visible) {
- set_cursor_buffer(input, cursor->wl_buffer);
- }
- }
- else {
- if (cursor->visible) {
- set_cursor_buffer(input, nullptr);
- }
- }
-
+ cursor_visible_set(input, visible, input->cursor.is_hardware, CURSOR_VISIBLE_ALWAYS_SET);
return GHOST_kSuccess;
}
@@ -2788,16 +2884,15 @@ bool GHOST_SystemWayland::getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCurso
if (d->inputs.empty()) {
return false;
}
- if (mode == GHOST_kGrabWrap) {
- return true;
- }
+
#ifdef USE_GNOME_CONFINE_HACK
- if (mode == GHOST_kGrabNormal) {
- const input_t *input = d->inputs[0];
- return input->xy_software_confine;
- }
+ input_t *input = d->inputs[0];
+ const bool use_software_confine = input->xy_software_confine;
+#else
+ const bool use_software_confine = false;
#endif
- return false;
+
+ return cursor_is_software(mode, use_software_confine);
}
#ifdef USE_GNOME_CONFINE_HACK
@@ -2826,6 +2921,18 @@ static bool setCursorGrab_use_software_confine(const GHOST_TGrabCursorMode mode,
}
#endif
+static input_grab_state_t input_grab_state_from_mode(const GHOST_TGrabCursorMode mode,
+ const bool use_software_confine)
+{
+ /* Initialize all members. */
+ const struct input_grab_state_t grab_state = {
+ /* Warping happens to require software cursor which also hides. */
+ .use_lock = (mode == GHOST_kGrabWrap || mode == GHOST_kGrabHide) || use_software_confine,
+ .use_confine = (mode == GHOST_kGrabNormal) && (use_software_confine == false),
+ };
+ return grab_state;
+}
+
GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode,
const GHOST_TGrabCursorMode mode_current,
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list