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
24 #include <libevdev/libevdev.h>
25 #include <xkbcommon/xkbcommon.h>
26 #include <wayland-server.h>
27 #include <wayland-client.h>
36 #include "xdg-shell-client-protocol.h"
37 #include "xdg-shell-server-protocol.h"
38 #include "gtk-shell-client-protocol.h"
39 #include "gtk-shell-server-protocol.h"
41 /* Window Managers calls */
44 /* Wayland user data */
53 cairo_surface_t *surface;
57 struct wl_client *cli;
58 list_t *ptrs; // of struct wl_resource
59 list_t *kbds; // of struct wl_resource
60 list_t *tchs; // of struct wl_resource
63 /* Internal structures */
65 struct wl_resource *sfc;
66 struct wl_resource *ssfc;
67 struct wl_resource *xsfc;
68 struct wl_resource *buf;
70 int x,y; // surface x,y
71 int wx,wy; // window x,y inside sfc
72 int ww,wh; // window w,h inside sfc
78 static list_t *clients; // of sys_cdata_t
79 static list_t *windows; // of win_t
82 static double cursor_x;
83 static double cursor_y;
84 static double cursor_dx;
85 static double cursor_dy;
87 static GtkWidget *screen;
89 static struct wl_resource *output;
90 static struct wl_display *display;
91 static struct wl_event_loop *events;
97 static int get_serial(void)
99 static int serial = 0;
103 static int get_time(void)
105 static uint64_t epoch;
108 clock_gettime(CLOCK_REALTIME, &ts);
110 uint64_t now = (((uint64_t)ts.tv_sec ) * 1000)
111 + (((uint64_t)ts.tv_nsec) / 1000000);
116 return (int)(now - epoch);
119 static win_t *find_win(int x, int y)
121 for (list_t *cur = windows; cur; cur = cur->prev) {
122 win_t *win = cur->data;
127 if (l <= x && x <= r && t <= y && y <= b)
133 static sys_cdata_t *find_cdata(struct wl_client *cli)
135 // Search for existing client
136 for (list_t *cur = clients; cur; cur = cur->next) {
137 sys_cdata_t *cdata = cur->data;
138 if (cdata->cli == cli)
142 // Not found, create new one
143 sys_cdata_t *cdata = new0(sys_cdata_t);
144 clients = list_insert(clients, cdata);
149 /****************************
150 * Wayland Buffer Interface *
151 ****************************/
152 static void buffer_destroy(struct wl_client *cli, struct wl_resource *reso)
154 printf("buffer_destroy\n");
157 static struct wl_buffer_interface buffer_iface = {
158 .destroy = buffer_destroy,
161 /***********************************
162 * Wayland Shared Memory Interface *
163 ***********************************/
166 static void pool_create_buffer(struct wl_client *cli, struct wl_resource *pool,
167 uint32_t id, int32_t offset, int32_t width, int32_t height,
168 int32_t stride, uint32_t format)
170 sys_bdata_t *bdata = new0(sys_bdata_t);
171 bdata->pool = wl_resource_get_user_data(pool);
172 bdata->mem = bdata->pool->mem + offset;
174 printf("pool_create_buffer - %dx%d %p+%d : %d,%d,%d\n",
175 width, height, bdata->pool->mem, offset, id, stride, format);
177 if (offset > bdata->pool->size || offset < 0)
179 printf("\n\nerror\n\n");
180 wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_STRIDE,
181 "offset is too big or negative");
186 format == WL_SHM_FORMAT_ARGB8888 ? CAIRO_FORMAT_ARGB32 :
187 format == WL_SHM_FORMAT_XRGB8888 ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_INVALID;
189 bdata->surface = cairo_image_surface_create_for_data(bdata->mem, cf, width, height, stride);
191 struct wl_resource *res = wl_resource_create(cli, &wl_buffer_interface,
192 wl_resource_get_version(pool), id);
193 wl_resource_set_implementation(res, &buffer_iface, bdata, NULL);
196 static void pool_destroy(struct wl_client *cli, struct wl_resource *pool)
198 printf("pool_destroy\n");
201 static void pool_resize(struct wl_client *cli, struct wl_resource *pool,
204 printf("[ WMPUS ] pool_resize - %d\n", size);
205 sys_pool_t *data = wl_resource_get_user_data(pool);
206 void *ptr = mremap(data->mem, data->size, size, MREMAP_MAYMOVE);
207 if (ptr == MAP_FAILED)
209 printf("\n\nerror\n\n");
210 wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_FD,
211 "mremap failed: %s", strerror(errno));
218 static struct wl_shm_pool_interface pool_iface = {
219 .create_buffer = &pool_create_buffer,
220 .destroy = &pool_destroy,
221 .resize = &pool_resize,
225 static void shm_create_pool(struct wl_client *cli, struct wl_resource *shm,
226 uint32_t id, int32_t fd, int32_t size)
228 printf("shm_create_pool - #%d %d %d\n", id, fd, size);
230 sys_pool_t *data = new0(sys_pool_t);
232 struct wl_resource *res = wl_resource_create(cli, &wl_shm_pool_interface,
233 wl_resource_get_version(shm), id);
234 wl_resource_set_implementation(res, &pool_iface, data, NULL);
236 data->mem = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
240 static struct wl_shm_interface shm_iface = {
241 .create_pool = shm_create_pool,
244 /**************************
245 * Wayland Seat Interface *
246 **************************/
249 static void pointer_kill(struct wl_resource *ptr)
251 sys_cdata_t *cdata = wl_resource_get_user_data(ptr);
252 list_t *link = list_find(cdata->ptrs, ptr);
253 cdata->ptrs = list_remove(cdata->ptrs, link, 0);
254 if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
255 list_t *clink = list_find(clients, cdata);
256 clients = list_remove(clients, clink, 1);
260 static void pointer_set_cursor(struct wl_client *cli, struct wl_resource *ptr,
261 uint32_t serial, struct wl_resource *sfc,
262 int32_t hotspot_x, int32_t hotspot_y)
264 printf("pointer_set_cursor %d,%d\n", hotspot_x, hotspot_y);
265 win_t *win = wl_resource_get_user_data(sfc);
266 win->type = TYPE_CURSOR;
267 cursor_dx = hotspot_x;
268 cursor_dy = hotspot_y;
272 static void pointer_release(struct wl_client *cli, struct wl_resource *ptr)
274 printf("pointer_release\n");
277 static struct wl_pointer_interface pointer_iface = {
278 .set_cursor = pointer_set_cursor,
279 .release = pointer_release,
283 static void keyboard_kill(struct wl_resource *kbd)
285 sys_cdata_t *cdata = wl_resource_get_user_data(kbd);
286 list_t *link = list_find(cdata->kbds, kbd);
287 cdata->kbds = list_remove(cdata->kbds, link, 0);
288 if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
289 list_t *clink = list_find(clients, cdata);
290 clients = list_remove(clients, clink, 1);
294 static void keyboard_release(struct wl_client *cli, struct wl_resource *kbd)
296 printf("keyboard_release\n");
299 static struct wl_keyboard_interface keyboard_iface = {
300 .release = keyboard_release,
304 static void touch_kill(struct wl_resource *tch)
306 sys_cdata_t *cdata = wl_resource_get_user_data(tch);
307 list_t *link = list_find(cdata->tchs, tch);
308 cdata->tchs = list_remove(cdata->tchs, link, 0);
309 if (!cdata->ptrs && !cdata->kbds && !cdata->tchs) {
310 list_t *clink = list_find(clients, cdata);
311 clients = list_remove(clients, clink, 1);
315 static void touch_release(struct wl_client *cli, struct wl_resource *tch)
317 printf("touch_release\n");
320 static struct wl_touch_interface touch_iface = {
321 .release = touch_release,
325 static void seat_get_pointer(struct wl_client *cli, struct wl_resource *seat,
327 sys_cdata_t *cdata = find_cdata(cli);
328 struct wl_resource *res = wl_resource_create(cli, &wl_pointer_interface, 3, id);
329 wl_resource_set_implementation(res, &pointer_iface, cdata, pointer_kill);
330 cdata->ptrs = list_insert(cdata->ptrs, res);
331 printf("seat_get_pointer - cli=%p cdata=%p ptr=%p\n", cli, cdata, res);
334 static void seat_get_keyboard(struct wl_client *cli, struct wl_resource *seat,
336 sys_cdata_t *cdata = find_cdata(cli);
337 struct wl_resource *res = wl_resource_create(cli, &wl_keyboard_interface, 4, id);
338 wl_resource_set_implementation(res, &keyboard_iface, cdata, keyboard_kill);
340 //map = xkb_keymap_new_from_names(xkb->context, NULL, 0);
341 //xkb->context = xkb_context_new(0);
342 //xkb->keymap.map = xkb_keymap_new_from_names(xkb->context, NULL, 0);
343 //wl_keyboard_send_keymap(cli, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
344 // keyboard->xkb.keymap.fd,
345 // keyboard->xkb.keymap.size - 1);
347 cdata->kbds = list_insert(cdata->kbds, res);
348 printf("seat_get_keyboard - cli=%p cdata=%p kbd=%p\n", cli, cdata, res);
351 static void seat_get_touch(struct wl_client *cli, struct wl_resource *seat,
353 sys_cdata_t *cdata = find_cdata(cli);
354 struct wl_resource *res = wl_resource_create(cli, &wl_touch_interface, 3, id);
355 wl_resource_set_implementation(res, &touch_iface, cdata, touch_kill);
356 cdata->tchs = list_insert(cdata->tchs, res);
357 printf("seat_get_touch - cli=%p cdata=%p tch=%p\n", cli, cdata, res);
360 static struct wl_seat_interface seat_iface = {
361 .get_pointer = &seat_get_pointer,
362 .get_keyboard = &seat_get_keyboard,
363 .get_touch = &seat_get_touch,
366 /*****************************************
367 * Wayland Data Device Manager Interface *
368 *****************************************/
371 static void doff_accept(struct wl_client *cli, struct wl_resource *doff,
372 uint32_t serial, const char *mime_type)
374 printf("doff_accept\n");
377 static void doff_receive(struct wl_client *cli, struct wl_resource *doff,
378 const char *mime_type, int32_t fd)
380 printf("doff_receive\n");
383 static void doff_destroy(struct wl_client *cli, struct wl_resource *doff)
385 printf("doff_destroy\n");
388 static struct wl_data_offer_interface doff_iface = {
389 .accept = doff_accept,
390 .receive = doff_receive,
391 .destroy = doff_destroy,
395 static void dsrc_offer(struct wl_client *cli, struct wl_resource *dsrc,
396 const char *mime_type)
399 printf("dsrc_offer\n");
402 static void dsrc_destroy(struct wl_client *cli, struct wl_resource *dsrc)
404 printf("dsrc_destroy\n");
407 static struct wl_data_source_interface dsrc_iface = {
409 .destroy = dsrc_destroy,
413 static void ddev_start_drag(struct wl_client *cli, struct wl_resource *dsrc,
414 struct wl_resource *source, struct wl_resource *origin,
415 struct wl_resource *icon, uint32_t serial)
417 printf("start_drag\n");
420 static void ddev_set_selection(struct wl_client *cli, struct wl_resource *dsrc,
421 struct wl_resource *source, uint32_t serial)
423 printf("set_selection\n");
426 static struct wl_data_device_interface ddev_iface = {
427 .start_drag = ddev_start_drag,
428 .set_selection = ddev_set_selection,
431 /* Data Device Manager */
432 static void ddm_create_data_source(struct wl_client *cli, struct wl_resource *ddm,
435 printf("ddm_create_data_source\n");
436 struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
437 wl_resource_set_implementation(res, &dsrc_iface, NULL, NULL);
440 static void ddm_get_data_device(struct wl_client *cli, struct wl_resource *ddm,
441 uint32_t id, struct wl_resource *seat)
443 printf("ddm_get_data_device\n");
444 struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
445 wl_resource_set_implementation(res, &ddev_iface, NULL, NULL);
448 static struct wl_data_device_manager_interface ddm_iface = {
449 .create_data_source = &ddm_create_data_source,
450 .get_data_device = &ddm_get_data_device,
453 /**************************************
454 * Wayland Shell/Compositor Interface *
455 **************************************/
458 static void surface_kill(struct wl_resource *sfc)
460 printf("surface_kill\n");
461 win_t *win = wl_resource_get_user_data(sfc);
462 list_t *link = list_find(windows, win);
465 windows = list_remove(windows, link, 0);
466 gtk_widget_queue_draw(screen);
469 static void surface_destroy(struct wl_client *cli, struct wl_resource *sfc)
471 printf("surface_destroy\n");
475 static void surface_attach(struct wl_client *cli, struct wl_resource *sfc,
476 struct wl_resource *buf, int32_t x, int32_t y)
478 win_t *win = wl_resource_get_user_data(sfc);
479 sys_bdata_t *bdata = wl_resource_get_user_data(buf);
480 printf("surface_attach - %p - %d,%d\n", bdata->pool->mem, x, y);
486 static void surface_damage(struct wl_client *cli, struct wl_resource *sfc,
487 int32_t x, int32_t y, int32_t width, int32_t height)
489 printf("surface_damage\n");
492 static void surface_frame(struct wl_client *cli, struct wl_resource *sfc,
495 printf("surface_frame\n");
496 struct wl_resource *cb = wl_resource_create(cli, &wl_callback_interface, 1, id);
497 wl_resource_set_implementation(cb, NULL, NULL, NULL);
498 wl_callback_send_done(cb, get_time());
501 static void surface_set_opaque_region(struct wl_client *cli, struct wl_resource *sfc,
502 struct wl_resource *reg)
504 printf("surface_set_opaque_region\n");
507 static void surface_set_input_region(struct wl_client *cli, struct wl_resource *sfc,
508 struct wl_resource *reg)
510 printf("surface_set_input_region\n");
513 static void surface_commit(struct wl_client *cli, struct wl_resource *sfc)
515 printf("surface_commit\n");
516 gtk_widget_queue_draw(screen);
519 static void surface_set_buffer_transform(struct wl_client *cli, struct wl_resource *sfc,
522 printf("surface_set_buffer_transform\n");
525 static void surface_set_buffer_scale(struct wl_client *cli, struct wl_resource *sfc,
528 printf("surface_set_buffer_scale\n");
531 static struct wl_surface_interface surface_iface = {
532 .destroy = surface_destroy,
533 .attach = surface_attach,
534 .damage = surface_damage,
535 .frame = surface_frame,
536 .set_opaque_region = surface_set_opaque_region,
537 .set_input_region = surface_set_input_region,
538 .commit = surface_commit,
539 .set_buffer_transform = surface_set_buffer_transform,
540 .set_buffer_scale = surface_set_buffer_scale,
544 static void region_destroy(struct wl_client *cli, struct wl_resource *reg)
546 printf("region_destroy\n");
549 static void region_add(struct wl_client *cli, struct wl_resource *reg,
550 int32_t x, int32_t y, int32_t width, int32_t height)
552 printf("region_add\n");
555 static void region_subtract(struct wl_client *cli, struct wl_resource *reg,
556 int32_t x, int32_t y, int32_t width, int32_t height)
558 printf("region_subtract\n");
561 static struct wl_region_interface region_iface = {
562 .destroy = region_destroy,
564 .subtract = region_subtract,
568 static void comp_create_surface(struct wl_client *cli, struct wl_resource *comp,
571 win_t *win = new0(win_t);
572 win->sys = new0(win_sys_t);
574 struct wl_resource *res = wl_resource_create(cli, &wl_surface_interface, 3, id);
575 wl_resource_set_implementation(res, &surface_iface, win, surface_kill);
576 wl_surface_send_enter(res, output);
579 win->sys->cdata = find_cdata(cli);
581 windows = list_insert(windows, win);
583 printf("comp_create_surface - cli=%p win=%p cdata=%p\n",
584 cli, win, win->sys->cdata);
587 static void comp_create_region(struct wl_client *cli, struct wl_resource *comp,
590 printf("comp_create_region\n");
591 struct wl_resource *res = wl_resource_create(cli, &wl_region_interface, 1, id);
592 wl_resource_set_implementation(res, ®ion_iface, NULL, NULL);
595 static struct wl_compositor_interface comp_iface = {
596 .create_surface = comp_create_surface,
597 .create_region = comp_create_region,
601 static void ssurface_kill(struct wl_resource *ssfc)
603 win_t *win = wl_resource_get_user_data(ssfc);
604 printf("ssurface_kill - %p\n", win);
605 win->sys->ssfc = NULL;
610 static void ssurface_pong(struct wl_client *cli, struct wl_resource *ssfc,
613 printf("ssurface_pong\n");
616 static void ssurface_move(struct wl_client *cli, struct wl_resource *ssfc,
617 struct wl_resource *seat, uint32_t serial)
619 printf("ssurface_move\n");
622 static void ssurface_resize(struct wl_client *cli, struct wl_resource *ssfc,
623 struct wl_resource *seat, uint32_t serial, uint32_t edges)
625 printf("ssurface_resize\n");
628 static void ssurface_set_toplevel(struct wl_client *cli, struct wl_resource *ssfc)
630 printf("ssurface_set_toplevel\n");
633 static void ssurface_set_transient(struct wl_client *cli, struct wl_resource *ssfc,
634 struct wl_resource *parent, int32_t x, int32_t y, uint32_t flags)
636 printf("ssurface_set_transient\n");
639 static void ssurface_set_fullscreen(struct wl_client *cli, struct wl_resource *ssfc,
640 uint32_t method, uint32_t framerate, struct wl_resource *out)
642 printf("ssurface_set_fullscreen\n");
645 static void ssurface_set_popup(struct wl_client *cli, struct wl_resource *ssfc,
646 struct wl_resource *seat, uint32_t serial, struct wl_resource *parent,
647 int32_t x, int32_t y, uint32_t flags)
649 printf("ssurface_set_popup\n");
652 static void ssurface_set_maximized(struct wl_client *cli, struct wl_resource *ssfc,
653 struct wl_resource *out)
655 printf("ssurface_set_maximized\n");
658 static void ssurface_set_title(struct wl_client *cli, struct wl_resource *ssfc,
661 printf("ssurface_set_title\n");
664 static void ssurface_set_class(struct wl_client *cli, struct wl_resource *ssfc,
667 printf("ssurface_set_class\n");
670 static struct wl_shell_surface_interface ssurface_iface = {
671 .pong = ssurface_pong,
672 .move = ssurface_move,
673 .resize = ssurface_resize,
674 .set_toplevel = ssurface_set_toplevel,
675 .set_transient = ssurface_set_transient,
676 .set_fullscreen = ssurface_set_fullscreen,
677 .set_popup = ssurface_set_popup,
678 .set_maximized = ssurface_set_maximized,
679 .set_title = ssurface_set_title,
680 .set_class = ssurface_set_class,
684 static void shell_get_shell_surface(struct wl_client *cli, struct wl_resource *shell, uint32_t id,
685 struct wl_resource *sfc) {
686 win_t *win = wl_resource_get_user_data(sfc);
687 printf("shell_get_shell_surface - %p\n", win);
689 struct wl_resource *res = wl_resource_create(cli, &wl_shell_surface_interface, 1, id);
690 wl_resource_set_implementation(res, &ssurface_iface, win, ssurface_kill);
692 win->type = TYPE_NORMAL;
693 win->sys->ssfc = res;
697 static struct wl_shell_interface shell_iface = {
698 .get_shell_surface = shell_get_shell_surface,
702 static void xpopup_destroy(struct wl_client *cli, struct wl_resource *xpopup)
704 printf("xpopup_destroy\n");
707 static struct xdg_popup_interface xpopup_iface = {
708 .destroy = xpopup_destroy,
712 static void xsurface_kill(struct wl_resource *xsfc)
714 win_t *win = wl_resource_get_user_data(xsfc);
715 printf("xsurface_kill - %p\n", win);
716 win->sys->xsfc = NULL;
721 static void xsurface_destroy(struct wl_client *cli, struct wl_resource *xsfc)
723 printf("xsurface_destroy\n");
726 static void xsurface_set_parent(struct wl_client *cli, struct wl_resource *xsfc,
727 struct wl_resource *parent)
729 win_t *win = wl_resource_get_user_data(xsfc);
730 printf("xsurface_set_parent - %p\n", win);
731 win->type = TYPE_DIALOG;
734 static void xsurface_set_title(struct wl_client *cli, struct wl_resource *xsfc,
737 printf("xsurface_set_title\n");
740 static void xsurface_set_app_id(struct wl_client *cli, struct wl_resource *xsfc,
743 printf("xsurface_set_app_id\n");
746 static void xsurface_show_window_menu(struct wl_client *cli, struct wl_resource *xsfc,
747 struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y)
749 printf("xsurface_show_window_menu\n");
752 static void xsurface_move(struct wl_client *cli, struct wl_resource *xsfc,
753 struct wl_resource *seat, uint32_t serial)
755 printf("xsurface_move\n");
758 static void xsurface_resize(struct wl_client *cli, struct wl_resource *xsfc,
759 struct wl_resource *seat, uint32_t serial, uint32_t edges)
761 printf("xsurface_resize\n");
764 static void xsurface_ack_configure(struct wl_client *cli, struct wl_resource *xsfc,
767 printf("xsurface_ack_configure\n");
770 static void xsurface_set_window_geometry(struct wl_client *cli, struct wl_resource *xsfc,
771 int32_t x, int32_t y, int32_t width, int32_t height)
773 win_t *win = wl_resource_get_user_data(xsfc);
774 printf("xsurface_set_window_geometry - %p\n", win);
777 win->sys->ww = width;
778 win->sys->wh = height;
781 static void xsurface_set_maximized(struct wl_client *cli, struct wl_resource *xsfc)
783 printf("xsurface_set_maximized\n");
786 static void xsurface_unset_maximized(struct wl_client *cli, struct wl_resource *xsfc)
788 printf("xsurface_unset_maximized\n");
791 static void xsurface_set_fullscreen(struct wl_client *cli, struct wl_resource *xsfc,
792 struct wl_resource *output)
794 printf("xsurface_set_fullscreen\n");
797 static void xsurface_unset_fullscreen(struct wl_client *cli, struct wl_resource *xsfc)
799 printf("xsurface_unset_fullscreen\n");
802 static void xsurface_set_minimized(struct wl_client *cli, struct wl_resource *xsfc)
804 printf("xsurface_set_minimized\n");
807 static struct xdg_surface_interface xsurface_iface = {
808 .destroy = xsurface_destroy,
809 .set_parent = xsurface_set_parent,
810 .set_title = xsurface_set_title,
811 .set_app_id = xsurface_set_app_id,
812 .show_window_menu = xsurface_show_window_menu,
813 .move = xsurface_move,
814 .resize = xsurface_resize,
815 .ack_configure = xsurface_ack_configure,
816 .set_window_geometry = xsurface_set_window_geometry,
817 .set_maximized = xsurface_set_maximized,
818 .unset_maximized = xsurface_unset_maximized,
819 .set_fullscreen = xsurface_set_fullscreen,
820 .unset_fullscreen = xsurface_unset_fullscreen,
821 .set_minimized = xsurface_set_minimized,
825 static void xshell_use_unstable_version(struct wl_client *cli, struct wl_resource *xshell,
828 printf("xshell_use_unstable_version\n");
831 static void xshell_get_xdg_surface(struct wl_client *cli, struct wl_resource *xshell,
832 uint32_t id, struct wl_resource *sfc)
834 win_t *win = wl_resource_get_user_data(sfc);
835 printf("xshell_get_xdg_surface - %p\n", win);
837 struct wl_resource *res = wl_resource_create(cli, &xdg_surface_interface, 1, id);
838 wl_resource_set_implementation(res, &xsurface_iface, win, xsurface_kill);
840 win->type = TYPE_NORMAL;
841 win->sys->xsfc = res;
845 static void xshell_get_xdg_popup(struct wl_client *cli, struct wl_resource *xshell,
846 uint32_t id, struct wl_resource *sfc, struct wl_resource *parent,
847 struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y, uint32_t flags)
849 printf("xshell_get_xdg_popup\n");
850 struct wl_resource *res = wl_resource_create(cli, &xdg_popup_interface, 1, id);
851 wl_resource_set_implementation(res, &xpopup_iface, NULL, NULL);
854 static void xshell_pong(struct wl_client *cli, struct wl_resource *xshell,
857 printf("xshell_pong\n");
860 static struct xdg_shell_interface xshell_iface = {
861 .use_unstable_version = xshell_use_unstable_version,
862 .get_xdg_surface = xshell_get_xdg_surface,
863 .get_xdg_popup = xshell_get_xdg_popup,
868 static void gsurface_set_dbus_properties(struct wl_client *cli, struct wl_resource *gsfc,
869 const char *application_id, const char *app_menu_path,
870 const char *menubar_path, const char *window_object_path,
871 const char *application_object_path, const char *unique_bus_name)
873 printf("gsurface_set_dbus_properties\n");
876 static struct gtk_surface_interface gsurface_iface = {
877 .set_dbus_properties = gsurface_set_dbus_properties,
881 static void gshell_get_gtk_surface(struct wl_client *cli, struct wl_resource *gshell,
882 uint32_t id, struct wl_resource *sfc)
884 printf("gshell_get_gtk_surface\n");
885 struct wl_resource *res = wl_resource_create(cli, >k_surface_interface, 1, id);
886 wl_resource_set_implementation(res, &gsurface_iface, NULL, NULL);
889 static struct gtk_shell_interface gshell_iface = {
890 .get_gtk_surface = gshell_get_gtk_surface,
898 static struct wl_global *ref_shm;
899 static struct wl_global *ref_output;
900 static struct wl_global *ref_seat;
901 static struct wl_global *ref_ddm;
902 static struct wl_global *ref_comp;
903 static struct wl_global *ref_shell;
904 static struct wl_global *ref_xshell;
905 static struct wl_global *ref_gshell;
908 static void bind_shm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
910 printf("bind_shm\n");
915 struct wl_resource *res = wl_resource_create(cli, &wl_shm_interface, version, id);
916 wl_resource_set_implementation(res, &shm_iface, NULL, NULL);
918 wl_shm_send_format(res, WL_SHM_FORMAT_XRGB8888);
919 wl_shm_send_format(res, WL_SHM_FORMAT_ARGB8888);
922 static void bind_output(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
924 printf("bind_output\n");
926 struct wl_resource *res = wl_resource_create(cli, &wl_output_interface, version, id);
929 wl_output_send_geometry(res,
930 0, 0, 330, 210, // x/y (px), w/h (mm)
931 WL_OUTPUT_SUBPIXEL_UNKNOWN, // subpixel format
932 "unknown", "unknown", // make, model
933 WL_OUTPUT_TRANSFORM_NORMAL); // rotatoin
934 wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 800, 600, 60);
935 wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1024, 768, 60);
936 wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1280, 1024, 60);
937 wl_output_send_done(res);
940 static void bind_seat(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
942 printf("bind_seat\n");
944 struct wl_resource *res = wl_resource_create(cli, &wl_seat_interface, version, id);
945 wl_resource_set_implementation(res, &seat_iface, NULL, NULL);
947 wl_seat_send_capabilities(res,
948 WL_SEAT_CAPABILITY_KEYBOARD |
949 WL_SEAT_CAPABILITY_POINTER);
952 static void bind_ddm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
954 printf("bind_ddm\n");
956 struct wl_resource *res = wl_resource_create(cli, &wl_data_device_manager_interface, version, id);
957 wl_resource_set_implementation(res, &ddm_iface, NULL, NULL);
960 static void bind_comp(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
962 printf("bind_comp\n");
963 struct wl_resource *res = wl_resource_create(cli, &wl_compositor_interface, version, id);
964 wl_resource_set_implementation(res, &comp_iface, NULL, NULL);
967 static void bind_shell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
969 printf("bind_shell\n");
970 struct wl_resource *res = wl_resource_create(cli, &wl_shell_interface, version, id);
971 wl_resource_set_implementation(res, &shell_iface, NULL, NULL);
974 static void bind_xshell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
976 printf("bind_xshell\n");
977 struct wl_resource *res = wl_resource_create(cli, &xdg_shell_interface, version, id);
978 wl_resource_set_implementation(res, &xshell_iface, NULL, NULL);
981 static void bind_gshell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
983 printf("bind_gshell\n");
984 struct wl_resource *res = wl_resource_create(cli, >k_shell_interface, version, id);
985 wl_resource_set_implementation(res, &gshell_iface, NULL, NULL);
992 static void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer user_data)
994 printf("on_destroy\n");
998 static gboolean on_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
1000 /* Handle special keys */
1001 if (event->keyval == GDK_KEY_q)
1003 if (event->keyval == GDK_KEY_t)
1004 g_spawn_command_line_async("st-wl", NULL);
1006 /* Send key to wayland */
1007 printf(g_ascii_isprint(event->keyval)
1008 ? "on_key - win=%p cdata=%p '%c'\n"
1009 : "on_key - win=%p cdata=%p 0x%X\n",
1010 focus, focus?focus->sys->cdata:0, event->keyval);
1011 if (!focus || !focus->sys->cdata)
1013 for (list_t *cur = focus->sys->cdata->kbds; cur; cur = cur->next) {
1014 uint32_t serial = get_serial();
1015 uint32_t stamp = get_time();
1016 uint32_t key = event->hardware_keycode-8;
1017 uint32_t state = event->type == GDK_KEY_PRESS
1018 ? WL_KEYBOARD_KEY_STATE_PRESSED
1019 : WL_KEYBOARD_KEY_STATE_RELEASED;
1020 wl_keyboard_send_key(cur->data, serial, stamp, key, state);
1021 printf(" send -> %p tm=%d key=%d state=%d\n",
1022 cur->data, stamp, key, state);
1027 static gboolean on_button(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
1029 win_t *win = find_win(event->x, event->y);
1030 printf("on_button - win=%p cdata=%p\n",
1031 win, win?win->sys->cdata:0);
1032 if (!win || !win->sys->cdata)
1034 for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next) {
1035 uint32_t serial = get_serial();
1036 uint32_t stamp = get_time();
1037 uint32_t button = BTN_MOUSE+(event->button-1);
1038 uint32_t state = event->type == GDK_BUTTON_PRESS
1039 ? WL_POINTER_BUTTON_STATE_PRESSED
1040 : WL_POINTER_BUTTON_STATE_RELEASED;
1041 wl_pointer_send_button(cur->data, serial, stamp, button, state);
1042 printf(" send -> %p tm=%d btn=%d state=%d\n",
1043 cur->data, stamp, button, state);
1048 static gboolean on_move(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
1050 win_t *win = find_win(event->x, event->y);
1055 static struct wl_array keys;
1057 /* Queue draw event for cursor */
1058 gtk_widget_queue_draw(screen);
1060 /* Save cursor position */
1061 cursor_x = event->x;
1062 cursor_y = event->y;
1065 wl_fixed_t x = wl_fixed_from_double(event->x - win->x);
1066 wl_fixed_t y = wl_fixed_from_double(event->y - win->y);
1068 /* No focus change */
1069 if (win == focus && win->sys->cdata) {
1070 uint32_t t = get_time();
1071 for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next)
1072 wl_pointer_send_motion(cur->data, t, x, y);
1076 /* Send leave event */
1077 uint32_t s = get_serial();
1078 if (focus && focus->sys->sfc && focus->sys->cdata) {
1079 printf("on_move - leave win=%p\n", focus);
1080 for (list_t *cur = focus->sys->cdata->ptrs; cur; cur = cur->next)
1081 wl_pointer_send_leave(cur->data, s, focus->sys->sfc);
1082 for (list_t *cur = focus->sys->cdata->kbds; cur; cur = cur->next)
1083 wl_keyboard_send_leave(cur->data, s, focus->sys->sfc);
1085 if (win && win->sys->sfc && win->sys->cdata) {
1086 for (list_t *cur = win->sys->cdata->ptrs; cur; cur = cur->next) {
1087 printf("on_move - enter win=%p ptr=%p\n", win, cur->data);
1088 wl_pointer_send_enter(cur->data, s, win->sys->sfc, x, y);
1090 for (list_t *cur = win->sys->cdata->kbds; cur; cur = cur->next) {
1091 printf("on_move - enter win=%p kbd=%p\n", win, cur->data);
1092 wl_keyboard_send_enter(cur->data, s, win->sys->sfc, &keys);
1099 static void on_size(GtkWidget *widget, GtkAllocation *alloc, gpointer user_data)
1101 printf("on_size - %dx%d\n", alloc->width, alloc->height);
1102 root->w = alloc->width;
1103 root->h = alloc->height;
1106 static gboolean on_draw(GtkWidget *widget, cairo_t *cairo, gpointer user_data)
1108 printf("on_draw\n");
1110 wm_update(); // Hacks for now
1112 /* Draw windows bottom up */
1113 list_t *bottom = list_last(windows);
1114 for (list_t *cur = bottom; cur; cur = cur->prev) {
1115 win_t *win = cur->data;
1116 if (win->sys->buf == NULL)
1118 if (win->type == TYPE_CURSOR)
1120 sys_bdata_t *bdata = wl_resource_get_user_data(win->sys->buf);
1121 int x = win->type == TYPE_NORMAL ? win->x : win->sys->x;
1122 int y = win->type == TYPE_NORMAL ? win->y : win->sys->y;
1123 if (win->sys->wx) x -= win->sys->wx;
1124 if (win->sys->wy) y -= win->sys->wy;
1125 printf(" win = %p\n", win);
1126 cairo_surface_mark_dirty(bdata->surface);
1127 cairo_set_source_surface(cairo, bdata->surface, x, y);
1129 //wl_buffer_send_release(win->sys->buf);
1130 //win->sys->buf = 0;
1134 if (cursor && cursor->sys->buf) {
1135 int x = cursor_x, y = cursor_y;
1136 sys_bdata_t *bdata = wl_resource_get_user_data(cursor->sys->buf);
1137 cairo_surface_mark_dirty(bdata->surface);
1138 cairo_set_source_surface(cairo, bdata->surface, x, y);
1145 static gboolean on_wayland(gpointer user_data)
1147 // TODO - convert to polled execution
1148 wl_display_flush_clients(display);
1149 wl_event_loop_dispatch(events, 0);
1153 /********************
1154 * System functions *
1155 ********************/
1156 void sys_move(win_t *win, int x, int y, int w, int h)
1158 static uint32_t active;
1159 static struct wl_array states;
1161 active = XDG_SURFACE_STATE_ACTIVATED;
1162 wl_array_init(&states);
1163 uint32_t *ptr = wl_array_add(&states, sizeof(active));
1168 printf("sys_move: %p - %d,%d %dx%d\n",
1171 if (win->x == x && win->y == y &&
1172 win->w == w && win->h == h)
1181 wl_shell_surface_send_configure(win->sys->ssfc,
1182 WL_SHELL_SURFACE_RESIZE_NONE, w, h);
1185 xdg_surface_send_configure(win->sys->xsfc,
1186 w, h, &states, get_serial());
1189 void sys_raise(win_t *win)
1191 printf("sys_raise: %p\n", win);
1194 void sys_focus(win_t *win)
1196 printf("sys_focus: %p\n", win);
1199 void sys_show(win_t *win, state_t state)
1201 printf("sys_show: %p: %d\n", win, state);
1204 void sys_watch(win_t *win, event_t ev, mod_t mod)
1206 printf("sys_watch: %p - %x %hhx\n",
1207 win, ev, mod2int(mod));
1210 void sys_unwatch(win_t *win, event_t ev, mod_t mod)
1212 printf("sys_unwatch: %p - %x %hhx\n",
1213 win, ev, mod2int(mod));
1216 list_t *sys_info(win_t *win)
1218 printf("sys_info: %p\n", win);
1219 return list_insert(NULL, win);
1222 win_t *sys_init(void)
1224 printf("sys_init\n");
1226 /* Create root window */
1233 /* Register log handler */
1234 wl_log_set_handler_server((wl_log_func_t)vprintf);
1236 /* Open the display */
1237 if (!(display = wl_display_create()))
1238 error("Unable to create display");
1239 if (wl_display_add_socket(display, NULL) != 0)
1240 error("Unable to add socket");
1241 if (!(events = wl_display_get_event_loop(display)))
1242 error("Unable to get event loop");
1244 /* Register interfaces */
1245 ref_shm = wl_global_create(display, &wl_shm_interface, 1, NULL, &bind_shm);
1246 ref_output = wl_global_create(display, &wl_output_interface, 2, NULL, &bind_output);
1247 ref_ddm = wl_global_create(display, &wl_data_device_manager_interface, 1, NULL, &bind_ddm);
1248 ref_shell = wl_global_create(display, &wl_shell_interface, 1, NULL, &bind_shell);
1249 ref_comp = wl_global_create(display, &wl_compositor_interface, 3, NULL, &bind_comp);
1250 ref_seat = wl_global_create(display, &wl_seat_interface, 4, NULL, &bind_seat);
1251 ref_xshell = wl_global_create(display, &xdg_shell_interface, 1, NULL, &bind_xshell);
1252 ref_gshell = wl_global_create(display, >k_shell_interface, 1, NULL, &bind_gshell);
1254 /* Setup GTK display */
1255 gtk_init(&conf_argc, &conf_argv);
1256 screen = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1257 gtk_widget_add_events(screen,
1258 GDK_KEY_PRESS_MASK |
1259 GDK_BUTTON_PRESS_MASK |
1260 GDK_BUTTON_RELEASE_MASK |
1261 GDK_POINTER_MOTION_MASK);
1262 g_signal_connect(screen, "destroy", G_CALLBACK(on_destroy), NULL);
1263 g_signal_connect(screen, "key-press-event", G_CALLBACK(on_key), NULL);
1264 g_signal_connect(screen, "key-release-event", G_CALLBACK(on_key), NULL);
1265 g_signal_connect(screen, "button-press-event", G_CALLBACK(on_button), NULL);
1266 g_signal_connect(screen, "button-release-event", G_CALLBACK(on_button), NULL);
1267 g_signal_connect(screen, "motion-notify-event", G_CALLBACK(on_move), NULL);
1268 g_signal_connect(screen, "size-allocate", G_CALLBACK(on_size), NULL);
1269 g_signal_connect(screen, "draw", G_CALLBACK(on_draw), NULL);
1270 g_timeout_add(1000/60, on_wayland, NULL);
1271 gtk_widget_show(screen);
1276 void sys_run(win_t *root)
1278 printf("sys_run: %p\n", root);
1284 printf("sys_exit\n");
1288 void sys_free(win_t *root)
1290 printf("sys_free: %p\n", root);