#ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #ifndef __USE_GNU #define __USE_GNU #endif #include #include #include #include #include #include #include #include #include "backend.h" #define static void handler(int sig) { void *array[10]; size_t size; // get void*'s for all entries on the stack size = backtrace(array, 10); // print out all the frames to stderr fprintf(stderr, "Error: signal %d:\n", sig); backtrace_symbols_fd(array, size, STDERR_FILENO); exit(1); } #define BINDFUNC(interface, implementation) \ static void interface##_bind (struct wl_client *client, void *data, uint32_t version, uint32_t id) { \ printf ("bind: " #interface "\n"); \ struct wl_resource *resource = wl_resource_create (client, &interface##_interface, 1, id); \ if (resource == NULL) { \ wl_client_post_no_memory(client); \ return; \ } \ wl_resource_set_implementation (resource, &implementation, NULL, NULL); \ } struct lorie_composiror { struct wl_display *display; struct wl_list clients; struct wl_list surfaces; struct surface *main_surface; struct modifier_state modifier_state; uint32_t width, height; } c = {0}; struct client { struct wl_client *client; struct wl_resource *pointer; struct wl_resource *keyboard; struct wl_list link; }; static struct client *get_client (struct wl_client *_client) { struct client *client; wl_list_for_each (client, &c.clients, link) { if (client->client == _client) return client; } client = calloc (1, sizeof(struct client)); client->client = _client; wl_list_insert (&c.clients, &client->link); return client; } struct surface { struct wl_resource *surface; //struct wl_resource *xdg_surface; struct wl_resource *buffer; struct wl_resource *frame_callback; //int x, y; //struct texture texture; struct client *client; struct wl_list link; }; struct lorie_client { struct wl_client *client; struct wl_resource *pointer; struct wl_resource *keyboard; struct wl_list link; }; void *null = NULL; // region /*No op*/ static void region_destroy (struct wl_client *client, struct wl_resource *resource) {} /*No op*/ static void region_add (struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) {} /*No op*/ static void region_subtract (struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) {} /*No op*/ static struct wl_region_interface region_interface = {®ion_destroy, ®ion_add, ®ion_subtract}; // surface /*No op*/ static void surface_destroy (struct wl_client *client, struct wl_resource *resource) {} static void surface_attach (struct wl_client *client, struct wl_resource *resource, struct wl_resource *buffer, int32_t x, int32_t y) { struct surface *surface = wl_resource_get_user_data (resource); surface->buffer = buffer; c.main_surface = surface; } static void surface_damage (struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) { printf("Surface damage\n"); } static void surface_frame (struct wl_client *client, struct wl_resource *resource, uint32_t callback) { struct surface *surface = wl_resource_get_user_data (resource); surface->frame_callback = wl_resource_create (client, &wl_callback_interface, 1, callback); } /*No op*/ static void surface_set_opaque_region (struct wl_client *client, struct wl_resource *resource, struct wl_resource *region) {} /*No op*/ static void surface_set_input_region (struct wl_client *client, struct wl_resource *resource, struct wl_resource *region) {} static void surface_commit (struct wl_client *client, struct wl_resource *resource) { printf("Surface commit\n"); } /*No op*/ static void surface_set_buffer_transform (struct wl_client *client, struct wl_resource *resource, int32_t transform) {} /*No op*/ static void surface_set_buffer_scale (struct wl_client *client, struct wl_resource *resource, int32_t scale) {} static void surface_delete (struct wl_resource *resource) { struct surface *surface = wl_resource_get_user_data (resource); if (c.main_surface == surface) c.main_surface = NULL; wl_list_remove (&surface->link); free (surface); } static struct wl_surface_interface surface_interface = {&surface_destroy, &surface_attach, &surface_damage, &surface_frame, &surface_set_opaque_region, &surface_set_input_region, &surface_commit, &surface_set_buffer_transform, &surface_set_buffer_scale}; // compositor static void compositor_create_surface (struct wl_client *client, struct wl_resource *resource, uint32_t id) { struct surface *surface = calloc (1, sizeof(struct surface)); surface->surface = wl_resource_create (client, &wl_surface_interface, 3, id); wl_resource_set_implementation (surface->surface, &surface_interface, surface, &surface_delete); surface->client = get_client (client); wl_list_insert (&c.surfaces, &surface->link); } static void compositor_create_region (struct wl_client *client, struct wl_resource *resource, uint32_t id) { struct wl_resource *region = wl_resource_create (client, &wl_region_interface, 1, id); wl_resource_set_implementation (region, ®ion_interface, NULL, NULL); } static struct wl_compositor_interface compositor_interface = {&compositor_create_surface, &compositor_create_region}; BINDFUNC(wl_compositor, compositor_interface); // shell surface /*No op*/ static void shell_surface_pong (struct wl_client *client, struct wl_resource *resource, uint32_t serial) {} /*No op*/ static void shell_surface_move (struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, uint32_t serial) {} /*No op*/ static void shell_surface_resize (struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, uint32_t serial, uint32_t edges) {} /*No op*/ static void shell_surface_set_toplevel (struct wl_client *client, struct wl_resource *resource) {} /*No op*/ static void shell_surface_set_transient (struct wl_client *client, struct wl_resource *resource, struct wl_resource *parent, int32_t x, int32_t y, uint32_t flags) {} /*No op*/ static void shell_surface_set_fullscreen (struct wl_client *client, struct wl_resource *resource, uint32_t method, uint32_t framerate, struct wl_resource *output) {} /*No op*/ static void shell_surface_set_popup (struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat, uint32_t serial, struct wl_resource *parent, int32_t x, int32_t y, uint32_t flags) {} /*No op*/ static void shell_surface_set_maximized (struct wl_client *client, struct wl_resource *resource, struct wl_resource *output) {} /*No op*/ static void shell_surface_set_title (struct wl_client *client, struct wl_resource *resource, const char *title) {} /*No op*/ static void shell_surface_set_class (struct wl_client *client, struct wl_resource *resource, const char *class_) {} /*No op*/ static struct wl_shell_surface_interface shell_surface_interface = {&shell_surface_pong, &shell_surface_move, &shell_surface_resize, &shell_surface_set_toplevel, &shell_surface_set_transient, &shell_surface_set_fullscreen, &shell_surface_set_popup, &shell_surface_set_maximized, &shell_surface_set_title, &shell_surface_set_class}; // wl shell static void shell_get_shell_surface (struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface) { struct wl_resource *shell_surface = wl_resource_create (client, &wl_shell_surface_interface, 1, id); wl_resource_set_implementation (shell_surface, &shell_surface_interface, NULL, NULL); wl_shell_surface_send_configure(shell_surface, 0, c.width, c.height); } static struct wl_shell_interface shell_interface = {&shell_get_shell_surface}; BINDFUNC(wl_shell, shell_interface); // pointer /*No op*/ static void pointer_set_cursor (struct wl_client *client, struct wl_resource *resource, uint32_t serial, struct wl_resource *_surface, int32_t hotspot_x, int32_t hotspot_y) {} /*No op*/ static void pointer_release (struct wl_client *client, struct wl_resource *resource) {} /*No op*/ static struct wl_pointer_interface pointer_interface = {&pointer_set_cursor, &pointer_release}; // keyboard /*No op*/ static void keyboard_release (struct wl_client *client, struct wl_resource *resource) {} /*No op*/ static struct wl_keyboard_interface keyboard_interface = {&keyboard_release}; // seat static void seat_get_pointer (struct wl_client *client, struct wl_resource *resource, uint32_t id) { struct wl_resource *pointer = wl_resource_create (client, &wl_pointer_interface, 1, id); wl_resource_set_implementation (pointer, &pointer_interface, NULL, NULL); get_client(client)->pointer = pointer; } static void seat_get_keyboard (struct wl_client *client, struct wl_resource *resource, uint32_t id) { struct wl_resource *keyboard = wl_resource_create (client, &wl_keyboard_interface, 1, id); wl_resource_set_implementation (keyboard, &keyboard_interface, NULL, NULL); //get_client(client)->keyboard = keyboard; //int fd, size; //backend_get_keymap (&fd, &size); //wl_keyboard_send_keymap (keyboard, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, fd, size); //close (fd); } /*No op*/ static void seat_get_touch (struct wl_client *client, struct wl_resource *resource, uint32_t id) {} static struct wl_seat_interface seat_interface = {&seat_get_pointer, &seat_get_keyboard, &seat_get_touch}; static void wl_seat_bind (struct wl_client *client, void *data, uint32_t version, uint32_t id) { printf ("bind: wl_seat\n"); struct wl_resource *seat = wl_resource_create (client, &wl_seat_interface, 1, id); wl_resource_set_implementation (seat, &seat_interface, NULL, NULL); wl_seat_send_capabilities (seat, WL_SEAT_CAPABILITY_POINTER|WL_SEAT_CAPABILITY_KEYBOARD); } static void output_release(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); } static const struct wl_output_interface output_interface = { output_release, }; static void wl_output_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) { int DPI = 240; struct wl_resource *resource = wl_resource_create(client, &wl_output_interface, version, id); if (resource == NULL) { wl_client_post_no_memory(client); return; } wl_resource_set_implementation(resource, &output_interface, NULL, NULL); int mm_width = c.width/DPI*25; int mm_height = c.height/DPI*25; wl_output_send_geometry(resource, c.width, c.height, mm_width, mm_height, 0, "non-weston", "none", 0); if (version >= WL_OUTPUT_SCALE_SINCE_VERSION) wl_output_send_scale(resource, 1.0); wl_output_send_mode(resource, 3, c.width, c.height, 60000); if (version >= WL_OUTPUT_DONE_SINCE_VERSION) wl_output_send_done(resource); } // backend callbacks /*No op*/ static void handle_resize_event (int width, int height) {} /*No op*/ static void handle_draw_event (void) {} static void handle_mouse_motion_event (int x, int y) { if (!c.main_surface || !c.main_surface->client->pointer) return; wl_fixed_t surface_x = wl_fixed_from_double (x); wl_fixed_t surface_y = wl_fixed_from_double (y); wl_pointer_send_motion (c.main_surface->client->pointer, backend_get_timestamp(), surface_x, surface_y); } static void handle_mouse_button_event (int button, int state) { if (!c.main_surface || !c.main_surface->client->pointer) return; wl_pointer_send_button (c.main_surface->client->pointer, 0, backend_get_timestamp(), button, state); } static void handle_key_event (int key, int state) { //if (!c.main_surface || !c.main_surface->client->keyboard) return; //wl_keyboard_send_key (c.main_surface->client->keyboard, 0, backend_get_timestamp(), key, state); } static void handle_modifiers_changed (struct modifier_state new_state) { //if (new_state.depressed == c.modifier_state.depressed && new_state.latched == c.modifier_state.latched && new_state.locked == c.modifier_state.locked && new_state.group == c.modifier_state.group) return; //c.modifier_state = new_state; //if (c.main_surface && c.main_surface->client->keyboard) // wl_keyboard_send_modifiers (c.main_surface->client->keyboard, 0, c.modifier_state.depressed, c.modifier_state.latched, c.modifier_state.locked, c.modifier_state.group); } static struct callbacks callbacks = {&handle_resize_event, &handle_draw_event, &handle_mouse_motion_event, &handle_mouse_button_event, &handle_key_event, &handle_modifiers_changed}; void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * data); static void draw (void) { glClearColor (1, 1, 0, 1); glClear (GL_COLOR_BUFFER_BIT); //glLoadIdentity(); struct surface *surface = c.main_surface; if (!surface) { return; } //wl_list_for_each_reverse (surface, &c.surfaces, link) { if (surface) { struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (surface->buffer); if (shm_buffer == NULL) return; //if (shm_buffer == NULL) continue; uint32_t width = wl_shm_buffer_get_width (shm_buffer); uint32_t height = wl_shm_buffer_get_height (shm_buffer); void *data = wl_shm_buffer_get_data (shm_buffer); if (data) { printf("Showing %dx%d window\n", width, height); glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); backend_swap_buffers(); wl_buffer_send_release (surface->buffer); usleep(500000); } } glFlush (); backend_swap_buffers (); } int main(void) { printf("Starting lorie server\n"); signal(SIGSEGV, handler); backend_init (&callbacks); //setenv("WAYLAND_DEBUG", "1", 1); memset(&c, 0, sizeof(c)); wl_list_init (&c.clients); wl_list_init (&c.surfaces); c.width = 1024; c.height = 600; c.display = wl_display_create (); wl_display_add_socket_auto (c.display); wl_global_create (c.display, &wl_compositor_interface, 4, NULL, &wl_compositor_bind); wl_global_create (c.display, &wl_shell_interface, 1, NULL, &wl_shell_bind); wl_global_create (c.display, &wl_seat_interface, 5, NULL, &wl_seat_bind); wl_global_create (c.display, &wl_output_interface, 3, NULL, &wl_output_bind); wl_display_init_shm (c.display); struct wl_event_loop *event_loop = wl_display_get_event_loop (c.display); int wayland_fd = wl_event_loop_get_fd (event_loop); while (1) { wl_event_loop_dispatch (event_loop, 0); backend_dispatch_nonblocking (); wl_display_flush_clients (c.display); draw (); backend_wait_for_events (wayland_fd); } wl_display_destroy (c.display); return 0; }