summaryrefslogtreecommitdiff
path: root/src/x11/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/x11/window.c')
-rw-r--r--src/x11/window.c51
1 files changed, 42 insertions, 9 deletions
diff --git a/src/x11/window.c b/src/x11/window.c
index b80bfe0..4680d3f 100644
--- a/src/x11/window.c
+++ b/src/x11/window.c
@@ -19,6 +19,13 @@
#define INPUT_CAP 256
#define TEXT_LIMIT (16 * 1024 * 1024)
+#ifndef likely
+#define likely(x) __builtin_expect(!!(x), 1)
+#endif
+#ifndef unlikely
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+
struct x11_surface {
struct yasl_surface base;
struct x11_surface *next;
@@ -58,6 +65,7 @@ struct x11_display {
struct x11_surface *paste_target;
uint32_t mods;
char *app_id;
+ bool owns_loop;
};
static struct x11_display *display_of(const struct yasl_surface *s)
@@ -438,10 +446,10 @@ static void dispatch(struct yasl_display *base)
static unsigned long component(uint32_t color, unsigned long mask)
{
- if (!mask) return 0;
- unsigned shift = 0;
- while (!(mask & 1)) { mask >>= 1; shift++; }
- return (((unsigned long)color * mask + 127) / 255) << shift;
+ if (unlikely(!mask)) return 0;
+ unsigned shift = (unsigned)__builtin_ctzl(mask);
+ unsigned long m = mask >> shift;
+ return (((unsigned long)color * m + 127) / 255) << shift;
}
static bool present(struct yasl_surface *base, const struct yasl_framebuffer *fb,
@@ -511,6 +519,18 @@ static int ready(int fd, short events, void *ud)
return 0;
}
+static int dispatch_timeout(struct yasl_display *base, int timeout_ms)
+{
+ struct x11_display *d = (struct x11_display *)base;
+ if (unlikely(!d || !d->native)) return -1;
+ dispatch(base);
+ if (!XPending(d->native) && d->loop && timeout_ms != 0) {
+ yasl_loop_step(d->loop, timeout_ms);
+ dispatch(base);
+ }
+ return 0;
+}
+
static struct yasl_display *display_open(struct yasl_loop *loop,
const struct yasl_display_spec *spec)
{
@@ -520,7 +540,12 @@ static struct yasl_display *display_open(struct yasl_loop *loop,
d->native = XOpenDisplay(NULL);
if (!d->native) { free(d); errno = ENODEV; return NULL; }
d->screen = DefaultScreen(d->native);
- d->loop = loop;
+ if (!loop) {
+ d->loop = yasl_loop_create();
+ d->owns_loop = true;
+ } else {
+ d->loop = loop;
+ }
d->app_id = strdup(spec && spec->app_id ? spec->app_id : "YASL");
if (!d->app_id) { XCloseDisplay(d->native); free(d); return NULL; }
d->im = XOpenIM(d->native, NULL, NULL, NULL);
@@ -539,13 +564,14 @@ static struct yasl_display *display_open(struct yasl_loop *loop,
ATOM(maximized_h, "_NET_WM_STATE_MAXIMIZED_HORZ");
ATOM(maximized_v, "_NET_WM_STATE_MAXIMIZED_VERT");
#undef ATOM
- if (loop) {
- d->watch = yasl_loop_add_fd(loop, ConnectionNumber(d->native), POLLIN, ready, &d->base);
+ if (d->loop) {
+ d->watch = yasl_loop_add_fd(d->loop, ConnectionNumber(d->native), POLLIN, ready, &d->base);
if (d->watch < 0) {
if (d->im) XCloseIM(d->im);
XDestroyWindow(d->native, d->selection_window);
XCloseDisplay(d->native);
free(d->app_id);
+ if (d->owns_loop) yasl_loop_destroy(d->loop);
free(d);
return NULL;
}
@@ -557,7 +583,8 @@ static void display_close(struct yasl_display *base)
{
struct x11_display *d = (struct x11_display *)base;
assert(!d->surfaces && "destroy every surface before its display");
- if (d->loop) yasl_loop_del_fd(d->loop, d->watch);
+ if (d->loop && d->watch > 0) yasl_loop_del_fd(d->loop, d->watch);
+ if (d->owns_loop && d->loop) yasl_loop_destroy(d->loop);
if (d->im) XCloseIM(d->im);
XDestroyWindow(d->native, d->selection_window);
XCloseDisplay(d->native);
@@ -619,7 +646,12 @@ static bool input_poll(struct yasl_surface *base, struct yasl_input_event *event
static void schedule_redraw(struct yasl_surface *base)
{
struct x11_surface *s = (struct x11_surface *)base;
- if (!s->destroyed) s->want_draw = true;
+ if (!s->destroyed) {
+ s->want_draw = true;
+ struct x11_display *d = display_of(base);
+ if (d && d->loop)
+ yasl_loop_kick(d->loop);
+ }
}
static struct yasl_display *surface_display(const struct yasl_surface *s) { return s->display; }
@@ -698,6 +730,7 @@ const struct yasl_backend_ops yasl_x11_backend = {
.display_close = display_close,
.display_caps = caps,
.display_dispatch = dispatch,
+ .display_dispatch_timeout = dispatch_timeout,
.display_flush = flush,
.display_modifiers = mods,
.display_copy = copy,