summaryrefslogtreecommitdiff
path: root/src/surface
diff options
context:
space:
mode:
authorVincent Sanders <vincent.sanders@collabora.co.uk>2013-03-22 16:59:27 +0000
committerVincent Sanders <vincent.sanders@collabora.co.uk>2013-03-22 16:59:27 +0000
commit433c8b3244b4c4e665aac5510e50d0f2dbe93d31 (patch)
tree5f0a3240e15e9af61988b9f9e041a126fe37d4f6 /src/surface
parentf75a698b15f978c854cc424ee79a38e157165091 (diff)
downloadlibnsfb-433c8b3244b4c4e665aac5510e50d0f2dbe93d31.tar.gz
libnsfb-433c8b3244b4c4e665aac5510e50d0f2dbe93d31.tar.bz2
basic window opening working
Diffstat (limited to 'src/surface')
-rw-r--r--src/surface/wld.c287
1 files changed, 234 insertions, 53 deletions
diff --git a/src/surface/wld.c b/src/surface/wld.c
index d450738..ded996d 100644
--- a/src/surface/wld.c
+++ b/src/surface/wld.c
@@ -13,15 +13,22 @@
#include <stdio.h>
#include <string.h>
-#include <sys/ipc.h>
-#include <sys/shm.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#if 0
#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
#include <xcb/xcb_atom.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_keysyms.h>
+#endif
+#include <wayland-client.h>
#include "libnsfb.h"
#include "libnsfb_event.h"
@@ -33,6 +40,8 @@
#include "plot.h"
#include "cursor.h"
+#if 0
+
#if defined(NSFB_NEED_HINTS_ALLOC)
static xcb_size_hints_t *
xcb_alloc_size_hints(void)
@@ -574,11 +583,14 @@ xcopy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
}
+#endif
+
static int
wld_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
{
}
+#if 0
static int
x_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
{
@@ -766,6 +778,7 @@ create_blank_cursor(xcb_connection_t *conn, const xcb_screen_t *scr)
}
return cur;
}
+#endif
/** structure for display, registry and other global objects that
* should be cached when connecting to a wayland instance
@@ -794,19 +807,19 @@ struct wld_connection {
};
-/** shared memory interface format available callback
+/** shared memory interface format available callback
*
* @param ctx context from when listener was added.
- * @param wl_shm The shared memory object.
- * @param format The available shared memory format. Found in
- * wayland-client-protocol.h there are currently only two
+ * @param wl_shm The shared memory object.
+ * @param format The available shared memory format. Found in
+ * wayland-client-protocol.h there are currently only two
* formats available (A|X)RGB8888 so using a bitfield is ok.
*/
static void
shm_format(void *ctx, struct wl_shm *wl_shm, uint32_t format)
{
struct wld_connection* connection = ctx;
-
+
connection->shm_formats |= (1 << format);
}
@@ -818,7 +831,7 @@ struct wl_shm_listener shm_listenter = {
/** registry global addition callback
*
- * @param ctx context from when listener was added
+ * @param ctx context from when listener was added
*/
static void
registry_handle_global(void *ctx,
@@ -850,8 +863,8 @@ registry_handle_global(void *ctx,
* and add a listener for the shared memory callbacks
*/
connection->shm = wl_registry_bind(registry,
- id,
- &wl_shm_interface,
+ id,
+ &wl_shm_interface,
1);
if (connection->shm != NULL) {
connection->shm_formats = 0;
@@ -875,6 +888,30 @@ static const struct wl_registry_listener registry_listener = {
};
+static void
+free_connection(struct wld_connection* connection)
+{
+ if (connection->compositor != NULL) {
+ wl_compositor_destroy(connection->compositor);
+ }
+
+ if (connection->shell != NULL) {
+ wl_shell_destroy(connection->shell);
+ }
+
+ if (connection->shm != NULL) {
+ wl_shm_destroy(connection->shm);
+ }
+
+ wl_registry_destroy(connection->registry);
+
+ wl_display_flush(connection->display);
+
+ wl_display_disconnect(connection->display);
+
+ free(connection);
+}
+
/** construct a new connection to the wayland instance and aquire all
* necessary global objects
*/
@@ -928,7 +965,7 @@ new_connection(void)
wl_display_roundtrip(connection->display);
/* check the XRGB8888 shared memory format is available */
- if (!(display->formats & (1 << WL_SHM_FORMAT_XRGB8888))) {
+ if (!(connection->shm_formats & (1 << WL_SHM_FORMAT_XRGB8888))) {
fprintf(stderr, "WL_SHM_FORMAT_XRGB8888 not available\n");
free_connection(connection);
@@ -939,33 +976,11 @@ new_connection(void)
return connection;
}
-static void
-free_connection(struct wld_connection* connection)
-{
- if (connection->compositor != NULL) {
- wl_compositor_destroy(connection->compositor);
- }
-
- if (connection->shell != NULL) {
- wl_shell_destroy(connection->shell);
- }
-
- if (connection->shm != NULL) {
- wl_shm_destroy(connection->shm);
- }
-
- wl_registry_destroy(connection->registry);
-
- wl_display_flush(connection->display);
-
- wl_display_disconnect(connection->display);
-
- free(connection);
-}
typedef struct wldstate_s {
struct wld_connection* connection; /**< connection to wayland server */
struct wld_window *window;
+ struct wld_shm_buffer *shm_buffer;
#if 0
xcb_connection_t *connection; /* The x server connection */
xcb_screen_t *screen; /* The screen to put the window on */
@@ -989,14 +1004,8 @@ struct wld_window {
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
- struct wl_callback *callback;
int width, height;
-
-#if 0
- struct buffer buffers[2];
- struct buffer *prev_buffer;
-#endif
};
static void
@@ -1034,7 +1043,6 @@ new_window(struct wld_connection *connection, int width, int height)
}
window->connection = connection;
- window->callback = NULL;
window->width = width;
window->height = height;
@@ -1069,10 +1077,6 @@ new_window(struct wld_connection *connection, int width, int height)
static void
free_window(struct wld_window *window)
{
- if (window->callback != NULL) {
-
- wl_callback_destroy(window->callback);
- }
wl_shell_surface_destroy(window->shell_surface);
wl_surface_destroy(window->surface);
@@ -1080,6 +1084,143 @@ free_window(struct wld_window *window)
free(window);
}
+/*
+ * Create a new, unique, anonymous file of the given size, and
+ * return the file descriptor for it. The file descriptor is set
+ * CLOEXEC. The file is immediately suitable for mmap()'ing
+ * the given size at offset zero.
+ *
+ * The file should not have a permanent backing store like a disk,
+ * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
+ *
+ * The file name is deleted from the file system.
+ *
+ * The file is suitable for buffer sharing between processes by
+ * transmitting the file descriptor over Unix sockets using the
+ * SCM_RIGHTS methods.
+ */
+static int
+os_create_anonymous_file(off_t size)
+{
+ static const char template[] = "/weston-shared-XXXXXX";
+ const char *path;
+ char *name;
+ int fd;
+
+ path = getenv("XDG_RUNTIME_DIR");
+ if (!path) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ name = malloc(strlen(path) + sizeof(template));
+ if (!name)
+ return -1;
+
+ strcpy(name, path);
+ strcat(name, template);
+
+ fd = mkostemp(name, O_CLOEXEC);
+ if (fd >= 0)
+ unlink(name);
+
+ free(name);
+
+ if (fd < 0)
+ return -1;
+
+ if (ftruncate(fd, size) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+struct wld_shm_buffer {
+ struct wl_buffer *buffer; /**< wayland buffer object */
+ void *data; /**< mapped memory */
+ int size; /**< size of mapped memory */
+ bool inuse; /**< flag to indicate if the buffer has been released
+ * after commit to a surface.
+ */
+};
+
+static void
+buffer_release(void *data, struct wl_buffer *buffer)
+{
+ struct wld_shm_buffer *shmbuf = data;
+
+ shmbuf->inuse = false;
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+ buffer_release
+};
+
+static struct wld_shm_buffer *
+new_shm_buffer(struct wl_shm *shm,
+ int width,
+ int height,
+ uint32_t format)
+{
+ struct wl_shm_pool *pool;
+ struct wld_shm_buffer *shmbuff;
+ int fd;
+ int stride;
+
+ shmbuff = calloc(1, sizeof(struct wld_shm_buffer));
+ if (shmbuff == NULL) {
+ return NULL;
+ }
+
+ stride = width * 4;
+ shmbuff->size = stride * height;
+
+ fd = os_create_anonymous_file(shmbuff->size);
+ if (fd < 0) {
+ free(shmbuff);
+ return NULL;
+ }
+
+ shmbuff->data = mmap(NULL,
+ shmbuff->size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ fd,
+ 0);
+ if (shmbuff->data == MAP_FAILED) {
+ close(fd);
+ free(shmbuff);
+ return NULL;
+ }
+
+ pool = wl_shm_create_pool(shm, fd, shmbuff->size);
+ shmbuff->buffer = wl_shm_pool_create_buffer(pool,
+ 0,
+ width,
+ height,
+ stride,
+ format);
+ wl_shm_pool_destroy(pool);
+ close(fd);
+
+ if (shmbuff->buffer == NULL) {
+ munmap(shmbuff->data, shmbuff->size);
+ free(shmbuff);
+ return NULL;
+ }
+
+ wl_buffer_add_listener(shmbuff->buffer, &buffer_listener, shmbuff);
+
+ return shmbuff;
+}
+
+static void free_shm_buffer(struct wld_shm_buffer *shmbuf)
+{
+ munmap(shmbuf->data, shmbuf->size);
+ free(shmbuf);
+}
static int wld_initialise(nsfb_t *nsfb)
{
@@ -1101,19 +1242,38 @@ static int wld_initialise(nsfb_t *nsfb)
wldstate->connection = new_connection();
if (wldstate->connection == NULL) {
fprintf(stderr, "Error initialising wayland connection\n");
+
free(wldstate);
+
return -1; /* error */
}
- wldstate->window = new_window(wldstate->connection,
- nsfb->width,
+ wldstate->window = new_window(wldstate->connection,
+ nsfb->width,
nsfb->height);
- if (wldstate->connection == NULL) {
+ if (wldstate->window == NULL) {
fprintf(stderr, "Error creating wayland window\n");
free_connection(wldstate->connection);
free(wldstate);
+
+ return -1; /* error */
+ }
+
+ wldstate->shm_buffer = new_shm_buffer(wldstate->connection->shm,
+ nsfb->width,
+ nsfb->height,
+ WL_SHM_FORMAT_XRGB8888);
+ if (wldstate->shm_buffer == NULL) {
+ fprintf(stderr, "Error creating wayland shared memory\n");
+
+ free_window(wldstate->window);
+
+ free_connection(wldstate->connection);
+
+ free(wldstate);
+
return -1; /* error */
}
@@ -1130,11 +1290,14 @@ static int wld_finalise(nsfb_t *nsfb)
return 0; /* not initialised */
}
+ free_shm_buffer(wldstate->shm_buffer);
+
free_window(wldstate->window);
free_connection(wldstate->connection);
}
+#if 0
static int x_initialise(nsfb_t *nsfb)
{
uint32_t mask;
@@ -1265,11 +1428,29 @@ static int x_finalise(nsfb_t *nsfb)
return 0;
}
+#endif
static bool wld_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
{
+ wldstate_t *wldstate = nsfb->surface_priv;
+ int ret = 0;
+
+ if (wldstate == NULL) {
+ return false;
+ }
+
+ ret = wl_display_dispatch(wldstate->connection->display);
+ if (ret == -1) {
+ /* error, time to quit */
+ event->type = NSFB_EVENT_CONTROL;
+ event->value.controlcode = NSFB_CONTROL_QUIT;
+ return true;
+ }
+
+ return false;
}
+#if 0
static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
{
xcb_generic_event_t *e;
@@ -1423,13 +1604,10 @@ static bool x_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
return true;
}
+#endif
static int wld_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
{
-}
-
-static int x_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
-{
struct nsfb_cursor_s *cursor = nsfb->cursor;
if ((cursor != NULL) &&
@@ -1440,12 +1618,12 @@ static int x_claim(nsfb_t *nsfb, nsfb_bbox_t *box)
return 0;
}
-
static int
wld_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
{
}
+#if 0
static int
x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
{
@@ -1477,11 +1655,13 @@ x_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
}
return true;
}
+#endif
static int wld_update(nsfb_t *nsfb, nsfb_bbox_t *box)
{
}
+#if 0
static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box)
{
xstate_t *xstate = nsfb->surface_priv;
@@ -1496,6 +1676,7 @@ static int x_update(nsfb_t *nsfb, nsfb_bbox_t *box)
return 0;
}
+#endif
const nsfb_surface_rtns_t wld_rtns = {
.initialise = wld_initialise,