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-10-21 02:00:09 +0300
committerCampbell Barton <campbell@blender.org>2022-10-21 03:08:03 +0300
commitff8c0f062a6ac521b13ebbda3103cda4f9a4dc46 (patch)
tree44e314c19540043590a1774638440c97ea9ce128
parent97f4e076c7fcd362c9803dcf1afb303c110c997e (diff)
GHOST/Wayland: code comments, minor improvements
- Clarify how data_offer is used for both the clipboard & drag-and-drop. - Acquire the clipboards mutex lock before freeing. - Log a warning when creating a pipe fails. - Add doxy-sections.
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp203
1 files changed, 132 insertions, 71 deletions
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index fb69973eac6..68ad028631c 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -234,7 +234,7 @@ static const GWL_ModifierInfo g_modifier_info_table[MOD_INDEX_NUM] = {
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Private Types & Defines
+/** \name Internal #GWL_SimpleBuffer Type
* \{ */
struct GWL_SimpleBuffer {
@@ -250,7 +250,9 @@ static void gwl_simple_buffer_free_data(GWL_SimpleBuffer *buffer)
buffer->data_size = 0;
}
-static void gwl_simple_buffer_set(GWL_SimpleBuffer *buffer, const char *data, size_t data_size)
+static void gwl_simple_buffer_set_and_take_ownership(GWL_SimpleBuffer *buffer,
+ const char *data,
+ size_t data_size)
{
free(const_cast<char *>(buffer->data));
buffer->data = data;
@@ -274,6 +276,12 @@ static char *gwl_simple_buffer_as_string(const GWL_SimpleBuffer *buffer)
return buffer_str;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_Cursor Type
+ * \{ */
+
/**
* From XKB internals, use for converting a scan-code from WAYLAND to a #xkb_keycode_t.
* Ideally this wouldn't need a local define.
@@ -289,16 +297,26 @@ struct GWL_Cursor {
* the hardware cursor is used.
*/
bool is_hardware = true;
+ /** When true, a custom image is used to display the cursor (stored in `wl_image`). */
bool is_custom = false;
struct wl_surface *wl_surface = nullptr;
struct wl_buffer *wl_buffer = nullptr;
struct wl_cursor_image wl_image = {0};
struct wl_cursor_theme *wl_theme = nullptr;
void *custom_data = nullptr;
+ /** The size of `custom_data` in bytes. */
size_t custom_data_size = 0;
- int size = 0;
+ /**
+ * The name of the theme (loaded by DBUS, depends on #WITH_GHOST_WAYLAND_DBUS).
+ * When disabled, leave as an empty string and the default theme will be used.
+ */
std::string theme_name;
-
+ /**
+ * The size of the cursor (when looking up a cursor theme).
+ * This must be scaled by the maximum output scale when passing to wl_cursor_theme_load.
+ * See #update_cursor_scale.
+ * */
+ int theme_size = 0;
int custom_scale = 1;
};
@@ -309,6 +327,7 @@ struct GWL_Cursor {
*/
struct GWL_TabletTool {
struct GWL_Seat *seat = nullptr;
+ /** Tablets have a separate cursor to the 'pointer', this surface is used for cursor drawing. */
struct wl_surface *wl_surface_cursor = nullptr;
/** Used to delay clearing tablet focused wl_surface until the frame is handled. */
bool proximity = false;
@@ -316,23 +335,51 @@ struct GWL_TabletTool {
GHOST_TabletData data = GHOST_TABLET_DATA_NONE;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_DataOffer Type
+ * \{ */
+
+/**
+ * Data storage used for clipboard paste & drag-and-drop.
+ */
struct GWL_DataOffer {
- std::unordered_set<std::string> types;
- uint32_t source_actions = 0;
- uint32_t dnd_action = 0;
struct wl_data_offer *id = nullptr;
+ std::unordered_set<std::string> types;
std::atomic<bool> in_use = false;
+
struct {
+ /**
+ * Bit-mask with available drop options.
+ * #WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY, #WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE.. etc.
+ * The application that initializes the drag may set these depending on modifiers held
+ * \note when dragging begins. Currently ghost doesn't make use of these.
+ */
+ enum wl_data_device_manager_dnd_action source_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+ enum wl_data_device_manager_dnd_action action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
/** Compatible with #GWL_Seat.xy coordinates. */
wl_fixed_t xy[2] = {0, 0};
} dnd;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_DataSource Type
+ * \{ */
+
struct GWL_DataSource {
- struct wl_data_source *wl_data_source = nullptr;
+ struct wl_data_source *wl_source = nullptr;
GWL_SimpleBuffer buffer_out;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_Seat Type (#wl_seat wrapper & associated types)
+ * \{ */
+
/**
* Data used to implement client-side key-repeat.
*
@@ -605,6 +652,12 @@ struct GWL_Seat {
uint32_t data_source_serial = 0;
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_Display Type (#wl_display & #wl_compositor wrapper)
+ * \{ */
+
struct GWL_Display {
GHOST_SystemWayland *system = nullptr;
@@ -633,8 +686,6 @@ struct GWL_Display {
GWL_SimpleBuffer clipboard_primary;
};
-#undef LOG
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -710,8 +761,8 @@ static void display_destroy(GWL_Display *display)
std::lock_guard lock{seat->data_source_mutex};
if (seat->data_source) {
gwl_simple_buffer_free_data(&seat->data_source->buffer_out);
- if (seat->data_source->wl_data_source) {
- wl_data_source_destroy(seat->data_source->wl_data_source);
+ if (seat->data_source->wl_source) {
+ wl_data_source_destroy(seat->data_source->wl_source);
}
delete seat->data_source;
}
@@ -833,8 +884,11 @@ static void display_destroy(GWL_Display *display)
wl_display_disconnect(display->wl_display);
}
- gwl_simple_buffer_free_data(&display->clipboard);
- gwl_simple_buffer_free_data(&display->clipboard_primary);
+ {
+ std::lock_guard lock{system_clipboard_mutex};
+ gwl_simple_buffer_free_data(&display->clipboard);
+ gwl_simple_buffer_free_data(&display->clipboard_primary);
+ }
delete display;
}
@@ -1399,16 +1453,17 @@ static const char *read_file_as_buffer(const int fd, size_t *r_len)
return buf;
}
-static const char *read_pipe(GWL_DataOffer *data_offer,
- const std::string mime_receive,
- std::mutex *mutex,
- size_t *r_len)
+static const char *read_buffer_from_data_offer(GWL_DataOffer *data_offer,
+ const char *mime_receive,
+ std::mutex *mutex,
+ size_t *r_len)
{
int pipefd[2];
if (UNLIKELY(pipe(pipefd) != 0)) {
- return {};
+ CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno));
+ return nullptr;
}
- wl_data_offer_receive(data_offer->id, mime_receive.c_str(), pipefd[1]);
+ wl_data_offer_receive(data_offer->id, mime_receive, pipefd[1]);
close(pipefd[1]);
data_offer->in_use.store(false);
@@ -1423,16 +1478,18 @@ static const char *read_pipe(GWL_DataOffer *data_offer,
return buf;
}
-static const char *read_pipe_primary(GWL_PrimarySelection_DataOffer *data_offer,
- const std::string mime_receive,
- std::mutex *mutex,
- size_t *r_len)
+static const char *read_buffer_from_primary_selection_offer(
+ GWL_PrimarySelection_DataOffer *data_offer,
+ const char *mime_receive,
+ std::mutex *mutex,
+ size_t *r_len)
{
int pipefd[2];
if (UNLIKELY(pipe(pipefd) != 0)) {
- return {};
+ CLOG_WARN(LOG, "error creating pipe: %s", std::strerror(errno));
+ return nullptr;
}
- zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive.c_str(), pipefd[1]);
+ zwp_primary_selection_offer_v1_receive(data_offer->id, mime_receive, pipefd[1]);
close(pipefd[1]);
data_offer->in_use.store(false);
@@ -1481,8 +1538,8 @@ static void data_source_handle_cancelled(void *data, struct wl_data_source *wl_d
CLOG_INFO(LOG, 2, "cancelled");
GWL_Seat *seat = static_cast<GWL_Seat *>(data);
GWL_DataSource *data_source = seat->data_source;
- if (seat->data_source->wl_data_source == wl_data_source) {
- data_source->wl_data_source = nullptr;
+ if (seat->data_source->wl_source == wl_data_source) {
+ data_source->wl_source = nullptr;
}
wl_data_source_destroy(wl_data_source);
@@ -1553,7 +1610,8 @@ static void data_offer_handle_offer(void *data,
const char *mime_type)
{
CLOG_INFO(LOG, 2, "offer (mime_type=%s)", mime_type);
- static_cast<GWL_DataOffer *>(data)->types.insert(mime_type);
+ GWL_DataOffer *data_offer = static_cast<GWL_DataOffer *>(data);
+ data_offer->types.insert(mime_type);
}
static void data_offer_handle_source_actions(void *data,
@@ -1561,7 +1619,8 @@ static void data_offer_handle_source_actions(void *data,
const uint32_t source_actions)
{
CLOG_INFO(LOG, 2, "source_actions (%u)", source_actions);
- static_cast<GWL_DataOffer *>(data)->source_actions = source_actions;
+ GWL_DataOffer *data_offer = static_cast<GWL_DataOffer *>(data);
+ data_offer->dnd.source_actions = (enum wl_data_device_manager_dnd_action)source_actions;
}
static void data_offer_handle_action(void *data,
@@ -1569,7 +1628,8 @@ static void data_offer_handle_action(void *data,
const uint32_t dnd_action)
{
CLOG_INFO(LOG, 2, "actions (%u)", dnd_action);
- static_cast<GWL_DataOffer *>(data)->dnd_action = dnd_action;
+ GWL_DataOffer *data_offer = static_cast<GWL_DataOffer *>(data);
+ data_offer->dnd.action = (enum wl_data_device_manager_dnd_action)dnd_action;
}
static const struct wl_data_offer_listener data_offer_listener = {
@@ -1693,7 +1753,8 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
const wl_fixed_t xy[2] = {UNPACK2(data_offer->dnd.xy)};
size_t data_buf_len = 0;
- const char *data_buf = read_pipe(data_offer, mime_receive, nullptr, &data_buf_len);
+ const char *data_buf = read_buffer_from_data_offer(
+ data_offer, mime_receive.c_str(), nullptr, &data_buf_len);
std::string data = data_buf ? std::string(data_buf, data_buf_len) : "";
free(const_cast<char *>(data_buf));
@@ -1812,13 +1873,13 @@ static void data_device_handle_selection(void *data,
}
size_t data_len = 0;
- const char *data = read_pipe(
- data_offer, mime_receive, &seat->data_offer_copy_paste_mutex, &data_len);
+ const char *data = read_buffer_from_data_offer(
+ data_offer, mime_receive.c_str(), &seat->data_offer_copy_paste_mutex, &data_len);
{
std::lock_guard lock{system_clipboard_mutex};
GWL_SimpleBuffer *buf = system->clipboard_data(false);
- gwl_simple_buffer_set(buf, data, data_len);
+ gwl_simple_buffer_set_and_take_ownership(buf, data, data_len);
}
};
@@ -1892,7 +1953,8 @@ static bool update_cursor_scale(GWL_Cursor &cursor,
wl_surface_set_buffer_scale(wl_cursor_surface, scale);
}
wl_cursor_theme_destroy(cursor.wl_theme);
- cursor.wl_theme = wl_cursor_theme_load(cursor.theme_name.c_str(), scale * cursor.size, shm);
+ cursor.wl_theme = wl_cursor_theme_load(
+ cursor.theme_name.c_str(), scale * cursor.theme_size, shm);
return true;
}
return false;
@@ -3165,13 +3227,13 @@ static void primary_selection_device_handle_selection(
}
}
size_t data_len = 0;
- const char *data = read_pipe_primary(
- data_offer, mime_receive, &primary->data_offer_mutex, &data_len);
+ const char *data = read_buffer_from_primary_selection_offer(
+ data_offer, mime_receive.c_str(), &primary->data_offer_mutex, &data_len);
{
std::lock_guard lock{system_clipboard_mutex};
GWL_SimpleBuffer *buf = system->clipboard_data(true);
- gwl_simple_buffer_set(buf, data, data_len);
+ gwl_simple_buffer_set_and_take_ownership(buf, data, data_len);
}
};
@@ -3262,9 +3324,9 @@ static void seat_handle_capabilities(void *data,
seat->cursor.wl_surface = wl_compositor_create_surface(seat->system->wl_compositor());
seat->cursor.visible = true;
seat->cursor.wl_buffer = nullptr;
- if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.size)) {
+ if (!get_cursor_settings(seat->cursor.theme_name, seat->cursor.theme_size)) {
seat->cursor.theme_name = std::string();
- seat->cursor.size = default_cursor_size;
+ seat->cursor.theme_size = default_cursor_size;
}
wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, data);
@@ -3990,18 +4052,17 @@ static void system_clipboard_put(GWL_Display *display, const char *buffer)
/* Copy buffer. */
gwl_simple_buffer_set_from_string(&data_source->buffer_out, buffer);
- data_source->wl_data_source = wl_data_device_manager_create_data_source(
- display->data_device_manager);
+ data_source->wl_source = wl_data_device_manager_create_data_source(display->data_device_manager);
- wl_data_source_add_listener(data_source->wl_data_source, &data_source_listener, seat);
+ wl_data_source_add_listener(data_source->wl_source, &data_source_listener, seat);
for (const std::string &type : mime_send) {
- wl_data_source_offer(data_source->wl_data_source, type.c_str());
+ wl_data_source_offer(data_source->wl_source, type.c_str());
}
if (seat->data_device) {
wl_data_device_set_selection(
- seat->data_device, data_source->wl_data_source, seat->data_source_serial);
+ seat->data_device, data_source->wl_source, seat->data_source_serial);
}
}
@@ -4284,22 +4345,22 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
*/
static void cursor_buffer_show(const GWL_Seat *seat)
{
- const GWL_Cursor *c = &seat->cursor;
+ const GWL_Cursor *cursor = &seat->cursor;
if (seat->wl_pointer) {
- const int scale = c->is_custom ? c->custom_scale : seat->pointer.theme_scale;
- const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale;
- const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale;
+ const int scale = cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale;
+ const int32_t hotspot_x = int32_t(cursor->wl_image.hotspot_x) / scale;
+ const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale;
if (seat->wl_pointer) {
wl_pointer_set_cursor(
- seat->wl_pointer, seat->pointer.serial, c->wl_surface, hotspot_x, hotspot_y);
+ seat->wl_pointer, seat->pointer.serial, cursor->wl_surface, hotspot_x, hotspot_y);
}
}
if (!seat->tablet_tools.empty()) {
- const int scale = c->is_custom ? c->custom_scale : seat->tablet.theme_scale;
- const int32_t hotspot_x = int32_t(c->wl_image.hotspot_x) / scale;
- const int32_t hotspot_y = int32_t(c->wl_image.hotspot_y) / scale;
+ const int scale = cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale;
+ const int32_t hotspot_x = int32_t(cursor->wl_image.hotspot_x) / scale;
+ const int32_t hotspot_y = int32_t(cursor->wl_image.hotspot_y) / scale;
for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
@@ -4362,21 +4423,21 @@ static void cursor_buffer_set_surface_impl(const GWL_Seat *seat,
static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer)
{
- const GWL_Cursor *c = &seat->cursor;
+ const GWL_Cursor *cursor = &seat->cursor;
const wl_cursor_image *wl_image = &seat->cursor.wl_image;
- const bool visible = (c->visible && c->is_hardware);
+ const bool visible = (cursor->visible && cursor->is_hardware);
/* This is a requirement of WAYLAND, when this isn't the case,
* it causes Blender's window to close intermittently. */
if (seat->wl_pointer) {
const int scale = cursor_buffer_compatible_scale_from_image(
- wl_image, c->is_custom ? c->custom_scale : seat->pointer.theme_scale);
+ wl_image, cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale);
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
- cursor_buffer_set_surface_impl(seat, buffer, c->wl_surface, scale);
+ cursor_buffer_set_surface_impl(seat, buffer, cursor->wl_surface, scale);
wl_pointer_set_cursor(seat->wl_pointer,
seat->pointer.serial,
- visible ? c->wl_surface : nullptr,
+ visible ? cursor->wl_surface : nullptr,
hotspot_x,
hotspot_y);
}
@@ -4384,7 +4445,7 @@ static void cursor_buffer_set(const GWL_Seat *seat, wl_buffer *buffer)
/* Set the cursor for all tablet tools as well. */
if (!seat->tablet_tools.empty()) {
const int scale = cursor_buffer_compatible_scale_from_image(
- wl_image, c->is_custom ? c->custom_scale : seat->tablet.theme_scale);
+ wl_image, cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale);
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
for (struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->tablet_tools) {
@@ -4471,31 +4532,31 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s
(*cursor_find).second;
GWL_Seat *seat = display_->seats[0];
- GWL_Cursor *c = &seat->cursor;
+ GWL_Cursor *cursor = &seat->cursor;
- if (!c->wl_theme) {
+ if (!cursor->wl_theme) {
/* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */
- c->wl_theme = wl_cursor_theme_load(
- c->theme_name.c_str(), c->size, display_->seats[0]->system->wl_shm());
+ cursor->wl_theme = wl_cursor_theme_load(
+ cursor->theme_name.c_str(), cursor->theme_size, wl_shm());
}
- wl_cursor *cursor = wl_cursor_theme_get_cursor(c->wl_theme, cursor_name);
+ wl_cursor *wl_cursor = wl_cursor_theme_get_cursor(cursor->wl_theme, cursor_name);
- if (!cursor) {
+ if (!wl_cursor) {
GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl);
return GHOST_kFailure;
}
- struct wl_cursor_image *image = cursor->images[0];
+ struct wl_cursor_image *image = wl_cursor->images[0];
struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
if (!buffer) {
return GHOST_kFailure;
}
- c->visible = true;
- c->is_custom = false;
- c->wl_buffer = buffer;
- c->wl_image = *image;
+ cursor->visible = true;
+ cursor->is_custom = false;
+ cursor->wl_buffer = buffer;
+ cursor->wl_image = *image;
cursor_buffer_set(seat, buffer);