Hello, I am making a simple wayland client using the simple-shm, simple-egl and fullscreen as a guide; while the surface is displayed and updated correctly on weston attempting to move the surface on pointer move event by calling xdg_surface_move will sometimes(almost always, sometimes the surface actually moves with no problems) make the client crash with a Segmentation fault (core dumped). Is there any minimum requirement I am missing to handle this feature the right way? Or is my main loop handled incorrectly? Is the double buffer swapping implemented on simple-shm really neccesary?
Wayland and weston version: 1.9.0, the code is send as an attachment. Any help would be appreciated. Thanks.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <wayland-client.h> #include <wayland-cursor.h> #include <cairo/cairo.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #include <linux/input.h> #include "xdg-shell-client-protocol.h" #define BUFFER 1024 * 1024 * 10 enum colors { CYAN = 150, MAGENTA = 250, BLACK = 350, YELLOW = 450 }; struct display { struct wl_display* display; struct wl_registry* registry; struct wl_compositor* compositor; struct wl_shm* shm; struct wl_shm_pool* shm_pool; struct xdg_shell* xdg_shell; struct wl_seat* seat; struct wl_pointer* pointer; struct wl_output* output; struct wl_cursor_theme* cursor_theme; struct wl_cursor *default_cursor; int format; int fd; int serial; } display; struct window { int width; int height; int bytes; struct wl_buffer* buffer; struct wl_surface* surface; struct xdg_surface* xdg_surface; struct wl_callback* callback; cairo_surface_t* cairo_surface; cairo_t* cr; cairo_pattern_t* linpat; void* shm_data; enum colors current_color; int fullscreen; int focused; }; void global(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version) { printf("interface: %s \t version: %i \n", interface, version); struct display* display = data; if(strcmp(interface, "wl_compositor") == 0) display->compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3); if(strcmp(interface, "wl_shm") == 0) { display->shm = wl_registry_bind(wl_registry, name, &wl_shm_interface, 1); display->cursor_theme = wl_cursor_theme_load(NULL, 32, display->shm); if (!display->cursor_theme) { fprintf(stderr, "unable to load default theme\n"); return; } display->default_cursor = wl_cursor_theme_get_cursor(display->cursor_theme, "left_ptr"); if (!display->default_cursor) { fprintf(stderr, "unable to load default left pointer\n"); return; } } if(strcmp(interface, "wl_seat") == 0) display->seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 4); if(strcmp(interface, "xdg_shell") == 0) { display->xdg_shell = wl_registry_bind(wl_registry, name, &xdg_shell_interface, 1); xdg_shell_use_unstable_version(display->xdg_shell, XDG_SHELL_VERSION_CURRENT); } if(strcmp(interface, "wl_output") == 0) { display->output = wl_registry_bind(wl_registry, name, &wl_output_interface, 2); } } const struct wl_registry_listener registry_listener = { global }; void format(void *data, struct wl_shm *wl_shm, uint32_t format) { struct display* display = data; if(format == WL_SHM_FORMAT_ARGB8888) { display->format = format; } } const struct wl_shm_listener shm_listener = { format }; void xdg_ping(void *data, struct xdg_shell *xdg_shell, uint32_t serial) { xdg_shell_pong(xdg_shell, serial); } const struct xdg_shell_listener xdg_shell_listener = { xdg_ping }; void enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { display.serial = serial; } void leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) { display.serial = serial; } void motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { } void button(void *data, struct wl_pointer *wl_pointer, uint32_t serial,uint32_t time, uint32_t button, uint32_t state) { struct window* w = data; display.serial = serial; if (!w->xdg_surface) return; if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) xdg_surface_move(w->xdg_surface, display.seat, serial); } void axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { if(axis == WL_POINTER_AXIS_VERTICAL_SCROLL) printf("scrolling vertical!!: %i\n", value); if(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) printf("scrolling horizontal !!: %i\n", value); } const struct wl_pointer_listener pointer_listener = { enter, leave, motion, button, axis }; static const struct wl_callback_listener frame_listener; void redraw(void *data, struct wl_callback *wl_callback, uint32_t callback_data) { struct window* w = data; switch (w->current_color) { case CYAN: cairo_set_source_rgb(w->cr, 0.96, 0, 0.52); //MAGENTA w->current_color = MAGENTA; break; case MAGENTA: cairo_set_source_rgb(w->cr, 0, 0, 0); //BLACK w->current_color = BLACK; break; case BLACK: cairo_set_source_rgb(w->cr, 1, 1, 0); //YELLOW w->current_color = YELLOW; break; case YELLOW: cairo_set_source_rgb(w->cr, 0, 1, 1); //CYAN w->current_color = CYAN; break; } cairo_rectangle(w->cr, 0, 0, w->width, w->height); cairo_fill (w->cr); wl_surface_attach(w->surface, w->buffer, 0, 0); wl_surface_damage(w->surface, 0, 0, w->width, w->height); if (wl_callback) wl_callback_destroy(wl_callback); w->callback = wl_surface_frame(w->surface); wl_callback_add_listener(w->callback, &frame_listener, w); unsigned long int c = 0; do{ c++; }while(c < 400000000); wl_surface_commit(w->surface); } static const struct wl_callback_listener frame_listener = { redraw }; void xdg_configure(void *data, struct xdg_surface *xdg_surface, int32_t width, int32_t height, struct wl_array *states, uint32_t serial) { struct window* w = data; uint32_t *p; wl_array_for_each(p, states) { uint32_t state = *p; switch (state) { case XDG_SURFACE_STATE_FULLSCREEN: w->fullscreen = 1; printf(" FULLSCREEN \n"); break; case XDG_SURFACE_STATE_ACTIVATED: w->focused = 1; printf(" ACTIVATED \n" ); break; default: break; } } xdg_surface_ack_configure(xdg_surface, serial); } void xdg_close(void *data, struct xdg_surface *xdg_surface) { } const struct xdg_surface_listener xdg_surface_listener = { xdg_configure, xdg_close }; int temp_buffer_file(int size, char* temp_buffer_path) { const char template[] = "/shared-shm-XXXXXX"; const char* path = getenv("XDG_RUNTIME_DIR"); char* name = (char*) malloc(strlen(path) + sizeof(template)); strcpy(name, path); strcat(name, template); int fd = mkstemp(name); int ret = posix_fallocate(fd, 0, size); if (ret == 0) { printf("POSIX ALLOCATE SUCCES\n"); unlink(name); } strcpy(temp_buffer_path, name); free(name); return fd; } struct wl_buffer* create_buffer(int width, int height, int bytes) { return wl_shm_pool_create_buffer(display.shm_pool, 0, width, height, bytes, display.format); } int main() { display.display = wl_display_connect("wayland-0"); display.registry = wl_display_get_registry(display.display); wl_registry_add_listener(display.registry, ®istry_listener, &display); wl_display_roundtrip(display.display); wl_shm_add_listener(display.shm, &shm_listener, &display); display.pointer = wl_seat_get_pointer(display.seat); wl_pointer_add_listener(display.pointer, &pointer_listener, &display); wl_display_roundtrip(display.display); display.fd = temp_buffer_file(BUFFER, (char*) malloc(sizeof(char) * 100)); display.shm_pool = wl_shm_create_pool(display.shm, display.fd, BUFFER); //creating a "window" struct window* w = malloc(sizeof(struct window*)); w->width = 640; w->height = 480; w->bytes = 4 * w->width; w->buffer = create_buffer(w->width, w->height, w->bytes); w->surface = wl_compositor_create_surface(display.compositor); w->xdg_surface = xdg_shell_get_xdg_surface(display.xdg_shell, w->surface); w->current_color = CYAN; w->fullscreen = 0; w->focused = 0; xdg_surface_set_title(w->xdg_surface, "window_title"); xdg_surface_set_app_id(w->xdg_surface, "app_id"); xdg_shell_add_listener(display.xdg_shell, &xdg_shell_listener, w); xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w); w->shm_data = mmap(NULL, w->bytes * w->height, PROT_READ | PROT_WRITE, MAP_SHARED, display.fd, 0); //cairo stuff int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w->width); w->cairo_surface = cairo_image_surface_create_for_data((unsigned char*)w->shm_data,CAIRO_FORMAT_ARGB32, w->width, w->height, stride); w->cr = cairo_create(w->cairo_surface); cairo_set_source_rgb(w->cr, 0, 1, 1); cairo_rectangle(w->cr, 0, 0, w->width, w->height); cairo_fill (w->cr); wl_surface_attach(w->surface, w->buffer, 0, 0); wl_surface_damage(w->surface, 0, 0, w->width, w->height); redraw(w, NULL, 0); wl_display_flush(display.display); int ret = 0; while ( ret != -1 ) { ret = wl_display_dispatch(display.display); } return 0; }
_______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel