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, &registry_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

Reply via email to