#include <assert.h>
#include <stdlib.h>
+
#include <wayland-client.h>
-#include "backend.h"
#include "libds/log.h"
#include "libds/output.h"
-
#include "xdg-shell-client-protocol.h"
+#include "output.h"
+#include "backend.h"
+
const struct ds_output_interface wl_output_iface;
static const struct xdg_surface_listener wl_output_xdg_surface_listener;
static const struct xdg_toplevel_listener wl_output_xdg_toplevel_listener;
+static void output_update_cursor(struct ds_wl_output *output);
+static bool output_set_custom_mode(struct ds_output *ds_output,
+ int32_t width, int32_t height, int32_t refresh);
+
struct ds_output *
ds_wl_backend_create_output(struct ds_backend *ds_backend)
{
- ds_wl_backend_t *backend;
- ds_wl_output_t *output;
+ struct ds_wl_backend *backend;
+ struct ds_wl_output *output;
backend = wl_backend_from_backend(ds_backend);
+ if (!ds_backend->started) {
+ backend->requested_outputs++;
+ return NULL;
+ }
+
+ output = create_wl_output(backend);
+ if (!output) {
+ ds_err("Could not create ds_wl_output");
+ return NULL;
+ }
+
+ return &output->base;
+}
+
+struct ds_wl_output *
+create_wl_output(struct ds_wl_backend *backend)
+{
+ struct ds_wl_output *output;
+
output = calloc(1, sizeof *output);
if (!output) {
ds_log_errno(DS_ERR, "Could not allocate ds_wl_output");
ds_dbg("Wayland output(%p) created", output);
- return &output->base;
+ return output;
err:
ds_output_destroy(&output->base);
}
void
-destroy_wl_buffer(ds_wl_buffer_t *buffer)
+destroy_wl_buffer(struct ds_wl_buffer *buffer)
{
if (buffer == NULL)
return;
free(buffer);
}
-static ds_wl_output_t *
+void
+output_enter_pointer(struct ds_wl_output *output,
+ struct ds_wl_pointer *pointer, uint32_t serial)
+{
+ output->cursor.pointer = pointer;
+ output->cursor.enter_serial = serial;
+
+ output_update_cursor(output);
+}
+
+void
+output_leave_pointer(struct ds_wl_output *output)
+{
+ output->cursor.pointer = NULL;
+ output->cursor.enter_serial = 0;
+}
+
+static void output_update_cursor(struct ds_wl_output *output)
+{
+ struct ds_wl_pointer *pointer = output->cursor.pointer;
+
+ wl_pointer_set_cursor(pointer->wl_pointer, output->cursor.enter_serial,
+ output->cursor.surface, output->cursor.hotspot_x,
+ output->cursor.hotspot_y);
+}
+
+static struct ds_wl_output *
wl_output_from_output(struct ds_output *ds_output)
{
assert(ds_output->iface == &wl_output_iface);
- return (ds_wl_output_t *)ds_output;
+ return (struct ds_wl_output *)ds_output;
}
static void
wl_output_iface_destroy(struct ds_output *ds_output)
{
- ds_wl_output_t *output;
+ struct ds_wl_output *output;
output = wl_output_from_output(ds_output);
}
static struct wl_buffer *
-import_shm(ds_wl_backend_t *backend, struct ds_shm_attributes *shm)
+import_shm(struct ds_wl_backend *backend, struct ds_shm_attributes *shm)
{
enum wl_shm_format wl_shm_format = WL_SHM_FORMAT_XRGB8888;
struct wl_shm_pool *pool;
static void
buffer_handle_release(void *data, struct wl_buffer *wl_buffer)
{
- ds_wl_buffer_t *buffer = data;
+ struct ds_wl_buffer *buffer = data;
ds_dbg("Wayland output: Buffer(%p) released.", buffer->buffer);
buffer->released = true;
ds_buffer_unlock(buffer->buffer);
}
-static const struct wl_buffer_listener buffer_listener = {
+static const struct wl_buffer_listener buffer_listener =
+{
.release = buffer_handle_release,
};
static void
buffer_handle_buffer_destroy(struct wl_listener *listener, void *data)
{
- ds_wl_buffer_t *buffer;
+ struct ds_wl_buffer *buffer;
buffer = wl_container_of(listener, buffer, buffer_destroy);
destroy_wl_buffer(buffer);
}
-static ds_wl_buffer_t *
-create_wl_buffer(ds_wl_backend_t *backend, struct ds_buffer *ds_buffer)
+static struct ds_wl_buffer *
+create_wl_buffer(struct ds_wl_backend *backend, struct ds_buffer *ds_buffer)
{
struct ds_shm_attributes shm;
- ds_wl_buffer_t *buffer;
+ struct ds_wl_buffer *buffer;
struct wl_buffer *wl_buffer;
if (ds_buffer_get_shm(ds_buffer, &shm)) {
return buffer;
}
-static ds_wl_buffer_t *
-get_or_create_wl_buffer(ds_wl_backend_t *backend, struct ds_buffer *ds_buffer)
+static struct ds_wl_buffer *
+get_or_create_wl_buffer(struct ds_wl_backend *backend, struct ds_buffer *ds_buffer)
{
- ds_wl_buffer_t *buffer;
+ struct ds_wl_buffer *buffer;
wl_list_for_each(buffer, &backend->buffers, link) {
if (buffer->buffer == ds_buffer && buffer->released) {
static void
surface_frame_callback(void *data, struct wl_callback *cb, uint32_t time)
{
- ds_wl_output_t *output = data;
+ struct ds_wl_output *output = data;
wl_callback_destroy(cb);
output->frame_callback = NULL;
wl_signal_emit(&output->base.events.frame, &output->base);
}
-static const struct wl_callback_listener frame_listener = {
+static const struct wl_callback_listener frame_listener =
+{
.done = surface_frame_callback
};
static bool
wl_output_iface_commit(struct ds_output *ds_output)
{
- ds_wl_output_t *output;
- ds_wl_buffer_t *buffer;
+ struct ds_wl_output *output;
+ struct ds_wl_buffer *buffer;
struct ds_buffer *ds_buffer;
output = wl_output_from_output(ds_output);
+ if (ds_output->pending.committed & DS_OUTPUT_STATE_MODE) {
+ if (!output_set_custom_mode(ds_output,
+ ds_output->pending.custom_mode.width,
+ ds_output->pending.custom_mode.height,
+ ds_output->pending.custom_mode.refresh))
+ return false;
+ }
+
ds_buffer = ds_output->pending.buffer;
buffer = get_or_create_wl_buffer(output->backend, ds_buffer);
if (!buffer)
wl_surface_attach(output->surface, buffer->wl_buffer, 0, 0);
wl_surface_damage_buffer(output->surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(output->surface);
-
- ds_dbg("Swap Buffer!!!!!");
}
wl_display_flush(output->backend->server.display);
int32_t width, int32_t height, struct wl_array *states)
{
// TODO
- // ds_wl_output_t *output = data;
+ // struct ds_wl_output *output = data;
if (width == 0 || height == 0)
return;
wl_output_xdg_toplevel_handle_close(void *data,
struct xdg_toplevel *xdg_toplevel)
{
- ds_wl_output_t *output = data;
+ struct ds_wl_output *output = data;
ds_output_destroy(&output->base);
}
.configure = wl_output_xdg_toplevel_handle_configure,
.close = wl_output_xdg_toplevel_handle_close,
};
+
+static bool output_set_custom_mode(struct ds_output *ds_output,
+ int32_t width, int32_t height, int32_t refresh)
+{
+ ds_output_update_custom_mode(ds_output, width, height, 0);
+
+ return true;
+}