commit 994e235d9939788238dd2c66cdefb4cc4ade1bce
parent 3a21eba1783e1d29204d54e006fe9f5efb016fc3
Author: lumidify <nobody@lumidify.org>
Date: Sun, 5 Jun 2022 23:45:33 +0200
Abstract event handling a bit
Diffstat:
27 files changed, 594 insertions(+), 385 deletions(-)
diff --git a/Makefile b/Makefile
@@ -39,7 +39,7 @@ OBJ = \
src/strtonum.o \
src/util.o \
src/memory.o \
- src/color.o \
+ src/color_xlib.o \
src/rect.o \
src/widget.o \
src/ltkd.o \
@@ -53,6 +53,7 @@ OBJ = \
src/theme.o \
src/graphics_xlib.o \
src/surface_cache.o \
+ src/event_xlib.o \
$(EXTRA_OBJ)
# src/draw.o \
@@ -79,7 +80,9 @@ HDR = \
src/theme.h \
src/graphics.h \
src/surface_cache.h \
- src/macros.h
+ src/macros.h \
+ src/event.h \
+ src/xlib_shared.h
# src/draw.h \
all: src/ltkd src/ltkc
diff --git a/src/box.c b/src/box.c
@@ -20,9 +20,7 @@
#include <stdint.h>
#include <string.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
+#include "event.h"
#include "memory.h"
#include "color.h"
#include "rect.h"
@@ -42,10 +40,10 @@ static int ltk_box_add(ltk_window *window, ltk_widget *widget, ltk_box *box, uns
static int ltk_box_remove(ltk_window *window, ltk_widget *widget, ltk_widget *self, char **errstr);
/* static int ltk_box_clear(ltk_window *window, ltk_box *box, int shallow, char **errstr); */
static void ltk_box_scroll(ltk_widget *self);
-static int ltk_box_mouse_event(ltk_box *box, XEvent event, void (*handler)(ltk_widget *, XEvent));
-static int ltk_box_mouse_press(ltk_widget *self, XEvent event);
-static int ltk_box_mouse_release(ltk_widget *self, XEvent event);
-static int ltk_box_motion_notify(ltk_widget *self, XEvent event);
+static int ltk_box_mouse_event(ltk_box *box, int x, int y, ltk_event *event, void (*handler)(ltk_widget *, ltk_event *));
+static int ltk_box_mouse_press(ltk_widget *self, ltk_event *event);
+static int ltk_box_mouse_release(ltk_widget *self, ltk_event *event);
+static int ltk_box_motion_notify(ltk_widget *self, ltk_event *event);
static struct ltk_widget_vtable vtable = {
.change_state = NULL,
@@ -324,10 +322,10 @@ ltk_box_scroll(ltk_widget *self) {
}
static int
-ltk_box_mouse_event(ltk_box *box, XEvent event, void (*handler)(ltk_widget *, XEvent)) {
+ltk_box_mouse_event(ltk_box *box, int x, int y, ltk_event *event, void (*handler)(ltk_widget *, ltk_event *)) {
ltk_widget *widget;
- if (ltk_collide_rect(box->sc->widget.rect, event.xbutton.x, event.xbutton.y)) {
+ if (ltk_collide_rect(box->sc->widget.rect, x, y)) {
handler((ltk_widget *)box->sc, event);
return 0;
}
@@ -335,7 +333,7 @@ ltk_box_mouse_event(ltk_box *box, XEvent event, void (*handler)(ltk_widget *, XE
/* FIXME: check only the currently visible items */
for (size_t i = 0; i < box->num_widgets; i++) {
widget = box->widgets[i];
- if (ltk_collide_rect(widget->rect, event.xbutton.x, event.xbutton.y)) {
+ if (ltk_collide_rect(widget->rect, x, y)) {
handler(widget, event);
return 0;
}
@@ -344,41 +342,41 @@ ltk_box_mouse_event(ltk_box *box, XEvent event, void (*handler)(ltk_widget *, XE
}
static int
-ltk_box_mouse_press(ltk_widget *self, XEvent event) {
+ltk_box_mouse_press(ltk_widget *self, ltk_event *event) {
ltk_box *box = (ltk_box *)self;
/* FIXME: combine multiple events into one for efficiency */
/* FIXME: fix this whole state handling */
- if (event.xbutton.button == 4 || event.xbutton.button == 5) {
+ if (event->button.button == LTK_BUTTON4 || event->button.button == LTK_BUTTON5) {
ltk_widget *widget;
int default_handler = 1;
for (size_t i = 0; i < box->num_widgets; i++) {
widget = box->widgets[i];
- if (ltk_collide_rect(widget->rect, event.xbutton.x, event.xbutton.y)) {
+ if (ltk_collide_rect(widget->rect, event->button.x, event->button.y)) {
if (widget->vtable->mouse_press)
default_handler = widget->vtable->mouse_press(widget, event);
}
}
/* FIXME: configure scrollstep */
if (default_handler) {
- int delta = event.xbutton.button == 4 ? -15 : 15;
+ int delta = event->button.button == LTK_BUTTON4 ? -15 : 15;
ltk_scrollbar_scroll((ltk_widget *)box->sc, delta, 0);
}
return 0;
} else {
- return ltk_box_mouse_event(box, event, <k_widget_mouse_press_event);
+ return ltk_box_mouse_event(box, event->button.x, event->button.y, event, <k_widget_mouse_press_event);
}
}
static int
-ltk_box_mouse_release(ltk_widget *self, XEvent event) {
+ltk_box_mouse_release(ltk_widget *self, ltk_event *event) {
ltk_box *box = (ltk_box *)self;
- return ltk_box_mouse_event(box, event, <k_widget_mouse_release_event);
+ return ltk_box_mouse_event(box, event->button.x, event->button.y, event, <k_widget_mouse_release_event);
}
static int
-ltk_box_motion_notify(ltk_widget *self, XEvent event) {
+ltk_box_motion_notify(ltk_widget *self, ltk_event *event) {
ltk_box *box = (ltk_box *)self;
- return ltk_box_mouse_event(box, event, <k_widget_motion_notify_event);
+ return ltk_box_mouse_event(box, event->motion.x, event->motion.y, event, <k_widget_motion_notify_event);
}
/* box <box id> add <widget id> [sticky] */
diff --git a/src/button.c b/src/button.c
@@ -20,9 +20,7 @@
#include <string.h>
#include <stdarg.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
+#include "event.h"
#include "memory.h"
#include "color.h"
#include "rect.h"
@@ -39,7 +37,7 @@
#define MAX_BUTTON_PADDING 500
static void ltk_button_draw(ltk_widget *self, ltk_rect clip);
-static int ltk_button_mouse_release(ltk_widget *self, XEvent event);
+static int ltk_button_mouse_release(ltk_widget *self, ltk_event *event);
static ltk_button *ltk_button_create(ltk_window *window,
const char *id, char *text);
static void ltk_button_destroy(ltk_widget *self, int shallow);
@@ -171,9 +169,9 @@ ltk_button_change_state(ltk_widget *self) {
/* FIXME: only when pressed button was actually this one */
static int
-ltk_button_mouse_release(ltk_widget *self, XEvent event) {
+ltk_button_mouse_release(ltk_widget *self, ltk_event *event) {
ltk_button *button = (ltk_button *)self;
- if (event.xbutton.button == 1) {
+ if (event->button.button == LTK_BUTTONL) {
ltk_queue_event(button->widget.window, LTK_EVENT_BUTTON, button->widget.id, "button_click");
return 1;
}
diff --git a/src/color.c b/src/color.c
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2021 lumidify <nobody@lumidify.org>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdarg.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#include "util.h"
-#include "color.h"
-#include "compat.h"
-
-/* FIXME: avoid initializing part of the struct and then error returning */
-/* FIXME: better error codes */
-/* FIXME: I think xcolor is unneeded when xft is enabled */
-int
-ltk_color_create(Display *dpy, Visual *vis, Colormap cm, const char *hex, ltk_color *col) {
- if (!XParseColor(dpy, cm, hex, &col->xcolor))
- return 1;
- if (!XAllocColor(dpy, cm, &col->xcolor))
- return 1;
- /* FIXME: replace with XftColorAllocValue */
- #if USE_XFT == 1
- if (!XftColorAllocName(dpy, vis, cm, hex, &col->xftcolor))
- return 1;
- #else
- (void)vis;
- #endif
- return 0;
-}
-
-void
-ltk_color_destroy(Display *dpy, Visual *vis, Colormap cm, ltk_color *col) {
- /* FIXME: what should the 'planes' argument be? */
- XFreeColors(dpy, cm, &col->xcolor.pixel, 1, 0);
- #if USE_XFT == 1
- XftColorFree(dpy, vis, cm, &col->xftcolor);
- #else
- (void)vis;
- #endif
-}
diff --git a/src/color.h b/src/color.h
@@ -23,6 +23,9 @@
#include <X11/Xft/Xft.h>
#endif
+/* FIXME: proper compilation option */
+#include <X11/Xlib.h>
+
typedef struct {
XColor xcolor;
#if USE_XFT == 1
@@ -30,8 +33,9 @@ typedef struct {
#endif
} ltk_color;
+#include "graphics.h"
/* returns 1 on failure, 0 on success */
-int ltk_color_create(Display *dpy, Visual *vis, Colormap cm, const char *hex, ltk_color *col);
-void ltk_color_destroy(Display *dpy, Visual *vis, Colormap cm, ltk_color *col);
+int ltk_color_create(ltk_renderdata *renderdata, const char *hex, ltk_color *col);
+void ltk_color_destroy(ltk_renderdata *renderdata, ltk_color *col);
#endif /* _LTK_COLOR_H_ */
diff --git a/src/color_xlib.c b/src/color_xlib.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, 2022 lumidify <nobody@lumidify.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdarg.h>
+#include "util.h"
+#include "color.h"
+#include "compat.h"
+#include "xlib_shared.h"
+
+/* FIXME: avoid initializing part of the struct and then error returning */
+/* FIXME: better error codes */
+/* FIXME: I think xcolor is unneeded when xft is enabled */
+int
+ltk_color_create(ltk_renderdata *renderdata, const char *hex, ltk_color *col) {
+ if (!XParseColor(renderdata->dpy, renderdata->cm, hex, &col->xcolor))
+ return 1;
+ if (!XAllocColor(renderdata->dpy, renderdata->cm, &col->xcolor))
+ return 1;
+ /* FIXME: replace with XftColorAllocValue */
+ #if USE_XFT == 1
+ if (!XftColorAllocName(renderdata->dpy, renderdata->vis, renderdata->cm, hex, &col->xftcolor))
+ return 1;
+ #endif
+ return 0;
+}
+
+void
+ltk_color_destroy(ltk_renderdata *renderdata, ltk_color *col) {
+ /* FIXME: what should the 'planes' argument be? */
+ XFreeColors(renderdata->dpy, renderdata->cm, &col->xcolor.pixel, 1, 0);
+ #if USE_XFT == 1
+ XftColorFree(renderdata->dpy, renderdata->vis, renderdata->cm, &col->xftcolor);
+ #endif
+}
diff --git a/src/event.h b/src/event.h
@@ -0,0 +1,96 @@
+#ifndef LTK_EVENT_H
+#define LTK_EVENT_H
+
+typedef enum {
+ LTK_UNKNOWN_EVENT, /* FIXME: a bit weird */
+ LTK_BUTTONPRESS_EVENT,
+ LTK_BUTTONRELEASE_EVENT,
+ LTK_MOTION_EVENT,
+ LTK_KEYPRESS_EVENT,
+ LTK_KEYRELEASE_EVENT,
+ LTK_CONFIGURE_EVENT,
+ LTK_EXPOSE_EVENT,
+ LTK_WINDOWCLOSE_EVENT
+} ltk_event_type;
+
+/* FIXME: button mask also in motion */
+
+typedef enum {
+ LTK_BUTTONL,
+ LTK_BUTTONM,
+ LTK_BUTTONR,
+ /* FIXME: dedicated scroll event */
+ LTK_BUTTON4,
+ LTK_BUTTON5,
+ LTK_BUTTON6,
+ LTK_BUTTON7
+} ltk_button_type;
+
+typedef struct {
+ ltk_event_type type;
+ ltk_button_type button;
+ int x, y;
+} ltk_button_event;
+
+typedef struct {
+ ltk_event_type type;
+ int x, y;
+} ltk_motion_event;
+
+/* FIXME: just steal the definitions from X when using Xlib so no conversion is necessary? */
+typedef enum {
+ LTK_KEY_NONE = 0,
+ LTK_KEY_LEFT,
+ LTK_KEY_RIGHT,
+ LTK_KEY_UP,
+ LTK_KEY_DOWN,
+ LTK_KEY_BACKSPACE,
+ LTK_KEY_DELETE,
+ LTK_KEY_SPACE,
+ LTK_KEY_RETURN
+} ltk_keysym;
+
+typedef enum {
+ LTK_MOD_CTRL,
+ LTK_MOD_SHIFT,
+ LTK_MOD_ALT,
+ LTK_MOD_SUPER
+} ltk_mod_type;
+
+typedef struct {
+ ltk_event_type type;
+ int x, y;
+ ltk_mod_type modmask;
+ ltk_keysym sym;
+ char *text;
+ char *mapped;
+} ltk_key_event;
+
+typedef struct {
+ ltk_event_type type;
+ int x, y;
+ int w, h;
+} ltk_configure_event;
+
+/* FIXME: should maybe be handled in backend with double buffering */
+typedef struct {
+ ltk_event_type type;
+ int x, y;
+ int w, h;
+} ltk_expose_event;
+
+typedef union {
+ ltk_event_type type;
+ ltk_button_event button;
+ ltk_motion_event motion;
+ ltk_key_event key;
+ ltk_configure_event configure;
+ ltk_expose_event expose;
+} ltk_event;
+
+#include "ltk.h"
+
+int ltk_events_pending(ltk_renderdata *renderdata);
+void ltk_next_event(ltk_renderdata *renderdata, ltk_event *event);
+
+#endif /* LTK_EVENT_H */
diff --git a/src/event_xlib.c b/src/event_xlib.c
@@ -0,0 +1,80 @@
+#include "graphics.h"
+#include "xlib_shared.h"
+
+int
+ltk_events_pending(ltk_renderdata *renderdata) {
+ return XPending(renderdata->dpy);
+}
+
+static ltk_button_type
+get_button(unsigned int button) {
+ switch (button) {
+ case Button1: return LTK_BUTTONL;
+ case Button2: return LTK_BUTTONM;
+ case Button3: return LTK_BUTTONR;
+ case 4: return LTK_BUTTON4;
+ case 5: return LTK_BUTTON5;
+ case 6: return LTK_BUTTON6;
+ case 7: return LTK_BUTTON7;
+ default: return LTK_BUTTONL; /* FIXME: what to do here? */
+ }
+}
+
+void
+ltk_next_event(ltk_renderdata *renderdata, ltk_event *event) {
+ XEvent xevent;
+ XNextEvent(renderdata->dpy, &xevent);
+ *event = (ltk_event){.type = LTK_UNKNOWN_EVENT};
+ switch (xevent.type) {
+ case ButtonPress:
+ *event = (ltk_event){.button = {
+ .type = LTK_BUTTONPRESS_EVENT,
+ .button = get_button(xevent.xbutton.button),
+ .x = xevent.xbutton.x,
+ .y = xevent.xbutton.y
+ }};
+ break;
+ case ButtonRelease:
+ *event = (ltk_event){.button = {
+ .type = LTK_BUTTONRELEASE_EVENT,
+ .button = get_button(xevent.xbutton.button),
+ .x = xevent.xbutton.x,
+ .y = xevent.xbutton.y
+ }};
+ break;
+ case MotionNotify:
+ *event = (ltk_event){.motion = {
+ .type = LTK_MOTION_EVENT,
+ .x = xevent.xmotion.x,
+ .y = xevent.xmotion.y
+ }};
+ break;
+ case ConfigureNotify:
+ *event = (ltk_event){.configure = {
+ .type = LTK_CONFIGURE_EVENT,
+ .x = xevent.xconfigure.x,
+ .y = xevent.xconfigure.y,
+ .w = xevent.xconfigure.width,
+ .h = xevent.xconfigure.height
+ }};
+ break;
+ case Expose:
+ /* FIXME: ignoring all of these events would make it not
+ work anymore if the actual rectangle wasn't ignored
+ later anyways */
+ if (xevent.xexpose.count == 0) {
+ *event = (ltk_event){.expose = {
+ .type = LTK_EXPOSE_EVENT,
+ .x = xevent.xexpose.x,
+ .y = xevent.xexpose.y,
+ .w = xevent.xexpose.width,
+ .h = xevent.xexpose.height
+ }};
+ }
+ break;
+ case ClientMessage:
+ if ((Atom)xevent.xclient.data.l[0] == renderdata->wm_delete_msg)
+ *event = (ltk_event){.type = LTK_WINDOWCLOSE_EVENT};
+ break;
+ }
+}
diff --git a/src/graphics.h b/src/graphics.h
@@ -14,12 +14,14 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef _LTK_GRAPHICS_H_
-#define _LTK_GRAPHICS_H_
+#ifndef LTK_GRAPHICS_H
+#define LTK_GRAPHICS_H
/* FIXME: make this global and use it elsewhere */
#define USE_XLIB_GRAPHICS 1
+typedef struct ltk_renderdata ltk_renderdata;
+
/* FIXME: Is it faster to take ltk_color* or ltk_color? */
#include <X11/Xft/Xft.h>
@@ -45,13 +47,13 @@ typedef struct {
/* typedef struct ltk_surface ltk_surface; */
/* FIXME: graphics context */
-ltk_surface *ltk_surface_create(ltk_window *window, int w, int h);
+ltk_surface *ltk_surface_create(ltk_renderdata *renderdata, int w, int h);
void ltk_surface_destroy(ltk_surface *s);
/* returns 0 if successful, 1 if not resizable */
int ltk_surface_resize(ltk_surface *s, int w, int h);
/* FIXME: kind of hacky */
void ltk_surface_update_size(ltk_surface *s, int w, int h);
-ltk_surface *ltk_surface_from_window(ltk_window *window);
+ltk_surface *ltk_surface_from_window(ltk_renderdata *renderdata, int w, int h);
void ltk_surface_get_size(ltk_surface *s, int *w, int *h);
void ltk_surface_copy(ltk_surface *src, ltk_surface *dst, ltk_rect src_rect, int dst_x, int dst_y);
void ltk_surface_draw_rect(ltk_surface *s, ltk_color *c, ltk_rect rect, int line_width);
@@ -76,4 +78,12 @@ XftDraw *ltk_surface_get_xft_draw(ltk_surface *s);
Drawable ltk_surface_get_drawable(ltk_surface *s);
#endif
-#endif /* _LTK_GRAPHICS_H_ */
+ltk_renderdata *renderer_create_window(const char *title, int x, int y, unsigned int w, unsigned int h);
+void renderer_destroy_window(ltk_renderdata *renderdata);
+void renderer_set_window_properties(ltk_renderdata *renderdata, ltk_color *bg, ltk_color *border, unsigned int border_width);
+/* FIXME: this is kind of out of place */
+void renderer_swap_buffers(ltk_renderdata *renderdata);
+/* FIXME: this is just for the socket name and is a bit weird */
+unsigned long renderer_get_window_id(ltk_renderdata *renderdata);
+
+#endif /* LTK_GRAPHICS_H */
diff --git a/src/graphics_xlib.c b/src/graphics_xlib.c
@@ -16,18 +16,19 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <X11/extensions/Xdbe.h>
#include <stdint.h>
#include "color.h"
#include "rect.h"
-#include "widget.h"
-#include "ltk.h"
+#include "util.h"
#include "memory.h"
#include "compat.h"
+#include "xlib_shared.h"
struct ltk_surface {
int w, h;
- ltk_window *window;
+ ltk_renderdata *renderdata;
Drawable d;
#if USE_XFT == 1
XftDraw *xftdraw;
@@ -36,7 +37,7 @@ struct ltk_surface {
};
ltk_surface *
-ltk_surface_create(ltk_window *window, int w, int h) {
+ltk_surface_create(ltk_renderdata *renderdata, int w, int h) {
ltk_surface *s = ltk_malloc(sizeof(ltk_surface));
if (w <= 0)
w = 1;
@@ -44,24 +45,24 @@ ltk_surface_create(ltk_window *window, int w, int h) {
h = 1;
s->w = w;
s->h = h;
- s->window = window;
- s->d = XCreatePixmap(window->dpy, window->xwindow, w, h, window->depth);
+ s->renderdata = renderdata;
+ s->d = XCreatePixmap(renderdata->dpy, renderdata->xwindow, w, h, renderdata->depth);
#if USE_XFT == 1
- s->xftdraw = XftDrawCreate(window->dpy, s->d, window->vis, window->cm);
+ s->xftdraw = XftDrawCreate(renderdata->dpy, s->d, renderdata->vis, renderdata->cm);
#endif
s->resizable = 1;
return s;
}
ltk_surface *
-ltk_surface_from_window(ltk_window *window) {
+ltk_surface_from_window(ltk_renderdata *renderdata, int w, int h) {
ltk_surface *s = ltk_malloc(sizeof(ltk_surface));
- s->w = window->rect.w;
- s->h = window->rect.h;
- s->window = window;
- s->d = window->drawable;
+ s->w = w;
+ s->h = h;
+ s->renderdata = renderdata;
+ s->d = renderdata->drawable;
#if USE_XFT == 1
- s->xftdraw = XftDrawCreate(window->dpy, s->d, window->vis, window->cm);
+ s->xftdraw = XftDrawCreate(renderdata->dpy, s->d, renderdata->vis, renderdata->cm);
#endif
s->resizable = 0;
return s;
@@ -73,12 +74,13 @@ ltk_surface_destroy(ltk_surface *s) {
XftDrawDestroy(s->xftdraw);
#endif
if (s->resizable)
- XFreePixmap(s->window->dpy, (Pixmap)s->d);
+ XFreePixmap(s->renderdata->dpy, (Pixmap)s->d);
ltk_free(s);
}
void
ltk_surface_update_size(ltk_surface *s, int w, int h) {
+ /* FIXME: maybe return directly if surface is resizable? */
s->w = w;
s->h = h;
}
@@ -89,8 +91,8 @@ ltk_surface_resize(ltk_surface *s, int w, int h) {
return 1;
s->w = w;
s->h = h;
- XFreePixmap(s->window->dpy, (Pixmap)s->d);
- s->d = XCreatePixmap(s->window->dpy, s->window->xwindow, w, h, s->window->depth);
+ XFreePixmap(s->renderdata->dpy, (Pixmap)s->d);
+ s->d = XCreatePixmap(s->renderdata->dpy, s->renderdata->xwindow, w, h, s->renderdata->depth);
#if USE_XFT == 1
XftDrawChange(s->xftdraw, s->d);
#endif
@@ -105,30 +107,30 @@ ltk_surface_get_size(ltk_surface *s, int *w, int *h) {
void
ltk_surface_draw_rect(ltk_surface *s, ltk_color *c, ltk_rect rect, int line_width) {
- XSetForeground(s->window->dpy, s->window->gc, c->xcolor.pixel);
- XSetLineAttributes(s->window->dpy, s->window->gc, line_width, LineSolid, CapButt, JoinMiter);
- XDrawRectangle(s->window->dpy, s->d, s->window->gc, rect.x, rect.y, rect.w, rect.h);
+ XSetForeground(s->renderdata->dpy, s->renderdata->gc, c->xcolor.pixel);
+ XSetLineAttributes(s->renderdata->dpy, s->renderdata->gc, line_width, LineSolid, CapButt, JoinMiter);
+ XDrawRectangle(s->renderdata->dpy, s->d, s->renderdata->gc, rect.x, rect.y, rect.w, rect.h);
}
void
ltk_surface_draw_border(ltk_surface *s, ltk_color *c, ltk_rect rect, int line_width, ltk_border_sides border_sides) {
/* drawn as rectangles to have proper control over line width - I'm not sure how exactly
XDrawLine handles even line widths (i.e. on which side the extra pixel will be) */
- XSetForeground(s->window->dpy, s->window->gc, c->xcolor.pixel);
+ XSetForeground(s->renderdata->dpy, s->renderdata->gc, c->xcolor.pixel);
if (border_sides & LTK_BORDER_TOP)
- XFillRectangle(s->window->dpy, s->d, s->window->gc, rect.x, rect.y, rect.w, line_width);
+ XFillRectangle(s->renderdata->dpy, s->d, s->renderdata->gc, rect.x, rect.y, rect.w, line_width);
if (border_sides & LTK_BORDER_BOTTOM)
- XFillRectangle(s->window->dpy, s->d, s->window->gc, rect.x, rect.y + rect.h - line_width, rect.w, line_width);
+ XFillRectangle(s->renderdata->dpy, s->d, s->renderdata->gc, rect.x, rect.y + rect.h - line_width, rect.w, line_width);
if (border_sides & LTK_BORDER_LEFT)
- XFillRectangle(s->window->dpy, s->d, s->window->gc, rect.x, rect.y, line_width, rect.h);
+ XFillRectangle(s->renderdata->dpy, s->d, s->renderdata->gc, rect.x, rect.y, line_width, rect.h);
if (border_sides & LTK_BORDER_RIGHT)
- XFillRectangle(s->window->dpy, s->d, s->window->gc, rect.x + rect.w - line_width, rect.y, line_width, rect.h);
+ XFillRectangle(s->renderdata->dpy, s->d, s->renderdata->gc, rect.x + rect.w - line_width, rect.y, line_width, rect.h);
}
void
ltk_surface_fill_rect(ltk_surface *s, ltk_color *c, ltk_rect rect) {
- XSetForeground(s->window->dpy, s->window->gc, c->xcolor.pixel);
- XFillRectangle(s->window->dpy, s->d, s->window->gc, rect.x, rect.y, rect.w, rect.h);
+ XSetForeground(s->renderdata->dpy, s->renderdata->gc, c->xcolor.pixel);
+ XFillRectangle(s->renderdata->dpy, s->d, s->renderdata->gc, rect.x, rect.y, rect.w, rect.h);
}
void
@@ -147,8 +149,8 @@ ltk_surface_fill_polygon(ltk_surface *s, ltk_color *c, ltk_point *points, size_t
final_points[i].x = (short)points[i].x;
final_points[i].y = (short)points[i].y;
}
- XSetForeground(s->window->dpy, s->window->gc, c->xcolor.pixel);
- XFillPolygon(s->window->dpy, s->d, s->window->gc, final_points, (int)npoints, Complex, CoordModeOrigin);
+ XSetForeground(s->renderdata->dpy, s->renderdata->gc, c->xcolor.pixel);
+ XFillPolygon(s->renderdata->dpy, s->d, s->renderdata->gc, final_points, (int)npoints, Complex, CoordModeOrigin);
if (npoints > 6)
free(final_points);
}
@@ -156,7 +158,7 @@ ltk_surface_fill_polygon(ltk_surface *s, ltk_color *c, ltk_point *points, size_t
void
ltk_surface_copy(ltk_surface *src, ltk_surface *dst, ltk_rect src_rect, int dst_x, int dst_y) {
XCopyArea(
- src->window->dpy, src->d, dst->d, src->window->gc,
+ src->renderdata->dpy, src->d, dst->d, src->renderdata->gc,
src_rect.x, src_rect.y, src_rect.w, src_rect.h, dst_x, dst_y
);
}
@@ -187,9 +189,124 @@ ltk_surface_get_xft_draw(ltk_surface *s) {
}
#endif
-#if USE_XLIB_GRAPHICS == 1
Drawable
ltk_surface_get_drawable(ltk_surface *s) {
return s->d;
}
-#endif
+
+ltk_renderdata *
+renderer_create_window(const char *title, int x, int y, unsigned int w, unsigned int h) {
+ XSetWindowAttributes attrs;
+ ltk_renderdata *renderdata = ltk_malloc(sizeof(ltk_renderdata));
+
+ renderdata->dpy = XOpenDisplay(NULL);
+ renderdata->screen = DefaultScreen(renderdata->dpy);
+ /* based on http://wili.cc/blog/xdbe.html */
+ int major, minor, found = 0;
+ if (XdbeQueryExtension(renderdata->dpy, &major, &minor)) {
+ int num_screens = 1;
+ Drawable screens[] = {DefaultRootWindow(renderdata->dpy)};
+ XdbeScreenVisualInfo *info = XdbeGetVisualInfo(
+ renderdata->dpy, screens, &num_screens
+ );
+ if (!info || num_screens < 1 || info->count < 1) {
+ ltk_fatal("No visuals support Xdbe.");
+ }
+ XVisualInfo xvisinfo_templ;
+ /* we know there's at least one */
+ xvisinfo_templ.visualid = info->visinfo[0].visual;
+ /* FIXME: proper screen number? */
+ xvisinfo_templ.screen = 0;
+ xvisinfo_templ.depth = info->visinfo[0].depth;
+ int matches;
+ XVisualInfo *xvisinfo_match = XGetVisualInfo(
+ renderdata->dpy,
+ VisualIDMask | VisualScreenMask | VisualDepthMask,
+ &xvisinfo_templ, &matches
+ );
+ if (!xvisinfo_match || matches < 1) {
+ ltk_fatal("Couldn't match a Visual with double buffering.\n");
+ }
+ renderdata->vis = xvisinfo_match->visual;
+ /* FIXME: is it legal to free this while keeping the visual? */
+ XFree(xvisinfo_match);
+ XdbeFreeVisualInfo(info);
+ found = 1;
+ } else {
+ renderdata->vis = DefaultVisual(renderdata->dpy, renderdata->screen);
+ ltk_warn("No Xdbe support.\n");
+ }
+ renderdata->cm = DefaultColormap(renderdata->dpy, renderdata->screen);
+ renderdata->wm_delete_msg = XInternAtom(renderdata->dpy, "WM_DELETE_WINDOW", False);
+
+ memset(&attrs, 0, sizeof(attrs));
+ attrs.background_pixel = BlackPixel(renderdata->dpy, renderdata->screen);
+ attrs.colormap = renderdata->cm;
+ attrs.border_pixel = WhitePixel(renderdata->dpy, renderdata->screen);
+ /* this causes the window contents to be kept
+ * when it is resized, leading to less flicker */
+ attrs.bit_gravity = NorthWestGravity;
+ attrs.event_mask =
+ ExposureMask | KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask |
+ StructureNotifyMask | PointerMotionMask;
+ renderdata->depth = DefaultDepth(renderdata->dpy, renderdata->screen);
+ /* FIXME: set border width */
+ renderdata->xwindow = XCreateWindow(
+ renderdata->dpy, DefaultRootWindow(renderdata->dpy), x, y,
+ w, h, 0, renderdata->depth,
+ InputOutput, renderdata->vis,
+ CWBackPixel | CWColormap | CWBitGravity | CWEventMask | CWBorderPixel, &attrs
+ );
+
+ if (found) {
+ renderdata->back_buf = XdbeAllocateBackBufferName(
+ renderdata->dpy, renderdata->xwindow, XdbeBackground
+ );
+ } else {
+ renderdata->back_buf = renderdata->xwindow;
+ }
+ renderdata->drawable = renderdata->back_buf;
+ renderdata->gc = XCreateGC(renderdata->dpy, renderdata->xwindow, 0, 0);
+ XSetStandardProperties(
+ renderdata->dpy, renderdata->xwindow,
+ title, NULL, None, NULL, 0, NULL
+ );
+ XSetWMProtocols(renderdata->dpy, renderdata->xwindow, &renderdata->wm_delete_msg, 1);
+ XClearWindow(renderdata->dpy, renderdata->xwindow);
+ XMapRaised(renderdata->dpy, renderdata->xwindow);
+
+ return renderdata;
+}
+
+void
+renderer_destroy_window(ltk_renderdata *renderdata) {
+ XFreeGC(renderdata->dpy, renderdata->gc);
+ XDestroyWindow(renderdata->dpy, renderdata->xwindow);
+ XCloseDisplay(renderdata->dpy);
+ free(renderdata);
+}
+
+/* FIXME: this is a completely random collection of properties and should be
+ changed to a more sensible list */
+void
+renderer_set_window_properties(ltk_renderdata *renderdata, ltk_color *bg, ltk_color *border, unsigned int border_width) {
+ XSetWindowBorder(renderdata->dpy, renderdata->xwindow, border->xcolor.pixel);
+ XSetWindowBackground(renderdata->dpy, renderdata->xwindow, bg->xcolor.pixel);
+ XSetWindowBorderWidth(renderdata->dpy, renderdata->xwindow, border_width);
+}
+
+void
+renderer_swap_buffers(ltk_renderdata *renderdata) {
+ XdbeSwapInfo swap_info;
+ swap_info.swap_window = renderdata->xwindow;
+ swap_info.swap_action = XdbeBackground;
+ if (!XdbeSwapBuffers(renderdata->dpy, &swap_info, 1))
+ ltk_fatal("Unable to swap buffers.\n");
+ XFlush(renderdata->dpy);
+}
+
+unsigned long
+renderer_get_window_id(ltk_renderdata *renderdata) {
+ return (unsigned long)renderdata->xwindow;
+}
diff --git a/src/grid.c b/src/grid.c
@@ -28,9 +28,7 @@
#include <stdarg.h>
#include <stdint.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
+#include "event.h"
#include "memory.h"
#include "color.h"
#include "rect.h"
@@ -52,9 +50,9 @@ static int ltk_grid_add(ltk_window *window, ltk_widget *widget, ltk_grid *grid,
static int ltk_grid_ungrid(ltk_window *window, ltk_widget *widget, ltk_widget *self, char **errstr);
static int ltk_grid_find_nearest_column(ltk_grid *grid, int x);
static int ltk_grid_find_nearest_row(ltk_grid *grid, int y);
-static int ltk_grid_mouse_press(ltk_widget *self, XEvent event);
-static int ltk_grid_mouse_release(ltk_widget *self, XEvent event);
-static int ltk_grid_motion_notify(ltk_widget *self, XEvent event);
+static int ltk_grid_mouse_press(ltk_widget *self, ltk_event *event);
+static int ltk_grid_mouse_release(ltk_widget *self, ltk_event *event);
+static int ltk_grid_motion_notify(ltk_widget *self, ltk_event *event);
static struct ltk_widget_vtable vtable = {
.draw = <k_grid_draw,
@@ -386,10 +384,10 @@ ltk_grid_find_nearest_row(ltk_grid *grid, int y) {
}
static int
-ltk_grid_mouse_press(ltk_widget *self, XEvent event) {
+ltk_grid_mouse_press(ltk_widget *self, ltk_event *event) {
ltk_grid *grid = (ltk_grid *)self;
- int x = event.xbutton.x;
- int y = event.xbutton.y;
+ int x = event->button.x;
+ int y = event->button.y;
int row = ltk_grid_find_nearest_row(grid, y);
int column = ltk_grid_find_nearest_column(grid, x);
if (row == -1 || column == -1)
@@ -403,10 +401,10 @@ ltk_grid_mouse_press(ltk_widget *self, XEvent event) {
}
static int
-ltk_grid_mouse_release(ltk_widget *self, XEvent event) {
+ltk_grid_mouse_release(ltk_widget *self, ltk_event *event) {
ltk_grid *grid = (ltk_grid *)self;
- int x = event.xbutton.x;
- int y = event.xbutton.y;
+ int x = event->button.x;
+ int y = event->button.y;
int row = ltk_grid_find_nearest_row(grid, y);
int column = ltk_grid_find_nearest_column(grid, x);
if (row == -1 || column == -1)
@@ -420,14 +418,10 @@ ltk_grid_mouse_release(ltk_widget *self, XEvent event) {
}
static int
-ltk_grid_motion_notify(ltk_widget *self, XEvent event) {
+ltk_grid_motion_notify(ltk_widget *self, ltk_event *event) {
ltk_grid *grid = (ltk_grid *)self;
- /* FIXME: Why does it check this? */
- short pressed = (event.xmotion.state & Button1Mask) == Button1Mask;
- if (pressed)
- return 0;
- int x = event.xbutton.x;
- int y = event.xbutton.y;
+ int x = event->motion.x;
+ int y = event->motion.y;
int row = ltk_grid_find_nearest_row(grid, y);
int column = ltk_grid_find_nearest_column(grid, x);
if (row == -1 || column == -1)
diff --git a/src/label.c b/src/label.c
@@ -20,9 +20,7 @@
#include <string.h>
#include <stdarg.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
+#include "event.h"
#include "memory.h"
#include "color.h"
#include "rect.h"
diff --git a/src/ltk.h b/src/ltk.h
@@ -17,29 +17,17 @@
#ifndef _LTK_H_
#define _LTK_H_
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
#include <stdint.h>
-#include <X11/extensions/Xdbe.h>
-#include "color.h"
typedef enum {
LTK_EVENT_RESIZE = 1 << 0,
LTK_EVENT_BUTTON = 1 << 1,
LTK_EVENT_KEY = 1 << 2,
LTK_EVENT_MENU = 1 << 3
-} ltk_event_type;
-
-typedef struct {
- int border_width;
- int font_size;
- char *font;
- ltk_color fg;
- ltk_color bg;
-} ltk_window_theme;
+} ltk_userevent_type;
struct ltk_event_queue {
- ltk_event_type event_type;
+ ltk_userevent_type event_type;
char *data;
struct ltk_event_queue *prev;
struct ltk_event_queue *next;
@@ -59,28 +47,21 @@ struct ltk_event_queue {
typedef struct ltk_window ltk_window;
typedef struct ltk_text_context ltk_text_context;
typedef struct ltk_surface ltk_surface;
+typedef struct ltk_window_theme ltk_window_theme;
#include "widget.h"
#include "surface_cache.h"
+#include "event.h"
struct ltk_window {
- Display *dpy;
- Visual *vis;
+ ltk_renderdata *renderdata;
ltk_surface_cache *surface_cache;
ltk_text_context *text_context;
ltk_surface *surface;
- Colormap cm;
- GC gc;
- int screen;
- Atom wm_delete_msg;
- Window xwindow;
- XdbeBackBuffer back_buf;
- Drawable drawable;
- int depth;
ltk_widget *root_widget;
ltk_widget *active_widget;
ltk_widget *pressed_widget;
- void (*other_event) (struct ltk_window *, XEvent event);
+ void (*other_event) (struct ltk_window *, ltk_event *event);
ltk_rect rect;
ltk_window_theme *theme;
ltk_rect dirty_rect;
@@ -96,9 +77,18 @@ struct ltk_window {
char popups_locked;
};
+#include "color.h"
+
+struct ltk_window_theme {
+ int border_width;
+ int font_size;
+ char *font;
+ ltk_color fg;
+ ltk_color bg;
+};
+
void ltk_window_invalidate_rect(ltk_window *window, ltk_rect rect);
-int ltk_create_xcolor(ltk_window *window, const char *hex, XColor *col);
-void ltk_queue_event(ltk_window *window, ltk_event_type type, const char *id, const char *data);
+void ltk_queue_event(ltk_window *window, ltk_userevent_type type, const char *id, const char *data);
void ltk_window_set_active_widget(ltk_window *window, ltk_widget *widget);
void ltk_window_set_pressed_widget(ltk_window *window, ltk_widget *widget);
void ltk_quit(ltk_window *window);
diff --git a/src/ltkd.c b/src/ltkd.c
@@ -36,12 +36,11 @@
#include <sys/select.h>
#include <sys/socket.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
#include "ini.h"
#include "khash.h"
+#include "graphics.h"
+#include "surface_cache.h"
#include "theme.h"
#include "memory.h"
#include "color.h"
@@ -113,8 +112,8 @@ static ltk_window *ltk_create_window(const char *title, int x, int y,
unsigned int w, unsigned int h);
static void ltk_destroy_window(ltk_window *window);
static void ltk_redraw_window(ltk_window *window);
-static void ltk_window_other_event(ltk_window *window, XEvent event);
-static void ltk_handle_event(ltk_window *window, XEvent event);
+static void ltk_window_other_event(ltk_window *window, ltk_event *event);
+static void ltk_handle_event(ltk_window *window, ltk_event *event);
static void ltk_load_theme(ltk_window *window, const char *path);
static void ltk_uninitialize_theme(ltk_window *window);
@@ -172,7 +171,7 @@ int main(int argc, char *argv[]) {
anyways, so it doesn't matter, but still... */
main_window = ltk_create_window(title, 0, 0, 500, 500);
- sock_path = get_sock_path(ltk_dir, main_window->xwindow);
+ sock_path = get_sock_path(ltk_dir, renderer_get_window_id(main_window->renderdata));
if (!sock_path) ltk_fatal_errno("Unable to allocate memory for socket path.\n");
/* Note: sockets should be initialized to 0 because it is static */
@@ -189,7 +188,7 @@ int main(int argc, char *argv[]) {
static int
ltk_mainloop(ltk_window *window) {
- XEvent event;
+ ltk_event event;
fd_set rfds, wfds, rallfds, wallfds;
int maxfd;
int rretval, wretval;
@@ -207,7 +206,7 @@ ltk_mainloop(ltk_window *window) {
FD_SET(listenfd, &rallfds);
maxfd = listenfd;
- printf("%lu", window->xwindow);
+ printf("%lu", renderer_get_window_id(main_window->renderdata));
fflush(stdout);
if (daemonize_flag)
daemonize();
@@ -218,6 +217,8 @@ ltk_mainloop(ltk_window *window) {
struct timespec now, elapsed, last;
clock_gettime(CLOCK_MONOTONIC, &last);
+ /* FIXME: framerate limiting for draw */
+
while (running) {
rfds = rallfds;
wfds = wallfds;
@@ -228,9 +229,9 @@ ltk_mainloop(ltk_window *window) {
/* value of tv doesn't really matter anymore here because the
necessary framerate-limiting delay is already done */
wretval = select(maxfd + 1, NULL, &wfds, NULL, &tv);
- while (XPending(window->dpy)) {
- XNextEvent(window->dpy, &event);
- ltk_handle_event(window, event);
+ while (ltk_events_pending(window->renderdata)) {
+ ltk_next_event(window->renderdata, &event);
+ ltk_handle_event(window, &event);
}
if (rretval > 0 || (sock_write_available && wretval > 0)) {
@@ -459,7 +460,7 @@ ltk_log_msg(const char *mode, const char *format, va_list args) {
strftime(logtime, 25, "%Y-%m-%d %H:%M:%S", timeptr);
if (main_window)
- fprintf(stderr, "%s ltkd(%lu) %s: ", logtime, main_window->xwindow, mode);
+ fprintf(stderr, "%s ltkd(%lu) %s: ", logtime, renderer_get_window_id(main_window->renderdata), mode);
else
fprintf(stderr, "%s ltkd(?) %s: ", logtime, mode);
vfprintf(stderr, format, args);
@@ -495,18 +496,8 @@ ltk_window_invalidate_rect(ltk_window *window, ltk_rect rect) {
window->dirty_rect = ltk_rect_union(rect, window->dirty_rect);
}
-/* FIXME: Proper error checking by calling functions */
-int
-ltk_create_xcolor(ltk_window *window, const char *hex, XColor *col) {
- if (!XParseColor(window->dpy, window->cm, hex, col))
- return 0;
- XAllocColor(window->dpy, window->cm, col);
-
- return 1;
-}
-
void
-ltk_queue_event(ltk_window *window, ltk_event_type type, const char *id, const char *data) {
+ltk_queue_event(ltk_window *window, ltk_userevent_type type, const char *id, const char *data) {
/* FIXME: make it nicer and safer */
struct ltk_event_queue *new = ltk_malloc(sizeof(struct ltk_event_queue));
new->event_type = type;
@@ -535,14 +526,9 @@ ltk_redraw_window(ltk_window *window) {
window->dirty_rect.w -= window->dirty_rect.x + window->dirty_rect.w - window->rect.w;
if (window->dirty_rect.y + window->dirty_rect.h > window->rect.h)
window->dirty_rect.h -= window->dirty_rect.y + window->dirty_rect.h - window->rect.h;
- XSetForeground(window->dpy, window->gc, window->theme->bg.xcolor.pixel);
/* FIXME: this should use window->dirty_rect, but that doesn't work
properly with double buffering */
- XFillRectangle(
- window->dpy, window->drawable, window->gc,
- window->rect.x, window->rect.y,
- window->rect.w, window->rect.h
- );
+ ltk_surface_fill_rect(window->surface, &window->theme->bg, (ltk_rect){0, 0, window->rect.w, window->rect.h});
if (window->root_widget) {
ptr = window->root_widget;
ptr->vtable->draw(ptr, window->rect);
@@ -552,22 +538,17 @@ ltk_redraw_window(ltk_window *window) {
ptr = window->popups[i];
ptr->vtable->draw(ptr, window->rect);
}
- XdbeSwapInfo swap_info;
- swap_info.swap_window = window->xwindow;
- swap_info.swap_action = XdbeBackground;
- if (!XdbeSwapBuffers(window->dpy, &swap_info, 1))
- ltk_fatal("Unable to swap buffers.\n");
- XFlush(window->dpy);
+ renderer_swap_buffers(window->renderdata);
}
static void
-ltk_window_other_event(ltk_window *window, XEvent event) {
+ltk_window_other_event(ltk_window *window, ltk_event *event) {
ltk_widget *ptr = window->root_widget;
- if (event.type == ConfigureNotify) {
+ if (event->type == LTK_CONFIGURE_EVENT) {
ltk_window_unregister_all_popups(window);
int w, h;
- w = event.xconfigure.width;
- h = event.xconfigure.height;
+ w = event->configure.w;
+ h = event->configure.h;
int orig_w = window->rect.w;
int orig_h = window->rect.h;
if (orig_w != w || orig_h != h) {
@@ -581,15 +562,14 @@ ltk_window_other_event(ltk_window *window, XEvent event) {
ltk_widget_resize(ptr);
}
}
- } else if (event.type == Expose && event.xexpose.count == 0) {
+ } else if (event->type == LTK_EXPOSE_EVENT) {
ltk_rect r;
- r.x = event.xexpose.x;
- r.y = event.xexpose.y;
- r.w = event.xexpose.width;
- r.h = event.xexpose.height;
+ r.x = event->expose.x;
+ r.y = event->expose.y;
+ r.w = event->expose.w;
+ r.h = event->expose.h;
ltk_window_invalidate_rect(window, r);
- } else if (event.type == ClientMessage
- && (Atom)event.xclient.data.l[0] == window->wm_delete_msg) {
+ } else if (event->type == LTK_WINDOWCLOSE_EVENT) {
ltk_quit(window);
}
}
@@ -784,7 +764,6 @@ ltk_uninitialize_theme(ltk_window *window) {
static ltk_window *
ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int h) {
char *theme_path;
- XSetWindowAttributes attrs;
ltk_window *window = ltk_malloc(sizeof(ltk_window));
@@ -792,111 +771,39 @@ ltk_create_window(const char *title, int x, int y, unsigned int w, unsigned int
window->popups_num = window->popups_alloc = 0;
window->popups_locked = 0;
- window->dpy = XOpenDisplay(NULL);
- window->screen = DefaultScreen(window->dpy);
- /* based on http://wili.cc/blog/xdbe.html */
- int major, minor, found = 0;
- if (XdbeQueryExtension(window->dpy, &major, &minor)) {
- int num_screens = 1;
- Drawable screens[] = {DefaultRootWindow(window->dpy)};
- XdbeScreenVisualInfo *info = XdbeGetVisualInfo(
- window->dpy, screens, &num_screens
- );
- if (!info || num_screens < 1 || info->count < 1) {
- ltk_fatal("No visuals support Xdbe.");
- }
- XVisualInfo xvisinfo_templ;
- /* we know there's at least one */
- xvisinfo_templ.visualid = info->visinfo[0].visual;
- /* FIXME: proper screen number? */
- xvisinfo_templ.screen = 0;
- xvisinfo_templ.depth = info->visinfo[0].depth;
- int matches;
- XVisualInfo *xvisinfo_match = XGetVisualInfo(
- window->dpy,
- VisualIDMask | VisualScreenMask | VisualDepthMask,
- &xvisinfo_templ, &matches
- );
- if (!xvisinfo_match || matches < 1) {
- ltk_fatal("Couldn't match a Visual with double buffering.\n");
- }
- window->vis = xvisinfo_match->visual;
- /* FIXME: is it legal to free this while keeping the visual? */
- XFree(xvisinfo_match);
- XdbeFreeVisualInfo(info);
- found = 1;
- } else {
- window->vis = DefaultVisual(window->dpy, window->screen);
- ltk_warn("No Xdbe support.\n");
- }
- //printf("%d %d\n", WidthOfScreen(XDefaultScreenOfDisplay(window->dpy)), WidthMMOfScreen(XDefaultScreenOfDisplay(window->dpy)));
- window->cm = DefaultColormap(window->dpy, window->screen);
+ ltk_renderdata *renderer_create_window(const char *title, int x, int y, unsigned int w, unsigned int h);
+ void renderer_set_window_properties(ltk_renderdata *renderdata, ltk_color *bg_pixel, ltk_color *border_pixel, unsigned int border_width);
+ window->renderdata = renderer_create_window(title, x, y, w, h);
theme_path = ltk_strcat_useful(ltk_dir, "/theme.ini");
window->theme = &window_theme;
ltk_load_theme(window, theme_path);
ltk_free(theme_path);
+
/* FIXME: fix theme memory leaks when exit happens between here and the end of this function */
- window->wm_delete_msg = XInternAtom(window->dpy, "WM_DELETE_WINDOW", False);
-
- memset(&attrs, 0, sizeof(attrs));
- attrs.background_pixel = window->theme->bg.xcolor.pixel;
- attrs.colormap = window->cm;
- attrs.border_pixel = window->theme->fg.xcolor.pixel;
- /* this causes the window contents to be kept
- * when it is resized, leading to less flicker */
- attrs.bit_gravity = NorthWestGravity;
- attrs.event_mask =
- ExposureMask | KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask |
- StructureNotifyMask | PointerMotionMask;
- window->depth = DefaultDepth(window->dpy, window->screen);
- window->xwindow = XCreateWindow(
- window->dpy, DefaultRootWindow(window->dpy), x, y,
- w, h, window->theme->border_width, window->depth,
- InputOutput, window->vis,
- CWBackPixel | CWColormap | CWBitGravity | CWEventMask | CWBorderPixel, &attrs
- );
-
- if (found) {
- window->back_buf = XdbeAllocateBackBufferName(
- window->dpy, window->xwindow, XdbeBackground
- );
- } else {
- window->back_buf = window->xwindow;
- }
- window->drawable = window->back_buf;
- window->gc = XCreateGC(window->dpy, window->xwindow, 0, 0);
- XSetForeground(window->dpy, window->gc, window->theme->fg.xcolor.pixel);
- XSetBackground(window->dpy, window->gc, window->theme->bg.xcolor.pixel);
- XSetStandardProperties(
- window->dpy, window->xwindow,
- title, NULL, None, NULL, 0, NULL
- );
- XSetWMProtocols(window->dpy, window->xwindow, &window->wm_delete_msg, 1);
+
+ renderer_set_window_properties(window->renderdata, &window->theme->bg, &window->theme->fg, window->theme->border_width);
+
window->root_widget = NULL;
window->active_widget = NULL;
window->pressed_widget = NULL;
- window->surface_cache = ltk_surface_cache_create(window);
+ window->surface_cache = ltk_surface_cache_create(window->renderdata);
window->other_event = <k_window_other_event;
window->first_event = window->last_event = NULL;
- window->rect.w = 0;
- window->rect.h = 0;
+ window->rect.w = w;
+ window->rect.h = h;
window->rect.x = 0;
window->rect.y = 0;
window->dirty_rect.w = 0;
window->dirty_rect.h = 0;
window->dirty_rect.x = 0;
window->dirty_rect.y = 0;
- window->surface = ltk_surface_from_window(window);
+ window->surface = ltk_surface_from_window(window->renderdata, w, h);
window->text_context = ltk_text_context_create(window, window->theme->font);
- XClearWindow(window->dpy, window->xwindow);
- XMapRaised(window->dpy, window->xwindow);
-
return window;
}
@@ -905,11 +812,9 @@ ltk_destroy_window(ltk_window *window) {
ltk_text_context_destroy(window->text_context);
if (window->popups)
ltk_free(window->popups);
- XFreeGC(window->dpy, window->gc);
- XDestroyWindow(window->dpy, window->xwindow);
- XCloseDisplay(window->dpy);
- ltk_surface_destroy(window->surface);
ltk_surface_cache_destroy(window->surface_cache);
+ ltk_surface_destroy(window->surface);
+ renderer_destroy_window(window->renderdata);
ltk_free(window);
}
@@ -958,16 +863,16 @@ get_hover_popup(ltk_window *window, int x, int y) {
}
static void
-ltk_handle_event(ltk_window *window, XEvent event) {
+ltk_handle_event(ltk_window *window, ltk_event *event) {
ltk_widget *hover_popup;
ltk_widget *root_widget = window->root_widget;
- switch (event.type) {
- case KeyPress:
+ switch (event->type) {
+ case LTK_KEYPRESS_EVENT:
break;
- case KeyRelease:
+ case LTK_KEYRELEASE_EVENT:
break;
- case ButtonPress:
- hover_popup = get_hover_popup(window, event.xbutton.x, event.xbutton.y);
+ case LTK_BUTTONPRESS_EVENT:
+ hover_popup = get_hover_popup(window, event->button.x, event->button.y);
if (hover_popup) {
ltk_widget_mouse_press_event(hover_popup, event);
} else if (root_widget) {
@@ -975,15 +880,15 @@ ltk_handle_event(ltk_window *window, XEvent event) {
ltk_widget_mouse_press_event(root_widget, event);
}
break;
- case ButtonRelease:
- hover_popup = get_hover_popup(window, event.xbutton.x, event.xbutton.y);
+ case LTK_BUTTONRELEASE_EVENT:
+ hover_popup = get_hover_popup(window, event->button.x, event->button.y);
if (hover_popup)
ltk_widget_mouse_release_event(hover_popup, event);
else if (root_widget)
ltk_widget_mouse_release_event(root_widget, event);
break;
- case MotionNotify:
- hover_popup = get_hover_popup(window, event.xmotion.x, event.xmotion.y);
+ case LTK_MOTION_EVENT:
+ hover_popup = get_hover_popup(window, event->motion.x, event->motion.y);
if (hover_popup)
ltk_widget_motion_notify_event(hover_popup, event);
else if (root_widget)
diff --git a/src/memory.c b/src/memory.c
@@ -16,12 +16,9 @@
#include <stdio.h>
#include <stdlib.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
#include <stdarg.h>
#include <string.h>
#include <stdint.h>
-#include "color.h"
#include "util.h"
#include "memory.h"
diff --git a/src/menu.c b/src/menu.c
@@ -21,9 +21,7 @@
#include <stdarg.h>
#include <math.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
+#include "event.h"
#include "memory.h"
#include "color.h"
#include "rect.h"
@@ -88,15 +86,15 @@ static void ltk_menu_scroll_callback(void *data);
static void stop_scrolling(ltk_menu *menu);
static size_t get_entry_at_point(ltk_menu *menu, int x, int y, ltk_rect *entry_rect_ret);
static int set_scroll_timer(ltk_menu *menu, int x, int y);
-static int ltk_menu_mouse_release(ltk_widget *self, XEvent event);
-static int ltk_menu_mouse_press(ltk_widget *self, XEvent event);
+static int ltk_menu_mouse_release(ltk_widget *self, ltk_event *event);
+static int ltk_menu_mouse_press(ltk_widget *self, ltk_event *event);
static void ltk_menu_hide(ltk_widget *self);
static void popup_active_menu(ltk_menu *menu, ltk_rect r);
static void unpopup_active_entry(ltk_menu *menu);
static void handle_hover(ltk_menu *menu, int x, int y);
-static int ltk_menu_motion_notify(ltk_widget *self, XEvent event);
-static int ltk_menu_mouse_enter(ltk_widget *self, XEvent event);
-static int ltk_menu_mouse_leave(ltk_widget *self, XEvent event);
+static int ltk_menu_motion_notify(ltk_widget *self, ltk_event *event);
+static int ltk_menu_mouse_enter(ltk_widget *self, ltk_event *event);
+static int ltk_menu_mouse_leave(ltk_widget *self, ltk_event *event);
static ltk_menu *ltk_menu_create(ltk_window *window, const char *id, int is_submenu);
static ltk_menuentry *insert_entry(ltk_menu *menu, size_t idx);
static void recalc_menu_size(ltk_menu *menu);
@@ -604,9 +602,9 @@ set_scroll_timer(ltk_menu *menu, int x, int y) {
}
static int
-ltk_menu_mouse_release(ltk_widget *self, XEvent event) {
+ltk_menu_mouse_release(ltk_widget *self, ltk_event *event) {
ltk_menu *menu = (ltk_menu *)self;
- size_t idx = get_entry_at_point(menu, event.xbutton.x, event.xbutton.y, NULL);
+ size_t idx = get_entry_at_point(menu, event->button.x, event->button.y, NULL);
if (idx < menu->num_entries && idx == menu->pressed_entry) {
ltk_window_unregister_all_popups(self->window);
/* FIXME: give menu id and entry id */
@@ -622,33 +620,33 @@ ltk_menu_mouse_release(ltk_widget *self, XEvent event) {
}
static int
-ltk_menu_mouse_press(ltk_widget *self, XEvent event) {
+ltk_menu_mouse_press(ltk_widget *self, ltk_event *event) {
ltk_menu *menu = (ltk_menu *)self;
size_t idx;
/* FIXME: configure scroll step */
- switch (event.xbutton.button) {
- case 1:
- idx = get_entry_at_point(menu, event.xbutton.x, event.xbutton.y, NULL);
+ switch (event->button.button) {
+ case LTK_BUTTONL:
+ idx = get_entry_at_point(menu, event->button.x, event->button.y, NULL);
if (idx < menu->num_entries) {
menu->pressed_entry = idx;
self->dirty = 1;
}
break;
- case 4:
+ case LTK_BUTTON4:
ltk_menu_scroll(menu, 1, 0, 0, 0, 10);
- handle_hover(menu, event.xbutton.x, event.xbutton.y);
+ handle_hover(menu, event->button.x, event->button.y);
break;
- case 5:
+ case LTK_BUTTON5:
ltk_menu_scroll(menu, 0, 1, 0, 0, 10);
- handle_hover(menu, event.xbutton.x, event.xbutton.y);
+ handle_hover(menu, event->button.x, event->button.y);
break;
- case 6:
+ case LTK_BUTTON6:
ltk_menu_scroll(menu, 0, 0, 1, 0, 10);
- handle_hover(menu, event.xbutton.x, event.xbutton.y);
+ handle_hover(menu, event->button.x, event->button.y);
break;
- case 7:
+ case LTK_BUTTON7:
ltk_menu_scroll(menu, 0, 0, 0, 1, 10);
- handle_hover(menu, event.xbutton.x, event.xbutton.y);
+ handle_hover(menu, event->button.x, event->button.y);
break;
default:
break;
@@ -807,19 +805,19 @@ handle_hover(ltk_menu *menu, int x, int y) {
}
static int
-ltk_menu_motion_notify(ltk_widget *self, XEvent event) {
- handle_hover((ltk_menu *)self, event.xmotion.x, event.xmotion.y);
+ltk_menu_motion_notify(ltk_widget *self, ltk_event *event) {
+ handle_hover((ltk_menu *)self, event->motion.x, event->motion.y);
return 1;
}
static int
-ltk_menu_mouse_enter(ltk_widget *self, XEvent event) {
- handle_hover((ltk_menu *)self, event.xbutton.x, event.xbutton.y);
+ltk_menu_mouse_enter(ltk_widget *self, ltk_event *event) {
+ handle_hover((ltk_menu *)self, event->motion.x, event->motion.y);
return 1;
}
static int
-ltk_menu_mouse_leave(ltk_widget *self, XEvent event) {
+ltk_menu_mouse_leave(ltk_widget *self, ltk_event *event) {
(void)event;
stop_scrolling((ltk_menu *)self);
return 1;
diff --git a/src/scrollbar.c b/src/scrollbar.c
@@ -24,6 +24,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include "event.h"
#include "memory.h"
#include "color.h"
#include "rect.h"
@@ -36,8 +37,8 @@
#define MAX_SCROLLBAR_WIDTH 100 /* completely arbitrary */
static void ltk_scrollbar_draw(ltk_widget *self, ltk_rect clip);
-static int ltk_scrollbar_mouse_press(ltk_widget *self, XEvent event);
-static int ltk_scrollbar_motion_notify(ltk_widget *self, XEvent event);
+static int ltk_scrollbar_mouse_press(ltk_widget *self, ltk_event *event);
+static int ltk_scrollbar_motion_notify(ltk_widget *self, ltk_event *event);
static void ltk_scrollbar_destroy(ltk_widget *self, int shallow);
static struct ltk_widget_vtable vtable = {
@@ -164,12 +165,12 @@ ltk_scrollbar_draw(ltk_widget *self, ltk_rect clip) {
}
static int
-ltk_scrollbar_mouse_press(ltk_widget *self, XEvent event) {
+ltk_scrollbar_mouse_press(ltk_widget *self, ltk_event *event) {
ltk_scrollbar *sc = (ltk_scrollbar *)self;
int max_pos;
- if (event.xbutton.button != 1)
+ if (event->button.button != LTK_BUTTONL)
return 0;
- int ex = event.xbutton.x, ey = event.xbutton.y;
+ int ex = event->button.x, ey = event->button.y;
ltk_rect handle_rect = get_handle_rect(sc);
if (sc->orient == LTK_HORIZONTAL) {
if (ex < handle_rect.x || ex > handle_rect.x + handle_rect.w) {
@@ -187,8 +188,8 @@ ltk_scrollbar_mouse_press(ltk_widget *self, XEvent event) {
else if (sc->cur_pos > max_pos)
sc->cur_pos = max_pos;
sc->callback(sc->callback_data);
- sc->last_mouse_x = event.xbutton.x;
- sc->last_mouse_y = event.xbutton.y;
+ sc->last_mouse_x = event->button.x;
+ sc->last_mouse_y = event->button.y;
return 1;
}
@@ -218,19 +219,19 @@ ltk_scrollbar_scroll(ltk_widget *self, int delta, int scaled) {
}
static int
-ltk_scrollbar_motion_notify(ltk_widget *self, XEvent event) {
+ltk_scrollbar_motion_notify(ltk_widget *self, ltk_event *event) {
ltk_scrollbar *sc = (ltk_scrollbar *)self;
int delta;
if (self->state != LTK_PRESSED) {
return 1;
}
if (sc->orient == LTK_HORIZONTAL)
- delta = event.xbutton.x - sc->last_mouse_x;
+ delta = event->button.x - sc->last_mouse_x;
else
- delta = event.xbutton.y - sc->last_mouse_y;
+ delta = event->button.y - sc->last_mouse_y;
ltk_scrollbar_scroll(self, delta, 1);
- sc->last_mouse_x = event.xbutton.x;
- sc->last_mouse_y = event.xbutton.y;
+ sc->last_mouse_x = event->button.x;
+ sc->last_mouse_y = event->button.y;
return 0;
}
diff --git a/src/surface_cache.c b/src/surface_cache.c
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "graphics.h"
#include "surface_cache.h"
#include "memory.h"
@@ -50,7 +51,7 @@ struct cache_surface {
struct ltk_surface_cache {
/* FIXME: many widgets won't use named keys anyways, so this is a bit wasteful */
- ltk_window *window;
+ ltk_renderdata *renderdata;
struct named_cache_widget_entry named_keys[LTK_NUM_WIDGETS];
struct cache_surface **surfaces;
size_t surfaces_num; /* total number of stored surfaces */
@@ -68,9 +69,9 @@ struct ltk_surface_cache {
*/
ltk_surface_cache *
-ltk_surface_cache_create(ltk_window *window) {
+ltk_surface_cache_create(ltk_renderdata *renderdata) {
ltk_surface_cache *sc = ltk_malloc(sizeof(ltk_surface_cache));
- sc->window = window;
+ sc->renderdata = renderdata;
for (int i = 0; i < LTK_NUM_WIDGETS; i++) {
sc->named_keys[i].entries = NULL;
sc->named_keys[i].entries_num = 0;
@@ -194,7 +195,7 @@ ltk_surface_cache_get_surface(ltk_surface_cache_key *key, ltk_surface **s_ret) {
c->surfaces[i] = NULL;
}
struct cache_surface *cs = ltk_malloc(sizeof(struct cache_surface));
- cs->s = ltk_surface_create(c->window, key->min_w, key->min_h);
+ cs->s = ltk_surface_create(c->renderdata, key->min_w, key->min_h);
cs->key = key;
key->s = cs;
c->surfaces[0] = cs;
@@ -216,7 +217,7 @@ ltk_surface_cache_get_surface(ltk_surface_cache_key *key, ltk_surface **s_ret) {
struct cache_surface *cs = c->surfaces[c->surfaces_num];
c->surfaces_num++;
c->surfaces_realnum++;
- cs->s = ltk_surface_create(c->window, key->min_w, key->min_h);
+ cs->s = ltk_surface_create(c->renderdata, key->min_w, key->min_h);
cs->key = key;
key->s = cs;
c->free_pixels -= (long)key->min_w * key->min_h;
@@ -309,7 +310,7 @@ ltk_surface_cache_get_surface(ltk_surface_cache_key *key, ltk_surface **s_ret) {
if (!c->surfaces[0])
c->surfaces[0] = ltk_malloc(sizeof(struct cache_surface));
struct cache_surface *cs = c->surfaces[0];
- cs->s = ltk_surface_create(c->window, key->min_w, key->min_h);
+ cs->s = ltk_surface_create(c->renderdata, key->min_w, key->min_h);
cs->key = key;
key->s = cs;
c->surfaces_num = 1;
diff --git a/src/surface_cache.h b/src/surface_cache.h
@@ -13,7 +13,7 @@ typedef struct ltk_surface_cache_key ltk_surface_cache_key;
#include "ltk.h"
#include "graphics.h"
-ltk_surface_cache *ltk_surface_cache_create(ltk_window *window);
+ltk_surface_cache *ltk_surface_cache_create(ltk_renderdata *renderdata);
void ltk_surface_cache_destroy(ltk_surface_cache *cache);
ltk_surface_cache_key *ltk_surface_cache_get_named_key(ltk_surface_cache *cache, ltk_widget_type type, int id, int min_w, int min_h);
ltk_surface_cache_key *ltk_surface_cache_get_unnamed_key(ltk_surface_cache *cache, int min_w, int min_h);
diff --git a/src/text.h b/src/text.h
@@ -25,6 +25,7 @@ typedef struct ltk_text_line ltk_text_line;
/* typedef struct ltk_text_context ltk_text_context; */
/* FIXME: something to hold display, etc. to avoid circular reference between window and text context */
+/* FIXME: this is done now (ltk_renderdata), just need to use it here... */
ltk_text_context *ltk_text_context_create(ltk_window *window, char *default_font);
void ltk_text_context_destroy(ltk_text_context *ctx);
diff --git a/src/text_pango.c b/src/text_pango.c
@@ -26,6 +26,7 @@
#include <pango/pangoxft.h>
+#include "xlib_shared.h"
#include "memory.h"
#include "color.h"
#include "rect.h"
@@ -52,7 +53,7 @@ ltk_text_context *
ltk_text_context_create(ltk_window *window, char *default_font) {
ltk_text_context *ctx = ltk_malloc(sizeof(ltk_text_context));
ctx->window = window;
- ctx->fontmap = pango_xft_get_font_map(window->dpy, window->screen);
+ ctx->fontmap = pango_xft_get_font_map(window->renderdata->dpy, window->renderdata->screen);
ctx->context = pango_font_map_create_context(ctx->fontmap);
ctx->default_font = ltk_strdup(default_font);
return ctx;
diff --git a/src/text_stb.c b/src/text_stb.c
@@ -29,6 +29,7 @@
#include "khash.h"
#include "stb_truetype.h" /* http://nothings.org/stb/stb_truetype.h */
+#include "xlib_shared.h"
#include "memory.h"
#include "color.h"
#include "rect.h"
@@ -591,7 +592,7 @@ ltk_text_line_draw(ltk_text_line *tl, ltk_surface *s, ltk_color *color, int x, i
if (w <= 0 || h <= 0)
return;
Drawable d = ltk_surface_get_drawable(s);
- XImage *img = XGetImage(tl->ctx->window->dpy, d, x, y, w, h, 0xFFFFFF, ZPixmap);
+ XImage *img = XGetImage(tl->ctx->window->renderdata->dpy, d, x, y, w, h, 0xFFFFFF, ZPixmap);
int last_break = 0;
for (int i = 0; i < tl->lines; i++) {
@@ -607,7 +608,7 @@ ltk_text_line_draw(ltk_text_line *tl, ltk_surface *s, ltk_color *color, int x, i
}
last_break = next_break;
}
- XPutImage(tl->ctx->window->dpy, d, tl->ctx->window->gc, img, 0, 0, x, y, w, h);
+ XPutImage(tl->ctx->window->renderdata->dpy, d, tl->ctx->window->renderdata->gc, img, 0, 0, x, y, w, h);
XDestroyImage(img);
}
diff --git a/src/theme.c b/src/theme.c
@@ -1,3 +1,5 @@
+#include "graphics.h"
+#include "surface_cache.h"
#include "util.h"
#include "theme.h"
#include "memory.h"
@@ -48,7 +50,7 @@ ltk_theme_handle_value(ltk_window *window, char *debug_name, const char *prop, c
entry->initialized = 1;
break;
case THEME_COLOR:
- if (ltk_color_create(window->dpy, window->vis, window->cm, value, entry->ptr.color)) {
+ if (ltk_color_create(window->renderdata, value, entry->ptr.color)) {
ltk_warn("Unable to create color '%s' for property '%s:%s'.\n", value, debug_name, prop);
return 1;
} else {
@@ -110,7 +112,7 @@ ltk_theme_fill_defaults(ltk_window *window, char *debug_name, ltk_theme_parseinf
e->initialized = 1;
break;
case THEME_COLOR:
- if (ltk_color_create(window->dpy, window->vis, window->cm, e->defaultval.color, e->ptr.color)) {
+ if (ltk_color_create(window->renderdata, e->defaultval.color, e->ptr.color)) {
ltk_warn("Unable to create default color '%s' for property '%s:%s'.\n", e->defaultval.color, debug_name, e->key);
return 1;
} else {
@@ -145,7 +147,7 @@ ltk_theme_uninitialize(ltk_window *window, ltk_theme_parseinfo *parseinfo, size_
e->initialized = 0;
break;
case THEME_COLOR:
- ltk_color_destroy(window->dpy, window->vis, window->cm, e->ptr.color);
+ ltk_color_destroy(window->renderdata, e->ptr.color);
e->initialized = 0;
break;
case THEME_INT:
diff --git a/src/theme.h b/src/theme.h
@@ -38,6 +38,7 @@ typedef struct {
int initialized;
} ltk_theme_parseinfo;
+/* FIXME: this only needs renderdata, not window */
/* Both return 1 on error, 0 on success */
int ltk_theme_handle_value(ltk_window *window, char *debug_name, const char *prop, const char *value, ltk_theme_parseinfo *parseinfo, size_t len, int *sorted);
int ltk_theme_fill_defaults(ltk_window *window, char *debug_name, ltk_theme_parseinfo *parseinfo, size_t len);
diff --git a/src/widget.c b/src/widget.c
@@ -22,11 +22,9 @@
*/
#include <stdarg.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
#include <stdint.h>
+#include "event.h"
#include "rect.h"
#include "widget.h"
#include "color.h"
@@ -129,20 +127,20 @@ ltk_widget_change_state(ltk_widget *widget) {
}
void
-ltk_widget_mouse_press_event(ltk_widget *widget, XEvent event) {
+ltk_widget_mouse_press_event(ltk_widget *widget, ltk_event *event) {
if (!widget || widget->state == LTK_DISABLED)
return;
int default_handler = 1;
if (widget->vtable->mouse_press)
default_handler = widget->vtable->mouse_press(widget, event);
if (default_handler) {
- if (event.xbutton.button == 1)
+ if (event->button.button == LTK_BUTTONL)
ltk_window_set_pressed_widget(widget->window, widget);
}
}
void
-ltk_widget_mouse_release_event(ltk_widget *widget, XEvent event) {
+ltk_widget_mouse_release_event(ltk_widget *widget, ltk_event *event) {
if (!widget || widget->state == LTK_DISABLED)
return;
if (widget->vtable->mouse_release)
@@ -151,7 +149,7 @@ ltk_widget_mouse_release_event(ltk_widget *widget, XEvent event) {
}
void
-ltk_widget_motion_notify_event(ltk_widget *widget, XEvent event) {
+ltk_widget_motion_notify_event(ltk_widget *widget, ltk_event *event) {
/* FIXME: THIS WHOLE STATE HANDLING IS STILL PARTIALLY BROKEN */
/* FIXME: need to bring back hover state to make enter/leave work properly */
/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
diff --git a/src/widget.h b/src/widget.h
@@ -17,9 +17,8 @@
#ifndef _LTK_WIDGET_H_
#define _LTK_WIDGET_H_
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
#include "rect.h"
+#include "event.h"
/* FIXME: SORT OUT INCLUDES PROPERLY! */
@@ -85,14 +84,16 @@ struct ltk_widget {
char hidden;
};
+/* FIXME: just give the structs for the actual event type here instead
+ of the generic ltk_event */
struct ltk_widget_vtable {
- void (*key_press) (struct ltk_widget *, XEvent);
- void (*key_release) (struct ltk_widget *, XEvent);
- int (*mouse_press) (struct ltk_widget *, XEvent);
- int (*mouse_release) (struct ltk_widget *, XEvent);
- int (*motion_notify) (struct ltk_widget *, XEvent);
- int (*mouse_leave) (struct ltk_widget *, XEvent);
- int (*mouse_enter) (struct ltk_widget *, XEvent);
+ void (*key_press) (struct ltk_widget *, ltk_event *);
+ void (*key_release) (struct ltk_widget *, ltk_event *);
+ int (*mouse_press) (struct ltk_widget *, ltk_event *);
+ int (*mouse_release) (struct ltk_widget *, ltk_event *);
+ int (*motion_notify) (struct ltk_widget *, ltk_event *);
+ int (*mouse_leave) (struct ltk_widget *, ltk_event *);
+ int (*mouse_enter) (struct ltk_widget *, ltk_event *);
void (*resize) (struct ltk_widget *);
void (*hide) (struct ltk_widget *);
@@ -113,9 +114,9 @@ int ltk_widget_destroy_cmd(struct ltk_window *window, char **tokens, size_t num_
void ltk_fill_widget_defaults(ltk_widget *widget, const char *id, struct ltk_window *window,
struct ltk_widget_vtable *vtable, int w, int h);
void ltk_widget_change_state(ltk_widget *widget);
-void ltk_widget_mouse_press_event(ltk_widget *widget, XEvent event);
-void ltk_widget_mouse_release_event(ltk_widget *widget, XEvent event);
-void ltk_widget_motion_notify_event(ltk_widget *widget, XEvent event);
+void ltk_widget_mouse_press_event(ltk_widget *widget, ltk_event *event);
+void ltk_widget_mouse_release_event(ltk_widget *widget, ltk_event *event);
+void ltk_widget_motion_notify_event(ltk_widget *widget, ltk_event *event);
int ltk_widget_id_free(const char *id);
ltk_widget *ltk_get_widget(const char *id, ltk_widget_type type, char **errstr);
void ltk_set_widget(ltk_widget *widget, const char *id);
diff --git a/src/xlib_shared.h b/src/xlib_shared.h
@@ -0,0 +1,20 @@
+#ifndef XLIB_SHARED_H
+#define XLIB_SHARED_H
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xdbe.h>
+
+struct ltk_renderdata {
+ Display *dpy;
+ Visual *vis;
+ Colormap cm;
+ GC gc;
+ int screen;
+ Atom wm_delete_msg;
+ Window xwindow;
+ XdbeBackBuffer back_buf;
+ Drawable drawable;
+ int depth;
+};
+
+#endif /* XLIB_SHARED_H */