summaryrefslogtreecommitdiff
path: root/src/platform/wayland
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 23:41:31 +0300
commit76073fe5fad8799e5850805f2f090af2cb62c741 (patch)
tree9658019babe4760a3634bdab4da0731a10e42e68 /src/platform/wayland
parentdd1775a9927922c14f8679ccbc4d3ca8d5917e20 (diff)
Simplify the public event and CPU API
Applications now need far less ceremony: hello.c is a 20-line loop that handles REFRESH, CLOSE and QUIT and draws into the surface's own pixels. - Fold GEOMETRY, STATE and FOCUS into one WINDOW event carrying size, scale and state; unchanged values send nothing. - Guarantee REFRESH once a window has a size and after every resize, never at size zero. - Merge DROP_HOVER into DROP with over/leave/data actions and give drag and drop actions enums. - Keep event strings valid until the next wait and drop yasl_event_release; empty or failed waits report NONE. - Replace copy-in presentation with a lent pixel buffer: yasl_cpu_pixels and yasl_cpu_present. - Remove yasl_poll_event, yasl_cpu_read_pixels, unused event fields and comments that restated names. - Wayland: resize floating windows in request_size instead of reporting it unsupported, and stop marking new GPU surfaces as Vulkan so yasl_vulkan_create_surface no longer fails with NATIVE_WINDOW_IN_USE. Also includes the in-progress public API refactor that was uncommitted in the tree (removal of the app/loop layer, new surface, GL and Vulkan entry points). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'src/platform/wayland')
-rw-r--r--src/platform/wayland/api.h50
-rw-r--r--src/platform/wayland/backend.c236
-rw-r--r--src/platform/wayland/buffer.c93
-rw-r--r--src/platform/wayland/clipboard.c60
-rw-r--r--src/platform/wayland/clipboard.h16
-rw-r--r--src/platform/wayland/drag.c54
-rw-r--r--src/platform/wayland/ime.c147
-rw-r--r--src/platform/wayland/internal.h70
-rw-r--r--src/platform/wayland/keyboard.c60
-rw-r--r--src/platform/wayland/keymap.c2
-rw-r--r--src/platform/wayland/keymap.h6
-rw-r--r--src/platform/wayland/native.c14
-rw-r--r--src/platform/wayland/pointer.c398
-rw-r--r--src/platform/wayland/popup.c79
-rw-r--r--src/platform/wayland/shell.c50
-rw-r--r--src/platform/wayland/surface.c119
16 files changed, 1007 insertions, 447 deletions
diff --git a/src/platform/wayland/api.h b/src/platform/wayland/api.h
index 0f935b2..9670af1 100644
--- a/src/platform/wayland/api.h
+++ b/src/platform/wayland/api.h
@@ -1,48 +1,48 @@
-#ifndef YASL_WAYLAND_API_H
-#define YASL_WAYLAND_API_H
+#ifndef YASL_PRIVATE_WAYLAND_API_H
+#define YASL_PRIVATE_WAYLAND_API_H
-#include "yasl/yasl.h"
+#include "common/types.h"
struct wayland_display;
struct wayland_surface;
-struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struct yasl_display_spec *spec);
+struct wayland_display *wayland_display_open(struct yasl_private_loop *loop, const struct yasl_private_display_spec *spec);
void wayland_display_close(struct wayland_display *d);
uint32_t wayland_display_caps(const struct wayland_display *d);
int wayland_display_dispatch_timeout(struct wayland_display *d, int timeout_ms);
void wayland_display_flush(struct wayland_display *d);
int wayland_display_modifiers(const struct wayland_display *d);
-void wayland_display_copy(struct wayland_display *d, enum yasl_selection sel, const char *text);
-void wayland_display_paste(struct wayland_display *d, enum yasl_selection sel, struct wayland_surface *target);
-bool wayland_display_copy_text(struct wayland_display *d, enum yasl_selection sel, const char *text);
-bool wayland_display_request_paste(struct wayland_display *d, enum yasl_selection sel,
+void wayland_display_copy(struct wayland_display *d, enum yasl_private_selection sel, const char *text);
+void wayland_display_paste(struct wayland_display *d, enum yasl_private_selection sel, struct wayland_surface *target);
+bool wayland_display_copy_text(struct wayland_display *d, enum yasl_private_selection sel, const char *text);
+bool wayland_display_request_paste(struct wayland_display *d, enum yasl_private_selection sel,
struct wayland_surface *target, uint64_t request_id);
-bool wayland_display_drag_start(struct wayland_display *d, struct wayland_surface *origin, const struct yasl_drag_image *image, const struct yasl_drag_listener *l, void *ud);
+bool wayland_display_drag_start(struct wayland_display *d, struct wayland_surface *origin, const struct yasl_private_drag_image *image, const struct yasl_private_drag_listener *l, void *ud);
void wayland_display_drag_cancel(struct wayland_display *d);
struct wayland_surface *wayland_surface_create_toplevel(struct wayland_display *d,
- const struct yasl_window_spec *spec, void *graphics_device);
-struct wayland_surface *wayland_surface_create_popup(struct wayland_surface *parent, const struct yasl_popup_spec *spec);
-bool wayland_surface_popup_reposition(struct wayland_surface *popup, const struct yasl_popup_spec *spec);
+ const struct yasl_private_window_spec *spec, void *graphics_device);
+struct wayland_surface *wayland_surface_create_popup(struct wayland_surface *parent, const struct yasl_private_popup_spec *spec);
+bool wayland_surface_popup_reposition(struct wayland_surface *popup, const struct yasl_private_popup_spec *spec);
void wayland_surface_destroy(struct wayland_surface *s);
-void wayland_surface_set_callbacks(struct wayland_surface *s, const struct yasl_window_cbs *cbs, void *ud);
+void wayland_surface_set_callbacks(struct wayland_surface *s, const struct yasl_private_window_cbs *cbs, void *ud);
void wayland_surface_set_title(struct wayland_surface *s, const char *title);
void wayland_surface_schedule_redraw(struct wayland_surface *s);
-bool wayland_surface_present(struct wayland_surface *s, const struct yasl_framebuffer *fb, const struct yasl_damage_list *damage);
-bool wayland_surface_poll_event(struct wayland_surface *s, struct yasl_event *ev);
-struct yasl_geometry wayland_surface_geometry(const struct wayland_surface *s);
-struct yasl_timing wayland_surface_timing(const struct wayland_surface *s);
-void wayland_surface_set_cursor(struct wayland_surface *s, enum yasl_cursor cursor);
-bool wayland_surface_set_pointer_mode(struct wayland_surface *s, enum yasl_pointer_mode mode);
+bool wayland_surface_present(struct wayland_surface *s, const struct yasl_private_framebuffer *fb, const struct yasl_private_damage_list *damage);
+bool wayland_surface_poll_event(struct wayland_surface *s, struct yasl_private_event *ev);
+struct yasl_private_geometry wayland_surface_geometry(const struct wayland_surface *s);
+struct yasl_private_timing wayland_surface_timing(const struct wayland_surface *s);
+void wayland_surface_set_cursor(struct wayland_surface *s, enum yasl_private_cursor cursor);
+bool wayland_surface_set_pointer_mode(struct wayland_surface *s, enum yasl_private_pointer_mode mode);
void wayland_surface_set_background_color(struct wayland_surface *s, uint32_t bg);
bool wayland_surface_ime_preedit_cursor(const struct wayland_surface *s, int *begin, int *end);
-void wayland_surface_set_ime_caret(struct wayland_surface *s, struct yasl_rect2i caret);
+void wayland_surface_set_ime_caret(struct wayland_surface *s, struct yasl_private_rect2i caret);
bool wayland_surface_start_interactive_move(struct wayland_surface *s);
-bool wayland_surface_start_interactive_resize(struct wayland_surface *s, enum yasl_resize_edge edge);
-bool wayland_surface_show_window_menu(struct wayland_surface *s, struct yasl_vector2i pos);
-bool wayland_surface_drag_carry(struct wayland_surface *s, struct yasl_vector2i offset);
-bool wayland_surface_place_under_pointer(struct wayland_surface *s, struct yasl_vector2i at);
+bool wayland_surface_start_interactive_resize(struct wayland_surface *s, enum yasl_private_resize_edge edge);
+bool wayland_surface_show_window_menu(struct wayland_surface *s, struct yasl_private_vector2i pos);
+bool wayland_surface_drag_carry(struct wayland_surface *s, struct yasl_private_vector2i offset);
+bool wayland_surface_place_under_pointer(struct wayland_surface *s, struct yasl_private_vector2i at);
bool wayland_surface_bell(struct wayland_surface *s);
bool wayland_surface_read_pixels(struct wayland_surface *s, uint32_t *out, size_t cap,
- struct yasl_vector2i *size);
+ struct yasl_private_vector2i *size);
#endif
diff --git a/src/platform/wayland/backend.c b/src/platform/wayland/backend.c
index 7026a8c..02aae59 100644
--- a/src/platform/wayland/backend.c
+++ b/src/platform/wayland/backend.c
@@ -2,50 +2,50 @@
#include "platform/freedesktop/dbus.h"
#include <errno.h>
-static struct yasl_display *impl_display_open(struct yasl_loop *loop, const struct yasl_display_spec *spec)
+static struct yasl_private_display *impl_display_open(struct yasl_private_loop *loop, const struct yasl_private_display_spec *spec)
{
struct wayland_display *result = wayland_display_open(loop, spec);
return result ? &result->base : NULL;
}
-static void impl_display_close(struct yasl_display *d)
+static void impl_display_close(struct yasl_private_display *d)
{
wayland_display_close((struct wayland_display *)d);
}
-static uint32_t impl_display_caps(const struct yasl_display *d)
+static uint32_t impl_display_caps(const struct yasl_private_display *d)
{
return wayland_display_caps((const struct wayland_display *)d);
}
-static int impl_display_dispatch_timeout(struct yasl_display *d, int timeout_ms)
+static int impl_display_dispatch_timeout(struct yasl_private_display *d, int timeout_ms)
{
return wayland_display_dispatch_timeout((struct wayland_display *)d, timeout_ms);
}
-static void impl_display_flush(struct yasl_display *d)
+static void impl_display_flush(struct yasl_private_display *d)
{
wayland_display_flush((struct wayland_display *)d);
}
-static int impl_display_modifiers(const struct yasl_display *d)
+static int impl_display_modifiers(const struct yasl_private_display *d)
{
return wayland_display_modifiers((const struct wayland_display *)d);
}
-static int impl_display_double_click_ms(const struct yasl_display *d)
+static int impl_display_double_click_ms(const struct yasl_private_display *d)
{
/* Wayland has no protocol for it; desktops publish it as a setting. */
(void)d;
return portal_double_click_ms();
}
-static void impl_display_copy(struct yasl_display *d, enum yasl_selection sel, const char *text)
+static void impl_display_copy(struct yasl_private_display *d, enum yasl_private_selection sel, const char *text)
{
wayland_display_copy((struct wayland_display *)d, sel, text);
}
-static bool impl_display_copy_text(struct yasl_display *d, enum yasl_selection sel,
+static bool impl_display_copy_text(struct yasl_private_display *d, enum yasl_private_selection sel,
const char *text)
{
bool ok = wayland_display_copy_text((struct wayland_display *)d, sel, text);
@@ -53,12 +53,12 @@ static bool impl_display_copy_text(struct yasl_display *d, enum yasl_selection s
return ok;
}
-static void impl_display_paste(struct yasl_display *d, enum yasl_selection sel, struct yasl_surface *target)
+static void impl_display_paste(struct yasl_private_display *d, enum yasl_private_selection sel, struct yasl_surface *target)
{
wayland_display_paste((struct wayland_display *)d, sel, (struct wayland_surface *)target);
}
-static bool impl_display_request_paste(struct yasl_display *d, enum yasl_selection sel,
+static bool impl_display_request_paste(struct yasl_private_display *d, enum yasl_private_selection sel,
struct yasl_surface *target, uint64_t request_id)
{
bool ok = wayland_display_request_paste((struct wayland_display *)d, sel,
@@ -67,30 +67,171 @@ static bool impl_display_request_paste(struct yasl_display *d, enum yasl_selecti
return ok;
}
-static bool impl_display_drag_start(struct yasl_display *d, struct yasl_surface *origin, const struct yasl_drag_image *image, const struct yasl_drag_listener *l, void *ud)
+static bool impl_display_drag_start(struct yasl_private_display *d, struct yasl_surface *origin, const struct yasl_private_drag_image *image, const struct yasl_private_drag_listener *l, void *ud)
{
return wayland_display_drag_start((struct wayland_display *)d, (struct wayland_surface *)origin, image, l, ud);
}
-static void impl_display_drag_cancel(struct yasl_display *d)
+static void impl_display_drag_cancel(struct yasl_private_display *d)
{
wayland_display_drag_cancel((struct wayland_display *)d);
}
-static struct yasl_surface *impl_surface_create_toplevel(struct yasl_display *d,
- const struct yasl_window_spec *spec, void *graphics_device)
+static struct yasl_surface *impl_surface_create_toplevel(struct yasl_private_display *d,
+ const struct yasl_private_window_spec *spec, void *graphics_device)
{
struct wayland_surface *result = wayland_surface_create_toplevel((struct wayland_display *)d, spec, graphics_device);
return result ? &result->base : NULL;
}
-static struct yasl_surface *impl_surface_create_popup(struct yasl_surface *parent, const struct yasl_popup_spec *spec)
+static bool impl_surface_update_text_input(struct yasl_surface *s)
+{
+ return wayland_surface_update_text_input((struct wayland_surface *)s);
+}
+
+#if YASL_HAS_EGL
+static bool egl_configure(struct wayland_display *d, const struct yasl_private_gl_options *o, EGLConfig *config)
+{
+ if (!d->egl_initialized) return false;
+ EGLint renderable = o->api == YASL_PRIVATE_GL_OPENGL_ES
+ ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT;
+#ifdef EGL_OPENGL_ES_BIT
+ if (o->api == YASL_PRIVATE_GL_OPENGL_ES && o->major < 2)
+ renderable = EGL_OPENGL_ES_BIT;
+#endif
+#ifdef EGL_OPENGL_ES3_BIT_KHR
+ if (o->api == YASL_PRIVATE_GL_OPENGL_ES && o->major >= 3)
+ renderable = EGL_OPENGL_ES3_BIT_KHR;
+#endif
+ EGLint attrs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, renderable,
+ EGL_RED_SIZE, o->red_bits,
+ EGL_GREEN_SIZE, o->green_bits,
+ EGL_BLUE_SIZE, o->blue_bits,
+ EGL_ALPHA_SIZE, o->alpha_bits,
+ EGL_DEPTH_SIZE, o->depth_bits,
+ EGL_STENCIL_SIZE, o->stencil_bits,
+ EGL_SAMPLE_BUFFERS, o->samples > 0 ? 1 : 0,
+ EGL_SAMPLES, o->samples,
+ EGL_NONE,
+ };
+ EGLint api = o->api == YASL_PRIVATE_GL_OPENGL_ES ? EGL_OPENGL_ES_API : EGL_OPENGL_API;
+ if (d->egl_api && d->egl_api != api) return false;
+ EGLint count = 0;
+ if (!eglChooseConfig(d->egl_display, attrs, config, 1, &count) || count < 1)
+ return false;
+ d->egl_api = api;
+ return eglBindAPI(api) == EGL_TRUE;
+}
+
+static struct yasl_surface *impl_surface_create_gl(struct yasl_private_display *display,
+ const struct yasl_private_window_spec *spec, const int *attributes, struct yasl_surface *share)
+{
+ struct wayland_display *d = (struct wayland_display *)display;
+ struct yasl_private_gl_options o;
+ if (!spec || !yasl_private_gl_parse_options(attributes, &o) || !d || !d->egl_initialized)
+ return NULL;
+ struct yasl_private_window_spec gl_spec = *spec;
+ gl_spec.external_gpu = true;
+ gl_spec.flags &= ~YASL_PRIVATE_SURFACE_CPU;
+ struct wayland_surface *w = wayland_surface_create_toplevel(d, &gl_spec, NULL);
+ if (!w) return NULL;
+ if (!egl_configure(d, &o, &w->egl_config)) goto fail;
+ EGLContext share_context = share && share->display == display
+ ? ((struct wayland_surface *)share)->egl_context : EGL_NO_CONTEXT;
+ if (share && share_context == EGL_NO_CONTEXT) goto fail;
+ w->egl_window = wl_egl_window_create(w->surface, w->width, w->height);
+ if (!w->egl_window) goto fail;
+ EGLint context_attrs[12];
+ int n = 0;
+ if (o.api == YASL_PRIVATE_GL_OPENGL_ES) {
+ context_attrs[n++] = EGL_CONTEXT_CLIENT_VERSION;
+ context_attrs[n++] = o.major;
+ } else {
+ context_attrs[n++] = EGL_CONTEXT_MAJOR_VERSION_KHR;
+ context_attrs[n++] = o.major;
+ context_attrs[n++] = EGL_CONTEXT_MINOR_VERSION_KHR;
+ context_attrs[n++] = o.minor;
+ if (o.profile != YASL_PRIVATE_GL_ANY) {
+ context_attrs[n++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR;
+ context_attrs[n++] = o.profile == YASL_PRIVATE_GL_CORE
+ ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
+ : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
+ }
+ EGLint flags = (o.debug ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0) |
+ (o.forward_compat ? EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR : 0);
+ if (flags) {
+ context_attrs[n++] = EGL_CONTEXT_FLAGS_KHR;
+ context_attrs[n++] = flags;
+ }
+ }
+ context_attrs[n] = EGL_NONE;
+ w->egl_context = eglCreateContext(d->egl_display, w->egl_config, share_context, context_attrs);
+ if (w->egl_context == EGL_NO_CONTEXT) goto fail;
+ EGLint surface_attrs[] = {
+#ifdef EGL_GL_COLORSPACE_KHR
+ EGL_GL_COLORSPACE_KHR, o.srgb ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
+#endif
+ EGL_NONE,
+ };
+ w->egl_surface = eglCreateWindowSurface(d->egl_display, w->egl_config,
+ (EGLNativeWindowType)w->egl_window, surface_attrs);
+ if (w->egl_surface == EGL_NO_SURFACE) { w->egl_surface = 0; goto fail; }
+ w->base.presenter = YASL_PRIVATE_PRESENTER_GL;
+ return &w->base;
+fail:
+ wayland_surface_destroy(w);
+ return NULL;
+}
+
+static bool impl_gl_make_current(struct yasl_private_display *display, struct yasl_surface *surface)
+{
+ struct wayland_display *d = (struct wayland_display *)display;
+ struct wayland_surface *w = (struct wayland_surface *)surface;
+ if (!d) return false;
+ if (!w)
+ return eglMakeCurrent(d->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) == EGL_TRUE;
+ return w->conn == d && w->base.presenter == YASL_PRIVATE_PRESENTER_GL &&
+ eglMakeCurrent(d->egl_display, w->egl_surface, w->egl_surface, w->egl_context) == EGL_TRUE;
+}
+
+static yasl_private_gl_proc impl_gl_get_proc_address(struct yasl_private_display *display, const char *name)
+{
+ (void)display;
+ return name ? (yasl_private_gl_proc)eglGetProcAddress(name) : NULL;
+}
+
+static bool impl_gl_swap_interval(struct yasl_private_display *display, struct yasl_surface *surface, int interval)
+{
+ struct wayland_display *d = (struct wayland_display *)display;
+ struct wayland_surface *w = (struct wayland_surface *)surface;
+ return d && w && w->conn == d && w->base.presenter == YASL_PRIVATE_PRESENTER_GL &&
+ impl_gl_make_current(display, surface) && eglSwapInterval(d->egl_display, interval) == EGL_TRUE;
+}
+
+static bool impl_gl_swap_buffers(struct yasl_private_display *display, struct yasl_surface *surface)
+{
+ struct wayland_display *d = (struct wayland_display *)display;
+ struct wayland_surface *w = (struct wayland_surface *)surface;
+ if (!d || !w || w->conn != d || w->closed || !w->configured ||
+ w->base.presenter != YASL_PRIVATE_PRESENTER_GL)
+ return false;
+ if (!impl_gl_make_current(display, surface)) return false;
+ wayland_surface_arm_frame(w);
+ surface_request_presentation_feedback(w);
+ if (!eglSwapBuffers(d->egl_display, w->egl_surface)) return false;
+ return true;
+}
+#endif
+
+static struct yasl_surface *impl_surface_create_popup(struct yasl_surface *parent, const struct yasl_private_popup_spec *spec)
{
struct wayland_surface *result = wayland_surface_create_popup((struct wayland_surface *)parent, spec);
return result ? &result->base : NULL;
}
-static bool impl_surface_popup_reposition(struct yasl_surface *popup, const struct yasl_popup_spec *spec)
+static bool impl_surface_popup_reposition(struct yasl_surface *popup, const struct yasl_private_popup_spec *spec)
{
return wayland_surface_popup_reposition((struct wayland_surface *)popup, spec);
}
@@ -106,7 +247,7 @@ static struct input_queue *impl_surface_input_queue(struct yasl_surface *s)
return w ? &w->input : NULL;
}
-static bool impl_surface_set_size(struct yasl_surface *s, struct yasl_vector2i size)
+static bool impl_surface_set_size(struct yasl_surface *s, struct yasl_private_vector2i size)
{
struct wayland_surface *w = (struct wayland_surface *)s;
if (!w || w->closed || w->destroyed || !w->toplevel ||
@@ -114,8 +255,19 @@ static bool impl_surface_set_size(struct yasl_surface *s, struct yasl_vector2i s
errno = EINVAL;
return false;
}
- errno = ENOTSUP;
- return false;
+ /* Floating windows choose their own size; constrained states keep it for later. */
+ w->floating_width = size.x;
+ w->floating_height = size.y;
+ if (w->base.state & (YASL_PRIVATE_STATE_MAXIMIZED | YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_TILED))
+ return true;
+ w->req_width = w->req_height = 0;
+ w->size_pending = true;
+ if (w->base.presenter != YASL_PRIVATE_PRESENTER_CPU && w->configured && apply_pending_geometry(w) < 0) {
+ errno = EIO;
+ return false;
+ }
+ wayland_surface_schedule_redraw(w);
+ return true;
}
static bool impl_surface_set_fullscreen(struct yasl_surface *s, bool enabled)
@@ -153,14 +305,14 @@ static bool impl_surface_minimize(struct yasl_surface *s)
return true;
}
-static struct yasl_display *impl_surface_display(const struct yasl_surface *s)
+static struct yasl_private_display *impl_surface_display(const struct yasl_surface *s)
{
const struct wayland_surface *w = (const struct wayland_surface *)s;
struct wayland_display *result = w ? w->conn : NULL;
return result ? &result->base : NULL;
}
-static void impl_surface_set_callbacks(struct yasl_surface *s, const struct yasl_window_cbs *cbs, void *ud)
+static void impl_surface_set_callbacks(struct yasl_surface *s, const struct yasl_private_window_cbs *cbs, void *ud)
{
wayland_surface_set_callbacks((struct wayland_surface *)s, cbs, ud);
}
@@ -175,37 +327,37 @@ static void impl_surface_schedule_redraw(struct yasl_surface *s)
wayland_surface_schedule_redraw((struct wayland_surface *)s);
}
-static bool impl_surface_present(struct yasl_surface *s, const struct yasl_framebuffer *fb, const struct yasl_damage_list *damage)
+static bool impl_surface_present(struct yasl_surface *s, const struct yasl_private_framebuffer *fb, const struct yasl_private_damage_list *damage)
{
return wayland_surface_present((struct wayland_surface *)s, fb, damage);
}
-static bool impl_surface_poll_event(struct yasl_surface *s, struct yasl_event *ev)
+static bool impl_surface_poll_event(struct yasl_surface *s, struct yasl_private_event *ev)
{
return wayland_surface_poll_event((struct wayland_surface *)s, ev);
}
-static struct yasl_geometry impl_surface_geometry(const struct yasl_surface *s)
+static struct yasl_private_geometry impl_surface_geometry(const struct yasl_surface *s)
{
return wayland_surface_geometry((const struct wayland_surface *)s);
}
-static struct yasl_timing impl_surface_timing(const struct yasl_surface *s)
+static struct yasl_private_timing impl_surface_timing(const struct yasl_surface *s)
{
return wayland_surface_timing((const struct wayland_surface *)s);
}
static uint64_t impl_surface_frame_time_ns(struct yasl_surface *s, uint64_t now)
{
- return yasl_clock_frame_timestamp_ns(&((struct wayland_surface *)s)->clock, now);
+ return yasl_private_clock_frame_timestamp_ns(&((struct wayland_surface *)s)->clock, now);
}
-static void impl_surface_set_cursor(struct yasl_surface *s, enum yasl_cursor cursor)
+static void impl_surface_set_cursor(struct yasl_surface *s, enum yasl_private_cursor cursor)
{
wayland_surface_set_cursor((struct wayland_surface *)s, cursor);
}
-static bool impl_surface_set_pointer_mode(struct yasl_surface *s, enum yasl_pointer_mode mode)
+static bool impl_surface_set_pointer_mode(struct yasl_surface *s, enum yasl_private_pointer_mode mode)
{
return wayland_surface_set_pointer_mode((struct wayland_surface *)s, mode);
}
@@ -226,7 +378,7 @@ static bool impl_surface_ime_preedit_cursor(const struct yasl_surface *s, int *b
return wayland_surface_ime_preedit_cursor((const struct wayland_surface *)s, begin, end);
}
-static void impl_surface_set_ime_caret(struct yasl_surface *s, struct yasl_rect2i caret)
+static void impl_surface_set_ime_caret(struct yasl_surface *s, struct yasl_private_rect2i caret)
{
wayland_surface_set_ime_caret((struct wayland_surface *)s, caret);
}
@@ -236,28 +388,28 @@ static bool impl_surface_start_interactive_move(struct yasl_surface *s)
return wayland_surface_start_interactive_move((struct wayland_surface *)s);
}
-static bool impl_surface_start_interactive_resize(struct yasl_surface *s, enum yasl_resize_edge edge)
+static bool impl_surface_start_interactive_resize(struct yasl_surface *s, enum yasl_private_resize_edge edge)
{
return wayland_surface_start_interactive_resize((struct wayland_surface *)s, edge);
}
-static bool impl_surface_show_window_menu(struct yasl_surface *s, struct yasl_vector2i pos)
+static bool impl_surface_show_window_menu(struct yasl_surface *s, struct yasl_private_vector2i pos)
{
return wayland_surface_show_window_menu((struct wayland_surface *)s, pos);
}
-static bool impl_surface_drag_carry(struct yasl_surface *s, struct yasl_vector2i offset)
+static bool impl_surface_drag_carry(struct yasl_surface *s, struct yasl_private_vector2i offset)
{
return wayland_surface_drag_carry((struct wayland_surface *)s, offset);
}
-static bool impl_surface_place_under_pointer(struct yasl_surface *s, struct yasl_vector2i at)
+static bool impl_surface_place_under_pointer(struct yasl_surface *s, struct yasl_private_vector2i at)
{
return wayland_surface_place_under_pointer((struct wayland_surface *)s, at);
}
static bool impl_surface_read_pixels(struct yasl_surface *s, uint32_t *out, size_t cap,
- struct yasl_vector2i *size)
+ struct yasl_private_vector2i *size)
{
return wayland_surface_read_pixels((struct wayland_surface *)s, out, cap, size);
}
@@ -267,7 +419,7 @@ static bool impl_surface_bell(struct yasl_surface *s)
return wayland_surface_bell((struct wayland_surface *)s);
}
-static void *impl_display_get_native_handle(struct yasl_display *d)
+static void *impl_display_get_native_handle(struct yasl_private_display *d)
{
struct wayland_display *w = (struct wayland_display *)d;
return w ? w->wl : NULL;
@@ -279,8 +431,16 @@ static void *impl_surface_get_native_handle(struct yasl_surface *s)
return w ? w->surface : NULL;
}
-const struct yasl_backend_ops yasl_wayland_backend = {
- .type = YASL_BACKEND_WAYLAND,
+const struct yasl_private_backend_ops yasl_private_wayland_backend = {
+#if YASL_HAS_EGL
+ .surface_create_gl = impl_surface_create_gl,
+ .gl_make_current = impl_gl_make_current,
+ .gl_get_proc_address = impl_gl_get_proc_address,
+ .gl_swap_interval = impl_gl_swap_interval,
+ .gl_swap_buffers = impl_gl_swap_buffers,
+#endif
+ .surface_update_text_input = impl_surface_update_text_input,
+ .type = YASL_PRIVATE_BACKEND_WAYLAND,
.display_open = impl_display_open,
.display_close = impl_display_close,
.display_caps = impl_display_caps,
diff --git a/src/platform/wayland/buffer.c b/src/platform/wayland/buffer.c
index 874cc76..bbc055d 100644
--- a/src/platform/wayland/buffer.c
+++ b/src/platform/wayland/buffer.c
@@ -24,7 +24,7 @@ static const struct wl_buffer_listener buffer_listener;
int device_px(int logical, uint32_t scale_120)
{
- int64_t px = ((int64_t)logical * scale_120 + YASL_SCALE_UNIT / 2) / YASL_SCALE_UNIT;
+ int64_t px = ((int64_t)logical * scale_120 + YASL_PRIVATE_SCALE_UNIT / 2) / YASL_PRIVATE_SCALE_UNIT;
return px > 0 && px <= INT_MAX ? (int)px : -1;
}
@@ -58,7 +58,7 @@ int buffer_reserve(struct wayland_surface *w, struct buffer *b, size_t needed)
if (b->busy || needed > INT32_MAX) return -1;
size_t capacity = b->capacity <= INT32_MAX / 2 ? b->capacity * 2 : INT32_MAX;
if (capacity < needed) capacity = needed;
- int fd = memfd_create("yasl_surface_buffer", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ int fd = memfd_create("yasl_private_surface_buffer", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (fd < 0) return -1;
if (!fd_truncate(fd, capacity) ||
fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_SEAL) < 0) {
@@ -89,7 +89,7 @@ int buffer_prepare(struct wayland_surface *w, struct buffer *b, int width, int h
{
if (b->proxy && !b->busy && b->width == width && b->height == height) return 0;
long faults_before = minor_faults();
- uint64_t t0 = yasl_loop_now_ns();
+ uint64_t t0 = yasl_private_loop_now_ns();
size_t bytes;
if (!buffer_size(width, height, &bytes) || buffer_reserve(w, b, bytes) < 0)
return -1;
@@ -104,7 +104,7 @@ int buffer_prepare(struct wayland_surface *w, struct buffer *b, int width, int h
b->busy = false;
b->presented = false;
wl_buffer_add_listener(proxy, listener, b);
- yasl_clock_note_resize(&w->clock, yasl_loop_now_ns() - t0);
+ yasl_private_clock_note_resize(&w->clock, yasl_private_loop_now_ns() - t0);
long faults = minor_faults() - faults_before;
if (faults > 0) w->clock.resize_minflt += faults;
return 0;
@@ -114,10 +114,10 @@ static void publish_surface_scale(struct wayland_surface *w)
{
if (w->viewport) {
wp_viewport_set_destination(w->viewport, w->logical_width, w->logical_height);
- } else if (w->scale_120 % YASL_SCALE_UNIT == 0 &&
+ } else if (w->scale_120 % YASL_PRIVATE_SCALE_UNIT == 0 &&
wl_proxy_get_version((struct wl_proxy *)w->surface) >=
WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION) {
- wl_surface_set_buffer_scale(w->surface, (int32_t)(w->scale_120 / YASL_SCALE_UNIT));
+ wl_surface_set_buffer_scale(w->surface, (int32_t)(w->scale_120 / YASL_PRIVATE_SCALE_UNIT));
}
}
@@ -137,16 +137,16 @@ int apply_pending_geometry(struct wayland_surface *w)
return 0;
}
bool floating = !w->parent && !(w->base.state &
- (YASL_STATE_MAXIMIZED | YASL_STATE_FULLSCREEN | YASL_STATE_TILED));
+ (YASL_PRIVATE_STATE_MAXIMIZED | YASL_PRIVATE_STATE_FULLSCREEN | YASL_PRIVATE_STATE_TILED));
int free_w = floating && w->floating_width > 0 ? w->floating_width : w->logical_width;
int free_h = floating && w->floating_height > 0 ? w->floating_height : w->logical_height;
int logical_w = !w->parent && w->req_width > 0 ? w->req_width : free_w;
int logical_h = !w->parent && w->req_height > 0 ? w->req_height : free_h;
if (!w->parent) {
- if (logical_w < YASL_MIN_LOGICAL_PX) logical_w = YASL_MIN_LOGICAL_PX;
- if (logical_h < YASL_MIN_LOGICAL_PX) logical_h = YASL_MIN_LOGICAL_PX;
+ if (logical_w < YASL_PRIVATE_MIN_LOGICAL_PX) logical_w = YASL_PRIVATE_MIN_LOGICAL_PX;
+ if (logical_h < YASL_PRIVATE_MIN_LOGICAL_PX) logical_h = YASL_PRIVATE_MIN_LOGICAL_PX;
}
- if (!(w->base.state & YASL_STATE_FULLSCREEN)) {
+ if (!(w->base.state & YASL_PRIVATE_STATE_FULLSCREEN)) {
if (w->bound_width > 0 && logical_w > w->bound_width)
logical_w = w->bound_width;
if (w->bound_height > 0 && logical_h > w->bound_height)
@@ -155,7 +155,9 @@ int apply_pending_geometry(struct wayland_surface *w)
int width = device_px(logical_w, w->pending_scale_120);
int height = device_px(logical_h, w->pending_scale_120);
size_t bytes;
- if (!buffer_size(width, height, &bytes)) {
+ if (width <= 0 || height <= 0 ||
+ (w->base.presenter == YASL_PRIVATE_PRESENTER_CPU &&
+ !buffer_size(width, height, &bytes))) {
return -1;
}
bool rescaled = w->scale_120 != w->pending_scale_120;
@@ -169,13 +171,17 @@ int apply_pending_geometry(struct wayland_surface *w)
return 0;
w->scale_120 = w->pending_scale_120;
- w->scale_factor = (double)w->scale_120 / YASL_SCALE_UNIT;
+ w->scale_factor = (double)w->scale_120 / YASL_PRIVATE_SCALE_UNIT;
w->width = width;
w->height = height;
- w->base.size = (struct yasl_vector2i){width, height};
+ w->base.size = (struct yasl_private_vector2i){width, height};
w->base.scale_120 = w->scale_120;
w->logical_width = logical_w;
w->logical_height = logical_h;
+#if YASL_HAS_EGL
+ if (w->egl_window && (resized || rescaled))
+ wl_egl_window_resize(w->egl_window, width, height, 0, 0);
+#endif
surface_update_opaque_region(w);
if (resized || rescaled) {
for (int i = 0; i < NBUF; i++)
@@ -183,7 +189,7 @@ int apply_pending_geometry(struct wayland_surface *w)
}
publish_surface_scale(w);
if (resized || rescaled) {
- yasl_surface_notify_configure(&w->base, (struct yasl_geometry){
+ yasl_private_surface_notify_configure(&w->base, (struct yasl_private_geometry){
.size = { .x = width, .y = height }, .scale_120 = w->scale_120,
});
if (w->closed || w->destroyed)
@@ -225,7 +231,7 @@ void surface_follow_outputs(struct wayland_surface *w)
w->clock.refresh_ns = refresh;
if (need_scale)
- surface_request_scale(w, (uint32_t)max_scale * YASL_SCALE_UNIT);
+ surface_request_scale(w, (uint32_t)max_scale * YASL_PRIVATE_SCALE_UNIT);
}
static void surface_enter(void *data, struct wl_surface *surface, struct wl_output *output)
@@ -250,7 +256,7 @@ static void surface_preferred_scale(void *data, struct wl_surface *surface, int3
struct wayland_surface *w = data;
if (w->frac_scale || w->parent || factor <= 0)
return;
- surface_request_scale(w, (uint32_t)factor * YASL_SCALE_UNIT);
+ surface_request_scale(w, (uint32_t)factor * YASL_PRIVATE_SCALE_UNIT);
}
static void surface_preferred_transform(void *data, struct wl_surface *surface,
@@ -285,13 +291,15 @@ static void frame_done(void *data, struct wl_callback *cb, uint32_t ms)
wl_callback_destroy(cb);
w->frame_cb = NULL;
- uint64_t now = yasl_loop_now_ns();
+ uint64_t now = yasl_private_loop_now_ns();
if (!w->conn->pres_clock_known) {
- yasl_clock_presented(&w->clock, yasl_clock_extend_ms(ms, now), w->sample_refresh);
- w->clock.source = YASL_TIMING_FRAME_CALLBACK;
+ yasl_private_clock_presented(&w->clock, yasl_private_clock_extend_ms(ms, now), w->sample_refresh);
+ w->clock.source = YASL_PRIVATE_TIMING_FRAME_CALLBACK;
}
- if (w->want_draw)
+ if (w->base.presenter != YASL_PRIVATE_PRESENTER_CPU)
+ yasl_private_surface_notify_refresh(&w->base);
+ else if (w->want_draw)
wayland_surface_schedule_redraw(w);
}
@@ -299,14 +307,14 @@ static const struct wl_callback_listener frame_listener = {
.done = frame_done,
};
-static void arm_frame(struct wayland_surface *w)
+void wayland_surface_arm_frame(struct wayland_surface *w)
{
if (!w->configured || w->closed || w->frame_cb)
return;
w->frame_cb = wl_surface_frame(w->surface);
if (!w->frame_cb) { surface_fail(w); return; }
w->sample_refresh = w->clock.last_present_ns &&
- yasl_loop_now_ns() - w->clock.last_present_ns <
+ yasl_private_loop_now_ns() - w->clock.last_present_ns <
(uint64_t)(w->clock.refresh_ns / 2);
if (wl_callback_add_listener(w->frame_cb, &frame_listener, w) < 0) {
wl_callback_destroy(w->frame_cb);
@@ -365,7 +373,7 @@ static void presented(void *data, struct wp_presentation_feedback *fb,
(((uint64_t)tv_sec_hi << 32) | tv_sec_lo) * 1000000000ull + tv_nsec);
if (refresh) w->clock.refresh_ns = refresh;
w->clock.last_present_ns = ns;
- w->clock.source = YASL_TIMING_PRESENTATION;
+ w->clock.source = YASL_PRIVATE_TIMING_PRESENTATION;
}
(void)fb;
feedback_destroy(feedback);
@@ -419,7 +427,7 @@ static void commit_buffer(struct wayland_surface *w, int idx)
{
wl_surface_attach(w->surface, w->buffers[idx].proxy, 0, 0);
- const struct yasl_damage_list *d = &w->damage;
+ const struct yasl_private_damage_list *d = &w->damage;
if (d->n < 0 || !w->buffers[idx].presented)
wl_surface_damage_buffer(w->surface, 0, 0, w->width, w->height);
else
@@ -438,8 +446,8 @@ static void commit_buffer(struct wayland_surface *w, int idx)
wp_fifo_v1_set_barrier(w->fifo);
}
if (w->commit_timer && w->conn->pres_clock_known) {
- uint64_t now = yasl_loop_now_ns();
- uint64_t next = yasl_clock_next_present_ns(&w->clock);
+ uint64_t now = yasl_private_loop_now_ns();
+ uint64_t next = yasl_private_clock_next_present_ns(&w->clock);
bool soon = next > now && next - now < (uint64_t)(w->clock.refresh_ns * 1.5);
next = conn_mono_to_pres(w->conn, next);
if (soon)
@@ -458,10 +466,11 @@ static void commit_buffer(struct wayland_surface *w, int idx)
w->buffers[idx].presented = true;
}
-bool wayland_surface_present(struct wayland_surface *w, const struct yasl_framebuffer *fb,
- const struct yasl_damage_list *damage)
+bool wayland_surface_present(struct wayland_surface *w, const struct yasl_private_framebuffer *fb,
+ const struct yasl_private_damage_list *damage)
{
- if (!w || w->closed || !w->frame_active || w->frame_presented || !fb ||
+ if (!w || w->base.presenter != YASL_PRIVATE_PRESENTER_CPU ||
+ w->closed || !w->frame_active || w->frame_presented || !fb ||
!damage || fb->pixels != w->frame.target.pixels ||
fb->size.x != w->width || fb->size.y != w->height)
return false;
@@ -470,7 +479,7 @@ bool wayland_surface_present(struct wayland_surface *w, const struct yasl_frameb
w->damage.bounds = damage->bounds;
if (damage->n > 0)
memcpy(w->damage.rects, damage->rects, (size_t)damage->n * sizeof(damage->rects[0]));
- arm_frame(w);
+ wayland_surface_arm_frame(w);
if (w->closed)
return false;
commit_buffer(w, w->cur);
@@ -481,17 +490,17 @@ bool wayland_surface_present(struct wayland_surface *w, const struct yasl_frameb
}
bool wayland_surface_read_pixels(struct wayland_surface *w, uint32_t *out, size_t cap,
- struct yasl_vector2i *size)
+ struct yasl_private_vector2i *size)
{
if (!w || w->closed || w->frame_active || !w->has_shown) return false;
const struct buffer *b = &w->buffers[w->shown];
if (!b->pixels) return false;
- return yasl_copy_frame(b->pixels, (struct yasl_vector2i){b->width, b->height}, out, cap, size);
+ return yasl_private_copy_frame(b->pixels, (struct yasl_private_vector2i){b->width, b->height}, out, cap, size);
}
void surface_draw_frame(struct wayland_surface *w)
{
- if (w->closed || !w->configured)
+ if (w->closed || !w->configured || w->base.presenter != YASL_PRIVATE_PRESENTER_CPU)
return;
if (apply_pending_geometry(w) < 0) {
surface_fail(w);
@@ -517,18 +526,18 @@ void surface_draw_frame(struct wayland_surface *w)
if (w->parent)
memset(w->buffers[idx].pixels, 0, (size_t)w->width * (size_t)w->height * sizeof(uint32_t));
- w->damage = (struct yasl_damage_list){0};
- w->frame = (struct yasl_frame){
+ w->damage = (struct yasl_private_damage_list){0};
+ w->frame = (struct yasl_private_frame){
.surface = &w->base,
.target = {
- .generation = yasl_frame_begin(&w->base),
+ .generation = yasl_private_frame_begin(&w->base),
.pixels = w->buffers[idx].pixels,
.size = { .x = w->width, .y = w->height },
},
};
w->frame_active = true;
w->frame_presented = false;
- yasl_surface_draw(&w->base, &w->frame);
+ yasl_private_surface_draw(&w->base, &w->frame);
if (w->closed || w->destroyed)
return;
w->frame_active = false;
@@ -555,21 +564,21 @@ int surface_init_scaling(struct wayland_surface *w)
void wayland_surface_set_title(struct wayland_surface *w, const char *title)
{
if (!w || !w->toplevel || !title) return;
- char *copy = yasl_utf8_sanitize_dup(title);
+ char *copy = yasl_private_utf8_sanitize_dup(title);
if (!copy) return;
xdg_toplevel_set_title(w->toplevel, copy);
free(copy);
}
-struct yasl_timing wayland_surface_timing(const struct wayland_surface *w)
+struct yasl_private_timing wayland_surface_timing(const struct wayland_surface *w)
{
- struct yasl_timing t = {
+ struct yasl_private_timing t = {
.refresh_ns = w->clock.refresh_ns,
.last_present_ns = w->clock.last_present_ns,
- .next_present_ns = yasl_clock_next_present_ns(&w->clock),
+ .next_present_ns = yasl_private_clock_next_present_ns(&w->clock),
.frames_skipped = w->frames_skipped,
.source = w->clock.source,
};
- yasl_clock_resize_stats(&w->clock, &t.resize);
+ yasl_private_clock_resize_stats(&w->clock, &t.resize);
return t;
}
diff --git a/src/platform/wayland/clipboard.c b/src/platform/wayland/clipboard.c
index 8ca9b93..cf39b6c 100644
--- a/src/platform/wayland/clipboard.c
+++ b/src/platform/wayland/clipboard.c
@@ -25,7 +25,7 @@ struct transfer {
struct offer *drop;
struct wl_surface *drop_surface;
int fd, id;
- yasl_timer_id timeout;
+ yasl_private_timer_id timeout;
char *text;
size_t len, offset, capacity;
uint64_t request_id;
@@ -48,7 +48,7 @@ struct clipboard {
struct offer *drag_offer;
struct primary_offer *primary_selection;
struct primary_offer *primary_pending_offers;
- struct yasl_loop *loop;
+ struct yasl_private_loop *loop;
struct transfer *transfers;
char *text;
char *primary_text;
@@ -70,7 +70,7 @@ const char *clipboard_drag_mime(void)
return mime;
}
-static void drag_event(struct clipboard *c, enum yasl_drag_event ev,
+static void drag_event(struct clipboard *c, enum yasl_private_drag_event ev,
wl_fixed_t x, wl_fixed_t y)
{
if (c->drag)
@@ -78,7 +78,7 @@ static void drag_event(struct clipboard *c, enum yasl_drag_event ev,
c->drag_ud);
}
-static void drop_event(struct clipboard *c, enum yasl_drop_event ev)
+static void drop_event(struct clipboard *c, enum yasl_private_drop_event ev)
{
if (c->drop && c->drag_surface)
c->drop(ev, c->drag_surface, wl_fixed_to_double(c->drag_x),
@@ -89,7 +89,7 @@ static void free_offer(struct offer *o);
static void transfer_end(struct transfer *t, bool complete);
-static uint64_t transfer_timeout(void *ud, yasl_timer_id id, uint64_t interval)
+static uint64_t transfer_timeout(void *ud, yasl_private_timer_id id, uint64_t interval)
{
(void)interval;
struct transfer *t = ud;
@@ -106,9 +106,9 @@ static void transfer_end(struct transfer *t, bool complete)
struct transfer **p = &owner->transfers;
while (*p && *p != t) p = &(*p)->next;
if (*p) *p = t->next;
- yasl_loop_del_fd(owner->loop, t->id);
+ yasl_private_loop_del_fd(owner->loop, t->id);
if (t->timeout)
- yasl_loop_del_timer(owner->loop, t->timeout);
+ yasl_private_loop_del_timer(owner->loop, t->timeout);
close(t->fd);
if (t->drop) {
if (complete && wl_data_offer_get_version(t->drop->proxy) >=
@@ -124,7 +124,7 @@ static void transfer_end(struct transfer *t, bool complete)
struct wl_surface *surface = t->drop_surface;
uint64_t request_id = t->request_id;
bool uri_list = t->uri_list;
- enum yasl_transfer_status status = complete ? YASL_TRANSFER_OK : YASL_TRANSFER_FAILED;
+ enum yasl_private_transfer_status status = complete ? YASL_PRIVATE_TRANSFER_OK : YASL_PRIVATE_TRANSFER_FAILED;
const char *text = complete ? (t->text ? t->text : "") : NULL;
size_t len = complete ? t->len : 0;
if (notify)
@@ -156,7 +156,7 @@ static int transfer_io(int fd, short events, void *ud)
if (n > 0) {
t->len += (size_t)n;
} else if (n == 0) {
- bool valid = yasl_utf8_validate(t->text, t->len);
+ bool valid = yasl_private_utf8_validate(t->text, t->len);
transfer_end(t, valid);
} else if (errno != EAGAIN && errno != EINTR) transfer_end(t, false);
}
@@ -176,12 +176,12 @@ static struct transfer *start_transfer_text(struct clipboard *c, int fd, bool se
if (!t->text) { close(fd); free(t); return NULL; }
t->len = strlen(t->text);
}
- t->id = yasl_loop_add_fd(c->loop, fd, sending ? POLLOUT : POLLIN, transfer_io, t);
+ t->id = yasl_private_loop_add_fd(c->loop, fd, sending ? POLLOUT : POLLIN, transfer_io, t);
if (t->id < 0) { close(fd); free(t->text); free(t); return NULL; }
- t->timeout = yasl_loop_add_timer(c->loop, CLIPBOARD_TRANSFER_TIMEOUT_NS,
+ t->timeout = yasl_private_loop_add_timer(c->loop, CLIPBOARD_TRANSFER_TIMEOUT_NS,
transfer_timeout, t);
if (!t->timeout) {
- yasl_loop_del_fd(c->loop, t->id);
+ yasl_private_loop_del_fd(c->loop, t->id);
close(fd);
free(t->text);
free(t);
@@ -311,9 +311,9 @@ static void drag_offer_enter(void *ud, struct wl_data_device *device, uint32_t s
c->drag_y = y;
c->drag_surface = surface;
if (o && o->tab)
- drag_event(c, YASL_DRAG_OVER, x, y);
+ drag_event(c, YASL_PRIVATE_DRAG_OVER, x, y);
else if (o && !o->tab && (o->uri_list || o->mime))
- drop_event(c, YASL_DROP_OVER);
+ drop_event(c, YASL_PRIVATE_DROP_OVER);
}
}
static void drag_offer_clear(void *ud, struct wl_data_device *device)
@@ -321,10 +321,10 @@ static void drag_offer_clear(void *ud, struct wl_data_device *device)
(void)device;
struct clipboard *c = ud;
if (c->drag_offer && c->drag_offer->tab)
- drag_event(c, YASL_DRAG_LEAVE, c->drag_x, c->drag_y);
+ drag_event(c, YASL_PRIVATE_DRAG_LEAVE, c->drag_x, c->drag_y);
else if (c->drag_offer && !c->drag_offer->tab &&
(c->drag_offer->uri_list || c->drag_offer->mime))
- drop_event(c, YASL_DROP_LEAVE);
+ drop_event(c, YASL_PRIVATE_DROP_LEAVE);
free_offer(c->drag_offer);
c->drag_offer = NULL;
c->drag_surface = NULL;
@@ -336,10 +336,10 @@ static void drag_motion(void *ud, struct wl_data_device *device, uint32_t time,
c->drag_x = x;
c->drag_y = y;
if (c->drag_offer && c->drag_offer->tab)
- drag_event(c, YASL_DRAG_OVER, x, y);
+ drag_event(c, YASL_PRIVATE_DRAG_OVER, x, y);
else if (c->drag_offer && !c->drag_offer->tab &&
(c->drag_offer->uri_list || c->drag_offer->mime))
- drop_event(c, YASL_DROP_OVER);
+ drop_event(c, YASL_PRIVATE_DROP_OVER);
}
static void drag_drop(void *ud, struct wl_data_device *device)
{
@@ -350,11 +350,11 @@ static void drag_drop(void *ud, struct wl_data_device *device)
c->drag_offer = NULL;
bool v3 = wl_data_offer_get_version(o->proxy) >= 3;
if (o->tab) {
- drag_event(c, YASL_DRAG_DROP, c->drag_x, c->drag_y);
+ drag_event(c, YASL_PRIVATE_DRAG_DROP, c->drag_x, c->drag_y);
if (v3)
wl_data_offer_finish(o->proxy);
} else if (o && !o->tab && (o->uri_list || o->mime)) {
- drop_event(c, YASL_DROP_LEAVE);
+ drop_event(c, YASL_PRIVATE_DROP_LEAVE);
int fds[2];
if (pipe2(fds, O_CLOEXEC) == 0) {
wl_data_offer_receive(o->proxy, o->uri_list ? "text/uri-list" : o->mime, fds[1]);
@@ -522,7 +522,7 @@ struct wl_data_device *clipboard_data_device(const struct clipboard *c)
}
struct clipboard *clipboard_create(struct wl_display *display, struct wl_data_device_manager *manager,
- struct wl_seat *seat, struct yasl_loop *loop,
+ struct wl_seat *seat, struct yasl_private_loop *loop,
clipboard_receive_fn receive, void *ud)
{
if (!manager || !seat) return NULL;
@@ -603,7 +603,7 @@ bool clipboard_copy(struct clipboard *c, const char *text, uint32_t serial)
void clipboard_paste(struct clipboard *c, struct wl_surface *target)
{
if (c && target)
- (void)clipboard_request_paste(c, YASL_CLIPBOARD, target, 0);
+ (void)clipboard_request_paste(c, YASL_PRIVATE_CLIPBOARD, target, 0);
}
bool clipboard_copy_primary(struct clipboard *c, const char *text, uint32_t serial)
@@ -630,24 +630,24 @@ bool clipboard_copy_primary(struct clipboard *c, const char *text, uint32_t seri
void clipboard_paste_primary(struct clipboard *c, struct wl_surface *target)
{
if (c && target)
- (void)clipboard_request_paste(c, YASL_PRIMARY, target, 0);
+ (void)clipboard_request_paste(c, YASL_PRIVATE_PRIMARY, target, 0);
}
-bool clipboard_request_paste(struct clipboard *c, enum yasl_selection selection,
+bool clipboard_request_paste(struct clipboard *c, enum yasl_private_selection selection,
struct wl_surface *target, uint64_t request_id)
{
if (!c || !target || !c->receive)
return false;
int fds[2];
- if (selection == YASL_PRIMARY) {
+ if (selection == YASL_PRIVATE_PRIMARY) {
if (!c->primary_device || !c->primary_selection || !c->primary_selection->mime) {
c->receive(NULL, 0, false, target, request_id,
- YASL_TRANSFER_UNAVAILABLE, c->ud);
+ YASL_PRIVATE_TRANSFER_UNAVAILABLE, c->ud);
return true;
}
if (pipe2(fds, O_CLOEXEC) < 0) {
c->receive(NULL, 0, false, target, request_id,
- YASL_TRANSFER_FAILED, c->ud);
+ YASL_PRIVATE_TRANSFER_FAILED, c->ud);
return true;
}
zwp_primary_selection_offer_v1_receive(c->primary_selection->proxy,
@@ -656,12 +656,12 @@ bool clipboard_request_paste(struct clipboard *c, enum yasl_selection selection,
} else {
if (!c->device || !c->selection || !c->selection->mime) {
c->receive(NULL, 0, false, target, request_id,
- YASL_TRANSFER_UNAVAILABLE, c->ud);
+ YASL_PRIVATE_TRANSFER_UNAVAILABLE, c->ud);
return true;
}
if (pipe2(fds, O_CLOEXEC) < 0) {
c->receive(NULL, 0, false, target, request_id,
- YASL_TRANSFER_FAILED, c->ud);
+ YASL_PRIVATE_TRANSFER_FAILED, c->ud);
return true;
}
wl_data_offer_receive(c->selection->proxy, c->selection->mime, fds[1]);
@@ -670,7 +670,7 @@ bool clipboard_request_paste(struct clipboard *c, enum yasl_selection selection,
struct transfer *transfer = start_transfer_paste(c, fds[0], target, request_id);
if (!transfer) {
c->receive(NULL, 0, false, target, request_id,
- YASL_TRANSFER_FAILED, c->ud);
+ YASL_PRIVATE_TRANSFER_FAILED, c->ud);
return true;
}
if (wl_display_flush(c->display) < 0 && errno != EAGAIN)
diff --git a/src/platform/wayland/clipboard.h b/src/platform/wayland/clipboard.h
index 133cc14..d03df17 100644
--- a/src/platform/wayland/clipboard.h
+++ b/src/platform/wayland/clipboard.h
@@ -1,10 +1,10 @@
-#ifndef YASL_WAYLAND_CLIPBOARD_H
-#define YASL_WAYLAND_CLIPBOARD_H
+#ifndef YASL_PRIVATE_WAYLAND_CLIPBOARD_H
+#define YASL_PRIVATE_WAYLAND_CLIPBOARD_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
-#include "yasl/yasl.h"
+#include "common/types.h"
struct wl_display;
struct wl_data_device_manager;
@@ -16,27 +16,27 @@ struct zwp_primary_selection_device_manager_v1;
typedef void (*clipboard_receive_fn)(const char *, size_t, bool uri_list,
struct wl_surface *on, uint64_t request_id,
- enum yasl_transfer_status, void *);
+ enum yasl_private_transfer_status, void *);
struct clipboard *clipboard_create(struct wl_display *, struct wl_data_device_manager *,
- struct wl_seat *, struct yasl_loop *,
+ struct wl_seat *, struct yasl_private_loop *,
clipboard_receive_fn, void *);
void clipboard_destroy(struct clipboard *);
bool clipboard_set_seat(struct clipboard *, struct wl_seat *);
void clipboard_set_primary_manager(struct clipboard *, struct zwp_primary_selection_device_manager_v1 *);
bool clipboard_copy(struct clipboard *, const char *, uint32_t);
void clipboard_paste(struct clipboard *, struct wl_surface *target);
-bool clipboard_request_paste(struct clipboard *, enum yasl_selection,
+bool clipboard_request_paste(struct clipboard *, enum yasl_private_selection,
struct wl_surface *target, uint64_t request_id);
void clipboard_forget_surface(struct clipboard *, struct wl_surface *);
bool clipboard_copy_primary(struct clipboard *, const char *, uint32_t);
void clipboard_paste_primary(struct clipboard *, struct wl_surface *target);
-typedef void (*clipboard_drag_fn)(enum yasl_drag_event, struct wl_surface *on,
+typedef void (*clipboard_drag_fn)(enum yasl_private_drag_event, struct wl_surface *on,
double x, double y, void *);
void clipboard_set_drag_handler(struct clipboard *, clipboard_drag_fn, void *);
-typedef void (*clipboard_drop_fn)(enum yasl_drop_event, struct wl_surface *on,
+typedef void (*clipboard_drop_fn)(enum yasl_private_drop_event, struct wl_surface *on,
double x, double y, void *);
void clipboard_set_drop_handler(struct clipboard *, clipboard_drop_fn, void *);
const char *clipboard_drag_mime(void);
diff --git a/src/platform/wayland/drag.c b/src/platform/wayland/drag.c
index 1f4a78b..07e31b5 100644
--- a/src/platform/wayland/drag.c
+++ b/src/platform/wayland/drag.c
@@ -11,13 +11,13 @@ static void icon_clear(struct drag_icon *icon)
*icon = (struct drag_icon){0};
}
-static bool icon_create(struct wayland_display *c, const struct yasl_drag_image *image)
+static bool icon_create(struct wayland_display *c, const struct yasl_private_drag_image *image)
{
struct drag_icon *icon = &c->drag.icon;
size_t bytes;
if (!image->pixels || !buffer_size(image->size.x, image->size.y, &bytes))
return false;
- int fd = memfd_create("yasl_drag_icon", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ int fd = memfd_create("yasl_private_drag_icon", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (fd < 0)
return false;
void *mapping = MAP_FAILED;
@@ -48,7 +48,7 @@ static bool icon_create(struct wayland_display *c, const struct yasl_drag_image
return true;
}
-static void icon_show(struct wayland_display *c, const struct yasl_drag_image *image)
+static void icon_show(struct wayland_display *c, const struct yasl_private_drag_image *image)
{
struct drag_icon *icon = &c->drag.icon;
uint32_t scale = c->drag.scale_120;
@@ -56,18 +56,18 @@ static void icon_show(struct wayland_display *c, const struct yasl_drag_image *i
icon->viewport = wp_viewporter_get_viewport(c->viewporter, icon->surface);
if (icon->viewport)
wp_viewport_set_destination(icon->viewport,
- yasl_scale_to_logical(image->size.x, scale),
- yasl_scale_to_logical(image->size.y, scale));
- } else if (scale % YASL_SCALE_UNIT == 0 &&
+ yasl_private_scale_to_logical(image->size.x, scale),
+ yasl_private_scale_to_logical(image->size.y, scale));
+ } else if (scale % YASL_PRIVATE_SCALE_UNIT == 0 &&
wl_proxy_get_version((struct wl_proxy *)icon->surface) >=
WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION) {
- wl_surface_set_buffer_scale(icon->surface, (int32_t)(scale / YASL_SCALE_UNIT));
+ wl_surface_set_buffer_scale(icon->surface, (int32_t)(scale / YASL_PRIVATE_SCALE_UNIT));
}
if (wl_proxy_get_version((struct wl_proxy *)icon->surface) >=
WL_SURFACE_OFFSET_SINCE_VERSION)
wl_surface_offset(icon->surface,
- -yasl_scale_to_logical(image->hotspot.x, scale),
- -yasl_scale_to_logical(image->hotspot.y, scale));
+ -yasl_private_scale_to_logical(image->hotspot.x, scale),
+ -yasl_private_scale_to_logical(image->hotspot.y, scale));
wl_surface_attach(icon->surface, icon->buffer, 0, 0);
wl_surface_damage_buffer(icon->surface, 0, 0, image->size.x, image->size.y);
wl_surface_commit(icon->surface);
@@ -88,9 +88,9 @@ static void drag_clear(struct wayland_display *c, bool ended)
*d = (struct conn_drag){0};
}
-static void drag_finish(struct wayland_display *c, enum yasl_drag_end how, bool ended)
+static void drag_finish(struct wayland_display *c, enum yasl_private_drag_end how, bool ended)
{
- struct yasl_drag_listener l = c->drag.listener;
+ struct yasl_private_drag_listener l = c->drag.listener;
void *ud = c->drag.ud;
drag_clear(c, ended);
if (l.end)
@@ -100,7 +100,7 @@ static void drag_finish(struct wayland_display *c, enum yasl_drag_end how, bool
void conn_drag_end(struct wayland_display *c)
{
if (c && c->drag.source)
- drag_finish(c, YASL_DRAG_CANCELLED, false);
+ drag_finish(c, YASL_PRIVATE_DRAG_CANCELLED, false);
}
static void source_target(void *ud, struct wl_data_source *s, const char *mime) { (void)ud; (void)s; (void)mime; }
@@ -112,7 +112,7 @@ static void source_cancelled(void *ud, struct wl_data_source *s)
(void)s;
struct wayland_display *c = ud;
bool released = c->drag.dropped;
- drag_finish(c, released ? YASL_DRAG_DROPPED : YASL_DRAG_CANCELLED, true);
+ drag_finish(c, released ? YASL_PRIVATE_DRAG_DROPPED : YASL_PRIVATE_DRAG_CANCELLED, true);
}
static void source_dropped(void *ud, struct wl_data_source *s)
@@ -124,7 +124,7 @@ static void source_dropped(void *ud, struct wl_data_source *s)
static void source_finished(void *ud, struct wl_data_source *s)
{
(void)s;
- drag_finish(ud, YASL_DRAG_DROPPED, true);
+ drag_finish(ud, YASL_PRIVATE_DRAG_DROPPED, true);
}
static const struct wl_data_source_listener source_listener = {
@@ -150,8 +150,8 @@ static struct seat *drag_seat(struct wayland_display *c, struct wayland_surface
}
bool wayland_display_drag_start(struct wayland_display *c, struct wayland_surface *origin,
- const struct yasl_drag_image *image,
- const struct yasl_drag_listener *l, void *ud)
+ const struct yasl_private_drag_image *image,
+ const struct yasl_private_drag_listener *l, void *ud)
{
if (!c || !origin || origin->conn != c || !l || c->drag.source)
return false;
@@ -190,39 +190,39 @@ bool wayland_display_drag_start(struct wayland_display *c, struct wayland_surfac
void wayland_display_drag_cancel(struct wayland_display *c)
{
if (c && c->drag.source)
- drag_finish(c, YASL_DRAG_CANCELLED, false);
+ drag_finish(c, YASL_PRIVATE_DRAG_CANCELLED, false);
}
-bool wayland_surface_drag_carry(struct wayland_surface *w, struct yasl_vector2i offset)
+bool wayland_surface_drag_carry(struct wayland_surface *w, struct yasl_private_vector2i offset)
{
struct wayland_display *c = w ? w->conn : NULL;
if (!c || !c->drag.source || !c->drag.toplevel || !w->toplevel)
return false;
uint32_t scale = c->drag.scale_120;
xdg_toplevel_drag_v1_attach(c->drag.toplevel, w->toplevel,
- yasl_scale_to_logical(offset.x, scale),
- yasl_scale_to_logical(offset.y, scale));
+ yasl_private_scale_to_logical(offset.x, scale),
+ yasl_private_scale_to_logical(offset.y, scale));
c->drag.carrying = true;
return true;
}
-bool wayland_surface_place_under_pointer(struct wayland_surface *w, struct yasl_vector2i at)
+bool wayland_surface_place_under_pointer(struct wayland_surface *w, struct yasl_private_vector2i at)
{
(void)w;
(void)at;
return false;
}
-static struct yasl_vector2i drag_device_pos(const struct wayland_surface *w, double x, double y)
+static struct yasl_private_vector2i drag_device_pos(const struct wayland_surface *w, double x, double y)
{
double dx = x * w->scale_factor, dy = y * w->scale_factor;
- return (struct yasl_vector2i){
+ return (struct yasl_private_vector2i){
.x = (int)(dx < 0 ? dx - 0.5 : dx + 0.5),
.y = (int)(dy < 0 ? dy - 0.5 : dy + 0.5),
};
}
-void conn_drop_target(struct wayland_display *c, enum yasl_drop_event ev,
+void conn_drop_target(struct wayland_display *c, enum yasl_private_drop_event ev,
struct wl_surface *on, double x, double y)
{
(void)c;
@@ -230,10 +230,10 @@ void conn_drop_target(struct wayland_display *c, enum yasl_drop_event ev,
(struct wayland_surface *)wl_surface_get_user_data(on) : NULL;
if (!w || w->parent || w->closed)
return;
- yasl_surface_notify_drop(&w->base, ev, drag_device_pos(w, x, y));
+ yasl_private_surface_notify_drop(&w->base, ev, drag_device_pos(w, x, y));
}
-void conn_drag_target(struct wayland_display *c, enum yasl_drag_event ev,
+void conn_drag_target(struct wayland_display *c, enum yasl_private_drag_event ev,
struct wl_surface *on, double x, double y)
{
(void)c;
@@ -241,5 +241,5 @@ void conn_drag_target(struct wayland_display *c, enum yasl_drag_event ev,
(struct wayland_surface *)wl_surface_get_user_data(on) : NULL;
if (!w || w->parent || w->closed)
return;
- yasl_surface_notify_drag(&w->base, ev, drag_device_pos(w, x, y));
+ yasl_private_surface_notify_drag(&w->base, ev, drag_device_pos(w, x, y));
}
diff --git a/src/platform/wayland/ime.c b/src/platform/wayland/ime.c
index 4a091d8..62e5936 100644
--- a/src/platform/wayland/ime.c
+++ b/src/platform/wayland/ime.c
@@ -1,5 +1,7 @@
#include "internal.h"
+#include <errno.h>
+
#define IME_TEXT_MAX (256u * 1024)
static void show_preedit(struct wayland_surface *w, char *text, int begin, int end)
@@ -12,7 +14,7 @@ static void show_preedit(struct wayland_surface *w, char *text, int begin, int e
w->ime_shown_begin = begin;
w->ime_shown_end = end;
if (changed) {
- yasl_surface_notify_composition(&w->base, w->ime_shown,
+ yasl_private_surface_notify_composition(&w->base, w->ime_shown,
w->ime_shown_begin, w->ime_shown_end);
wayland_surface_schedule_redraw(w);
}
@@ -24,21 +26,63 @@ void ime_reset(struct wayland_surface *w)
w->ime_preedit = NULL;
free(w->ime_commit);
w->ime_commit = NULL;
+ w->ime_delete_pending = false;
show_preedit(w, NULL, -1, -1);
}
void ime_send_caret(struct wayland_surface *w)
{
+ wayland_surface_update_text_input(w);
+}
+
+bool wayland_surface_update_text_input(struct wayland_surface *w)
+{
+ if (!w || !w->conn) {
+ errno = EINVAL;
+ return false;
+ }
+ if (!w->conn->text_input_mgr) {
+ errno = ENOTSUP;
+ return false;
+ }
struct seat *seat = w->ime_seat;
- if (!seat || !seat->text_input)
- return;
- uint32_t scale = w->scale_120 ? w->scale_120 : YASL_SCALE_UNIT;
+ if (!seat || !seat->text_input || seat->ime_focus != w)
+ return true;
+ if (!w->base.text_input_active) {
+ if (seat->ime_enabled) {
+ zwp_text_input_v3_disable(seat->text_input);
+ zwp_text_input_v3_commit(seat->text_input);
+ seat->ime_enabled = false;
+ }
+ ime_reset(w);
+ return true;
+ }
+ if (!seat->ime_enabled) {
+ zwp_text_input_v3_enable(seat->text_input);
+ seat->ime_enabled = true;
+ }
+ unsigned purpose = w->base.text_purpose;
+ if (purpose > ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL)
+ purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL;
+ zwp_text_input_v3_set_content_type(seat->text_input,
+ ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE, purpose);
+ const char *surrounding = w->base.text_surrounding ? w->base.text_surrounding : "";
+ size_t length = w->base.text_surrounding ? w->base.text_length : 0;
+ size_t cursor = w->base.text_surrounding ? w->base.text_end : 0;
+ size_t anchor = w->base.text_surrounding ? w->base.text_begin : 0;
+ if (cursor > length) cursor = length;
+ if (anchor > length) anchor = length;
+ if (length <= INT32_MAX && cursor <= INT32_MAX && anchor <= INT32_MAX)
+ zwp_text_input_v3_set_surrounding_text(seat->text_input, surrounding,
+ (int32_t)cursor, (int32_t)anchor);
+ uint32_t scale = w->scale_120 ? w->scale_120 : YASL_PRIVATE_SCALE_UNIT;
zwp_text_input_v3_set_cursor_rectangle(seat->text_input,
- yasl_scale_to_logical(w->ime_caret.x, scale),
- yasl_scale_to_logical(w->ime_caret.y, scale),
- yasl_scale_to_logical(w->ime_caret.width, scale),
- yasl_scale_to_logical(w->ime_caret.height, scale));
+ yasl_private_scale_to_logical(w->ime_caret.x, scale),
+ yasl_private_scale_to_logical(w->ime_caret.y, scale),
+ yasl_private_scale_to_logical(w->ime_caret.width, scale),
+ yasl_private_scale_to_logical(w->ime_caret.height, scale));
zwp_text_input_v3_commit(seat->text_input);
+ return true;
}
bool wayland_surface_ime_preedit_cursor(const struct wayland_surface *w, int *begin, int *end)
@@ -50,7 +94,7 @@ bool wayland_surface_ime_preedit_cursor(const struct wayland_surface *w, int *be
return true;
}
-void wayland_surface_set_ime_caret(struct wayland_surface *w, struct yasl_rect2i caret)
+void wayland_surface_set_ime_caret(struct wayland_surface *w, struct yasl_private_rect2i caret)
{
if (!w || (w->ime_caret.x == caret.x && w->ime_caret.y == caret.y &&
w->ime_caret.width == caret.width && w->ime_caret.height == caret.height))
@@ -62,17 +106,14 @@ void wayland_surface_set_ime_caret(struct wayland_surface *w, struct yasl_rect2i
static void text_input_enter(void *data, struct zwp_text_input_v3 *text_input,
struct wl_surface *surface)
{
+ (void)text_input;
struct seat *s = data;
struct wayland_surface *w = surface_root(surface ?
(struct wayland_surface *)wl_surface_get_user_data(surface) : NULL);
s->ime_focus = w;
if (!w) return;
- zwp_text_input_v3_enable(text_input);
- zwp_text_input_v3_set_content_type(text_input,
- ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE,
- ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL);
w->ime_seat = s;
- ime_send_caret(w);
+ wayland_surface_update_text_input(w);
}
static void text_input_leave(void *data, struct zwp_text_input_v3 *text_input,
@@ -83,8 +124,11 @@ static void text_input_leave(void *data, struct zwp_text_input_v3 *text_input,
struct wayland_surface *w = s->ime_focus;
s->ime_focus = NULL;
if (!w) return;
- zwp_text_input_v3_disable(text_input);
- zwp_text_input_v3_commit(text_input);
+ if (s->ime_enabled) {
+ zwp_text_input_v3_disable(text_input);
+ zwp_text_input_v3_commit(text_input);
+ s->ime_enabled = false;
+ }
if (w->ime_seat == s)
w->ime_seat = NULL;
ime_reset(w);
@@ -110,7 +154,7 @@ static void text_input_preedit_string(void *data,
{
(void)text_input;
struct wayland_surface *w = ((struct seat *)data)->ime_focus;
- if (!w) return;
+ if (!w || !w->base.text_input_active) return;
keyboard_text_reset((struct seat *)data);
free(w->ime_preedit);
w->ime_preedit = text ? copy_text(text) : NULL;
@@ -126,7 +170,7 @@ static void text_input_commit_string(void *data,
{
(void)text_input;
struct wayland_surface *w = ((struct seat *)data)->ime_focus;
- if (!w) return;
+ if (!w || !w->base.text_input_active) return;
keyboard_text_reset((struct seat *)data);
free(w->ime_commit);
w->ime_commit = (text && text[0]) ? copy_text(text) : NULL;
@@ -136,7 +180,31 @@ static void text_input_delete_surrounding_text(void *data,
struct zwp_text_input_v3 *text_input, uint32_t before_length,
uint32_t after_length)
{
- (void)data; (void)text_input; (void)before_length; (void)after_length;
+ (void)text_input;
+ struct seat *seat = data;
+ struct wayland_surface *w = seat->ime_focus;
+ if (!w || !w->base.text_input_active || !w->base.text_surrounding)
+ return;
+ size_t length = w->base.text_length;
+ size_t cursor = w->base.text_end <= length ? w->base.text_end : length;
+ while (cursor && cursor < length &&
+ (((unsigned char)w->base.text_surrounding[cursor] & 0xc0) == 0x80))
+ cursor--;
+ size_t begin = before_length > cursor ? 0 : cursor - before_length;
+ size_t end = after_length > length - cursor ? length : cursor + after_length;
+ while (begin && begin < length &&
+ (((unsigned char)w->base.text_surrounding[begin] & 0xc0) == 0x80))
+ begin--;
+ while (end < length && (((unsigned char)w->base.text_surrounding[end] & 0xc0) == 0x80))
+ end++;
+ /* text_input_v3 batches deletion and commit into one `done` group. Keep
+ * the replacement range paired with that group's committed text and
+ * enqueue both together below, preserving snapshot metadata. */
+ w->ime_delete_pending = true;
+ w->ime_delete_begin = begin;
+ w->ime_delete_end = end;
+ w->ime_delete_revision = w->base.text_revision;
+ w->ime_delete_generation = w->base.text_generation;
}
static void text_input_done(void *data, struct zwp_text_input_v3 *text_input,
@@ -144,17 +212,46 @@ static void text_input_done(void *data, struct zwp_text_input_v3 *text_input,
{
(void)text_input; (void)serial;
struct wayland_surface *w = ((struct seat *)data)->ime_focus;
- if (!w) return;
- if (w->ime_commit) {
- struct yasl_event ev = {
- .type = YASL_EVENT_TEXT,
+ if (!w || !w->base.text_input_active) return;
+ bool has_snapshot = w->base.text_surrounding != NULL &&
+ w->base.text_length <= INT32_MAX;
+ bool has_commit = w->ime_commit && w->ime_commit[0];
+ bool edit = w->ime_delete_pending || (has_commit && has_snapshot);
+ if (edit) {
+ size_t begin = w->ime_delete_pending ? w->ime_delete_begin : w->base.text_begin;
+ size_t end = w->ime_delete_pending ? w->ime_delete_end : w->base.text_end;
+ if (begin > w->base.text_length) begin = w->base.text_length;
+ if (end > w->base.text_length) end = w->base.text_length;
+ if (end < begin) end = begin;
+ struct yasl_private_event ev = {
+ .type = YASL_PRIVATE_EVENT_TEXT_EDIT,
+ .surface = &w->base,
+ .text_edit = {
+ .data = has_commit ? w->ime_commit : "",
+ .len = has_commit ? strlen(w->ime_commit) : 0,
+ .revision = w->ime_delete_revision,
+ .generation = w->ime_delete_generation,
+ .begin = begin,
+ .end = end,
+ },
+ };
+ if (!w->ime_delete_pending) {
+ ev.text_edit.revision = w->base.text_revision;
+ ev.text_edit.generation = w->base.text_generation;
+ }
+ input_queue_push(&w->input, &ev);
+ w->ime_delete_pending = false;
+ }
+ if (w->ime_commit && !edit) {
+ struct yasl_private_event ev = {
+ .type = YASL_PRIVATE_EVENT_TEXT,
.surface = &w->base,
.text = { .data = w->ime_commit, .len = strlen(w->ime_commit) },
};
input_queue_push(&w->input, &ev);
- free(w->ime_commit);
- w->ime_commit = NULL;
}
+ free(w->ime_commit);
+ w->ime_commit = NULL;
char *preedit = w->ime_preedit && w->ime_preedit[0] ? w->ime_preedit : NULL;
if (!preedit)
free(w->ime_preedit);
diff --git a/src/platform/wayland/internal.h b/src/platform/wayland/internal.h
index 34d4133..a479e2b 100644
--- a/src/platform/wayland/internal.h
+++ b/src/platform/wayland/internal.h
@@ -1,5 +1,5 @@
-#ifndef YASL_WAYLAND_INTERNAL_H
-#define YASL_WAYLAND_INTERNAL_H
+#ifndef YASL_PRIVATE_WAYLAND_INTERNAL_H
+#define YASL_PRIVATE_WAYLAND_INTERNAL_H
#define _GNU_SOURCE
@@ -10,6 +10,11 @@
#include <wayland-client.h>
#include <wayland-cursor.h>
+#if YASL_HAS_EGL
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <wayland-egl.h>
+#endif
#include "protocols/xdg-shell-client-protocol.h"
#include "protocols/xdg-decoration-client-protocol.h"
#include "protocols/cursor-shape-v1-client-protocol.h"
@@ -73,7 +78,7 @@ struct wl_conn_output {
struct pending_press {
struct wayland_surface *surface;
- struct yasl_vector2i pos;
+ struct yasl_private_vector2i pos;
int button;
bool release;
};
@@ -105,7 +110,7 @@ struct conn_drag {
struct wl_data_source *source;
struct xdg_toplevel_drag_v1 *toplevel;
struct drag_icon icon;
- struct yasl_drag_listener listener;
+ struct yasl_private_drag_listener listener;
void *ud;
struct seat *seat;
uint32_t scale_120;
@@ -160,15 +165,20 @@ struct seat {
uint64_t pointer_buttons;
uint64_t tool_buttons;
double axis[2], axis_value120[2];
+ double axis_pixels[2];
int64_t axis_discrete[2];
+ uint32_t axis_source;
+ bool scroll_gesture, axis_stop_pending;
+ unsigned axis_phase;
+ bool ime_enabled;
bool axis_has_value120[2], axis_has_discrete[2];
double touch_scroll_y;
/* Embedded structs */
xkb_mod_mask_t input_mod_masks[8];
- struct yasl_vector2i pointer_pos;
- struct yasl_vector2i ptr_left_pos;
- struct yasl_vector2i tool_pos;
+ struct yasl_private_vector2i pointer_pos;
+ struct yasl_private_vector2i ptr_left_pos;
+ struct yasl_private_vector2i tool_pos;
struct touch_point touch_points[SEAT_TOUCH_POINTS];
struct press_queue ptr_presses;
struct press_queue tool_presses;
@@ -183,7 +193,7 @@ struct seat {
uint32_t press_serial;
uint32_t pointer_serial;
int cursor_shape;
- struct yasl_pointer_pen pen;
+ struct yasl_private_pointer_pen pen;
int tool_wheel;
/* 1-byte booleans grouped tightly */
@@ -199,9 +209,14 @@ struct seat {
#include "common/input.h"
struct wayland_display {
- struct yasl_display base;
+ struct yasl_private_display base;
/* 8-byte pointers & 64-bit masks */
struct wl_display *wl;
+#if YASL_HAS_EGL
+ EGLDisplay egl_display;
+ EGLint egl_api;
+ bool egl_initialized;
+#endif
struct wl_registry *registry;
struct wl_compositor *compositor;
struct wl_shm *shm;
@@ -228,8 +243,8 @@ struct wayland_display {
struct wp_fifo_manager_v1 *fifo_mgr;
struct wp_commit_timing_manager_v1 *commit_timing_mgr;
struct xkb_context *xkb_ctx;
- struct yasl_loop *loop;
- const struct yasl_display_cbs *cbs;
+ struct yasl_private_loop *loop;
+ const struct yasl_private_display_cbs *cbs;
void *ud;
char *app_id;
struct xdg_toplevel_drag_manager_v1 *toplevel_drag_mgr;
@@ -243,6 +258,7 @@ struct wayland_display {
clockid_t pres_clock;
int watch;
int depth;
+ uint64_t next_tool_id;
/* 1-byte booleans */
bool owns_loop;
@@ -266,6 +282,12 @@ struct wayland_surface {
struct wayland_surface *dead_next;
struct wayland_surface *parent;
struct wl_surface *surface;
+#if YASL_HAS_EGL
+ struct wl_egl_window *egl_window;
+ EGLSurface egl_surface;
+ EGLContext egl_context;
+ EGLConfig egl_config;
+#endif
struct xdg_surface *xdg_surface;
struct xdg_toplevel *toplevel;
struct xdg_popup *popup;
@@ -276,6 +298,8 @@ struct wayland_surface {
char *ime_commit;
char *ime_shown;
struct seat *ime_seat;
+ size_t ime_delete_begin, ime_delete_end;
+ uint64_t ime_delete_revision, ime_delete_generation;
struct wp_tearing_control_v1 *tearing_control;
struct latency_feedback *latency_feedbacks;
struct latency_feedback latency_pool[8];
@@ -285,24 +309,24 @@ struct wayland_surface {
/* Persistent lock held while relative; lock_seat owns the locked wl_pointer. */
struct zwp_locked_pointer_v1 *pointer_lock;
struct seat *lock_seat;
- const struct yasl_window_cbs *cbs;
+ const struct yasl_private_window_cbs *cbs;
void *ud;
uint64_t frames_skipped;
uint64_t outputs;
double scale_factor;
/* Sub-structures */
- struct yasl_rect2i ime_caret;
- struct yasl_rect2i content;
- struct yasl_frame_clock clock;
+ struct yasl_private_rect2i ime_caret;
+ struct yasl_private_rect2i content;
+ struct yasl_private_frame_clock clock;
struct buffer buffers[NBUF];
- struct yasl_frame frame;
- struct yasl_damage_list damage;
+ struct yasl_private_frame frame;
+ struct yasl_private_damage_list damage;
int ime_cursor_begin;
struct input_queue input;
/* 4-byte integers */
- enum yasl_cursor cursor;
+ enum yasl_private_cursor cursor;
int ime_cursor_end;
int ime_shown_begin, ime_shown_end;
int floating_width, floating_height;
@@ -331,6 +355,7 @@ struct wayland_surface {
bool want_draw;
bool relative;
bool pointer_locked;
+ bool ime_delete_pending;
};
@@ -343,7 +368,7 @@ int buffer_prepare(struct wayland_surface *w, struct buffer *b, int width, int
const struct wl_buffer_listener *listener);
int apply_pending_geometry(struct wayland_surface *w);
-static inline void wl_damage_list(struct wl_surface *s, const struct yasl_damage_list *d)
+static inline void wl_damage_list(struct wl_surface *s, const struct yasl_private_damage_list *d)
{
if (d->n < 0) {
wl_surface_damage_buffer(s, d->bounds.x, d->bounds.y,
@@ -365,6 +390,7 @@ void surface_follow_outputs(struct wayland_surface *w);
uint64_t conn_pres_to_mono(const struct wayland_display *c, uint64_t ns);
uint64_t conn_mono_to_pres(const struct wayland_display *c, uint64_t ns);
void surface_draw_frame(struct wayland_surface *w);
+void wayland_surface_arm_frame(struct wayland_surface *w);
void surface_fail(struct wayland_surface *w);
void display_leave(struct wayland_display *c);
@@ -376,9 +402,9 @@ static inline struct wayland_surface *surface_root(struct wayland_surface *w)
}
void conn_drag_end(struct wayland_display *c);
-void conn_drop_target(struct wayland_display *c, enum yasl_drop_event ev,
+void conn_drop_target(struct wayland_display *c, enum yasl_private_drop_event ev,
struct wl_surface *on, double x, double y);
-void conn_drag_target(struct wayland_display *c, enum yasl_drag_event ev,
+void conn_drag_target(struct wayland_display *c, enum yasl_private_drag_event ev,
struct wl_surface *on, double x, double y);
void seat_bind(struct wayland_display *c, struct wl_registry *registry,
@@ -386,6 +412,7 @@ void seat_bind(struct wayland_display *c, struct wl_registry *registry,
bool seat_remove(struct wayland_display *c, uint32_t name);
void seat_destroy(struct seat *s);
void seat_note_input(struct seat *s, uint32_t serial);
+void seat_ensure_text_input(struct seat *s);
void seat_forget_surface(struct seat *s, struct wayland_surface *w);
void seat_clipboard_ensure(struct seat *s);
int display_input_init(struct wayland_display *c);
@@ -409,6 +436,7 @@ extern const struct zwp_text_input_v3_listener text_input_listener;
void ime_reset(struct wayland_surface *w);
void keyboard_text_reset(struct seat *s);
void ime_send_caret(struct wayland_surface *w);
+bool wayland_surface_update_text_input(struct wayland_surface *w);
int surface_init_shell(struct wayland_surface *w, const char *title);
extern const struct xdg_surface_listener shell_surface_listener;
diff --git a/src/platform/wayland/keyboard.c b/src/platform/wayland/keyboard.c
index 7f8274d..6f9dec9 100644
--- a/src/platform/wayland/keyboard.c
+++ b/src/platform/wayland/keyboard.c
@@ -133,8 +133,8 @@ bool conn_keyboard_on(const struct wayland_display *c, const struct wayland_surf
static void push_focus(struct wayland_surface *w, bool focused)
{
- struct yasl_event ev = {
- .type = YASL_EVENT_FOCUS,
+ struct yasl_private_event ev = {
+ .type = YASL_PRIVATE_EVENT_FOCUS,
.surface = &w->base,
.focus = { .focused = focused },
};
@@ -218,18 +218,18 @@ static uint32_t key_codepoint_at_level(struct seat *s, uint32_t key, xkb_layout_
return n == 1 ? xkb_keysym_to_utf32(syms[0]) : 0;
}
-static struct yasl_key_event xkb_key_event(struct seat *s, uint32_t key,
+static struct yasl_private_key_event xkb_key_event(struct seat *s, uint32_t key,
enum yasl_key_action action)
{
uint32_t code = key + XKB_EVDEV_OFFSET;
xkb_layout_index_t layout = xkb_state_key_get_layout(s->xkb_state, code);
- struct yasl_key_event k = {
- .key = yasl_key_from_evdev(key),
+ struct yasl_private_key_event k = {
+ .key = yasl_private_key_from_evdev(key),
.action = action,
.mods = input_modifiers(s),
- .codepoint = yasl_key_label(key_codepoint_at_level(s, key, layout, 0)),
- .shifted = yasl_key_label(key_codepoint_at_level(s, key, layout, 1)),
+ .codepoint = yasl_private_key_label(key_codepoint_at_level(s, key, layout, 0)),
+ .shifted = yasl_private_key_label(key_codepoint_at_level(s, key, layout, 1)),
.native_code = key,
};
return k;
@@ -239,8 +239,8 @@ static void keyboard_text(struct seat *s, struct wayland_surface *w, uint32_t ke
{
uint32_t code = key + XKB_EVDEV_OFFSET;
unsigned mods = input_modifiers(s);
- if ((mods & (YASL_MOD_CTRL | YASL_MOD_SUPER)) ||
- ((mods & YASL_MOD_ALT) &&
+ if ((mods & (YASL_PRIVATE_MOD_CTRL | YASL_PRIVATE_MOD_SUPER)) ||
+ ((mods & YASL_PRIVATE_MOD_ALT) &&
!xkb_state_mod_index_is_consumed(s->xkb_state, code, s->mod_alt))) {
keyboard_text_reset(s);
return;
@@ -278,13 +278,13 @@ static void keyboard_text(struct seat *s, struct wayland_surface *w, uint32_t ke
else xkb_state_key_get_utf8(s->xkb_state, code, text, (size_t)len + 1);
/* Editing commands belong to key events, not text insertion. */
if ((unsigned char)text[0] >= 0x20 && text[0] != 0x7f) {
- struct yasl_event ev = {.type = YASL_EVENT_TEXT,
+ struct yasl_private_event ev = {.type = YASL_PRIVATE_EVENT_TEXT,
.surface = &w->base, .text = {.data = text, .len = (size_t)len}};
input_queue_push(&w->input, &ev);
}
if (text != local) free(text);
} else {
- struct yasl_event ev = {.type = YASL_EVENT_INPUT_RESET, .surface = &w->base};
+ struct yasl_private_event ev = {.type = YASL_PRIVATE_EVENT_INPUT_RESET, .surface = &w->base};
input_queue_push(&w->input, &ev);
}
}
@@ -296,9 +296,9 @@ static bool keyboard_dispatch_key(struct seat *s, struct wayland_surface *w, uin
{
if (!s->xkb_state || !w->cbs) return false;
- struct yasl_key_event k = xkb_key_event(s, key, action);
- struct yasl_event ev = {
- .type = YASL_EVENT_KEY,
+ struct yasl_private_key_event k = xkb_key_event(s, key, action);
+ struct yasl_private_event ev = {
+ .type = YASL_PRIVATE_EVENT_KEY,
.surface = &w->base,
.key = k,
};
@@ -329,7 +329,7 @@ static void keyboard_key(void *data, struct wl_keyboard *keyboard,
if (keyboard_dispatch_key(s, w, key, YASL_KEY_PRESS) && repeatable) {
s->repeat_key = key;
s->repeat_held = true;
- s->repeat_started_ns = yasl_loop_now_ns();
+ s->repeat_started_ns = yasl_private_loop_now_ns();
keyboard_repeat_sync(s);
}
}
@@ -389,7 +389,7 @@ int keyboard_repeat_init(struct seat *s)
if (s->repeat_fd >= 0) return 0;
s->repeat_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
if (s->repeat_fd < 0) return -1;
- s->repeat_watch = yasl_loop_add_fd(s->conn->loop, s->repeat_fd, POLLIN,
+ s->repeat_watch = yasl_private_loop_add_fd(s->conn->loop, s->repeat_fd, POLLIN,
keyboard_repeat_ready, s);
if (s->repeat_watch <= 0) {
s->repeat_watch = 0;
@@ -406,18 +406,18 @@ int seat_modifiers(const struct seat *s)
if (unlikely(!s || !s->xkb_state)) return 0;
return ((s->mod_shift != XKB_MOD_INVALID &&
xkb_state_mod_index_is_active(s->xkb_state, s->mod_shift,
- XKB_STATE_MODS_EFFECTIVE) > 0) * YASL_MOD_SHIFT) |
+ XKB_STATE_MODS_EFFECTIVE) > 0) * YASL_PRIVATE_MOD_SHIFT) |
((s->mod_alt != XKB_MOD_INVALID &&
xkb_state_mod_index_is_active(s->xkb_state, s->mod_alt,
- XKB_STATE_MODS_EFFECTIVE) > 0) * YASL_MOD_ALT) |
+ XKB_STATE_MODS_EFFECTIVE) > 0) * YASL_PRIVATE_MOD_ALT) |
((s->mod_ctrl != XKB_MOD_INVALID &&
xkb_state_mod_index_is_active(s->xkb_state, s->mod_ctrl,
- XKB_STATE_MODS_EFFECTIVE) > 0) * YASL_MOD_CTRL) |
+ XKB_STATE_MODS_EFFECTIVE) > 0) * YASL_PRIVATE_MOD_CTRL) |
((s->mod_super != XKB_MOD_INVALID &&
xkb_state_mod_index_is_active(s->xkb_state, s->mod_super,
- XKB_STATE_MODS_EFFECTIVE) > 0) * YASL_MOD_SUPER) |
+ XKB_STATE_MODS_EFFECTIVE) > 0) * YASL_PRIVATE_MOD_SUPER) |
((xkb_state_mod_name_is_active(s->xkb_state, XKB_MOD_NAME_CAPS,
- XKB_STATE_MODS_EFFECTIVE) > 0) * YASL_MOD_CAPS);
+ XKB_STATE_MODS_EFFECTIVE) > 0) * YASL_PRIVATE_MOD_CAPS);
}
int wayland_display_modifiers(const struct wayland_display *c)
@@ -425,12 +425,12 @@ int wayland_display_modifiers(const struct wayland_display *c)
return c ? seat_modifiers(c->active_seat ? c->active_seat : c->seats) : 0;
}
-void wayland_display_copy(struct wayland_display *c, enum yasl_selection sel, const char *text)
+void wayland_display_copy(struct wayland_display *c, enum yasl_private_selection sel, const char *text)
{
(void)wayland_display_copy_text(c, sel, text);
}
-bool wayland_display_copy_text(struct wayland_display *c, enum yasl_selection sel,
+bool wayland_display_copy_text(struct wayland_display *c, enum yasl_private_selection sel,
const char *text)
{
struct seat *s = c ? (c->active_seat ? c->active_seat : c->seats) : NULL;
@@ -447,28 +447,28 @@ bool wayland_display_copy_text(struct wayland_display *c, enum yasl_selection se
return false;
}
errno = 0;
- bool ok = sel == YASL_PRIMARY ?
+ bool ok = sel == YASL_PRIVATE_PRIMARY ?
clipboard_copy_primary(s->clipboard, text, s->input_serial) :
clipboard_copy(s->clipboard, text, s->input_serial);
return ok;
}
-void wayland_display_paste(struct wayland_display *c, enum yasl_selection sel, struct wayland_surface *target)
+void wayland_display_paste(struct wayland_display *c, enum yasl_private_selection sel, struct wayland_surface *target)
{
struct seat *s = c ? (c->active_seat ? c->active_seat : c->seats) : NULL;
if (!target || target->closed || target->destroyed) return;
if (!s || !s->clipboard) {
- yasl_surface_complete_paste(&target->base, 0,
- YASL_TRANSFER_UNAVAILABLE, NULL, 0);
+ yasl_private_surface_complete_paste(&target->base, 0,
+ YASL_PRIVATE_TRANSFER_UNAVAILABLE, NULL, 0);
return;
}
- if (sel == YASL_PRIMARY)
+ if (sel == YASL_PRIVATE_PRIMARY)
clipboard_paste_primary(s->clipboard, target->surface);
else
clipboard_paste(s->clipboard, target->surface);
}
-bool wayland_display_request_paste(struct wayland_display *c, enum yasl_selection sel,
+bool wayland_display_request_paste(struct wayland_display *c, enum yasl_private_selection sel,
struct wayland_surface *target, uint64_t request_id)
{
struct seat *s = c ? (c->active_seat ? c->active_seat : c->seats) : NULL;
@@ -486,7 +486,7 @@ bool wayland_display_request_paste(struct wayland_display *c, enum yasl_selectio
return ok;
}
-bool wayland_surface_poll_event(struct wayland_surface *w, struct yasl_event *ev)
+bool wayland_surface_poll_event(struct wayland_surface *w, struct yasl_private_event *ev)
{
return w && ev && input_queue_pop(&w->input, ev);
}
diff --git a/src/platform/wayland/keymap.c b/src/platform/wayland/keymap.c
index d626f30..6c3b4dd 100644
--- a/src/platform/wayland/keymap.c
+++ b/src/platform/wayland/keymap.c
@@ -1,7 +1,7 @@
#include "keymap.h"
/* Numeric Linux evdev codes; no platform headers are needed by this table. */
-enum yasl_key yasl_key_from_evdev(uint32_t code)
+enum yasl_key yasl_private_key_from_evdev(uint32_t code)
{
switch (code) {
case 1: return YASL_KEY_ESCAPE; /* KEY_ESC */
diff --git a/src/platform/wayland/keymap.h b/src/platform/wayland/keymap.h
index c0ff81e..26b6ed4 100644
--- a/src/platform/wayland/keymap.h
+++ b/src/platform/wayland/keymap.h
@@ -1,8 +1,8 @@
-#ifndef YASL_WAYLAND_KEYMAP_H
-#define YASL_WAYLAND_KEYMAP_H
+#ifndef YASL_PRIVATE_WAYLAND_KEYMAP_H
+#define YASL_PRIVATE_WAYLAND_KEYMAP_H
#include "yasl/keycodes.h"
-enum yasl_key yasl_key_from_evdev(uint32_t code);
+enum yasl_key yasl_private_key_from_evdev(uint32_t code);
#endif
diff --git a/src/platform/wayland/native.c b/src/platform/wayland/native.c
index 55ce445..54ca184 100644
--- a/src/platform/wayland/native.c
+++ b/src/platform/wayland/native.c
@@ -1,14 +1,14 @@
#include "common/backend.h"
-#include "yasl/native/wayland.h"
+#include "common/private_native_wayland.h"
-struct wl_display *yasl_wayland_display_get_wl_display(struct yasl_display *d)
+struct wl_display *yasl_private_wayland_display_get_wl_display(struct yasl_private_display *d)
{
- return (d && yasl_display_backend(d) == YASL_BACKEND_WAYLAND) ?
- (struct wl_display *)yasl_display_get_native_handle(d) : NULL;
+ return (d && yasl_private_display_backend(d) == YASL_PRIVATE_BACKEND_WAYLAND) ?
+ (struct wl_display *)yasl_private_display_get_native_handle(d) : NULL;
}
-struct wl_surface *yasl_wayland_surface_get_wl_surface(struct yasl_surface *s)
+struct wl_surface *yasl_private_wayland_surface_get_wl_surface(struct yasl_surface *s)
{
- return (s && s->display && yasl_display_backend(s->display) == YASL_BACKEND_WAYLAND) ?
- (struct wl_surface *)yasl_surface_get_native_handle(s) : NULL;
+ return (s && s->display && yasl_private_display_backend(s->display) == YASL_PRIVATE_BACKEND_WAYLAND) ?
+ (struct wl_surface *)yasl_private_surface_get_native_handle(s) : NULL;
}
diff --git a/src/platform/wayland/pointer.c b/src/platform/wayland/pointer.c
index da666da..5f486ae 100644
--- a/src/platform/wayland/pointer.c
+++ b/src/platform/wayland/pointer.c
@@ -12,12 +12,22 @@ struct tablet_tool {
struct zwp_tablet_tool_v2 *proxy;
struct wp_cursor_shape_device_v1 *shape_dev;
uint32_t proximity_serial;
+ uint64_t device_id, tool_id;
+ uint32_t axes_valid, axes_changed, capability_mask;
+ double x, y;
+ double pressure, tilt_x, tilt_y, rotation, distance, tangential, wheel_degrees;
+ unsigned changed_button;
+ unsigned pending_actions[8], pending_buttons[8], pending_action_count;
+ bool pending_contacts[8];
+ unsigned kind;
+ bool in_contact, pen_in_proximity;
bool eraser;
};
struct tablet_device {
struct tablet_device *next;
struct zwp_tablet_v2 *proxy;
+ uint64_t id;
};
struct tablet_pad {
@@ -25,10 +35,10 @@ struct tablet_pad {
struct zwp_tablet_pad_v2 *proxy;
};
-static struct yasl_vector2i device_from_fixed(const struct wayland_surface *w,
+static struct yasl_private_vector2i device_from_fixed(const struct wayland_surface *w,
wl_fixed_t x, wl_fixed_t y)
{
- return (struct yasl_vector2i){
+ return (struct yasl_private_vector2i){
.x = (int)lrint(wl_fixed_to_double(x) * w->scale_factor),
.y = (int)lrint(wl_fixed_to_double(y) * w->scale_factor),
};
@@ -41,10 +51,10 @@ void seat_note_input(struct seat *s, uint32_t serial)
}
static void push_pointer(struct seat *s, struct wayland_surface *w,
- enum yasl_event_type type, struct yasl_pointer_event ev)
+ enum yasl_private_event_type type, struct yasl_private_pointer_event ev)
{
ev.mods = (uint32_t)seat_modifiers(s);
- struct yasl_event input_ev = {
+ struct yasl_private_event input_ev = {
.type = type,
.surface = &w->base,
.pointer = ev,
@@ -52,13 +62,15 @@ static void push_pointer(struct seat *s, struct wayland_surface *w,
input_queue_push(&surface_root(w)->input, &input_ev);
}
-static void report_wheel(struct seat *s, struct wayland_surface *w,
- struct yasl_vector2i pos, double x, double y)
+static unsigned scroll_source_of(uint32_t source)
{
- if ((x == 0 && y == 0) || !isfinite(x) || !isfinite(y)) return;
- push_pointer(s, w, YASL_EVENT_POINTER_SCROLL, (struct yasl_pointer_event){
- .pos = pos, .scroll = {x, y},
- });
+ switch (source) {
+ case WL_POINTER_AXIS_SOURCE_WHEEL: return 1;
+ case WL_POINTER_AXIS_SOURCE_WHEEL_TILT: return 1;
+ case WL_POINTER_AXIS_SOURCE_FINGER: return 2;
+ case WL_POINTER_AXIS_SOURCE_CONTINUOUS: return 3;
+ default: return 0;
+ }
}
static bool cursor_theme_for(struct wayland_display *c, int scale)
@@ -90,10 +102,10 @@ static bool seat_cursor_surface(struct seat *s)
}
static void set_cursor_theme_fallback(struct seat *s, struct wayland_surface *w,
- enum yasl_cursor shape)
+ enum yasl_private_cursor shape)
{
struct wayland_display *c = s->conn;
- int scale = (int)((w->scale_120 + YASL_SCALE_UNIT - 1) / YASL_SCALE_UNIT);
+ int scale = (int)((w->scale_120 + YASL_PRIVATE_SCALE_UNIT - 1) / YASL_PRIVATE_SCALE_UNIT);
if (scale < 1) scale = 1;
if (!seat_cursor_surface(s) || !cursor_theme_for(c, scale)) return;
static const char *names[][2] = {
@@ -107,7 +119,7 @@ static void set_cursor_theme_fallback(struct seat *s, struct wayland_surface *w,
{"ew-resize", "ew-resize"},
{"ns-resize", "ns-resize"},
};
- int idx = (unsigned)shape < YASL_CURSOR_HIDDEN ? (int)shape : 0;
+ int idx = (unsigned)shape < YASL_PRIVATE_CURSOR_HIDDEN ? (int)shape : 0;
struct wl_cursor *cursor = wl_cursor_theme_get_cursor(c->cursor_theme, names[idx][0]);
if (!cursor) cursor = wl_cursor_theme_get_cursor(c->cursor_theme, names[idx][1]);
if (!cursor || !cursor->image_count) return;
@@ -117,11 +129,11 @@ static void set_cursor_theme_fallback(struct seat *s, struct wayland_surface *w,
int theme_scale = c->cursor_theme_scale;
if (s->cursor_viewport) {
- uint32_t scale_120 = (uint32_t)theme_scale * YASL_SCALE_UNIT;
+ uint32_t scale_120 = (uint32_t)theme_scale * YASL_PRIVATE_SCALE_UNIT;
wp_viewport_set_destination(s->cursor_viewport,
- (int)(((int64_t)(int)img->width * YASL_SCALE_UNIT + scale_120 - 1) /
+ (int)(((int64_t)(int)img->width * YASL_PRIVATE_SCALE_UNIT + scale_120 - 1) /
scale_120),
- (int)(((int64_t)(int)img->height * YASL_SCALE_UNIT + scale_120 - 1) /
+ (int)(((int64_t)(int)img->height * YASL_PRIVATE_SCALE_UNIT + scale_120 - 1) /
scale_120));
} else {
if (img->width % (uint32_t)theme_scale || img->height % (uint32_t)theme_scale)
@@ -137,17 +149,17 @@ static void set_cursor_theme_fallback(struct seat *s, struct wayland_surface *w,
wl_surface_commit(s->cursor_surface);
}
-static uint32_t cursor_shape_of(enum yasl_cursor shape)
+static uint32_t cursor_shape_of(enum yasl_private_cursor shape)
{
switch (shape) {
- case YASL_CURSOR_TEXT: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT;
- case YASL_CURSOR_LINK: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER;
- case YASL_CURSOR_CROSSHAIR: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR;
- case YASL_CURSOR_MOVE: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE;
- case YASL_CURSOR_RESIZE_EW: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE;
- case YASL_CURSOR_RESIZE_NS: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE;
- case YASL_CURSOR_RESIZE_NWSE: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE;
- case YASL_CURSOR_RESIZE_NESW: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE;
+ case YASL_PRIVATE_CURSOR_TEXT: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT;
+ case YASL_PRIVATE_CURSOR_LINK: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER;
+ case YASL_PRIVATE_CURSOR_CROSSHAIR: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR;
+ case YASL_PRIVATE_CURSOR_MOVE: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE;
+ case YASL_PRIVATE_CURSOR_RESIZE_EW: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE;
+ case YASL_PRIVATE_CURSOR_RESIZE_NS: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE;
+ case YASL_PRIVATE_CURSOR_RESIZE_NWSE: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE;
+ case YASL_PRIVATE_CURSOR_RESIZE_NESW: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE;
default: return WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT;
}
}
@@ -155,11 +167,11 @@ static uint32_t cursor_shape_of(enum yasl_cursor shape)
/* Relative mode hides the pointer but keeps w->cursor for the return to NORMAL. */
static void seat_set_cursor(struct seat *s, struct wayland_surface *w)
{
- enum yasl_cursor shape = w->relative ? YASL_CURSOR_HIDDEN : w->cursor;
+ enum yasl_private_cursor shape = w->relative ? YASL_PRIVATE_CURSOR_HIDDEN : w->cursor;
if (!s->pointer || !s->pointer_serial || s->pointer_focus != w ||
s->cursor_shape == (int)shape)
return;
- if (shape == YASL_CURSOR_HIDDEN)
+ if (shape == YASL_PRIVATE_CURSOR_HIDDEN)
wl_pointer_set_cursor(s->pointer, s->pointer_serial, NULL, 0, 0);
else if (s->cursor_shape_dev)
wp_cursor_shape_device_v1_set_shape(s->cursor_shape_dev,
@@ -169,20 +181,20 @@ static void seat_set_cursor(struct seat *s, struct wayland_surface *w)
s->cursor_shape = shape;
}
-static void tool_set_cursor(struct tablet_tool *t, enum yasl_cursor shape)
+static void tool_set_cursor(struct tablet_tool *t, enum yasl_private_cursor shape)
{
if (!t->proximity_serial)
return;
- if (shape == YASL_CURSOR_HIDDEN)
+ if (shape == YASL_PRIVATE_CURSOR_HIDDEN)
zwp_tablet_tool_v2_set_cursor(t->proxy, t->proximity_serial, NULL, 0, 0);
else if (t->shape_dev)
wp_cursor_shape_device_v1_set_shape(t->shape_dev, t->proximity_serial,
cursor_shape_of(shape));
}
-void wayland_surface_set_cursor(struct wayland_surface *w, enum yasl_cursor shape)
+void wayland_surface_set_cursor(struct wayland_surface *w, enum yasl_private_cursor shape)
{
- if (!w || !w->conn || w->destroyed || (unsigned)shape > YASL_CURSOR_HIDDEN) return;
+ if (!w || !w->conn || w->destroyed || (unsigned)shape > YASL_PRIVATE_CURSOR_HIDDEN) return;
w->cursor = shape;
for (struct seat *s = w->conn->seats; s; s = s->next) {
seat_set_cursor(s, w);
@@ -193,7 +205,7 @@ void wayland_surface_set_cursor(struct wayland_surface *w, enum yasl_cursor shap
static void press_queue_flush(struct seat *s, struct press_queue *q,
struct wayland_surface *only, uint64_t *buttons,
- struct yasl_pointer_event like)
+ struct yasl_private_pointer_event like)
{
int kept = 0;
int count = q->n;
@@ -206,10 +218,10 @@ static void press_queue_flush(struct seat *s, struct press_queue *q,
if (!p.surface) continue;
uint64_t mask = 1ull << p.button;
*buttons = (*buttons & ~mask) | ((uint64_t)(!p.release) << p.button);
- struct yasl_pointer_event ev = like;
+ struct yasl_private_pointer_event ev = like;
ev.pos = p.pos;
- ev.button = (enum yasl_pointer_button)p.button;
- enum yasl_event_type type = p.release ? YASL_EVENT_POINTER_UP : YASL_EVENT_POINTER_DOWN;
+ ev.button = (enum yasl_private_pointer_button)p.button;
+ enum yasl_private_event_type type = p.release ? YASL_PRIVATE_EVENT_POINTER_UP : YASL_PRIVATE_EVENT_POINTER_DOWN;
push_pointer(s, p.surface, type, ev);
}
q->head = 0;
@@ -217,7 +229,7 @@ static void press_queue_flush(struct seat *s, struct press_queue *q,
}
static void press_queue_push(struct press_queue *q, struct wayland_surface *w,
- struct yasl_vector2i pos, int button, bool release)
+ struct yasl_private_vector2i pos, int button, bool release)
{
if (q->n == 8) {
q->head = (q->head + 1) & 7;
@@ -244,10 +256,15 @@ void seat_pointer_reset(struct seat *s)
s->pointer_serial = 0;
s->motion_pending = false;
memset(s->axis, 0, sizeof(s->axis));
+ memset(s->axis_pixels, 0, sizeof(s->axis_pixels));
memset(s->axis_value120, 0, sizeof(s->axis_value120));
memset(s->axis_discrete, 0, sizeof(s->axis_discrete));
memset(s->axis_has_value120, 0, sizeof(s->axis_has_value120));
memset(s->axis_has_discrete, 0, sizeof(s->axis_has_discrete));
+ s->axis_stop_pending = false;
+ s->scroll_gesture = false;
+ s->axis_phase = 0;
+ s->axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
s->cursor_shape = -1;
}
@@ -263,7 +280,7 @@ static void flush_pending_motion(struct seat *s, struct wayland_surface *w)
{
if (!s->motion_pending) return;
s->motion_pending = false;
- push_pointer(s, w, YASL_EVENT_POINTER_MOTION, (struct yasl_pointer_event){
+ push_pointer(s, w, YASL_PRIVATE_EVENT_POINTER_MOTION, (struct yasl_private_pointer_event){
.pos = s->pointer_pos,
});
}
@@ -356,6 +373,13 @@ static void pointer_axis(void *data, struct wl_pointer *pointer,
double v = wl_fixed_to_double(value);
if (likely(axis < 2)) {
s->axis[axis] += v;
+ s->axis_pixels[axis] += v;
+ if (s->axis_source == WL_POINTER_AXIS_SOURCE_FINGER ||
+ s->axis_source == WL_POINTER_AXIS_SOURCE_CONTINUOUS) {
+ if (!s->scroll_gesture) s->axis_phase = 1u;
+ else if (s->axis_phase != 1u) s->axis_phase = 2u;
+ s->scroll_gesture = true;
+ }
}
pointer_event_done(s);
}
@@ -363,13 +387,14 @@ static void pointer_axis(void *data, struct wl_pointer *pointer,
static void pointer_axis_source(void *data, struct wl_pointer *pointer, uint32_t axis_source)
{
(void)pointer;
- (void)data; (void)axis_source;
+ ((struct seat *)data)->axis_source = axis_source;
}
static void pointer_axis_stop(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis)
{
/* A stop ends a gesture, not the offsets already received in this frame. */
- (void)data; (void)pointer; (void)time; (void)axis;
+ (void)pointer; (void)time; (void)axis;
+ ((struct seat *)data)->axis_stop_pending = true;
}
static void pointer_axis_discrete(void *data, struct wl_pointer *pointer, uint32_t axis, int32_t discrete)
@@ -405,7 +430,28 @@ static void pointer_frame_scroll(struct seat *s, struct wayland_surface *w)
s->axis_discrete[axis] = 0;
s->axis_has_value120[axis] = s->axis_has_discrete[axis] = false;
}
- report_wheel(s, w, s->pointer_pos, lines[1], lines[0]);
+ bool stopped = s->axis_stop_pending;
+ unsigned source = scroll_source_of(s->axis_source);
+ unsigned phase = source == 2 || source == 3
+ ? (stopped ? 3u : s->axis_phase) : 0u;
+ bool has_pixels = (source == 2 || source == 3) &&
+ (s->axis_pixels[0] != 0 || s->axis_pixels[1] != 0);
+ if (lines[0] != 0 || lines[1] != 0 || stopped) {
+ push_pointer(s, w, YASL_PRIVATE_EVENT_POINTER_SCROLL,
+ (struct yasl_private_pointer_event){
+ .pos = s->pointer_pos,
+ .scroll = {lines[1], lines[0]},
+ .pixel_scroll = {s->axis_pixels[1] * w->scale_factor,
+ s->axis_pixels[0] * w->scale_factor},
+ .scroll_valid = 1u | (has_pixels ? 2u : 0u),
+ .scroll_source = source,
+ .scroll_phase = phase,
+ });
+ }
+ memset(s->axis_pixels, 0, sizeof(s->axis_pixels));
+ s->axis_stop_pending = false;
+ if (stopped) s->scroll_gesture = false;
+ s->axis_phase = 0;
}
static void pointer_frame(void *data, struct wl_pointer *pointer)
@@ -416,14 +462,14 @@ static void pointer_frame(void *data, struct wl_pointer *pointer)
if (left) {
s->ptr_left = NULL;
if (s->ptr_left_motion)
- push_pointer(s, left, YASL_EVENT_POINTER_MOTION, (struct yasl_pointer_event){
+ push_pointer(s, left, YASL_PRIVATE_EVENT_POINTER_MOTION, (struct yasl_private_pointer_event){
.pos = s->ptr_left_pos,
});
- press_queue_flush(s, &s->ptr_presses, left, &s->pointer_buttons, (struct yasl_pointer_event){0});
- push_pointer(s, left, YASL_EVENT_POINTER_LEAVE, (struct yasl_pointer_event){
+ press_queue_flush(s, &s->ptr_presses, left, &s->pointer_buttons, (struct yasl_private_pointer_event){0});
+ push_pointer(s, left, YASL_PRIVATE_EVENT_POINTER_LEAVE, (struct yasl_private_pointer_event){
.pos = s->ptr_left_pos,
});
- struct yasl_vector2i pos = s->pointer_pos;
+ struct yasl_private_vector2i pos = s->pointer_pos;
bool motion = s->motion_pending;
uint32_t serial = s->pointer_focus ? s->pointer_serial : 0;
int shape = s->pointer_focus ? s->cursor_shape : -1;
@@ -440,7 +486,7 @@ static void pointer_frame(void *data, struct wl_pointer *pointer)
}
flush_pending_motion(s, w);
- press_queue_flush(s, &s->ptr_presses, NULL, &s->pointer_buttons, (struct yasl_pointer_event){0});
+ press_queue_flush(s, &s->ptr_presses, NULL, &s->pointer_buttons, (struct yasl_private_pointer_event){0});
pointer_frame_scroll(s, w);
}
@@ -460,7 +506,7 @@ static void relative_motion(void *data, struct zwp_relative_pointer_v1 *pointer,
/* Unlocked movement arrives as wl_pointer.motion; the queue derives its delta. */
if (!w || !w->pointer_locked || w->lock_seat != s) return;
flush_pending_motion(s, w);
- push_pointer(s, w, YASL_EVENT_POINTER_MOTION, (struct yasl_pointer_event){
+ push_pointer(s, w, YASL_PRIVATE_EVENT_POINTER_MOTION, (struct yasl_private_pointer_event){
.pos = s->pointer_pos,
.delta = {wl_fixed_to_double(dx) * w->scale_factor,
wl_fixed_to_double(dy) * w->scale_factor},
@@ -525,12 +571,12 @@ static void seat_lock_surfaces(struct seat *s)
surface_lock_pointer(w, s);
}
-bool wayland_surface_set_pointer_mode(struct wayland_surface *w, enum yasl_pointer_mode mode)
+bool wayland_surface_set_pointer_mode(struct wayland_surface *w, enum yasl_private_pointer_mode mode)
{
if (!w || !w->conn || w->destroyed)
return false;
struct wayland_display *c = w->conn;
- bool relative = mode == YASL_POINTER_RELATIVE;
+ bool relative = mode == YASL_PRIVATE_POINTER_RELATIVE;
if (relative && (!c->relative_pointer_mgr || !c->pointer_constraints))
return false;
w->relative = relative;
@@ -572,10 +618,10 @@ static struct touch_point *touch_find(struct seat *s, int32_t id)
return NULL;
}
-static struct yasl_vector2i touch_pos(const struct touch_point *p)
+static struct yasl_private_vector2i touch_pos(const struct touch_point *p)
{
double scale = p->surface->scale_factor;
- return (struct yasl_vector2i){
+ return (struct yasl_private_vector2i){
.x = (int)lrint(p->x * scale), .y = (int)lrint(p->y * scale),
};
}
@@ -583,11 +629,11 @@ static struct yasl_vector2i touch_pos(const struct touch_point *p)
static void touch_report(struct seat *s, struct touch_point *p, int button,
- enum yasl_event_type type)
+ enum yasl_private_event_type type)
{
- push_pointer(s, p->surface, type, (struct yasl_pointer_event){
- .pos = touch_pos(p), .button = (enum yasl_pointer_button)button,
- .device = YASL_PTR_DEV_TOUCH,
+ push_pointer(s, p->surface, type, (struct yasl_private_pointer_event){
+ .pos = touch_pos(p), .button = (enum yasl_private_pointer_button)button,
+ .device = YASL_PRIVATE_PTR_DEV_TOUCH,
});
}
@@ -644,7 +690,7 @@ static void touch_frame(void *data, struct wl_touch *touch)
if (p->down && !s->touch_primary && !s->touch_scrolling) {
s->touch_primary = p;
s->touch_pressed = true;
- touch_report(s, p, 0, YASL_EVENT_POINTER_DOWN);
+ touch_report(s, p, 0, YASL_PRIVATE_EVENT_POINTER_DOWN);
}
if (!p->up) {
active_n++;
@@ -657,7 +703,7 @@ static void touch_frame(void *data, struct wl_touch *touch)
struct touch_point *primary = s->touch_primary;
if (primary && !s->touch_scrolling && active_n >= 2) {
if (s->touch_pressed)
- touch_report(s, primary, 0, YASL_EVENT_POINTER_UP);
+ touch_report(s, primary, 0, YASL_PRIVATE_EVENT_POINTER_UP);
s->touch_pressed = false;
s->touch_scrolling = true;
s->touch_scroll_y = centroid_n ? centroid_sum / centroid_n : 0;
@@ -667,14 +713,14 @@ static void touch_frame(void *data, struct wl_touch *touch)
s->touch_scroll_y = y;
if (dy != 0.0) {
double lines = dy / SCROLL_PX_PER_LINE;
- push_pointer(s, primary->surface, YASL_EVENT_POINTER_SCROLL, (struct yasl_pointer_event){
+ push_pointer(s, primary->surface, YASL_PRIVATE_EVENT_POINTER_SCROLL, (struct yasl_private_pointer_event){
.pos = touch_pos(primary),
.scroll = {0, -lines},
- .device = YASL_PTR_DEV_TOUCH,
+ .device = YASL_PRIVATE_PTR_DEV_TOUCH,
});
}
} else if (primary && primary->moved && s->touch_pressed) {
- touch_report(s, primary, 0, YASL_EVENT_POINTER_MOTION);
+ touch_report(s, primary, 0, YASL_PRIVATE_EVENT_POINTER_MOTION);
}
for (int i = 0; i < SEAT_TOUCH_POINTS; i++) {
struct touch_point *p = &s->touch_points[i];
@@ -683,7 +729,7 @@ static void touch_frame(void *data, struct wl_touch *touch)
active_n--;
if (p == s->touch_primary) {
if (s->touch_pressed)
- touch_report(s, p, 0, YASL_EVENT_POINTER_UP);
+ touch_report(s, p, 0, YASL_PRIVATE_EVENT_POINTER_UP);
s->touch_pressed = false;
s->touch_primary = NULL;
}
@@ -701,7 +747,7 @@ static void touch_cancel(void *data, struct wl_touch *touch)
(void)touch;
struct seat *s = data;
if (s->touch_primary && s->touch_pressed)
- touch_report(s, s->touch_primary, 0, YASL_EVENT_POINTER_UP);
+ touch_report(s, s->touch_primary, 0, YASL_PRIVATE_EVENT_POINTER_UP);
memset(s->touch_points, 0, sizeof(s->touch_points));
s->touch_primary = NULL;
s->touch_pressed = false;
@@ -719,29 +765,100 @@ static const struct wl_touch_listener touch_listener = {
.frame = touch_frame, .cancel = touch_cancel,
};
-static struct yasl_pointer_event tool_event(const struct seat *s)
+static struct yasl_private_pointer_event tool_event(const struct seat *s)
{
- return (struct yasl_pointer_event){
- .device = s->tool && s->tool->eraser ? YASL_PTR_DEV_ERASER : YASL_PTR_DEV_PEN,
+ return (struct yasl_private_pointer_event){
+ .device = s->tool && s->tool->eraser ? YASL_PRIVATE_PTR_DEV_ERASER : YASL_PRIVATE_PTR_DEV_PEN,
.pen = s->pen,
};
}
+static void push_pen_sample(struct tablet_tool *tool, struct wayland_surface *w,
+ unsigned action, uint32_t changed)
+{
+ struct seat *s = tool->seat;
+ if (!w) return;
+ uint64_t buttons = s->tool_buttons;
+ for (int i = 0; i < s->tool_presses.n; i++) {
+ const struct pending_press *press = &s->tool_presses.ev[(s->tool_presses.head + i) & 7];
+ if (press->surface && press->button >= 0 && press->button < 32) {
+ uint64_t bit = 1ull << press->button;
+ buttons = (buttons & ~bit) | ((uint64_t)!press->release << press->button);
+ }
+ }
+ if (action == YASL_PRIVATE_PEN_LEAVE || action == YASL_PRIVATE_PEN_CANCEL)
+ buttons = 0;
+ struct yasl_private_event ev = {
+ .type = YASL_PRIVATE_EVENT_PEN,
+ .surface = &w->base,
+ .pen = {
+ .device_id = tool->device_id,
+ .tool_id = tool->tool_id,
+ .x = tool->x,
+ .y = tool->y,
+ .pressure = tool->pressure,
+ .tilt_x = tool->tilt_x,
+ .tilt_y = tool->tilt_y,
+ .rotation = tool->rotation,
+ .distance = tool->distance,
+ .tangential = tool->tangential,
+ .wheel_degrees = tool->wheel_degrees,
+ .axes_valid = tool->axes_valid,
+ .axes_changed = changed,
+ .buttons = (uint32_t)buttons,
+ .changed_button = tool->changed_button,
+ .in_contact = tool->in_contact,
+ .tool = tool->kind,
+ .action = action,
+ },
+ };
+ input_queue_push(&surface_root(w)->input, &ev);
+}
+
+static void pen_action_push(struct tablet_tool *tool, unsigned action, unsigned button)
+{
+ if (tool->pending_action_count == 8) {
+ memmove(tool->pending_actions, tool->pending_actions + 1,
+ 7 * sizeof(tool->pending_actions[0]));
+ memmove(tool->pending_buttons, tool->pending_buttons + 1,
+ 7 * sizeof(tool->pending_buttons[0]));
+ memmove(tool->pending_contacts, tool->pending_contacts + 1,
+ 7 * sizeof(tool->pending_contacts[0]));
+ tool->pending_action_count--;
+ }
+ unsigned i = tool->pending_action_count++;
+ tool->pending_actions[i] = action;
+ tool->pending_buttons[i] = button;
+ tool->pending_contacts[i] = tool->in_contact;
+}
+
static void tablet_tool_proximity_in(void *data,
struct zwp_tablet_tool_v2 *tool, uint32_t serial,
struct zwp_tablet_v2 *tablet, struct wl_surface *surface)
{
- (void)tool; (void)tablet;
+ (void)tool;
struct tablet_tool *t = data;
struct seat *s = t->seat;
struct wayland_surface *w = surface ?
(struct wayland_surface *)wl_surface_get_user_data(surface) : NULL;
s->tablet_focus = w;
s->tool = t;
+ t->device_id = 0;
+ for (struct tablet_device *device = s->tablet_devices; device; device = device->next)
+ if (device->proxy == tablet) { t->device_id = device->id; break; }
+ t->pen_in_proximity = true;
+ t->in_contact = false;
+ t->pending_action_count = 0;
+ pen_action_push(t, YASL_PRIVATE_PEN_ENTER, 0);
+ t->axes_changed = 0;
+ t->pressure = t->tilt_x = t->tilt_y = t->rotation = t->distance = 0;
+ t->tangential = t->wheel_degrees = 0;
s->tool_buttons = 0;
- s->pen = (struct yasl_pointer_pen){0};
+ s->pen = (struct yasl_private_pointer_pen){0};
t->proximity_serial = serial;
if (!w) return;
+ t->x = s->tool_pos.x;
+ t->y = s->tool_pos.y;
if (s->conn->cursor_shape_mgr && !t->shape_dev)
t->shape_dev = wp_cursor_shape_manager_v1_get_tablet_tool_v2(
s->conn->cursor_shape_mgr, t->proxy);
@@ -756,11 +873,14 @@ static void tablet_tool_proximity_out(void *data, struct zwp_tablet_tool_v2 *too
struct seat *s = t->seat;
struct wayland_surface *w = s->tablet_focus;
if (w) {
+ t->in_contact = false;
+ t->pressure = 0;
+ push_pen_sample(t, w, YASL_PRIVATE_PEN_LEAVE, 0);
press_queue_flush(s, &s->tool_presses, NULL, &s->tool_buttons, tool_event(s));
s->pen.pressure = 0;
- struct yasl_pointer_event ev = tool_event(s);
+ struct yasl_private_pointer_event ev = tool_event(s);
ev.pos = s->tool_pos;
- push_pointer(s, w, YASL_EVENT_POINTER_LEAVE, ev);
+ push_pointer(s, w, YASL_PRIVATE_EVENT_POINTER_LEAVE, ev);
}
s->tool_presses.n = 0;
s->tablet_focus = NULL;
@@ -769,28 +889,38 @@ static void tablet_tool_proximity_out(void *data, struct zwp_tablet_tool_v2 *too
s->tool_wheel = 0;
s->tool_buttons = 0;
t->proximity_serial = 0;
+ t->pen_in_proximity = false;
+ t->in_contact = false;
}
static void tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial)
{
(void)tool;
- struct seat *s = ((struct tablet_tool *)data)->seat;
+ struct tablet_tool *t = data;
+ struct seat *s = t->seat;
struct wayland_surface *w = s->tablet_focus;
if (!w) return;
seat_note_input(s, serial);
s->press_serial = serial;
s->press_surface = w;
press_queue_push(&s->tool_presses, w, s->tool_pos, 0, false);
+ t->in_contact = true;
+ pen_action_push(t, YASL_PRIVATE_PEN_DOWN, 0);
}
static void tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *tool)
{
(void)tool;
struct seat *s = ((struct tablet_tool *)data)->seat;
+ struct tablet_tool *t = data;
struct wayland_surface *w = s->tablet_focus;
if (!w) return;
s->pen.pressure = 0;
press_queue_push(&s->tool_presses, w, s->tool_pos, 0, true);
+ t->pressure = 0;
+ t->in_contact = false;
+ pen_action_push(t, YASL_PRIVATE_PEN_UP, 0);
+ t->axes_changed |= YASL_PRIVATE_PEN_PRESSURE;
}
static void tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool, wl_fixed_t x, wl_fixed_t y)
@@ -800,6 +930,9 @@ static void tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool, wl_f
struct wayland_surface *w = s->tablet_focus;
if (!w) return;
s->tool_pos = device_from_fixed(w, x, y);
+ struct tablet_tool *owned = data;
+ owned->x = wl_fixed_to_double(x) * w->scale_factor;
+ owned->y = wl_fixed_to_double(y) * w->scale_factor;
s->tool_motion = true;
}
@@ -807,7 +940,8 @@ static void tablet_tool_button(void *data, struct zwp_tablet_tool_v2 *tool,
uint32_t serial, uint32_t button, uint32_t state)
{
(void)tool;
- struct seat *s = ((struct tablet_tool *)data)->seat;
+ struct tablet_tool *t = data;
+ struct seat *s = t->seat;
struct wayland_surface *w = s->tablet_focus;
if (!w) return;
seat_note_input(s, serial);
@@ -820,13 +954,18 @@ static void tablet_tool_button(void *data, struct zwp_tablet_tool_v2 *tool,
}
bool release = state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED;
press_queue_push(&s->tool_presses, w, s->tool_pos, b, release);
+ pen_action_push(t, YASL_PRIVATE_PEN_BUTTON, (unsigned)b);
}
static void tool_pressure(void *d, struct zwp_tablet_tool_v2 *t, uint32_t v)
{
(void)t;
struct seat *s = ((struct tablet_tool *)d)->seat;
+ struct tablet_tool *owned = d;
s->pen.pressure = v > 65535 ? 65535 : (uint16_t)v;
+ owned->pressure = (double)(v > 65535 ? 65535 : v) / 65535.0;
+ owned->axes_valid |= YASL_PRIVATE_PEN_PRESSURE;
+ owned->axes_changed |= YASL_PRIVATE_PEN_PRESSURE;
s->tool_motion = true;
}
@@ -840,40 +979,68 @@ static void tool_tilt(void *d, struct zwp_tablet_tool_v2 *t, wl_fixed_t x, wl_fi
{
(void)t;
struct seat *s = ((struct tablet_tool *)d)->seat;
+ struct tablet_tool *owned = d;
s->pen.tilt_x = tilt_degrees(x);
s->pen.tilt_y = tilt_degrees(y);
+ owned->tilt_x = wl_fixed_to_double(x);
+ owned->tilt_y = wl_fixed_to_double(y);
+ owned->axes_valid |= YASL_PRIVATE_PEN_TILT;
+ owned->axes_changed |= YASL_PRIVATE_PEN_TILT;
s->tool_motion = true;
}
static void tool_wheel(void *d, struct zwp_tablet_tool_v2 *t, wl_fixed_t deg, int32_t clicks)
{
- (void)t; (void)deg;
- ((struct tablet_tool *)d)->seat->tool_wheel += clicks;
+ (void)t;
+ struct tablet_tool *owned = d;
+ owned->seat->tool_wheel += clicks;
+ owned->wheel_degrees += wl_fixed_to_double(deg);
+ owned->axes_valid |= YASL_PRIVATE_PEN_WHEEL;
+ owned->axes_changed |= YASL_PRIVATE_PEN_WHEEL;
}
static void tool_frame(void *d, struct zwp_tablet_tool_v2 *t, uint32_t time)
{
(void)t; (void)time;
struct seat *s = ((struct tablet_tool *)d)->seat;
+ struct tablet_tool *owned = d;
struct wayland_surface *w = s->tablet_focus;
if (!w) {
s->tool_presses.n = 0;
s->tool_wheel = 0;
return;
}
- struct yasl_pointer_event like = tool_event(s);
+ struct yasl_private_pointer_event like = tool_event(s);
+ if (owned->pending_action_count) {
+ unsigned actions = owned->pending_action_count;
+ bool contact = owned->in_contact;
+ for (unsigned i = 0; i < actions; i++) {
+ owned->changed_button = owned->pending_buttons[i];
+ owned->in_contact = owned->pending_contacts[i];
+ push_pen_sample(owned, w, owned->pending_actions[i],
+ i + 1 == actions ? owned->axes_changed : 0);
+ }
+ owned->in_contact = contact;
+ owned->pending_action_count = 0;
+ owned->axes_changed = 0;
+ owned->changed_button = 0;
+ } else if (s->tool_motion || owned->axes_changed) {
+ push_pen_sample(owned, w, YASL_PRIVATE_PEN_MOVE, owned->axes_changed);
+ owned->axes_changed = 0;
+ owned->changed_button = 0;
+ }
if (s->tool_motion) {
- struct yasl_pointer_event ev = like;
+ struct yasl_private_pointer_event ev = like;
ev.pos = s->tool_pos;
- push_pointer(s, w, YASL_EVENT_POINTER_MOTION, ev);
+ push_pointer(s, w, YASL_PRIVATE_EVENT_POINTER_MOTION, ev);
s->tool_motion = false;
}
press_queue_flush(s, &s->tool_presses, NULL, &s->tool_buttons, like);
if (s->tool_wheel) {
- struct yasl_pointer_event ev = like;
+ struct yasl_private_pointer_event ev = like;
ev.pos = s->tool_pos;
ev.scroll.y = s->tool_wheel;
- push_pointer(s, w, YASL_EVENT_POINTER_SCROLL, ev);
+ push_pointer(s, w, YASL_PRIVATE_EVENT_POINTER_SCROLL, ev);
s->tool_wheel = 0;
}
}
@@ -899,16 +1066,43 @@ static void tablet_tool_removed(void *data, struct zwp_tablet_tool_v2 *tool)
static void tool_type(void *d, struct zwp_tablet_tool_v2 *t, uint32_t type)
{
(void)t;
- ((struct tablet_tool *)d)->eraser = type == ZWP_TABLET_TOOL_V2_TYPE_ERASER;
+ struct tablet_tool *tool = d;
+ tool->eraser = type == ZWP_TABLET_TOOL_V2_TYPE_ERASER;
+ switch (type) {
+ case ZWP_TABLET_TOOL_V2_TYPE_PEN: tool->kind = 1; break;
+ case ZWP_TABLET_TOOL_V2_TYPE_ERASER: tool->kind = 2; break;
+ case ZWP_TABLET_TOOL_V2_TYPE_BRUSH: tool->kind = 3; break;
+ case ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH: tool->kind = 4; break;
+ case ZWP_TABLET_TOOL_V2_TYPE_PENCIL: tool->kind = 5; break;
+ default: tool->kind = 0; break;
+ }
}
-static void tool_hardware_serial(void *d, struct zwp_tablet_tool_v2 *t, uint32_t hi, uint32_t lo) { (void)d; (void)t; (void)hi; (void)lo; }
+static void tool_hardware_serial(void *d, struct zwp_tablet_tool_v2 *t, uint32_t hi, uint32_t lo)
+{ (void)t; struct tablet_tool *tool = d; uint64_t id = ((uint64_t)hi << 32) | lo; if (id) tool->tool_id = id; }
static void tool_hardware_id_wacom(void *d, struct zwp_tablet_tool_v2 *t, uint32_t hi, uint32_t lo) { (void)d; (void)t; (void)hi; (void)lo; }
-static void tool_capability(void *d, struct zwp_tablet_tool_v2 *t, uint32_t cap) { (void)d; (void)t; (void)cap; }
+static void tool_capability(void *d, struct zwp_tablet_tool_v2 *t, uint32_t cap)
+{
+ (void)t;
+ struct tablet_tool *tool = d;
+ tool->capability_mask |= 1u << cap;
+ switch (cap) {
+ case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE: tool->axes_valid |= YASL_PRIVATE_PEN_PRESSURE; break;
+ case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT: tool->axes_valid |= YASL_PRIVATE_PEN_TILT; break;
+ case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION: tool->axes_valid |= YASL_PRIVATE_PEN_ROTATION; break;
+ case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE: tool->axes_valid |= YASL_PRIVATE_PEN_DISTANCE; break;
+ case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER: tool->axes_valid |= YASL_PRIVATE_PEN_TANGENTIAL; break;
+ case ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL: tool->axes_valid |= YASL_PRIVATE_PEN_WHEEL; break;
+ default: break;
+ }
+}
static void tool_done(void *d, struct zwp_tablet_tool_v2 *t) { (void)d; (void)t; }
-static void tool_distance(void *d, struct zwp_tablet_tool_v2 *t, uint32_t v) { (void)d; (void)t; (void)v; }
-static void tool_rotation(void *d, struct zwp_tablet_tool_v2 *t, wl_fixed_t deg) { (void)d; (void)t; (void)deg; }
-static void tool_slider(void *d, struct zwp_tablet_tool_v2 *t, int32_t pos) { (void)d; (void)t; (void)pos; }
+static void tool_distance(void *d, struct zwp_tablet_tool_v2 *t, uint32_t v)
+{ (void)t; struct tablet_tool *tool = d; tool->distance = (double)(v > 65535 ? 65535 : v) / 65535.0; tool->axes_valid |= YASL_PRIVATE_PEN_DISTANCE; tool->axes_changed |= YASL_PRIVATE_PEN_DISTANCE; }
+static void tool_rotation(void *d, struct zwp_tablet_tool_v2 *t, wl_fixed_t deg)
+{ (void)t; struct tablet_tool *tool = d; tool->rotation = wl_fixed_to_double(deg); tool->axes_valid |= YASL_PRIVATE_PEN_ROTATION; tool->axes_changed |= YASL_PRIVATE_PEN_ROTATION; }
+static void tool_slider(void *d, struct zwp_tablet_tool_v2 *t, int32_t pos)
+{ (void)t; struct tablet_tool *tool = d; tool->tangential = pos / 65535.0; if (tool->tangential < -1) tool->tangential = -1; if (tool->tangential > 1) tool->tangential = 1; tool->axes_valid |= YASL_PRIVATE_PEN_TANGENTIAL; tool->axes_changed |= YASL_PRIVATE_PEN_TANGENTIAL; }
static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
.type = tool_type, .hardware_serial = tool_hardware_serial,
@@ -997,6 +1191,7 @@ static void tablet_seat_tablet_added(void *data, struct zwp_tablet_seat_v2 *tabl
struct tablet_device *owned = calloc(1, sizeof(*owned));
if (!owned) { zwp_tablet_v2_destroy(tablet); return; }
owned->proxy = tablet;
+ owned->id = ++s->conn->next_tool_id;
owned->next = s->tablet_devices;
s->tablet_devices = owned;
zwp_tablet_v2_add_listener(tablet, &tablet_listener, s);
@@ -1010,6 +1205,7 @@ static void tablet_seat_tool_added(void *data, struct zwp_tablet_seat_v2 *tablet
if (!owned) { zwp_tablet_tool_v2_destroy(tool); return; }
owned->proxy = tool;
owned->seat = s;
+ owned->tool_id = ++s->conn->next_tool_id;
owned->next = s->tablet_tools;
s->tablet_tools = owned;
zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, owned);
@@ -1035,7 +1231,7 @@ static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = {
static void clipboard_received(const char *text, size_t len, bool uri_list,
struct wl_surface *on, uint64_t request_id,
- enum yasl_transfer_status status, void *ud)
+ enum yasl_private_transfer_status status, void *ud)
{
(void)ud;
struct wayland_surface *w = on ?
@@ -1043,13 +1239,13 @@ static void clipboard_received(const char *text, size_t len, bool uri_list,
if (uri_list) w = surface_root(w);
if (!w || w->closed || w->destroyed) return;
if (!uri_list) {
- yasl_surface_complete_paste(&w->base, request_id, status, text, len);
+ yasl_private_surface_complete_paste(&w->base, request_id, status, text, len);
return;
}
- if (status != YASL_TRANSFER_OK) return;
- struct yasl_event ev = {
+ if (status != YASL_PRIVATE_TRANSFER_OK) return;
+ struct yasl_private_event ev = {
.surface = &w->base,
- .type = uri_list ? YASL_EVENT_DROP : YASL_EVENT_PASTE,
+ .type = uri_list ? YASL_PRIVATE_EVENT_DROP : YASL_PRIVATE_EVENT_PASTE,
.text = {
.data = text,
.len = len,
@@ -1058,14 +1254,14 @@ static void clipboard_received(const char *text, size_t len, bool uri_list,
input_queue_push(&w->input, &ev);
}
-static void clipboard_drag(enum yasl_drag_event ev, struct wl_surface *on,
+static void clipboard_drag(enum yasl_private_drag_event ev, struct wl_surface *on,
double x, double y, void *ud)
{
struct seat *s = ud;
conn_drag_target(s->conn, ev, on, x, y);
}
-static void clipboard_drop_hover(enum yasl_drop_event ev, struct wl_surface *on,
+static void clipboard_drop_hover(enum yasl_private_drop_event ev, struct wl_surface *on,
double x, double y, void *ud)
{
struct seat *s = ud;
@@ -1152,6 +1348,16 @@ static void seat_drop_touch(struct seat *s)
}
}
+void seat_ensure_text_input(struct seat *s)
+{
+ if (!s || !s->conn->text_input_mgr || s->text_input || !s->proxy)
+ return;
+ s->text_input = zwp_text_input_manager_v3_get_text_input(
+ s->conn->text_input_mgr, s->proxy);
+ if (s->text_input)
+ zwp_text_input_v3_add_listener(s->text_input, &text_input_listener, s);
+}
+
static void seat_capabilities(void *data, struct wl_seat *proxy, uint32_t caps)
{
struct seat *s = data;
@@ -1209,11 +1415,7 @@ static void seat_capabilities(void *data, struct wl_seat *proxy, uint32_t caps)
zwp_tablet_seat_v2_add_listener(s->tablet_seat, &tablet_seat_listener, s);
}
- if (c->text_input_mgr && !s->text_input) {
- s->text_input = zwp_text_input_manager_v3_get_text_input(c->text_input_mgr, proxy);
- if (s->text_input)
- zwp_text_input_v3_add_listener(s->text_input, &text_input_listener, s);
- }
+ seat_ensure_text_input(s);
seat_clipboard_ensure(s);
}
@@ -1297,8 +1499,8 @@ void seat_destroy(struct seat *s)
seat_drop_keyboard(s);
struct wayland_surface *left = s->focus_leaving;
if (left && !conn_keyboard_on(c, left, NULL)) {
- struct yasl_event ev = {
- .type = YASL_EVENT_FOCUS,
+ struct yasl_private_event ev = {
+ .type = YASL_PRIVATE_EVENT_FOCUS,
.surface = &left->base,
.focus = { .focused = false },
};
@@ -1306,7 +1508,7 @@ void seat_destroy(struct seat *s)
}
seat_drop_touch(s);
clipboard_destroy(s->clipboard);
- if (s->repeat_watch > 0) yasl_loop_del_fd(c->loop, s->repeat_watch);
+ if (s->repeat_watch > 0) yasl_private_loop_del_fd(c->loop, s->repeat_watch);
if (s->repeat_fd >= 0) close(s->repeat_fd);
if (s->cursor_viewport) wp_viewport_destroy(s->cursor_viewport);
if (s->cursor_surface) wl_surface_destroy(s->cursor_surface);
diff --git a/src/platform/wayland/popup.c b/src/platform/wayland/popup.c
index 44c7206..c563eb4 100644
--- a/src/platform/wayland/popup.c
+++ b/src/platform/wayland/popup.c
@@ -24,9 +24,19 @@ static const struct xdg_popup_listener popup_listener = {
};
static bool popup_spec_valid(const struct wayland_surface *parent,
- const struct yasl_popup_spec *spec)
+ const struct yasl_private_popup_spec *spec)
{
if (!parent || !spec) return false;
+ if (spec->positioner_explicit &&
+ (spec->anchor_edges > XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT ||
+ spec->gravity > XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT ||
+ (spec->constraints & ~(unsigned)(XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X |
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y))))
+ return false;
int64_t x = (int64_t)spec->anchor.x - parent->content.x;
int64_t y = (int64_t)spec->anchor.y - parent->content.y;
return x >= INT_MIN && x <= INT_MAX && y >= INT_MIN && y <= INT_MAX &&
@@ -37,29 +47,29 @@ static bool popup_spec_valid(const struct wayland_surface *parent,
(int64_t)spec->content_offset.y + spec->content_size.y <= spec->size.y;
}
-static bool popup_apply_spec(struct wayland_surface *w, const struct yasl_popup_spec *spec)
+static bool popup_apply_spec(struct wayland_surface *w, const struct yasl_private_popup_spec *spec)
{
uint32_t scale = w->parent->scale_120;
- struct yasl_vector2i logical = {
- .x = (int)(((int64_t)spec->size.x * YASL_SCALE_UNIT + scale - 1) / scale),
- .y = (int)(((int64_t)spec->size.y * YASL_SCALE_UNIT + scale - 1) / scale),
+ struct yasl_private_vector2i logical = {
+ .x = (int)(((int64_t)spec->size.x * YASL_PRIVATE_SCALE_UNIT + scale - 1) / scale),
+ .y = (int)(((int64_t)spec->size.y * YASL_PRIVATE_SCALE_UNIT + scale - 1) / scale),
};
int width = device_px(logical.x, scale);
int height = device_px(logical.y, scale);
size_t bytes;
if (logical.x <= 0 || logical.y <= 0 || !buffer_size(width, height, &bytes))
return false;
- struct yasl_vector2i content = spec->content_size;
+ struct yasl_private_vector2i content = spec->content_size;
if (!content.x) content.x = spec->size.x - spec->content_offset.x;
if (!content.y) content.y = spec->size.y - spec->content_offset.y;
bool rescaled = scale != w->scale_120;
w->scale_120 = w->pending_scale_120 = scale;
- w->scale_factor = (double)scale / YASL_SCALE_UNIT;
+ w->scale_factor = (double)scale / YASL_PRIVATE_SCALE_UNIT;
w->width = width;
w->height = height;
w->logical_width = logical.x;
w->logical_height = logical.y;
- w->content = (struct yasl_rect2i){
+ w->content = (struct yasl_private_rect2i){
.x = spec->content_offset.x, .y = spec->content_offset.y,
.width = content.x, .height = content.y
};
@@ -67,20 +77,20 @@ static bool popup_apply_spec(struct wayland_surface *w, const struct yasl_popup_
w->buffers[i].presented = false;
if (w->viewport)
wp_viewport_set_destination(w->viewport, logical.x, logical.y);
- else if ((rescaled || !w->configured) && scale % YASL_SCALE_UNIT == 0 &&
+ else if ((rescaled || !w->configured) && scale % YASL_PRIVATE_SCALE_UNIT == 0 &&
wl_proxy_get_version((struct wl_proxy *)w->surface) >=
WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
- wl_surface_set_buffer_scale(w->surface, (int32_t)(scale / YASL_SCALE_UNIT));
+ wl_surface_set_buffer_scale(w->surface, (int32_t)(scale / YASL_PRIVATE_SCALE_UNIT));
return true;
}
static void popup_set_geometry(struct wayland_surface *w)
{
uint32_t scale = w->scale_120;
- int gx = yasl_scale_to_logical(w->content.x, scale);
- int gy = yasl_scale_to_logical(w->content.y, scale);
- int gw = yasl_scale_to_logical(w->content.width, scale);
- int gh = yasl_scale_to_logical(w->content.height, scale);
+ int gx = yasl_private_scale_to_logical(w->content.x, scale);
+ int gy = yasl_private_scale_to_logical(w->content.y, scale);
+ int gw = yasl_private_scale_to_logical(w->content.width, scale);
+ int gh = yasl_private_scale_to_logical(w->content.height, scale);
if (gw < 1) gw = 1;
if (gh < 1) gh = 1;
if (gx + gw > w->logical_width)
@@ -91,41 +101,45 @@ static void popup_set_geometry(struct wayland_surface *w)
}
static struct xdg_positioner *popup_positioner(struct wayland_surface *w,
- const struct yasl_popup_spec *spec)
+ const struct yasl_private_popup_spec *spec)
{
struct wayland_surface *parent = w->parent;
struct xdg_positioner *pos = xdg_wm_base_create_positioner(w->conn->wm_base);
if (!pos)
return NULL;
uint32_t scale = parent->scale_120;
- int gw = yasl_scale_to_logical(w->content.width, scale);
- int gh = yasl_scale_to_logical(w->content.height, scale);
+ int gw = yasl_private_scale_to_logical(w->content.width, scale);
+ int gh = yasl_private_scale_to_logical(w->content.height, scale);
xdg_positioner_set_size(pos, gw > 0 ? gw : 1, gh > 0 ? gh : 1);
- struct yasl_vector2i at = {
+ struct yasl_private_vector2i at = {
.x = spec->anchor.x - parent->content.x,
.y = spec->anchor.y - parent->content.y,
};
- int aw = yasl_scale_to_logical(spec->anchor.width, scale);
- int ah = yasl_scale_to_logical(spec->anchor.height, scale);
+ int aw = yasl_private_scale_to_logical(spec->anchor.width, scale);
+ int ah = yasl_private_scale_to_logical(spec->anchor.height, scale);
xdg_positioner_set_anchor_rect(pos,
- yasl_scale_to_logical(at.x, scale),
- yasl_scale_to_logical(at.y, scale),
+ yasl_private_scale_to_logical(at.x, scale),
+ yasl_private_scale_to_logical(at.y, scale),
aw > 0 ? aw : 1, ah > 0 ? ah : 1);
- xdg_positioner_set_anchor(pos, spec->beside ? XDG_POSITIONER_ANCHOR_TOP_RIGHT
- : XDG_POSITIONER_ANCHOR_TOP_LEFT);
- xdg_positioner_set_gravity(pos, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
- xdg_positioner_set_constraint_adjustment(pos,
+ uint32_t anchor = spec->positioner_explicit ? spec->anchor_edges :
+ (spec->beside ? XDG_POSITIONER_ANCHOR_TOP_RIGHT : XDG_POSITIONER_ANCHOR_TOP_LEFT);
+ uint32_t gravity = spec->positioner_explicit ? spec->gravity :
+ XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT;
+ uint32_t constraints = spec->positioner_explicit ? spec->constraints :
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X |
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y |
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X |
- XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y);
+ XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y;
+ xdg_positioner_set_anchor(pos, anchor);
+ xdg_positioner_set_gravity(pos, gravity);
+ xdg_positioner_set_constraint_adjustment(pos, constraints);
if (xdg_positioner_get_version(pos) >= XDG_POSITIONER_SET_REACTIVE_SINCE_VERSION)
xdg_positioner_set_reactive(pos);
return pos;
}
struct wayland_surface *wayland_surface_create_popup(struct wayland_surface *parent,
- const struct yasl_popup_spec *spec)
+ const struct yasl_private_popup_spec *spec)
{
struct wayland_display *c = parent ? parent->conn : NULL;
struct seat *seat = c ? (c->active_seat ? c->active_seat : c->seats) : NULL;
@@ -137,7 +151,8 @@ struct wayland_surface *wayland_surface_create_popup(struct wayland_surface *par
if (!w)
return NULL;
w->base.display = &c->base;
- w->base.state = YASL_STATE_CSD;
+ w->base.state = YASL_PRIVATE_STATE_CSD;
+ w->base.presenter = YASL_PRIVATE_PRESENTER_CPU;
w->input.leave_ends_press = true;
w->conn = c;
w->conn_next = c->surfaces;
@@ -150,7 +165,7 @@ struct wayland_surface *wayland_surface_create_popup(struct wayland_surface *par
if (!w->surface)
goto err;
w->base.native_handle = w->surface;
- w->base.size = (struct yasl_vector2i){spec->size.x, spec->size.y};
+ w->base.size = (struct yasl_private_vector2i){spec->size.x, spec->size.y};
w->base.scale_120 = parent->scale_120;
wl_surface_set_user_data(w->surface, w);
if (surface_init_scaling(w) < 0)
@@ -180,13 +195,13 @@ err:
return NULL;
}
-bool wayland_surface_popup_reposition(struct wayland_surface *w, const struct yasl_popup_spec *spec)
+bool wayland_surface_popup_reposition(struct wayland_surface *w, const struct yasl_private_popup_spec *spec)
{
if (!w || !w->popup || w->closed || !w->conn || w->conn->lost ||
!popup_spec_valid(w->parent, spec) ||
xdg_popup_get_version(w->popup) < XDG_POPUP_REPOSITION_SINCE_VERSION)
return false;
- struct yasl_popup_spec old = {
+ struct yasl_private_popup_spec old = {
.size = { .x = w->width, .y = w->height },
.content_offset = { .x = w->content.x, .y = w->content.y },
.content_size = { .x = w->content.width, .y = w->content.height },
diff --git a/src/platform/wayland/shell.c b/src/platform/wayland/shell.c
index fc2ce2e..c2578e7 100644
--- a/src/platform/wayland/shell.c
+++ b/src/platform/wayland/shell.c
@@ -173,7 +173,7 @@ uint32_t conn_output_scale_120(const struct wayland_display *c, uint64_t outputs
for (const struct wl_conn_output *o = c->outputs; o; o = o->next)
if ((o->mask & outputs) && o->scale > scale)
scale = o->scale;
- return (uint32_t)scale * YASL_SCALE_UNIT;
+ return (uint32_t)scale * YASL_PRIVATE_SCALE_UNIT;
}
static void registry_global(void *data, struct wl_registry *registry,
@@ -227,6 +227,8 @@ static void registry_global(void *data, struct wl_registry *registry,
} else if (strcmp(interface, zwp_text_input_manager_v3_interface.name) == 0) {
c->text_input_mgr = wl_registry_bind(registry, name,
&zwp_text_input_manager_v3_interface, 1);
+ for (struct seat *seat = c->seats; seat; seat = seat->next)
+ seat_ensure_text_input(seat);
} else if (strcmp(interface, wp_tearing_control_manager_v1_interface.name) == 0) {
c->tearing_mgr = wl_registry_bind(registry, name,
&wp_tearing_control_manager_v1_interface, 1);
@@ -277,7 +279,7 @@ static void set_state(struct wayland_surface *w, uint32_t state)
{
if (state == w->base.state) return;
w->base.state = state;
- yasl_surface_notify_state(&w->base, state);
+ yasl_private_surface_notify_state(&w->base, state);
}
static void toplevel_configure(void *data, struct xdg_toplevel *toplevel,
@@ -286,21 +288,21 @@ static void toplevel_configure(void *data, struct xdg_toplevel *toplevel,
(void)toplevel;
struct wayland_surface *w = data;
- uint32_t state = w->base.state & ~(YASL_STATE_FULLSCREEN |
- YASL_STATE_MAXIMIZED | YASL_STATE_ACTIVATED |
- YASL_STATE_SUSPENDED | YASL_STATE_TILED);
+ uint32_t state = w->base.state & ~(YASL_PRIVATE_STATE_FULLSCREEN |
+ YASL_PRIVATE_STATE_MAXIMIZED | YASL_PRIVATE_STATE_ACTIVATED |
+ YASL_PRIVATE_STATE_SUSPENDED | YASL_PRIVATE_STATE_TILED);
uint32_t *s;
wl_array_for_each(s, states) {
switch (*s) {
- case XDG_TOPLEVEL_STATE_FULLSCREEN: state |= YASL_STATE_FULLSCREEN; break;
- case XDG_TOPLEVEL_STATE_MAXIMIZED: state |= YASL_STATE_MAXIMIZED; break;
- case XDG_TOPLEVEL_STATE_ACTIVATED: state |= YASL_STATE_ACTIVATED; break;
- case XDG_TOPLEVEL_STATE_SUSPENDED: state |= YASL_STATE_SUSPENDED; break;
+ case XDG_TOPLEVEL_STATE_FULLSCREEN: state |= YASL_PRIVATE_STATE_FULLSCREEN; break;
+ case XDG_TOPLEVEL_STATE_MAXIMIZED: state |= YASL_PRIVATE_STATE_MAXIMIZED; break;
+ case XDG_TOPLEVEL_STATE_ACTIVATED: state |= YASL_PRIVATE_STATE_ACTIVATED; break;
+ case XDG_TOPLEVEL_STATE_SUSPENDED: state |= YASL_PRIVATE_STATE_SUSPENDED; break;
case XDG_TOPLEVEL_STATE_TILED_LEFT:
case XDG_TOPLEVEL_STATE_TILED_RIGHT:
case XDG_TOPLEVEL_STATE_TILED_TOP:
case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
- state |= YASL_STATE_TILED;
+ state |= YASL_PRIVATE_STATE_TILED;
break;
default: break;
}
@@ -316,7 +318,7 @@ static void toplevel_close(void *data, struct xdg_toplevel *toplevel)
(void)toplevel;
struct wayland_surface *w = data;
if (w && !w->closed)
- yasl_surface_notify_close(&w->base);
+ yasl_private_surface_notify_close(&w->base);
}
static void toplevel_configure_bounds(void *data, struct xdg_toplevel *toplevel,
@@ -349,11 +351,21 @@ static const struct xdg_toplevel_listener toplevel_listener = {
static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial)
{
struct wayland_surface *w = data;
- (void)xdg_surface;
w->pending_serial = serial;
w->has_pending_serial = true;
w->size_pending = true;
w->configured = true;
+ /* CPU surfaces acknowledge with their SHM commit. External presenters
+ * commit through EGL/Vulkan, so apply the configure and acknowledge it
+ * before renderer code can submit that first native buffer. */
+ if (w->base.presenter != YASL_PRIVATE_PRESENTER_CPU) {
+ xdg_surface_ack_configure(xdg_surface, serial);
+ w->has_pending_serial = false;
+ if (apply_pending_geometry(w) < 0) {
+ surface_fail(w);
+ return;
+ }
+ }
wayland_surface_schedule_redraw(w);
}
@@ -368,9 +380,9 @@ static void toplevel_decoration_configure(void *data,
struct wayland_surface *w = data;
uint32_t state = w->base.state;
if (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE)
- state &= ~YASL_STATE_CSD;
+ state &= ~YASL_PRIVATE_STATE_CSD;
else
- state |= YASL_STATE_CSD;
+ state |= YASL_PRIVATE_STATE_CSD;
set_state(w, state);
}
@@ -387,11 +399,11 @@ int surface_init_shell(struct wayland_surface *w, const char *title)
if (!w->toplevel) return -1;
xdg_toplevel_add_listener(w->toplevel, &toplevel_listener, w);
- wayland_surface_set_title(w, title ? title : "yasl_app");
+ wayland_surface_set_title(w, title ? title : "yasl_private_app");
- const char *app_id = w->conn->app_id ? w->conn->app_id : "yasl_app";
+ const char *app_id = w->conn->app_id ? w->conn->app_id : "yasl_private_app";
xdg_toplevel_set_app_id(w->toplevel, app_id);
- xdg_toplevel_set_min_size(w->toplevel, YASL_MIN_LOGICAL_PX, YASL_MIN_LOGICAL_PX);
+ xdg_toplevel_set_min_size(w->toplevel, YASL_PRIVATE_MIN_LOGICAL_PX, YASL_PRIVATE_MIN_LOGICAL_PX);
if (w->conn->decor_mgr) {
w->toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
@@ -400,7 +412,9 @@ int surface_init_shell(struct wayland_surface *w, const char *title)
zxdg_toplevel_decoration_v1_add_listener(w->toplevel_decor,
&toplevel_decoration_listener, w);
zxdg_toplevel_decoration_v1_set_mode(w->toplevel_decor,
- ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
+ (w->base.creation_flags & YASL_PRIVATE_SURFACE_UNDECORATED)
+ ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE
+ : ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
return 0;
}
diff --git a/src/platform/wayland/surface.c b/src/platform/wayland/surface.c
index 2e85e2b..31096f4 100644
--- a/src/platform/wayland/surface.c
+++ b/src/platform/wayland/surface.c
@@ -52,7 +52,7 @@ static void display_lose(struct wayland_display *c)
surface_fail(w);
}
display_leave(c);
- yasl_display_notify_event(&c->base, YASL_EVENT_DISPLAY_LOST);
+ yasl_private_display_notify_event(&c->base, YASL_PRIVATE_EVENT_DISPLAY_LOST);
}
void surface_fail(struct wayland_surface *w)
@@ -60,7 +60,7 @@ void surface_fail(struct wayland_surface *w)
if (w->closed)
return;
w->closed = true;
- yasl_surface_notify_close(&w->base);
+ yasl_private_surface_notify_close(&w->base);
}
static int display_ready(int fd, short revents, void *ud)
@@ -80,7 +80,7 @@ static int display_ready(int fd, short revents, void *ud)
if (revents & POLLOUT) {
if (wl_display_flush(c->wl) >= 0) {
if (c->loop && c->watch > 0)
- yasl_loop_set_fd_events(c->loop, c->watch, POLLIN);
+ yasl_private_loop_set_fd_events(c->loop, c->watch, POLLIN);
} else if (errno != EAGAIN) {
display_lose(c);
}
@@ -113,7 +113,7 @@ static bool display_arm(struct wayland_display *c)
events |= POLLOUT;
}
if (c->loop && c->watch > 0)
- yasl_loop_set_fd_events(c->loop, c->watch, events);
+ yasl_private_loop_set_fd_events(c->loop, c->watch, events);
return had_pending;
}
@@ -154,7 +154,7 @@ int wayland_display_dispatch_timeout(struct wayland_display *c, int timeout_ms)
int n = 0;
if (c->loop) {
- n = yasl_loop_step(c->loop, timeout_ms);
+ n = yasl_private_loop_step(c->loop, timeout_ms);
}
if (c->reading) {
@@ -190,7 +190,7 @@ void wayland_display_flush(struct wayland_display *c)
static void display_free(struct wayland_display *c)
{
conn_drag_end(c);
- if (c->loop && c->watch > 0) yasl_loop_del_fd(c->loop, c->watch);
+ if (c->loop && c->watch > 0) yasl_private_loop_del_fd(c->loop, c->watch);
if (c->wl) display_cancel_read(c);
while (c->seats)
seat_destroy(c->seats);
@@ -217,9 +217,12 @@ static void display_free(struct wayland_display *c)
if (c->shm) wl_shm_destroy(c->shm);
if (c->compositor) wl_compositor_destroy(c->compositor);
if (c->registry) wl_registry_destroy(c->registry);
+#if YASL_HAS_EGL
+ if (c->egl_initialized) eglTerminate(c->egl_display);
+#endif
if (c->wl) wl_display_disconnect(c->wl);
if (c->owns_loop && c->loop) {
- yasl_loop_destroy(c->loop);
+ yasl_private_loop_destroy(c->loop);
c->loop = NULL;
c->base.loop = NULL;
}
@@ -227,13 +230,13 @@ static void display_free(struct wayland_display *c)
free(c);
}
-struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struct yasl_display_spec *spec)
+struct wayland_display *wayland_display_open(struct yasl_private_loop *loop, const struct yasl_private_display_spec *spec)
{
struct wayland_display *c = calloc(1, sizeof(*c));
if (!c) return NULL;
- c->base.ops = &yasl_wayland_backend;
+ c->base.ops = &yasl_private_wayland_backend;
if (!loop) {
- c->loop = yasl_loop_create();
+ c->loop = yasl_private_loop_create();
c->owns_loop = true;
} else {
c->loop = loop;
@@ -241,7 +244,7 @@ struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struc
c->base.loop = c->loop;
if (!c->loop) goto err;
if (spec) {
- c->base.callbacks = spec->cbs ? *spec->cbs : (struct yasl_display_cbs){0};
+ c->base.callbacks = spec->cbs ? *spec->cbs : (struct yasl_private_display_cbs){0};
c->cbs = &c->base.callbacks;
c->ud = spec->ud;
if (spec->app_id) c->app_id = strdup(spec->app_id);
@@ -251,6 +254,13 @@ struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struc
c->wl = c->xkb_ctx ? wl_display_connect(NULL) : NULL;
if (!c->wl) goto err;
c->base.native_handle = c->wl;
+#if YASL_HAS_EGL
+ c->egl_display = eglGetDisplay((EGLNativeDisplayType)c->wl);
+ if (c->egl_display != EGL_NO_DISPLAY) {
+ EGLint major = 0, minor = 0;
+ c->egl_initialized = eglInitialize(c->egl_display, &major, &minor) == EGL_TRUE;
+ }
+#endif
c->registry = wl_display_get_registry(c->wl);
if (!c->registry) goto err;
@@ -260,7 +270,7 @@ struct wayland_display *wayland_display_open(struct yasl_loop *loop, const struc
surface_init_cursor(c);
if (c->loop) {
- c->watch = yasl_loop_add_fd(c->loop, wl_display_get_fd(c->wl), POLLIN, display_ready, c);
+ c->watch = yasl_private_loop_add_fd(c->loop, wl_display_get_fd(c->wl), POLLIN, display_ready, c);
if (c->watch <= 0) { c->watch = 0; goto err; }
}
if (display_input_init(c) < 0)
@@ -282,16 +292,18 @@ void wayland_display_close(struct wayland_display *c)
uint32_t wayland_display_caps(const struct wayland_display *c)
{
if (!c) return 0;
- uint32_t caps = YASL_CAP_POPUPS | YASL_CAP_CSD | YASL_CAP_FRAME_PACING;
- if (c->tablet_mgr) caps |= YASL_CAP_TABLET;
+ uint32_t caps = YASL_PRIVATE_CAP_POPUPS | YASL_PRIVATE_CAP_CSD |
+ YASL_PRIVATE_CAP_FRAME_PACING | YASL_PRIVATE_CAP_NATIVE_GRAPHICS;
+ if (c->tablet_mgr) caps |= YASL_PRIVATE_CAP_TABLET;
+ if (c->text_input_mgr) caps |= YASL_PRIVATE_CAP_TEXT_INPUT;
struct seat *s = c->active_seat ? c->active_seat : c->seats;
const struct wl_data_device *device = s ? clipboard_data_device(s->clipboard) : NULL;
if (device && wl_data_device_get_version((struct wl_data_device *)device) >= 3)
- caps |= YASL_CAP_DRAG;
+ caps |= YASL_PRIVATE_CAP_DRAG;
if (c->toplevel_drag_mgr)
- caps |= YASL_CAP_DRAG_CARRY;
+ caps |= YASL_PRIVATE_CAP_DRAG_CARRY;
if (c->primary_selection_mgr)
- caps |= YASL_CAP_PRIMARY_SELECTION;
+ caps |= YASL_PRIVATE_CAP_PRIMARY_SELECTION;
return caps;
}
@@ -321,15 +333,18 @@ static void conn_unlink(struct wayland_surface *w)
}
-static bool spec_valid(const struct yasl_window_spec *spec)
+static bool spec_valid(const struct yasl_private_window_spec *spec)
{
size_t bytes;
- return spec && spec->size.x > 0 && spec->size.y > 0 &&
- buffer_size(spec->size.x, spec->size.y, &bytes);
+ if (!spec || spec->size.x <= 0 || spec->size.y <= 0)
+ return false;
+ return spec->external_gpu && !(spec->flags & YASL_PRIVATE_SURFACE_CPU)
+ ? spec->size.x <= INT32_MAX && spec->size.y <= INT32_MAX
+ : buffer_size(spec->size.x, spec->size.y, &bytes);
}
struct wayland_surface *wayland_surface_create_toplevel(struct wayland_display *c,
- const struct yasl_window_spec *spec, void *graphics_device)
+ const struct yasl_private_window_spec *spec, void *graphics_device)
{
(void)graphics_device;
if (!c || c->lost || !spec_valid(spec))
@@ -340,28 +355,35 @@ struct wayland_surface *wayland_surface_create_toplevel(struct wayland_display *
if (!w) return NULL;
c->depth++;
conn_link(c, w);
- w->base.state = YASL_STATE_CSD;
+ w->base.state = YASL_PRIVATE_STATE_CSD;
+ w->base.creation_flags = spec->flags;
+ w->base.presenter = (spec->external_gpu && !(spec->flags & YASL_PRIVATE_SURFACE_CPU))
+ ? YASL_PRIVATE_PRESENTER_NONE : YASL_PRIVATE_PRESENTER_CPU;
wayland_surface_set_callbacks(w, NULL, NULL);
- w->cursor = YASL_CURSOR_TEXT;
+ w->cursor = YASL_PRIVATE_CURSOR_TEXT;
w->req_width = width;
w->req_height = height;
w->logical_width = width;
w->logical_height = height;
- w->scale_120 = YASL_SCALE_UNIT;
- w->pending_scale_120 = YASL_SCALE_UNIT;
+ w->scale_120 = YASL_PRIVATE_SCALE_UNIT;
+ w->pending_scale_120 = YASL_PRIVATE_SCALE_UNIT;
w->scale_factor = 1.0;
w->size_pending = true;
w->clock.refresh_ns = c->outputs && c->outputs->refresh_ns
- ? c->outputs->refresh_ns : YASL_REFRESH_DEFAULT_NS;
+ ? c->outputs->refresh_ns : YASL_PRIVATE_REFRESH_DEFAULT_NS;
w->surface = wl_compositor_create_surface(c->compositor);
if (!w->surface) goto err;
w->base.native_handle = w->surface;
- w->base.size = (struct yasl_vector2i){width, height};
- w->base.scale_120 = YASL_SCALE_UNIT;
+ w->base.size = (struct yasl_private_vector2i){width, height};
+ w->base.scale_120 = YASL_PRIVATE_SCALE_UNIT;
wl_surface_set_user_data(w->surface, w);
if (surface_init_scaling(w) < 0) goto err;
if (surface_init_shell(w, spec->title) < 0) goto err;
+ if (spec->flags & YASL_PRIVATE_SURFACE_FIXED_SIZE) {
+ xdg_toplevel_set_min_size(w->toplevel, width, height);
+ xdg_toplevel_set_max_size(w->toplevel, width, height);
+ }
w->opaque = spec->fullscreen;
if (spec->fullscreen)
xdg_toplevel_set_fullscreen(w->toplevel, NULL);
@@ -389,10 +411,10 @@ err:
return NULL;
}
-void wayland_surface_set_callbacks(struct wayland_surface *w, const struct yasl_window_cbs *cbs, void *ud)
+void wayland_surface_set_callbacks(struct wayland_surface *w, const struct yasl_private_window_cbs *cbs, void *ud)
{
if (w && !w->closed) {
- w->base.callbacks = cbs ? *cbs : (struct yasl_window_cbs){0};
+ w->base.callbacks = cbs ? *cbs : (struct yasl_private_window_cbs){0};
w->base.ud = ud;
w->cbs = &w->base.callbacks;
w->ud = ud;
@@ -410,6 +432,15 @@ void wayland_surface_destroy(struct wayland_surface *w)
free(w->ime_commit);
free(w->ime_shown);
if (w->tearing_control) wp_tearing_control_v1_destroy(w->tearing_control);
+#if YASL_HAS_EGL
+ if (w->egl_context) {
+ if (eglGetCurrentContext() == w->egl_context)
+ eglMakeCurrent(w->conn->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroyContext(w->conn->egl_display, w->egl_context);
+ }
+ if (w->egl_surface) eglDestroySurface(w->conn->egl_display, w->egl_surface);
+ if (w->egl_window) wl_egl_window_destroy(w->egl_window);
+#endif
if (w->fifo) wp_fifo_v1_destroy(w->fifo);
if (w->commit_timer) wp_commit_timer_v1_destroy(w->commit_timer);
surface_feedback_destroy(w);
@@ -427,7 +458,7 @@ void wayland_surface_destroy(struct wayland_surface *w)
}
struct wayland_display *c = w->conn;
conn_unlink(w);
- static const struct yasl_window_cbs no_callbacks = {0};
+ static const struct yasl_private_window_cbs no_callbacks = {0};
*w = (struct wayland_surface){
.base = w->base,
.conn_next = w->conn_next,
@@ -446,16 +477,20 @@ void wayland_surface_destroy(struct wayland_surface *w)
void wayland_surface_schedule_redraw(struct wayland_surface *w)
{
if (!w || w->closed) return;
+ if (w->base.presenter != YASL_PRIVATE_PRESENTER_CPU) {
+ yasl_private_surface_notify_refresh(&w->base);
+ return;
+ }
w->want_draw = true;
if (w->conn && w->conn->loop)
- yasl_loop_kick(w->conn->loop);
+ yasl_private_loop_kick(w->conn->loop);
}
-struct yasl_geometry wayland_surface_geometry(const struct wayland_surface *w)
+struct yasl_private_geometry wayland_surface_geometry(const struct wayland_surface *w)
{
- return (struct yasl_geometry){
- .size = w ? (struct yasl_vector2i){w->width, w->height} : (struct yasl_vector2i){0},
- .scale_120 = w ? w->scale_120 : YASL_SCALE_UNIT,
+ return (struct yasl_private_geometry){
+ .size = w ? (struct yasl_private_vector2i){w->width, w->height} : (struct yasl_private_vector2i){0},
+ .scale_120 = w ? w->scale_120 : YASL_PRIVATE_SCALE_UNIT,
};
}
@@ -473,23 +508,23 @@ bool wayland_surface_start_interactive_move(struct wayland_surface *s)
return true;
}
-bool wayland_surface_start_interactive_resize(struct wayland_surface *s, enum yasl_resize_edge edge)
+bool wayland_surface_start_interactive_resize(struct wayland_surface *s, enum yasl_private_resize_edge edge)
{
- if (!s || !s->toplevel || !s->conn || edge == YASL_EDGE_NONE) return false;
+ if (!s || !s->toplevel || !s->conn || edge == YASL_PRIVATE_EDGE_NONE) return false;
struct seat *seat = s->conn->active_seat ? s->conn->active_seat : s->conn->seats;
if (!seat || !seat->proxy || !seat->press_serial) return false;
xdg_toplevel_resize(s->toplevel, seat->proxy, seat->press_serial, (uint32_t)edge);
return true;
}
-bool wayland_surface_show_window_menu(struct wayland_surface *s, struct yasl_vector2i pos)
+bool wayland_surface_show_window_menu(struct wayland_surface *s, struct yasl_private_vector2i pos)
{
if (!s || !s->toplevel || !s->conn) return false;
struct seat *seat = s->conn->active_seat ? s->conn->active_seat : s->conn->seats;
if (!seat || !seat->proxy || !seat->press_serial) return false;
- uint32_t scale = s->scale_120 ? s->scale_120 : YASL_SCALE_UNIT;
+ uint32_t scale = s->scale_120 ? s->scale_120 : YASL_PRIVATE_SCALE_UNIT;
xdg_toplevel_show_window_menu(s->toplevel, seat->proxy, seat->press_serial,
- yasl_scale_to_logical(pos.x, scale),
- yasl_scale_to_logical(pos.y, scale));
+ yasl_private_scale_to_logical(pos.x, scale),
+ yasl_private_scale_to_logical(pos.y, scale));
return true;
}