summaryrefslogtreecommitdiff
path: root/src/x11/window.c
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-12 22:49:52 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-12 22:49:52 +0300
commit47bd4dbe2e4a576a1f02507e9a87502d99df4f52 (patch)
tree86964635b0f6f083dd799d8e367c4d1be2babdfd /src/x11/window.c
parentac84186b2c91c4ce6334fde71af3b41d0d83f729 (diff)
feat(x11): implement interactive resize, window menu, IME caret/preedit, and advertise YASL_CAP_CSD
Diffstat (limited to 'src/x11/window.c')
-rw-r--r--src/x11/window.c82
1 files changed, 81 insertions, 1 deletions
diff --git a/src/x11/window.c b/src/x11/window.c
index f7d036f..c00a449 100644
--- a/src/x11/window.c
+++ b/src/x11/window.c
@@ -62,6 +62,10 @@ struct x11_surface {
struct x11_surface *parent;
bool is_popup;
struct yasl_vector2i content_offset;
+ char *ime_preedit;
+ int ime_cursor_begin;
+ int ime_cursor_end;
+ struct yasl_rect2i ime_caret;
};
struct paste_request {
@@ -593,6 +597,8 @@ static void surface_destroy(struct yasl_surface *base)
if (*p == s) { *p = s->next; break; }
}
cancel_pastes(d, s);
+ free(s->ime_preedit);
+ s->ime_preedit = NULL;
if (s->ic) XDestroyIC(s->ic);
if (s->shm_active) {
XShmDetach(d->native, &s->shm_info);
@@ -1682,7 +1688,7 @@ static void display_close(struct yasl_display *base)
static uint32_t caps(const struct yasl_display *d)
{
return YASL_CAP_POPUPS | YASL_CAP_DRAG | YASL_CAP_DRAG_CARRY | YASL_CAP_PLACE_WINDOW |
- YASL_CAP_PRIMARY_SELECTION |
+ YASL_CAP_PRIMARY_SELECTION | YASL_CAP_CSD |
(((const struct x11_display *)d)->xi2 ? YASL_CAP_TABLET : 0);
}
@@ -1948,6 +1954,75 @@ static bool interactive_move(struct yasl_surface *base)
return true;
}
+static bool interactive_resize(struct yasl_surface *base, enum yasl_resize_edge edge)
+{
+ struct x11_surface *s = (struct x11_surface *)base;
+ struct x11_display *d = display_of(base);
+ Window root, child;
+ int rx, ry, x, y;
+ unsigned mask;
+ if (s->destroyed || !d->native || !XQueryPointer(d->native, s->window,
+ &root, &child, &rx, &ry, &x, &y, &mask)) return false;
+
+ int dir;
+ switch (edge) {
+ case YASL_EDGE_TOP_LEFT: dir = 0; break;
+ case YASL_EDGE_TOP: dir = 1; break;
+ case YASL_EDGE_TOP_RIGHT: dir = 2; break;
+ case YASL_EDGE_RIGHT: dir = 3; break;
+ case YASL_EDGE_BOTTOM_RIGHT: dir = 4; break;
+ case YASL_EDGE_BOTTOM: dir = 5; break;
+ case YASL_EDGE_BOTTOM_LEFT: dir = 6; break;
+ case YASL_EDGE_LEFT: dir = 7; break;
+ default: return false;
+ }
+
+ XUngrabPointer(d->native, CurrentTime);
+ net_message(s, XInternAtom(d->native, "_NET_WM_MOVERESIZE", False), rx, ry, dir, 1, 1);
+ return true;
+}
+
+static bool show_window_menu(struct yasl_surface *base, struct yasl_vector2i pos)
+{
+ struct x11_surface *s = (struct x11_surface *)base;
+ struct x11_display *d = display_of(base);
+ if (s->destroyed || !d->native) return false;
+ Atom atom = XInternAtom(d->native, "_GTK_SHOW_WINDOW_MENU", False);
+ net_message(s, atom, s->window, pos.x, pos.y, 0, 0);
+ return true;
+}
+
+static void set_ime_caret(struct yasl_surface *base, struct yasl_rect2i caret)
+{
+ struct x11_surface *s = (struct x11_surface *)base;
+ if (!s) return;
+ s->ime_caret = caret;
+ if (s->ic) {
+ XPoint spot = { (short)caret.x, (short)(caret.y + caret.height) };
+ XVaNestedList preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
+ if (preedit_attr) {
+ XSetICValues(s->ic, XNPreeditAttributes, preedit_attr, NULL);
+ XFree(preedit_attr);
+ }
+ }
+}
+
+static const char *ime_preedit(const struct yasl_surface *base)
+{
+ const struct x11_surface *s = (const struct x11_surface *)base;
+ return s ? s->ime_preedit : NULL;
+}
+
+static bool ime_preedit_cursor(const struct yasl_surface *base, int *begin, int *end)
+{
+ const struct x11_surface *s = (const struct x11_surface *)base;
+ if (!s || !s->ime_preedit || s->ime_cursor_begin < 0)
+ return false;
+ if (begin) *begin = s->ime_cursor_begin;
+ if (end) *end = s->ime_cursor_end;
+ return true;
+}
+
const struct yasl_backend_ops yasl_x11_backend = {
.type = YASL_BACKEND_X11,
.display_open = display_open,
@@ -1978,6 +2053,11 @@ const struct yasl_backend_ops yasl_x11_backend = {
.surface_drag_carry = drag_carry,
.surface_place_under_pointer = place,
.surface_start_interactive_move = interactive_move,
+ .surface_start_interactive_resize = interactive_resize,
+ .surface_show_window_menu = show_window_menu,
+ .surface_set_ime_caret = set_ime_caret,
+ .surface_ime_preedit = ime_preedit,
+ .surface_ime_preedit_cursor = ime_preedit_cursor,
.display_get_native_handle = native_display,
.surface_get_native_handle = native_surface,
};