2 * Copyright (c) 2014-2015 Andy Spencer <andy753421@gmail.com>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
26 #include <libevdev/libevdev.h>
27 #include <xkbcommon/xkbcommon.h>
28 #include <wayland-server.h>
29 #include <wayland-client.h>
38 #include "xdg-shell-client-protocol.h"
39 #include "xdg-shell-server-protocol.h"
40 #include "gtk-shell-client-protocol.h"
41 #include "gtk-shell-server-protocol.h"
43 /* Window Managers calls */
46 /* Wayland user data */
55 cairo_surface_t *surface;
59 struct wl_client *cli;
60 list_t *ptrs; // of struct wl_resource
61 list_t *kbds; // of struct wl_resource
62 list_t *tchs; // of struct wl_resource
65 /* Internal structures */
67 struct wl_resource *sfc;
68 struct wl_resource *ssfc;
69 struct wl_resource *xsfc;
70 struct wl_resource *buf;
72 int x,y; // surface x,y
73 int wx,wy; // window x,y inside sfc
74 int ww,wh; // window w,h inside sfc
78 static win_t *root; // root window
79 static win_t *hover; // window the mouse is over
80 static win_t *focus; // focused window
81 static win_t *cursor; // mouse cursor image
83 static list_t *clients; // of sys_cdata_t
84 static list_t *windows; // of win_t
86 static double cursor_x;
87 static double cursor_y;
88 static double cursor_dx;
89 static double cursor_dy;
91 static GtkWidget *screen;
93 static struct wl_resource *output;
94 static struct wl_display *display;
95 static struct wl_event_loop *events;
97 static struct wl_array keys;
100 static struct wl_array xstate_normal;
101 static struct wl_array xstate_active;
102 static struct wl_array xstate_max;
103 static struct wl_array xstate_full;
104 static struct wl_array xstate_resize;
106 /********************
108 ********************/
110 static void set_array(struct wl_array *array, int n, ...)
114 wl_array_init(array);
115 for (int i = 0; i < n; i++) {
116 uint32_t item = va_arg(ap, uint32_t);
117 uint32_t *ptr = wl_array_add(array, sizeof(item));
119 error("Unable to allocate constant");
125 static int get_serial(void)
127 static int serial = 0;
131 static int get_time(void)
133 static uint64_t epoch;
136 clock_gettime(CLOCK_REALTIME, &ts);
138 uint64_t now = (((uint64_t)ts.tv_sec ) * 1000)
139 + (((uint64_t)ts.tv_nsec) / 1000000);
144 return (int)(now - epoch);
147 static ptr_t get_ptr(win_t *win)
154 ptr.x = cursor_x - win->x;
155 ptr.y = cursor_y - win->y;
160 static mod_t get_mod(unsigned int state, int up)
163 .alt = !!(state & GDK_MOD1_MASK ),
164 .ctrl = !!(state & GDK_CONTROL_MASK),
165 .shift = !!(state & GDK_SHIFT_MASK ),
166 .win = !!(state & GDK_MOD4_MASK ),
171 static win_t *find_win(int x, int y)
173 for (list_t *cur = windows; cur; cur = cur->next) {
174 win_t *win = cur->data;
175 printf("find_win -- %p -- %4d,%-4d : %4dx%-4d\n",
176 win, win->x, win->y, win->w, win->h);
178 for (list_t *cur = windows; cur; cur = cur->next) {
179 win_t *win = cur->data;
184 if (l <= x && x <= r && t <= y && y <= b) {
185 printf("find_win -> %p\n", win);
192 static sys_cdata_t *find_cdata(struct wl_client *cli)
194 // Search for existing client
195 for (list_t *cur = clients; cur; cur = cur->next) {
196 sys_cdata_t *cdata = cur->data;
197 if (cdata->cli == cli)
201 // Not found, create new one
202 sys_cdata_t *cdata = new0(sys_cdata_t);
203 clients = list_insert(clients, cdata);
208 /****************************
209 * Wayland Buffer Interface *
210 ****************************/
211 static void buffer_destroy(struct wl_client *cli, struct wl_resource *reso)
213 printf("buffer_destroy\n");
216 static struct wl_buffer_interface buffer_iface = {
217 .destroy = buffer_destroy,
220 /***********************************
221 * Wayland Shared Memory Interface *
222 ***********************************/
225 static void pool_create_buffer(struct wl_client *cli, struct wl_resource *pool,
226 uint32_t id, int32_t offset, int32_t width, int32_t height,
227 int32_t stride, uint32_t format)
229 sys_bdata_t *bdata = new0(sys_bdata_t);
230 bdata->pool = wl_resource_get_user_data(pool);
231 bdata->mem = bdata->pool->mem + offset;
233 printf("pool_create_buffer - %dx%d %p+%d : %d,%d,%d\n",
234 width, height, bdata->pool->mem, offset, id, stride, format);
236 if (offset > bdata->pool->size || offset < 0)
238 printf("\n\nerror\n\n");
239 wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_STRIDE,
240 "offset is too big or negative");
245 format == WL_SHM_FORMAT_ARGB8888 ? CAIRO_FORMAT_ARGB32 :
246 format == WL_SHM_FORMAT_XRGB8888 ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_INVALID;
248 bdata->surface = cairo_image_surface_create_for_data(bdata->mem, cf, width, height, stride);
250 struct wl_resource *res = wl_resource_create(cli, &wl_buffer_interface,
251 wl_resource_get_version(pool), id);
252 wl_resource_set_implementation(res, &buffer_iface, bdata, NULL);
255 static void pool_destroy(struct wl_client *cli, struct wl_resource *pool)
257 printf("pool_destroy\n");
260 static void pool_resize(struct wl_client *cli, struct wl_resource *pool,
263 printf("[ WMPUS ] pool_resize - %d\n", size);
264 sys_pool_t *data = wl_resource_get_user_data(pool);
265 void *ptr = mremap(data->mem, data->size, size, MREMAP_MAYMOVE);
266 if (ptr == MAP_FAILED)
268 printf("\n\nerror\n\n");
269 wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_FD,
270 "mremap failed: %s", strerror(errno));
277 static struct wl_shm_pool_interface pool_iface = {
278 .create_buffer = &pool_create_buffer,
279 .destroy = &pool_destroy,
280 .resize = &pool_resize,
284 static void shm_create_pool(struct wl_client *cli, struct wl_resource *shm,
285 uint32_t id, int32_t fd, int32_t size)
287 printf("shm_create_pool - #%d %d %d\n", id, fd, size);
289 sys_pool_t *data = new0(sys_pool_t);
291 struct wl_resource *res = wl_resource_create(cli, &wl_shm_pool_interface,
292 wl_resource_get_version(shm), id);
293 wl_resource_set_implementation(res, &pool_iface, data, NULL);
295 data->mem = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
299 static struct wl_shm_interface shm_iface = {
300 .create_pool = shm_create_pool,
303 /**************************
304 * Wayland Seat Interface *
305 **************************/
308 static void pointer_kill(struct wl_resource *ptr)
310 sys_cdata_t *cdata = wl_resource_get_user_data(ptr);
311 list_t *link = list_find(cdata->ptrs, ptr);
312 cdata->ptrs = list_remove(cdata->ptrs, link, 0);
313 if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
314 list_t *clink = list_find(clients, cdata);
315 clients = list_remove(clients, clink, 1);
319 static void pointer_set_cursor(struct wl_client *cli, struct wl_resource *ptr,
320 uint32_t serial, struct wl_resource *sfc,
321 int32_t hotspot_x, int32_t hotspot_y)
323 printf("pointer_set_cursor %d,%d\n", hotspot_x, hotspot_y);
324 win_t *win = wl_resource_get_user_data(sfc);
325 win->type = TYPE_CURSOR;
326 cursor_dx = hotspot_x;
327 cursor_dy = hotspot_y;
331 static void pointer_release(struct wl_client *cli, struct wl_resource *ptr)
333 printf("pointer_release\n");
336 static struct wl_pointer_interface pointer_iface = {
337 .set_cursor = pointer_set_cursor,
338 .release = pointer_release,
342 static void keyboard_kill(struct wl_resource *kbd)
344 sys_cdata_t *cdata = wl_resource_get_user_data(kbd);
345 list_t *link = list_find(cdata->kbds, kbd);
346 cdata->kbds = list_remove(cdata->kbds, link, 0);
347 if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
348 list_t *clink = list_find(clients, cdata);
349 clients = list_remove(clients, clink, 1);
353 static void keyboard_release(struct wl_client *cli, struct wl_resource *kbd)
355 printf("keyboard_release\n");
358 static struct wl_keyboard_interface keyboard_iface = {
359 .release = keyboard_release,
363 static void touch_kill(struct wl_resource *tch)
365 sys_cdata_t *cdata = wl_resource_get_user_data(tch);
366 list_t *link = list_find(cdata->tchs, tch);
367 cdata->tchs = list_remove(cdata->tchs, link, 0);
368 if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
369 list_t *clink = list_find(clients, cdata);
370 clients = list_remove(clients, clink, 1);
374 static void touch_release(struct wl_client *cli, struct wl_resource *tch)
376 printf("touch_release\n");
379 static struct wl_touch_interface touch_iface = {
380 .release = touch_release,
384 static void seat_get_pointer(struct wl_client *cli, struct wl_resource *seat,
386 sys_cdata_t *cdata = find_cdata(cli);
387 struct wl_resource *res = wl_resource_create(cli, &wl_pointer_interface, 3, id);
388 wl_resource_set_implementation(res, &pointer_iface, cdata, pointer_kill);
389 cdata->ptrs = list_insert(cdata->ptrs, res);
390 printf("seat_get_pointer - cli=%p cdata=%p ptr=%p\n", cli, cdata, res);
393 static void seat_get_keyboard(struct wl_client *cli, struct wl_resource *seat,
395 sys_cdata_t *cdata = find_cdata(cli);
396 struct wl_resource *res = wl_resource_create(cli, &wl_keyboard_interface, 4, id);
397 wl_resource_set_implementation(res, &keyboard_iface, cdata, keyboard_kill);
399 //map = xkb_keymap_new_from_names(xkb->context, NULL, 0);
400 //xkb->context = xkb_context_new(0);
401 //xkb->keymap.map = xkb_keymap_new_from_names(xkb->context, NULL, 0);
402 //wl_keyboard_send_keymap(cli, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
403 // keyboard->xkb.keymap.fd,
404 // keyboard->xkb.keymap.size - 1);
406 cdata->kbds = list_insert(cdata->kbds, res);
407 printf("seat_get_keyboard - cli=%p cdata=%p kbd=%p\n", cli, cdata, res);
410 static void seat_get_touch(struct wl_client *cli, struct wl_resource *seat,
412 sys_cdata_t *cdata = find_cdata(cli);
413 struct wl_resource *res = wl_resource_create(cli, &wl_touch_interface, 3, id);
414 wl_resource_set_implementation(res, &touch_iface, cdata, touch_kill);
415 cdata->tchs = list_insert(cdata->tchs, res);
416 printf("seat_get_touch - cli=%p cdata=%p tch=%p\n", cli, cdata, res);
419 static struct wl_seat_interface seat_iface = {
420 .get_pointer = &seat_get_pointer,
421 .get_keyboard = &seat_get_keyboard,
422 .get_touch = &seat_get_touch,
425 /*****************************************
426 * Wayland Data Device Manager Interface *
427 *****************************************/
430 static void doff_accept(struct wl_client *cli, struct wl_resource *doff,
431 uint32_t serial, const char *mime_type)
433 printf("doff_accept\n");
436 static void doff_receive(struct wl_client *cli, struct wl_resource *doff,
437 const char *mime_type, int32_t fd)
439 printf("doff_receive\n");
442 static void doff_destroy(struct wl_client *cli, struct wl_resource *doff)
444 printf("doff_destroy\n");
447 static struct wl_data_offer_interface doff_iface = {
448 .accept = doff_accept,
449 .receive = doff_receive,
450 .destroy = doff_destroy,
454 static void dsrc_offer(struct wl_client *cli, struct wl_resource *dsrc,
455 const char *mime_type)
458 printf("dsrc_offer\n");
461 static void dsrc_destroy(struct wl_client *cli, struct wl_resource *dsrc)
463 printf("dsrc_destroy\n");
466 static struct wl_data_source_interface dsrc_iface = {
468 .destroy = dsrc_destroy,
472 static void ddev_start_drag(struct wl_client *cli, struct wl_resource *dsrc,
473 struct wl_resource *source, struct wl_resource *origin,
474 struct wl_resource *icon, uint32_t serial)
476 printf("start_drag\n");
479 static void ddev_set_selection(struct wl_client *cli, struct wl_resource *dsrc,
480 struct wl_resource *source, uint32_t serial)
482 printf("set_selection\n");
485 static struct wl_data_device_interface ddev_iface = {
486 .start_drag = ddev_start_drag,
487 .set_selection = ddev_set_selection,
490 /* Data Device Manager */
491 static void ddm_create_data_source(struct wl_client *cli, struct wl_resource *ddm,
494 printf("ddm_create_data_source\n");
495 struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
496 wl_resource_set_implementation(res, &dsrc_iface, NULL, NULL);
499 static void ddm_get_data_device(struct wl_client *cli, struct wl_resource *ddm,
500 uint32_t id, struct wl_resource *seat)
502 printf("ddm_get_data_device\n");
503 struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
504 wl_resource_set_implementation(res, &ddev_iface, NULL, NULL);
507 static struct wl_data_device_manager_interface ddm_iface = {
508 .create_data_source = &ddm_create_data_source,
509 .get_data_device = &ddm_get_data_device,
512 /**************************************
513 * Wayland Shell/Compositor Interface *
514 **************************************/
517 static void surface_kill(struct wl_resource *sfc)
519 win_t *win = wl_resource_get_user_data(sfc);
520 list_t *link = list_find(windows, win);
521 printf("surface_kill - %p\n", win);
522 if (win == NULL) return;
523 if (win == hover) hover = NULL;
524 if (win == focus) focus = NULL;
525 if (win == cursor) cursor = NULL;
528 windows = list_remove(windows, link, 0);
529 wl_resource_set_user_data(sfc, NULL);
530 gtk_widget_queue_draw(screen);
533 static void surface_destroy(struct wl_client *cli, struct wl_resource *sfc)
535 printf("surface_destroy\n");
539 static void surface_attach(struct wl_client *cli, struct wl_resource *sfc,
540 struct wl_resource *buf, int32_t x, int32_t y)
542 win_t *win = wl_resource_get_user_data(sfc);
543 printf("surface_attach - %p - %d,%d\n", buf, x, y);
549 static void surface_damage(struct wl_client *cli, struct wl_resource *sfc,
550 int32_t x, int32_t y, int32_t width, int32_t height)
552 printf("surface_damage\n");
555 static void surface_frame(struct wl_client *cli, struct wl_resource *sfc,
558 printf("surface_frame\n");
559 struct wl_resource *cb = wl_resource_create(cli, &wl_callback_interface, 1, id);
560 wl_resource_set_implementation(cb, NULL, NULL, NULL);
561 wl_callback_send_done(cb, get_time());
564 static void surface_set_opaque_region(struct wl_client *cli, struct wl_resource *sfc,
565 struct wl_resource *reg)
567 printf("surface_set_opaque_region\n");
570 static void surface_set_input_region(struct wl_client *cli, struct wl_resource *sfc,
571 struct wl_resource *reg)
573 printf("surface_set_input_region\n");
576 static void surface_commit(struct wl_client *cli, struct wl_resource *sfc)
578 printf("surface_commit\n");
579 gtk_widget_queue_draw(screen);
582 static void surface_set_buffer_transform(struct wl_client *cli, struct wl_resource *sfc,
585 printf("surface_set_buffer_transform\n");
588 static void surface_set_buffer_scale(struct wl_client *cli, struct wl_resource *sfc,
591 printf("surface_set_buffer_scale\n");
594 static struct wl_surface_interface surface_iface = {
595 .destroy = surface_destroy,
596 .attach = surface_attach,
597 .damage = surface_damage,
598 .frame = surface_frame,
599 .set_opaque_region = surface_set_opaque_region,
600 .set_input_region = surface_set_input_region,
601 .commit = surface_commit,
602 .set_buffer_transform = surface_set_buffer_transform,
603 .set_buffer_scale = surface_set_buffer_scale,
607 static void region_destroy(struct wl_client *cli, struct wl_resource *reg)
609 printf("region_destroy\n");
612 static void region_add(struct wl_client *cli, struct wl_resource *reg,
613 int32_t x, int32_t y, int32_t width, int32_t height)
615 printf("region_add\n");
618 static void region_subtract(struct wl_client *cli, struct wl_resource *reg,
619 int32_t x, int32_t y, int32_t width, int32_t height)
621 printf("region_subtract\n");
624 static struct wl_region_interface region_iface = {
625 .destroy = region_destroy,
627 .subtract = region_subtract,
631 static void comp_create_surface(struct wl_client *cli, struct wl_resource *comp,
634 win_t *win = new0(win_t);
635 win->sys = new0(win_sys_t);
637 struct wl_resource *res = wl_resource_create(cli, &wl_surface_interface, 3, id);
638 wl_resource_set_implementation(res, &surface_iface, win, surface_kill);
639 wl_surface_send_enter(res, output);
642 win->sys->cdata = find_cdata(cli);
644 windows = list_insert(windows, win);
646 printf("comp_create_surface - cli=%p win=%p cdata=%p\n",
647 cli, win, win->sys->cdata);
650 static void comp_create_region(struct wl_client *cli, struct wl_resource *comp,
653 printf("comp_create_region\n");
654 struct wl_resource *res = wl_resource_create(cli, &wl_region_interface, 1, id);
655 wl_resource_set_implementation(res, ®ion_iface, NULL, NULL);
658 static struct wl_compositor_interface comp_iface = {
659 .create_surface = comp_create_surface,
660 .create_region = comp_create_region,
664 static void ssurface_kill(struct wl_resource *ssfc)
666 win_t *win = wl_resource_get_user_data(ssfc);
667 printf("ssurface_kill - %p\n", win);
668 win->sys->ssfc = NULL;
673 static void ssurface_pong(struct wl_client *cli, struct wl_resource *ssfc,
676 printf("ssurface_pong\n");
679 static void ssurface_move(struct wl_client *cli, struct wl_resource *ssfc,
680 struct wl_resource *seat, uint32_t serial)
682 printf("ssurface_move\n");
685 static void ssurface_resize(struct wl_client *cli, struct wl_resource *ssfc,
686 struct wl_resource *seat, uint32_t serial, uint32_t edges)
688 printf("ssurface_resize\n");
691 static void ssurface_set_toplevel(struct wl_client *cli, struct wl_resource *ssfc)
693 printf("ssurface_set_toplevel\n");
696 static void ssurface_set_transient(struct wl_client *cli, struct wl_resource *ssfc,
697 struct wl_resource *parent, int32_t x, int32_t y, uint32_t flags)
699 printf("ssurface_set_transient\n");
702 static void ssurface_set_fullscreen(struct wl_client *cli, struct wl_resource *ssfc,
703 uint32_t method, uint32_t framerate, struct wl_resource *out)
705 printf("ssurface_set_fullscreen\n");
708 static void ssurface_set_popup(struct wl_client *cli, struct wl_resource *ssfc,
709 struct wl_resource *seat, uint32_t serial, struct wl_resource *parent,
710 int32_t x, int32_t y, uint32_t flags)
712 printf("ssurface_set_popup\n");
715 static void ssurface_set_maximized(struct wl_client *cli, struct wl_resource *ssfc,
716 struct wl_resource *out)
718 printf("ssurface_set_maximized\n");
721 static void ssurface_set_title(struct wl_client *cli, struct wl_resource *ssfc,
724 printf("ssurface_set_title\n");
727 static void ssurface_set_class(struct wl_client *cli, struct wl_resource *ssfc,
730 printf("ssurface_set_class\n");
733 static struct wl_shell_surface_interface ssurface_iface = {
734 .pong = ssurface_pong,
735 .move = ssurface_move,
736 .resize = ssurface_resize,
737 .set_toplevel = ssurface_set_toplevel,
738 .set_transient = ssurface_set_transient,
739 .set_fullscreen = ssurface_set_fullscreen,
740 .set_popup = ssurface_set_popup,
741 .set_maximized = ssurface_set_maximized,
742 .set_title = ssurface_set_title,
743 .set_class = ssurface_set_class,
747 static void shell_get_shell_surface(struct wl_client *cli, struct wl_resource *shell, uint32_t id,
748 struct wl_resource *sfc) {
749 win_t *win = wl_resource_get_user_data(sfc);
750 printf("shell_get_shell_surface - %p\n", win);
752 struct wl_resource *res = wl_resource_create(cli, &wl_shell_surface_interface, 1, id);
753 wl_resource_set_implementation(res, &ssurface_iface, win, ssurface_kill);
755 win->type = TYPE_NORMAL;
756 win->sys->ssfc = res;
760 static struct wl_shell_interface shell_iface = {
761 .get_shell_surface = shell_get_shell_surface,
765 static void xpopup_destroy(struct wl_client *cli, struct wl_resource *xpopup)
767 printf("xpopup_destroy\n");
770 static struct xdg_popup_interface xpopup_iface = {
771 .destroy = xpopup_destroy,
775 static void xsurface_kill(struct wl_resource *xsfc)
777 win_t *win = wl_resource_get_user_data(xsfc);
778 printf("xsurface_kill - %p\n", win);
781 win->sys->xsfc = NULL;
786 static void xsurface_destroy(struct wl_client *cli, struct wl_resource *xsfc)
788 printf("xsurface_destroy\n");
792 static void xsurface_set_parent(struct wl_client *cli, struct wl_resource *xsfc,
793 struct wl_resource *parent)
795 win_t *win = wl_resource_get_user_data(xsfc);
796 printf("xsurface_set_parent - %p\n", win);
797 //win->type = TYPE_DIALOG;
800 static void xsurface_set_title(struct wl_client *cli, struct wl_resource *xsfc,
803 printf("xsurface_set_title\n");
806 static void xsurface_set_app_id(struct wl_client *cli, struct wl_resource *xsfc,
809 printf("xsurface_set_app_id\n");
812 static void xsurface_show_window_menu(struct wl_client *cli, struct wl_resource *xsfc,
813 struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y)
815 printf("xsurface_show_window_menu\n");
818 static void xsurface_move(struct wl_client *cli, struct wl_resource *xsfc,
819 struct wl_resource *seat, uint32_t serial)
821 printf("xsurface_move\n");
824 static void xsurface_resize(struct wl_client *cli, struct wl_resource *xsfc,
825 struct wl_resource *seat, uint32_t serial, uint32_t edges)
827 printf("xsurface_resize\n");
830 static void xsurface_ack_configure(struct wl_client *cli, struct wl_resource *xsfc,
833 printf("xsurface_ack_configure\n");
836 static void xsurface_set_window_geometry(struct wl_client *cli, struct wl_resource *xsfc,
837 int32_t x, int32_t y, int32_t width, int32_t height)
839 win_t *win = wl_resource_get_user_data(xsfc);
840 printf("xsurface_set_window_geometry - %p\n", win);
843 win->sys->ww = width;
844 win->sys->wh = height;
847 static void xsurface_set_maximized(struct wl_client *cli, struct wl_resource *xsfc)
849 printf("xsurface_set_maximized\n");
852 static void xsurface_unset_maximized(struct wl_client *cli, struct wl_resource *xsfc)
854 printf("xsurface_unset_maximized\n");
857 static void xsurface_set_fullscreen(struct wl_client *cli, struct wl_resource *xsfc,
858 struct wl_resource *output)
860 printf("xsurface_set_fullscreen\n");
863 static void xsurface_unset_fullscreen(struct wl_client *cli, struct wl_resource *xsfc)
865 printf("xsurface_unset_fullscreen\n");
868 static void xsurface_set_minimized(struct wl_client *cli, struct wl_resource *xsfc)
870 printf("xsurface_set_minimized\n");
873 static struct xdg_surface_interface xsurface_iface = {
874 .destroy = xsurface_destroy,
875 .set_parent = xsurface_set_parent,
876 .set_title = xsurface_set_title,
877 .set_app_id = xsurface_set_app_id,
878 .show_window_menu = xsurface_show_window_menu,
879 .move = xsurface_move,
880 .resize = xsurface_resize,
881 .ack_configure = xsurface_ack_configure,
882 .set_window_geometry = xsurface_set_window_geometry,
883 .set_maximized = xsurface_set_maximized,
884 .unset_maximized = xsurface_unset_maximized,
885 .set_fullscreen = xsurface_set_fullscreen,
886 .unset_fullscreen = xsurface_unset_fullscreen,
887 .set_minimized = xsurface_set_minimized,
891 static void xshell_use_unstable_version(struct wl_client *cli, struct wl_resource *xshell,
894 printf("xshell_use_unstable_version\n");
897 static void xshell_get_xdg_surface(struct wl_client *cli, struct wl_resource *xshell,
898 uint32_t id, struct wl_resource *sfc)
900 win_t *win = wl_resource_get_user_data(sfc);
901 printf("xshell_get_xdg_surface - %p\n", win);
903 struct wl_resource *res = wl_resource_create(cli, &xdg_surface_interface, 1, id);
904 wl_resource_set_implementation(res, &xsurface_iface, win, xsurface_kill);
906 win->type = TYPE_NORMAL;
907 win->sys->xsfc = res;
911 static void xshell_get_xdg_popup(struct wl_client *cli, struct wl_resource *xshell,
912 uint32_t id, struct wl_resource *sfc, struct wl_resource *parent,
913 struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y, uint32_t flags)
915 win_t *win = wl_resource_get_user_data(sfc);
916 printf("xshell_get_xdg_popup - %p @ %d,%d\n", win, x, y);
918 struct wl_resource *res = wl_resource_create(cli, &xdg_popup_interface, 1, id);
919 wl_resource_set_implementation(res, &xpopup_iface, win, NULL);
921 win_t *par = wl_resource_get_user_data(parent);
922 win->type = TYPE_POPUP;
928 static void xshell_pong(struct wl_client *cli, struct wl_resource *xshell,
931 printf("xshell_pong\n");
934 static struct xdg_shell_interface xshell_iface = {
935 .use_unstable_version = xshell_use_unstable_version,
936 .get_xdg_surface = xshell_get_xdg_surface,
937 .get_xdg_popup = xshell_get_xdg_popup,
942 static void gsurface_set_dbus_properties(struct wl_client *cli, struct wl_resource *gsfc,
943 const char *application_id, const char *app_menu_path,
944 const char *menubar_path, const char *window_object_path,
945 const char *application_object_path, const char *unique_bus_name)
947 printf("gsurface_set_dbus_properties\n");
950 static struct gtk_surface_interface gsurface_iface = {
951 .set_dbus_properties = gsurface_set_dbus_properties,
955 static void gshell_get_gtk_surface(struct wl_client *cli, struct wl_resource *gshell,
956 uint32_t id, struct wl_resource *sfc)
958 printf("gshell_get_gtk_surface\n");
959 struct wl_resource *res = wl_resource_create(cli, >k_surface_interface, 1, id);
960 wl_resource_set_implementation(res, &gsurface_iface, NULL, NULL);
963 static struct gtk_shell_interface gshell_iface = {
964 .get_gtk_surface = gshell_get_gtk_surface,
972 static struct wl_global *ref_shm;
973 static struct wl_global *ref_output;
974 static struct wl_global *ref_seat;
975 static struct wl_global *ref_ddm;
976 static struct wl_global *ref_comp;
977 static struct wl_global *ref_shell;
978 static struct wl_global *ref_xshell;
979 static struct wl_global *ref_gshell;
982 static void bind_shm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
984 printf("bind_shm\n");
989 struct wl_resource *res = wl_resource_create(cli, &wl_shm_interface, version, id);
990 wl_resource_set_implementation(res, &shm_iface, NULL, NULL);
992 wl_shm_send_format(res, WL_SHM_FORMAT_XRGB8888);
993 wl_shm_send_format(res, WL_SHM_FORMAT_ARGB8888);
996 static void bind_output(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
998 printf("bind_output\n");
1000 struct wl_resource *res = wl_resource_create(cli, &wl_output_interface, version, id);
1003 wl_output_send_geometry(res,
1004 0, 0, 330, 210, // x/y (px), w/h (mm)
1005 WL_OUTPUT_SUBPIXEL_UNKNOWN, // subpixel format
1006 "unknown", "unknown", // make, model
1007 WL_OUTPUT_TRANSFORM_NORMAL); // rotatoin
1008 wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 800, 600, 60);
1009 wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1024, 768, 60);
1010 wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1280, 1024, 60);
1011 wl_output_send_done(res);
1014 static void bind_seat(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
1016 printf("bind_seat\n");
1018 struct wl_resource *res = wl_resource_create(cli, &wl_seat_interface, version, id);
1019 wl_resource_set_implementation(res, &seat_iface, NULL, NULL);
1021 wl_seat_send_capabilities(res,
1022 WL_SEAT_CAPABILITY_KEYBOARD |
1023 WL_SEAT_CAPABILITY_POINTER);
1026 static void bind_ddm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
1028 printf("bind_ddm\n");
1030 struct wl_resource *res = wl_resource_create(cli, &wl_data_device_manager_interface, version, id);
1031 wl_resource_set_implementation(res, &ddm_iface, NULL, NULL);
1034 static void bind_comp(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
1036 printf("bind_comp\n");
1037 struct wl_resource *res = wl_resource_create(cli, &wl_compositor_interface, version, id);
1038 wl_resource_set_implementation(res, &comp_iface, NULL, NULL);
1041 static void bind_shell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
1043 printf("bind_shell\n");
1044 struct wl_resource *res = wl_resource_create(cli, &wl_shell_interface, version, id);
1045 wl_resource_set_implementation(res, &shell_iface, NULL, NULL);
1048 static void bind_xshell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
1050 printf("bind_xshell\n");
1051 struct wl_resource *res = wl_resource_create(cli, &xdg_shell_interface, version, id);
1052 wl_resource_set_implementation(res, &xshell_iface, NULL, NULL);
1055 static void bind_gshell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
1057 printf("bind_gshell\n");
1058 struct wl_resource *res = wl_resource_create(cli, >k_shell_interface, version, id);
1059 wl_resource_set_implementation(res, &gshell_iface, NULL, NULL);
1066 static void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer user_data)
1068 printf("on_destroy\n");
1072 static gboolean on_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
1074 /* Handle special keys */
1075 if (event->state & GDK_CONTROL_MASK &&
1076 event->type == GDK_KEY_PRESS &&
1077 event->keyval == GDK_KEY_Return)
1078 g_spawn_command_line_async("vte2_90", NULL);
1080 /* Send key to WM */
1082 event_t ev = tolower(event->keyval);
1083 mod_t mod = get_mod(event->state, event->type == GDK_KEY_RELEASE);
1084 ptr_t ptr = get_ptr(focus);
1085 if (wm_handle_event(focus, ev, mod, ptr))
1089 /* Skip if no focused window */
1090 if (!focus || !focus->sys->cdata)
1093 /* Send key to wayland */
1094 printf(g_ascii_isprint(event->keyval)
1095 ? "on_key - win=%p cdata=%p '%c'\n"
1096 : "on_key - win=%p cdata=%p 0x%X\n",
1097 focus, focus?focus->sys->cdata:0, event->keyval);
1098 for (list_t *cur = focus->sys->cdata->kbds; cur; cur = cur->next) {
1099 uint32_t serial = get_serial();
1100 uint32_t stamp = get_time();
1101 uint32_t key = event->hardware_keycode-8;
1102 uint32_t state = event->type == GDK_KEY_PRESS
1103 ? WL_KEYBOARD_KEY_STATE_PRESSED
1104 : WL_KEYBOARD_KEY_STATE_RELEASED;
1105 wl_keyboard_send_key(cur->data, serial, stamp, key, state);
1106 printf(" send -> %p tm=%d key=%d state=%d\n",
1107 cur->data, stamp, key, state);
1112 static gboolean on_button(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
1114 win_t *win = find_win(event->x, event->y);
1115 printf("on_button - win=%p cdata=%p\n",
1116 win, win?win->sys->cdata:0);
1117 if (!win || !win->sys->cdata)
1119 for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next) {
1120 uint32_t serial = get_serial();
1121 uint32_t stamp = get_time();
1122 uint32_t button = BTN_MOUSE+(event->button-1);
1123 uint32_t state = event->type == GDK_BUTTON_PRESS
1124 ? WL_POINTER_BUTTON_STATE_PRESSED
1125 : WL_POINTER_BUTTON_STATE_RELEASED;
1126 wl_pointer_send_button(cur->data, serial, stamp, button, state);
1127 printf(" send -> %p tm=%d btn=%d state=%d\n",
1128 cur->data, stamp, button, state);
1133 static gboolean on_move(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
1135 win_t *win = find_win(event->x, event->y);
1139 /* Queue draw event for cursor */
1140 gtk_widget_queue_draw(screen);
1142 /* Save cursor position */
1143 cursor_x = event->x;
1144 cursor_y = event->y;
1146 /* Send enter/leave */
1148 wm_handle_event(hover, EV_LEAVE, MOD(), PTR());
1149 wm_handle_event(win, EV_ENTER, MOD(), PTR());
1153 /* Sent pointer to WM */
1154 if (wm_handle_ptr(win, get_ptr(win)))
1157 /* Send motion event to window */
1158 uint32_t t = get_time();
1159 wl_fixed_t x = wl_fixed_from_double(cursor_x - win->x);
1160 wl_fixed_t y = wl_fixed_from_double(cursor_y - win->y);
1161 for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next)
1162 wl_pointer_send_motion(cur->data, t, x, y);
1166 static void on_size(GtkWidget *widget, GtkAllocation *alloc, gpointer user_data)
1168 printf("on_size - %dx%d\n", alloc->width, alloc->height);
1169 root->w = alloc->width;
1170 root->h = alloc->height;
1173 static gboolean on_draw(GtkWidget *widget, cairo_t *cairo, gpointer user_data)
1175 printf("on_draw\n");
1177 //wm_update(); // Hacks for now
1179 /* Draw windows bottom up */
1180 list_t *bottom = list_last(windows);
1181 for (list_t *cur = bottom; cur; cur = cur->prev) {
1182 win_t *win = cur->data;
1183 if (win->sys->buf == NULL)
1185 if (win->type == TYPE_CURSOR)
1187 sys_bdata_t *bdata = wl_resource_get_user_data(win->sys->buf);
1190 if (win->type == TYPE_POPUP && win->parent) {
1191 x += win->parent->x;
1192 y += win->parent->y;
1194 //if (win->sys->wx) x -= win->sys->wx;
1195 //if (win->sys->wy) y -= win->sys->wy;
1196 printf(" win = %p %dx%d @ %d,%d\n",
1197 win, win->w, win->h, x, y);
1198 cairo_surface_mark_dirty(bdata->surface);
1199 cairo_set_source_surface(cairo, bdata->surface, x, y);
1201 //wl_buffer_send_release(win->sys->buf);
1202 //win->sys->buf = 0;
1206 if (cursor && cursor->sys->buf) {
1207 int x = cursor_x, y = cursor_y;
1208 sys_bdata_t *bdata = wl_resource_get_user_data(cursor->sys->buf);
1209 cairo_surface_mark_dirty(bdata->surface);
1210 cairo_set_source_surface(cairo, bdata->surface, x, y);
1217 static gboolean on_wayland(gpointer user_data)
1219 // TODO - convert to polled execution
1220 wl_display_flush_clients(display);
1221 wl_event_loop_dispatch(events, 0);
1225 /********************
1226 * System functions *
1227 ********************/
1228 void sys_move(win_t *win, int x, int y, int w, int h)
1230 if (win->x == x && win->y == y &&
1231 win->w == w && win->h == h)
1233 printf("sys_move: %p - %d,%d %dx%d\n",
1242 wl_shell_surface_send_configure(win->sys->ssfc,
1243 WL_SHELL_SURFACE_RESIZE_NONE, w, h);
1246 xdg_surface_send_configure(win->sys->xsfc, w, h,
1247 (win == focus) ? &xstate_active : &xstate_normal,
1250 gtk_widget_queue_draw(screen);
1253 void sys_raise(win_t *win)
1255 printf("sys_raise: %p\n", win);
1258 void sys_focus(win_t *win)
1262 printf("sys_focus: %p\n", win);
1264 /* Send leave event */
1265 uint32_t s = get_serial();
1266 wl_fixed_t x = wl_fixed_from_double(cursor_x - win->x);
1267 wl_fixed_t y = wl_fixed_from_double(cursor_y - win->y);
1268 if (focus && focus->sys->sfc && focus->sys->cdata) {
1269 printf("sys_focus - leave win=%p\n", focus);
1270 for (list_t *cur = focus->sys->cdata->ptrs; cur; cur = cur->next)
1271 wl_pointer_send_leave(cur->data, s, focus->sys->sfc);
1272 for (list_t *cur = focus->sys->cdata->kbds; cur; cur = cur->next)
1273 wl_keyboard_send_leave(cur->data, s, focus->sys->sfc);
1274 if (focus->sys->xsfc)
1275 xdg_surface_send_configure(focus->sys->xsfc, focus->w, focus->h,
1276 &xstate_normal, get_serial());
1278 if (win && win->sys->sfc && win->sys->cdata) {
1279 printf("sys_focus - enter win=%p\n", win);
1280 for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next)
1281 wl_pointer_send_enter(cur->data, s, win->sys->sfc, x, y);
1282 for (list_t *cur = win->sys->cdata->kbds; cur; cur = cur->next)
1283 wl_keyboard_send_enter(cur->data, s, win->sys->sfc, &keys);
1285 xdg_surface_send_configure(win->sys->xsfc, win->w, win->h,
1286 &xstate_active, get_serial());
1289 /* Update focused window */
1293 void sys_show(win_t *win, state_t state)
1295 printf("sys_show: %p: %d\n", win, state);
1298 void sys_watch(win_t *win, event_t ev, mod_t mod)
1300 printf("sys_watch: %p - %x %hhx\n",
1301 win, ev, mod2int(mod));
1304 void sys_unwatch(win_t *win, event_t ev, mod_t mod)
1306 printf("sys_unwatch: %p - %x %hhx\n",
1307 win, ev, mod2int(mod));
1310 list_t *sys_info(win_t *win)
1312 printf("sys_info: %p\n", win);
1313 return list_insert(NULL, win);
1316 win_t *sys_init(void)
1318 printf("sys_init\n");
1320 /* Create root window */
1327 /* Initalize constants */
1328 set_array(&xstate_normal, 0);
1329 set_array(&xstate_active, 1,
1330 XDG_SURFACE_STATE_ACTIVATED);
1331 set_array(&xstate_max,2,
1332 XDG_SURFACE_STATE_ACTIVATED,
1333 XDG_SURFACE_STATE_MAXIMIZED);
1334 set_array(&xstate_full, 2,
1335 XDG_SURFACE_STATE_ACTIVATED,
1336 XDG_SURFACE_STATE_FULLSCREEN);
1337 set_array(&xstate_resize, 2,
1338 XDG_SURFACE_STATE_ACTIVATED,
1339 XDG_SURFACE_STATE_RESIZING);
1341 /* Register log handler */
1342 wl_log_set_handler_server((wl_log_func_t)vprintf);
1344 /* Open the display */
1345 if (!(display = wl_display_create()))
1346 error("Unable to create display");
1347 if (wl_display_add_socket(display, NULL) != 0)
1348 error("Unable to add socket");
1349 if (!(events = wl_display_get_event_loop(display)))
1350 error("Unable to get event loop");
1352 /* Register interfaces */
1353 ref_shm = wl_global_create(display, &wl_shm_interface, 1, NULL, &bind_shm);
1354 ref_output = wl_global_create(display, &wl_output_interface, 2, NULL, &bind_output);
1355 ref_ddm = wl_global_create(display, &wl_data_device_manager_interface, 1, NULL, &bind_ddm);
1356 ref_shell = wl_global_create(display, &wl_shell_interface, 1, NULL, &bind_shell);
1357 ref_comp = wl_global_create(display, &wl_compositor_interface, 3, NULL, &bind_comp);
1358 ref_seat = wl_global_create(display, &wl_seat_interface, 4, NULL, &bind_seat);
1359 ref_xshell = wl_global_create(display, &xdg_shell_interface, 1, NULL, &bind_xshell);
1360 ref_gshell = wl_global_create(display, >k_shell_interface, 1, NULL, &bind_gshell);
1362 /* Setup GTK display */
1363 gtk_init(&conf_argc, &conf_argv);
1364 screen = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1365 gtk_widget_add_events(screen,
1366 GDK_KEY_PRESS_MASK |
1367 GDK_BUTTON_PRESS_MASK |
1368 GDK_BUTTON_RELEASE_MASK |
1369 GDK_POINTER_MOTION_MASK);
1370 g_signal_connect(screen, "destroy", G_CALLBACK(on_destroy), NULL);
1371 g_signal_connect(screen, "key-press-event", G_CALLBACK(on_key), NULL);
1372 g_signal_connect(screen, "key-release-event", G_CALLBACK(on_key), NULL);
1373 g_signal_connect(screen, "button-press-event", G_CALLBACK(on_button), NULL);
1374 g_signal_connect(screen, "button-release-event", G_CALLBACK(on_button), NULL);
1375 g_signal_connect(screen, "motion-notify-event", G_CALLBACK(on_move), NULL);
1376 g_signal_connect(screen, "size-allocate", G_CALLBACK(on_size), NULL);
1377 g_signal_connect(screen, "draw", G_CALLBACK(on_draw), NULL);
1378 g_timeout_add(1000/60, on_wayland, NULL);
1379 gtk_widget_show(screen);
1381 /* Setup environment */
1382 setenv("GDK_BACKEND", "wayland", 1);
1387 void sys_run(win_t *root)
1389 printf("sys_run: %p\n", root);
1395 printf("sys_exit\n");
1399 void sys_free(win_t *root)
1401 printf("sys_free: %p\n", root);