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
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel