2 * Copyright (c) 2014, 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 <xkbcommon/xkbcommon.h>
25 #include <wayland-server.h>
26 #include <wayland-client.h>
35 /* Internal structures */
48 cairo_surface_t *surface;
51 struct wl_resource *output;
53 sys_pool_t *gdata[10];
57 static struct wl_display *display;
58 static struct wl_event_loop *events;
60 static GtkWidget *window;
61 static sys_buf_t *buffer;
67 static void on_destroy(GtkWidget *widget, GdkEvent *event, gpointer user_data)
69 printf("on_destroy\n");
73 static gboolean on_key(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
75 printf(g_ascii_isprint(event->keyval)
79 if (event->keyval == GDK_KEY_q)
81 if (event->keyval == GDK_KEY_t)
82 g_spawn_command_line_async("st-wl", NULL);
86 static gboolean on_button(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
88 printf("on_button\n");
92 static gboolean on_move(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
94 //printf("on_motion\n");
98 static gboolean on_draw(GtkWidget *widget, cairo_t *cairo, gpointer user_data)
103 cairo_surface_mark_dirty(buffer->surface);
104 cairo_set_source_surface(cairo, buffer->surface, 10, 10);
108 cairo_set_source_rgb(cairo, 1, 1, 1);
109 cairo_arc(cairo, 150, 150, 50, 0, 2*G_PI);
113 //FILE *fd = fopen("/tmp/mem.txt", "w+");
114 //for (gi = 0; gi < 10; gi++) {
116 // while (gdata[gi] && (mi+32) < gdata[gi]->size) {
117 // fprintf(fd, "%d %p %08x: ", gi, gdata[gi]->mem, mi);
118 // for (int i = 0; i < 16; mi++, i += 2)
119 // fprintf(fd, "%02hhx%02hhx ",
120 // gdata[gi]->mem[mi+0],
121 // gdata[gi]->mem[mi+1]);
122 // fprintf(fd, "\n");
124 // fprintf(fd, "\n");
132 static gboolean on_wayland(gpointer user_data)
134 // TODO - convert to polled execution
135 wl_display_flush_clients(display);
136 wl_event_loop_dispatch(events, 0);
140 /*********************
141 * Wayland Callbacks *
142 *********************/
145 static void new_window(void)
147 printf("new_window\n");
150 static void new_screen(void)
152 printf("new_screen\n");
156 /****************************
157 * Wayland Buffer Interface *
158 ****************************/
159 static struct wl_buffer_interface buffer_iface = {
163 /***********************************
164 * Wayland Shared Memory Interface *
165 ***********************************/
168 static void pool_create_buffer(struct wl_client *cli, struct wl_resource *pool,
169 uint32_t id, int32_t offset, int32_t width, int32_t height,
170 int32_t stride, uint32_t format)
172 sys_buf_t *buf = new0(sys_buf_t);
173 buf->pool = wl_resource_get_user_data(pool);
174 buf->mem = buf->pool->mem + offset;
176 printf("pool_create_buffer - %dx%d %p+%d : %d,%d,%d\n",
177 width, height, buf->pool->mem, offset, id, stride, format);
179 if (offset > buf->pool->size || offset < 0)
181 printf("\n\nerror\n\n");
182 wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_STRIDE,
183 "offset is too big or negative");
188 format == WL_SHM_FORMAT_ARGB8888 ? CAIRO_FORMAT_ARGB32 :
189 format == WL_SHM_FORMAT_XRGB8888 ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_INVALID;
191 buf->surface = cairo_image_surface_create_for_data(buf->mem, cf, width, height, stride);
193 struct wl_resource *res = wl_resource_create(cli, &wl_buffer_interface,
194 wl_resource_get_version(pool), id);
195 wl_resource_set_implementation(res, &buffer_iface, buf, NULL);
198 static void pool_destroy(struct wl_client *cli, struct wl_resource *pool)
200 printf("pool_destroy\n");
203 static void pool_resize(struct wl_client *cli, struct wl_resource *pool,
206 printf("[ WMPUS ] pool_resize - %d\n", size);
207 sys_pool_t *data = wl_resource_get_user_data(pool);
208 void *ptr = mremap(data->mem, data->size, size, MREMAP_MAYMOVE);
209 if (ptr == MAP_FAILED)
211 printf("\n\nerror\n\n");
212 wl_resource_post_error(pool, WL_SHM_ERROR_INVALID_FD,
213 "mremap failed: %s", strerror(errno));
218 gdata[gidx++] = data;
221 static struct wl_shm_pool_interface pool_iface = {
222 .create_buffer = &pool_create_buffer,
223 .destroy = &pool_destroy,
224 .resize = &pool_resize,
228 static void shm_create_pool(struct wl_client *cli, struct wl_resource *shm,
229 uint32_t id, int32_t fd, int32_t size)
231 printf("shm_create_pool - #%d %d %d\n", id, fd, size);
233 sys_pool_t *data = new0(sys_pool_t);
235 struct wl_resource *res = wl_resource_create(cli, &wl_shm_pool_interface,
236 wl_resource_get_version(shm), id);
237 wl_resource_set_implementation(res, &pool_iface, data, NULL);
239 data->mem = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
241 gdata[gidx++] = data;
244 static struct wl_shm_interface shm_iface = {
245 .create_pool = shm_create_pool,
248 /**************************
249 * Wayland Seat Interface *
250 **************************/
253 static struct wl_pointer_interface pointer_iface = {
259 static struct wl_keyboard_interface keyboard_iface = {
264 static struct wl_touch_interface touch_iface = {
269 static void seat_get_pointer(struct wl_client *cli, struct wl_resource *seat,
271 printf("seat_get_pointer\n");
272 struct wl_resource *res = wl_resource_create(cli, &wl_pointer_interface, 3, id);
273 wl_resource_set_implementation(res, &pointer_iface, NULL, NULL);
276 static void seat_get_keyboard(struct wl_client *cli, struct wl_resource *seat,
278 printf("seat_get_keyboard\n");
279 struct wl_resource *res = wl_resource_create(cli, &wl_keyboard_interface, 3, id);
280 wl_resource_set_implementation(res, &keyboard_iface, NULL, NULL);
283 static void seat_get_touch(struct wl_client *cli, struct wl_resource *seat,
285 printf("seat_get_touch\n");
286 struct wl_resource *res = wl_resource_create(cli, &wl_touch_interface, 3, id);
287 wl_resource_set_implementation(res, &touch_iface, NULL, NULL);
290 static struct wl_seat_interface seat_iface = {
291 .get_pointer = &seat_get_pointer,
292 .get_keyboard = &seat_get_keyboard,
293 .get_touch = &seat_get_touch,
296 /*****************************************
297 * Wayland Data Device Manager Interface *
298 *****************************************/
301 static struct wl_data_offer_interface doff_iface = {
308 static struct wl_data_source_interface dsrc_iface = {
314 static struct wl_data_device_interface ddev_iface = {
316 .set_selection = NULL,
319 /* Data Device Manager */
320 static void ddm_create_data_source(struct wl_client *cli, struct wl_resource *ddm,
323 printf("ddm_create_data_source\n");
324 struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
325 wl_resource_set_implementation(res, &dsrc_iface, NULL, NULL);
328 static void ddm_get_data_device(struct wl_client *cli, struct wl_resource *ddm,
329 uint32_t id, struct wl_resource *seat)
331 printf("ddm_get_data_device\n");
332 struct wl_resource *res = wl_resource_create(cli, &wl_data_device_interface, 1, id);
333 wl_resource_set_implementation(res, &ddev_iface, NULL, NULL);
336 static struct wl_data_device_manager_interface ddm_iface = {
337 .create_data_source = &ddm_create_data_source,
338 .get_data_device = &ddm_get_data_device,
341 /**************************************
342 * Wayland Shell/Compositor Interface *
343 **************************************/
346 static void frame_callback(struct wl_resource *res)
348 printf("frame_callback\n");
352 static void surface_destroy(struct wl_client *cli, struct wl_resource *res)
354 printf("surface_destroy\n");
357 static void surface_attach(struct wl_client *cli, struct wl_resource *res,
358 struct wl_resource *buf, int32_t x, int32_t y)
360 sys_buf_t *data = wl_resource_get_user_data(buf);
361 printf("surface_attach - %p\n", data->pool->mem);
365 static void surface_damage(struct wl_client *cli, struct wl_resource *res,
366 int32_t x, int32_t y, int32_t width, int32_t height)
368 printf("surface_damage\n");
371 static void surface_frame(struct wl_client *cli, struct wl_resource *res,
374 printf("surface_frame\n");
375 struct wl_resource *cb = wl_resource_create(cli, &wl_callback_interface, 1, id);
376 wl_resource_set_implementation(cb, NULL, NULL, &frame_callback);
377 wl_callback_send_done(cb, time(NULL));
380 static void surface_set_opaque_region(struct wl_client *cli, struct wl_resource *res,
381 struct wl_resource *reg)
383 printf("surface_set_opaque_region\n");
386 static void surface_set_input_region(struct wl_client *cli, struct wl_resource *res,
387 struct wl_resource *reg)
389 printf("surface_set_input_region\n");
392 static void surface_commit(struct wl_client *cli, struct wl_resource *res)
394 printf("surface_commit\n");
395 gtk_widget_queue_draw(window);
398 static void surface_set_buffer_transform(struct wl_client *cli, struct wl_resource *res,
401 printf("surface_set_buffer_transform\n");
404 static void surface_set_buffer_scale(struct wl_client *cli, struct wl_resource *res,
407 printf("surface_set_buffer_scale\n");
410 static struct wl_surface_interface surface_iface = {
411 .destroy = surface_destroy,
412 .attach = surface_attach,
413 .damage = surface_damage,
414 .frame = surface_frame,
415 .set_opaque_region = surface_set_opaque_region,
416 .set_input_region = surface_set_input_region,
417 .commit = surface_commit,
418 .set_buffer_transform = surface_set_buffer_transform,
419 .set_buffer_scale = surface_set_buffer_scale,
423 static void region_destroy(struct wl_client *cli, struct wl_resource *res)
425 printf("region_destroy\n");
428 static void region_add(struct wl_client *cli, struct wl_resource *res,
429 int32_t x, int32_t y, int32_t width, int32_t height)
431 printf("region_add\n");
434 static void region_subtract(struct wl_client *cli, struct wl_resource *res,
435 int32_t x, int32_t y, int32_t width, int32_t height)
437 printf("region_subtract\n");
440 static struct wl_region_interface region_iface = {
441 .destroy = region_destroy,
443 .subtract = region_subtract,
447 static void comp_create_surface(struct wl_client *cli, struct wl_resource *comp,
450 printf("comp_create_surface\n");
451 struct wl_resource *res = wl_resource_create(cli, &wl_surface_interface, 3, id);
452 wl_resource_set_implementation(res, &surface_iface, NULL, NULL);
453 wl_surface_send_enter(res, output);
456 static void comp_create_region(struct wl_client *cli, struct wl_resource *comp,
459 printf("comp_create_region\n");
460 struct wl_resource *res = wl_resource_create(cli, &wl_region_interface, 1, id);
461 wl_resource_set_implementation(res, ®ion_iface, NULL, NULL);
464 static struct wl_compositor_interface comp_iface = {
465 .create_surface = comp_create_surface,
466 .create_region = comp_create_region,
470 static void ssurface_pong(struct wl_client *cli, struct wl_resource *res,
473 printf("ssurface_pong\n");
476 static void ssurface_move(struct wl_client *cli, struct wl_resource *res,
477 struct wl_resource *seat, uint32_t serial)
479 printf("ssurface_move\n");
482 static void ssurface_resize(struct wl_client *cli, struct wl_resource *res,
483 struct wl_resource *seat, uint32_t serial, uint32_t edges)
485 printf("ssurface_resize\n");
488 static void ssurface_set_toplevel(struct wl_client *cli, struct wl_resource *res)
490 printf("ssurface_set_toplevel\n");
493 static void ssurface_set_transient(struct wl_client *cli, struct wl_resource *res,
494 struct wl_resource *parent, int32_t x, int32_t y, uint32_t flags)
496 printf("ssurface_set_transient\n");
499 static void ssurface_set_fullscreen(struct wl_client *cli, struct wl_resource *res,
500 uint32_t method, uint32_t framerate, struct wl_resource *out)
502 printf("ssurface_set_fullscreen\n");
505 static void ssurface_set_popup(struct wl_client *cli, struct wl_resource *res,
506 struct wl_resource *seat, uint32_t serial, struct wl_resource *parent,
507 int32_t x, int32_t y, uint32_t flags)
509 printf("ssurface_set_popup\n");
512 static void ssurface_set_maximized(struct wl_client *cli, struct wl_resource *res,
513 struct wl_resource *out)
515 printf("ssurface_set_maximized\n");
518 static void ssurface_set_title(struct wl_client *cli, struct wl_resource *res,
521 printf("ssurface_set_title\n");
524 static void ssurface_set_class(struct wl_client *cli, struct wl_resource *res,
527 printf("ssurface_set_class\n");
530 static struct wl_shell_surface_interface ssurface_iface = {
531 .pong = ssurface_pong,
532 .move = ssurface_move,
533 .resize = ssurface_resize,
534 .set_toplevel = ssurface_set_toplevel,
535 .set_transient = ssurface_set_transient,
536 .set_fullscreen = ssurface_set_fullscreen,
537 .set_popup = ssurface_set_popup,
538 .set_maximized = ssurface_set_maximized,
539 .set_title = ssurface_set_title,
540 .set_class = ssurface_set_class,
544 static void shell_get_shell_surface(struct wl_client *cli, struct wl_resource *shell, uint32_t id,
545 struct wl_resource *sfc) {
546 printf("shell_get_shell_surface\n");
547 struct wl_resource *res = wl_resource_create(cli, &wl_shell_surface_interface, 1, id);
548 wl_resource_set_implementation(res, &ssurface_iface, NULL, NULL);
551 static struct wl_shell_interface shell_iface = {
552 .get_shell_surface = shell_get_shell_surface,
560 static struct wl_global *ref_shm;
561 static struct wl_global *ref_output;
562 static struct wl_global *ref_seat;
563 static struct wl_global *ref_ddm;
564 static struct wl_global *ref_comp;
565 static struct wl_global *ref_shell;
568 static void bind_shm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
570 printf("bind_shm\n");
575 struct wl_resource *res = wl_resource_create(cli, &wl_shm_interface, version, id);
576 wl_resource_set_implementation(res, &shm_iface, NULL, NULL);
578 wl_shm_send_format(res, WL_SHM_FORMAT_XRGB8888);
579 wl_shm_send_format(res, WL_SHM_FORMAT_ARGB8888);
582 static void bind_output(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
584 printf("bind_output\n");
586 struct wl_resource *res = wl_resource_create(cli, &wl_output_interface, version, id);
589 wl_output_send_geometry(res,
590 0, 0, 330, 210, // x/y (px), w/h (mm)
591 WL_OUTPUT_SUBPIXEL_UNKNOWN, // subpixel format
592 "unknown", "unknown", // make, model
593 WL_OUTPUT_TRANSFORM_NORMAL); // rotatoin
594 //wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 800, 600, 60);
595 //wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1024, 768, 60);
596 wl_output_send_mode(res, WL_OUTPUT_MODE_CURRENT, 1280, 1024, 60);
597 //wl_output_send_done(res);
600 static void bind_seat(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
602 printf("bind_seat\n");
604 struct wl_resource *res = wl_resource_create(cli, &wl_seat_interface, version, id);
605 wl_resource_set_implementation(res, &seat_iface, NULL, NULL);
607 wl_seat_send_capabilities(res,
608 WL_SEAT_CAPABILITY_KEYBOARD |
609 WL_SEAT_CAPABILITY_POINTER);
612 static void bind_ddm(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
614 printf("bind_ddm\n");
616 struct wl_resource *res = wl_resource_create(cli, &wl_data_device_manager_interface, version, id);
617 wl_resource_set_implementation(res, &ddm_iface, NULL, NULL);
620 static void bind_comp(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
622 printf("bind_comp\n");
623 struct wl_resource *res = wl_resource_create(cli, &wl_compositor_interface, version, id);
624 wl_resource_set_implementation(res, &comp_iface, NULL, NULL);
627 static void bind_shell(struct wl_client *cli, void *data, uint32_t version, uint32_t id)
629 printf("bind_shell\n");
630 struct wl_resource *res = wl_resource_create(cli, &wl_shell_interface, version, id);
631 wl_resource_set_implementation(res, &shell_iface, NULL, NULL);
634 /********************
636 ********************/
637 void sys_move(win_t *win, int x, int y, int w, int h)
639 printf("sys_move: %p - %d,%d %dx%d\n",
643 void sys_raise(win_t *win)
645 printf("sys_raise: %p\n", win);
648 void sys_focus(win_t *win)
650 printf("sys_focus: %p\n", win);
653 void sys_show(win_t *win, state_t state)
655 printf("sys_show: %p: %d\n", win, state);
658 void sys_watch(win_t *win, event_t ev, mod_t mod)
660 printf("sys_watch: %p - %x %hhx\n",
661 win, ev, mod2int(mod));
664 void sys_unwatch(win_t *win, event_t ev, mod_t mod)
666 printf("sys_unwatch: %p - %x %hhx\n",
667 win, ev, mod2int(mod));
670 list_t *sys_info(win_t *win)
672 printf("sys_info: %p\n", win);
673 return list_insert(NULL, win);
676 win_t *sys_init(void)
678 printf("sys_init\n");
680 /* Register log handler */
681 wl_log_set_handler_server((wl_log_func_t)vprintf);
683 /* Open the display */
684 if (!(display = wl_display_create()))
685 error("Unable to create display");
686 if (wl_display_add_socket(display, NULL) != 0)
687 error("Unable to add socket");
688 if (!(events = wl_display_get_event_loop(display)))
689 error("Unable to get event loop");
691 /* Register interfaces */
692 ref_shm = wl_global_create(display, &wl_shm_interface, 1, NULL, &bind_shm);
693 ref_output = wl_global_create(display, &wl_output_interface, 2, NULL, &bind_output);
694 ref_ddm = wl_global_create(display, &wl_data_device_manager_interface, 1, NULL, &bind_ddm);
695 ref_shell = wl_global_create(display, &wl_shell_interface, 1, NULL, &bind_shell);
696 ref_comp = wl_global_create(display, &wl_compositor_interface, 3, NULL, &bind_comp);
697 ref_seat = wl_global_create(display, &wl_seat_interface, 3, NULL, &bind_seat);
699 /* Setup GTK display */
700 gtk_init(&conf_argc, &conf_argv);
701 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
702 gtk_widget_add_events(window,
704 GDK_BUTTON_PRESS_MASK |
705 GDK_BUTTON_RELEASE_MASK |
706 GDK_POINTER_MOTION_MASK);
707 g_signal_connect(window, "destroy", G_CALLBACK(on_destroy), NULL);
708 g_signal_connect(window, "key-press-event", G_CALLBACK(on_key), NULL);
709 g_signal_connect(window, "button-press-event", G_CALLBACK(on_button), NULL);
710 g_signal_connect(window, "motion-notify-event", G_CALLBACK(on_move), NULL);
711 g_signal_connect(window, "draw", G_CALLBACK(on_draw), NULL);
712 g_timeout_add(1000/60, on_wayland, NULL);
713 gtk_widget_show(window);
718 void sys_run(win_t *root)
720 printf("sys_run: %p\n", root);
726 printf("sys_exit\n");
730 void sys_free(win_t *root)
732 printf("sys_free: %p\n", root);