aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/gamma-control.c195
-rw-r--r--examples/idle-inhibit.c4
-rw-r--r--examples/idle.c22
-rw-r--r--examples/layer-shell.c2
-rw-r--r--examples/meson.build154
-rw-r--r--examples/multi-pointer.c20
-rw-r--r--examples/output-layout.c12
-rw-r--r--examples/pointer.c11
-rw-r--r--examples/rotation.c11
-rw-r--r--examples/simple.c45
-rw-r--r--examples/tablet.c13
-rw-r--r--examples/toplevel-decoration.c253
-rw-r--r--examples/touch.c11
13 files changed, 652 insertions, 101 deletions
diff --git a/examples/gamma-control.c b/examples/gamma-control.c
new file mode 100644
index 00000000..a060b883
--- /dev/null
+++ b/examples/gamma-control.c
@@ -0,0 +1,195 @@
+#define _POSIX_C_SOURCE 200809L
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wayland-client-protocol.h>
+#include <wayland-client.h>
+#include "wlr-gamma-control-unstable-v1-client-protocol.h"
+
+struct output {
+ struct wl_output *wl_output;
+ struct zwlr_gamma_control_v1 *gamma_control;
+ uint32_t ramp_size;
+ int table_fd;
+ uint16_t *table;
+ struct wl_list link;
+};
+
+static struct wl_list outputs;
+static struct zwlr_gamma_control_manager_v1 *gamma_control_manager = NULL;
+
+static int create_anonymous_file(off_t size) {
+ char template[] = "/tmp/wlroots-shared-XXXXXX";
+ int fd = mkstemp(template);
+ if (fd < 0) {
+ return -1;
+ }
+
+ int ret;
+ do {
+ errno = 0;
+ ret = ftruncate(fd, size);
+ } while (errno == EINTR);
+ if (ret < 0) {
+ close(fd);
+ return -1;
+ }
+
+ unlink(template);
+ return fd;
+}
+
+static int create_gamma_table(uint32_t ramp_size, uint16_t **table) {
+ size_t table_size = ramp_size * 3 * sizeof(uint16_t);
+ int fd = create_anonymous_file(table_size);
+ if (fd < 0) {
+ fprintf(stderr, "failed to create anonymous file\n");
+ return -1;
+ }
+
+ void *data =
+ mmap(NULL, table_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (data == MAP_FAILED) {
+ fprintf(stderr, "failed to mmap()\n");
+ close(fd);
+ return -1;
+ }
+
+ *table = data;
+ return fd;
+}
+
+static void gamma_control_handle_gamma_size(void *data,
+ struct zwlr_gamma_control_v1 *gamma_control, uint32_t ramp_size) {
+ struct output *output = data;
+ output->ramp_size = ramp_size;
+ output->table_fd = create_gamma_table(ramp_size, &output->table);
+ if (output->table_fd < 0) {
+ exit(EXIT_FAILURE);
+ }
+}
+
+static void gamma_control_handle_failed(void *data,
+ struct zwlr_gamma_control_v1 *gamma_control) {
+ fprintf(stderr, "failed to set gamma table\n");
+ exit(EXIT_FAILURE);
+}
+
+static const struct zwlr_gamma_control_v1_listener gamma_control_listener = {
+ .gamma_size = gamma_control_handle_gamma_size,
+ .failed = gamma_control_handle_failed,
+};
+
+static void registry_handle_global(void *data, struct wl_registry *registry,
+ uint32_t name, const char *interface, uint32_t version) {
+ if (strcmp(interface, wl_output_interface.name) == 0) {
+ struct output *output = calloc(1, sizeof(struct output));
+ output->wl_output = wl_registry_bind(registry, name,
+ &wl_output_interface, 1);
+ wl_list_insert(&outputs, &output->link);
+ } else if (strcmp(interface,
+ zwlr_gamma_control_manager_v1_interface.name) == 0) {
+ gamma_control_manager = wl_registry_bind(registry, name,
+ &zwlr_gamma_control_manager_v1_interface, 1);
+ }
+}
+
+static void registry_handle_global_remove(void *data,
+ struct wl_registry *registry, uint32_t name) {
+ // Who cares?
+}
+
+static const struct wl_registry_listener registry_listener = {
+ .global = registry_handle_global,
+ .global_remove = registry_handle_global_remove,
+};
+
+static void fill_gamma_table(uint16_t *table, uint32_t ramp_size,
+ double contrast, double brightness, double gamma) {
+ uint16_t *r = table;
+ uint16_t *g = table + ramp_size;
+ uint16_t *b = table + 2 * ramp_size;
+ for (uint32_t i = 0; i < ramp_size; ++i) {
+ double val = (double)i / (ramp_size - 1);
+ val = contrast * pow(val, 1.0 / gamma) + (brightness - 1);
+ if (val > 1.0) {
+ val = 1.0;
+ } else if (val < 0.0) {
+ val = 0.0;
+ }
+ r[i] = g[i] = b[i] = (uint16_t)(UINT16_MAX * val);
+ }
+}
+
+static const char usage[] = "usage: gamma-control [options]\n"
+ " -h show this help message\n"
+ " -c <value> set contrast (default: 1)\n"
+ " -b <value> set brightness (default: 1)\n"
+ " -g <value> set gamma (default: 1)\n";
+
+int main(int argc, char *argv[]) {
+ wl_list_init(&outputs);
+
+ double contrast = 1, brightness = 1, gamma = 1;
+ int opt;
+ while ((opt = getopt(argc, argv, "hc:b:g:")) != -1) {
+ switch (opt) {
+ case 'c':
+ contrast = strtod(optarg, NULL);
+ break;
+ case 'b':
+ brightness = strtod(optarg, NULL);
+ break;
+ case 'g':
+ gamma = strtod(optarg, NULL);
+ break;
+ case 'h':
+ default:
+ fprintf(stderr, usage);
+ return opt == 'h' ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+ }
+
+ struct wl_display *display = wl_display_connect(NULL);
+ if (display == NULL) {
+ fprintf(stderr, "failed to create display\n");
+ return -1;
+ }
+
+ struct wl_registry *registry = wl_display_get_registry(display);
+ wl_registry_add_listener(registry, &registry_listener, NULL);
+ wl_display_dispatch(display);
+ wl_display_roundtrip(display);
+
+ if (gamma_control_manager == NULL) {
+ fprintf(stderr,
+ "compositor doesn't support wlr-gamma-control-unstable-v1\n");
+ return EXIT_FAILURE;
+ }
+
+ struct output *output;
+ wl_list_for_each(output, &outputs, link) {
+ output->gamma_control = zwlr_gamma_control_manager_v1_get_gamma_control(
+ gamma_control_manager, output->wl_output);
+ zwlr_gamma_control_v1_add_listener(output->gamma_control,
+ &gamma_control_listener, output);
+ }
+ wl_display_roundtrip(display);
+
+ wl_list_for_each(output, &outputs, link) {
+ fill_gamma_table(output->table, output->ramp_size,
+ contrast, brightness, gamma);
+ zwlr_gamma_control_v1_set_gamma(output->gamma_control,
+ output->table_fd);
+ }
+
+ while (wl_display_dispatch(display) != -1) {
+ // This space is intentionnally left blank
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/idle-inhibit.c b/examples/idle-inhibit.c
index 348892ab..48c812e8 100644
--- a/examples/idle-inhibit.c
+++ b/examples/idle-inhibit.c
@@ -8,7 +8,11 @@
#include "idle-inhibit-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h"
+#ifdef __linux__
#include <linux/input-event-codes.h>
+#elif __FreeBSD__
+#include <dev/evdev/input-event-codes.h>
+#endif
/**
* Usage: idle-inhibit
diff --git a/examples/idle.c b/examples/idle.c
index 30e106db..3e1565ca 100644
--- a/examples/idle.c
+++ b/examples/idle.c
@@ -129,6 +129,7 @@ int main(int argc, char *argv[]) {
wl_registry_add_listener(registry, &registry_listener, NULL);
wl_display_dispatch(display);
wl_display_roundtrip(display);
+ free(registry);
if (idle_manager == NULL) {
fprintf(stderr, "display doesn't support idle protocol\n");
@@ -152,14 +153,20 @@ int main(int argc, char *argv[]) {
.display = display,
};
- if (simulate_activity_timeout != 0 && simulate_activity_timeout < close_timeout) {
+ bool create_t1 = (simulate_activity_timeout != 0) &&
+ (simulate_activity_timeout < close_timeout);
+
+ if (create_t1) {
if (pthread_create(&t1, NULL, &simulate_activity, (void *)&arg) != 0) {
return -1;
}
}
- if (close_timeout != 0) {
+
+ bool create_t2 = (close_timeout != 0);
+
+ if (create_t2) {
if (pthread_create(&t2, NULL, &close_program, (void *)&arg) != 0) {
- if (simulate_activity_timeout != 0) {
+ if (create_t1) {
pthread_cancel(t1);
}
return -1;
@@ -170,18 +177,19 @@ int main(int argc, char *argv[]) {
fprintf(stdout, "waiting\n");
if (pthread_create(&t3, NULL, &main_loop, (void *)display) != 0) {
- if (simulate_activity_timeout != 0) {
+ if (create_t1) {
pthread_cancel(t1);
}
- if (close_timeout != 0 ) {
+ if (create_t2) {
pthread_cancel(t2);
}
+ return -1;
}
- if (simulate_activity_timeout != 0) {
+ if (create_t1) {
pthread_join(t1, NULL);
}
- if (close_timeout != 0) {
+ if (create_t2) {
pthread_join(t2, NULL);
}
pthread_cancel(t3);
diff --git a/examples/layer-shell.c b/examples/layer-shell.c
index 70ae21f0..f56825c3 100644
--- a/examples/layer-shell.c
+++ b/examples/layer-shell.c
@@ -1,4 +1,4 @@
-#define _POSIX_C_SOURCE 199309L
+#define _POSIX_C_SOURCE 200112L
#ifdef __linux__
#include <linux/input-event-codes.h>
#elif __FreeBSD__
diff --git a/examples/meson.build b/examples/meson.build
index 18f44fde..b5ad6c98 100644
--- a/examples/meson.build
+++ b/examples/meson.build
@@ -1,68 +1,110 @@
threads = dependency('threads')
wayland_cursor = dependency('wayland-cursor')
-
libpng = dependency('libpng', required: false)
-
# These versions correspond to ffmpeg 4.0
libavutil = dependency('libavutil', version: '>=56.14.100', required: false)
libavcodec = dependency('libavcodec', version: '>=58.18.100', required: false)
libavformat = dependency('libavformat', version: '>=58.12.100', required: false)
+# Small hack until https://github.com/mesonbuild/meson/pull/3386/ is merged
+foreach dep : ['libpng', 'libavutil', 'libavcodec', 'libavformat']
+ if not get_variable(dep).found()
+ set_variable(dep, disabler())
+ endif
+endforeach
+
if not cc.has_header('libavutil/hwcontext_drm.h', dependencies: libavutil)
- libavutil = disabler()
+ libavutil = disabler()
endif
-executable('simple', 'simple.c', dependencies: wlroots)
-executable('pointer', 'pointer.c', dependencies: wlroots)
-executable('touch', 'touch.c', 'cat.c', dependencies: wlroots)
-executable('tablet', 'tablet.c', dependencies: wlroots)
-executable('rotation', 'rotation.c', 'cat.c', dependencies: wlroots)
-executable('multi-pointer', 'multi-pointer.c', dependencies: wlroots)
-executable('output-layout', 'output-layout.c', 'cat.c', dependencies: wlroots)
-
-executable(
- 'screenshot',
- 'screenshot.c',
- dependencies: [wayland_client, wlr_protos, wlroots]
-)
-
-executable(
- 'idle',
- 'idle.c',
- dependencies: [wayland_client, wlr_protos, wlroots, threads]
-)
-
-executable(
- 'idle-inhibit',
- 'idle-inhibit.c',
- dependencies: [wayland_client, wlr_protos, wlroots, threads]
-)
+examples = {
+ 'simple': {
+ 'src': 'simple.c',
+ 'dep': [wlroots],
+ },
+ 'pointer': {
+ 'src': 'pointer.c',
+ 'dep': [wlroots],
+ },
+ 'touch': {
+ 'src': ['touch.c', 'cat.c'],
+ 'dep': [wlroots],
+ },
+ 'tablet': {
+ 'src': 'tablet.c',
+ 'dep': [wlroots],
+ },
+ 'rotation': {
+ 'src': ['rotation.c', 'cat.c'],
+ 'dep': [wlroots],
+ },
+ 'multi-pointer': {
+ 'src': 'multi-pointer.c',
+ 'dep': [wlroots],
+ },
+ 'output-layout': {
+ 'src': ['output-layout.c', 'cat.c'],
+ 'dep': [wlroots],
+ },
+ 'screenshot': {
+ 'src': 'screenshot.c',
+ 'dep': [wayland_client, wlr_protos, wlroots],
+ },
+ 'idle': {
+ 'src': 'idle.c',
+ 'dep': [wayland_client, wlr_protos, wlroots, threads],
+ },
+ 'idle-inhibit': {
+ 'src': 'idle-inhibit.c',
+ 'dep': [wayland_client, wlr_protos, wlroots],
+ },
+ 'layer-shell': {
+ 'src': 'layer-shell.c',
+ 'dep': [wayland_client, wayland_cursor, wlr_protos, wlroots],
+ },
+ 'input-inhibitor': {
+ 'src': 'input-inhibitor.c',
+ 'dep': [wayland_client, wayland_cursor, wlr_protos, wlroots],
+ },
+ 'gamma-control': {
+ 'src': 'gamma-control.c',
+ 'dep': [wayland_client, wayland_cursor, wlr_protos, wlroots],
+ },
+ 'dmabuf-capture': {
+ 'src': 'dmabuf-capture.c',
+ 'dep': [
+ libavcodec,
+ libavformat,
+ libavutil,
+ threads,
+ wayland_client,
+ wlr_protos,
+ wlroots,
+ ],
+ },
+ 'screencopy': {
+ 'src': 'screencopy.c',
+ 'dep': [libpng, wayland_client, wlr_protos, wlroots],
+ },
+ 'toplevel-decoration': {
+ 'src': 'toplevel-decoration.c',
+ 'dep': [wayland_client, wlr_protos, wlroots],
+ },
+}
-executable(
- 'layer-shell',
- 'layer-shell.c',
- dependencies: [wayland_cursor, wayland_client, wlr_protos, wlroots]
-)
-
-executable(
- 'input-inhibitor',
- 'input-inhibitor.c',
- dependencies: [wayland_cursor, wayland_client, wlr_protos, wlroots]
-)
-
-if libavutil.found() and libavcodec.found() and libavformat.found()
- executable(
- 'dmabuf-capture',
- 'dmabuf-capture.c',
- dependencies: [wayland_client, wlr_protos, libavutil, libavcodec,
- libavformat, wlroots, threads ]
- )
-endif
-
-if libpng.found()
- executable(
- 'screencopy',
- 'screencopy.c',
- dependencies: [wayland_client, wlr_protos, wlroots, libpng]
- )
-endif
+foreach name, info : examples
+ all_dep_found = true
+ foreach d : info.get('dep')
+ all_dep_found = all_dep_found and d.found()
+ endforeach
+ if all_dep_found
+ executable(
+ name,
+ info.get('src'),
+ dependencies: info.get('dep'),
+ build_by_default: get_option('examples'),
+ )
+ else
+ warning('Dependencies not satisfied for ' + name)
+ endif
+endforeach
diff --git a/examples/multi-pointer.c b/examples/multi-pointer.c
index 58689649..49670c39 100644
--- a/examples/multi-pointer.c
+++ b/examples/multi-pointer.c
@@ -1,5 +1,4 @@
#define _POSIX_C_SOURCE 200112L
-#define _XOPEN_SOURCE 500
#include <assert.h>
#include <GLES2/gl2.h>
#include <math.h>
@@ -240,15 +239,21 @@ void new_input_notify(struct wl_listener *listener, void *data) {
wlr_log(WLR_ERROR, "Failed to create XKB context");
exit(1);
}
- wlr_keyboard_set_keymap(device->keyboard, xkb_map_new_from_names(context,
- &rules, XKB_KEYMAP_COMPILE_NO_FLAGS));
+ struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
+ if (!keymap) {
+ wlr_log(WLR_ERROR, "Failed to create XKB keymap");
+ exit(1);
+ }
+ wlr_keyboard_set_keymap(device->keyboard, keymap);
+ xkb_keymap_unref(keymap);
xkb_context_unref(context);
break;
case WLR_INPUT_DEVICE_POINTER:;
- struct sample_cursor *cursor = calloc(1, sizeof(struct sample_cursor));
+ struct sample_cursor *cursor = calloc(1, sizeof(struct sample_cursor));
struct sample_pointer *pointer = calloc(1, sizeof(struct sample_pointer));
pointer->device = device;
- cursor->sample = sample;
+ cursor->sample = sample;
cursor->device = device;
cursor->cursor = wlr_cursor_create();
@@ -325,6 +330,11 @@ int main(int argc, char *argv[]) {
cursor_destroy(cursor);
}
+ struct sample_pointer *pointer, *tmp_pointer;
+ wl_list_for_each_safe(pointer, tmp_pointer, &state.pointers, link) {
+ free(pointer);
+ }
+
wlr_xcursor_theme_destroy(theme);
wlr_output_layout_destroy(state.layout);
}
diff --git a/examples/output-layout.c b/examples/output-layout.c
index 2bfc5923..2d1bc58b 100644
--- a/examples/output-layout.c
+++ b/examples/output-layout.c
@@ -239,8 +239,14 @@ void new_input_notify(struct wl_listener *listener, void *data) {
wlr_log(WLR_ERROR, "Failed to create XKB context");
exit(1);
}
- wlr_keyboard_set_keymap(device->keyboard, xkb_map_new_from_names(context,
- &rules, XKB_KEYMAP_COMPILE_NO_FLAGS));
+ struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
+ if (!keymap) {
+ wlr_log(WLR_ERROR, "Failed to create XKB keymap");
+ exit(1);
+ }
+ wlr_keyboard_set_keymap(device->keyboard, keymap);
+ xkb_keymap_unref(keymap);
xkb_context_unref(context);
break;
default:
@@ -285,6 +291,6 @@ int main(int argc, char *argv[]) {
wlr_texture_destroy(state.cat_texture);
- wlr_output_layout_destroy(state.layout);
wl_display_destroy(state.display);
+ wlr_output_layout_destroy(state.layout);
}
diff --git a/examples/pointer.c b/examples/pointer.c
index e0f009b3..cc58c223 100644
--- a/examples/pointer.c
+++ b/examples/pointer.c
@@ -1,5 +1,4 @@
#define _POSIX_C_SOURCE 200112L
-#define _XOPEN_SOURCE 500
#include <assert.h>
#include <math.h>
#include <stdio.h>
@@ -305,8 +304,14 @@ void new_input_notify(struct wl_listener *listener, void *data) {
wlr_log(WLR_ERROR, "Failed to create XKB context");
exit(1);
}
- wlr_keyboard_set_keymap(device->keyboard, xkb_map_new_from_names(context,
- &rules, XKB_KEYMAP_COMPILE_NO_FLAGS));
+ struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
+ if (!keymap) {
+ wlr_log(WLR_ERROR, "Failed to create XKB keymap");
+ exit(1);
+ }
+ wlr_keyboard_set_keymap(device->keyboard, keymap);
+ xkb_keymap_unref(keymap);
xkb_context_unref(context);
break;
default:
diff --git a/examples/rotation.c b/examples/rotation.c
index 2d2fb179..7cf5727b 100644
--- a/examples/rotation.c
+++ b/examples/rotation.c
@@ -1,5 +1,4 @@
#define _POSIX_C_SOURCE 200112L
-#define _XOPEN_SOURCE 500
#include <GLES2/gl2.h>
#include <getopt.h>
#include <math.h>
@@ -189,8 +188,14 @@ void new_input_notify(struct wl_listener *listener, void *data) {
wlr_log(WLR_ERROR, "Failed to create XKB context");
exit(1);
}
- wlr_keyboard_set_keymap(device->keyboard, xkb_map_new_from_names(context,
- &rules, XKB_KEYMAP_COMPILE_NO_FLAGS));
+ struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
+ if (!keymap) {
+ wlr_log(WLR_ERROR, "Failed to create XKB keymap");
+ exit(1);
+ }
+ wlr_keyboard_set_keymap(device->keyboard, keymap);
+ xkb_keymap_unref(keymap);
xkb_context_unref(context);
break;
default:
diff --git a/examples/simple.c b/examples/simple.c
index f161dc22..e1c10906 100644
--- a/examples/simple.c
+++ b/examples/simple.c
@@ -37,8 +37,8 @@ struct sample_keyboard {
};
void output_frame_notify(struct wl_listener *listener, void *data) {
- wlr_log(WLR_DEBUG, "Output removed");
- struct sample_output *sample_output = wl_container_of(listener, sample_output, frame);
+ struct sample_output *sample_output =
+ wl_container_of(listener, sample_output, frame);
struct sample_state *sample = sample_output->sample;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -66,7 +66,9 @@ void output_frame_notify(struct wl_listener *listener, void *data) {
}
void output_remove_notify(struct wl_listener *listener, void *data) {
- struct sample_output *sample_output = wl_container_of(listener, sample_output, destroy);
+ struct sample_output *sample_output =
+ wl_container_of(listener, sample_output, destroy);
+ wlr_log(WLR_DEBUG, "Output removed");
wl_list_remove(&sample_output->frame.link);
wl_list_remove(&sample_output->destroy.link);
free(sample_output);
@@ -74,10 +76,13 @@ void output_remove_notify(struct wl_listener *listener, void *data) {
void new_output_notify(struct wl_listener *listener, void *data) {
struct wlr_output *output = data;
- struct sample_state *sample = wl_container_of(listener, sample, new_output);
- struct sample_output *sample_output = calloc(1, sizeof(struct sample_output));
+ struct sample_state *sample =
+ wl_container_of(listener, sample, new_output);
+ struct sample_output *sample_output =
+ calloc(1, sizeof(struct sample_output));
if (!wl_list_empty(&output->modes)) {
- struct wlr_output_mode *mode = wl_container_of(output->modes.prev, mode, link);
+ struct wlr_output_mode *mode =
+ wl_container_of(output->modes.prev, mode, link);
wlr_output_set_mode(output, mode);
}
sample_output->output = output;
@@ -105,7 +110,8 @@ void keyboard_key_notify(struct wl_listener *listener, void *data) {
}
void keyboard_destroy_notify(struct wl_listener *listener, void *data) {
- struct sample_keyboard *keyboard = wl_container_of(listener, keyboard, destroy);
+ struct sample_keyboard *keyboard =
+ wl_container_of(listener, keyboard, destroy);
wl_list_remove(&keyboard->destroy.link);
wl_list_remove(&keyboard->key.link);
free(keyboard);
@@ -116,7 +122,8 @@ void new_input_notify(struct wl_listener *listener, void *data) {
struct sample_state *sample = wl_container_of(listener, sample, new_input);
switch (device->type) {
case WLR_INPUT_DEVICE_KEYBOARD:;
- struct sample_keyboard *keyboard = calloc(1, sizeof(struct sample_keyboard));
+ struct sample_keyboard *keyboard =
+ calloc(1, sizeof(struct sample_keyboard));
keyboard->device = device;
keyboard->sample = sample;
wl_signal_add(&device->events.destroy, &keyboard->destroy);
@@ -134,8 +141,14 @@ void new_input_notify(struct wl_listener *listener, void *data) {
wlr_log(WLR_ERROR, "Failed to create XKB context");
exit(1);
}
- wlr_keyboard_set_keymap(device->keyboard, xkb_map_new_from_names(context,
- &rules, XKB_KEYMAP_COMPILE_NO_FLAGS));
+ struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
+ if (!keymap) {
+ wlr_log(WLR_ERROR, "Failed to create XKB keymap");
+ exit(1);
+ }
+ wlr_keyboard_set_keymap(device->keyboard, keymap);
+ xkb_keymap_unref(keymap);
xkb_context_unref(context);
break;
default:
@@ -152,19 +165,19 @@ int main(void) {
.last_frame = { 0 },
.display = display
};
- struct wlr_backend *wlr = wlr_backend_autocreate(display, NULL);
- if (!wlr) {
+ struct wlr_backend *backend = wlr_backend_autocreate(display, NULL);
+ if (!backend) {
exit(1);
}
- wl_signal_add(&wlr->events.new_output, &state.new_output);
+ wl_signal_add(&backend->events.new_output, &state.new_output);
state.new_output.notify = new_output_notify;
- wl_signal_add(&wlr->events.new_input, &state.new_input);
+ wl_signal_add(&backend->events.new_input, &state.new_input);
state.new_input.notify = new_input_notify;
clock_gettime(CLOCK_MONOTONIC, &state.last_frame);
- if (!wlr_backend_start(wlr)) {
+ if (!wlr_backend_start(backend)) {
wlr_log(WLR_ERROR, "Failed to start backend");
- wlr_backend_destroy(wlr);
+ wlr_backend_destroy(backend);
exit(1);
}
wl_display_run(display);
diff --git a/examples/tablet.c b/examples/tablet.c
index 4a27d0e1..fad30d52 100644
--- a/examples/tablet.c
+++ b/examples/tablet.c
@@ -1,5 +1,4 @@
-#define _POSIX_C_SOURCE 200112L
-#define _XOPEN_SOURCE 500
+#define _XOPEN_SOURCE 600
#include <GLES2/gl2.h>
#include <math.h>
#include <stdio.h>
@@ -298,8 +297,14 @@ void new_input_notify(struct wl_listener *listener, void *data) {
wlr_log(WLR_ERROR, "Failed to create XKB context");
exit(1);
}
- wlr_keyboard_set_keymap(device->keyboard, xkb_map_new_from_names(context,
- &rules, XKB_KEYMAP_COMPILE_NO_FLAGS));
+ struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
+ if (!keymap) {
+ wlr_log(WLR_ERROR, "Failed to create XKB keymap");
+ exit(1);
+ }
+ wlr_keyboard_set_keymap(device->keyboard, keymap);
+ xkb_keymap_unref(keymap);
xkb_context_unref(context);
break;
case WLR_INPUT_DEVICE_TABLET_PAD:;
diff --git a/examples/toplevel-decoration.c b/examples/toplevel-decoration.c
new file mode 100644
index 00000000..e930c417
--- /dev/null
+++ b/examples/toplevel-decoration.c
@@ -0,0 +1,253 @@
+#include <GLES2/gl2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wayland-client.h>
+#include <wayland-egl.h>
+#include <wlr/render/egl.h>
+#include "xdg-shell-client-protocol.h"
+#include "xdg-decoration-unstable-v1-client-protocol.h"
+
+/**
+ * Usage: toplevel-decoration [mode]
+ * Creates an xdg-toplevel supporting decoration negotiation. If `mode` is
+ * specified, the client will prefer this decoration mode.
+ */
+
+static int width = 500, height = 300;
+
+static struct wl_compositor *compositor = NULL;
+static struct xdg_wm_base *wm_base = NULL;
+static struct zxdg_decoration_manager_v1 *decoration_manager = NULL;
+
+struct wlr_egl egl;
+struct wl_egl_window *egl_window;
+struct wlr_egl_surface *egl_surface;
+
+struct zxdg_toplevel_decoration_v1 *decoration;
+enum zxdg_toplevel_decoration_v1_mode client_preferred_mode, current_mode;
+
+static const char *get_mode_name(enum zxdg_toplevel_decoration_v1_mode mode) {
+ switch (mode) {
+ case ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE:
+ return "client-side decorations";
+ case ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE:
+ return "server-side decorations";
+ }
+ abort();
+}
+
+static void request_preferred_mode(void) {
+ enum zxdg_toplevel_decoration_v1_mode mode = client_preferred_mode;
+ if (mode == 0) {
+ printf("Requesting compositor preferred mode\n");
+ zxdg_toplevel_decoration_v1_unset_mode(decoration);
+ return;
+ }
+ if (mode == current_mode) {
+ return;
+ }
+
+ printf("Requesting %s\n", get_mode_name(mode));
+ zxdg_toplevel_decoration_v1_set_mode(decoration, mode);
+}
+
+static void draw(void) {
+ eglMakeCurrent(egl.display, egl_surface, egl_surface, egl.context);
+
+ float color[] = {1.0, 1.0, 0.0, 1.0};
+ if (current_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE) {
+ color[0] = 0.0;
+ }
+
+ glViewport(0, 0, width, height);
+ glClearColor(color[0], color[1], color[2], 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ eglSwapBuffers(egl.display, egl_surface);
+}
+
+static void xdg_surface_handle_configure(void *data,
+ struct xdg_surface *xdg_surface, uint32_t serial) {
+ xdg_surface_ack_configure(xdg_surface, serial);
+ wl_egl_window_resize(egl_window, width, height, 0, 0);
+ draw();
+}
+
+static const struct xdg_surface_listener xdg_surface_listener = {
+ .configure = xdg_surface_handle_configure,
+};
+
+static void xdg_toplevel_handle_configure(void *data,
+ struct xdg_toplevel *xdg_toplevel, int32_t w, int32_t h,
+ struct wl_array *states) {
+ width = w;
+ height = h;
+}
+
+static const struct xdg_toplevel_listener xdg_toplevel_listener = {
+ .configure = xdg_toplevel_handle_configure,
+};
+
+static void decoration_handle_configure(void *data,
+ struct zxdg_toplevel_decoration_v1 *decoration,
+ enum zxdg_toplevel_decoration_v1_mode mode) {
+ printf("Using %s\n", get_mode_name(mode));
+ current_mode = mode;
+}
+
+static const struct zxdg_toplevel_decoration_v1_listener decoration_listener = {
+ .configure = decoration_handle_configure,
+};
+
+static void pointer_handle_enter(void *data, struct wl_pointer *pointer,
+ uint32_t serial, struct wl_surface *surface,
+ wl_fixed_t sx, wl_fixed_t sy) {
+ // No-op
+}
+
+static void pointer_handle_leave(void *data, struct wl_pointer *pointer,
+ uint32_t serial, struct wl_surface *surface) {
+ // No-op
+}
+
+static void pointer_handle_motion(void *data, struct wl_pointer *pointer,
+ uint32_t time, wl_fixed_t sx, wl_fixed_t sy) {
+ // No-op
+}
+
+static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
+ uint32_t serial, uint32_t time, uint32_t button,
+ enum wl_pointer_button_state state) {
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
+ // Toggle mode
+ if (client_preferred_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) {
+ client_preferred_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
+ } else {
+ client_preferred_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
+ }
+ request_preferred_mode();
+ }
+}
+
+static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
+ uint32_t time, enum wl_pointer_axis axis, wl_fixed_t value) {
+ // No-op
+}
+
+static const struct wl_pointer_listener pointer_listener = {
+ .enter = pointer_handle_enter,
+ .leave = pointer_handle_leave,
+ .motion = pointer_handle_motion,
+ .button = pointer_handle_button,
+ .axis = pointer_handle_axis,
+};
+
+static void seat_handle_capabilities(void *data, struct wl_seat *seat,
+ enum wl_seat_capability caps) {
+ if (caps & WL_SEAT_CAPABILITY_POINTER) {
+ struct wl_pointer *pointer = wl_seat_get_pointer(seat);
+ wl_pointer_add_listener(pointer, &pointer_listener, NULL);
+ }
+}
+
+static const struct wl_seat_listener seat_listener = {
+ .capabilities = seat_handle_capabilities,
+};
+
+static void handle_global(void *data, struct wl_registry *registry,
+ uint32_t name, const char *interface, uint32_t version) {
+ if (strcmp(interface, wl_compositor_interface.name) == 0) {
+ compositor = wl_registry_bind(registry, name, &wl_compositor_interface,
+ 1);
+ } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
+ wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
+ } else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) {
+ decoration_manager = wl_registry_bind(registry, name,
+ &zxdg_decoration_manager_v1_interface, 1);
+ } else if (strcmp(interface, wl_seat_interface.name) == 0) {
+ struct wl_seat *seat =
+ wl_registry_bind(registry, name, &wl_seat_interface, 1);
+ wl_seat_add_listener(seat, &seat_listener, NULL);
+ }
+}
+
+static void handle_global_remove(void *data, struct wl_registry *registry,
+ uint32_t name) {
+ // Who cares?
+}
+
+static const struct wl_registry_listener registry_listener = {
+ .global = handle_global,
+ .global_remove = handle_global_remove,
+};
+
+int main(int argc, char **argv) {
+ if (argc == 2) {
+ char *mode = argv[1];
+ if (strcmp(mode, "client") == 0) {
+ client_preferred_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
+ } else if (strcmp(mode, "server") == 0) {
+ client_preferred_mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
+ } else {
+ fprintf(stderr, "Invalid decoration mode\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ struct wl_display *display = wl_display_connect(NULL);
+ if (display == NULL) {
+ fprintf(stderr, "Failed to create display\n");
+ return EXIT_FAILURE;
+ }
+
+ struct wl_registry *registry = wl_display_get_registry(display);
+ wl_registry_add_listener(registry, &registry_listener, NULL);
+ wl_display_dispatch(display);
+ wl_display_roundtrip(display);
+
+ if (compositor == NULL) {
+ fprintf(stderr, "wl-compositor not available\n");
+ return EXIT_FAILURE;
+ }
+ if (wm_base == NULL) {
+ fprintf(stderr, "xdg-shell not available\n");
+ return EXIT_FAILURE;
+ }
+ if (decoration_manager == NULL) {
+ fprintf(stderr, "xdg-decoration not available\n");
+ return EXIT_FAILURE;
+ }
+
+ wlr_egl_init(&egl, EGL_PLATFORM_WAYLAND_EXT, display, NULL,
+ WL_SHM_FORMAT_ARGB8888);
+
+ struct wl_surface *surface = wl_compositor_create_surface(compositor);
+ struct xdg_surface *xdg_surface =
+ xdg_wm_base_get_xdg_surface(wm_base, surface);
+ struct xdg_toplevel *xdg_toplevel = xdg_surface_get_toplevel(xdg_surface);
+ decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
+ decoration_manager, xdg_toplevel);
+
+ wl_display_roundtrip(display);
+ request_preferred_mode();
+
+ xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, NULL);
+ xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, NULL);
+ zxdg_toplevel_decoration_v1_add_listener(decoration, &decoration_listener,
+ NULL);
+ wl_surface_commit(surface);
+
+ egl_window = wl_egl_window_create(surface, width, height);
+ egl_surface = wlr_egl_create_surface(&egl, egl_window);
+
+ wl_display_roundtrip(display);
+
+ draw();
+
+ while (wl_display_dispatch(display) != -1) {
+ // This space is intentionally left blank
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/touch.c b/examples/touch.c
index 9954cdbd..9ed20a28 100644
--- a/examples/touch.c
+++ b/examples/touch.c
@@ -1,5 +1,4 @@
#define _POSIX_C_SOURCE 200112L
-#define _XOPEN_SOURCE 500
#include <GLES2/gl2.h>
#include <math.h>
#include <stdint.h>
@@ -211,8 +210,14 @@ void new_input_notify(struct wl_listener *listener, void *data) {
wlr_log(WLR_ERROR, "Failed to create XKB context");
exit(1);
}
- wlr_keyboard_set_keymap(device->keyboard, xkb_map_new_from_names(context,
- &rules, XKB_KEYMAP_COMPILE_NO_FLAGS));
+ struct xkb_keymap *keymap = xkb_map_new_from_names(context, &rules,
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
+ if (!keymap) {
+ wlr_log(WLR_ERROR, "Failed to create XKB keymap");
+ exit(1);
+ }
+ wlr_keyboard_set_keymap(device->keyboard, keymap);
+ xkb_keymap_unref(keymap);
xkb_context_unref(context);
break;
case WLR_INPUT_DEVICE_TOUCH:;