Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <campbell@blender.org>2022-06-30 15:53:35 +0300
committerCampbell Barton <campbell@blender.org>2022-06-30 16:46:57 +0300
commit58ccd8338e53423e223085094af2d35c76285c30 (patch)
tree4356c25db8ba4a80854a672cbddac539235aa976 /intern/ghost
parent7c98632289ead480c3d8d28f47815078a4d4c329 (diff)
GHOST/Wayland: clarify window access from surfaces
It wasn't obvious when direct access or lookups should be used. Add class methods for direct lookups as well as searching from known windows when windows are accessed outside Wayland's handlers. This avoids having to check if the window has been removed in some cases.
Diffstat (limited to 'intern/ghost')
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp160
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.cpp42
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.h12
3 files changed, 108 insertions, 106 deletions
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 6665a962e81..985310dc919 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -45,8 +45,6 @@
#include <cstring>
#include <mutex>
-static GHOST_WindowWayland *window_from_surface(struct wl_surface *surface);
-
static void keyboard_handle_key_repeat_cancel(struct input_t *input);
static void output_handle_done(void *data, struct wl_output *wl_output);
@@ -152,6 +150,8 @@ struct cursor_t {
struct tablet_tool_input_t {
struct input_t *input = nullptr;
struct wl_surface *cursor_surface = nullptr;
+ /** Used to delay clearing tablet focused surface until the frame is handled. */
+ bool proximity = false;
GHOST_TabletData data = GHOST_TABLET_DATA_NONE;
};
@@ -783,10 +783,7 @@ static void relative_pointer_handle_relative_motion(
const wl_fixed_t /*dy_unaccel*/)
{
input_t *input = static_cast<input_t *>(data);
- GHOST_WindowWayland *win = window_from_surface(input->pointer.wl_surface);
- if (!win) {
- return;
- }
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(input->pointer.wl_surface);
const wl_fixed_t scale = win->scale();
const wl_fixed_t xy_next[2] = {
input->pointer.xy[0] + (dx / scale),
@@ -809,10 +806,7 @@ static void dnd_events(const input_t *const input, const GHOST_TEventType event)
{
/* NOTE: `input->data_offer_dnd_mutex` must already be locked. */
const uint64_t time = input->system->getMilliSeconds();
- GHOST_WindowWayland *const win = window_from_surface(input->focus_dnd);
- if (!win) {
- return;
- }
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(input->focus_dnd);
const wl_fixed_t scale = win->scale();
const int event_xy[2] = {
wl_fixed_to_int(scale * input->data_offer_dnd->dnd.xy[0]),
@@ -1077,7 +1071,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
static constexpr const char *file_proto = "file://";
static constexpr const char *crlf = "\r\n";
- GHOST_WindowWayland *win = window_from_surface(surface);
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(surface);
GHOST_ASSERT(win != nullptr, "Unable to find window for drop event from surface");
std::vector<std::string> uris;
@@ -1213,19 +1207,6 @@ const struct wl_buffer_listener cursor_buffer_listener = {
/** \name Listener (Surface), #wl_surface_listener
* \{ */
-static GHOST_WindowWayland *window_from_surface(struct wl_surface *surface)
-{
- if (surface) {
- for (GHOST_IWindow *iwin : window_manager->getWindows()) {
- GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(iwin);
- if (surface == win->surface()) {
- return win;
- }
- }
- }
- return nullptr;
-}
-
static bool update_cursor_scale(cursor_t &cursor, wl_shm *shm)
{
int scale = 0;
@@ -1291,10 +1272,7 @@ static void pointer_handle_enter(void *data,
const wl_fixed_t surface_x,
const wl_fixed_t surface_y)
{
- GHOST_WindowWayland *win = window_from_surface(surface);
- if (!win) {
- return;
- }
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(surface);
win->activate();
@@ -1310,7 +1288,7 @@ static void pointer_handle_enter(void *data,
const wl_fixed_t scale = win->scale();
input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
GHOST_kEventCursorMove,
- static_cast<GHOST_WindowWayland *>(win),
+ win,
wl_fixed_to_int(scale * input->pointer.xy[0]),
wl_fixed_to_int(scale * input->pointer.xy[1]),
GHOST_TABLET_DATA_NONE));
@@ -1323,12 +1301,12 @@ static void pointer_handle_leave(void *data,
{
/* First clear the `pointer.wl_surface`, since the window won't exist when closing the window. */
static_cast<input_t *>(data)->pointer.wl_surface = nullptr;
-
- GHOST_IWindow *win = window_from_surface(surface);
- if (!win) {
+ /* Use `from_surface_find_mut` because this callback runs when the window is has been closed. */
+ if (!surface) {
return;
}
- static_cast<GHOST_WindowWayland *>(win)->deactivate();
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(surface);
+ win->deactivate();
}
static void pointer_handle_motion(void *data,
@@ -1341,10 +1319,7 @@ static void pointer_handle_motion(void *data,
input->pointer.xy[0] = surface_x;
input->pointer.xy[1] = surface_y;
- GHOST_WindowWayland *win = window_from_surface(input->pointer.wl_surface);
- if (!win) {
- return;
- }
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(input->pointer.wl_surface);
const wl_fixed_t scale = win->scale();
input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
GHOST_kEventCursorMove,
@@ -1401,11 +1376,7 @@ static void pointer_handle_button(void *data,
input->data_source_serial = serial;
input->pointer.buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
- GHOST_IWindow *win = window_from_surface(input->pointer.wl_surface);
- if (!win) {
- return;
- }
-
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(input->pointer.wl_surface);
input->system->pushEvent(new GHOST_EventButton(
input->system->getMilliSeconds(), etype, win, ebutton, GHOST_TABLET_DATA_NONE));
}
@@ -1422,10 +1393,7 @@ static void pointer_handle_axis(void *data,
return;
}
- GHOST_IWindow *win = window_from_surface(input->pointer.wl_surface);
- if (!win) {
- return;
- }
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(input->pointer.wl_surface);
input->system->pushEvent(
new GHOST_EventWheel(input->system->getMilliSeconds(), win, std::signbit(value) ? +1 : -1));
}
@@ -1497,6 +1465,7 @@ static void tablet_tool_handle_proximity_in(void *data,
struct wl_surface *surface)
{
tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
+ tool_input->proximity = true;
input_t *input = tool_input->input;
input->cursor_source_serial = serial;
@@ -1513,10 +1482,8 @@ static void tablet_tool_handle_proximity_in(void *data,
/* In case pressure isn't supported. */
td.Pressure = 1.0f;
- GHOST_WindowWayland *win = window_from_surface(input->tablet.wl_surface);
- if (!win) {
- return;
- }
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(input->tablet.wl_surface);
+
win->activate();
win->setCursorShape(win->getCursorShape());
@@ -1525,14 +1492,9 @@ static void tablet_tool_handle_proximity_out(void *data,
struct zwp_tablet_tool_v2 * /*zwp_tablet_tool_v2*/)
{
tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- input_t *input = tool_input->input;
- input->tablet.wl_surface = nullptr;
-
- GHOST_WindowWayland *win = window_from_surface(input->tablet.wl_surface);
- if (!win) {
- return;
- }
- win->setCursorShape(win->getCursorShape());
+ /* Defer clearing the surface until the frame is handled.
+ * Without this, the frame can not access the surface. */
+ tool_input->proximity = false;
}
static void tablet_tool_handle_down(void *data,
@@ -1547,10 +1509,7 @@ static void tablet_tool_handle_down(void *data,
input->data_source_serial = serial;
input->tablet.buttons.set(ebutton, true);
- GHOST_WindowWayland *win = window_from_surface(input->tablet.wl_surface);
- if (!win) {
- return;
- }
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(input->tablet.wl_surface);
input->system->pushEvent(new GHOST_EventButton(
input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data));
}
@@ -1564,10 +1523,7 @@ static void tablet_tool_handle_up(void *data, struct zwp_tablet_tool_v2 * /*zwp_
input->tablet.buttons.set(ebutton, false);
- GHOST_WindowWayland *win = window_from_surface(input->tablet.wl_surface);
- if (!win) {
- return;
- }
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(input->tablet.wl_surface);
input->system->pushEvent(new GHOST_EventButton(
input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data));
}
@@ -1591,12 +1547,6 @@ static void tablet_tool_handle_pressure(void *data,
const uint32_t pressure)
{
tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- input_t *input = tool_input->input;
- GHOST_WindowWayland *win = window_from_surface(input->tablet.wl_surface);
- if (!win) {
- return;
- }
-
GHOST_TabletData &td = tool_input->data;
td.Pressure = (float)pressure / 65535;
}
@@ -1611,12 +1561,6 @@ static void tablet_tool_handle_tilt(void *data,
const wl_fixed_t tilt_y)
{
tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
- input_t *input = tool_input->input;
- GHOST_WindowWayland *win = window_from_surface(input->tablet.wl_surface);
- if (!win) {
- return;
- }
-
GHOST_TabletData &td = tool_input->data;
/* Map degrees to `-1.0..1.0`. */
td.Xtilt = wl_fixed_to_double(tilt_x) / 90.0f;
@@ -1649,11 +1593,7 @@ static void tablet_tool_handle_wheel(void *data,
tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
input_t *input = tool_input->input;
- GHOST_WindowWayland *win = window_from_surface(input->tablet.wl_surface);
- if (!win) {
- return;
- }
-
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(input->tablet.wl_surface);
input->system->pushEvent(new GHOST_EventWheel(input->system->getMilliSeconds(), win, clicks));
}
static void tablet_tool_handle_button(void *data,
@@ -1691,10 +1631,7 @@ static void tablet_tool_handle_button(void *data,
input->data_source_serial = serial;
input->tablet.buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
- GHOST_WindowWayland *win = window_from_surface(input->tablet.wl_surface);
- if (!win) {
- return;
- }
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_mut(input->tablet.wl_surface);
input->system->pushEvent(new GHOST_EventButton(
input->system->getMilliSeconds(), etype, win, ebutton, tool_input->data));
}
@@ -1704,18 +1641,26 @@ static void tablet_tool_handle_frame(void *data,
{
tablet_tool_input_t *tool_input = static_cast<tablet_tool_input_t *>(data);
input_t *input = tool_input->input;
- GHOST_WindowWayland *win = window_from_surface(input->tablet.wl_surface);
- if (!win) {
- return;
- }
- const wl_fixed_t scale = win->scale();
- input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
- GHOST_kEventCursorMove,
- win,
- wl_fixed_to_int(scale * input->tablet.xy[0]),
- wl_fixed_to_int(scale * input->tablet.xy[1]),
- tool_input->data));
+ /* Use "find", unlike most other handlers because the window
+ * may have been closed before this handler is called. */
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_find_mut(input->tablet.wl_surface);
+ if (win) {
+ const wl_fixed_t scale = win->scale();
+ input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
+ GHOST_kEventCursorMove,
+ win,
+ wl_fixed_to_int(scale * input->tablet.xy[0]),
+ wl_fixed_to_int(scale * input->tablet.xy[1]),
+ tool_input->data));
+ }
+
+ if (tool_input->proximity == false) {
+ if (win) {
+ win->setCursorShape(win->getCursorShape());
+ }
+ input->tablet.wl_surface = nullptr;
+ }
}
static const struct zwp_tablet_tool_v2_listener tablet_tool_listner = {
@@ -2021,8 +1966,7 @@ static void keyboard_handle_key(void *data,
input->data_source_serial = serial;
- GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
- wl_surface_get_user_data(input->keyboard.wl_surface));
+ GHOST_IWindow *win = GHOST_WindowWayland::from_surface_mut(input->keyboard.wl_surface);
input->system->pushEvent(new GHOST_EventKey(
input->system->getMilliSeconds(), etype, win, gkey, '\0', utf8_buf, false));
@@ -2045,7 +1989,8 @@ static void keyboard_handle_key(void *data,
task->getUserData());
input_t *input = payload->input;
- if (GHOST_IWindow *win = window_from_surface(input->keyboard.wl_surface)) {
+ if (GHOST_IWindow *win = GHOST_WindowWayland::from_surface_find_mut(
+ input->keyboard.wl_surface)) {
GHOST_SystemWayland *system = input->system;
/* Calculate this value every time in case modifier keys are pressed. */
char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
@@ -2727,7 +2672,8 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(int32_t &x, int32_t &y) co
if (!input_state || !input_state->wl_surface) {
return GHOST_kFailure;
}
- GHOST_WindowWayland *win = window_from_surface(input->pointer.wl_surface);
+ /* Use 'from_surface_find_mut' because this can be called outside WAYLAND's event loop. */
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_find_mut(input->pointer.wl_surface);
if (!win) {
return GHOST_kFailure;
}
@@ -2743,7 +2689,8 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorPosition(const int32_t x, const int
if (!input->pointer.wl_surface) {
return GHOST_kFailure;
}
- GHOST_WindowWayland *win = window_from_surface(input->pointer.wl_surface);
+ /* Use 'from_surface_find_mut' because this can be called outside WAYLAND's event loop. */
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_find_mut(input->pointer.wl_surface);
if (!win) {
return GHOST_kFailure;
}
@@ -3333,7 +3280,8 @@ static bool setCursorGrab_use_software_confine(const GHOST_TGrabCursorMode mode,
if (mode != GHOST_kGrabNormal) {
return false;
}
- GHOST_WindowWayland *win = window_from_surface(surface);
+ /* Use 'from_surface_find_mut' because this can be called outside WAYLAND's event loop. */
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_find_mut(surface);
if (!win) {
return false;
}
@@ -3412,8 +3360,8 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo
if (input->locked_pointer) {
/* Request location to restore to. */
if (mode_current == GHOST_kGrabWrap) {
- /* The chance this fails is _very_ low. */
- GHOST_WindowWayland *win = window_from_surface(surface);
+ /* The chance this fails is _very_ low, it may be called outside WAYLAND's event loop. */
+ GHOST_WindowWayland *win = GHOST_WindowWayland::from_surface_find_mut(surface);
if (!win) {
GHOST_PRINT("could not find window from surface when un-grabbing!" << std::endl);
}
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index 27bda5ea41e..dd61832e2ee 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -14,6 +14,7 @@
#include "GHOST_ContextEGL.h"
#include "GHOST_ContextNone.h"
+#include <wayland-client-protocol.h>
#include <wayland-egl.h>
#include <algorithm> /* For `std::find`. */
@@ -24,6 +25,8 @@
static constexpr size_t base_dpi = 96;
+static GHOST_WindowManager *window_manager = nullptr;
+
struct window_t {
GHOST_WindowWayland *w = nullptr;
struct wl_surface *wl_surface = nullptr;
@@ -380,6 +383,11 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
m_system(system),
w(new window_t)
{
+ /* Globally store pointer to window manager. */
+ if (!window_manager) {
+ window_manager = m_system->getWindowManager();
+ }
+
w->w = this;
w->size[0] = int32_t(width);
@@ -521,6 +529,40 @@ wl_surface *GHOST_WindowWayland::surface() const
return w->wl_surface;
}
+GHOST_WindowWayland *GHOST_WindowWayland::from_surface_find_mut(const wl_surface *surface)
+{
+ GHOST_ASSERT(surface, "argument must not be NULL");
+ for (GHOST_IWindow *iwin : window_manager->getWindows()) {
+ GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(iwin);
+ if (surface == win->surface()) {
+ return win;
+ }
+ }
+ return nullptr;
+}
+
+const GHOST_WindowWayland *GHOST_WindowWayland::from_surface_find(const wl_surface *surface)
+{
+ return GHOST_WindowWayland::from_surface_find_mut(surface);
+}
+
+GHOST_WindowWayland *GHOST_WindowWayland::from_surface_mut(wl_surface *surface)
+{
+ GHOST_WindowWayland *win = static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface));
+ GHOST_ASSERT(win == GHOST_WindowWayland::from_surface_find_mut(surface),
+ "Inconsistent window state, consider using \"from_surface_find_mut\"");
+ return win;
+}
+
+const GHOST_WindowWayland *GHOST_WindowWayland::from_surface(const wl_surface *surface)
+{
+ const GHOST_WindowWayland *win = static_cast<const GHOST_WindowWayland *>(
+ wl_surface_get_user_data(const_cast<wl_surface *>(surface)));
+ GHOST_ASSERT(win == GHOST_WindowWayland::from_surface_find(surface),
+ "Inconsistent window state, consider using \"from_surface_find\"");
+ return win;
+}
+
const std::vector<output_t *> &GHOST_WindowWayland::outputs()
{
return w->outputs;
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
index b5aeecd6204..1d0693ff1f8 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.h
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -105,6 +105,18 @@ class GHOST_WindowWayland : public GHOST_Window {
struct wl_surface *surface() const;
+ /**
+ * Use window find function when the window may have been closed.
+ * Typically this is needed when accessing surfaces outside WAYLAND handlers.
+ */
+ static const GHOST_WindowWayland *from_surface_find(const wl_surface *surface);
+ static GHOST_WindowWayland *from_surface_find_mut(const wl_surface *surface);
+ /**
+ * Use direct access when from WAYLAND handlers.
+ */
+ static const GHOST_WindowWayland *from_surface(const wl_surface *surface);
+ static GHOST_WindowWayland *from_surface_mut(wl_surface *surface);
+
output_t *output_find_by_wl(struct wl_output *output);
const std::vector<output_t *> &outputs();