#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <libevdev/libevdev.h>
#include <xkbcommon/xkbcommon.h>
#include <wayland-server.h>
#include <wayland-client.h>
#include "gtk-shell-client-protocol.h"
#include "gtk-shell-server-protocol.h"
+/* Window Managers calls */
+void wm_update(void);
+
/* Wayland user data */
typedef struct {
- uint8_t *mem;
- size_t size;
+ uint8_t *mem;
+ size_t size;
} sys_pool_t;
typedef struct {
- sys_pool_t *pool;
- uint8_t *mem;
- cairo_surface_t *surface;
-} sys_buf_t;
+ sys_pool_t *pool;
+ uint8_t *mem;
+ cairo_surface_t *surface;
+} sys_bdata_t;
+
+typedef struct {
+ struct wl_client *cli;
+ list_t *ptrs; // of struct wl_resource
+ list_t *kbds; // of struct wl_resource
+ list_t *tchs; // of struct wl_resource
+} sys_cdata_t;
/* Internal structures */
struct win_sys {
- struct wl_client *cli;
- struct wl_resource *sfc;
- sys_buf_t *buf;
+ struct wl_resource *sfc;
+ struct wl_resource *ssfc;
+ struct wl_resource *xsfc;
+ struct wl_resource *buf;
+ sys_cdata_t *cdata;
+ int x,y; // surface x,y
+ int wx,wy; // window x,y inside sfc
+ int ww,wh; // window w,h inside sfc
};
/* Global data */
+static win_t *root; // root window
+static win_t *hover; // window the mouse is over
+static win_t *focus; // focused window
+static win_t *cursor; // mouse cursor image
+
+static list_t *clients; // of sys_cdata_t
+static list_t *windows; // of win_t
+
+static double cursor_x;
+static double cursor_y;
+static double cursor_dx;
+static double cursor_dy;
+
static GtkWidget *screen;
-static list_t *windows;
static struct wl_resource *output;
static struct wl_display *display;
static struct wl_event_loop *events;
-/*****************
- * Gtk Callbacks *
- *****************/
+static struct wl_array keys;
-static void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer user_data)
-{
- printf("on_destroy\n");
- sys_exit();
+/* Constant data */
+static struct wl_array xstate_normal;
+static struct wl_array xstate_active;
+static struct wl_array xstate_max;
+static struct wl_array xstate_full;
+static struct wl_array xstate_resize;
+
+/********************
+ * Helper Functions *
+ ********************/
+
+static void set_array(struct wl_array *array, int n, ...)
+{
+ va_list ap;
+ va_start(ap, n);
+ wl_array_init(array);
+ for (int i = 0; i < n; i++) {
+ uint32_t item = va_arg(ap, uint32_t);
+ uint32_t *ptr = wl_array_add(array, sizeof(item));
+ if (!ptr)
+ error("Unable to allocate constant");
+ *ptr = item;
+ }
+ va_end(ap);
}
-static gboolean on_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+static int get_serial(void)
{
- printf(g_ascii_isprint(event->keyval)
- ? "on_key: '%c'\n"
- : "on_key: 0x%X\n",
- event->keyval);
- if (event->keyval == GDK_KEY_q)
- sys_exit();
- if (event->keyval == GDK_KEY_t)
- g_spawn_command_line_async("st-wl", NULL);
- return TRUE;
+ static int serial = 0;
+ return serial++;
}
-static gboolean on_button(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+static int get_time(void)
{
- printf("on_button\n");
- return TRUE;
+ static uint64_t epoch;
+
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ uint64_t now = (((uint64_t)ts.tv_sec ) * 1000)
+ + (((uint64_t)ts.tv_nsec) / 1000000);
+
+ if (epoch == 0)
+ epoch = now;
+
+ return (int)(now - epoch);
}
-static gboolean on_move(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
+static ptr_t get_ptr(win_t *win)
{
- return TRUE;
+ ptr_t ptr = {
+ .rx = cursor_x,
+ .ry = cursor_y,
+ };
+ if (win) {
+ ptr.x = cursor_x - win->x;
+ ptr.y = cursor_y - win->y;
+ };
+ return ptr;
}
-static gboolean on_draw(GtkWidget *widget, cairo_t *cairo, gpointer user_data)
+static mod_t get_mod(unsigned int state, int up)
{
- printf("on_draw\n");
+ return (mod_t){
+ .alt = !!(state & GDK_MOD1_MASK ),
+ .ctrl = !!(state & GDK_CONTROL_MASK),
+ .shift = !!(state & GDK_SHIFT_MASK ),
+ .win = !!(state & GDK_MOD4_MASK ),
+ .up = up,
+ };
+}
- list_t *bottom = list_last(windows);
- for (list_t *cur = bottom; cur; cur = cur->prev) {
- win_t *win = cur->data;
- sys_buf_t *buf = win->sys->buf;
- if (buf == NULL)
- continue;
- printf(" win = %p", win);
- cairo_surface_mark_dirty(buf->surface);
- cairo_set_source_surface(cairo, buf->surface, 10, 10);
- cairo_paint(cairo);
+static win_t *find_win(int x, int y)
+{
+ for (list_t *cur = windows; cur; cur = cur->next) {
+ win_t *win = cur->data;
+ printf("find_win -- %p -- %4d,%-4d : %4dx%-4d\n",
+ win, win->x, win->y, win->w, win->h);
}
-
- return TRUE;
+ for (list_t *cur = windows; cur; cur = cur->next) {
+ win_t *win = cur->data;
+ int l = win->x;
+ int r = win->w + l;
+ int t = win->y;
+ int b = win->h + t;
+ if (l <= x && x <= r && t <= y && y <= b) {
+ printf("find_win -> %p\n", win);
+ return win;
+ }
+ }
+ return NULL;
}
-static gboolean on_wayland(gpointer user_data)
+static sys_cdata_t *find_cdata(struct wl_client *cli)
{
- // TODO - convert to polled execution
- wl_display_flush_clients(display);
- wl_event_loop_dispatch(events, 0);
- return TRUE;
+ // Search for existing client
+ for (list_t *cur = clients; cur; cur = cur->next) {
+ sys_cdata_t *cdata = cur->data;
+ if (cdata->cli == cli)
+ return cdata;
+ }
+
+ // Not found, create new one
+ sys_cdata_t *cdata = new0(sys_cdata_t);
+ clients = list_insert(clients, cdata);
+ cdata->cli = cli;
+ return cdata;
}
/****************************
uint32_t id, int32_t offset, int32_t width, int32_t height,
int32_t stride, uint32_t format)
{
- sys_buf_t *buf = new0(sys_buf_t);
- buf->pool = wl_resource_get_user_data(pool);
- buf->mem = buf->pool->mem + offset;
+ sys_bdata_t *bdata = new0(sys_bdata_t);
+ bdata->pool = wl_resource_get_user_data(pool);
+ bdata->mem = bdata->pool->mem + offset;
printf("pool_create_buffer - %dx%d %p+%d : %d,%d,%d\n",
- width, height, buf->pool->mem, offset, id, stride, format);
+ width, height, bdata->pool->mem, offset, id, stride, format);
- if (offset > buf->pool->size || offset < 0)
+ if (offset > bdata->pool->size || offset < 0)
{
printf("\n\nerror\n\n");
wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_STRIDE,
format == WL_SHM_FORMAT_ARGB8888 ? CAIRO_FORMAT_ARGB32 :
format == WL_SHM_FORMAT_XRGB8888 ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_INVALID;
- buf->surface = cairo_image_surface_create_for_data(buf->mem, cf, width, height, stride);
+ bdata->surface = cairo_image_surface_create_for_data(bdata->mem, cf, width, height, stride);
struct wl_resource *res = wl_resource_create(cli, &wl_buffer_interface,
wl_resource_get_version(pool), id);
- wl_resource_set_implementation(res, &buffer_iface, buf, NULL);
+ wl_resource_set_implementation(res, &buffer_iface, bdata, NULL);
}
static void pool_destroy(struct wl_client *cli, struct wl_resource *pool)
**************************/
/* Pointer */
+static void pointer_kill(struct wl_resource *ptr)
+{
+ sys_cdata_t *cdata = wl_resource_get_user_data(ptr);
+ list_t *link = list_find(cdata->ptrs, ptr);
+ cdata->ptrs = list_remove(cdata->ptrs, link, 0);
+ if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
+ list_t *clink = list_find(clients, cdata);
+ clients = list_remove(clients, clink, 1);
+ }
+}
+
static void pointer_set_cursor(struct wl_client *cli, struct wl_resource *ptr,
- uint32_t serial,
- struct wl_resource *surface,
- int32_t hotspot_x,
- int32_t hotspot_y)
+ uint32_t serial, struct wl_resource *sfc,
+ int32_t hotspot_x, int32_t hotspot_y)
{
- printf("pointer_set_cursor\n");
+ printf("pointer_set_cursor %d,%d\n", hotspot_x, hotspot_y);
+ win_t *win = wl_resource_get_user_data(sfc);
+ win->type = TYPE_CURSOR;
+ cursor_dx = hotspot_x;
+ cursor_dy = hotspot_y;
+ cursor = win;
}
static void pointer_release(struct wl_client *cli, struct wl_resource *ptr)
};
/* Keyboard */
+static void keyboard_kill(struct wl_resource *kbd)
+{
+ sys_cdata_t *cdata = wl_resource_get_user_data(kbd);
+ list_t *link = list_find(cdata->kbds, kbd);
+ cdata->kbds = list_remove(cdata->kbds, link, 0);
+ if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
+ list_t *clink = list_find(clients, cdata);
+ clients = list_remove(clients, clink, 1);
+ }
+}
+
static void keyboard_release(struct wl_client *cli, struct wl_resource *kbd)
{
printf("keyboard_release\n");
};
/* Touch */
+static void touch_kill(struct wl_resource *tch)
+{
+ sys_cdata_t *cdata = wl_resource_get_user_data(tch);
+ list_t *link = list_find(cdata->tchs, tch);
+ cdata->tchs = list_remove(cdata->tchs, link, 0);
+ if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
+ list_t *clink = list_find(clients, cdata);
+ clients = list_remove(clients, clink, 1);
+ }
+}
+
static void touch_release(struct wl_client *cli, struct wl_resource *tch)
{
printf("touch_release\n");
/* Seat */
static void seat_get_pointer(struct wl_client *cli, struct wl_resource *seat,
uint32_t id) {
- printf("seat_get_pointer\n");
+ sys_cdata_t *cdata = find_cdata(cli);
struct wl_resource *res = wl_resource_create(cli, &wl_pointer_interface, 3, id);
- wl_resource_set_implementation(res, &pointer_iface, NULL, NULL);
+ wl_resource_set_implementation(res, &pointer_iface, cdata, pointer_kill);
+ cdata->ptrs = list_insert(cdata->ptrs, res);
+ printf("seat_get_pointer - cli=%p cdata=%p ptr=%p\n", cli, cdata, res);
}
static void seat_get_keyboard(struct wl_client *cli, struct wl_resource *seat,
uint32_t id) {
- printf("seat_get_keyboard\n");
+ sys_cdata_t *cdata = find_cdata(cli);
struct wl_resource *res = wl_resource_create(cli, &wl_keyboard_interface, 4, id);
- wl_resource_set_implementation(res, &keyboard_iface, NULL, NULL);
+ wl_resource_set_implementation(res, &keyboard_iface, cdata, keyboard_kill);
+
+ //map = xkb_keymap_new_from_names(xkb->context, NULL, 0);
+ //xkb->context = xkb_context_new(0);
+ //xkb->keymap.map = xkb_keymap_new_from_names(xkb->context, NULL, 0);
+ //wl_keyboard_send_keymap(cli, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
+ // keyboard->xkb.keymap.fd,
+ // keyboard->xkb.keymap.size - 1);
+
+ cdata->kbds = list_insert(cdata->kbds, res);
+ printf("seat_get_keyboard - cli=%p cdata=%p kbd=%p\n", cli, cdata, res);
}
static void seat_get_touch(struct wl_client *cli, struct wl_resource *seat,
uint32_t id) {
- printf("seat_get_touch\n");
+ sys_cdata_t *cdata = find_cdata(cli);
struct wl_resource *res = wl_resource_create(cli, &wl_touch_interface, 3, id);
- wl_resource_set_implementation(res, &touch_iface, NULL, NULL);
+ wl_resource_set_implementation(res, &touch_iface, cdata, touch_kill);
+ cdata->tchs = list_insert(cdata->tchs, res);
+ printf("seat_get_touch - cli=%p cdata=%p tch=%p\n", cli, cdata, res);
}
static struct wl_seat_interface seat_iface = {
/* Surface */
static void surface_kill(struct wl_resource *sfc)
{
- printf("surface_kill\n");
- list_t *link = wl_resource_get_user_data(sfc);
- win_t *win = link->data;
+ win_t *win = wl_resource_get_user_data(sfc);
+ list_t *link = list_find(windows, win);
+ printf("surface_kill - %p\n", win);
+ if (win == NULL) return;
+ if (win == hover) hover = NULL;
+ if (win == focus) focus = NULL;
+ if (win == cursor) cursor = NULL;
free(win->sys);
free(win);
windows = list_remove(windows, link, 0);
+ wl_resource_set_user_data(sfc, NULL);
gtk_widget_queue_draw(screen);
}
static void surface_attach(struct wl_client *cli, struct wl_resource *sfc,
struct wl_resource *buf, int32_t x, int32_t y)
{
- list_t *link = wl_resource_get_user_data(sfc);
- sys_buf_t *data = wl_resource_get_user_data(buf);
- win_t *win = link->data;
- printf("surface_attach - %p\n", data->pool->mem);
- win->sys->buf = data;
+ win_t *win = wl_resource_get_user_data(sfc);
+ printf("surface_attach - %p - %d,%d\n", buf, x, y);
+ win->sys->buf = buf;
+ win->sys->x = x;
+ win->sys->y = y;
}
static void surface_damage(struct wl_client *cli, struct wl_resource *sfc,
printf("surface_frame\n");
struct wl_resource *cb = wl_resource_create(cli, &wl_callback_interface, 1, id);
wl_resource_set_implementation(cb, NULL, NULL, NULL);
- wl_callback_send_done(cb, time(NULL));
+ wl_callback_send_done(cb, get_time());
}
static void surface_set_opaque_region(struct wl_client *cli, struct wl_resource *sfc,
uint32_t id)
{
win_t *win = new0(win_t);
- printf("comp_create_surface - win=%p\n", win);
-
- windows = list_insert(windows, win);
+ win->sys = new0(win_sys_t);
struct wl_resource *res = wl_resource_create(cli, &wl_surface_interface, 3, id);
- wl_resource_set_implementation(res, &surface_iface, windows, surface_kill);
+ wl_resource_set_implementation(res, &surface_iface, win, surface_kill);
wl_surface_send_enter(res, output);
- win->sys = new0(win_sys_t);
- win->sys->cli = cli;
- win->sys->sfc = res;
+ win->sys->sfc = res;
+ win->sys->cdata = find_cdata(cli);
+
+ windows = list_insert(windows, win);
+
+ printf("comp_create_surface - cli=%p win=%p cdata=%p\n",
+ cli, win, win->sys->cdata);
}
static void comp_create_region(struct wl_client *cli, struct wl_resource *comp,
};
/* Shell Surface */
+static void ssurface_kill(struct wl_resource *ssfc)
+{
+ win_t *win = wl_resource_get_user_data(ssfc);
+ printf("ssurface_kill - %p\n", win);
+ win->sys->ssfc = NULL;
+ if (!win->sys->xsfc)
+ wm_remove(win);
+}
+
static void ssurface_pong(struct wl_client *cli, struct wl_resource *ssfc,
uint32_t serial)
{
/* Shell */
static void shell_get_shell_surface(struct wl_client *cli, struct wl_resource *shell, uint32_t id,
struct wl_resource *sfc) {
- printf("shell_get_shell_surface\n");
+ win_t *win = wl_resource_get_user_data(sfc);
+ printf("shell_get_shell_surface - %p\n", win);
+
struct wl_resource *res = wl_resource_create(cli, &wl_shell_surface_interface, 1, id);
- wl_resource_set_implementation(res, &ssurface_iface, NULL, NULL);
+ wl_resource_set_implementation(res, &ssurface_iface, win, ssurface_kill);
+
+ win->type = TYPE_NORMAL;
+ win->sys->ssfc = res;
+ wm_insert(win);
}
static struct wl_shell_interface shell_iface = {
};
/* XDG Surface */
+static void xsurface_kill(struct wl_resource *xsfc)
+{
+ win_t *win = wl_resource_get_user_data(xsfc);
+ printf("xsurface_kill - %p\n", win);
+ if (!win)
+ return;
+ win->sys->xsfc = NULL;
+ if (!win->sys->ssfc)
+ wm_remove(win);
+}
+
static void xsurface_destroy(struct wl_client *cli, struct wl_resource *xsfc)
{
printf("xsurface_destroy\n");
+ xsurface_kill(xsfc);
}
static void xsurface_set_parent(struct wl_client *cli, struct wl_resource *xsfc,
struct wl_resource *parent)
{
- printf("xsurface_set_parent\n");
+ win_t *win = wl_resource_get_user_data(xsfc);
+ printf("xsurface_set_parent - %p\n", win);
+ //win->type = TYPE_DIALOG;
}
static void xsurface_set_title(struct wl_client *cli, struct wl_resource *xsfc,
static void xsurface_set_window_geometry(struct wl_client *cli, struct wl_resource *xsfc,
int32_t x, int32_t y, int32_t width, int32_t height)
{
- printf("xsurface_set_window_geometry\n");
+ win_t *win = wl_resource_get_user_data(xsfc);
+ printf("xsurface_set_window_geometry - %p\n", win);
+ win->sys->wx = x;
+ win->sys->wy = y;
+ win->sys->ww = width;
+ win->sys->wh = height;
}
static void xsurface_set_maximized(struct wl_client *cli, struct wl_resource *xsfc)
};
/* XDG Shell */
-static void xshell_use_unstable_version(struct wl_client *cli, struct wl_resource *gshell,
+static void xshell_use_unstable_version(struct wl_client *cli, struct wl_resource *xshell,
int32_t version)
{
printf("xshell_use_unstable_version\n");
}
-static void xshell_get_xdg_surface(struct wl_client *cli, struct wl_resource *gshell,
- uint32_t id, struct wl_resource *surface)
+static void xshell_get_xdg_surface(struct wl_client *cli, struct wl_resource *xshell,
+ uint32_t id, struct wl_resource *sfc)
{
- printf("xshell_get_xdg_surface\n");
+ win_t *win = wl_resource_get_user_data(sfc);
+ printf("xshell_get_xdg_surface - %p\n", win);
+
struct wl_resource *res = wl_resource_create(cli, &xdg_surface_interface, 1, id);
- wl_resource_set_implementation(res, &xsurface_iface, NULL, NULL);
+ wl_resource_set_implementation(res, &xsurface_iface, win, xsurface_kill);
+
+ win->type = TYPE_NORMAL;
+ win->sys->xsfc = res;
+ wm_insert(win);
}
-static void xshell_get_xdg_popup(struct wl_client *cli, struct wl_resource *gshell,
- uint32_t id, struct wl_resource *surface, struct wl_resource *parent,
+static void xshell_get_xdg_popup(struct wl_client *cli, struct wl_resource *xshell,
+ uint32_t id, struct wl_resource *sfc, struct wl_resource *parent,
struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y, uint32_t flags)
{
- printf("xshell_get_xdg_popup\n");
+ win_t *win = wl_resource_get_user_data(sfc);
+ printf("xshell_get_xdg_popup - %p @ %d,%d\n", win, x, y);
+
struct wl_resource *res = wl_resource_create(cli, &xdg_popup_interface, 1, id);
- wl_resource_set_implementation(res, &xpopup_iface, NULL, NULL);
+ wl_resource_set_implementation(res, &xpopup_iface, win, NULL);
+
+ win_t *par = wl_resource_get_user_data(parent);
+ win->type = TYPE_POPUP;
+ win->parent = par;
+ win->x = x;
+ win->y = y;
}
-static void xshell_pong(struct wl_client *cli, struct wl_resource *gshell,
+static void xshell_pong(struct wl_client *cli, struct wl_resource *xshell,
uint32_t serial)
{
printf("xshell_pong\n");
wl_resource_set_implementation(res, &gshell_iface, NULL, NULL);
}
+/*****************
+ * Gtk Callbacks *
+ *****************/
+
+static void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer user_data)
+{
+ printf("on_destroy\n");
+ sys_exit();
+}
+
+static gboolean on_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
+{
+ /* Handle special keys */
+ if (event->state & GDK_CONTROL_MASK &&
+ event->type == GDK_KEY_PRESS &&
+ event->keyval == GDK_KEY_Return)
+ g_spawn_command_line_async("vte2_90", NULL);
+
+ /* Send key to WM */
+ if (focus) {
+ event_t ev = tolower(event->keyval);
+ mod_t mod = get_mod(event->state, event->type == GDK_KEY_RELEASE);
+ ptr_t ptr = get_ptr(focus);
+ if (wm_handle_event(focus, ev, mod, ptr))
+ return TRUE;
+ }
+
+ /* Skip if no focused window */
+ if (!focus || !focus->sys->cdata)
+ return FALSE;
+
+ /* Send key to wayland */
+ printf(g_ascii_isprint(event->keyval)
+ ? "on_key - win=%p cdata=%p '%c'\n"
+ : "on_key - win=%p cdata=%p 0x%X\n",
+ focus, focus?focus->sys->cdata:0, event->keyval);
+ for (list_t *cur = focus->sys->cdata->kbds; cur; cur = cur->next) {
+ uint32_t serial = get_serial();
+ uint32_t stamp = get_time();
+ uint32_t key = event->hardware_keycode-8;
+ uint32_t state = event->type == GDK_KEY_PRESS
+ ? WL_KEYBOARD_KEY_STATE_PRESSED
+ : WL_KEYBOARD_KEY_STATE_RELEASED;
+ wl_keyboard_send_key(cur->data, serial, stamp, key, state);
+ printf(" send -> %p tm=%d key=%d state=%d\n",
+ cur->data, stamp, key, state);
+ }
+ return TRUE;
+}
+
+static gboolean on_button(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+ win_t *win = find_win(event->x, event->y);
+ printf("on_button - win=%p cdata=%p\n",
+ win, win?win->sys->cdata:0);
+ if (!win || !win->sys->cdata)
+ return FALSE;
+ for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next) {
+ uint32_t serial = get_serial();
+ uint32_t stamp = get_time();
+ uint32_t button = BTN_MOUSE+(event->button-1);
+ uint32_t state = event->type == GDK_BUTTON_PRESS
+ ? WL_POINTER_BUTTON_STATE_PRESSED
+ : WL_POINTER_BUTTON_STATE_RELEASED;
+ wl_pointer_send_button(cur->data, serial, stamp, button, state);
+ printf(" send -> %p tm=%d btn=%d state=%d\n",
+ cur->data, stamp, button, state);
+ }
+ return TRUE;
+}
+
+static gboolean on_move(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
+{
+ win_t *win = find_win(event->x, event->y);
+ if (!win)
+ return FALSE;
+
+ /* Queue draw event for cursor */
+ gtk_widget_queue_draw(screen);
+
+ /* Save cursor position */
+ cursor_x = event->x;
+ cursor_y = event->y;
+
+ /* Send enter/leave */
+ if (win != hover) {
+ wm_handle_event(hover, EV_LEAVE, MOD(), PTR());
+ wm_handle_event(win, EV_ENTER, MOD(), PTR());
+ hover = win;
+ }
+
+ /* Sent pointer to WM */
+ if (wm_handle_ptr(win, get_ptr(win)))
+ return TRUE;
+
+ /* Send motion event to window */
+ uint32_t t = get_time();
+ wl_fixed_t x = wl_fixed_from_double(cursor_x - win->x);
+ wl_fixed_t y = wl_fixed_from_double(cursor_y - win->y);
+ for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next)
+ wl_pointer_send_motion(cur->data, t, x, y);
+ return TRUE;
+}
+
+static void on_size(GtkWidget *widget, GtkAllocation *alloc, gpointer user_data)
+{
+ printf("on_size - %dx%d\n", alloc->width, alloc->height);
+ root->w = alloc->width;
+ root->h = alloc->height;
+}
+
+static gboolean on_draw(GtkWidget *widget, cairo_t *cairo, gpointer user_data)
+{
+ printf("on_draw\n");
+
+ //wm_update(); // Hacks for now
+
+ /* Draw windows bottom up */
+ list_t *bottom = list_last(windows);
+ for (list_t *cur = bottom; cur; cur = cur->prev) {
+ win_t *win = cur->data;
+ if (win->sys->buf == NULL)
+ continue;
+ if (win->type == TYPE_CURSOR)
+ continue;
+ sys_bdata_t *bdata = wl_resource_get_user_data(win->sys->buf);
+ int x = win->x;
+ int y = win->y;
+ if (win->type == TYPE_POPUP && win->parent) {
+ x += win->parent->x;
+ y += win->parent->y;
+ }
+ //if (win->sys->wx) x -= win->sys->wx;
+ //if (win->sys->wy) y -= win->sys->wy;
+ printf(" win = %p %dx%d @ %d,%d\n",
+ win, win->w, win->h, x, y);
+ cairo_surface_mark_dirty(bdata->surface);
+ cairo_set_source_surface(cairo, bdata->surface, x, y);
+ cairo_paint(cairo);
+ //wl_buffer_send_release(win->sys->buf);
+ //win->sys->buf = 0;
+ }
+
+ /* Draw cursor */
+ if (cursor && cursor->sys->buf) {
+ int x = cursor_x, y = cursor_y;
+ sys_bdata_t *bdata = wl_resource_get_user_data(cursor->sys->buf);
+ cairo_surface_mark_dirty(bdata->surface);
+ cairo_set_source_surface(cairo, bdata->surface, x, y);
+ cairo_paint(cairo);
+ }
+
+ return TRUE;
+}
+
+static gboolean on_wayland(gpointer user_data)
+{
+ // TODO - convert to polled execution
+ wl_display_flush_clients(display);
+ wl_event_loop_dispatch(events, 0);
+ return TRUE;
+}
+
/********************
* System functions *
********************/
void sys_move(win_t *win, int x, int y, int w, int h)
{
+ if (win->x == x && win->y == y &&
+ win->w == w && win->h == h)
+ return;
printf("sys_move: %p - %d,%d %dx%d\n",
win, x, y, w, h);
+
+ win->x = x;
+ win->y = y;
+ win->w = w;
+ win->h = h;
+
+ if (win->sys->ssfc)
+ wl_shell_surface_send_configure(win->sys->ssfc,
+ WL_SHELL_SURFACE_RESIZE_NONE, w, h);
+
+ if (win->sys->xsfc)
+ xdg_surface_send_configure(win->sys->xsfc, w, h,
+ (win == focus) ? &xstate_active : &xstate_normal,
+ get_serial());
+
+ gtk_widget_queue_draw(screen);
}
void sys_raise(win_t *win)
void sys_focus(win_t *win)
{
+ if (win == focus)
+ return;
printf("sys_focus: %p\n", win);
+
+ /* Send leave event */
+ uint32_t s = get_serial();
+ wl_fixed_t x = wl_fixed_from_double(cursor_x - win->x);
+ wl_fixed_t y = wl_fixed_from_double(cursor_y - win->y);
+ if (focus && focus->sys->sfc && focus->sys->cdata) {
+ printf("sys_focus - leave win=%p\n", focus);
+ for (list_t *cur = focus->sys->cdata->ptrs; cur; cur = cur->next)
+ wl_pointer_send_leave(cur->data, s, focus->sys->sfc);
+ for (list_t *cur = focus->sys->cdata->kbds; cur; cur = cur->next)
+ wl_keyboard_send_leave(cur->data, s, focus->sys->sfc);
+ if (focus->sys->xsfc)
+ xdg_surface_send_configure(focus->sys->xsfc, focus->w, focus->h,
+ &xstate_normal, get_serial());
+ }
+ if (win && win->sys->sfc && win->sys->cdata) {
+ printf("sys_focus - enter win=%p\n", win);
+ for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next)
+ wl_pointer_send_enter(cur->data, s, win->sys->sfc, x, y);
+ for (list_t *cur = win->sys->cdata->kbds; cur; cur = cur->next)
+ wl_keyboard_send_enter(cur->data, s, win->sys->sfc, &keys);
+ if (win->sys->xsfc)
+ xdg_surface_send_configure(win->sys->xsfc, win->w, win->h,
+ &xstate_active, get_serial());
+ }
+
+ /* Update focused window */
+ focus = win;
}
void sys_show(win_t *win, state_t state)
{
printf("sys_init\n");
+ /* Create root window */
+ root = new0(win_t);
+ root->x = 0;
+ root->y = 0;
+ root->w = 800;
+ root->h = 600;
+
+ /* Initalize constants */
+ set_array(&xstate_normal, 0);
+ set_array(&xstate_active, 1,
+ XDG_SURFACE_STATE_ACTIVATED);
+ set_array(&xstate_max,2,
+ XDG_SURFACE_STATE_ACTIVATED,
+ XDG_SURFACE_STATE_MAXIMIZED);
+ set_array(&xstate_full, 2,
+ XDG_SURFACE_STATE_ACTIVATED,
+ XDG_SURFACE_STATE_FULLSCREEN);
+ set_array(&xstate_resize, 2,
+ XDG_SURFACE_STATE_ACTIVATED,
+ XDG_SURFACE_STATE_RESIZING);
+
/* Register log handler */
wl_log_set_handler_server((wl_log_func_t)vprintf);
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK);
- g_signal_connect(screen, "destroy", G_CALLBACK(on_destroy), NULL);
- g_signal_connect(screen, "key-press-event", G_CALLBACK(on_key), NULL);
- g_signal_connect(screen, "button-press-event", G_CALLBACK(on_button), NULL);
- g_signal_connect(screen, "motion-notify-event", G_CALLBACK(on_move), NULL);
- g_signal_connect(screen, "draw", G_CALLBACK(on_draw), NULL);
+ g_signal_connect(screen, "destroy", G_CALLBACK(on_destroy), NULL);
+ g_signal_connect(screen, "key-press-event", G_CALLBACK(on_key), NULL);
+ g_signal_connect(screen, "key-release-event", G_CALLBACK(on_key), NULL);
+ g_signal_connect(screen, "button-press-event", G_CALLBACK(on_button), NULL);
+ g_signal_connect(screen, "button-release-event", G_CALLBACK(on_button), NULL);
+ g_signal_connect(screen, "motion-notify-event", G_CALLBACK(on_move), NULL);
+ g_signal_connect(screen, "size-allocate", G_CALLBACK(on_size), NULL);
+ g_signal_connect(screen, "draw", G_CALLBACK(on_draw), NULL);
g_timeout_add(1000/60, on_wayland, NULL);
gtk_widget_show(screen);
- return new0(win_t);
+ /* Setup environment */
+ setenv("GDK_BACKEND", "wayland", 1);
+
+ return root;
}
void sys_run(win_t *root)