aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.build.yml2
-rw-r--r--.editorconfig2
-rw-r--r--backend/drm/atomic.c16
-rw-r--r--backend/drm/backend.c7
-rw-r--r--backend/drm/drm.c505
-rw-r--r--backend/drm/legacy.c5
-rw-r--r--backend/drm/renderer.c39
-rw-r--r--backend/drm/util.c32
-rw-r--r--backend/libinput/tablet_pad.c6
-rw-r--r--backend/meson.build20
-rw-r--r--backend/multi/backend.c2
-rw-r--r--backend/session/direct-freebsd.c50
-rw-r--r--backend/session/direct-ipc.c24
-rw-r--r--backend/session/session.c10
-rw-r--r--backend/wayland/wl_seat.c2
-rw-r--r--backend/x11/backend.c2
-rw-r--r--backend/x11/meson.build44
-rw-r--r--backend/x11/output.c23
-rw-r--r--docs/env_vars.md2
-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
-rwxr-xr-xglgen.sh16
-rw-r--r--include/backend/drm/drm.h5
-rw-r--r--include/render/gles2.h2
-rw-r--r--include/rootston/cursor.h3
-rw-r--r--include/rootston/desktop.h17
-rw-r--r--include/rootston/input.h2
-rw-r--r--include/rootston/view.h13
-rw-r--r--include/types/wlr_xdg_shell.h3
-rw-r--r--include/types/wlr_xdg_shell_v6.h3
-rw-r--r--include/wlr/backend.h8
-rw-r--r--include/wlr/backend/drm.h14
-rw-r--r--include/wlr/backend/headless.h8
-rw-r--r--include/wlr/backend/interface.h8
-rw-r--r--include/wlr/backend/libinput.h8
-rw-r--r--include/wlr/backend/meson.build16
-rw-r--r--include/wlr/backend/multi.h8
-rw-r--r--include/wlr/backend/session.h4
-rw-r--r--include/wlr/backend/session/interface.h8
-rw-r--r--include/wlr/backend/session/meson.build1
-rw-r--r--include/wlr/config.h.in19
-rw-r--r--include/wlr/interfaces/meson.build10
-rw-r--r--include/wlr/interfaces/wlr_input_device.h8
-rw-r--r--include/wlr/interfaces/wlr_keyboard.h8
-rw-r--r--include/wlr/interfaces/wlr_output.h10
-rw-r--r--include/wlr/interfaces/wlr_pointer.h8
-rw-r--r--include/wlr/interfaces/wlr_tablet_pad.h8
-rw-r--r--include/wlr/interfaces/wlr_tablet_tool.h8
-rw-r--r--include/wlr/interfaces/wlr_touch.h8
-rw-r--r--include/wlr/meson.build20
-rw-r--r--include/wlr/render/dmabuf.h8
-rw-r--r--include/wlr/render/egl.h8
-rw-r--r--include/wlr/render/gles2.h8
-rw-r--r--include/wlr/render/interface.h8
-rw-r--r--include/wlr/render/meson.build9
-rw-r--r--include/wlr/render/wlr_renderer.h8
-rw-r--r--include/wlr/render/wlr_texture.h8
-rw-r--r--include/wlr/types/meson.build42
-rw-r--r--include/wlr/types/wlr_box.h8
-rw-r--r--include/wlr/types/wlr_buffer.h8
-rw-r--r--include/wlr/types/wlr_compositor.h8
-rw-r--r--include/wlr/types/wlr_cursor.h8
-rw-r--r--include/wlr/types/wlr_data_device.h10
-rw-r--r--include/wlr/types/wlr_export_dmabuf_v1.h8
-rw-r--r--include/wlr/types/wlr_gamma_control.h12
-rw-r--r--include/wlr/types/wlr_gamma_control_v1.h35
-rw-r--r--include/wlr/types/wlr_idle.h9
-rw-r--r--include/wlr/types/wlr_idle_inhibit_v1.h11
-rw-r--r--include/wlr/types/wlr_input_device.h8
-rw-r--r--include/wlr/types/wlr_input_inhibitor.h9
-rw-r--r--include/wlr/types/wlr_keyboard.h8
-rw-r--r--include/wlr/types/wlr_layer_shell.h9
-rw-r--r--include/wlr/types/wlr_linux_dmabuf_v1.h (renamed from include/wlr/types/wlr_linux_dmabuf.h)24
-rw-r--r--include/wlr/types/wlr_list.h8
-rw-r--r--include/wlr/types/wlr_matrix.h37
-rw-r--r--include/wlr/types/wlr_output.h24
-rw-r--r--include/wlr/types/wlr_output_damage.h8
-rw-r--r--include/wlr/types/wlr_output_layout.h11
-rw-r--r--include/wlr/types/wlr_pointer.h8
-rw-r--r--include/wlr/types/wlr_primary_selection.h12
-rw-r--r--include/wlr/types/wlr_region.h8
-rw-r--r--include/wlr/types/wlr_screencopy_v1.h13
-rw-r--r--include/wlr/types/wlr_screenshooter.h12
-rw-r--r--include/wlr/types/wlr_seat.h8
-rw-r--r--include/wlr/types/wlr_server_decoration.h9
-rw-r--r--include/wlr/types/wlr_surface.h9
-rw-r--r--include/wlr/types/wlr_tablet_pad.h8
-rw-r--r--include/wlr/types/wlr_tablet_tool.h8
-rw-r--r--include/wlr/types/wlr_tablet_v2.h12
-rw-r--r--include/wlr/types/wlr_touch.h8
-rw-r--r--include/wlr/types/wlr_virtual_keyboard_v1.h9
-rw-r--r--include/wlr/types/wlr_wl_shell.h9
-rw-r--r--include/wlr/types/wlr_xcursor_manager.h8
-rw-r--r--include/wlr/types/wlr_xdg_decoration_v1.h69
-rw-r--r--include/wlr/types/wlr_xdg_output.h12
-rw-r--r--include/wlr/types/wlr_xdg_shell.h36
-rw-r--r--include/wlr/types/wlr_xdg_shell_v6.h11
-rw-r--r--include/wlr/util/edges.h16
-rw-r--r--include/wlr/util/log.h21
-rw-r--r--include/wlr/util/meson.build6
-rw-r--r--include/wlr/util/region.h17
-rw-r--r--include/wlr/version.h.in16
-rw-r--r--include/wlr/xcursor.h15
-rw-r--r--include/wlr/xwayland.h50
-rw-r--r--include/xwayland/xwm.h2
-rw-r--r--meson.build118
-rw-r--r--meson_options.txt18
-rw-r--r--protocol/meson.build69
-rw-r--r--protocol/wlr-gamma-control-unstable-v1.xml126
-rw-r--r--render/gles2/renderer.c8
-rw-r--r--render/gles2/texture.c18
-rw-r--r--render/meson.build8
-rw-r--r--render/wlr_renderer.c7
-rw-r--r--rootston/config.c15
-rw-r--r--rootston/cursor.c19
-rw-r--r--rootston/desktop.c32
-rw-r--r--rootston/input.c15
-rw-r--r--rootston/keyboard.c57
-rw-r--r--rootston/layer_shell.c82
-rw-r--r--rootston/meson.build13
-rw-r--r--rootston/output.c26
-rw-r--r--rootston/seat.c25
-rw-r--r--rootston/xdg_shell.c72
-rw-r--r--rootston/xdg_shell_v6.c1
-rw-r--r--types/data_device/wlr_drag.c3
-rw-r--r--types/meson.build6
-rw-r--r--types/seat/wlr_seat_keyboard.c2
-rw-r--r--types/tablet_v2/wlr_tablet_v2.c18
-rw-r--r--types/tablet_v2/wlr_tablet_v2_pad.c2
-rw-r--r--types/wlr_buffer.c16
-rw-r--r--types/wlr_cursor.c2
-rw-r--r--types/wlr_export_dmabuf_v1.c2
-rw-r--r--types/wlr_gamma_control.c8
-rw-r--r--types/wlr_gamma_control_v1.c266
-rw-r--r--types/wlr_idle.c2
-rw-r--r--types/wlr_idle_inhibit_v1.c6
-rw-r--r--types/wlr_input_inhibitor.c2
-rw-r--r--types/wlr_layer_shell.c2
-rw-r--r--types/wlr_linux_dmabuf_v1.c (renamed from types/wlr_linux_dmabuf.c)66
-rw-r--r--types/wlr_output.c12
-rw-r--r--types/wlr_output_layout.c31
-rw-r--r--types/wlr_primary_selection.c3
-rw-r--r--types/wlr_screencopy_v1.c4
-rw-r--r--types/wlr_screenshooter.c3
-rw-r--r--types/wlr_server_decoration.c4
-rw-r--r--types/wlr_surface.c8
-rw-r--r--types/wlr_virtual_keyboard_v1.c6
-rw-r--r--types/wlr_xdg_decoration_v1.c304
-rw-r--r--types/wlr_xdg_output.c6
-rw-r--r--types/xdg_shell/wlr_xdg_popup.c3
-rw-r--r--types/xdg_shell/wlr_xdg_shell.c2
-rw-r--r--types/xdg_shell/wlr_xdg_surface.c63
-rw-r--r--types/xdg_shell/wlr_xdg_toplevel.c39
-rw-r--r--types/xdg_shell_v6/wlr_xdg_popup_v6.c3
-rw-r--r--types/xdg_shell_v6/wlr_xdg_shell_v6.c2
-rw-r--r--types/xdg_shell_v6/wlr_xdg_surface_v6.c20
-rw-r--r--types/xdg_shell_v6/wlr_xdg_toplevel_v6.c7
-rw-r--r--util/log.c4
-rw-r--r--util/os-compatibility.c45
-rw-r--r--wlroots.syms2
-rw-r--r--xwayland/meson.build40
-rw-r--r--xwayland/xwayland.c26
-rw-r--r--xwayland/xwm.c129
174 files changed, 3640 insertions, 832 deletions
diff --git a/.build.yml b/.build.yml
index 8b2f9c1f..4b3e197d 100644
--- a/.build.yml
+++ b/.build.yml
@@ -25,4 +25,4 @@ tasks:
ninja
- clang: |
cd wlroots/build-clang
- ninja
+ ninja scan-build
diff --git a/.editorconfig b/.editorconfig
index b6b6a367..c74fecda 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,10 +5,8 @@ end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = tab
-indent_size = 4
trim_trailing_whitespace = true
[*.xml]
indent_style = space
indent_size = 2
-tab_width = 8
diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c
index 61d2f6e1..335c9de1 100644
--- a/backend/drm/atomic.c
+++ b/backend/drm/atomic.c
@@ -199,14 +199,20 @@ static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm,
static bool atomic_crtc_set_gamma(struct wlr_drm_backend *drm,
struct wlr_drm_crtc *crtc, uint16_t *r, uint16_t *g, uint16_t *b,
uint32_t size) {
- struct drm_color_lut gamma[size];
-
// Fallback to legacy gamma interface when gamma properties are not available
// (can happen on older intel gpu's that support gamma but not degamma)
- if (crtc->props.gamma_lut == 0) {
+ // TEMP: This is broken on AMDGPU. Always fallback to legacy until they get
+ // it fixed. Ref https://bugs.freedesktop.org/show_bug.cgi?id=107459
+ if (crtc->props.gamma_lut == 0 || true) {
return legacy_iface.crtc_set_gamma(drm, crtc, r, g, b, size);
}
+ struct drm_color_lut *gamma = malloc(size * sizeof(struct drm_color_lut));
+ if (gamma == NULL) {
+ wlr_log(WLR_ERROR, "Failed to allocate gamma table");
+ return false;
+ }
+
for (uint32_t i = 0; i < size; i++) {
gamma[i].red = r[i];
gamma[i].green = g[i];
@@ -218,10 +224,12 @@ static bool atomic_crtc_set_gamma(struct wlr_drm_backend *drm,
}
if (drmModeCreatePropertyBlob(drm->fd, gamma,
- sizeof(struct drm_color_lut) * size, &crtc->gamma_lut)) {
+ size * sizeof(struct drm_color_lut), &crtc->gamma_lut)) {
+ free(gamma);
wlr_log_errno(WLR_ERROR, "Unable to create property blob");
return false;
}
+ free(gamma);
struct atomic atom;
atomic_begin(crtc, &atom);
diff --git a/backend/drm/backend.c b/backend/drm/backend.c
index 5833d46e..1df5cdd1 100644
--- a/backend/drm/backend.c
+++ b/backend/drm/backend.c
@@ -51,7 +51,12 @@ static void backend_destroy(struct wlr_backend *backend) {
static struct wlr_renderer *backend_get_renderer(
struct wlr_backend *backend) {
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)backend;
- return drm->renderer.wlr_rend;
+
+ if (drm->parent) {
+ return drm->parent->renderer.wlr_rend;
+ } else {
+ return drm->renderer.wlr_rend;
+ }
}
static struct wlr_backend_impl backend_impl = {
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index c4674235..e37eba74 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -27,6 +27,23 @@
#include "util/signal.h"
bool check_drm_features(struct wlr_drm_backend *drm) {
+ if (drm->parent) {
+ uint64_t cap;
+ if (drmGetCap(drm->fd, DRM_CAP_PRIME, &cap) ||
+ !(cap & DRM_PRIME_CAP_IMPORT)) {
+ wlr_log(WLR_ERROR,
+ "PRIME import not supported on secondary GPU");
+ return false;
+ }
+
+ if (drmGetCap(drm->parent->fd, DRM_CAP_PRIME, &cap) ||
+ !(cap & DRM_PRIME_CAP_EXPORT)) {
+ wlr_log(WLR_ERROR,
+ "PRIME export not supported on primary GPU");
+ return false;
+ }
+ }
+
if (drmSetClientCap(drm->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) {
wlr_log(WLR_ERROR, "DRM universal planes unsupported");
return false;
@@ -228,30 +245,54 @@ static bool drm_connector_swap_buffers(struct wlr_output *output,
return true;
}
-static void drm_connector_set_gamma(struct wlr_output *output,
- uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b) {
+static void fill_empty_gamma_table(uint32_t size,
+ uint16_t *r, uint16_t *g, uint16_t *b) {
+ for (uint32_t i = 0; i < size; ++i) {
+ uint16_t val = (uint32_t)0xffff * i / (size - 1);
+ r[i] = g[i] = b[i] = val;
+ }
+}
+
+static uint32_t drm_connector_get_gamma_size(struct wlr_output *output) {
struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output;
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend;
- bool ok;
if (conn->crtc) {
- ok = drm->iface->crtc_set_gamma(drm, conn->crtc, r, g, b, size);
- if (ok) {
- wlr_output_update_needs_swap(output);
- }
+ return drm->iface->crtc_get_gamma_size(drm, conn->crtc);
}
+ return 0;
}
-static uint32_t drm_connector_get_gamma_size(struct wlr_output *output) {
+static bool drm_connector_set_gamma(struct wlr_output *output,
+ uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b) {
struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output;
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend;
- if (conn->crtc) {
- return drm->iface->crtc_get_gamma_size(drm, conn->crtc);
+ if (!conn->crtc) {
+ return false;
}
- return 0;
+ uint16_t *reset_table = NULL;
+ if (size == 0) {
+ size = drm_connector_get_gamma_size(output);
+ reset_table = malloc(3 * size * sizeof(uint16_t));
+ if (reset_table == NULL) {
+ wlr_log(WLR_ERROR, "Failed to allocate gamma table");
+ return false;
+ }
+ r = reset_table;
+ g = reset_table + size;
+ b = reset_table + 2 * size;
+ fill_empty_gamma_table(size, r, g, b);
+ }
+
+ bool ok = drm->iface->crtc_set_gamma(drm, conn->crtc, r, g, b, size);
+ if (ok) {
+ wlr_output_update_needs_swap(output);
+ }
+ free(reset_table);
+ return ok;
}
static bool drm_connector_export_dmabuf(struct wlr_output *output,
@@ -303,7 +344,8 @@ static void drm_connector_start_renderer(struct wlr_drm_connector *conn) {
void enable_drm_connector(struct wlr_output *output, bool enable) {
struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output;
- if (conn->state != WLR_DRM_CONN_CONNECTED) {
+ if (conn->state != WLR_DRM_CONN_CONNECTED
+ && conn->state != WLR_DRM_CONN_NEEDS_MODESET) {
return;
}
@@ -362,9 +404,11 @@ static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in,
struct wlr_drm_plane *new = &drm->type_planes[type][crtc_res[i]];
if (*old != new) {
- wlr_log(WLR_DEBUG, "Assigning plane %d -> %d to CRTC %d",
+ wlr_log(WLR_DEBUG,
+ "Assigning plane %d -> %d (type %zu) to CRTC %d",
*old ? (int)(*old)->id : -1,
new ? (int)new->id : -1,
+ type,
c->id);
changed_outputs[crtc_res[i]] = true;
@@ -378,192 +422,41 @@ static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in,
}
}
-static void realloc_crtcs(struct wlr_drm_backend *drm,
- struct wlr_drm_connector *conn, bool *changed_outputs) {
- uint32_t crtc[drm->num_crtcs];
- uint32_t crtc_res[drm->num_crtcs];
- ssize_t num_outputs = wl_list_length(&drm->outputs);
- uint32_t possible_crtc[num_outputs];
-
- for (size_t i = 0; i < drm->num_crtcs; ++i) {
- crtc[i] = UNMATCHED;
- }
-
- memset(possible_crtc, 0, sizeof(possible_crtc));
-
- wlr_log(WLR_DEBUG, "Reallocating CRTCs for output '%s'", conn->output.name);
-
- ssize_t index = -1, i = -1;
- struct wlr_drm_connector *c;
- wl_list_for_each(c, &drm->outputs, link) {
- i++;
- if (c == conn) {
- index = i;
- }
-
- wlr_log(WLR_DEBUG, "output '%s' crtc=%p state=%d",
- c->output.name, c->crtc, c->state);
-
- if (c->crtc) {
- crtc[c->crtc - drm->crtcs] = i;
- }
-
- if (c->state == WLR_DRM_CONN_CONNECTED) {
- possible_crtc[i] = c->possible_crtc;
- }
- }
- assert(index != -1);
-
- possible_crtc[index] = conn->possible_crtc;
- match_obj(wl_list_length(&drm->outputs), possible_crtc,
- drm->num_crtcs, crtc, crtc_res);
-
- bool matched[num_outputs];
- memset(matched, false, sizeof(matched));
- for (size_t i = 0; i < drm->num_crtcs; ++i) {
- if (crtc_res[i] != UNMATCHED) {
- matched[crtc_res[i]] = true;
- }
- }
-
- // There is no point doing anything if this monitor doesn't get activated
- if (!matched[index]) {
- wlr_log(WLR_DEBUG, "Could not match a CRTC for this output");
- return;
- }
-
- for (size_t i = 0; i < drm->num_crtcs; ++i) {
- // We don't want any of the current monitors to be deactivated.
- if (crtc[i] != UNMATCHED && !matched[crtc[i]]) {
- wlr_log(WLR_DEBUG, "Could not match a CRTC for other output %d",
- crtc[i]);
- return;
- }
- }
-
- changed_outputs[index] = true;
-
- for (size_t i = 0; i < drm->num_crtcs; ++i) {
- if (crtc_res[i] == UNMATCHED) {
- continue;
- }
-
- if (crtc_res[i] != crtc[i]) {
- changed_outputs[crtc_res[i]] = true;
- struct wlr_drm_connector *c;
- size_t pos = 0;
- wl_list_for_each(c, &drm->outputs, link) {
- if (pos == crtc_res[i]) {
- break;
- }
- pos++;
- }
- c->crtc = &drm->crtcs[i];
-
- wlr_log(WLR_DEBUG, "Assigning CRTC %d to output '%s'",
- drm->crtcs[i].id, c->output.name);
- }
- }
-
- realloc_planes(drm, crtc_res, changed_outputs);
-}
-
-static uint32_t get_possible_crtcs(int fd, uint32_t conn_id) {
- drmModeConnector *conn = drmModeGetConnector(fd, conn_id);
- if (!conn) {
- wlr_log_errno(WLR_ERROR, "Failed to get DRM connector");
- return 0;
- }
-
- if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) {
- wlr_log(WLR_ERROR, "Output is not connected");
- goto error_conn;
- }
-
- drmModeEncoder *enc = NULL;
- for (int i = 0; !enc && i < conn->count_encoders; ++i) {
- enc = drmModeGetEncoder(fd, conn->encoders[i]);
- }
-
- if (!enc) {
- wlr_log(WLR_ERROR, "Failed to get DRM encoder");
- goto error_conn;
- }
-
- uint32_t ret = enc->possible_crtcs;
- drmModeFreeEncoder(enc);
- drmModeFreeConnector(conn);
- return ret;
-
-error_conn:
- drmModeFreeConnector(conn);
- return 0;
-}
-
static void drm_connector_cleanup(struct wlr_drm_connector *conn);
static bool drm_connector_set_mode(struct wlr_output *output,
struct wlr_output_mode *mode) {
struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output;
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend;
- bool changed_outputs[wl_list_length(&drm->outputs)];
-
- wlr_log(WLR_INFO, "Modesetting '%s' with '%ux%u@%u mHz'", conn->output.name,
- mode->width, mode->height, mode->refresh);
-
- conn->possible_crtc = get_possible_crtcs(drm->fd, conn->id);
- if (conn->possible_crtc == 0) {
- goto error_conn;
+ if (conn->crtc == NULL) {
+ wlr_log(WLR_ERROR, "Cannot modeset '%s': no CRTC for this connector",
+ conn->output.name);
+ // Save the desired mode for later, when we'll get a proper CRTC
+ conn->desired_mode = mode;
+ return false;
}
- memset(changed_outputs, false, sizeof(changed_outputs));
- realloc_crtcs(drm, conn, changed_outputs);
+ wlr_log(WLR_INFO, "Modesetting '%s' with '%ux%u@%u mHz'",
+ conn->output.name, mode->width, mode->height, mode->refresh);
- struct wlr_drm_crtc *crtc = conn->crtc;
- if (!crtc) {
- wlr_log(WLR_ERROR, "Unable to match %s with a CRTC", conn->output.name);
- goto error_conn;
+ if (!init_drm_plane_surfaces(conn->crtc->primary, drm,
+ mode->width, mode->height, GBM_FORMAT_XRGB8888)) {
+ wlr_log(WLR_ERROR, "Failed to initialize renderer for plane");
+ return false;
}
- wlr_log(WLR_DEBUG, "%s: crtc=%td ovr=%td pri=%td cur=%td", conn->output.name,
- crtc - drm->crtcs,
- crtc->overlay ? crtc->overlay - drm->overlay_planes : -1,
- crtc->primary ? crtc->primary - drm->primary_planes : -1,
- crtc->cursor ? crtc->cursor - drm->cursor_planes : -1);
conn->state = WLR_DRM_CONN_CONNECTED;
+ conn->desired_mode = NULL;
wlr_output_update_mode(&conn->output, mode);
+ wlr_output_update_enabled(&conn->output, true);
+
+ drm_connector_start_renderer(conn);
// When switching VTs, the mode is not updated but the buffers become
// invalid, so we need to manually damage the output here
wlr_output_damage_whole(&conn->output);
- // Since realloc_crtcs can deallocate planes on OTHER outputs,
- // we actually need to reinitialize any that has changed
- ssize_t output_index = -1;
- wl_list_for_each(conn, &drm->outputs, link) {
- output_index++;
- struct wlr_output_mode *mode = conn->output.current_mode;
- struct wlr_drm_crtc *crtc = conn->crtc;
-
- if (conn->state != WLR_DRM_CONN_CONNECTED ||
- !changed_outputs[output_index]) {
- continue;
- }
-
- if (!init_drm_plane_surfaces(crtc->primary, drm,
- mode->width, mode->height, GBM_FORMAT_XRGB8888)) {
- wlr_log(WLR_ERROR, "Failed to initialize renderer for plane");
- goto error_conn;
- }
-
- drm_connector_start_renderer(conn);
- }
-
return true;
-
-error_conn:
- drm_connector_cleanup(conn);
- return false;
}
bool wlr_drm_connector_add_mode(struct wlr_output *output,
@@ -604,7 +497,6 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
bool update_texture) {
struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output;
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend;
- struct wlr_drm_renderer *renderer = &drm->renderer;
struct wlr_drm_crtc *crtc = conn->crtc;
if (!crtc) {
@@ -630,13 +522,16 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
ret = drmGetCap(drm->fd, DRM_CAP_CURSOR_HEIGHT, &h);
h = ret ? 64 : h;
+ struct wlr_drm_renderer *renderer =
+ drm->parent ? &drm->parent->renderer : &drm->renderer;
+
if (!init_drm_surface(&plane->surf, renderer, w, h,
GBM_FORMAT_ARGB8888, 0)) {
wlr_log(WLR_ERROR, "Cannot allocate cursor resources");
return false;
}
- plane->cursor_bo = gbm_bo_create(renderer->gbm, w, h,
+ plane->cursor_bo = gbm_bo_create(drm->renderer.gbm, w, h,
GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
if (!plane->cursor_bo) {
wlr_log_errno(WLR_ERROR, "Failed to create cursor bo");
@@ -811,6 +706,176 @@ static const int32_t subpixel_map[] = {
[DRM_MODE_SUBPIXEL_NONE] = WL_OUTPUT_SUBPIXEL_NONE,
};
+static void dealloc_crtc(struct wlr_drm_connector *conn) {
+ struct wlr_drm_backend *drm = (struct wlr_drm_backend *)conn->output.backend;
+ if (conn->crtc == NULL) {
+ return;
+ }
+
+ wlr_log(WLR_DEBUG, "De-allocating CRTC %zu for output '%s'",
+ conn->crtc - drm->crtcs, conn->output.name);
+
+ for (size_t type = 0; type < 3; ++type) {
+ struct wlr_drm_plane *plane = conn->crtc->planes[type];
+ if (plane == NULL) {
+ continue;
+ }
+
+ finish_drm_surface(&plane->surf);
+ conn->crtc->planes[type] = NULL;
+ }
+
+ drm->iface->conn_enable(drm, conn, false);
+
+ conn->crtc = NULL;
+}
+
+void realloc_crtcs(struct wlr_drm_backend *drm, bool *changed_outputs) {
+ size_t num_outputs = wl_list_length(&drm->outputs);
+
+ wlr_log(WLR_DEBUG, "Reallocating CRTCs");
+
+ uint32_t crtc[drm->num_crtcs];
+ for (size_t i = 0; i < drm->num_crtcs; ++i) {
+ crtc[i] = UNMATCHED;
+ }
+
+ uint32_t possible_crtc[num_outputs];
+ memset(possible_crtc, 0, sizeof(possible_crtc));
+
+ wlr_log(WLR_DEBUG, "State before reallocation:");
+ ssize_t i = -1;
+ struct wlr_drm_connector *conn;
+ wl_list_for_each(conn, &drm->outputs, link) {
+ i++;
+
+ wlr_log(WLR_DEBUG, " '%s' crtc=%d state=%d", conn->output.name,
+ conn->crtc ? (int)(conn->crtc - drm->crtcs) : -1, conn->state);
+
+ if (conn->crtc) {
+ crtc[conn->crtc - drm->crtcs] = i;
+ }
+
+ if (conn->state == WLR_DRM_CONN_CONNECTED ||
+ conn->state == WLR_DRM_CONN_NEEDS_MODESET) {
+ possible_crtc[i] = conn->possible_crtc;
+ }
+ }
+
+ uint32_t crtc_res[drm->num_crtcs];
+ match_obj(wl_list_length(&drm->outputs), possible_crtc,
+ drm->num_crtcs, crtc, crtc_res);
+
+ bool matched[num_outputs];
+ memset(matched, false, sizeof(matched));
+ for (size_t i = 0; i < drm->num_crtcs; ++i) {
+ if (crtc_res[i] != UNMATCHED) {
+ matched[crtc_res[i]] = true;
+ }
+ }
+
+ for (size_t i = 0; i < drm->num_crtcs; ++i) {
+ // We don't want any of the current monitors to be deactivated
+ if (crtc[i] != UNMATCHED && !matched[crtc[i]]) {
+ wlr_log(WLR_DEBUG, "Could not match a CRTC for connected output %d",
+ crtc[i]);
+ return;
+ }
+ }
+
+ struct wlr_drm_connector *connectors[num_outputs];
+ i = 0;
+ wl_list_for_each(conn, &drm->outputs, link) {
+ connectors[i] = conn;
+ i++;
+ }
+
+ for (size_t i = 0; i < drm->num_crtcs; ++i) {
+ if (crtc_res[i] == UNMATCHED) {
+ // De-allocate CRTCs we don't use anymore
+ if (crtc[i] != UNMATCHED) {
+ dealloc_crtc(connectors[crtc[i]]);
+ }
+ continue;
+ }
+
+ if (crtc_res[i] != crtc[i]) {
+ changed_outputs[crtc_res[i]] = true;
+
+ struct wlr_drm_connector *conn = connectors[crtc_res[i]];
+
+ dealloc_crtc(conn);
+ conn->crtc = &drm->crtcs[i];
+
+ wlr_log(WLR_DEBUG, "Assigning CRTC %zu to output %d -> %d '%s'",
+ i, crtc[i], crtc_res[i], conn->output.name);
+ }
+ }
+
+ wlr_log(WLR_DEBUG, "State after reallocation:");
+ wl_list_for_each(conn, &drm->outputs, link) {
+ wlr_log(WLR_DEBUG, " '%s' crtc=%d state=%d", conn->output.name,
+ conn->crtc ? (int)(conn->crtc - drm->crtcs) : -1, conn->state);
+ }
+
+ realloc_planes(drm, crtc_res, changed_outputs);
+
+ // We need to reinitialize any plane that has changed
+ i = -1;
+ wl_list_for_each(conn, &drm->outputs, link) {
+ i++;
+ struct wlr_output_mode *mode = conn->output.current_mode;
+
+ if (conn->state != WLR_DRM_CONN_CONNECTED || !changed_outputs[i]) {
+ continue;
+ }
+ assert(conn->crtc);
+
+ if (!init_drm_plane_surfaces(conn->crtc->primary, drm,
+ mode->width, mode->height, GBM_FORMAT_XRGB8888)) {
+ wlr_log(WLR_ERROR, "Failed to initialize renderer for plane");
+ drm_connector_cleanup(conn);
+ break;
+ }
+
+ drm_connector_start_renderer(conn);
+
+ wlr_output_damage_whole(&conn->output);
+ }
+}
+
+static uint32_t get_possible_crtcs(int fd, uint32_t conn_id) {
+ drmModeConnector *conn = drmModeGetConnector(fd, conn_id);
+ if (!conn) {
+ wlr_log_errno(WLR_ERROR, "Failed to get DRM connector");
+ return 0;
+ }
+
+ if (conn->connection != DRM_MODE_CONNECTED || conn->count_modes == 0) {
+ wlr_log(WLR_ERROR, "Output is not connected");
+ goto error_conn;
+ }
+
+ drmModeEncoder *enc = NULL;
+ for (int i = 0; !enc && i < conn->count_encoders; ++i) {
+ enc = drmModeGetEncoder(fd, conn->encoders[i]);
+ }
+
+ if (!enc) {
+ wlr_log(WLR_ERROR, "Failed to get DRM encoder");
+ goto error_conn;
+ }
+
+ uint32_t ret = enc->possible_crtcs;
+ drmModeFreeEncoder(enc);
+ drmModeFreeConnector(conn);
+ return ret;
+
+error_conn:
+ drmModeFreeConnector(conn);
+ return 0;
+}
+
void scan_drm_connectors(struct wlr_drm_backend *drm) {
wlr_log(WLR_INFO, "Scanning DRM connectors");
@@ -824,7 +889,9 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
// +1 so length can never be 0, which is undefined behaviour.
// Last element isn't used.
bool seen[seen_len + 1];
- memset(seen, 0, sizeof(seen));
+ memset(seen, false, sizeof(seen));
+ size_t new_outputs_len = 0;
+ struct wlr_drm_connector *new_outputs[res->count_connectors + 1];
for (int i = 0; i < res->count_connectors; ++i) {
drmModeConnector *drm_conn = drmModeGetConnector(drm->fd,
@@ -864,17 +931,16 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
wlr_conn->state = WLR_DRM_CONN_DISCONNECTED;
wlr_conn->id = drm_conn->connector_id;
+ snprintf(wlr_conn->output.name, sizeof(wlr_conn->output.name),
+ "%s-%"PRIu32, conn_get_name(drm_conn->connector_type),
+ drm_conn->connector_type_id);
+
if (curr_enc) {
wlr_conn->old_crtc = drmModeGetCrtc(drm->fd, curr_enc->crtc_id);
}
- snprintf(wlr_conn->output.name, sizeof(wlr_conn->output.name),
- "%s-%"PRIu32,
- conn_get_name(drm_conn->connector_type),
- drm_conn->connector_type_id);
-
wl_list_insert(&drm->outputs, &wlr_conn->link);
- wlr_log(WLR_INFO, "Found display '%s'", wlr_conn->output.name);
+ wlr_log(WLR_INFO, "Found connector '%s'", wlr_conn->output.name);
} else {
seen[index] = true;
}
@@ -930,18 +996,20 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
wl_list_insert(&wlr_conn->output.modes, &mode->wlr_mode.link);
}
- wlr_output_update_enabled(&wlr_conn->output, true);
+ wlr_conn->possible_crtc = get_possible_crtcs(drm->fd, wlr_conn->id);
+ if (wlr_conn->possible_crtc == 0) {
+ wlr_log(WLR_ERROR, "No CRTC possible for connector '%s'",
+ wlr_conn->output.name);
+ }
+
+ wlr_output_update_enabled(&wlr_conn->output, wlr_conn->crtc != NULL);
wlr_conn->state = WLR_DRM_CONN_NEEDS_MODESET;
- wlr_log(WLR_INFO, "Sending modesetting signal for '%s'",
- wlr_conn->output.name);
- wlr_signal_emit_safe(&drm->backend.events.new_output,
- &wlr_conn->output);
+ new_outputs[new_outputs_len++] = wlr_conn;
} else if (wlr_conn->state == WLR_DRM_CONN_CONNECTED &&
drm_conn->connection != DRM_MODE_CONNECTED) {
wlr_log(WLR_INFO, "'%s' disconnected", wlr_conn->output.name);
- wlr_output_update_enabled(&wlr_conn->output, false);
drm_connector_cleanup(wlr_conn);
}
@@ -967,6 +1035,44 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
wl_list_remove(&conn->link);
free(conn);
}
+
+ bool changed_outputs[wl_list_length(&drm->outputs)];
+ memset(changed_outputs, false, sizeof(changed_outputs));
+ for (size_t i = 0; i < new_outputs_len; ++i) {
+ struct wlr_drm_connector *conn = new_outputs[i];
+
+ ssize_t pos = -1;
+ struct wlr_drm_connector *c;
+ wl_list_for_each(c, &drm->outputs, link) {
+ ++pos;
+ if (c == conn) {
+ break;
+ }
+ }
+ assert(pos >= 0);
+
+ changed_outputs[pos] = true;
+ }
+
+ realloc_crtcs(drm, changed_outputs);
+
+ for (size_t i = 0; i < new_outputs_len; ++i) {
+ struct wlr_drm_connector *conn = new_outputs[i];
+
+ wlr_log(WLR_INFO, "Requesting modeset for '%s'",
+ conn->output.name);
+ wlr_signal_emit_safe(&drm->backend.events.new_output,
+ &conn->output);
+ }
+
+ // Try to modeset any output that has a desired mode and a CRTC (ie. was
+ // lacking a CRTC on last modeset)
+ wl_list_for_each(conn, &drm->outputs, link) {
+ if (conn->state == WLR_DRM_CONN_NEEDS_MODESET && conn->crtc != NULL &&
+ conn->desired_mode != NULL) {
+ drm_connector_set_mode(&conn->output, conn->desired_mode);
+ }
+ }
}
static void page_flip_handler(int fd, unsigned seq,
@@ -1062,23 +1168,28 @@ static void drm_connector_cleanup(struct wlr_drm_connector *conn) {
}
conn->output.current_mode = NULL;
+ conn->desired_mode = NULL;
struct wlr_drm_mode *mode, *tmp;
wl_list_for_each_safe(mode, tmp, &conn->output.modes, wlr_mode.link) {
wl_list_remove(&mode->wlr_mode.link);
free(mode);
}
+ conn->output.enabled = false;
+ conn->output.width = conn->output.height = conn->output.refresh = 0;
+
memset(&conn->output.make, 0, sizeof(conn->output.make));
memset(&conn->output.model, 0, sizeof(conn->output.model));
memset(&conn->output.serial, 0, sizeof(conn->output.serial));
- conn->crtc = NULL;
- conn->possible_crtc = 0;
conn->pageflip_pending = false;
/* Fallthrough */
case WLR_DRM_CONN_NEEDS_MODESET:
wlr_log(WLR_INFO, "Emitting destruction signal for '%s'",
conn->output.name);
+ dealloc_crtc(conn);
+ conn->possible_crtc = 0;
+ conn->desired_mode = NULL;
wlr_signal_emit_safe(&conn->output.events.destroy, &conn->output);
break;
case WLR_DRM_CONN_DISCONNECTED:
diff --git a/backend/drm/legacy.c b/backend/drm/legacy.c
index d27cf137..c205e167 100644
--- a/backend/drm/legacy.c
+++ b/backend/drm/legacy.c
@@ -39,7 +39,10 @@ bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm,
}
if (!bo) {
- drmModeSetCursor(drm->fd, crtc->id, 0, 0, 0);
+ if (drmModeSetCursor(drm->fd, crtc->id, 0, 0, 0)) {
+ wlr_log_errno(WLR_DEBUG, "Failed to clear hardware cursor");
+ return false;
+ }
return true;
}
diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c
index 38e6315d..fa7d090e 100644
--- a/backend/drm/renderer.c
+++ b/backend/drm/renderer.c
@@ -188,46 +188,29 @@ bool export_drm_bo(struct gbm_bo *bo, struct wlr_dmabuf_attributes *attribs) {
return true;
}
-struct tex {
- struct wlr_egl *egl;
- EGLImageKHR img;
- struct wlr_texture *tex;
-};
-
-static void free_eglimage(struct gbm_bo *bo, void *data) {
- struct tex *tex = data;
-
- wlr_egl_destroy_image(tex->egl, tex->img);
- wlr_texture_destroy(tex->tex);
- free(tex);
+static void free_tex(struct gbm_bo *bo, void *data) {
+ struct wlr_texture *tex = data;
+ wlr_texture_destroy(tex);
}
static struct wlr_texture *get_tex_for_bo(struct wlr_drm_renderer *renderer,
struct gbm_bo *bo) {
- struct tex *tex = gbm_bo_get_user_data(bo);
- if (tex != NULL) {
- return tex->tex;
- }
-
- tex = calloc(1, sizeof(struct tex));
- if (tex == NULL) {
- return NULL;
+ struct wlr_texture *tex = gbm_bo_get_user_data(bo);
+ if (tex) {
+ return tex;
}
struct wlr_dmabuf_attributes attribs;
if (!export_drm_bo(bo, &attribs)) {
- free(tex);
return NULL;
}
- tex->tex = wlr_texture_from_dmabuf(renderer->wlr_rend, &attribs);
- if (tex->tex == NULL) {
- free(tex);
- return NULL;
+ tex = wlr_texture_from_dmabuf(renderer->wlr_rend, &attribs);
+ if (tex) {
+ gbm_bo_set_user_data(bo, tex, free_tex);
}
- gbm_bo_set_user_data(bo, tex, free_eglimage);
- return tex->tex;
+ return tex;
}
struct gbm_bo *copy_drm_surface_mgpu(struct wlr_drm_surface *dest,
@@ -238,7 +221,7 @@ struct gbm_bo *copy_drm_surface_mgpu(struct wlr_drm_surface *dest,
assert(tex);
float mat[9];
- wlr_matrix_projection(mat, 1, 1, WL_OUTPUT_TRANSFORM_FLIPPED_180);
+ wlr_matrix_projection(mat, 1, 1, WL_OUTPUT_TRANSFORM_NORMAL);
struct wlr_renderer *renderer = dest->renderer->wlr_rend;
wlr_renderer_begin(renderer, dest->width, dest->height);
diff --git a/backend/drm/util.c b/backend/drm/util.c
index baacbfa8..050da2a6 100644
--- a/backend/drm/util.c
+++ b/backend/drm/util.c
@@ -144,6 +144,9 @@ const char *conn_get_name(uint32_t type_id) {
case DRM_MODE_CONNECTOR_eDP: return "eDP";
case DRM_MODE_CONNECTOR_VIRTUAL: return "Virtual";
case DRM_MODE_CONNECTOR_DSI: return "DSI";
+#ifdef DRM_MODE_CONNECTOR_DPI
+ case DRM_MODE_CONNECTOR_DPI: return "DPI";
+#endif
default: return "Unknown";
}
}
@@ -225,9 +228,6 @@ static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_
st->replaced = replaced;
memcpy(st->best, st->res, sizeof(st->best[0]) * st->num_res);
- if (st->score == st->num_objs && st->replaced == 0) {
- st->exit_early = true;
- }
st->exit_early = (st->score == st->num_res - skips
|| st->score == st->num_objs)
&& st->replaced == 0;
@@ -247,37 +247,44 @@ static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_
* Attempt to use the current solution first, to try and avoid
* recalculating everything
*/
-
if (st->orig[i] != UNMATCHED && !is_taken(i, st->res, st->orig[i])) {
st->res[i] = st->orig[i];
if (match_obj_(st, skips, score + 1, replaced, i + 1)) {
return true;
}
}
+ if (st->orig[i] == UNMATCHED) {
+ st->res[i] = UNMATCHED;
+ match_obj_(st, skips, score, replaced, i + 1);
+ if (st->exit_early) {
+ return true;
+ }
+ }
if (st->orig[i] != UNMATCHED) {
++replaced;
}
- bool is_best = false;
- for (st->res[i] = 0; st->res[i] < st->num_objs; ++st->res[i]) {
+ bool has_best = false;
+ for (size_t candidate = 0; candidate < st->num_objs; ++candidate) {
// We tried this earlier
- if (st->res[i] == st->orig[i]) {
+ if (candidate == st->orig[i]) {
continue;
}
// Not compatible
- if (!(st->objs[st->res[i]] & (1 << i))) {
+ if (!(st->objs[candidate] & (1 << i))) {
continue;
}
// Already taken
- if (is_taken(i, st->res, st->res[i])) {
+ if (is_taken(i, st->res, candidate)) {
continue;
}
+ st->res[i] = candidate;
if (match_obj_(st, skips, score + 1, replaced, i + 1)) {
- is_best = true;
+ has_best = true;
}
if (st->exit_early) {
@@ -285,7 +292,7 @@ static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_
}
}
- if (is_best) {
+ if (has_best) {
return true;
}
@@ -298,6 +305,9 @@ size_t match_obj(size_t num_objs, const uint32_t objs[static restrict num_objs],
size_t num_res, const uint32_t res[static restrict num_res],
uint32_t out[static restrict num_res]) {
uint32_t solution[num_res];
+ for (size_t i = 0; i < num_res; ++i) {
+ solution[i] = UNMATCHED;
+ }
struct match_state st = {
.num_objs = num_objs,
diff --git a/backend/libinput/tablet_pad.c b/backend/libinput/tablet_pad.c
index 579a11cf..0642f925 100644
--- a/backend/libinput/tablet_pad.c
+++ b/backend/libinput/tablet_pad.c
@@ -28,7 +28,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad,
++group->ring_count;
}
}
- group->rings = calloc(sizeof(int), group->ring_count);
+ group->rings = calloc(sizeof(unsigned int), group->ring_count);
size_t ring = 0;
for (size_t i = 0; i < pad->ring_count; ++i) {
if (libinput_tablet_pad_mode_group_has_ring(li_group, i)) {
@@ -41,7 +41,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad,
++group->strip_count;
}
}
- group->strips = calloc(sizeof(int), group->strip_count);
+ group->strips = calloc(sizeof(unsigned int), group->strip_count);
size_t strip = 0;
for (size_t i = 0; i < pad->strip_count; ++i) {
if (libinput_tablet_pad_mode_group_has_strip(li_group, i)) {
@@ -54,7 +54,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad,
++group->button_count;
}
}
- group->buttons = calloc(sizeof(int), group->button_count);
+ group->buttons = calloc(sizeof(unsigned int), group->button_count);
size_t button = 0;
for (size_t i = 0; i < pad->button_count; ++i) {
if (libinput_tablet_pad_mode_group_has_button(li_group, i)) {
diff --git a/backend/meson.build b/backend/meson.build
index 52abe64d..dd1f4df3 100644
--- a/backend/meson.build
+++ b/backend/meson.build
@@ -1,3 +1,4 @@
+backend_parts = []
backend_files = files(
'backend.c',
'drm/atomic.c',
@@ -44,28 +45,17 @@ else
backend_files += files('session/direct.c')
endif
-if conf_data.get('WLR_HAS_SYSTEMD', false)
+if logind.found()
backend_files += files('session/logind.c')
- backend_deps += systemd
+ backend_deps += logind
endif
-if conf_data.get('WLR_HAS_X11_BACKEND', false)
- backend_files += files(
- 'x11/backend.c',
- 'x11/input_device.c',
- 'x11/output.c',
- )
- backend_deps += xcb_xkb
-endif
-
-if conf_data.get('WLR_HAS_ELOGIND', false)
- backend_files += files('session/logind.c')
- backend_deps += elogind
-endif
+subdir('x11')
lib_wlr_backend = static_library(
'wlr_backend',
backend_files,
include_directories: wlr_inc,
+ link_whole: backend_parts,
dependencies: backend_deps,
)
diff --git a/backend/multi/backend.c b/backend/multi/backend.c
index f1d50347..e0038955 100644
--- a/backend/multi/backend.c
+++ b/backend/multi/backend.c
@@ -143,7 +143,7 @@ bool wlr_multi_backend_add(struct wlr_backend *_multi,
struct wlr_renderer *multi_renderer =
multi_backend_get_renderer(&multi->backend);
struct wlr_renderer *backend_renderer = wlr_backend_get_renderer(backend);
- if (multi_renderer != NULL && backend_renderer != NULL) {
+ if (multi_renderer != NULL && backend_renderer != NULL && multi_renderer != backend_renderer) {
wlr_log(WLR_ERROR, "Could not add backend: multiple renderers at the "
"same time aren't supported");
return false;
diff --git a/backend/session/direct-freebsd.c b/backend/session/direct-freebsd.c
index 63e1be01..cecfb0c1 100644
--- a/backend/session/direct-freebsd.c
+++ b/backend/session/direct-freebsd.c
@@ -15,6 +15,7 @@
#include <wayland-server.h>
#include <wlr/backend/session/interface.h>
#include <wlr/util/log.h>
+#include <xf86drm.h>
#include "backend/session/direct-ipc.h"
#include "util/signal.h"
@@ -23,6 +24,7 @@ const struct session_impl session_direct;
struct direct_session {
struct wlr_session base;
int tty_fd;
+ int old_tty;
int old_kbmode;
int sock;
pid_t child;
@@ -40,23 +42,18 @@ static int direct_session_open(struct wlr_session *base, const char *path) {
return fd;
}
- struct stat st;
- if (fstat(fd, &st) < 0) {
- close(fd);
- return -errno;
- }
-
return fd;
}
static void direct_session_close(struct wlr_session *base, int fd) {
struct direct_session *session = wl_container_of(base, session, base);
- struct stat st;
- if (fstat(fd, &st) < 0) {
- wlr_log_errno(WLR_ERROR, "Stat failed");
- close(fd);
- return;
+ int ev;
+ struct drm_version dv = {0};
+ if (ioctl(fd, DRM_IOCTL_VERSION, &dv) == 0) {
+ direct_ipc_dropmaster(session->sock, fd);
+ } else if (ioctl(fd, EVIOCGVERSION, &ev) == 0) {
+ ioctl(fd, EVIOCREVOKE, 0);
}
close(fd);
@@ -79,6 +76,8 @@ static void direct_session_destroy(struct wlr_session *base) {
ioctl(session->tty_fd, KDSETMODE, KD_TEXT);
ioctl(session->tty_fd, VT_SETMODE, &mode);
+ ioctl(session->tty_fd, VT_ACTIVATE, session->old_tty);
+
if (errno) {
wlr_log(WLR_ERROR, "Failed to restore tty");
}
@@ -93,13 +92,29 @@ static void direct_session_destroy(struct wlr_session *base) {
static int vt_handler(int signo, void *data) {
struct direct_session *session = data;
+ struct drm_version dv = {0};
+ struct wlr_device *dev;
if (session->base.active) {
session->base.active = false;
wlr_signal_emit_safe(&session->base.session_signal, session);
+
+ wl_list_for_each(dev, &session->base.devices, link) {
+ if (ioctl(dev->fd, DRM_IOCTL_VERSION, &dv) == 0) {
+ direct_ipc_dropmaster(session->sock, dev->fd);
+ }
+ }
+
ioctl(session->tty_fd, VT_RELDISP, 1);
} else {
ioctl(session->tty_fd, VT_RELDISP, VT_ACKACQ);
+
+ wl_list_for_each(dev, &session->base.devices, link) {
+ if (ioctl(dev->fd, DRM_IOCTL_VERSION, &dv) == 0) {
+ direct_ipc_setmaster(session->sock, dev->fd);
+ }
+ }
+
session->base.active = true;
wlr_signal_emit_safe(&session->base.session_signal, session);
}
@@ -108,11 +123,15 @@ static int vt_handler(int signo, void *data) {
}
static bool setup_tty(struct direct_session *session, struct wl_display *display) {
- int fd = -1, tty = -1, tty0_fd = -1;
+ int fd = -1, tty = -1, tty0_fd = -1, old_tty = 1;
if ((tty0_fd = open("/dev/ttyv0", O_RDWR | O_CLOEXEC)) < 0) {
wlr_log_errno(WLR_ERROR, "Could not open /dev/ttyv0 to find a free vt");
goto error;
}
+ if (ioctl(tty0_fd, VT_GETACTIVE, &old_tty) != 0) {
+ wlr_log_errno(WLR_ERROR, "Could not get active vt");
+ goto error;
+ }
if (ioctl(tty0_fd, VT_OPENQRY, &tty) != 0) {
wlr_log_errno(WLR_ERROR, "Could not find a free vt");
goto error;
@@ -168,13 +187,16 @@ static bool setup_tty(struct direct_session *session, struct wl_display *display
session->base.vtnr = tty;
session->tty_fd = fd;
+ session->old_tty = old_tty;
session->old_kbmode = old_kbmode;
return true;
error:
- // Drop back to tty 1, better than hanging in a useless blank console
- ioctl(fd, VT_ACTIVATE, 1);
+ // In case we could not get the last active one, drop back to tty 1,
+ // better than hanging in a useless blank console. Otherwise activate the
+ // last active.
+ ioctl(fd, VT_ACTIVATE, old_tty);
close(fd);
return false;
}
diff --git a/backend/session/direct-ipc.c b/backend/session/direct-ipc.c
index 5fdb95ac..3abce46a 100644
--- a/backend/session/direct-ipc.c
+++ b/backend/session/direct-ipc.c
@@ -1,7 +1,7 @@
#define _POSIX_C_SOURCE 200809L
#ifdef __FreeBSD__
#define __BSD_VISIBLE 1
-#define INPUT_MAJOR 0
+#include <dev/evdev/input.h>
#endif
#include <errno.h>
#include <fcntl.h>
@@ -142,6 +142,7 @@ static void communicate(int sock) {
goto error;
}
+#ifndef __FreeBSD__
struct stat st;
if (fstat(fd, &st) < 0) {
ret = errno;
@@ -157,6 +158,20 @@ static void communicate(int sock) {
if (maj == DRM_MAJOR && drmSetMaster(fd)) {
ret = errno;
}
+#else
+ int ev;
+ struct drm_version dv = {0};
+ if (ioctl(fd, EVIOCGVERSION, &ev) == -1 &&
+ ioctl(fd, DRM_IOCTL_VERSION, &dv) == -1) {
+ ret = ENOTSUP;
+ goto error;
+ }
+
+ if (dv.version_major != 0 && drmSetMaster(fd)) {
+ ret = errno;
+ }
+#endif
+
error:
send_msg(sock, ret ? -1 : fd, &ret, sizeof(ret));
if (fd >= 0) {
@@ -193,8 +208,11 @@ int direct_ipc_open(int sock, const char *path) {
send_msg(sock, -1, &msg, sizeof(msg));
- int fd, err;
- recv_msg(sock, &fd, &err, sizeof(err));
+ int fd, err, ret;
+ int retry = 0;
+ do {
+ ret = recv_msg(sock, &fd, &err, sizeof(err));
+ } while (ret == 0 && retry++ < 3);
return err ? -err : fd;
}
diff --git a/backend/session/session.c b/backend/session/session.c
index 8d74bafe..3fcac3e3 100644
--- a/backend/session/session.c
+++ b/backend/session/session.c
@@ -79,6 +79,7 @@ struct wlr_session *wlr_session_create(struct wl_display *disp) {
session->active = true;
wl_signal_init(&session->session_signal);
+ wl_signal_init(&session->events.destroy);
wl_list_init(&session->devices);
session->udev = udev_new();
@@ -125,6 +126,7 @@ void wlr_session_destroy(struct wlr_session *session) {
return;
}
+ wlr_signal_emit_safe(&session->events.destroy, session);
wl_list_remove(&session->display_destroy.link);
wl_event_source_remove(session->udev_event);
@@ -220,17 +222,9 @@ static int open_if_kms(struct wlr_session *restrict session, const char *restric
goto out_fd;
}
- if (res->count_crtcs <= 0 || res->count_connectors <= 0 ||
- res->count_encoders <= 0) {
-
- goto out_res;
- }
-
drmModeFreeResources(res);
return fd;
-out_res:
- drmModeFreeResources(res);
out_fd:
wlr_session_close_file(session, fd);
return -1;
diff --git a/backend/wayland/wl_seat.c b/backend/wayland/wl_seat.c
index 5163e804..8fb4aa5f 100644
--- a/backend/wayland/wl_seat.c
+++ b/backend/wayland/wl_seat.c
@@ -1,4 +1,4 @@
-#define _XOPEN_SOURCE 500
+#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
diff --git a/backend/x11/backend.c b/backend/x11/backend.c
index e0f5d6e7..0ff2925d 100644
--- a/backend/x11/backend.c
+++ b/backend/x11/backend.c
@@ -163,6 +163,8 @@ static bool backend_start(struct wlr_backend *backend) {
0,
0,
0);
+
+ free(reply);
}
}
#endif
diff --git a/backend/x11/meson.build b/backend/x11/meson.build
new file mode 100644
index 00000000..1164df1e
--- /dev/null
+++ b/backend/x11/meson.build
@@ -0,0 +1,44 @@
+x11_libs = []
+x11_required = [
+ 'xcb',
+ 'x11-xcb',
+]
+x11_optional = [
+ 'xcb-xkb',
+]
+
+foreach lib : x11_required
+ dep = dependency(lib, required: get_option('x11-backend'))
+ if not dep.found()
+ subdir_done()
+ endif
+
+ x11_libs += dep
+endforeach
+
+foreach lib : x11_optional
+ dep = dependency(lib, required: get_option(lib))
+ if dep.found()
+ x11_libs += dep
+ conf_data.set('WLR_HAS_' + lib.underscorify().to_upper(), true)
+ endif
+endforeach
+
+lib_wlr_backend_x11 = static_library(
+ 'wlr_backend_x11',
+ files(
+ 'backend.c',
+ 'input_device.c',
+ 'output.c',
+ ),
+ include_directories: wlr_inc,
+ dependencies: [
+ wayland_server,
+ pixman,
+ xkbcommon,
+ x11_libs,
+ ],
+)
+
+backend_parts += lib_wlr_backend_x11
+conf_data.set('WLR_HAS_X11_BACKEND', true)
diff --git a/backend/x11/output.c b/backend/x11/output.c
index 151807dd..b678296d 100644
--- a/backend/x11/output.c
+++ b/backend/x11/output.c
@@ -121,6 +121,9 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
struct wlr_output *wlr_output = &output->wlr_output;
wlr_output_init(wlr_output, &x11->backend, &output_impl, x11->wl_display);
+ wlr_output->width = 1024;
+ wlr_output->height = 768;
+
output_set_refresh(&output->wlr_output, 0);
snprintf(wlr_output->name, sizeof(wlr_output->name), "X11-%d",
@@ -137,8 +140,8 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
};
output->win = xcb_generate_id(x11->xcb_conn);
xcb_create_window(x11->xcb_conn, XCB_COPY_FROM_PARENT, output->win,
- x11->screen->root, 0, 0, 1024, 768, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT,
- x11->screen->root_visual, mask, values);
+ x11->screen->root, 0, 0, wlr_output->width, wlr_output->height, 1,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, x11->screen->root_visual, mask, values);
output->surf = wlr_egl_create_surface(&x11->egl, &output->win);
if (!output->surf) {
@@ -187,11 +190,17 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
void handle_x11_configure_notify(struct wlr_x11_output *output,
xcb_configure_notify_event_t *ev) {
- wlr_output_update_custom_mode(&output->wlr_output, ev->width,
- ev->height, output->wlr_output.refresh);
-
- // Move the pointer to its new location
- update_x11_pointer_position(output, output->x11->time);
+ // ignore events that set an invalid size:
+ if (ev->width > 0 && ev->height > 0) {
+ wlr_output_update_custom_mode(&output->wlr_output, ev->width,
+ ev->height, output->wlr_output.refresh);
+
+ // Move the pointer to its new location
+ update_x11_pointer_position(output, output->x11->time);
+ } else {
+ wlr_log(WLR_DEBUG,"Ignoring X11 configure event for height=%d, width=%d",
+ ev->width, ev->height);
+ }
}
bool wlr_output_is_x11(struct wlr_output *wlr_output) {
diff --git a/docs/env_vars.md b/docs/env_vars.md
index 3f1926d3..b28849cc 100644
--- a/docs/env_vars.md
+++ b/docs/env_vars.md
@@ -12,6 +12,8 @@ wlroots specific
wayland, x11, headless)
* *WLR_WL_OUTPUTS*: when using the wayland backend specifies the number of outputs
* *WLR_X11_OUTPUTS*: when using the X11 backend specifies the number of outputs
+* *WLR_HEADLESS_OUTPUTS*: when using the headless backend specifies the number
+ of outputs
rootston specific
------------------
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:;
diff --git a/glgen.sh b/glgen.sh
index 0356cf98..fb3bb3c6 100755
--- a/glgen.sh
+++ b/glgen.sh
@@ -7,16 +7,15 @@
# to fail if it can't load the function. You'll need to check if that function
# is NULL before using it.
-if [ $# -ne 3 ]; then
+if [ $# -ne 2 ]; then
exit 1
fi
SPEC=$1
-OUT_C=$2
-OUT_H=$3
+OUTDIR=$2
BASE=$(basename "$SPEC" .txt)
-INCLUDE_GUARD=$(printf %s "$OUT_H" | tr -c [:alnum:] _ | tr [:lower:] [:upper:])
+INCLUDE_GUARD=$(printf %s_%s_H "$OUTDIR" "$BASE" | tr -c [:alnum:] _ | tr [:lower:] [:upper:])
DECL=""
DEFN=""
@@ -56,9 +55,9 @@ while read -r COMMAND; do
if [ $OPTIONAL -eq 0 ]; then
LOADER="$LOADER$(printf "\n$CHECK_FMT" "$COMMAND" "$COMMAND")"
fi
-done < $SPEC
+done < "$SPEC"
-cat > $OUT_H << EOF
+cat > "$OUTDIR/$BASE.h" << EOF
#ifndef $INCLUDE_GUARD
#define $INCLUDE_GUARD
@@ -66,7 +65,6 @@ cat > $OUT_H << EOF
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <EGL/eglmesaext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
@@ -76,9 +74,9 @@ $DECL
#endif
EOF
-cat > $OUT_C << EOF
+cat > "$OUTDIR/$BASE.c" << EOF
#include <wlr/util/log.h>
-#include "$OUT_H"
+#include "$BASE.h"
$DEFN
bool load_$BASE(void) {
diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h
index 416507ea..fe279917 100644
--- a/include/backend/drm/drm.h
+++ b/include/backend/drm/drm.h
@@ -119,6 +119,7 @@ struct wlr_drm_connector {
struct wlr_output output;
enum wlr_drm_connector_state state;
+ struct wlr_output_mode *desired_mode;
uint32_t id;
struct wlr_drm_crtc *crtc;
@@ -143,9 +144,5 @@ void restore_drm_outputs(struct wlr_drm_backend *drm);
void scan_drm_connectors(struct wlr_drm_backend *state);
int handle_drm_event(int fd, uint32_t mask, void *data);
void enable_drm_connector(struct wlr_output *output, bool enable);
-/**
- * Add mode to the list of available modes
- */
-bool wlr_drm_connector_add_mode(struct wlr_output *output, const drmModeModeInfo *mode);
#endif
diff --git a/include/render/gles2.h b/include/render/gles2.h
index 8b036f80..f649f3e2 100644
--- a/include/render/gles2.h
+++ b/include/render/gles2.h
@@ -88,7 +88,7 @@ const struct wlr_gles2_pixel_format *get_gles2_format_from_wl(
enum wl_shm_format fmt);
const enum wl_shm_format *get_gles2_formats(size_t *len);
-struct wlr_gles2_texture *get_gles2_texture_in_context(
+struct wlr_gles2_texture *gles2_get_texture(
struct wlr_texture *wlr_texture);
void push_gles2_marker(const char *file, const char *func);
diff --git a/include/rootston/cursor.h b/include/rootston/cursor.h
index f7410dec..2c687a39 100644
--- a/include/rootston/cursor.h
+++ b/include/rootston/cursor.h
@@ -80,4 +80,7 @@ void roots_cursor_handle_tool_tip(struct roots_cursor *cursor,
void roots_cursor_handle_request_set_cursor(struct roots_cursor *cursor,
struct wlr_seat_pointer_request_set_cursor_event *event);
+void roots_cursor_update_position(struct roots_cursor *cursor,
+ uint32_t time);
+
#endif
diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h
index d9add26a..3496fb43 100644
--- a/include/rootston/desktop.h
+++ b/include/rootston/desktop.h
@@ -4,26 +4,24 @@
#include <wayland-server.h>
#include <wlr/config.h>
#include <wlr/types/wlr_compositor.h>
+#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_gamma_control.h>
+#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_input_inhibitor.h>
#include <wlr/types/wlr_layer_shell.h>
-#include <wlr/types/wlr_linux_dmabuf.h>
#include <wlr/types/wlr_list.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_primary_selection.h>
+#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_screenshooter.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_wl_shell.h>
#include <wlr/types/wlr_xcursor_manager.h>
+#include <wlr/types/wlr_xdg_decoration_v1.h>
#include <wlr/types/wlr_xdg_shell_v6.h>
#include <wlr/types/wlr_xdg_shell.h>
-#include <wlr/types/wlr_list.h>
-#include <wlr/types/wlr_idle.h>
-#include <wlr/types/wlr_idle_inhibit_v1.h>
-#include <wlr/types/wlr_screencopy_v1.h>
-#include "rootston/view.h"
#include "rootston/config.h"
#include "rootston/output.h"
#include "rootston/view.h"
@@ -45,14 +43,15 @@ struct roots_desktop {
struct wlr_xdg_shell_v6 *xdg_shell_v6;
struct wlr_xdg_shell *xdg_shell;
struct wlr_gamma_control_manager *gamma_control_manager;
+ struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
struct wlr_screenshooter *screenshooter;
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1;
struct wlr_server_decoration_manager *server_decoration_manager;
+ struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager;
struct wlr_primary_selection_device_manager *primary_selection_device_manager;
struct wlr_idle *idle;
struct wlr_idle_inhibit_manager_v1 *idle_inhibit;
struct wlr_input_inhibit_manager *input_inhibit;
- struct wlr_linux_dmabuf *linux_dmabuf;
struct wlr_layer_shell *layer_shell;
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
struct wlr_screencopy_manager_v1 *screencopy;
@@ -64,7 +63,7 @@ struct roots_desktop {
struct wl_listener xdg_shell_surface;
struct wl_listener wl_shell_surface;
struct wl_listener layer_shell_surface;
- struct wl_listener decoration_new;
+ struct wl_listener xdg_toplevel_decoration;
struct wl_listener input_inhibit_activate;
struct wl_listener input_inhibit_deactivate;
struct wl_listener virtual_keyboard_new;
@@ -94,6 +93,7 @@ void view_apply_damage(struct roots_view *view);
void view_damage_whole(struct roots_view *view);
void view_update_position(struct roots_view *view, double x, double y);
void view_update_size(struct roots_view *view, uint32_t width, uint32_t height);
+void view_update_decorated(struct roots_view *view, bool decorated);
void view_initial_focus(struct roots_view *view);
void view_map(struct roots_view *view, struct wlr_surface *surface);
void view_unmap(struct roots_view *view);
@@ -101,6 +101,7 @@ void view_arrange_maximized(struct roots_view *view);
void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data);
void handle_xdg_shell_surface(struct wl_listener *listener, void *data);
+void handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data);
void handle_wl_shell_surface(struct wl_listener *listener, void *data);
void handle_layer_shell_surface(struct wl_listener *listener, void *data);
void handle_xwayland_surface(struct wl_listener *listener, void *data);
diff --git a/include/rootston/input.h b/include/rootston/input.h
index ef46fab2..2cdb13e6 100644
--- a/include/rootston/input.h
+++ b/include/rootston/input.h
@@ -32,4 +32,6 @@ struct roots_seat *input_get_seat(struct roots_input *input, char *name);
struct roots_seat *input_last_active_seat(struct roots_input *input);
+void input_update_cursor_focus(struct roots_input *input);
+
#endif
diff --git a/include/rootston/view.h b/include/rootston/view.h
index 4e3859d5..14448fc6 100644
--- a/include/rootston/view.h
+++ b/include/rootston/view.h
@@ -4,6 +4,7 @@
#include <wlr/config.h>
#include <wlr/types/wlr_box.h>
#include <wlr/types/wlr_surface.h>
+#include <wlr/types/wlr_xdg_decoration_v1.h>
#include <wlr/types/wlr_xdg_shell_v6.h>
#include <wlr/types/wlr_xdg_shell.h>
@@ -38,6 +39,8 @@ struct roots_xdg_surface_v6 {
uint32_t pending_move_resize_configure_serial;
};
+struct roots_xdg_toplevel_decoration;
+
struct roots_xdg_surface {
struct roots_view *view;
@@ -53,6 +56,8 @@ struct roots_xdg_surface {
struct wl_listener surface_commit;
uint32_t pending_move_resize_configure_serial;
+
+ struct roots_xdg_toplevel_decoration *xdg_toplevel_decoration;
};
struct roots_xwayland_surface {
@@ -190,6 +195,14 @@ struct roots_xdg_popup {
struct wl_listener new_popup;
};
+struct roots_xdg_toplevel_decoration {
+ struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration;
+ struct roots_xdg_surface *surface;
+ struct wl_listener destroy;
+ struct wl_listener request_mode;
+ struct wl_listener surface_commit;
+};
+
void view_get_box(const struct roots_view *view, struct wlr_box *box);
void view_activate(struct roots_view *view, bool active);
void view_move(struct roots_view *view, double x, double y);
diff --git a/include/types/wlr_xdg_shell.h b/include/types/wlr_xdg_shell.h
index 7a17d286..93fdc670 100644
--- a/include/types/wlr_xdg_shell.h
+++ b/include/types/wlr_xdg_shell.h
@@ -19,7 +19,8 @@ struct wlr_xdg_surface *create_xdg_surface(
uint32_t id);
void unmap_xdg_surface(struct wlr_xdg_surface *surface);
void destroy_xdg_surface(struct wlr_xdg_surface *surface);
-void handle_xdg_surface_committed(struct wlr_surface *wlr_surface);
+void handle_xdg_surface_commit(struct wlr_surface *wlr_surface);
+void handle_xdg_surface_precommit(struct wlr_surface *wlr_surface);
void create_xdg_positioner(struct wlr_xdg_client *client, uint32_t id);
struct wlr_xdg_positioner_resource *get_xdg_positioner_from_resource(
diff --git a/include/types/wlr_xdg_shell_v6.h b/include/types/wlr_xdg_shell_v6.h
index 030c10e4..59fca667 100644
--- a/include/types/wlr_xdg_shell_v6.h
+++ b/include/types/wlr_xdg_shell_v6.h
@@ -19,7 +19,8 @@ struct wlr_xdg_surface_v6 *create_xdg_surface_v6(
uint32_t id);
void unmap_xdg_surface_v6(struct wlr_xdg_surface_v6 *surface);
void destroy_xdg_surface_v6(struct wlr_xdg_surface_v6 *surface);
-void handle_xdg_surface_v6_committed(struct wlr_surface *wlr_surface);
+void handle_xdg_surface_v6_commit(struct wlr_surface *wlr_surface);
+void handle_xdg_surface_v6_precommit(struct wlr_surface *wlr_surface);
void create_xdg_positioner_v6(struct wlr_xdg_client_v6 *client, uint32_t id);
struct wlr_xdg_positioner_v6_resource *get_xdg_positioner_v6_from_resource(
diff --git a/include/wlr/backend.h b/include/wlr/backend.h
index f40f5353..39d072e2 100644
--- a/include/wlr/backend.h
+++ b/include/wlr/backend.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_BACKEND_H
#define WLR_BACKEND_H
diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h
index 7f41ca15..5d47647d 100644
--- a/include/wlr/backend/drm.h
+++ b/include/wlr/backend/drm.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_BACKEND_DRM_H
#define WLR_BACKEND_DRM_H
@@ -20,6 +28,12 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
bool wlr_backend_is_drm(struct wlr_backend *backend);
bool wlr_output_is_drm(struct wlr_output *output);
+/**
+ * Add mode to the list of available modes
+ */
+typedef struct _drmModeModeInfo drmModeModeInfo;
+bool wlr_drm_connector_add_mode(struct wlr_output *output, const drmModeModeInfo *mode);
+
struct wlr_session *wlr_drm_backend_get_session(struct wlr_backend *backend);
#endif
diff --git a/include/wlr/backend/headless.h b/include/wlr/backend/headless.h
index 02c7cd11..eab102e2 100644
--- a/include/wlr/backend/headless.h
+++ b/include/wlr/backend/headless.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_BACKEND_HEADLESS_H
#define WLR_BACKEND_HEADLESS_H
diff --git a/include/wlr/backend/interface.h b/include/wlr/backend/interface.h
index 42b39a16..f3dee69b 100644
--- a/include/wlr/backend/interface.h
+++ b/include/wlr/backend/interface.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_BACKEND_INTERFACE_H
#define WLR_BACKEND_INTERFACE_H
diff --git a/include/wlr/backend/libinput.h b/include/wlr/backend/libinput.h
index 92d31415..1a2ab294 100644
--- a/include/wlr/backend/libinput.h
+++ b/include/wlr/backend/libinput.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_BACKEND_LIBINPUT_H
#define WLR_BACKEND_LIBINPUT_H
diff --git a/include/wlr/backend/meson.build b/include/wlr/backend/meson.build
new file mode 100644
index 00000000..e005b854
--- /dev/null
+++ b/include/wlr/backend/meson.build
@@ -0,0 +1,16 @@
+install_headers(
+ 'drm.h',
+ 'headless.h',
+ 'interface.h',
+ 'libinput.h',
+ 'multi.h',
+ 'session.h',
+ 'wayland.h',
+ subdir: 'wlr/backend',
+)
+
+if conf_data.get('WLR_HAS_X11_BACKEND', false)
+ install_headers('x11.h', subdir: 'wlr/backend')
+endif
+
+subdir('session')
diff --git a/include/wlr/backend/multi.h b/include/wlr/backend/multi.h
index 1e04dba4..7137b075 100644
--- a/include/wlr/backend/multi.h
+++ b/include/wlr/backend/multi.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_BACKEND_MULTI_H
#define WLR_BACKEND_MULTI_H
diff --git a/include/wlr/backend/session.h b/include/wlr/backend/session.h
index 1cf41939..7b26f34c 100644
--- a/include/wlr/backend/session.h
+++ b/include/wlr/backend/session.h
@@ -39,6 +39,10 @@ struct wlr_session {
struct wl_list devices;
struct wl_listener display_destroy;
+
+ struct {
+ struct wl_signal destroy;
+ } events;
};
/*
diff --git a/include/wlr/backend/session/interface.h b/include/wlr/backend/session/interface.h
index b35ed71d..5ccf9c8a 100644
--- a/include/wlr/backend/session/interface.h
+++ b/include/wlr/backend/session/interface.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_BACKEND_SESSION_INTERFACE_H
#define WLR_BACKEND_SESSION_INTERFACE_H
diff --git a/include/wlr/backend/session/meson.build b/include/wlr/backend/session/meson.build
new file mode 100644
index 00000000..21b5a96b
--- /dev/null
+++ b/include/wlr/backend/session/meson.build
@@ -0,0 +1 @@
+install_headers('interface.h', subdir: 'wlr/backend/session')
diff --git a/include/wlr/config.h.in b/include/wlr/config.h.in
new file mode 100644
index 00000000..750ad3b7
--- /dev/null
+++ b/include/wlr/config.h.in
@@ -0,0 +1,19 @@
+#ifndef WLR_CONFIG_H
+#define WLR_CONFIG_H
+
+#mesondefine WLR_HAS_LIBCAP
+
+#mesondefine WLR_HAS_SYSTEMD
+#mesondefine WLR_HAS_ELOGIND
+
+#mesondefine WLR_HAS_X11_BACKEND
+
+#mesondefine WLR_HAS_XWAYLAND
+
+#mesondefine WLR_HAS_XCB_ERRORS
+#mesondefine WLR_HAS_XCB_ICCCM
+#mesondefine WLR_HAS_XCB_XKB
+
+#mesondefine WLR_HAS_POSIX_FALLOCATE
+
+#endif
diff --git a/include/wlr/interfaces/meson.build b/include/wlr/interfaces/meson.build
new file mode 100644
index 00000000..207896b5
--- /dev/null
+++ b/include/wlr/interfaces/meson.build
@@ -0,0 +1,10 @@
+install_headers(
+ 'wlr_input_device.h',
+ 'wlr_keyboard.h',
+ 'wlr_output.h',
+ 'wlr_pointer.h',
+ 'wlr_tablet_pad.h',
+ 'wlr_tablet_tool.h',
+ 'wlr_touch.h',
+ subdir: 'wlr/interfaces',
+)
diff --git a/include/wlr/interfaces/wlr_input_device.h b/include/wlr/interfaces/wlr_input_device.h
index a5c513b7..05248bf6 100644
--- a/include/wlr/interfaces/wlr_input_device.h
+++ b/include/wlr/interfaces/wlr_input_device.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_INTERFACES_WLR_INPUT_DEVICE_H
#define WLR_INTERFACES_WLR_INPUT_DEVICE_H
diff --git a/include/wlr/interfaces/wlr_keyboard.h b/include/wlr/interfaces/wlr_keyboard.h
index c9a13fd7..5d537827 100644
--- a/include/wlr/interfaces/wlr_keyboard.h
+++ b/include/wlr/interfaces/wlr_keyboard.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_INTERFACES_WLR_KEYBOARD_H
#define WLR_INTERFACES_WLR_KEYBOARD_H
diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h
index 8f87408a..4860a5b6 100644
--- a/include/wlr/interfaces/wlr_output.h
+++ b/include/wlr/interfaces/wlr_output.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_INTERFACES_WLR_OUTPUT_H
#define WLR_INTERFACES_WLR_OUTPUT_H
@@ -20,7 +28,7 @@ struct wlr_output_impl {
void (*destroy)(struct wlr_output *output);
bool (*make_current)(struct wlr_output *output, int *buffer_age);
bool (*swap_buffers)(struct wlr_output *output, pixman_region32_t *damage);
- void (*set_gamma)(struct wlr_output *output,
+ bool (*set_gamma)(struct wlr_output *output,
uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b);
uint32_t (*get_gamma_size)(struct wlr_output *output);
bool (*export_dmabuf)(struct wlr_output *output,
diff --git a/include/wlr/interfaces/wlr_pointer.h b/include/wlr/interfaces/wlr_pointer.h
index f0cf9081..fd3ab102 100644
--- a/include/wlr/interfaces/wlr_pointer.h
+++ b/include/wlr/interfaces/wlr_pointer.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_INTERFACES_WLR_POINTER_H
#define WLR_INTERFACES_WLR_POINTER_H
diff --git a/include/wlr/interfaces/wlr_tablet_pad.h b/include/wlr/interfaces/wlr_tablet_pad.h
index 5ec1e3eb..86bbe9c3 100644
--- a/include/wlr/interfaces/wlr_tablet_pad.h
+++ b/include/wlr/interfaces/wlr_tablet_pad.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_INTERFACES_WLR_TABLET_PAD_H
#define WLR_INTERFACES_WLR_TABLET_PAD_H
diff --git a/include/wlr/interfaces/wlr_tablet_tool.h b/include/wlr/interfaces/wlr_tablet_tool.h
index 12b2e32e..9cfc3ca0 100644
--- a/include/wlr/interfaces/wlr_tablet_tool.h
+++ b/include/wlr/interfaces/wlr_tablet_tool.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_INTERFACES_WLR_TABLET_TOOL_H
#define WLR_INTERFACES_WLR_TABLET_TOOL_H
diff --git a/include/wlr/interfaces/wlr_touch.h b/include/wlr/interfaces/wlr_touch.h
index 63bac6b8..cc426332 100644
--- a/include/wlr/interfaces/wlr_touch.h
+++ b/include/wlr/interfaces/wlr_touch.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_INTERFACES_WLR_TOUCH_H
#define WLR_INTERFACES_WLR_TOUCH_H
diff --git a/include/wlr/meson.build b/include/wlr/meson.build
index 6259c311..43b5aec9 100644
--- a/include/wlr/meson.build
+++ b/include/wlr/meson.build
@@ -4,11 +4,23 @@ version_data.set_quoted('WLR_VERSION_STR', meson.project_version())
version_data.set('WLR_VERSION_MAJOR', version_array[0])
version_data.set('WLR_VERSION_MINOR', version_array[1])
version_data.set('WLR_VERSION_MICRO', version_array[2])
-version_data.set('WLR_VERSION_NUM', '(WLR_VERSION_MAJOR << 16) | (WLR_VERSION_MINOR << 8) | WLR_VERSION_MICRO')
version_data.set('WLR_VERSION_API_CURRENT', so_version[0])
version_data.set('WLR_VERSION_API_REVISION', so_version[1])
version_data.set('WLR_VERSION_API_AGE', so_version[2])
-wlr_inc_dest = join_paths(get_option('includedir'), 'wlr')
-configure_file(output: 'config.h', install_dir: wlr_inc_dest, configuration: conf_data)
-configure_file(output: 'version.h', install_dir: wlr_inc_dest, configuration: version_data)
+install_headers(
+ configure_file(input: 'config.h.in', output: 'config.h',configuration: conf_data),
+ configure_file(input: 'version.h.in', output: 'version.h', configuration: version_data),
+ 'backend.h',
+ 'xcursor.h',
+ subdir: 'wlr'
+)
+if conf_data.get('WLR_HAS_XWAYLAND', false)
+ install_headers('xwayland.h', subdir: 'wlr')
+endif
+
+subdir('backend')
+subdir('interfaces')
+subdir('render')
+subdir('types')
+subdir('util')
diff --git a/include/wlr/render/dmabuf.h b/include/wlr/render/dmabuf.h
index 78f8c2eb..33c3a129 100644
--- a/include/wlr/render/dmabuf.h
+++ b/include/wlr/render/dmabuf.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_RENDER_DMABUF_H
#define WLR_RENDER_DMABUF_H
diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h
index 6b887f4f..c42b0325 100644
--- a/include/wlr/render/egl.h
+++ b/include/wlr/render/egl.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_RENDER_EGL_H
#define WLR_RENDER_EGL_H
diff --git a/include/wlr/render/gles2.h b/include/wlr/render/gles2.h
index 866c6658..fca11ab8 100644
--- a/include/wlr/render/gles2.h
+++ b/include/wlr/render/gles2.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_RENDER_GLES2_H
#define WLR_RENDER_GLES2_H
diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h
index f4565ad5..63f4265c 100644
--- a/include/wlr/render/interface.h
+++ b/include/wlr/render/interface.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_RENDER_INTERFACE_H
#define WLR_RENDER_INTERFACE_H
diff --git a/include/wlr/render/meson.build b/include/wlr/render/meson.build
new file mode 100644
index 00000000..05127bb7
--- /dev/null
+++ b/include/wlr/render/meson.build
@@ -0,0 +1,9 @@
+install_headers(
+ 'dmabuf.h',
+ 'egl.h',
+ 'gles2.h',
+ 'interface.h',
+ 'wlr_renderer.h',
+ 'wlr_texture.h',
+ subdir: 'wlr/render'
+)
diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h
index 0650bf1b..9c031b7f 100644
--- a/include/wlr/render/wlr_renderer.h
+++ b/include/wlr/render/wlr_renderer.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_RENDER_WLR_RENDERER_H
#define WLR_RENDER_WLR_RENDERER_H
diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h
index 9370fa25..dbfabfee 100644
--- a/include/wlr/render/wlr_texture.h
+++ b/include/wlr/render/wlr_texture.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_RENDER_WLR_TEXTURE_H
#define WLR_RENDER_WLR_TEXTURE_H
diff --git a/include/wlr/types/meson.build b/include/wlr/types/meson.build
new file mode 100644
index 00000000..8c81cb0e
--- /dev/null
+++ b/include/wlr/types/meson.build
@@ -0,0 +1,42 @@
+install_headers(
+ 'wlr_box.h',
+ 'wlr_buffer.h',
+ 'wlr_compositor.h',
+ 'wlr_cursor.h',
+ 'wlr_data_device.h',
+ 'wlr_export_dmabuf_v1.h',
+ 'wlr_gamma_control.h',
+ 'wlr_gamma_control_v1.h',
+ 'wlr_idle.h',
+ 'wlr_idle_inhibit_v1.h',
+ 'wlr_input_device.h',
+ 'wlr_input_inhibitor.h',
+ 'wlr_keyboard.h',
+ 'wlr_layer_shell.h',
+ 'wlr_linux_dmabuf_v1.h',
+ 'wlr_list.h',
+ 'wlr_matrix.h',
+ 'wlr_output.h',
+ 'wlr_output_damage.h',
+ 'wlr_output_layout.h',
+ 'wlr_pointer.h',
+ 'wlr_primary_selection.h',
+ 'wlr_region.h',
+ 'wlr_screencopy_v1.h',
+ 'wlr_screenshooter.h',
+ 'wlr_seat.h',
+ 'wlr_server_decoration.h',
+ 'wlr_surface.h',
+ 'wlr_tablet_pad.h',
+ 'wlr_tablet_tool.h',
+ 'wlr_tablet_v2.h',
+ 'wlr_touch.h',
+ 'wlr_virtual_keyboard_v1.h',
+ 'wlr_wl_shell.h',
+ 'wlr_xcursor_manager.h',
+ 'wlr_xdg_decoration_v1.h',
+ 'wlr_xdg_output.h',
+ 'wlr_xdg_shell.h',
+ 'wlr_xdg_shell_v6.h',
+ subdir: 'wlr/types',
+)
diff --git a/include/wlr/types/wlr_box.h b/include/wlr/types/wlr_box.h
index 0e586a18..11a53b56 100644
--- a/include/wlr/types/wlr_box.h
+++ b/include/wlr/types/wlr_box.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_BOX_H
#define WLR_TYPES_WLR_BOX_H
diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h
index eabc8b51..0c987b17 100644
--- a/include/wlr/types/wlr_buffer.h
+++ b/include/wlr/types/wlr_buffer.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_BUFFER_H
#define WLR_TYPES_WLR_BUFFER_H
diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h
index 0d79b0bb..1772e54b 100644
--- a/include/wlr/types/wlr_compositor.h
+++ b/include/wlr/types/wlr_compositor.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_COMPOSITOR_H
#define WLR_TYPES_WLR_COMPOSITOR_H
diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h
index 998c6f0d..ba582be9 100644
--- a/include/wlr/types/wlr_cursor.h
+++ b/include/wlr/types/wlr_cursor.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_CURSOR_H
#define WLR_TYPES_WLR_CURSOR_H
diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h
index 8b7b374c..c45e8d1c 100644
--- a/include/wlr/types/wlr_data_device.h
+++ b/include/wlr/types/wlr_data_device.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_DATA_DEVICE_H
#define WLR_TYPES_WLR_DATA_DEVICE_H
@@ -85,8 +93,6 @@ struct wlr_drag_icon {
bool is_pointer;
int32_t touch_id;
- int32_t sx, sy;
-
struct {
struct wl_signal map;
struct wl_signal unmap;
diff --git a/include/wlr/types/wlr_export_dmabuf_v1.h b/include/wlr/types/wlr_export_dmabuf_v1.h
index a094b3de..56767540 100644
--- a/include/wlr/types/wlr_export_dmabuf_v1.h
+++ b/include/wlr/types/wlr_export_dmabuf_v1.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_EXPORT_DMABUF_V1_H
#define WLR_TYPES_WLR_EXPORT_DMABUF_V1_H
diff --git a/include/wlr/types/wlr_gamma_control.h b/include/wlr/types/wlr_gamma_control.h
index f195c8ef..912a413c 100644
--- a/include/wlr/types/wlr_gamma_control.h
+++ b/include/wlr/types/wlr_gamma_control.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_GAMMA_CONTROL_H
#define WLR_TYPES_WLR_GAMMA_CONTROL_H
@@ -9,6 +17,10 @@ struct wlr_gamma_control_manager {
struct wl_listener display_destroy;
+ struct {
+ struct wl_signal destroy;
+ } events;
+
void *data;
};
diff --git a/include/wlr/types/wlr_gamma_control_v1.h b/include/wlr/types/wlr_gamma_control_v1.h
new file mode 100644
index 00000000..f186aa81
--- /dev/null
+++ b/include/wlr/types/wlr_gamma_control_v1.h
@@ -0,0 +1,35 @@
+#ifndef WLR_TYPES_WLR_GAMMA_CONTROL_V1_H
+#define WLR_TYPES_WLR_GAMMA_CONTROL_V1_H
+
+#include <wayland-server.h>
+
+struct wlr_gamma_control_manager_v1 {
+ struct wl_global *global;
+ struct wl_list resources;
+ struct wl_list controls; // wlr_gamma_control_v1::link
+
+ struct wl_listener display_destroy;
+
+ struct {
+ struct wl_signal destroy;
+ } events;
+
+ void *data;
+};
+
+struct wlr_gamma_control_v1 {
+ struct wl_resource *resource;
+ struct wlr_output *output;
+ struct wl_list link;
+
+ struct wl_listener output_destroy_listener;
+
+ void *data;
+};
+
+struct wlr_gamma_control_manager_v1 *wlr_gamma_control_manager_v1_create(
+ struct wl_display *display);
+void wlr_gamma_control_manager_v1_destroy(
+ struct wlr_gamma_control_manager_v1 *manager);
+
+#endif
diff --git a/include/wlr/types/wlr_idle.h b/include/wlr/types/wlr_idle.h
index 53fc6b98..d8c81a60 100644
--- a/include/wlr/types/wlr_idle.h
+++ b/include/wlr/types/wlr_idle.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_IDLE_H
#define WLR_TYPES_WLR_IDLE_H
@@ -22,6 +30,7 @@ struct wlr_idle {
struct wl_listener display_destroy;
struct {
struct wl_signal activity_notify;
+ struct wl_signal destroy;
} events;
void *data;
diff --git a/include/wlr/types/wlr_idle_inhibit_v1.h b/include/wlr/types/wlr_idle_inhibit_v1.h
index 011abbe5..2093eafe 100644
--- a/include/wlr/types/wlr_idle_inhibit_v1.h
+++ b/include/wlr/types/wlr_idle_inhibit_v1.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_IDLE_INHIBIT_V1_H
#define WLR_TYPES_WLR_IDLE_INHIBIT_V1_H
@@ -19,11 +27,12 @@ struct wlr_idle_inhibit_manager_v1 {
struct wl_list resources; // wl_resource_get_link
struct wl_list inhibitors; // wlr_idle_inhibit_inhibitor_v1::link
struct wl_global *global;
-
+
struct wl_listener display_destroy;
struct {
struct wl_signal new_inhibitor;
+ struct wl_signal destroy;
} events;
void *data;
diff --git a/include/wlr/types/wlr_input_device.h b/include/wlr/types/wlr_input_device.h
index cce15d90..ab0aecb6 100644
--- a/include/wlr/types/wlr_input_device.h
+++ b/include/wlr/types/wlr_input_device.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_INPUT_DEVICE_H
#define WLR_TYPES_WLR_INPUT_DEVICE_H
diff --git a/include/wlr/types/wlr_input_inhibitor.h b/include/wlr/types/wlr_input_inhibitor.h
index 2f333f3b..f3187540 100644
--- a/include/wlr/types/wlr_input_inhibitor.h
+++ b/include/wlr/types/wlr_input_inhibitor.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_INPUT_INHIBITOR_H
#define WLR_TYPES_INPUT_INHIBITOR_H
#include <wayland-server.h>
@@ -12,6 +20,7 @@ struct wlr_input_inhibit_manager {
struct {
struct wl_signal activate; // struct wlr_input_inhibit_manager *
struct wl_signal deactivate; // struct wlr_input_inhibit_manager *
+ struct wl_signal destroy;
} events;
void *data;
diff --git a/include/wlr/types/wlr_keyboard.h b/include/wlr/types/wlr_keyboard.h
index 67d4e5be..3e207523 100644
--- a/include/wlr/types/wlr_keyboard.h
+++ b/include/wlr/types/wlr_keyboard.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_KEYBOARD_H
#define WLR_TYPES_WLR_KEYBOARD_H
diff --git a/include/wlr/types/wlr_layer_shell.h b/include/wlr/types/wlr_layer_shell.h
index 2848a115..c7ddd180 100644
--- a/include/wlr/types/wlr_layer_shell.h
+++ b/include/wlr/types/wlr_layer_shell.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_LAYER_SHELL_H
#define WLR_TYPES_WLR_LAYER_SHELL_H
#include <stdbool.h>
@@ -31,6 +39,7 @@ struct wlr_layer_shell {
// Note: the output may be NULL. In this case, it is your
// responsibility to assign an output before returning.
struct wl_signal new_surface;
+ struct wl_signal destroy;
} events;
void *data;
diff --git a/include/wlr/types/wlr_linux_dmabuf.h b/include/wlr/types/wlr_linux_dmabuf_v1.h
index 4a03170c..f21b0b3a 100644
--- a/include/wlr/types/wlr_linux_dmabuf.h
+++ b/include/wlr/types/wlr_linux_dmabuf_v1.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_LINUX_DMABUF_H
#define WLR_TYPES_WLR_LINUX_DMABUF_H
@@ -5,7 +13,7 @@
#include <wayland-server-protocol.h>
#include <wlr/render/dmabuf.h>
-struct wlr_dmabuf_buffer {
+struct wlr_dmabuf_v1_buffer {
struct wlr_renderer *renderer;
struct wl_resource *buffer_resource;
struct wl_resource *params_resource;
@@ -17,24 +25,24 @@ struct wlr_dmabuf_buffer {
* Returns true if the given resource was created via the linux-dmabuf
* buffer protocol, false otherwise
*/
-bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource);
+bool wlr_dmabuf_v1_resource_is_buffer(struct wl_resource *buffer_resource);
/**
* Returns the wlr_dmabuf_buffer if the given resource was created
* via the linux-dmabuf buffer protocol
*/
-struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_buffer_resource(
+struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_from_buffer_resource(
struct wl_resource *buffer_resource);
/**
* Returns the wlr_dmabuf_buffer if the given resource was created
* via the linux-dmabuf params protocol
*/
-struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_params_resource(
+struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_from_params_resource(
struct wl_resource *params_resource);
/* the protocol interface */
-struct wlr_linux_dmabuf {
+struct wlr_linux_dmabuf_v1 {
struct wl_global *global;
struct wlr_renderer *renderer;
struct wl_list resources;
@@ -50,18 +58,18 @@ struct wlr_linux_dmabuf {
/**
* Create linux-dmabuf interface
*/
-struct wlr_linux_dmabuf *wlr_linux_dmabuf_create(struct wl_display *display,
+struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_create(struct wl_display *display,
struct wlr_renderer *renderer);
/**
* Destroy the linux-dmabuf interface
*/
-void wlr_linux_dmabuf_destroy(struct wlr_linux_dmabuf *linux_dmabuf);
+void wlr_linux_dmabuf_v1_destroy(struct wlr_linux_dmabuf_v1 *linux_dmabuf);
/**
* Returns the wlr_linux_dmabuf if the given resource was created
* via the linux_dmabuf protocol
*/
-struct wlr_linux_dmabuf *wlr_linux_dmabuf_from_resource(
+struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_from_resource(
struct wl_resource *resource);
#endif
diff --git a/include/wlr/types/wlr_list.h b/include/wlr/types/wlr_list.h
index 23bf53b7..60f388f9 100644
--- a/include/wlr/types/wlr_list.h
+++ b/include/wlr/types/wlr_list.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_LIST_H
#define WLR_TYPES_WLR_LIST_H
diff --git a/include/wlr/types/wlr_matrix.h b/include/wlr/types/wlr_matrix.h
index 02111db8..a3961c35 100644
--- a/include/wlr/types/wlr_matrix.h
+++ b/include/wlr/types/wlr_matrix.h
@@ -1,20 +1,57 @@
+/*
+ * This is a stable interface of wlroots. Future changes will be limited to:
+ *
+ * - New functions
+ * - New struct members
+ * - New enum members
+ *
+ * Note that wlroots does not make an ABI compatibility promise - in the future,
+ * the layout and size of structs used by wlroots may change, requiring code
+ * depending on this header to be recompiled (but not edited).
+ *
+ * Breaking changes are announced by email and follow a 1-year deprecation
+ * schedule. Send an email to ~sircmpwn/wlroots-announce+subscribe@lists.sr.ht
+ * to receive these announcements.
+ */
+
#ifndef WLR_TYPES_WLR_MATRIX_H
#define WLR_TYPES_WLR_MATRIX_H
#include <wayland-server.h>
#include <wlr/types/wlr_box.h>
+/** Writes the identity matrix into mat */
void wlr_matrix_identity(float mat[static 9]);
+
+/** mat ← a × b */
void wlr_matrix_multiply(float mat[static 9], const float a[static 9],
const float b[static 9]);
+
void wlr_matrix_transpose(float mat[static 9], const float a[static 9]);
+
+/** Writes a 2D translation matrix to mat of magnitude (x, y) */
void wlr_matrix_translate(float mat[static 9], float x, float y);
+
+/** Writes a 2D scale matrix to mat of magnitude (x, y) */
void wlr_matrix_scale(float mat[static 9], float x, float y);
+
+/** Writes a 2D rotation matrix to mat at an angle of rad radians */
void wlr_matrix_rotate(float mat[static 9], float rad);
+
+/** Writes a transformation matrix which applies the specified
+ * wl_output_transform to mat */
void wlr_matrix_transform(float mat[static 9],
enum wl_output_transform transform);
+
+/** Writes a 2D orthographic projection matrix to mat of (width, height) with a
+ * specified wl_output_transform*/
void wlr_matrix_projection(float mat[static 9], int width, int height,
enum wl_output_transform transform);
+
+/** Shortcut for the various matrix operations involved in projecting the
+ * specified wlr_box onto a given orthographic projection with a given
+ * rotation. The result is written to mat, which can be applied to each
+ * coordinate of the box to get a new coordinate from [-1,1]. */
void wlr_matrix_project_box(float mat[static 9], const struct wlr_box *box,
enum wl_output_transform transform, float rotation,
const float projection[static 9]);
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index 5084eb5a..3a9f3c41 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_OUTPUT_H
#define WLR_TYPES_WLR_OUTPUT_H
@@ -6,7 +14,7 @@
#include <time.h>
#include <wayland-server.h>
#include <wayland-util.h>
-#include <wlr/types/wlr_linux_dmabuf.h>
+#include <wlr/render/dmabuf.h>
struct wlr_output_mode {
uint32_t flags; // enum wl_output_mode
@@ -166,9 +174,19 @@ bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when,
* it is a no-op.
*/
void wlr_output_schedule_frame(struct wlr_output *output);
-void wlr_output_set_gamma(struct wlr_output *output,
- uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b);
+/**
+ * Returns the maximum length of each gamma ramp, or 0 if unsupported.
+ */
uint32_t wlr_output_get_gamma_size(struct wlr_output *output);
+/**
+ * Sets the gamma table for this output. `r`, `g` and `b` are gamma ramps for
+ * red, green and blue. `size` is the length of the ramps and must not exceed
+ * the value returned by `wlr_output_get_gamma_size`.
+ *
+ * Providing zero-sized ramps resets the gamma table.
+ */
+bool wlr_output_set_gamma(struct wlr_output *output,
+ uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b);
bool wlr_output_export_dmabuf(struct wlr_output *output,
struct wlr_dmabuf_attributes *attribs);
void wlr_output_set_fullscreen_surface(struct wlr_output *output,
diff --git a/include/wlr/types/wlr_output_damage.h b/include/wlr/types/wlr_output_damage.h
index a4333c1a..d614e6d6 100644
--- a/include/wlr/types/wlr_output_damage.h
+++ b/include/wlr/types/wlr_output_damage.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_OUTPUT_DAMAGE_H
#define WLR_TYPES_WLR_OUTPUT_DAMAGE_H
diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h
index 759c8ccf..cc9d2328 100644
--- a/include/wlr/types/wlr_output_layout.h
+++ b/include/wlr/types/wlr_output_layout.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_OUTPUT_LAYOUT_H
#define WLR_TYPES_WLR_OUTPUT_LAYOUT_H
@@ -118,5 +126,8 @@ enum wlr_direction {
struct wlr_output *wlr_output_layout_adjacent_output(
struct wlr_output_layout *layout, enum wlr_direction direction,
struct wlr_output *reference, double ref_lx, double ref_ly);
+struct wlr_output *wlr_output_layout_farthest_output(
+ struct wlr_output_layout *layout, enum wlr_direction direction,
+ struct wlr_output *reference, double ref_lx, double ref_ly);
#endif
diff --git a/include/wlr/types/wlr_pointer.h b/include/wlr/types/wlr_pointer.h
index 48c89151..7dc643ae 100644
--- a/include/wlr/types/wlr_pointer.h
+++ b/include/wlr/types/wlr_pointer.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_POINTER_H
#define WLR_TYPES_WLR_POINTER_H
diff --git a/include/wlr/types/wlr_primary_selection.h b/include/wlr/types/wlr_primary_selection.h
index 78f23ad6..f33f6368 100644
--- a/include/wlr/types/wlr_primary_selection.h
+++ b/include/wlr/types/wlr_primary_selection.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_PRIMARY_SELECTION_H
#define WLR_TYPES_WLR_PRIMARY_SELECTION_H
@@ -9,6 +17,10 @@ struct wlr_primary_selection_device_manager {
struct wl_listener display_destroy;
+ struct {
+ struct wl_signal destroy;
+ } events;
+
void *data;
};
diff --git a/include/wlr/types/wlr_region.h b/include/wlr/types/wlr_region.h
index be2f8b84..3c4a0532 100644
--- a/include/wlr/types/wlr_region.h
+++ b/include/wlr/types/wlr_region.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_REGION_H
#define WLR_TYPES_WLR_REGION_H
diff --git a/include/wlr/types/wlr_screencopy_v1.h b/include/wlr/types/wlr_screencopy_v1.h
index 892687aa..aba32a45 100644
--- a/include/wlr/types/wlr_screencopy_v1.h
+++ b/include/wlr/types/wlr_screencopy_v1.h
@@ -1,7 +1,16 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_SCREENCOPY_V1_H
#define WLR_TYPES_WLR_SCREENCOPY_V1_H
#include <wayland-server.h>
+#include <wlr/types/wlr_box.h>
struct wlr_screencopy_manager_v1 {
struct wl_global *global;
@@ -10,6 +19,10 @@ struct wlr_screencopy_manager_v1 {
struct wl_listener display_destroy;
+ struct {
+ struct wl_signal destroy;
+ } events;
+
void *data;
};
diff --git a/include/wlr/types/wlr_screenshooter.h b/include/wlr/types/wlr_screenshooter.h
index 916c8942..b7b87b39 100644
--- a/include/wlr/types/wlr_screenshooter.h
+++ b/include/wlr/types/wlr_screenshooter.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_SCREENSHOOTER_H
#define WLR_TYPES_WLR_SCREENSHOOTER_H
@@ -9,6 +17,10 @@ struct wlr_screenshooter {
struct wl_listener display_destroy;
+ struct {
+ struct wl_signal destroy;
+ } events;
+
void *data;
};
diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h
index 92d0a233..b3c02cf2 100644
--- a/include/wlr/types/wlr_seat.h
+++ b/include/wlr/types/wlr_seat.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_SEAT_H
#define WLR_TYPES_WLR_SEAT_H
diff --git a/include/wlr/types/wlr_server_decoration.h b/include/wlr/types/wlr_server_decoration.h
index 23387968..ff8d1369 100644
--- a/include/wlr/types/wlr_server_decoration.h
+++ b/include/wlr/types/wlr_server_decoration.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_SERVER_DECORATION_H
#define WLR_TYPES_WLR_SERVER_DECORATION_H
@@ -37,6 +45,7 @@ struct wlr_server_decoration_manager {
struct {
struct wl_signal new_decoration;
+ struct wl_signal destroy;
} events;
void *data;
diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h
index 0e3b5ff4..063f9e26 100644
--- a/include/wlr/types/wlr_surface.h
+++ b/include/wlr/types/wlr_surface.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_SURFACE_H
#define WLR_TYPES_WLR_SURFACE_H
@@ -39,6 +47,7 @@ struct wlr_surface_state {
struct wlr_surface_role {
const char *name;
void (*commit)(struct wlr_surface *surface);
+ void (*precommit)(struct wlr_surface *surface);
};
struct wlr_surface {
diff --git a/include/wlr/types/wlr_tablet_pad.h b/include/wlr/types/wlr_tablet_pad.h
index 23ac464d..d9bb284f 100644
--- a/include/wlr/types/wlr_tablet_pad.h
+++ b/include/wlr/types/wlr_tablet_pad.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_TABLET_PAD_H
#define WLR_TYPES_WLR_TABLET_PAD_H
diff --git a/include/wlr/types/wlr_tablet_tool.h b/include/wlr/types/wlr_tablet_tool.h
index bfa2e1f7..cb516ed9 100644
--- a/include/wlr/types/wlr_tablet_tool.h
+++ b/include/wlr/types/wlr_tablet_tool.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_TABLET_TOOL_H
#define WLR_TYPES_TABLET_TOOL_H
diff --git a/include/wlr/types/wlr_tablet_v2.h b/include/wlr/types/wlr_tablet_v2.h
index e2a39392..d6fd646d 100644
--- a/include/wlr/types/wlr_tablet_v2.h
+++ b/include/wlr/types/wlr_tablet_v2.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_TABLET_V2_H
#define WLR_TYPES_WLR_TABLET_V2_H
@@ -37,6 +45,10 @@ struct wlr_tablet_manager_v2 {
struct wl_listener display_destroy;
+ struct {
+ struct wl_signal destroy;
+ } events;
+
void *data;
};
diff --git a/include/wlr/types/wlr_touch.h b/include/wlr/types/wlr_touch.h
index 70070f84..99316ae0 100644
--- a/include/wlr/types/wlr_touch.h
+++ b/include/wlr/types/wlr_touch.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_TOUCH_H
#define WLR_TYPES_WLR_TOUCH_H
diff --git a/include/wlr/types/wlr_virtual_keyboard_v1.h b/include/wlr/types/wlr_virtual_keyboard_v1.h
index 1236ae24..e75ed8ec 100644
--- a/include/wlr/types/wlr_virtual_keyboard_v1.h
+++ b/include/wlr/types/wlr_virtual_keyboard_v1.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_VIRTUAL_KEYBOARD_V1_H
#define WLR_TYPES_WLR_VIRTUAL_KEYBOARD_V1_H
@@ -14,6 +22,7 @@ struct wlr_virtual_keyboard_manager_v1 {
struct {
struct wl_signal new_virtual_keyboard; // struct wlr_virtual_keyboard_v1*
+ struct wl_signal destroy;
} events;
};
diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h
index c4cc1999..dffbb4d7 100644
--- a/include/wlr/types/wlr_wl_shell.h
+++ b/include/wlr/types/wlr_wl_shell.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_WL_SHELL_H
#define WLR_TYPES_WLR_WL_SHELL_H
@@ -16,6 +24,7 @@ struct wlr_wl_shell {
struct {
struct wl_signal new_surface;
+ struct wl_signal destroy;
} events;
void *data;
diff --git a/include/wlr/types/wlr_xcursor_manager.h b/include/wlr/types/wlr_xcursor_manager.h
index c7fa83be..285006bf 100644
--- a/include/wlr/types/wlr_xcursor_manager.h
+++ b/include/wlr/types/wlr_xcursor_manager.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_XCURSOR_MANAGER_H
#define WLR_TYPES_WLR_XCURSOR_MANAGER_H
diff --git a/include/wlr/types/wlr_xdg_decoration_v1.h b/include/wlr/types/wlr_xdg_decoration_v1.h
new file mode 100644
index 00000000..ba1ad84b
--- /dev/null
+++ b/include/wlr/types/wlr_xdg_decoration_v1.h
@@ -0,0 +1,69 @@
+#ifndef WLR_TYPES_WLR_XDG_DECORATION_V1
+#define WLR_TYPES_WLR_XDG_DECORATION_V1
+
+#include <wayland-server.h>
+#include <wlr/types/wlr_xdg_shell.h>
+
+enum wlr_xdg_toplevel_decoration_v1_mode {
+ WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_NONE = 0,
+ WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE = 1,
+ WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE = 2,
+};
+
+struct wlr_xdg_decoration_manager_v1 {
+ struct wl_global *global;
+ struct wl_list resources;
+ struct wl_list decorations; // wlr_xdg_toplevel_decoration::link
+
+ struct wl_listener display_destroy;
+
+ struct {
+ struct wl_signal new_toplevel_decoration; // struct wlr_xdg_toplevel_decoration *
+ struct wl_signal destroy;
+ } events;
+
+ void *data;
+};
+
+struct wlr_xdg_toplevel_decoration_v1_configure {
+ struct wl_list link; // wlr_xdg_toplevel_decoration::configure_list
+ struct wlr_xdg_surface_configure *surface_configure;
+ enum wlr_xdg_toplevel_decoration_v1_mode mode;
+};
+
+struct wlr_xdg_toplevel_decoration_v1 {
+ struct wl_resource *resource;
+ struct wlr_xdg_surface *surface;
+ struct wlr_xdg_decoration_manager_v1 *manager;
+ struct wl_list link; // wlr_xdg_decoration_manager_v1::link
+
+ bool added;
+ enum wlr_xdg_toplevel_decoration_v1_mode current_mode;
+ enum wlr_xdg_toplevel_decoration_v1_mode client_pending_mode;
+ enum wlr_xdg_toplevel_decoration_v1_mode server_pending_mode;
+
+ struct wl_list configure_list; // wlr_xdg_toplevel_decoration_v1_configure::link
+
+ struct {
+ struct wl_signal destroy;
+ struct wl_signal request_mode;
+ } events;
+
+ struct wl_listener surface_destroy;
+ struct wl_listener surface_configure;
+ struct wl_listener surface_ack_configure;
+ struct wl_listener surface_commit;
+
+ void *data;
+};
+
+struct wlr_xdg_decoration_manager_v1 *
+ wlr_xdg_decoration_manager_v1_create(struct wl_display *display);
+void wlr_xdg_decoration_manager_v1_destroy(
+ struct wlr_xdg_decoration_manager_v1 *manager);
+
+uint32_t wlr_xdg_toplevel_decoration_v1_set_mode(
+ struct wlr_xdg_toplevel_decoration_v1 *decoration,
+ enum wlr_xdg_toplevel_decoration_v1_mode mode);
+
+#endif
diff --git a/include/wlr/types/wlr_xdg_output.h b/include/wlr/types/wlr_xdg_output.h
index 81566ab9..60611307 100644
--- a/include/wlr/types/wlr_xdg_output.h
+++ b/include/wlr/types/wlr_xdg_output.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_XDG_OUTPUT_H
#define WLR_TYPES_WLR_XDG_OUTPUT_H
#include <wayland-server.h>
@@ -26,6 +34,10 @@ struct wlr_xdg_output_manager {
struct wl_listener layout_add;
struct wl_listener layout_change;
struct wl_listener layout_destroy;
+
+ struct {
+ struct wl_signal destroy;
+ } events;
};
struct wlr_xdg_output_manager *wlr_xdg_output_manager_create(
diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h
index 9c0e6adc..1bca9ef3 100644
--- a/include/wlr/types/wlr_xdg_shell.h
+++ b/include/wlr/types/wlr_xdg_shell.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_XDG_SHELL_H
#define WLR_TYPES_WLR_XDG_SHELL_H
#include <wlr/types/wlr_box.h>
@@ -21,6 +29,7 @@ struct wlr_xdg_shell {
* surface will be ready to be managed on the `map` event.
*/
struct wl_signal new_surface;
+ struct wl_signal destroy;
} events;
void *data;
@@ -119,10 +128,13 @@ struct wlr_xdg_toplevel {
struct wl_signal request_resize;
struct wl_signal request_show_window_menu;
struct wl_signal set_parent;
+ struct wl_signal set_title;
+ struct wl_signal set_app_id;
} events;
};
struct wlr_xdg_surface_configure {
+ struct wlr_xdg_surface *surface;
struct wl_list link; // wlr_xdg_surface::configure_list
uint32_t serial;
@@ -186,6 +198,10 @@ struct wlr_xdg_surface {
* surface has been hidden or is about to be destroyed.
*/
struct wl_signal unmap;
+
+ // for protocol extensions
+ struct wl_signal configure; // wlr_xdg_surface_configure
+ struct wl_signal ack_configure; // wlr_xdg_surface_configure
} events;
void *data;
@@ -224,6 +240,8 @@ struct wlr_xdg_surface *wlr_xdg_surface_from_resource(
struct wl_resource *resource);
struct wlr_xdg_surface *wlr_xdg_surface_from_popup_resource(
struct wl_resource *resource);
+struct wlr_xdg_surface *wlr_xdg_surface_from_toplevel_resource(
+ struct wl_resource *resource);
struct wlr_box wlr_xdg_positioner_get_geometry(
struct wlr_xdg_positioner *positioner);
@@ -283,13 +301,6 @@ uint32_t wlr_xdg_toplevel_set_tiled(struct wlr_xdg_surface *surface,
void wlr_xdg_surface_send_close(struct wlr_xdg_surface *surface);
/**
- * Compute the popup position in its parent's surface-local coordinate system.
- * This aborts if called for popups whose parent is not an xdg_surface.
- */
-void wlr_xdg_surface_popup_get_position(struct wlr_xdg_surface *surface,
- double *popup_sx, double *popup_sy);
-
-/**
* Get the geometry for this positioner based on the anchor rect, gravity, and
* size of this positioner.
*/
@@ -350,7 +361,8 @@ struct wlr_xdg_surface *wlr_xdg_surface_from_wlr_surface(
*
* The x and y value can be <0
*/
-void wlr_xdg_surface_get_geometry(struct wlr_xdg_surface *surface, struct wlr_box *box);
+void wlr_xdg_surface_get_geometry(struct wlr_xdg_surface *surface,
+ struct wlr_box *box);
/**
* Call `iterator` on each surface and popup in the xdg-surface tree, with the
@@ -358,7 +370,13 @@ void wlr_xdg_surface_get_geometry(struct wlr_xdg_surface *surface, struct wlr_bo
* from root to leaves (in rendering order).
*/
void wlr_xdg_surface_for_each_surface(struct wlr_xdg_surface *surface,
- wlr_surface_iterator_func_t iterator, void *user_data);
+ wlr_surface_iterator_func_t iterator, void *user_data);
+
+/**
+ * Schedule a surface configuration. This should only be called by protocols
+ * extending the shell.
+ */
+uint32_t wlr_xdg_surface_schedule_configure(struct wlr_xdg_surface *surface);
/**
* Call `iterator` on each popup in the xdg-surface tree, with the popup's
diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h
index 2e1b6f11..a69e488f 100644
--- a/include/wlr/types/wlr_xdg_shell_v6.h
+++ b/include/wlr/types/wlr_xdg_shell_v6.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_TYPES_WLR_XDG_SHELL_V6_H
#define WLR_TYPES_WLR_XDG_SHELL_V6_H
@@ -22,6 +30,7 @@ struct wlr_xdg_shell_v6 {
* surface will be ready to be managed on the `map` event.
*/
struct wl_signal new_surface;
+ struct wl_signal destroy;
} events;
void *data;
@@ -127,6 +136,8 @@ struct wlr_xdg_toplevel_v6 {
struct wl_signal request_resize;
struct wl_signal request_show_window_menu;
struct wl_signal set_parent;
+ struct wl_signal set_title;
+ struct wl_signal set_app_id;
} events;
};
diff --git a/include/wlr/util/edges.h b/include/wlr/util/edges.h
index 53268323..bf1eb1e7 100644
--- a/include/wlr/util/edges.h
+++ b/include/wlr/util/edges.h
@@ -1,3 +1,19 @@
+/*
+ * This is a stable interface of wlroots. Future changes will be limited to:
+ *
+ * - New functions
+ * - New struct members
+ * - New enum members
+ *
+ * Note that wlroots does not make an ABI compatibility promise - in the future,
+ * the layout and size of structs used by wlroots may change, requiring code
+ * depending on this header to be recompiled (but not edited).
+ *
+ * Breaking changes are announced by email and follow a 1-year deprecation
+ * schedule. Send an email to ~sircmpwn/wlroots-announce+subscribe@lists.sr.ht
+ * to receive these announcements.
+ */
+
#ifndef WLR_UTIL_EDGES_H
#define WLR_UTIL_EDGES_H
diff --git a/include/wlr/util/log.h b/include/wlr/util/log.h
index 098a020d..2c441180 100644
--- a/include/wlr/util/log.h
+++ b/include/wlr/util/log.h
@@ -1,3 +1,19 @@
+/*
+ * This is a stable interface of wlroots. Future changes will be limited to:
+ *
+ * - New functions
+ * - New struct members
+ * - New enum members
+ *
+ * Note that wlroots does not make an ABI compatibility promise - in the future,
+ * the layout and size of structs used by wlroots may change, requiring code
+ * depending on this header to be recompiled (but not edited).
+ *
+ * Breaking changes are announced by email and follow a 1-year deprecation
+ * schedule. Send an email to ~sircmpwn/wlroots-announce+subscribe@lists.sr.ht
+ * to receive these announcements.
+ */
+
#ifndef WLR_UTIL_LOG_H
#define WLR_UTIL_LOG_H
@@ -19,8 +35,13 @@ typedef void (*wlr_log_func_t)(enum wlr_log_importance importance,
// Will log all messages less than or equal to `verbosity`
// If `callback` is NULL, wlr will use its default logger.
+// The function can be called multiple times to update the verbosity or
+// callback function.
void wlr_log_init(enum wlr_log_importance verbosity, wlr_log_func_t callback);
+// Returns the log verbosity provided to wlr_log_init
+enum wlr_log_importance wlr_log_get_verbosity(void);
+
#ifdef __GNUC__
#define _WLR_ATTRIB_PRINTF(start, end) __attribute__((format(printf, start, end)))
#else
diff --git a/include/wlr/util/meson.build b/include/wlr/util/meson.build
new file mode 100644
index 00000000..ee72cbd6
--- /dev/null
+++ b/include/wlr/util/meson.build
@@ -0,0 +1,6 @@
+install_headers(
+ 'edges.h',
+ 'log.h',
+ 'region.h',
+ subdir: 'wlr/util',
+)
diff --git a/include/wlr/util/region.h b/include/wlr/util/region.h
index c0fe6063..32387bfb 100644
--- a/include/wlr/util/region.h
+++ b/include/wlr/util/region.h
@@ -1,6 +1,21 @@
+/*
+ * This is a stable interface of wlroots. Future changes will be limited to:
+ *
+ * - New functions
+ * - New struct members
+ * - New enum members
+ *
+ * Note that wlroots does not make an ABI compatibility promise - in the future,
+ * the layout and size of structs used by wlroots may change, requiring code
+ * depending on this header to be recompiled (but not edited).
+ *
+ * Breaking changes are announced by email and follow a 1-year deprecation
+ * schedule. Send an email to ~sircmpwn/wlroots-announce+subscribe@lists.sr.ht
+ * to receive these announcements.
+ */
+
#ifndef WLR_UTIL_REGION_H
#define WLR_UTIL_REGION_H
-
#include <pixman.h>
#include <wayland-server.h>
diff --git a/include/wlr/version.h.in b/include/wlr/version.h.in
new file mode 100644
index 00000000..cdc0fd75
--- /dev/null
+++ b/include/wlr/version.h.in
@@ -0,0 +1,16 @@
+#ifndef WLR_VERSION_H
+#define WLR_VERSION_H
+
+#mesondefine WLR_VERSION_STR
+
+#mesondefine WLR_VERSION_MAJOR
+#mesondefine WLR_VERSION_MINOR
+#mesondefine WLR_VERSION_MICRO
+
+#define WLR_VERSION_NUM ((WLR_VERSION_MAJOR << 16) | (WLR_VERSION_MINOR << 8) | WLR_VERSION_MICRO)
+
+#mesondefine WLR_VERSION_API_CURRENT
+#mesondefine WLR_VERSION_API_REVISION
+#mesondefine WLR_VERSION_API_AGE
+
+#endif
diff --git a/include/wlr/xcursor.h b/include/wlr/xcursor.h
index d97469f8..39874f39 100644
--- a/include/wlr/xcursor.h
+++ b/include/wlr/xcursor.h
@@ -24,8 +24,19 @@
*/
/*
- * This is adapted from wayland-cursor, but with the wl_shm client stuff removed
- * so we can use it on the compositor, too.
+ * This is a stable interface of wlroots. Future changes will be limited to:
+ *
+ * - New functions
+ * - New struct members
+ * - New enum members
+ *
+ * Note that wlroots does not make an ABI compatibility promise - in the future,
+ * the layout and size of structs used by wlroots may change, requiring code
+ * depending on this header to be recompiled (but not edited).
+ *
+ * Breaking changes are announced by email and follow a 1-year deprecation
+ * schedule. Send an email to ~sircmpwn/wlroots-announce+subscribe@lists.sr.ht
+ * to receive these announcements.
*/
#ifndef WLR_XCURSOR_H
diff --git a/include/wlr/xwayland.h b/include/wlr/xwayland.h
index 7471bbc6..eb5d6985 100644
--- a/include/wlr/xwayland.h
+++ b/include/wlr/xwayland.h
@@ -1,3 +1,11 @@
+/*
+ * This an unstable interface of wlroots. No guarantees are made regarding the
+ * future consistency of this API.
+ */
+#ifndef WLR_USE_UNSTABLE
+#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
+#endif
+
#ifndef WLR_XWAYLAND_H
#define WLR_XWAYLAND_H
@@ -108,6 +116,7 @@ struct wlr_xwayland_surface {
char *title;
char *class;
char *instance;
+ char *role;
pid_t pid;
bool has_utf8_title;
@@ -130,6 +139,7 @@ struct wlr_xwayland_surface {
struct wl_event_source *ping_timer;
// _NET_WM_STATE
+ bool modal;
bool fullscreen;
bool maximized_vert, maximized_horz;
@@ -142,14 +152,18 @@ struct wlr_xwayland_surface {
struct wl_signal request_resize;
struct wl_signal request_maximize;
struct wl_signal request_fullscreen;
+ struct wl_signal request_activate;
struct wl_signal map;
struct wl_signal unmap;
struct wl_signal set_title;
struct wl_signal set_class;
+ struct wl_signal set_role;
struct wl_signal set_parent;
struct wl_signal set_pid;
struct wl_signal set_window_type;
+ struct wl_signal set_hints;
+ struct wl_signal set_override_redirect;
struct wl_signal ping_timeout;
} events;
@@ -174,6 +188,14 @@ struct wlr_xwayland_resize_event {
uint32_t edges;
};
+/** Create an Xwayland server.
+ *
+ * The server supports a lazy mode in which Xwayland is only started when a
+ * client tries to connect.
+ *
+ * Note: wlr_xwayland will setup a global SIGUSR1 handler on the compositor
+ * process.
+ */
struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display,
struct wlr_compositor *compositor, bool lazy);
@@ -200,9 +222,6 @@ void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland_surface *surface,
void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland,
struct wlr_seat *seat);
-bool wlr_xwayland_surface_is_unmanaged(
- const struct wlr_xwayland_surface *surface);
-
bool wlr_surface_is_xwayland_surface(struct wlr_surface *surface);
struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface(
@@ -210,4 +229,29 @@ struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface(
void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface);
+/** Metric to guess if an OR window should "receive" focus
+ *
+ * In the pure X setups, window managers usually straight up ignore override
+ * redirect windows, and never touch them. (we have to handle them for mapping)
+ *
+ * When such a window wants to receive keyboard input (e.g. rofi/dzen) it will
+ * use mechanics we don't support (sniffing/grabbing input).
+ * [Sadly this is unrelated to xwayland-keyboard-grab]
+ *
+ * To still support these windows, while keeping general OR semantics as is, we
+ * need to hand a subset of windows focus.
+ * The dirty truth is, we need to hand focus to any Xwayland window, though
+ * pretending this window has focus makes it easier to handle unmap.
+ *
+ * This function provides a handy metric based on the window type to guess if
+ * the OR window wants focus.
+ * It's probably not perfect, nor exactly intended but works in practice.
+ *
+ * Returns: true if the window should receive focus
+ * false if it should be ignored
+ */
+bool wlr_xwayland_or_surface_wants_focus(
+ const struct wlr_xwayland_surface *surface);
+
+
#endif
diff --git a/include/xwayland/xwm.h b/include/xwayland/xwm.h
index 08d37736..3536bbc8 100644
--- a/include/xwayland/xwm.h
+++ b/include/xwayland/xwm.h
@@ -25,6 +25,7 @@ enum atom_name {
WM_HINTS,
WM_NORMAL_HINTS,
WM_SIZE_HINTS,
+ WM_WINDOW_ROLE,
MOTIF_WM_HINTS,
UTF8_STRING,
WM_S0,
@@ -40,6 +41,7 @@ enum atom_name {
_NET_WM_MOVERESIZE,
_NET_WM_NAME,
_NET_SUPPORTING_WM_CHECK,
+ _NET_WM_STATE_MODAL,
_NET_WM_STATE_FULLSCREEN,
_NET_WM_STATE_MAXIMIZED_VERT,
_NET_WM_STATE_MAXIMIZED_HORZ,
diff --git a/meson.build b/meson.build
index b65cd51a..ff4e5e5f 100644
--- a/meson.build
+++ b/meson.build
@@ -3,7 +3,7 @@ project(
'c',
version: '0.0.1',
license: 'MIT',
- meson_version: '>=0.44.0',
+ meson_version: '>=0.47.1',
default_options: [
'c_std=c11',
'warning_level=2',
@@ -18,21 +18,17 @@ so_version = ['0', '0', '0']
add_project_arguments('-Wno-unused-parameter', language: 'c')
add_project_arguments(
- '-DWLR_SRC_DIR="@0@"'.format(meson.source_root()),
+ '-DWLR_SRC_DIR="@0@"'.format(meson.current_source_dir()),
language: 'c',
)
add_project_arguments(
- '-I@0@'.format(meson.build_root()),
- language: 'c',
-)
-add_project_link_arguments(
- '-Wl,-rpath,@0@'.format(meson.build_root()),
+ '-DWLR_USE_UNSTABLE',
language: 'c',
)
conf_data = configuration_data()
-wlr_inc = include_directories('include')
+wlr_inc = include_directories('.', 'include')
cc = meson.get_compiler('c')
@@ -49,7 +45,7 @@ add_project_arguments('-DWL_HIDE_DEPRECATED', language: 'c')
wayland_server = dependency('wayland-server', version: '>=1.15')
wayland_client = dependency('wayland-client')
wayland_egl = dependency('wayland-egl')
-wayland_protos = dependency('wayland-protocols', version: '>=1.14')
+wayland_protos = dependency('wayland-protocols', version: '>=1.15')
egl = dependency('egl')
glesv2 = dependency('glesv2')
drm = dependency('libdrm')
@@ -58,86 +54,37 @@ libinput = dependency('libinput', version: '>=1.7.0')
xkbcommon = dependency('xkbcommon')
udev = dependency('libudev')
pixman = dependency('pixman-1')
-libcap = dependency('libcap', required: get_option('enable-libcap') == 'true')
-systemd = dependency('libsystemd', required: get_option('enable-systemd') == 'true')
-elogind = dependency('libelogind', required: get_option('enable-elogind') == 'true')
+libcap = dependency('libcap', required: get_option('libcap'))
+logind = dependency('lib' + get_option('logind-provider'), required: get_option('logind'))
math = cc.find_library('m', required: false)
-exclude_headers = []
wlr_parts = []
wlr_deps = []
-if libcap.found() and get_option('enable-libcap') != 'false'
+if libcap.found()
conf_data.set('WLR_HAS_LIBCAP', true)
wlr_deps += libcap
endif
-if systemd.found() and get_option('enable-systemd') != 'false'
- conf_data.set('WLR_HAS_SYSTEMD', true)
- wlr_deps += systemd
-endif
-
-if elogind.found() and get_option('enable-elogind') != 'false'
- conf_data.set('WLR_HAS_ELOGIND', true)
-endif
-
-if get_option('enable-x11_backend') or get_option('enable-xwayland')
- xcb = dependency('xcb')
- xcb_composite = dependency('xcb-composite')
- xcb_xfixes = dependency('xcb-xfixes')
- xcb_image = dependency('xcb-image')
- xcb_render = dependency('xcb-render')
- x11_xcb = dependency('x11-xcb')
-
- xcb_icccm = dependency('xcb-icccm', required: false)
- xcb_xkb = dependency('xcb-xkb', required: false)
- xcb_errors = dependency('xcb-errors', required: get_option('enable-xcb_errors') == 'true')
-
- if xcb_icccm.found()
- conf_data.set('WLR_HAS_XCB_ICCCM', true)
- endif
-
- if xcb_xkb.found()
- conf_data.set('WLR_HAS_XCB_XKB', true)
- endif
-
- if xcb_errors.found() and get_option('enable-xcb_errors') != 'false'
- conf_data.set('WLR_HAS_XCB_ERRORS', true)
- endif
-
- wlr_deps += [
- xcb,
- xcb_composite,
- x11_xcb,
- ]
-else
- add_project_arguments('-DMESA_EGL_NO_X11_HEADERS', language: 'c')
+if logind.found()
+ conf_data.set('WLR_HAS_' + get_option('logind-provider').to_upper(), true)
+ wlr_deps += logind
endif
-if get_option('enable-x11_backend')
- conf_data.set('WLR_HAS_X11_BACKEND', true)
+if cc.has_header_symbol('fcntl.h', 'posix_fallocate', prefix: '#define _POSIX_C_SOURCE 200112L')
+ conf_data.set('WLR_HAS_POSIX_FALLOCATE', true)
endif
-if get_option('enable-xwayland')
- subdir('xwayland')
- wlr_parts += [lib_wlr_xwayland]
- conf_data.set('WLR_HAS_XWAYLAND', true)
-else
- exclude_headers += 'xwayland.h'
-endif
-
-includedir = get_option('includedir')
-exclude_headers += 'meson.build'
-install_subdir('include/wlr', install_dir: includedir, exclude_files: exclude_headers)
-
-
-subdir('include')
subdir('protocol')
subdir('render')
+
subdir('backend')
subdir('types')
subdir('util')
subdir('xcursor')
+subdir('xwayland')
+
+subdir('include')
wlr_parts += [
lib_wl_protos,
@@ -174,6 +121,7 @@ lib_wlr = library(
include_directories: wlr_inc,
install: true,
link_args : symbols_flag,
+ link_depends: symbols_file,
)
wlroots = declare_dependency(
@@ -182,7 +130,6 @@ wlroots = declare_dependency(
include_directories: wlr_inc,
)
-
summary = [
'',
'----------------',
@@ -200,14 +147,8 @@ summary = [
]
message('\n'.join(summary))
-
-if get_option('enable-rootston')
- subdir('rootston')
-endif
-
-if get_option('enable-examples')
- subdir('examples')
-endif
+subdir('examples')
+subdir('rootston')
pkgconfig = import('pkgconfig')
pkgconfig.generate(
@@ -222,26 +163,31 @@ git = find_program('git', required: false)
if git.found()
all_files = run_command(
git,
- ['--git-dir=@0@/.git'.format(meson.current_source_dir()),
- 'ls-files',
- ':/*.[ch]'])
+ '--git-dir=@0@/.git'.format(meson.current_source_dir()),
+ 'ls-files',
+ ':/*.[ch]',
+ )
all_files = files(all_files.stdout().split())
etags = find_program('etags', required: false)
if etags.found() and all_files.length() > 0
- custom_target('etags',
+ custom_target(
+ 'etags',
build_by_default: true,
input: all_files,
output: 'TAGS',
- command: [etags.path(), '-o', 'TAGS'] + all_files)
+ command: [etags, '-o', '@OUTPUT@', '@INPUT@'],
+ )
endif
ctags = find_program('ctags', required: false)
if ctags.found() and all_files.length() > 0
- custom_target('ctags',
+ custom_target(
+ 'ctags',
build_by_default: true,
input: all_files,
output: 'tags',
- command: [ctags.path(), '-o', 'tags'] + all_files)
+ command: [ctags, '-f', '@OUTPUT@', '@INPUT@'],
+ )
endif
endif
diff --git a/meson_options.txt b/meson_options.txt
index e474b8aa..360c6f6a 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,8 +1,10 @@
-option('enable-libcap', type: 'combo', choices: ['auto', 'true', 'false'], value: 'auto', description: 'Enable support for capabilities')
-option('enable-systemd', type: 'combo', choices: ['auto', 'true', 'false'], value: 'auto', description: 'Enable support for logind')
-option('enable-elogind', type: 'combo', choices: ['auto', 'true', 'false'], value: 'auto', description: 'Enable support for logind')
-option('enable-xcb_errors', type: 'combo', choices: ['auto', 'true', 'false'], value: 'auto', description: 'Use xcb-errors util library')
-option('enable-xwayland', type: 'boolean', value: true, description: 'Enable support X11 applications')
-option('enable-x11_backend', type: 'boolean', value: true, description: 'Enable X11 backend')
-option('enable-rootston', type: 'boolean', value: true, description: 'Build the rootston example compositor')
-option('enable-examples', type: 'boolean', value: true, description: 'Build example applications')
+option('libcap', type: 'feature', value: 'auto', description: 'Enable support for rootless session via capabilities (cap_sys_admin)')
+option('logind', type: 'feature', value: 'auto', description: 'Enable support for rootless session via logind')
+option('logind-provider', type: 'combo', choices: ['systemd', 'elogind'], value: 'systemd', description: 'Provider of logind support library')
+option('xcb-errors', type: 'feature', value: 'auto', description: 'Use xcb-errors util library')
+option('xcb-icccm', type: 'feature', value: 'auto', description: 'Use xcb-icccm util library')
+option('xcb-xkb', type: 'feature', value: 'auto', description: 'Use xcb-xkb util library')
+option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
+option('x11-backend', type: 'feature', value: 'auto', description: 'Enable X11 backend')
+option('rootston', type: 'boolean', value: true, description: 'Build the rootston example compositor')
+option('examples', type: 'boolean', value: true, description: 'Build example applications')
diff --git a/protocol/meson.build b/protocol/meson.build
index b7a6e80a..2d2a73ed 100644
--- a/protocol/meson.build
+++ b/protocol/meson.build
@@ -1,39 +1,23 @@
wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir')
-wayland_scanner = find_program('wayland-scanner')
-
-wayland_scanner_server = generator(
- wayland_scanner,
- output: '@BASENAME@-protocol.h',
- arguments: ['server-header', '@INPUT@', '@OUTPUT@'],
-)
-
-# should check wayland_scanner's version, but it is hard to get
-if wayland_server.version().version_compare('>=1.14.91')
- code_type = 'private-code'
+wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true)
+if wayland_scanner_dep.found()
+ wayland_scanner = find_program(
+ wayland_scanner_dep.get_pkgconfig_variable('wayland_scanner'),
+ native: true,
+ )
else
- code_type = 'code'
+ wayland_scanner = find_program('wayland-scanner', native: true)
endif
-wayland_scanner_code = generator(
- wayland_scanner,
- output: '@BASENAME@-protocol.c',
- arguments: [code_type, '@INPUT@', '@OUTPUT@'],
-)
-
-wayland_scanner_client = generator(
- wayland_scanner,
- output: '@BASENAME@-client-protocol.h',
- arguments: ['client-header', '@INPUT@', '@OUTPUT@'],
-)
-
protocols = [
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
- [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'],
- [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/tablet/tablet-unstable-v2.xml'],
+ [wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
+ [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
+ [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'],
'gamma-control.xml',
'gtk-primary-selection.xml',
'idle.xml',
@@ -41,18 +25,21 @@ protocols = [
'server-decoration.xml',
'virtual-keyboard-unstable-v1.xml',
'wlr-export-dmabuf-unstable-v1.xml',
+ 'wlr-gamma-control-unstable-v1.xml',
'wlr-input-inhibitor-unstable-v1.xml',
'wlr-layer-shell-unstable-v1.xml',
'wlr-screencopy-unstable-v1.xml',
]
client_protocols = [
- [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'],
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
+ [wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
+ [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'],
'idle.xml',
'screenshooter.xml',
'wlr-export-dmabuf-unstable-v1.xml',
+ 'wlr-gamma-control-unstable-v1.xml',
'wlr-input-inhibitor-unstable-v1.xml',
'wlr-layer-shell-unstable-v1.xml',
'wlr-screencopy-unstable-v1.xml',
@@ -63,17 +50,35 @@ wl_protos_headers = []
foreach p : protocols
xml = join_paths(p)
- wl_protos_src += wayland_scanner_code.process(xml)
- wl_protos_headers += wayland_scanner_server.process(xml)
+ wl_protos_src += custom_target(
+ xml.underscorify() + '_server_c',
+ input: xml,
+ output: '@BASENAME@-protocol.c',
+ command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'],
+ )
+ wl_protos_headers += custom_target(
+ xml.underscorify() + '_server_h',
+ input: xml,
+ output: '@BASENAME@-protocol.h',
+ command: [wayland_scanner, 'server-header', '@INPUT@', '@OUTPUT@'],
+ )
endforeach
foreach p : client_protocols
xml = join_paths(p)
- wl_protos_headers += wayland_scanner_client.process(xml)
+ wl_protos_headers += custom_target(
+ xml.underscorify() + '_client_h',
+ input: xml,
+ output: '@BASENAME@-client-protocol.h',
+ command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'],
+ )
endforeach
-lib_wl_protos = static_library('wl_protos', wl_protos_src + wl_protos_headers,
- dependencies: [wayland_client]) # for the include directory
+lib_wl_protos = static_library(
+ 'wl_protos',
+ wl_protos_src + wl_protos_headers,
+ dependencies: wayland_client.partial_dependency(includes: true),
+)
wlr_protos = declare_dependency(
link_with: lib_wl_protos,
diff --git a/protocol/wlr-gamma-control-unstable-v1.xml b/protocol/wlr-gamma-control-unstable-v1.xml
new file mode 100644
index 00000000..f55f3fe5
--- /dev/null
+++ b/protocol/wlr-gamma-control-unstable-v1.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="wlr_gamma_control_unstable_v1">
+ <copyright>
+ Copyright © 2015 Giulio camuffo
+ Copyright © 2018 Simon Ser
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of
+ the copyright holders not be used in advertising or publicity
+ pertaining to distribution of the software without specific,
+ written prior permission. The copyright holders make no
+ representations about the suitability of this software for any
+ purpose. It is provided "as is" without express or implied
+ warranty.
+
+ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+ THIS SOFTWARE.
+ </copyright>
+
+ <description summary="manage gamma tables of outputs">
+ This protocol allows a privileged client to set the gamma tables for
+ outputs.
+
+ Warning! The protocol described in this file is experimental and
+ backward incompatible changes may be made. Backward compatible changes
+ may be added together with the corresponding interface version bump.
+ Backward incompatible changes are done by bumping the version number in
+ the protocol and interface names and resetting the interface version.
+ Once the protocol is to be declared stable, the 'z' prefix and the
+ version number in the protocol and interface names are removed and the
+ interface version number is reset.
+ </description>
+
+ <interface name="zwlr_gamma_control_manager_v1" version="1">
+ <description summary="manager to create per-output gamma controls">
+ This interface is a manager that allows creating per-output gamma
+ controls.
+ </description>
+
+ <request name="get_gamma_control">
+ <description summary="get a gamma control for an output">
+ Create a gamma control that can be used to adjust gamma tables for the
+ provided output.
+ </description>
+ <arg name="id" type="new_id" interface="zwlr_gamma_control_v1"/>
+ <arg name="output" type="object" interface="wl_output"/>
+ </request>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the manager">
+ All objects created by the manager will still remain valid, until their
+ appropriate destroy request has been called.
+ </description>
+ </request>
+ </interface>
+
+ <interface name="zwlr_gamma_control_v1" version="1">
+ <description summary="adjust gamma tables for an output">
+ This interface allows a client to adjust gamma tables for a particular
+ output.
+
+ The client will receive the gamma size, and will then be able to set gamma
+ tables. At any time the compositor can send a failed event indicating that
+ this object is no longer valid.
+
+ There must always be at most one gamma control object per output, which
+ has exclusive access to this particular output. When the gamma control
+ object is destroyed, the gamma table is restored to its original value.
+ </description>
+
+ <event name="gamma_size">
+ <description summary="size of gamma ramps">
+ Advertise the size of each gamma ramp.
+
+ This event is sent immediately when the gamma control object is created.
+ </description>
+ <arg name="size" type="uint" summary="number of elements in a ramp"/>
+ </event>
+
+ <enum name="error">
+ <entry name="invalid_gamma" value="1" summary="invalid gamma tables"/>
+ </enum>
+
+ <request name="set_gamma">
+ <description summary="set the gamma table">
+ Set the gamma table. The file descriptor can be memory-mapped to provide
+ the raw gamma table, which contains successive gamma ramps for the red,
+ green and blue channels. Each gamma ramp is an array of 16-byte unsigned
+ integers which has the same length as the gamma size.
+
+ The file descriptor data must have the same length as three times the
+ gamma size.
+ </description>
+ <arg name="fd" type="fd" summary="gamma table file descriptor"/>
+ </request>
+
+ <event name="failed">
+ <description summary="object no longer valid">
+ This event indicates that the gamma control is no longer valid. This
+ can happen for a number of reasons, including:
+ - The output doesn't support gamma tables
+ - Setting the gamma tables failed
+ - Another client already has exclusive gamma control for this output
+ - The compositor has transfered gamma control to another client
+
+ Upon receiving this event, the client should destroy this object.
+ </description>
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy this control">
+ Destroys the gamma control object. If the object is still valid, this
+ restores the original gamma tables.
+ </description>
+ </request>
+ </interface>
+</protocol>
diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c
index 27c16e52..b6e97041 100644
--- a/render/gles2/renderer.c
+++ b/render/gles2/renderer.c
@@ -116,7 +116,7 @@ static bool gles2_render_texture_with_matrix(struct wlr_renderer *wlr_renderer,
struct wlr_gles2_renderer *renderer =
gles2_get_renderer_in_context(wlr_renderer);
struct wlr_gles2_texture *texture =
- get_gles2_texture_in_context(wlr_texture);
+ gles2_get_texture(wlr_texture);
struct wlr_gles2_tex_shader *shader = NULL;
GLenum target = 0;
@@ -213,7 +213,7 @@ static const enum wl_shm_format *gles2_renderer_formats(
static bool gles2_resource_is_wl_drm_buffer(struct wlr_renderer *wlr_renderer,
struct wl_resource *resource) {
struct wlr_gles2_renderer *renderer =
- gles2_get_renderer_in_context(wlr_renderer);
+ gles2_get_renderer(wlr_renderer);
if (!eglQueryWaylandBufferWL) {
return false;
@@ -227,7 +227,7 @@ static bool gles2_resource_is_wl_drm_buffer(struct wlr_renderer *wlr_renderer,
static void gles2_wl_drm_buffer_get_size(struct wlr_renderer *wlr_renderer,
struct wl_resource *buffer, int *width, int *height) {
struct wlr_gles2_renderer *renderer =
- gles2_get_renderer_in_context(wlr_renderer);
+ gles2_get_renderer(wlr_renderer);
if (!eglQueryWaylandBufferWL) {
return;
@@ -323,7 +323,7 @@ static struct wlr_texture *gles2_texture_from_dmabuf(
static void gles2_init_wl_display(struct wlr_renderer *wlr_renderer,
struct wl_display *wl_display) {
struct wlr_gles2_renderer *renderer =
- gles2_get_renderer_in_context(wlr_renderer);
+ gles2_get_renderer(wlr_renderer);
if (!wlr_egl_bind_display(renderer->egl, wl_display)) {
wlr_log(WLR_INFO, "failed to bind wl_display to EGL");
}
diff --git a/render/gles2/texture.c b/render/gles2/texture.c
index 1e55f4c4..22d02cde 100644
--- a/render/gles2/texture.c
+++ b/render/gles2/texture.c
@@ -16,7 +16,7 @@
static const struct wlr_texture_impl texture_impl;
-static struct wlr_gles2_texture *gles2_get_texture(
+struct wlr_gles2_texture *gles2_get_texture(
struct wlr_texture *wlr_texture) {
assert(wlr_texture->impl == &texture_impl);
return (struct wlr_gles2_texture *)wlr_texture;
@@ -25,7 +25,9 @@ static struct wlr_gles2_texture *gles2_get_texture(
struct wlr_gles2_texture *get_gles2_texture_in_context(
struct wlr_texture *wlr_texture) {
struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
- assert(wlr_egl_is_current(texture->egl));
+ if (!wlr_egl_is_current(texture->egl)) {
+ wlr_egl_make_current(texture->egl, EGL_NO_SURFACE, NULL);
+ }
return texture;
}
@@ -143,7 +145,9 @@ static const struct wlr_texture_impl texture_impl = {
struct wlr_texture *wlr_gles2_texture_from_pixels(struct wlr_egl *egl,
enum wl_shm_format wl_fmt, uint32_t stride, uint32_t width,
uint32_t height, const void *data) {
- assert(wlr_egl_is_current(egl));
+ if (!wlr_egl_is_current(egl)) {
+ wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL);
+ }
const struct wlr_gles2_pixel_format *fmt = get_gles2_format_from_wl(wl_fmt);
if (fmt == NULL) {
@@ -180,7 +184,9 @@ struct wlr_texture *wlr_gles2_texture_from_pixels(struct wlr_egl *egl,
struct wlr_texture *wlr_gles2_texture_from_wl_drm(struct wlr_egl *egl,
struct wl_resource *data) {
- assert(wlr_egl_is_current(egl));
+ if (!wlr_egl_is_current(egl)) {
+ wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL);
+ }
if (!glEGLImageTargetTexture2DOES) {
return NULL;
@@ -239,7 +245,9 @@ struct wlr_texture *wlr_gles2_texture_from_wl_drm(struct wlr_egl *egl,
struct wlr_texture *wlr_gles2_texture_from_dmabuf(struct wlr_egl *egl,
struct wlr_dmabuf_attributes *attribs) {
- assert(wlr_egl_is_current(egl));
+ if (!wlr_egl_is_current(egl)) {
+ wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL);
+ }
if (!glEGLImageTargetTexture2DOES) {
return NULL;
diff --git a/render/meson.build b/render/meson.build
index 4b90c229..ab66eab0 100644
--- a/render/meson.build
+++ b/render/meson.build
@@ -1,9 +1,10 @@
glgen = find_program('../glgen.sh')
-glapi = custom_target('glapi',
+glapi = custom_target(
+ 'glapi',
input: 'glapi.txt',
output: ['@BASENAME@.c', '@BASENAME@.h'],
- command: [glgen, '@INPUT@', '@OUTPUT0@', '@OUTPUT1@'],
+ command: [glgen, '@INPUT@', '@OUTDIR@'],
)
lib_wlr_render = static_library(
@@ -19,8 +20,7 @@ lib_wlr_render = static_library(
'wlr_renderer.c',
'wlr_texture.c',
),
- glapi[0],
- glapi[1],
+ glapi,
include_directories: wlr_inc,
dependencies: [egl, glesv2, pixman, wayland_server],
)
diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c
index 6c2b9fbb..31bf2b18 100644
--- a/render/wlr_renderer.c
+++ b/render/wlr_renderer.c
@@ -1,10 +1,11 @@
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
+#include <wlr/render/gles2.h>
#include <wlr/render/interface.h>
#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_linux_dmabuf_v1.h>
#include <wlr/types/wlr_matrix.h>
-#include <wlr/render/gles2.h>
#include <wlr/util/log.h>
#include "util/signal.h"
@@ -176,6 +177,10 @@ void wlr_renderer_init_wl_display(struct wlr_renderer *r,
}
}
+ if (r->impl->texture_from_dmabuf) {
+ wlr_linux_dmabuf_v1_create(wl_display, r);
+ }
+
if (r->impl->init_wl_display) {
r->impl->init_wl_display(r, wl_display);
}
diff --git a/rootston/config.c b/rootston/config.c
index 0c0ad055..92d90de1 100644
--- a/rootston/config.c
+++ b/rootston/config.c
@@ -26,7 +26,10 @@ static void usage(const char *name, int ret) {
" See `rootston.ini.example` for config\n"
" file documentation.\n"
" -E <COMMAND> Command that will be ran at startup.\n"
- " -D Enable damage tracking debugging.\n",
+ " -D Enable damage tracking debugging.\n"
+ " -l <LEVEL> Set log verbosity, where,\n"
+ " 0:SILENT, 1:ERROR, 2:INFO, 3+:DEBUG\n"
+ " (default: DEBUG)\n",
name);
exit(ret);
@@ -455,7 +458,8 @@ struct roots_config *roots_config_create_from_args(int argc, char *argv[]) {
wl_list_init(&config->bindings);
int c;
- while ((c = getopt(argc, argv, "C:E:hD")) != -1) {
+ unsigned int log_verbosity = WLR_DEBUG;
+ while ((c = getopt(argc, argv, "C:E:hDl:")) != -1) {
switch (c) {
case 'C':
config->config_path = strdup(optarg);
@@ -466,11 +470,18 @@ struct roots_config *roots_config_create_from_args(int argc, char *argv[]) {
case 'D':
config->debug_damage_tracking = true;
break;
+ case 'l':
+ log_verbosity = strtoul(optarg, NULL, 10);
+ if (log_verbosity >= WLR_LOG_IMPORTANCE_LAST) {
+ log_verbosity = WLR_LOG_IMPORTANCE_LAST - 1;
+ }
+ break;
case 'h':
case '?':
usage(argv[0], c != 'h');
}
}
+ wlr_log_init(log_verbosity, NULL);
if (!config->config_path) {
// get the config path from the current directory
diff --git a/rootston/cursor.c b/rootston/cursor.c
index 94f5520e..9a9f9af6 100644
--- a/rootston/cursor.c
+++ b/rootston/cursor.c
@@ -101,6 +101,7 @@ static void seat_view_deco_button(struct roots_seat_view *view, double sx,
static void roots_passthrough_cursor(struct roots_cursor *cursor,
uint32_t time) {
+ bool focus_changed;
double sx, sy;
struct roots_view *view = NULL;
struct roots_seat *seat = cursor->seat;
@@ -136,8 +137,11 @@ static void roots_passthrough_cursor(struct roots_cursor *cursor,
}
if (surface) {
+ focus_changed = (seat->seat->pointer_state.focused_surface != surface);
wlr_seat_pointer_notify_enter(seat->seat, surface, sx, sy);
- wlr_seat_pointer_notify_motion(seat->seat, time, sx, sy);
+ if (!focus_changed) {
+ wlr_seat_pointer_notify_motion(seat->seat, time, sx, sy);
+ }
} else {
wlr_seat_pointer_clear_focus(seat->seat);
}
@@ -148,8 +152,8 @@ static void roots_passthrough_cursor(struct roots_cursor *cursor,
}
}
-static void roots_cursor_update_position(
- struct roots_cursor *cursor, uint32_t time) {
+void roots_cursor_update_position(struct roots_cursor *cursor,
+ uint32_t time) {
struct roots_seat *seat = cursor->seat;
struct roots_view *view;
switch (cursor->mode) {
@@ -266,13 +270,7 @@ static void roots_cursor_press_button(struct roots_cursor *cursor,
cursor->mode = ROOTS_CURSOR_PASSTHROUGH;
}
- switch (state) {
- case WLR_BUTTON_RELEASED:
- if (!is_touch) {
- roots_cursor_update_position(cursor, time);
- }
- break;
- case WLR_BUTTON_PRESSED:
+ if (state == WLR_BUTTON_PRESSED) {
if (view) {
roots_seat_set_focus(seat, view);
}
@@ -283,7 +281,6 @@ static void roots_cursor_press_button(struct roots_cursor *cursor,
roots_seat_set_focus_layer(seat, layer);
}
}
- break;
}
}
diff --git a/rootston/desktop.c b/rootston/desktop.c
index 3f9faf24..efb7581a 100644
--- a/rootston/desktop.c
+++ b/rootston/desktop.c
@@ -9,11 +9,11 @@
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
#include <wlr/types/wlr_gamma_control.h>
+#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_input_inhibitor.h>
#include <wlr/types/wlr_layer_shell.h>
-#include <wlr/types/wlr_linux_dmabuf.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_primary_selection.h>
#include <wlr/types/wlr_server_decoration.h>
@@ -423,6 +423,7 @@ struct roots_subsurface *subsurface_create(struct roots_view *view,
view_child_init(&subsurface->view_child, view, wlr_subsurface->surface);
subsurface->destroy.notify = subsurface_handle_destroy;
wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
+ input_update_cursor_focus(view->desktop->server->input);
return subsurface;
}
@@ -468,6 +469,7 @@ void view_map(struct roots_view *view, struct wlr_surface *surface) {
wl_list_insert(&view->desktop->views, &view->link);
view_damage_whole(view);
+ input_update_cursor_focus(view->desktop->server->input);
}
void view_unmap(struct roots_view *view) {
@@ -550,6 +552,23 @@ void view_update_size(struct roots_view *view, uint32_t width, uint32_t height)
view_damage_whole(view);
}
+void view_update_decorated(struct roots_view *view, bool decorated) {
+ if (view->decorated == decorated) {
+ return;
+ }
+
+ view_damage_whole(view);
+ view->decorated = decorated;
+ if (decorated) {
+ view->border_width = 4;
+ view->titlebar_height = 12;
+ } else {
+ view->border_width = 0;
+ view->titlebar_height = 0;
+ }
+ view_damage_whole(view);
+}
+
static bool view_at(struct roots_view *view, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
if (view->type == ROOTS_WL_SHELL_VIEW &&
@@ -849,6 +868,8 @@ struct roots_desktop *desktop_create(struct roots_server *server,
desktop->gamma_control_manager = wlr_gamma_control_manager_create(
server->wl_display);
+ desktop->gamma_control_manager_v1 = wlr_gamma_control_manager_v1_create(
+ server->wl_display);
desktop->screenshooter = wlr_screenshooter_create(server->wl_display);
desktop->export_dmabuf_manager_v1 =
wlr_export_dmabuf_manager_v1_create(server->wl_display);
@@ -871,9 +892,6 @@ struct roots_desktop *desktop_create(struct roots_server *server,
wl_signal_add(&desktop->input_inhibit->events.deactivate,
&desktop->input_inhibit_deactivate);
- desktop->linux_dmabuf = wlr_linux_dmabuf_create(server->wl_display,
- server->renderer);
-
desktop->virtual_keyboard = wlr_virtual_keyboard_manager_v1_create(
server->wl_display);
wl_signal_add(&desktop->virtual_keyboard->events.new_virtual_keyboard,
@@ -882,6 +900,12 @@ struct roots_desktop *desktop_create(struct roots_server *server,
desktop->screencopy = wlr_screencopy_manager_v1_create(server->wl_display);
+ desktop->xdg_decoration_manager =
+ wlr_xdg_decoration_manager_v1_create(server->wl_display);
+ wl_signal_add(&desktop->xdg_decoration_manager->events.new_toplevel_decoration,
+ &desktop->xdg_toplevel_decoration);
+ desktop->xdg_toplevel_decoration.notify = handle_xdg_toplevel_decoration;
+
return desktop;
}
diff --git a/rootston/input.c b/rootston/input.c
index 84b5acae..b7a5f1ba 100644
--- a/rootston/input.c
+++ b/rootston/input.c
@@ -1,5 +1,7 @@
+#define _POSIX_C_SOURCE 200112L
#include <assert.h>
#include <stdlib.h>
+#include <time.h>
#include <wayland-server.h>
#include <wlr/backend/libinput.h>
#include <wlr/config.h>
@@ -126,3 +128,16 @@ bool input_view_has_focus(struct roots_input *input, struct roots_view *view) {
return false;
}
+
+static inline int64_t timespec_to_msec(const struct timespec *a) {
+ return (int64_t)a->tv_sec * 1000 + a->tv_nsec / 1000000;
+}
+
+void input_update_cursor_focus(struct roots_input *input) {
+ struct roots_seat *seat;
+ struct timespec now;
+ wl_list_for_each(seat, &input->seats, link) {
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ roots_cursor_update_position(seat->cursor, timespec_to_msec(&now));
+ }
+}
diff --git a/rootston/keyboard.c b/rootston/keyboard.c
index 6697ca83..b5a8093b 100644
--- a/rootston/keyboard.c
+++ b/rootston/keyboard.c
@@ -2,6 +2,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
+#include <sys/wait.h>
#include <unistd.h>
#include <wayland-server.h>
#include <wlr/backend/multi.h>
@@ -84,6 +85,39 @@ static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms,
}
}
+static void double_fork_shell_cmd(const char *shell_cmd) {
+ pid_t pid = fork();
+ if (pid < 0) {
+ wlr_log(WLR_ERROR, "cannot execute binding command: fork() failed");
+ return;
+ }
+
+ if (pid == 0) {
+ pid = fork();
+ if (pid == 0) {
+ execl("/bin/sh", "/bin/sh", "-c", shell_cmd, NULL);
+ _exit(EXIT_FAILURE);
+ } else {
+ _exit(pid == -1);
+ }
+ }
+
+ int status;
+ while (waitpid(pid, &status, 0) < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ wlr_log_errno(WLR_ERROR, "waitpid() on first child failed");
+ return;
+ }
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ return;
+ }
+
+ wlr_log(WLR_ERROR, "first child failed to fork command");
+}
+
static const char *exec_prefix = "exec ";
static bool outputs_enabled = true;
@@ -113,13 +147,7 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard,
}
} else if (strncmp(exec_prefix, command, strlen(exec_prefix)) == 0) {
const char *shell_cmd = command + strlen(exec_prefix);
- pid_t pid = fork();
- if (pid < 0) {
- wlr_log(WLR_ERROR, "cannot execute binding command: fork() failed");
- return;
- } else if (pid == 0) {
- execl("/bin/sh", "/bin/sh", "-c", shell_cmd, (void *)NULL);
- }
+ double_fork_shell_cmd(shell_cmd);
} else if (strcmp(command, "maximize") == 0) {
struct roots_view *focus = roots_seat_get_focus(seat);
if (focus != NULL) {
@@ -133,6 +161,21 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard,
wl_list_for_each(output, &keyboard->input->server->desktop->outputs, link) {
wlr_output_enable(output->wlr_output, outputs_enabled);
}
+ } else if (strcmp(command, "toggle_decoration_mode") == 0) {
+ struct roots_view *focus = roots_seat_get_focus(seat);
+ if (focus != NULL && focus->type == ROOTS_XDG_SHELL_VIEW) {
+ struct roots_xdg_toplevel_decoration *decoration =
+ focus->roots_xdg_surface->xdg_toplevel_decoration;
+ if (decoration != NULL) {
+ enum wlr_xdg_toplevel_decoration_v1_mode mode =
+ decoration->wlr_decoration->current_mode;
+ mode = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE
+ ? WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE
+ : WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
+ wlr_xdg_toplevel_decoration_v1_set_mode(
+ decoration->wlr_decoration, mode);
+ }
+ }
} else {
wlr_log(WLR_ERROR, "unknown binding command: %s", command);
}
diff --git a/rootston/layer_shell.c b/rootston/layer_shell.c
index ba69c3db..39054079 100644
--- a/rootston/layer_shell.c
+++ b/rootston/layer_shell.c
@@ -1,6 +1,12 @@
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200112L
+#endif
#include <assert.h>
+#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
+#include <string.h>
+#include <time.h>
#include <wayland-server.h>
#include <wlr/types/wlr_box.h>
#include <wlr/types/wlr_surface.h>
@@ -73,13 +79,38 @@ static void apply_exclusive(struct wlr_box *usable_area,
}
}
-static void arrange_layer(struct wlr_output *output, struct wl_list *list,
+static void update_cursors(struct roots_layer_surface *roots_surface,
+ struct wl_list *seats /* struct roots_seat */) {
+ struct roots_seat *seat;
+ wl_list_for_each(seat, seats, link) {
+ double sx, sy;
+
+ struct wlr_surface *surface = desktop_surface_at(
+ seat->input->server->desktop,
+ seat->cursor->cursor->x, seat->cursor->cursor->y, &sx, &sy, NULL);
+
+ if (surface == roots_surface->layer_surface->surface) {
+ struct timespec time;
+ if (clock_gettime(CLOCK_MONOTONIC, &time) == 0) {
+ roots_cursor_update_position(seat->cursor,
+ time.tv_sec * 1000 + time.tv_nsec / 1000000);
+ } else {
+ wlr_log(WLR_ERROR, "Failed to get time, not updating"
+ "position. Errno: %s\n", strerror(errno));
+ }
+ }
+ }
+}
+
+static void arrange_layer(struct wlr_output *output,
+ struct wl_list *seats /* struct *roots_seat */,
+ struct wl_list *list /* struct *roots_layer_surface */,
struct wlr_box *usable_area, bool exclusive) {
struct roots_layer_surface *roots_surface;
struct wlr_box full_area = { 0 };
wlr_output_effective_resolution(output,
&full_area.width, &full_area.height);
- wl_list_for_each(roots_surface, list, link) {
+ wl_list_for_each_reverse(roots_surface, list, link) {
struct wlr_layer_surface *layer = roots_surface->layer_surface;
struct wlr_layer_surface_state *state = &layer->current;
if (exclusive != (state->exclusive_zone > 0)) {
@@ -143,12 +174,25 @@ static void arrange_layer(struct wlr_output *output, struct wl_list *list,
wlr_layer_surface_close(layer);
continue;
}
+
// Apply
+ struct wlr_box old_geo = roots_surface->geo;
roots_surface->geo = box;
apply_exclusive(usable_area, state->anchor, state->exclusive_zone,
state->margin.top, state->margin.right,
state->margin.bottom, state->margin.left);
wlr_layer_surface_configure(layer, box.width, box.height);
+
+ // Having a cursor newly end up over the moved layer will not
+ // automatically send a motion event to the surface. The event needs to
+ // be synthesized.
+ // Only update layer surfaces which kept their size (and so buffers) the
+ // same, because those with resized buffers will be handled separately.
+
+ if (roots_surface->geo.x != old_geo.x
+ || roots_surface->geo.y != old_geo.y) {
+ update_cursors(roots_surface, seats);
+ }
}
}
@@ -158,16 +202,16 @@ void arrange_layers(struct roots_output *output) {
&usable_area.width, &usable_area.height);
// Arrange exclusive surfaces from top->bottom
- arrange_layer(output->wlr_output,
+ arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
&usable_area, true);
- arrange_layer(output->wlr_output,
+ arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
&usable_area, true);
- arrange_layer(output->wlr_output,
+ arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
&usable_area, true);
- arrange_layer(output->wlr_output,
+ arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
&usable_area, true);
memcpy(&output->usable_area, &usable_area, sizeof(struct wlr_box));
@@ -180,16 +224,16 @@ void arrange_layers(struct roots_output *output) {
}
// Arrange non-exlusive surfaces from top->bottom
- arrange_layer(output->wlr_output,
+ arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
&usable_area, false);
- arrange_layer(output->wlr_output,
+ arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
&usable_area, false);
- arrange_layer(output->wlr_output,
+ arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
&usable_area, false);
- arrange_layer(output->wlr_output,
+ arrange_layer(output->wlr_output, &output->desktop->server->input->seats,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
&usable_area, false);
@@ -238,6 +282,20 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
struct roots_output *output = wlr_output->data;
struct wlr_box old_geo = layer->geo;
arrange_layers(output);
+
+ // Cursor changes which happen as a consequence of resizing a layer
+ // surface are applied in arrange_layers. Because the resize happens
+ // before the underlying surface changes, it will only receive a cursor
+ // update if the new cursor position crosses the *old* sized surface in
+ // the *new* layer surface.
+ // Another cursor move event is needed when the surface actually
+ // changes.
+ struct wlr_surface *surface = layer_surface->surface;
+ if (surface->previous.width != surface->current.width ||
+ surface->previous.height != surface->current.height) {
+ update_cursors(layer, &output->desktop->server->input->seats);
+ }
+
if (memcmp(&old_geo, &layer->geo, sizeof(struct wlr_box)) != 0) {
output_damage_whole_local_surface(output, layer_surface->surface,
old_geo.x, old_geo.y, 0);
@@ -291,7 +349,10 @@ static void handle_map(struct wl_listener *listener, void *data) {
static void handle_unmap(struct wl_listener *listener, void *data) {
struct roots_layer_surface *layer = wl_container_of(
listener, layer, unmap);
+ struct wlr_output *wlr_output = layer->layer_surface->output;
+ struct roots_output *output = wlr_output->data;
unmap(layer->layer_surface);
+ input_update_cursor_focus(output->desktop->server->input);
}
static void popup_handle_map(struct wl_listener *listener, void *data) {
@@ -303,6 +364,7 @@ static void popup_handle_map(struct wl_listener *listener, void *data) {
int oy = popup->wlr_popup->geometry.y + layer->geo.y;
output_damage_whole_local_surface(output, popup->wlr_popup->base->surface,
ox, oy, 0);
+ input_update_cursor_focus(output->desktop->server->input);
}
static void popup_handle_unmap(struct wl_listener *listener, void *data) {
diff --git a/rootston/meson.build b/rootston/meson.build
index 8ab872b5..9d1decce 100644
--- a/rootston/meson.build
+++ b/rootston/meson.build
@@ -11,12 +11,17 @@ sources = [
'seat.c',
'virtual_keyboard.c',
'wl_shell.c',
- 'xdg_shell_v6.c',
'xdg_shell.c',
+ 'xdg_shell_v6.c',
]
-if get_option('enable-xwayland')
- sources += ['xwayland.c']
+
+if conf_data.get('WLR_HAS_XWAYLAND', false)
+ sources += 'xwayland.c'
endif
+
executable(
- 'rootston', sources, dependencies: [wlroots, wlr_protos, pixman]
+ 'rootston',
+ sources,
+ dependencies: [wlroots, wlr_protos, pixman],
+ build_by_default: get_option('rootston'),
)
diff --git a/rootston/output.c b/rootston/output.c
index 71ccf8bc..8677f491 100644
--- a/rootston/output.c
+++ b/rootston/output.c
@@ -3,6 +3,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
+#include <wlr/backend/drm.h>
#include <wlr/config.h>
#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_compositor.h>
@@ -16,7 +17,6 @@
#include "rootston/layers.h"
#include "rootston/output.h"
#include "rootston/server.h"
-#include "backend/drm/drm.h"
/**
* Rotate a child's position relative to a parent. The parent size is (pw, ph),
@@ -822,12 +822,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
wlr_output->model, wlr_output->serial, wlr_output->phys_width,
wlr_output->phys_height);
- if (!wl_list_empty(&wlr_output->modes)) {
- struct wlr_output_mode *mode =
- wl_container_of((&wlr_output->modes)->prev, mode, link);
- wlr_output_set_mode(wlr_output, mode);
- }
-
struct roots_output *output = calloc(1, sizeof(struct roots_output));
clock_gettime(CLOCK_MONOTONIC, &output->last_frame);
output->desktop = desktop;
@@ -856,22 +850,28 @@ void handle_new_output(struct wl_listener *listener, void *data) {
struct roots_output_config *output_config =
roots_config_get_output(config, wlr_output);
+
+ if ((!output_config || output_config->enable) && !wl_list_empty(&wlr_output->modes)) {
+ struct wlr_output_mode *mode =
+ wl_container_of(wlr_output->modes.prev, mode, link);
+ wlr_output_set_mode(wlr_output, mode);
+ }
+
if (output_config) {
if (output_config->enable) {
- struct roots_output_mode_config *mode_config;
-
if (wlr_output_is_drm(wlr_output)) {
+ struct roots_output_mode_config *mode_config;
wl_list_for_each(mode_config, &output_config->modes, link) {
wlr_drm_connector_add_mode(wlr_output, &mode_config->info);
}
- } else {
- if (!wl_list_empty(&output_config->modes)) {
- wlr_log(WLR_ERROR, "Can only add modes for DRM backend");
- }
+ } else if (!wl_list_empty(&output_config->modes)) {
+ wlr_log(WLR_ERROR, "Can only add modes for DRM backend");
}
+
if (output_config->mode.width) {
set_mode(wlr_output, output_config);
}
+
wlr_output_set_scale(wlr_output, output_config->scale);
wlr_output_set_transform(wlr_output, output_config->transform);
wlr_output_layout_add(desktop->layout, wlr_output, output_config->x,
diff --git a/rootston/seat.c b/rootston/seat.c
index f308da52..1ae098bc 100644
--- a/rootston/seat.c
+++ b/rootston/seat.c
@@ -1,4 +1,4 @@
-#define _POSIX_C_SOURCE 199309L
+#define _POSIX_C_SOURCE 200112L
#include <assert.h>
#include <libinput.h>
#include <stdlib.h>
@@ -127,13 +127,13 @@ static void handle_tablet_tool_position(struct roots_cursor *cursor,
struct wlr_surface *surface = desktop_surface_at(desktop,
cursor->cursor->x, cursor->cursor->y, &sx, &sy, &view);
struct roots_tablet_tool *roots_tool = tool->data;
-
+
if (!surface) {
wlr_tablet_v2_tablet_tool_notify_proximity_out(roots_tool->tablet_v2_tool);
/* XXX: TODO: Fallback pointer semantics */
return;
}
-
+
if (!wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) {
wlr_tablet_v2_tablet_tool_notify_proximity_out(roots_tool->tablet_v2_tool);
/* XXX: TODO: Fallback pointer semantics */
@@ -218,7 +218,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
static void handle_tablet_tool_destroy(struct wl_listener *listener, void *data) {
struct roots_tablet_tool *tool =
wl_container_of(listener, tool, tool_destroy);
-
+
wl_list_remove(&tool->link);
wl_list_remove(&tool->tool_link);
@@ -503,16 +503,16 @@ void roots_drag_icon_update_position(struct roots_drag_icon *icon) {
struct roots_seat *seat = icon->seat;
struct wlr_cursor *cursor = seat->cursor->cursor;
if (wlr_icon->is_pointer) {
- icon->x = cursor->x + wlr_icon->sx;
- icon->y = cursor->y + wlr_icon->sy;
+ icon->x = cursor->x;
+ icon->y = cursor->y;
} else {
struct wlr_touch_point *point =
wlr_seat_touch_get_point(seat->seat, wlr_icon->touch_id);
if (point == NULL) {
return;
}
- icon->x = seat->touch_x + wlr_icon->sx;
- icon->y = seat->touch_y + wlr_icon->sy;
+ icon->x = seat->touch_x;
+ icon->y = seat->touch_y;
}
roots_drag_icon_damage_whole(icon);
@@ -746,6 +746,7 @@ static void attach_tablet_pad(struct roots_tablet_pad *pad,
pad->tablet = tool;
+ wl_list_remove(&pad->tablet_destroy.link);
pad->tablet_destroy.notify = handle_pad_tool_destroy;
wl_signal_add(&tool->device->events.destroy, &pad->tablet_destroy);
}
@@ -813,7 +814,8 @@ static void seat_add_tablet_pad(struct roots_seat *seat,
&tablet_pad->device_destroy);
tablet_pad->attach.notify = handle_tablet_pad_attach;
- wl_signal_add(&tablet_pad->device->tablet_pad->events.attach_tablet, &tablet_pad->attach);
+ wl_signal_add(&tablet_pad->device->tablet_pad->events.attach_tablet,
+ &tablet_pad->attach);
tablet_pad->button.notify = handle_tablet_pad_button;
wl_signal_add(&tablet_pad->device->tablet_pad->events.button, &tablet_pad->button);
@@ -824,6 +826,8 @@ static void seat_add_tablet_pad(struct roots_seat *seat,
tablet_pad->ring.notify = handle_tablet_pad_ring;
wl_signal_add(&tablet_pad->device->tablet_pad->events.ring, &tablet_pad->ring);
+ wl_list_init(&tablet_pad->tablet_destroy.link);
+
struct roots_desktop *desktop = seat->input->server->desktop;
tablet_pad->tablet_v2_pad =
wlr_tablet_pad_create(desktop->tablet_v2, seat->seat, device);
@@ -1125,7 +1129,8 @@ void roots_seat_set_focus(struct roots_seat *seat, struct roots_view *view) {
#ifdef WLR_HAS_XWAYLAND
if (view && view->type == ROOTS_XWAYLAND_VIEW &&
- wlr_xwayland_surface_is_unmanaged(view->xwayland_surface)) {
+ !wlr_xwayland_or_surface_wants_focus(
+ view->xwayland_surface)) {
return;
}
#endif
diff --git a/rootston/xdg_shell.c b/rootston/xdg_shell.c
index d04d37e1..2cf2081e 100644
--- a/rootston/xdg_shell.c
+++ b/rootston/xdg_shell.c
@@ -6,6 +6,7 @@
#include <wlr/types/wlr_surface.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/util/log.h>
+#include "rootston/cursor.h"
#include "rootston/desktop.h"
#include "rootston/input.h"
#include "rootston/server.h"
@@ -33,6 +34,7 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) {
static void popup_handle_map(struct wl_listener *listener, void *data) {
struct roots_xdg_popup *popup = wl_container_of(listener, popup, map);
view_damage_whole(popup->view_child.view);
+ input_update_cursor_focus(popup->view_child.view->desktop->server->input);
}
static void popup_handle_unmap(struct wl_listener *listener, void *data) {
@@ -263,6 +265,7 @@ static void destroy(struct roots_view *view) {
wl_list_remove(&roots_xdg_surface->request_resize.link);
wl_list_remove(&roots_xdg_surface->request_maximize.link);
wl_list_remove(&roots_xdg_surface->request_fullscreen.link);
+ roots_xdg_surface->view->xdg_surface->data = NULL;
free(roots_xdg_surface);
}
@@ -437,6 +440,7 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
&roots_surface->request_fullscreen);
roots_surface->new_popup.notify = handle_new_popup;
wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup);
+ surface->data = roots_surface;
struct roots_view *view = view_create(desktop);
if (!view) {
@@ -463,3 +467,71 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
view_set_fullscreen(view, true, NULL);
}
}
+
+
+
+static void decoration_handle_destroy(struct wl_listener *listener,
+ void *data) {
+ struct roots_xdg_toplevel_decoration *decoration =
+ wl_container_of(listener, decoration, destroy);
+
+ decoration->surface->xdg_toplevel_decoration = NULL;
+ view_update_decorated(decoration->surface->view, false);
+ wl_list_remove(&decoration->destroy.link);
+ wl_list_remove(&decoration->request_mode.link);
+ wl_list_remove(&decoration->surface_commit.link);
+ free(decoration);
+}
+
+static void decoration_handle_request_mode(struct wl_listener *listener,
+ void *data) {
+ struct roots_xdg_toplevel_decoration *decoration =
+ wl_container_of(listener, decoration, request_mode);
+
+ enum wlr_xdg_toplevel_decoration_v1_mode mode =
+ decoration->wlr_decoration->client_pending_mode;
+ if (mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_NONE) {
+ mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
+ }
+ wlr_xdg_toplevel_decoration_v1_set_mode(decoration->wlr_decoration, mode);
+}
+
+static void decoration_handle_surface_commit(struct wl_listener *listener,
+ void *data) {
+ struct roots_xdg_toplevel_decoration *decoration =
+ wl_container_of(listener, decoration, surface_commit);
+
+ bool decorated = decoration->wlr_decoration->current_mode ==
+ WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
+ view_update_decorated(decoration->surface->view, decorated);
+}
+
+void handle_xdg_toplevel_decoration(struct wl_listener *listener, void *data) {
+ struct wlr_xdg_toplevel_decoration_v1 *wlr_decoration = data;
+
+ wlr_log(WLR_DEBUG, "new xdg toplevel decoration");
+
+ struct roots_xdg_surface *xdg_surface = wlr_decoration->surface->data;
+ assert(xdg_surface != NULL);
+ struct wlr_xdg_surface *wlr_xdg_surface = xdg_surface->view->xdg_surface;
+
+ struct roots_xdg_toplevel_decoration *decoration =
+ calloc(1, sizeof(struct roots_xdg_toplevel_decoration));
+ if (decoration == NULL) {
+ return;
+ }
+ decoration->wlr_decoration = wlr_decoration;
+ decoration->surface = xdg_surface;
+ xdg_surface->xdg_toplevel_decoration = decoration;
+
+ decoration->destroy.notify = decoration_handle_destroy;
+ wl_signal_add(&wlr_decoration->events.destroy, &decoration->destroy);
+ decoration->request_mode.notify = decoration_handle_request_mode;
+ wl_signal_add(&wlr_decoration->events.request_mode,
+ &decoration->request_mode);
+ decoration->surface_commit.notify = decoration_handle_surface_commit;
+ wl_signal_add(&wlr_xdg_surface->surface->events.commit,
+ &decoration->surface_commit);
+
+ decoration_handle_request_mode(&decoration->request_mode, wlr_decoration);
+}
diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c
index 219be2b0..1201ba68 100644
--- a/rootston/xdg_shell_v6.c
+++ b/rootston/xdg_shell_v6.c
@@ -34,6 +34,7 @@ static void popup_handle_map(struct wl_listener *listener, void *data) {
struct roots_xdg_popup_v6 *popup =
wl_container_of(listener, popup, map);
view_damage_whole(popup->view_child.view);
+ input_update_cursor_focus(popup->view_child.view->desktop->server->input);
}
static void popup_handle_unmap(struct wl_listener *listener, void *data) {
diff --git a/types/data_device/wlr_drag.c b/types/data_device/wlr_drag.c
index 7f3b346d..fcde7b3e 100644
--- a/types/data_device/wlr_drag.c
+++ b/types/data_device/wlr_drag.c
@@ -345,9 +345,6 @@ static void drag_icon_surface_role_commit(struct wlr_surface *surface) {
return;
}
- icon->sx += icon->surface->current.dx;
- icon->sy += icon->surface->current.dy;
-
drag_icon_set_mapped(icon, wlr_surface_has_buffer(surface));
}
diff --git a/types/meson.build b/types/meson.build
index 0b8584f8..23c6cd13 100644
--- a/types/meson.build
+++ b/types/meson.build
@@ -25,13 +25,14 @@ lib_wlr_types = static_library(
'wlr_cursor.c',
'wlr_export_dmabuf_v1.c',
'wlr_gamma_control.c',
+ 'wlr_gamma_control_v1.c',
'wlr_idle_inhibit_v1.c',
'wlr_idle.c',
'wlr_input_device.c',
'wlr_input_inhibitor.c',
'wlr_keyboard.c',
'wlr_layer_shell.c',
- 'wlr_linux_dmabuf.c',
+ 'wlr_linux_dmabuf_v1.c',
'wlr_list.c',
'wlr_matrix.c',
'wlr_output_damage.c',
@@ -53,9 +54,10 @@ lib_wlr_types = static_library(
'wlr_virtual_keyboard_v1.c',
'wlr_wl_shell.c',
'wlr_xcursor_manager.c',
+ 'wlr_xdg_decoration_v1.c',
'wlr_xdg_output.c',
'wlr_screencopy_v1.c',
),
include_directories: wlr_inc,
- dependencies: [pixman, xkbcommon, wayland_server, wlr_protos],
+ dependencies: [pixman, xkbcommon, wayland_server, wlr_protos, libinput],
)
diff --git a/types/seat/wlr_seat_keyboard.c b/types/seat/wlr_seat_keyboard.c
index 8c1b56e1..e8ea300e 100644
--- a/types/seat/wlr_seat_keyboard.c
+++ b/types/seat/wlr_seat_keyboard.c
@@ -110,7 +110,7 @@ static void handle_keyboard_repeat_info(struct wl_listener *listener,
static void handle_keyboard_destroy(struct wl_listener *listener, void *data) {
struct wlr_seat_keyboard_state *state =
wl_container_of(listener, state, keyboard_destroy);
- state->keyboard = NULL;
+ wlr_seat_set_keyboard(state->seat, NULL);
}
void wlr_seat_set_keyboard(struct wlr_seat *seat,
diff --git a/types/tablet_v2/wlr_tablet_v2.c b/types/tablet_v2/wlr_tablet_v2.c
index fa058e79..7f3d5f30 100644
--- a/types/tablet_v2/wlr_tablet_v2.c
+++ b/types/tablet_v2/wlr_tablet_v2.c
@@ -14,6 +14,7 @@
#include <wlr/types/wlr_tablet_v2.h>
#include <wlr/util/log.h>
#include "tablet-unstable-v2-protocol.h"
+#include "util/signal.h"
#define TABLET_MANAGER_VERSION 1
@@ -162,7 +163,7 @@ static void get_tablet_seat(struct wl_client *wl_client, struct wl_resource *res
struct wlr_tablet_seat_client_v2 *seat_client =
calloc(1, sizeof(struct wlr_tablet_seat_client_v2));
- if (tablet_seat == NULL) {
+ if (seat_client == NULL) {
wl_client_post_no_memory(wl_client);
return;
}
@@ -281,6 +282,8 @@ void wlr_tablet_v2_destroy(struct wlr_tablet_manager_v2 *manager) {
wlr_tablet_manager_v2_destroy(pos->resource);
}
+ wlr_signal_emit_safe(&manager->events.destroy, manager);
+ wl_list_remove(&manager->display_destroy.link);
wl_global_destroy(manager->wl_global);
free(manager);
}
@@ -292,12 +295,6 @@ struct wlr_tablet_manager_v2 *wlr_tablet_v2_create(struct wl_display *display) {
return NULL;
}
- wl_list_init(&tablet->clients);
- wl_list_init(&tablet->seats);
-
- tablet->display_destroy.notify = handle_display_destroy;
- wl_display_add_destroy_listener(display, &tablet->display_destroy);
-
tablet->wl_global = wl_global_create(display,
&zwp_tablet_manager_v2_interface, TABLET_MANAGER_VERSION,
tablet, tablet_v2_bind);
@@ -306,5 +303,12 @@ struct wlr_tablet_manager_v2 *wlr_tablet_v2_create(struct wl_display *display) {
return NULL;
}
+ wl_signal_init(&tablet->events.destroy);
+ wl_list_init(&tablet->clients);
+ wl_list_init(&tablet->seats);
+
+ tablet->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &tablet->display_destroy);
+
return tablet;
}
diff --git a/types/tablet_v2/wlr_tablet_v2_pad.c b/types/tablet_v2/wlr_tablet_v2_pad.c
index 74444708..185abfe8 100644
--- a/types/tablet_v2/wlr_tablet_v2_pad.c
+++ b/types/tablet_v2/wlr_tablet_v2_pad.c
@@ -373,7 +373,7 @@ struct wlr_tablet_v2_tablet_pad *wlr_tablet_pad_create(
pad->grab = &pad->default_grab;
pad->group_count = wl_list_length(&wlr_pad->groups);
- pad->groups = calloc(pad->group_count, sizeof(int));
+ pad->groups = calloc(pad->group_count, sizeof(uint32_t));
if (!pad->groups) {
free(pad);
return NULL;
diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c
index 5e4aedac..55ed4792 100644
--- a/types/wlr_buffer.c
+++ b/types/wlr_buffer.c
@@ -1,8 +1,8 @@
#include <assert.h>
#include <stdlib.h>
-#include <wlr/types/wlr_buffer.h>
-#include <wlr/types/wlr_linux_dmabuf.h>
#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_buffer.h>
+#include <wlr/types/wlr_linux_dmabuf_v1.h>
#include <wlr/util/log.h>
bool wlr_resource_is_buffer(struct wl_resource *resource) {
@@ -21,9 +21,9 @@ bool wlr_buffer_get_resource_size(struct wl_resource *resource,
resource)) {
wlr_renderer_wl_drm_buffer_get_size(renderer, resource,
width, height);
- } else if (wlr_dmabuf_resource_is_buffer(resource)) {
- struct wlr_dmabuf_buffer *dmabuf =
- wlr_dmabuf_buffer_from_buffer_resource(resource);
+ } else if (wlr_dmabuf_v1_resource_is_buffer(resource)) {
+ struct wlr_dmabuf_v1_buffer *dmabuf =
+ wlr_dmabuf_v1_buffer_from_buffer_resource(resource);
*width = dmabuf->attributes.width;
*height = dmabuf->attributes.height;
} else {
@@ -77,9 +77,9 @@ struct wlr_buffer *wlr_buffer_create(struct wlr_renderer *renderer,
released = true;
} else if (wlr_renderer_resource_is_wl_drm_buffer(renderer, resource)) {
texture = wlr_texture_from_wl_drm(renderer, resource);
- } else if (wlr_dmabuf_resource_is_buffer(resource)) {
- struct wlr_dmabuf_buffer *dmabuf =
- wlr_dmabuf_buffer_from_buffer_resource(resource);
+ } else if (wlr_dmabuf_v1_resource_is_buffer(resource)) {
+ struct wlr_dmabuf_v1_buffer *dmabuf =
+ wlr_dmabuf_v1_buffer_from_buffer_resource(resource);
texture = wlr_texture_from_dmabuf(renderer, &dmabuf->attributes);
// We have imported the DMA-BUF, but we need to prevent the client from
diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c
index 82ad1a4a..49f11b20 100644
--- a/types/wlr_cursor.c
+++ b/types/wlr_cursor.c
@@ -332,7 +332,7 @@ static void handle_pointer_motion(struct wl_listener *listener, void *data) {
static void apply_output_transform(double *x, double *y,
enum wl_output_transform transform) {
- double dx = *x, dy = *y;
+ double dx = 0.0, dy = 0.0;
double width = 1.0, height = 1.0;
switch (transform) {
diff --git a/types/wlr_export_dmabuf_v1.c b/types/wlr_export_dmabuf_v1.c
index 060f4afa..72c9bcec 100644
--- a/types/wlr_export_dmabuf_v1.c
+++ b/types/wlr_export_dmabuf_v1.c
@@ -2,8 +2,8 @@
#include <stdlib.h>
#include <unistd.h>
#include <wlr/interfaces/wlr_output.h>
+#include <wlr/render/dmabuf.h>
#include <wlr/types/wlr_export_dmabuf_v1.h>
-#include <wlr/types/wlr_linux_dmabuf.h>
#include <wlr/types/wlr_output.h>
#include "wlr-export-dmabuf-unstable-v1-protocol.h"
#include <wlr/util/log.h>
diff --git a/types/wlr_gamma_control.c b/types/wlr_gamma_control.c
index 5b871335..40ca2aca 100644
--- a/types/wlr_gamma_control.c
+++ b/types/wlr_gamma_control.c
@@ -25,7 +25,7 @@ static void gamma_control_destroy(struct wlr_gamma_control *gamma_control) {
static const struct gamma_control_interface gamma_control_impl;
-struct wlr_gamma_control *gamma_control_from_resource(
+static struct wlr_gamma_control *gamma_control_from_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &gamma_control_interface,
&gamma_control_impl));
@@ -83,7 +83,7 @@ static const struct gamma_control_interface gamma_control_impl = {
static const struct gamma_control_manager_interface gamma_control_manager_impl;
-struct wlr_gamma_control_manager *gamma_control_manager_from_resource(
+static struct wlr_gamma_control_manager *gamma_control_manager_from_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &gamma_control_manager_interface,
&gamma_control_manager_impl));
@@ -155,11 +155,12 @@ void wlr_gamma_control_manager_destroy(
if (!manager) {
return;
}
- wl_list_remove(&manager->display_destroy.link);
struct wlr_gamma_control *gamma_control, *tmp;
wl_list_for_each_safe(gamma_control, tmp, &manager->controls, link) {
gamma_control_destroy(gamma_control);
}
+ wlr_signal_emit_safe(&manager->events.destroy, manager);
+ wl_list_remove(&manager->display_destroy.link);
wl_global_destroy(manager->global);
free(manager);
}
@@ -186,6 +187,7 @@ struct wlr_gamma_control_manager *wlr_gamma_control_manager_create(
}
manager->global = global;
+ wl_signal_init(&manager->events.destroy);
wl_list_init(&manager->controls);
manager->display_destroy.notify = handle_display_destroy;
diff --git a/types/wlr_gamma_control_v1.c b/types/wlr_gamma_control_v1.c
new file mode 100644
index 00000000..9f049a0b
--- /dev/null
+++ b/types/wlr_gamma_control_v1.c
@@ -0,0 +1,266 @@
+#include <assert.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <wayland-server.h>
+#include <wlr/interfaces/wlr_output.h>
+#include <wlr/types/wlr_gamma_control_v1.h>
+#include <wlr/types/wlr_output.h>
+#include <wlr/util/log.h>
+#include "util/signal.h"
+#include "wlr-gamma-control-unstable-v1-protocol.h"
+
+#define GAMMA_CONTROL_MANAGER_V1_VERSION 1
+
+static void gamma_control_handle_destroy(struct wl_client *client,
+ struct wl_resource *resource) {
+ wl_resource_destroy(resource);
+}
+
+static void gamma_control_destroy(struct wlr_gamma_control_v1 *gamma_control) {
+ if (gamma_control == NULL) {
+ return;
+ }
+ wlr_output_set_gamma(gamma_control->output, 0, NULL, NULL, NULL);
+ wl_resource_set_user_data(gamma_control->resource, NULL);
+ wl_list_remove(&gamma_control->output_destroy_listener.link);
+ wl_list_remove(&gamma_control->link);
+ free(gamma_control);
+}
+
+static void gamma_control_send_failed(
+ struct wlr_gamma_control_v1 *gamma_control) {
+ zwlr_gamma_control_v1_send_failed(gamma_control->resource);
+ gamma_control_destroy(gamma_control);
+}
+
+static const struct zwlr_gamma_control_v1_interface gamma_control_impl;
+
+static struct wlr_gamma_control_v1 *gamma_control_from_resource(
+ struct wl_resource *resource) {
+ assert(wl_resource_instance_of(resource, &zwlr_gamma_control_v1_interface,
+ &gamma_control_impl));
+ return wl_resource_get_user_data(resource);
+}
+
+static void gamma_control_handle_resource_destroy(struct wl_resource *resource) {
+ struct wlr_gamma_control_v1 *gamma_control =
+ gamma_control_from_resource(resource);
+ gamma_control_destroy(gamma_control);
+}
+
+static void gamma_control_handle_output_destroy(struct wl_listener *listener,
+ void *data) {
+ struct wlr_gamma_control_v1 *gamma_control =
+ wl_container_of(listener, gamma_control, output_destroy_listener);
+ gamma_control_destroy(gamma_control);
+}
+
+static void gamma_control_handle_set_gamma(struct wl_client *client,
+ struct wl_resource *gamma_control_resource, int fd) {
+ struct wlr_gamma_control_v1 *gamma_control =
+ gamma_control_from_resource(gamma_control_resource);
+ if (gamma_control == NULL) {
+ goto error_fd;
+ }
+
+ uint32_t ramp_size = wlr_output_get_gamma_size(gamma_control->output);
+ size_t table_size = ramp_size * 3 * sizeof(uint16_t);
+
+ // Refuse to block when reading
+ int fd_flags = fcntl(fd, F_GETFL, 0);
+ if (fd_flags == -1) {
+ wlr_log_errno(WLR_ERROR, "failed to get FD flags");
+ gamma_control_send_failed(gamma_control);
+ goto error_fd;
+ }
+ if (fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK) == -1) {
+ wlr_log_errno(WLR_ERROR, "failed to set FD flags");
+ gamma_control_send_failed(gamma_control);
+ goto error_fd;
+ }
+
+ // Use the heap since gamma tables can be large
+ uint16_t *table = malloc(table_size);
+ if (table == NULL) {
+ wl_resource_post_no_memory(gamma_control_resource);
+ goto error_fd;
+ }
+
+ ssize_t n_read = read(fd, table, table_size);
+ if (n_read < 0) {
+ wlr_log_errno(WLR_ERROR, "failed to read gamma table");
+ gamma_control_send_failed(gamma_control);
+ goto error_table;
+ } else if ((size_t)n_read != table_size) {
+ wl_resource_post_error(gamma_control_resource,
+ ZWLR_GAMMA_CONTROL_V1_ERROR_INVALID_GAMMA,
+ "The gamma ramps don't have the correct size");
+ goto error_table;
+ }
+ close(fd);
+ fd = -1;
+
+ uint16_t *r = table;
+ uint16_t *g = table + ramp_size;
+ uint16_t *b = table + 2 * ramp_size;
+
+ bool ok = wlr_output_set_gamma(gamma_control->output, ramp_size, r, g, b);
+ if (!ok) {
+ gamma_control_send_failed(gamma_control);
+ goto error_table;
+ }
+ free(table);
+
+ return;
+
+error_table:
+ free(table);
+error_fd:
+ close(fd);
+}
+
+static const struct zwlr_gamma_control_v1_interface gamma_control_impl = {
+ .destroy = gamma_control_handle_destroy,
+ .set_gamma = gamma_control_handle_set_gamma,
+};
+
+static const struct zwlr_gamma_control_manager_v1_interface
+ gamma_control_manager_impl;
+
+static struct wlr_gamma_control_manager_v1 *gamma_control_manager_from_resource(
+ struct wl_resource *resource) {
+ assert(wl_resource_instance_of(resource,
+ &zwlr_gamma_control_manager_v1_interface, &gamma_control_manager_impl));
+ return wl_resource_get_user_data(resource);
+}
+
+static void gamma_control_manager_get_gamma_control(struct wl_client *client,
+ struct wl_resource *manager_resource, uint32_t id,
+ struct wl_resource *output_resource) {
+ struct wlr_gamma_control_manager_v1 *manager =
+ gamma_control_manager_from_resource(manager_resource);
+ struct wlr_output *output = wlr_output_from_resource(output_resource);
+
+ struct wlr_gamma_control_v1 *gamma_control =
+ calloc(1, sizeof(struct wlr_gamma_control_v1));
+ if (gamma_control == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ gamma_control->output = output;
+
+ uint32_t version = wl_resource_get_version(manager_resource);
+ gamma_control->resource = wl_resource_create(client,
+ &zwlr_gamma_control_v1_interface, version, id);
+ if (gamma_control->resource == NULL) {
+ free(gamma_control);
+ wl_client_post_no_memory(client);
+ return;
+ }
+ wl_resource_set_implementation(gamma_control->resource, &gamma_control_impl,
+ gamma_control, gamma_control_handle_resource_destroy);
+
+ wl_signal_add(&output->events.destroy,
+ &gamma_control->output_destroy_listener);
+ gamma_control->output_destroy_listener.notify =
+ gamma_control_handle_output_destroy;
+
+ wl_list_init(&gamma_control->link);
+
+ if (!output->impl->set_gamma) {
+ zwlr_gamma_control_v1_send_failed(gamma_control->resource);
+ gamma_control_destroy(gamma_control);
+ return;
+ }
+
+ struct wlr_gamma_control_v1 *gc;
+ wl_list_for_each(gc, &manager->controls, link) {
+ if (gc->output == output) {
+ zwlr_gamma_control_v1_send_failed(gc->resource);
+ gamma_control_destroy(gc);
+ return;
+ }
+ }
+
+ wl_list_remove(&gamma_control->link);
+ wl_list_insert(&manager->controls, &gamma_control->link);
+ zwlr_gamma_control_v1_send_gamma_size(gamma_control->resource,
+ wlr_output_get_gamma_size(output));
+}
+
+static const struct zwlr_gamma_control_manager_v1_interface
+ gamma_control_manager_impl = {
+ .get_gamma_control = gamma_control_manager_get_gamma_control,
+};
+
+static void gamma_control_manager_handle_resource_destroy(
+ struct wl_resource *resource) {
+ wl_list_remove(wl_resource_get_link(resource));
+}
+
+static void gamma_control_manager_bind(struct wl_client *client, void *data,
+ uint32_t version, uint32_t id) {
+ struct wlr_gamma_control_manager_v1 *manager = data;
+
+ struct wl_resource *resource = wl_resource_create(client,
+ &zwlr_gamma_control_manager_v1_interface, version, id);
+ if (resource == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ wl_resource_set_implementation(resource, &gamma_control_manager_impl,
+ manager, gamma_control_manager_handle_resource_destroy);
+ wl_list_insert(&manager->resources, wl_resource_get_link(resource));
+}
+
+void wlr_gamma_control_manager_v1_destroy(
+ struct wlr_gamma_control_manager_v1 *manager) {
+ if (!manager) {
+ return;
+ }
+ struct wlr_gamma_control_v1 *gamma_control, *tmp;
+ wl_list_for_each_safe(gamma_control, tmp, &manager->controls, link) {
+ wl_resource_destroy(gamma_control->resource);
+ }
+ wlr_signal_emit_safe(&manager->events.destroy, manager);
+ wl_list_remove(&manager->display_destroy.link);
+ struct wl_resource *resource, *resource_tmp;
+ wl_resource_for_each_safe(resource, resource_tmp, &manager->resources) {
+ wl_resource_destroy(resource);
+ }
+ wl_global_destroy(manager->global);
+ free(manager);
+}
+
+static void handle_display_destroy(struct wl_listener *listener, void *data) {
+ struct wlr_gamma_control_manager_v1 *manager =
+ wl_container_of(listener, manager, display_destroy);
+ wlr_gamma_control_manager_v1_destroy(manager);
+}
+
+struct wlr_gamma_control_manager_v1 *wlr_gamma_control_manager_v1_create(
+ struct wl_display *display) {
+ struct wlr_gamma_control_manager_v1 *manager =
+ calloc(1, sizeof(struct wlr_gamma_control_manager_v1));
+ if (!manager) {
+ return NULL;
+ }
+
+ manager->global = wl_global_create(display,
+ &zwlr_gamma_control_manager_v1_interface,
+ GAMMA_CONTROL_MANAGER_V1_VERSION, manager, gamma_control_manager_bind);
+ if (manager->global == NULL) {
+ free(manager);
+ return NULL;
+ }
+
+ wl_signal_init(&manager->events.destroy);
+ wl_list_init(&manager->resources);
+ wl_list_init(&manager->controls);
+
+ manager->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &manager->display_destroy);
+
+ return manager;
+}
diff --git a/types/wlr_idle.c b/types/wlr_idle.c
index b4e00451..2d0e8eed 100644
--- a/types/wlr_idle.c
+++ b/types/wlr_idle.c
@@ -187,6 +187,7 @@ void wlr_idle_destroy(struct wlr_idle *idle) {
if (!idle) {
return;
}
+ wlr_signal_emit_safe(&idle->events.destroy, idle);
wl_list_remove(&idle->display_destroy.link);
struct wlr_idle_timeout *timer, *tmp;
wl_list_for_each_safe(timer, tmp, &idle->idle_timers, link) {
@@ -208,6 +209,7 @@ struct wlr_idle *wlr_idle_create(struct wl_display *display) {
}
wl_list_init(&idle->idle_timers);
wl_signal_init(&idle->events.activity_notify);
+ wl_signal_init(&idle->events.destroy);
idle->enabled = true;
idle->event_loop = wl_display_get_event_loop(display);
diff --git a/types/wlr_idle_inhibit_v1.c b/types/wlr_idle_inhibit_v1.c
index 4cee3029..5f3d3d40 100644
--- a/types/wlr_idle_inhibit_v1.c
+++ b/types/wlr_idle_inhibit_v1.c
@@ -144,14 +144,15 @@ void wlr_idle_inhibit_v1_destroy(struct wlr_idle_inhibit_manager_v1 *idle_inhibi
return;
}
- wl_list_remove(&idle_inhibit->display_destroy.link);
-
struct wlr_idle_inhibitor_v1 *inhibitor;
struct wlr_idle_inhibitor_v1 *tmp;
wl_list_for_each_safe(inhibitor, tmp, &idle_inhibit->inhibitors, link) {
idle_inhibitor_v1_destroy(inhibitor);
}
+ wlr_signal_emit_safe(&idle_inhibit->events.destroy, idle_inhibit);
+ wl_list_remove(&idle_inhibit->display_destroy.link);
+
struct wl_resource *resource;
struct wl_resource *tmp_resource;
wl_resource_for_each_safe(resource, tmp_resource, &idle_inhibit->resources) {
@@ -175,6 +176,7 @@ struct wlr_idle_inhibit_manager_v1 *wlr_idle_inhibit_v1_create(struct wl_display
idle_inhibit->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &idle_inhibit->display_destroy);
wl_signal_init(&idle_inhibit->events.new_inhibitor);
+ wl_signal_init(&idle_inhibit->events.destroy);
idle_inhibit->global = wl_global_create(display,
&zwp_idle_inhibit_manager_v1_interface, 1,
diff --git a/types/wlr_input_inhibitor.c b/types/wlr_input_inhibitor.c
index dc5175f8..fa692d6c 100644
--- a/types/wlr_input_inhibitor.c
+++ b/types/wlr_input_inhibitor.c
@@ -112,6 +112,7 @@ void wlr_input_inhibit_manager_destroy(
input_inhibitor_destroy(manager->active_client,
manager->active_inhibitor);
}
+ wlr_signal_emit_safe(&manager->events.destroy, manager);
wl_list_remove(&manager->display_destroy.link);
wl_global_destroy(manager->global);
free(manager);
@@ -143,6 +144,7 @@ struct wlr_input_inhibit_manager *wlr_input_inhibit_manager_create(
wl_signal_init(&manager->events.activate);
wl_signal_init(&manager->events.deactivate);
+ wl_signal_init(&manager->events.destroy);
manager->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &manager->display_destroy);
diff --git a/types/wlr_layer_shell.c b/types/wlr_layer_shell.c
index 5d610ece..52e5088e 100644
--- a/types/wlr_layer_shell.c
+++ b/types/wlr_layer_shell.c
@@ -449,6 +449,7 @@ struct wlr_layer_shell *wlr_layer_shell_create(struct wl_display *display) {
layer_shell->global = global;
wl_signal_init(&layer_shell->events.new_surface);
+ wl_signal_init(&layer_shell->events.destroy);
layer_shell->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &layer_shell->display_destroy);
@@ -464,6 +465,7 @@ void wlr_layer_shell_destroy(struct wlr_layer_shell *layer_shell) {
wl_resource_for_each_safe(client, tmp, &layer_shell->client_resources) {
wl_resource_destroy(client);
}
+ wlr_signal_emit_safe(&layer_shell->events.destroy, layer_shell);
wl_list_remove(&layer_shell->display_destroy.link);
wl_global_destroy(layer_shell->global);
free(layer_shell);
diff --git a/types/wlr_linux_dmabuf.c b/types/wlr_linux_dmabuf_v1.c
index 2d5259d8..f72e7c07 100644
--- a/types/wlr_linux_dmabuf.c
+++ b/types/wlr_linux_dmabuf_v1.c
@@ -4,7 +4,7 @@
#include <unistd.h>
#include <wayland-server.h>
#include <wlr/render/wlr_renderer.h>
-#include <wlr/types/wlr_linux_dmabuf.h>
+#include <wlr/types/wlr_linux_dmabuf_v1.h>
#include <wlr/util/log.h>
#include "linux-dmabuf-unstable-v1-protocol.h"
#include "util/signal.h"
@@ -20,13 +20,13 @@ static const struct wl_buffer_interface buffer_impl = {
.destroy = buffer_handle_destroy,
};
-bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource) {
+bool wlr_dmabuf_v1_resource_is_buffer(struct wl_resource *buffer_resource) {
if (!wl_resource_instance_of(buffer_resource, &wl_buffer_interface,
&buffer_impl)) {
return false;
}
- struct wlr_dmabuf_buffer *buffer =
+ struct wlr_dmabuf_v1_buffer *buffer =
wl_resource_get_user_data(buffer_resource);
if (buffer && buffer->buffer_resource && !buffer->params_resource &&
buffer->buffer_resource == buffer_resource) {
@@ -36,12 +36,12 @@ bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource) {
return false;
}
-struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_buffer_resource(
+struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_from_buffer_resource(
struct wl_resource *buffer_resource) {
assert(wl_resource_instance_of(buffer_resource, &wl_buffer_interface,
&buffer_impl));
- struct wlr_dmabuf_buffer *buffer =
+ struct wlr_dmabuf_v1_buffer *buffer =
wl_resource_get_user_data(buffer_resource);
assert(buffer);
assert(buffer->buffer_resource);
@@ -51,7 +51,7 @@ struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_buffer_resource(
return buffer;
}
-static void linux_dmabuf_buffer_destroy(struct wlr_dmabuf_buffer *buffer) {
+static void linux_dmabuf_buffer_destroy(struct wlr_dmabuf_v1_buffer *buffer) {
wlr_dmabuf_attributes_finish(&buffer->attributes);
free(buffer);
}
@@ -65,8 +65,8 @@ static void params_add(struct wl_client *client,
struct wl_resource *params_resource, int32_t fd,
uint32_t plane_idx, uint32_t offset, uint32_t stride,
uint32_t modifier_hi, uint32_t modifier_lo) {
- struct wlr_dmabuf_buffer *buffer =
- wlr_dmabuf_buffer_from_params_resource(params_resource);
+ struct wlr_dmabuf_v1_buffer *buffer =
+ wlr_dmabuf_v1_buffer_from_params_resource(params_resource);
if (!buffer) {
wl_resource_post_error(params_resource,
@@ -113,12 +113,12 @@ static void params_add(struct wl_client *client,
}
static void buffer_handle_resource_destroy(struct wl_resource *buffer_resource) {
- struct wlr_dmabuf_buffer *buffer =
- wlr_dmabuf_buffer_from_buffer_resource(buffer_resource);
+ struct wlr_dmabuf_v1_buffer *buffer =
+ wlr_dmabuf_v1_buffer_from_buffer_resource(buffer_resource);
linux_dmabuf_buffer_destroy(buffer);
}
-static bool check_import_dmabuf(struct wlr_dmabuf_buffer *buffer) {
+static bool check_import_dmabuf(struct wlr_dmabuf_v1_buffer *buffer) {
struct wlr_texture *texture =
wlr_texture_from_dmabuf(buffer->renderer, &buffer->attributes);
if (texture == NULL) {
@@ -140,8 +140,8 @@ static void params_create_common(struct wl_client *client,
"params was already used to create a wl_buffer");
return;
}
- struct wlr_dmabuf_buffer *buffer =
- wlr_dmabuf_buffer_from_params_resource(params_resource);
+ struct wlr_dmabuf_v1_buffer *buffer =
+ wlr_dmabuf_v1_buffer_from_params_resource(params_resource);
/* Switch the linux_dmabuf_buffer object from params resource to
* eventually wl_buffer resource. */
@@ -302,13 +302,13 @@ static const struct zwp_linux_buffer_params_v1_interface
.create_immed = params_create_immed,
};
-struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_params_resource(
+struct wlr_dmabuf_v1_buffer *wlr_dmabuf_v1_buffer_from_params_resource(
struct wl_resource *params_resource) {
assert(wl_resource_instance_of(params_resource,
&zwp_linux_buffer_params_v1_interface,
&linux_buffer_params_impl));
- struct wlr_dmabuf_buffer *buffer =
+ struct wlr_dmabuf_v1_buffer *buffer =
wl_resource_get_user_data(params_resource);
assert(buffer);
assert(buffer->params_resource);
@@ -319,24 +319,24 @@ struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_params_resource(
}
static void handle_params_destroy(struct wl_resource *params_resource) {
- /* Check for NULL since wlr_dmabuf_buffer_from_params_resource will choke */
+ /* Check for NULL since wlr_dmabuf_v1_buffer_from_params_resource will choke */
if (!wl_resource_get_user_data(params_resource)) {
return;
}
- struct wlr_dmabuf_buffer *buffer =
- wlr_dmabuf_buffer_from_params_resource(params_resource);
+ struct wlr_dmabuf_v1_buffer *buffer =
+ wlr_dmabuf_v1_buffer_from_params_resource(params_resource);
linux_dmabuf_buffer_destroy(buffer);
}
static void linux_dmabuf_create_params(struct wl_client *client,
struct wl_resource *linux_dmabuf_resource,
uint32_t params_id) {
- struct wlr_linux_dmabuf *linux_dmabuf =
- wlr_linux_dmabuf_from_resource(linux_dmabuf_resource);
+ struct wlr_linux_dmabuf_v1 *linux_dmabuf =
+ wlr_linux_dmabuf_v1_from_resource(linux_dmabuf_resource);
uint32_t version = wl_resource_get_version(linux_dmabuf_resource);
- struct wlr_dmabuf_buffer *buffer = calloc(1, sizeof *buffer);
+ struct wlr_dmabuf_v1_buffer *buffer = calloc(1, sizeof *buffer);
if (!buffer) {
goto err;
}
@@ -372,17 +372,17 @@ static const struct zwp_linux_dmabuf_v1_interface linux_dmabuf_impl = {
.create_params = linux_dmabuf_create_params,
};
-struct wlr_linux_dmabuf *wlr_linux_dmabuf_from_resource(
+struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_from_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &zwp_linux_dmabuf_v1_interface,
&linux_dmabuf_impl));
- struct wlr_linux_dmabuf *dmabuf = wl_resource_get_user_data(resource);
+ struct wlr_linux_dmabuf_v1 *dmabuf = wl_resource_get_user_data(resource);
assert(dmabuf);
return dmabuf;
}
-static void linux_dmabuf_send_modifiers(struct wlr_linux_dmabuf *linux_dmabuf,
+static void linux_dmabuf_send_modifiers(struct wlr_linux_dmabuf_v1 *linux_dmabuf,
struct wl_resource *resource) {
struct wlr_renderer *renderer = linux_dmabuf->renderer;
/*
@@ -428,7 +428,7 @@ static void linux_dmabuf_resource_destroy(struct wl_resource *resource) {
static void linux_dmabuf_bind(struct wl_client *client, void *data,
uint32_t version, uint32_t id) {
- struct wlr_linux_dmabuf *linux_dmabuf = data;
+ struct wlr_linux_dmabuf_v1 *linux_dmabuf = data;
struct wl_resource *resource = wl_resource_create(client,
&zwp_linux_dmabuf_v1_interface, version, id);
@@ -445,7 +445,7 @@ static void linux_dmabuf_bind(struct wl_client *client, void *data,
}
}
-void wlr_linux_dmabuf_destroy(struct wlr_linux_dmabuf *linux_dmabuf) {
+void wlr_linux_dmabuf_v1_destroy(struct wlr_linux_dmabuf_v1 *linux_dmabuf) {
if (!linux_dmabuf) {
return;
}
@@ -465,21 +465,21 @@ void wlr_linux_dmabuf_destroy(struct wlr_linux_dmabuf *linux_dmabuf) {
}
static void handle_display_destroy(struct wl_listener *listener, void *data) {
- struct wlr_linux_dmabuf *linux_dmabuf =
+ struct wlr_linux_dmabuf_v1 *linux_dmabuf =
wl_container_of(listener, linux_dmabuf, display_destroy);
- wlr_linux_dmabuf_destroy(linux_dmabuf);
+ wlr_linux_dmabuf_v1_destroy(linux_dmabuf);
}
static void handle_renderer_destroy(struct wl_listener *listener, void *data) {
- struct wlr_linux_dmabuf *linux_dmabuf =
+ struct wlr_linux_dmabuf_v1 *linux_dmabuf =
wl_container_of(listener, linux_dmabuf, renderer_destroy);
- wlr_linux_dmabuf_destroy(linux_dmabuf);
+ wlr_linux_dmabuf_v1_destroy(linux_dmabuf);
}
-struct wlr_linux_dmabuf *wlr_linux_dmabuf_create(struct wl_display *display,
+struct wlr_linux_dmabuf_v1 *wlr_linux_dmabuf_v1_create(struct wl_display *display,
struct wlr_renderer *renderer) {
- struct wlr_linux_dmabuf *linux_dmabuf =
- calloc(1, sizeof(struct wlr_linux_dmabuf));
+ struct wlr_linux_dmabuf_v1 *linux_dmabuf =
+ calloc(1, sizeof(struct wlr_linux_dmabuf_v1));
if (linux_dmabuf == NULL) {
wlr_log(WLR_ERROR, "could not create simple dmabuf manager");
return NULL;
diff --git a/types/wlr_output.c b/types/wlr_output.c
index a1d00c0c..abbdab9c 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -552,11 +552,12 @@ void wlr_output_schedule_frame(struct wlr_output *output) {
wl_event_loop_add_idle(ev, schedule_frame_handle_idle_timer, output);
}
-void wlr_output_set_gamma(struct wlr_output *output,
- uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b) {
- if (output->impl->set_gamma) {
- output->impl->set_gamma(output, size, r, g, b);
+bool wlr_output_set_gamma(struct wlr_output *output, uint32_t size,
+ uint16_t *r, uint16_t *g, uint16_t *b) {
+ if (!output->impl->set_gamma) {
+ return false;
}
+ return output->impl->set_gamma(output, size, r, g, b);
}
uint32_t wlr_output_get_gamma_size(struct wlr_output *output) {
@@ -767,7 +768,8 @@ bool wlr_output_cursor_set_image(struct wlr_output_cursor *cursor,
return true;
}
- wlr_log(WLR_DEBUG, "Falling back to software cursor");
+ wlr_log(WLR_DEBUG, "Falling back to software cursor on output '%s'",
+ cursor->output->name);
output_cursor_damage_whole(cursor);
return true;
}
diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c
index 5ad0c99e..e634d2b2 100644
--- a/types/wlr_output_layout.c
+++ b/types/wlr_output_layout.c
@@ -430,15 +430,20 @@ struct wlr_output *wlr_output_layout_get_center_output(
return wlr_output_layout_output_at(layout, dest_x, dest_y);
}
+enum distance_selection_method {
+ NEAREST,
+ FARTHEST
+};
-struct wlr_output *wlr_output_layout_adjacent_output(
+struct wlr_output *wlr_output_layout_output_in_direction(
struct wlr_output_layout *layout, enum wlr_direction direction,
- struct wlr_output *reference, double ref_lx, double ref_ly) {
+ struct wlr_output *reference, double ref_lx, double ref_ly,
+ enum distance_selection_method distance_method) {
assert(reference);
struct wlr_box *ref_box = wlr_output_layout_get_box(layout, reference);
- double min_distance = DBL_MAX;
+ double min_distance = (distance_method == NEAREST) ? DBL_MAX : DBL_MIN;
struct wlr_output *closest_output = NULL;
struct wlr_output_layout_output *l_output;
wl_list_for_each(l_output, &layout->outputs, link) {
@@ -471,10 +476,28 @@ struct wlr_output *wlr_output_layout_adjacent_output(
ref_lx, ref_ly, &x, &y);
double distance =
(x - ref_lx) * (x - ref_lx) + (y - ref_ly) * (y - ref_ly);
- if (distance < min_distance) {
+
+ if ((distance_method == NEAREST)
+ ? distance < min_distance
+ : distance > min_distance) {
min_distance = distance;
closest_output = l_output->output;
}
}
return closest_output;
}
+
+struct wlr_output *wlr_output_layout_adjacent_output(
+ struct wlr_output_layout *layout, enum wlr_direction direction,
+ struct wlr_output *reference, double ref_lx, double ref_ly) {
+ return wlr_output_layout_output_in_direction(layout, direction,
+ reference, ref_lx, ref_ly, NEAREST);
+}
+
+struct wlr_output *wlr_output_layout_farthest_output(
+ struct wlr_output_layout *layout, enum wlr_direction direction,
+ struct wlr_output *reference, double ref_lx, double ref_ly) {
+ return wlr_output_layout_output_in_direction(layout, direction,
+ reference, ref_lx, ref_ly, FARTHEST);
+}
+
diff --git a/types/wlr_primary_selection.c b/types/wlr_primary_selection.c
index 750f9ab4..e561852f 100644
--- a/types/wlr_primary_selection.c
+++ b/types/wlr_primary_selection.c
@@ -408,6 +408,8 @@ struct wlr_primary_selection_device_manager *
return NULL;
}
+ wl_signal_init(&manager->events.destroy);
+
manager->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &manager->display_destroy);
@@ -419,6 +421,7 @@ void wlr_primary_selection_device_manager_destroy(
if (manager == NULL) {
return;
}
+ wlr_signal_emit_safe(&manager->events.destroy, manager);
wl_list_remove(&manager->display_destroy.link);
// TODO: free resources
wl_global_destroy(manager->global);
diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c
index bd3dfe9a..4f044eba 100644
--- a/types/wlr_screencopy_v1.c
+++ b/types/wlr_screencopy_v1.c
@@ -5,6 +5,7 @@
#include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/backend.h>
#include "wlr-screencopy-unstable-v1-protocol.h"
+#include "util/signal.h"
#define SCREENCOPY_MANAGER_VERSION 1
@@ -295,6 +296,8 @@ struct wlr_screencopy_manager_v1 *wlr_screencopy_manager_v1_create(
wl_list_init(&manager->resources);
wl_list_init(&manager->frames);
+ wl_signal_init(&manager->events.destroy);
+
manager->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &manager->display_destroy);
@@ -306,6 +309,7 @@ void wlr_screencopy_manager_v1_destroy(
if (manager == NULL) {
return;
}
+ wlr_signal_emit_safe(&manager->events.destroy, manager);
wl_list_remove(&manager->display_destroy.link);
struct wlr_screencopy_frame_v1 *frame, *tmp_frame;
wl_list_for_each_safe(frame, tmp_frame, &manager->frames, link) {
diff --git a/types/wlr_screenshooter.c b/types/wlr_screenshooter.c
index 37b70538..c85e6ba5 100644
--- a/types/wlr_screenshooter.c
+++ b/types/wlr_screenshooter.c
@@ -8,6 +8,7 @@
#include <wlr/types/wlr_screenshooter.h>
#include <wlr/util/log.h>
#include "screenshooter-protocol.h"
+#include "util/signal.h"
static struct wlr_screenshot *screenshot_from_resource(
struct wl_resource *resource) {
@@ -177,6 +178,7 @@ void wlr_screenshooter_destroy(struct wlr_screenshooter *screenshooter) {
wl_list_for_each_safe(screenshot, tmp, &screenshooter->screenshots, link) {
screenshot_destroy(screenshot);
}
+ wlr_signal_emit_safe(&screenshooter->events.destroy, screenshooter);
wl_global_destroy(screenshooter->global);
free(screenshooter);
}
@@ -195,6 +197,7 @@ struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display) {
}
wl_list_init(&screenshooter->screenshots);
+ wl_signal_init(&screenshooter->events.destroy);
screenshooter->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &screenshooter->display_destroy);
diff --git a/types/wlr_server_decoration.c b/types/wlr_server_decoration.c
index fceb1638..fd92fd04 100644
--- a/types/wlr_server_decoration.c
+++ b/types/wlr_server_decoration.c
@@ -167,12 +167,13 @@ void wlr_server_decoration_manager_destroy(
if (manager == NULL) {
return;
}
- wl_list_remove(&manager->display_destroy.link);
struct wlr_server_decoration *decoration, *tmp_decoration;
wl_list_for_each_safe(decoration, tmp_decoration, &manager->decorations,
link) {
server_decoration_destroy(decoration);
}
+ wlr_signal_emit_safe(&manager->events.destroy, manager);
+ wl_list_remove(&manager->display_destroy.link);
struct wl_resource *resource, *tmp_resource;
wl_resource_for_each_safe(resource, tmp_resource, &manager->resources) {
server_decoration_manager_destroy_resource(resource);
@@ -205,6 +206,7 @@ struct wlr_server_decoration_manager *wlr_server_decoration_manager_create(
wl_list_init(&manager->resources);
wl_list_init(&manager->decorations);
wl_signal_init(&manager->events.new_decoration);
+ wl_signal_init(&manager->events.destroy);
manager->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &manager->display_destroy);
diff --git a/types/wlr_surface.c b/types/wlr_surface.c
index f2b248ca..ab1dfc2d 100644
--- a/types/wlr_surface.c
+++ b/types/wlr_surface.c
@@ -360,10 +360,14 @@ static void surface_update_opaque_region(struct wlr_surface *surface) {
}
static void surface_commit_pending(struct wlr_surface *surface) {
- bool invalid_buffer = surface->pending.committed & WLR_SURFACE_STATE_BUFFER;
-
surface_state_finalize(surface, &surface->pending);
+ if (surface->role && surface->role->precommit) {
+ surface->role->precommit(surface);
+ }
+
+ bool invalid_buffer = surface->pending.committed & WLR_SURFACE_STATE_BUFFER;
+
surface->sx += surface->pending.dx;
surface->sy += surface->pending.dy;
surface_update_damage(&surface->buffer_damage,
diff --git a/types/wlr_virtual_keyboard_v1.c b/types/wlr_virtual_keyboard_v1.c
index cf7be0ee..e5463295 100644
--- a/types/wlr_virtual_keyboard_v1.c
+++ b/types/wlr_virtual_keyboard_v1.c
@@ -1,4 +1,4 @@
-#define _POSIX_C_SOURCE 1
+#define _POSIX_C_SOURCE 199309L
#include <assert.h>
#include <stdlib.h>
#include <sys/mman.h>
@@ -99,7 +99,7 @@ static void virtual_keyboard_destroy_resource(struct wl_resource *resource) {
virtual_keyboard_from_resource(resource);
wlr_signal_emit_safe(&keyboard->events.destroy, keyboard);
wl_list_remove(&keyboard->link);
- wlr_keyboard_destroy(keyboard->input_device.keyboard);
+ wlr_input_device_destroy(&keyboard->input_device);
free(keyboard);
}
@@ -223,6 +223,7 @@ struct wlr_virtual_keyboard_manager_v1*
wl_list_init(&manager->virtual_keyboards);
wl_signal_init(&manager->events.new_virtual_keyboard);
+ wl_signal_init(&manager->events.destroy);
manager->global = wl_global_create(display,
&zwp_virtual_keyboard_manager_v1_interface, 1, manager,
virtual_keyboard_manager_bind);
@@ -231,6 +232,7 @@ struct wlr_virtual_keyboard_manager_v1*
void wlr_virtual_keyboard_manager_v1_destroy(
struct wlr_virtual_keyboard_manager_v1 *manager) {
+ wlr_signal_emit_safe(&manager->events.destroy, manager);
wl_list_remove(&manager->display_destroy.link);
wl_global_destroy(manager->global);
struct wl_resource *resource, *resource_tmp;
diff --git a/types/wlr_xdg_decoration_v1.c b/types/wlr_xdg_decoration_v1.c
new file mode 100644
index 00000000..f5182daa
--- /dev/null
+++ b/types/wlr_xdg_decoration_v1.c
@@ -0,0 +1,304 @@
+#include <assert.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wlr/types/wlr_xdg_decoration_v1.h>
+#include <wlr/util/log.h>
+#include "util/signal.h"
+#include "xdg-decoration-unstable-v1-protocol.h"
+
+#define DECORATION_MANAGER_VERSION 1
+
+static const struct zxdg_toplevel_decoration_v1_interface
+ toplevel_decoration_impl;
+
+static struct wlr_xdg_toplevel_decoration_v1 *toplevel_decoration_from_resource(
+ struct wl_resource *resource) {
+ assert(wl_resource_instance_of(resource,
+ &zxdg_toplevel_decoration_v1_interface, &toplevel_decoration_impl));
+ return wl_resource_get_user_data(resource);
+}
+
+static void toplevel_decoration_handle_destroy(struct wl_client *client,
+ struct wl_resource *resource) {
+ wl_resource_destroy(resource);
+}
+
+static void toplevel_decoration_handle_set_mode(struct wl_client *client,
+ struct wl_resource *resource,
+ enum zxdg_toplevel_decoration_v1_mode mode) {
+ struct wlr_xdg_toplevel_decoration_v1 *decoration =
+ toplevel_decoration_from_resource(resource);
+
+ decoration->client_pending_mode =
+ (enum wlr_xdg_toplevel_decoration_v1_mode)mode;
+ wlr_signal_emit_safe(&decoration->events.request_mode, decoration);
+}
+
+static void toplevel_decoration_handle_unset_mode(struct wl_client *client,
+ struct wl_resource *resource) {
+ struct wlr_xdg_toplevel_decoration_v1 *decoration =
+ toplevel_decoration_from_resource(resource);
+
+ decoration->client_pending_mode = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_NONE;
+ wlr_signal_emit_safe(&decoration->events.request_mode, decoration);
+}
+
+static const struct zxdg_toplevel_decoration_v1_interface
+ toplevel_decoration_impl = {
+ .destroy = toplevel_decoration_handle_destroy,
+ .set_mode = toplevel_decoration_handle_set_mode,
+ .unset_mode = toplevel_decoration_handle_unset_mode,
+};
+
+uint32_t wlr_xdg_toplevel_decoration_v1_set_mode(
+ struct wlr_xdg_toplevel_decoration_v1 *decoration,
+ enum wlr_xdg_toplevel_decoration_v1_mode mode) {
+ assert(mode != WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_NONE);
+ decoration->server_pending_mode = mode;
+ return wlr_xdg_surface_schedule_configure(decoration->surface);
+}
+
+static void toplevel_decoration_handle_resource_destroy(
+ struct wl_resource *resource) {
+ struct wlr_xdg_toplevel_decoration_v1 *decoration =
+ toplevel_decoration_from_resource(resource);
+ wlr_signal_emit_safe(&decoration->events.destroy, decoration);
+ wl_list_remove(&decoration->surface_commit.link);
+ wl_list_remove(&decoration->surface_destroy.link);
+ wl_list_remove(&decoration->surface_configure.link);
+ wl_list_remove(&decoration->surface_ack_configure.link);
+ struct wlr_xdg_toplevel_decoration_v1_configure *configure, *tmp;
+ wl_list_for_each_safe(configure, tmp, &decoration->configure_list, link) {
+ free(configure);
+ }
+ wl_list_remove(&decoration->link);
+ free(decoration);
+}
+
+static void toplevel_decoration_handle_surface_destroy(
+ struct wl_listener *listener, void *data) {
+ struct wlr_xdg_toplevel_decoration_v1 *decoration =
+ wl_container_of(listener, decoration, surface_destroy);
+ wl_resource_destroy(decoration->resource);
+}
+
+static void toplevel_decoration_handle_surface_configure(
+ struct wl_listener *listener, void *data) {
+ struct wlr_xdg_toplevel_decoration_v1 *decoration =
+ wl_container_of(listener, decoration, surface_configure);
+ struct wlr_xdg_surface_configure *surface_configure = data;
+
+ if (decoration->current_mode == decoration->server_pending_mode) {
+ return;
+ }
+
+ struct wlr_xdg_toplevel_decoration_v1_configure *configure =
+ calloc(1, sizeof(struct wlr_xdg_toplevel_decoration_v1_configure));
+ if (configure == NULL) {
+ return;
+ }
+ configure->surface_configure = surface_configure;
+ configure->mode = decoration->server_pending_mode;
+ wl_list_insert(decoration->configure_list.prev, &configure->link);
+
+ zxdg_toplevel_decoration_v1_send_configure(decoration->resource,
+ configure->mode);
+}
+
+static void toplevel_decoration_handle_surface_ack_configure(
+ struct wl_listener *listener, void *data) {
+ struct wlr_xdg_toplevel_decoration_v1 *decoration =
+ wl_container_of(listener, decoration, surface_ack_configure);
+ struct wlr_xdg_surface_configure *surface_configure = data;
+
+ bool found = false;
+ struct wlr_xdg_toplevel_decoration_v1_configure *configure;
+ wl_list_for_each(configure, &decoration->configure_list, link) {
+ if (configure->surface_configure == surface_configure) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return;
+ }
+
+ decoration->current_mode = configure->mode;
+
+ wl_list_remove(&configure->link);
+ free(configure);
+}
+
+static void toplevel_decoration_handle_surface_commit(
+ struct wl_listener *listener, void *data) {
+ struct wlr_xdg_toplevel_decoration_v1 *decoration =
+ wl_container_of(listener, decoration, surface_commit);
+ struct wlr_xdg_decoration_manager_v1 *manager = decoration->manager;
+
+ if (decoration->surface->added) {
+ wl_list_remove(&decoration->surface_commit.link);
+ wl_list_init(&decoration->surface_commit.link);
+
+ decoration->added = true;
+ wlr_signal_emit_safe(&manager->events.new_toplevel_decoration,
+ decoration);
+ }
+}
+
+
+static const struct zxdg_decoration_manager_v1_interface decoration_manager_impl;
+
+static struct wlr_xdg_decoration_manager_v1 *
+ decoration_manager_from_resource(struct wl_resource *resource) {
+ assert(wl_resource_instance_of(resource,
+ &zxdg_decoration_manager_v1_interface,
+ &decoration_manager_impl));
+ return wl_resource_get_user_data(resource);
+}
+
+static void decoration_manager_handle_get_toplevel_decoration(
+ struct wl_client *client, struct wl_resource *manager_resource,
+ uint32_t id, struct wl_resource *toplevel_resource) {
+ struct wlr_xdg_decoration_manager_v1 *manager =
+ decoration_manager_from_resource(manager_resource);
+ struct wlr_xdg_surface *surface =
+ wlr_xdg_surface_from_toplevel_resource(toplevel_resource);
+ assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
+
+ if (wlr_surface_has_buffer(surface->surface)) {
+ wl_resource_post_error(manager_resource,
+ ZXDG_TOPLEVEL_DECORATION_V1_ERROR_UNCONFIGURED_BUFFER,
+ "xdg_toplevel_decoration must not have a buffer at creation");
+ return;
+ }
+
+ struct wlr_xdg_toplevel_decoration_v1 *decoration =
+ calloc(1, sizeof(struct wlr_xdg_toplevel_decoration_v1));
+ if (decoration == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ decoration->manager = manager;
+ decoration->surface = surface;
+
+ uint32_t version = wl_resource_get_version(manager_resource);
+ decoration->resource = wl_resource_create(client,
+ &zxdg_toplevel_decoration_v1_interface, version, id);
+ if (decoration->resource == NULL) {
+ free(decoration);
+ wl_client_post_no_memory(client);
+ return;
+ }
+ wl_resource_set_implementation(decoration->resource,
+ &toplevel_decoration_impl, decoration,
+ toplevel_decoration_handle_resource_destroy);
+
+ wlr_log(WLR_DEBUG, "new xdg_toplevel_decoration %p (res %p)", decoration,
+ decoration->resource);
+
+ wl_list_init(&decoration->configure_list);
+ wl_signal_init(&decoration->events.destroy);
+ wl_signal_init(&decoration->events.request_mode);
+
+ wl_signal_add(&surface->events.destroy, &decoration->surface_destroy);
+ decoration->surface_destroy.notify =
+ toplevel_decoration_handle_surface_destroy;
+ wl_signal_add(&surface->events.configure, &decoration->surface_configure);
+ decoration->surface_configure.notify =
+ toplevel_decoration_handle_surface_configure;
+ wl_signal_add(&surface->events.ack_configure,
+ &decoration->surface_ack_configure);
+ decoration->surface_ack_configure.notify =
+ toplevel_decoration_handle_surface_ack_configure;
+ wl_list_init(&decoration->surface_commit.link);
+
+ wl_list_insert(&manager->decorations, &decoration->link);
+
+ if (surface->added) {
+ decoration->added = true;
+ wlr_signal_emit_safe(&manager->events.new_toplevel_decoration,
+ decoration);
+ } else {
+ wl_list_remove(&decoration->surface_commit.link);
+ wl_signal_add(&surface->surface->events.commit,
+ &decoration->surface_commit);
+ decoration->surface_commit.notify =
+ toplevel_decoration_handle_surface_commit;
+ }
+}
+
+static const struct zxdg_decoration_manager_v1_interface
+ decoration_manager_impl = {
+ .get_toplevel_decoration = decoration_manager_handle_get_toplevel_decoration,
+};
+
+void decoration_manager_handle_resource_destroy(struct wl_resource *resource) {
+ wl_list_remove(wl_resource_get_link(resource));
+}
+
+static void decoration_manager_bind(struct wl_client *client, void *data,
+ uint32_t version, uint32_t id) {
+ struct wlr_xdg_decoration_manager_v1 *manager = data;
+
+ struct wl_resource *resource = wl_resource_create(client,
+ &zxdg_decoration_manager_v1_interface, version, id);
+ if (resource == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ wl_resource_set_implementation(resource, &decoration_manager_impl,
+ manager, decoration_manager_handle_resource_destroy);
+
+ wl_list_insert(&manager->resources, wl_resource_get_link(resource));
+}
+
+static void handle_display_destroy(struct wl_listener *listener, void *data) {
+ struct wlr_xdg_decoration_manager_v1 *manager =
+ wl_container_of(listener, manager, display_destroy);
+ wlr_xdg_decoration_manager_v1_destroy(manager);
+}
+
+struct wlr_xdg_decoration_manager_v1 *
+ wlr_xdg_decoration_manager_v1_create(struct wl_display *display) {
+ struct wlr_xdg_decoration_manager_v1 *manager =
+ calloc(1, sizeof(struct wlr_xdg_decoration_manager_v1));
+ if (manager == NULL) {
+ return NULL;
+ }
+ manager->global = wl_global_create(display,
+ &zxdg_decoration_manager_v1_interface, DECORATION_MANAGER_VERSION,
+ manager, decoration_manager_bind);
+ if (manager->global == NULL) {
+ free(manager);
+ return NULL;
+ }
+ wl_list_init(&manager->resources);
+ wl_list_init(&manager->decorations);
+ wl_signal_init(&manager->events.new_toplevel_decoration);
+ wl_signal_init(&manager->events.destroy);
+
+ manager->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &manager->display_destroy);
+
+ return manager;
+}
+
+void wlr_xdg_decoration_manager_v1_destroy(
+ struct wlr_xdg_decoration_manager_v1 *manager) {
+ if (manager == NULL) {
+ return;
+ }
+ wlr_signal_emit_safe(&manager->events.destroy, manager);
+ wl_list_remove(&manager->display_destroy.link);
+ struct wlr_xdg_toplevel_decoration_v1 *decoration, *tmp_decoration;
+ wl_list_for_each_safe(decoration, tmp_decoration, &manager->decorations,
+ link) {
+ wl_resource_destroy(decoration->resource);
+ }
+ struct wl_resource *resource, *tmp_resource;
+ wl_resource_for_each_safe(resource, tmp_resource, &manager->resources) {
+ wl_resource_destroy(resource);
+ }
+ wl_global_destroy(manager->global);
+ free(manager);
+}
diff --git a/types/wlr_xdg_output.c b/types/wlr_xdg_output.c
index 1a3bba2c..8c7a1fcb 100644
--- a/types/wlr_xdg_output.c
+++ b/types/wlr_xdg_output.c
@@ -6,6 +6,7 @@
#include <wlr/types/wlr_xdg_output.h>
#include <wlr/util/log.h>
#include "xdg-output-unstable-v1-protocol.h"
+#include "util/signal.h"
#define OUTPUT_MANAGER_VERSION 2
@@ -199,7 +200,7 @@ static void handle_layout_change(struct wl_listener *listener, void *data) {
static void handle_layout_destroy(struct wl_listener *listener, void *data) {
struct wlr_xdg_output_manager *manager =
- wl_container_of(listener, manager, layout_change);
+ wl_container_of(listener, manager, layout_destroy);
wlr_xdg_output_manager_destroy(manager);
}
@@ -227,6 +228,8 @@ struct wlr_xdg_output_manager *wlr_xdg_output_manager_create(
add_output(manager, layout_output);
}
+ wl_signal_init(&manager->events.destroy);
+
manager->layout_add.notify = handle_layout_add;
wl_signal_add(&layout->events.add, &manager->layout_add);
manager->layout_change.notify = handle_layout_change;
@@ -245,6 +248,7 @@ void wlr_xdg_output_manager_destroy(struct wlr_xdg_output_manager *manager) {
wl_resource_for_each_safe(resource, resource_tmp, &manager->resources) {
wl_resource_destroy(resource);
}
+ wlr_signal_emit_safe(&manager->events.destroy, manager);
wl_list_remove(&manager->layout_add.link);
wl_list_remove(&manager->layout_change.link);
wl_list_remove(&manager->layout_destroy.link);
diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c
index 26d248e1..b3409261 100644
--- a/types/xdg_shell/wlr_xdg_popup.c
+++ b/types/xdg_shell/wlr_xdg_popup.c
@@ -214,7 +214,8 @@ static void xdg_popup_handle_resource_destroy(struct wl_resource *resource) {
const struct wlr_surface_role xdg_popup_surface_role = {
.name = "xdg_popup",
- .commit = handle_xdg_surface_committed,
+ .commit = handle_xdg_surface_commit,
+ .precommit = handle_xdg_surface_precommit,
};
void create_xdg_popup(struct wlr_xdg_surface *xdg_surface,
diff --git a/types/xdg_shell/wlr_xdg_shell.c b/types/xdg_shell/wlr_xdg_shell.c
index 601e728c..58dc376c 100644
--- a/types/xdg_shell/wlr_xdg_shell.c
+++ b/types/xdg_shell/wlr_xdg_shell.c
@@ -155,6 +155,7 @@ struct wlr_xdg_shell *wlr_xdg_shell_create(struct wl_display *display) {
xdg_shell->global = global;
wl_signal_init(&xdg_shell->events.new_surface);
+ wl_signal_init(&xdg_shell->events.destroy);
xdg_shell->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &xdg_shell->display_destroy);
@@ -166,6 +167,7 @@ void wlr_xdg_shell_destroy(struct wlr_xdg_shell *xdg_shell) {
if (!xdg_shell) {
return;
}
+ wlr_signal_emit_safe(&xdg_shell->events.destroy, xdg_shell);
wl_list_remove(&xdg_shell->display_destroy.link);
wl_global_destroy(xdg_shell->global);
free(xdg_shell);
diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c
index dc98a3a5..e32b7f18 100644
--- a/types/xdg_shell/wlr_xdg_surface.c
+++ b/types/xdg_shell/wlr_xdg_surface.c
@@ -111,6 +111,7 @@ static void xdg_surface_handle_ack_configure(struct wl_client *client,
struct wlr_xdg_surface_configure *configure, *tmp;
wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
if (configure->serial < serial) {
+ wlr_signal_emit_safe(&surface->events.ack_configure, configure);
xdg_surface_configure_destroy(configure);
} else if (configure->serial == serial) {
found = true;
@@ -140,6 +141,7 @@ static void xdg_surface_handle_ack_configure(struct wl_client *client,
surface->configured = true;
surface->configure_serial = serial;
+ wlr_signal_emit_safe(&surface->events.ack_configure, configure);
xdg_surface_configure_destroy(configure);
}
@@ -157,6 +159,7 @@ static void surface_send_configure(void *user_data) {
wl_list_insert(surface->configure_list.prev, &configure->link);
configure->serial = surface->configure_next_serial;
+ configure->surface = surface;
switch (surface->role) {
case WLR_XDG_SURFACE_ROLE_NONE:
@@ -174,26 +177,15 @@ static void surface_send_configure(void *user_data) {
break;
}
+ wlr_signal_emit_safe(&surface->events.configure, configure);
+
xdg_surface_send_configure(surface->resource, configure->serial);
}
-uint32_t schedule_xdg_surface_configure(
- struct wlr_xdg_surface *surface) {
+static uint32_t schedule_configure(struct wlr_xdg_surface *surface,
+ bool pending_same) {
struct wl_display *display = wl_client_get_display(surface->client->client);
struct wl_event_loop *loop = wl_display_get_event_loop(display);
- bool pending_same = false;
-
- switch (surface->role) {
- case WLR_XDG_SURFACE_ROLE_NONE:
- assert(0 && "not reached");
- break;
- case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
- pending_same =
- compare_xdg_surface_toplevel_state(surface->toplevel);
- break;
- case WLR_XDG_SURFACE_ROLE_POPUP:
- break;
- }
if (surface->configure_idle != NULL) {
if (!pending_same) {
@@ -218,6 +210,27 @@ uint32_t schedule_xdg_surface_configure(
}
}
+uint32_t schedule_xdg_surface_configure(struct wlr_xdg_surface *surface) {
+ bool pending_same = false;
+
+ switch (surface->role) {
+ case WLR_XDG_SURFACE_ROLE_NONE:
+ assert(0 && "not reached");
+ break;
+ case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
+ pending_same = compare_xdg_surface_toplevel_state(surface->toplevel);
+ break;
+ case WLR_XDG_SURFACE_ROLE_POPUP:
+ break;
+ }
+
+ return schedule_configure(surface, pending_same);
+}
+
+uint32_t wlr_xdg_surface_schedule_configure(struct wlr_xdg_surface *surface) {
+ return schedule_configure(surface, false);
+}
+
static void xdg_surface_handle_get_popup(struct wl_client *client,
struct wl_resource *resource, uint32_t id,
struct wl_resource *parent_resource,
@@ -313,7 +326,7 @@ static void xdg_surface_handle_surface_commit(struct wl_listener *listener,
}
}
-void handle_xdg_surface_committed(struct wlr_surface *wlr_surface) {
+void handle_xdg_surface_commit(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface *surface =
wlr_xdg_surface_from_wlr_surface(wlr_surface);
if (surface == NULL) {
@@ -355,6 +368,22 @@ void handle_xdg_surface_committed(struct wlr_surface *wlr_surface) {
}
}
+void handle_xdg_surface_precommit(struct wlr_surface *wlr_surface) {
+ struct wlr_xdg_surface *surface =
+ wlr_xdg_surface_from_wlr_surface(wlr_surface);
+ if (surface == NULL) {
+ return;
+ }
+
+ if (wlr_surface->pending.committed & WLR_SURFACE_STATE_BUFFER &&
+ wlr_surface->pending.buffer_resource == NULL) {
+ // This is a NULL commit
+ if (surface->configured && surface->mapped) {
+ unmap_xdg_surface(surface);
+ }
+ }
+}
+
static void xdg_surface_handle_surface_destroy(struct wl_listener *listener,
void *data) {
struct wlr_xdg_surface *xdg_surface =
@@ -401,6 +430,8 @@ struct wlr_xdg_surface *create_xdg_surface(
wl_signal_init(&xdg_surface->events.new_popup);
wl_signal_init(&xdg_surface->events.map);
wl_signal_init(&xdg_surface->events.unmap);
+ wl_signal_init(&xdg_surface->events.configure);
+ wl_signal_init(&xdg_surface->events.ack_configure);
wl_signal_add(&xdg_surface->surface->events.destroy,
&xdg_surface->surface_destroy);
diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c
index f04aa654..77398c7e 100644
--- a/types/xdg_shell/wlr_xdg_toplevel.c
+++ b/types/xdg_shell/wlr_xdg_toplevel.c
@@ -200,7 +200,7 @@ void handle_xdg_surface_toplevel_committed(struct wlr_xdg_surface *surface) {
static const struct xdg_toplevel_interface xdg_toplevel_implementation;
-static struct wlr_xdg_surface *xdg_surface_from_xdg_toplevel_resource(
+struct wlr_xdg_surface *wlr_xdg_surface_from_toplevel_resource(
struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &xdg_toplevel_interface,
&xdg_toplevel_implementation));
@@ -210,11 +210,11 @@ static struct wlr_xdg_surface *xdg_surface_from_xdg_toplevel_resource(
static void xdg_toplevel_handle_set_parent(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *parent_resource) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
struct wlr_xdg_surface *parent = NULL;
if (parent_resource != NULL) {
- parent = xdg_surface_from_xdg_toplevel_resource(parent_resource);
+ parent = wlr_xdg_surface_from_toplevel_resource(parent_resource);
}
surface->toplevel->parent = parent;
@@ -224,7 +224,7 @@ static void xdg_toplevel_handle_set_parent(struct wl_client *client,
static void xdg_toplevel_handle_set_title(struct wl_client *client,
struct wl_resource *resource, const char *title) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
char *tmp;
tmp = strdup(title);
@@ -234,12 +234,13 @@ static void xdg_toplevel_handle_set_title(struct wl_client *client,
free(surface->toplevel->title);
surface->toplevel->title = tmp;
+ wlr_signal_emit_safe(&surface->toplevel->events.set_title, surface);
}
static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
struct wl_resource *resource, const char *app_id) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
char *tmp;
tmp = strdup(app_id);
@@ -249,13 +250,14 @@ static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
free(surface->toplevel->app_id);
surface->toplevel->app_id = tmp;
+ wlr_signal_emit_safe(&surface->toplevel->events.set_app_id, surface);
}
static void xdg_toplevel_handle_show_window_menu(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial, int32_t x, int32_t y) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
struct wlr_seat_client *seat =
wlr_seat_client_from_resource(seat_resource);
@@ -286,7 +288,7 @@ static void xdg_toplevel_handle_move(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
struct wlr_seat_client *seat =
wlr_seat_client_from_resource(seat_resource);
@@ -315,7 +317,7 @@ static void xdg_toplevel_handle_resize(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial, uint32_t edges) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
struct wlr_seat_client *seat =
wlr_seat_client_from_resource(seat_resource);
@@ -344,7 +346,7 @@ static void xdg_toplevel_handle_resize(struct wl_client *client,
static void xdg_toplevel_handle_set_max_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
surface->toplevel->client_pending.max_width = width;
surface->toplevel->client_pending.max_height = height;
}
@@ -352,7 +354,7 @@ static void xdg_toplevel_handle_set_max_size(struct wl_client *client,
static void xdg_toplevel_handle_set_min_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
surface->toplevel->client_pending.min_width = width;
surface->toplevel->client_pending.min_height = height;
}
@@ -360,7 +362,7 @@ static void xdg_toplevel_handle_set_min_size(struct wl_client *client,
static void xdg_toplevel_handle_set_maximized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
surface->toplevel->client_pending.maximized = true;
wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface);
}
@@ -368,7 +370,7 @@ static void xdg_toplevel_handle_set_maximized(struct wl_client *client,
static void xdg_toplevel_handle_unset_maximized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
surface->toplevel->client_pending.maximized = false;
wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface);
}
@@ -376,7 +378,7 @@ static void xdg_toplevel_handle_unset_maximized(struct wl_client *client,
static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *output_resource) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
struct wlr_output *output = NULL;
if (output_resource != NULL) {
@@ -397,7 +399,7 @@ static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
surface->toplevel->client_pending.fullscreen = false;
@@ -413,7 +415,7 @@ static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
static void xdg_toplevel_handle_set_minimized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
wlr_signal_emit_safe(&surface->toplevel->events.request_minimize, surface);
}
@@ -441,7 +443,7 @@ static const struct xdg_toplevel_interface xdg_toplevel_implementation = {
static void xdg_toplevel_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
- xdg_surface_from_xdg_toplevel_resource(resource);
+ wlr_xdg_surface_from_toplevel_resource(resource);
if (surface != NULL) {
destroy_xdg_toplevel(surface);
}
@@ -449,7 +451,8 @@ static void xdg_toplevel_handle_resource_destroy(struct wl_resource *resource) {
const struct wlr_surface_role xdg_toplevel_surface_role = {
.name = "xdg_toplevel",
- .commit = handle_xdg_surface_committed,
+ .commit = handle_xdg_surface_commit,
+ .precommit = handle_xdg_surface_precommit,
};
void create_xdg_toplevel(struct wlr_xdg_surface *xdg_surface,
@@ -471,6 +474,8 @@ void create_xdg_toplevel(struct wlr_xdg_surface *xdg_surface,
wl_signal_init(&xdg_surface->toplevel->events.request_resize);
wl_signal_init(&xdg_surface->toplevel->events.request_show_window_menu);
wl_signal_init(&xdg_surface->toplevel->events.set_parent);
+ wl_signal_init(&xdg_surface->toplevel->events.set_title);
+ wl_signal_init(&xdg_surface->toplevel->events.set_app_id);
xdg_surface->role = WLR_XDG_SURFACE_ROLE_TOPLEVEL;
xdg_surface->toplevel->base = xdg_surface;
diff --git a/types/xdg_shell_v6/wlr_xdg_popup_v6.c b/types/xdg_shell_v6/wlr_xdg_popup_v6.c
index 59af020f..097e0253 100644
--- a/types/xdg_shell_v6/wlr_xdg_popup_v6.c
+++ b/types/xdg_shell_v6/wlr_xdg_popup_v6.c
@@ -251,7 +251,8 @@ void handle_xdg_surface_v6_popup_committed(struct wlr_xdg_surface_v6 *surface) {
const struct wlr_surface_role xdg_popup_v6_surface_role = {
.name = "xdg_popup_v6",
- .commit = handle_xdg_surface_v6_committed,
+ .commit = handle_xdg_surface_v6_commit,
+ .precommit = handle_xdg_surface_v6_precommit,
};
void create_xdg_popup_v6(struct wlr_xdg_surface_v6 *xdg_surface,
diff --git a/types/xdg_shell_v6/wlr_xdg_shell_v6.c b/types/xdg_shell_v6/wlr_xdg_shell_v6.c
index d61b5dc2..fce8e96a 100644
--- a/types/xdg_shell_v6/wlr_xdg_shell_v6.c
+++ b/types/xdg_shell_v6/wlr_xdg_shell_v6.c
@@ -156,6 +156,7 @@ struct wlr_xdg_shell_v6 *wlr_xdg_shell_v6_create(struct wl_display *display) {
xdg_shell->global = global;
wl_signal_init(&xdg_shell->events.new_surface);
+ wl_signal_init(&xdg_shell->events.destroy);
xdg_shell->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &xdg_shell->display_destroy);
@@ -167,6 +168,7 @@ void wlr_xdg_shell_v6_destroy(struct wlr_xdg_shell_v6 *xdg_shell) {
if (!xdg_shell) {
return;
}
+ wlr_signal_emit_safe(&xdg_shell->events.destroy, xdg_shell);
wl_list_remove(&xdg_shell->display_destroy.link);
wl_global_destroy(xdg_shell->global);
free(xdg_shell);
diff --git a/types/xdg_shell_v6/wlr_xdg_surface_v6.c b/types/xdg_shell_v6/wlr_xdg_surface_v6.c
index ca729c48..c4007c71 100644
--- a/types/xdg_shell_v6/wlr_xdg_surface_v6.c
+++ b/types/xdg_shell_v6/wlr_xdg_surface_v6.c
@@ -371,7 +371,7 @@ static void xdg_surface_handle_surface_commit(struct wl_listener *listener,
}
}
-void handle_xdg_surface_v6_committed(struct wlr_surface *wlr_surface) {
+void handle_xdg_surface_v6_commit(struct wlr_surface *wlr_surface) {
struct wlr_xdg_surface_v6 *surface =
wlr_xdg_surface_v6_from_wlr_surface(wlr_surface);
if (surface == NULL) {
@@ -407,9 +407,21 @@ void handle_xdg_surface_v6_committed(struct wlr_surface *wlr_surface) {
surface->mapped = true;
wlr_signal_emit_safe(&surface->events.map, surface);
}
- if (surface->configured && !wlr_surface_has_buffer(surface->surface) &&
- surface->mapped) {
- unmap_xdg_surface_v6(surface);
+}
+
+void handle_xdg_surface_v6_precommit(struct wlr_surface *wlr_surface) {
+ struct wlr_xdg_surface_v6 *surface =
+ wlr_xdg_surface_v6_from_wlr_surface(wlr_surface);
+ if (surface == NULL) {
+ return;
+ }
+
+ if (wlr_surface->pending.committed & WLR_SURFACE_STATE_BUFFER &&
+ wlr_surface->pending.buffer_resource == NULL) {
+ // This is a NULL commit
+ if (surface->configured && surface->mapped) {
+ unmap_xdg_surface_v6(surface);
+ }
}
}
diff --git a/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c b/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c
index 43ca99f0..297f49f5 100644
--- a/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c
+++ b/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c
@@ -57,6 +57,7 @@ static void xdg_toplevel_handle_set_title(struct wl_client *client,
free(surface->toplevel->title);
surface->toplevel->title = tmp;
+ wlr_signal_emit_safe(&surface->toplevel->events.set_title, surface);
}
static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
@@ -71,6 +72,7 @@ static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
free(surface->toplevel->app_id);
surface->toplevel->app_id = tmp;
+ wlr_signal_emit_safe(&surface->toplevel->events.set_app_id, surface);
}
static void xdg_toplevel_handle_show_window_menu(struct wl_client *client,
@@ -419,7 +421,8 @@ static void xdg_toplevel_handle_resource_destroy(struct wl_resource *resource) {
const struct wlr_surface_role xdg_toplevel_v6_surface_role = {
.name = "xdg_toplevel_v6",
- .commit = handle_xdg_surface_v6_committed,
+ .commit = handle_xdg_surface_v6_commit,
+ .precommit = handle_xdg_surface_v6_precommit,
};
void create_xdg_toplevel_v6(struct wlr_xdg_surface_v6 *xdg_surface,
@@ -441,6 +444,8 @@ void create_xdg_toplevel_v6(struct wlr_xdg_surface_v6 *xdg_surface,
wl_signal_init(&xdg_surface->toplevel->events.request_resize);
wl_signal_init(&xdg_surface->toplevel->events.request_show_window_menu);
wl_signal_init(&xdg_surface->toplevel->events.set_parent);
+ wl_signal_init(&xdg_surface->toplevel->events.set_title);
+ wl_signal_init(&xdg_surface->toplevel->events.set_app_id);
xdg_surface->role = WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL;
xdg_surface->toplevel->base = xdg_surface;
diff --git a/util/log.c b/util/log.c
index 754ccfa9..3ef5f484 100644
--- a/util/log.c
+++ b/util/log.c
@@ -85,3 +85,7 @@ const char *_wlr_strip_path(const char *filepath) {
}
return filepath;
}
+
+enum wlr_log_importance wlr_log_get_verbosity(void) {
+ return log_importance;
+}
diff --git a/util/os-compatibility.c b/util/os-compatibility.c
index 38333605..bd39705d 100644
--- a/util/os-compatibility.c
+++ b/util/os-compatibility.c
@@ -23,7 +23,7 @@
* SOFTWARE.
*/
-#define _XOPEN_SOURCE 700
+#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
@@ -32,20 +32,22 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <wlr/config.h>
#include "util/os-compatibility.h"
int os_fd_set_cloexec(int fd) {
- long flags;
-
- if (fd == -1)
+ if (fd == -1) {
return -1;
+ }
- flags = fcntl(fd, F_GETFD);
- if (flags == -1)
+ long flags = fcntl(fd, F_GETFD);
+ if (flags == -1) {
return -1;
+ }
- if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
+ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
return -1;
+ }
return 0;
}
@@ -58,15 +60,14 @@ int set_cloexec_or_close(int fd) {
return fd;
}
-int create_tmpfile_cloexec(char *tmpname)
-{
+int create_tmpfile_cloexec(char *tmpname) {
int fd;
-
mode_t prev_umask = umask(0066);
#ifdef HAVE_MKOSTEMP
fd = mkostemp(tmpname, O_CLOEXEC);
- if (fd >= 0)
+ if (fd >= 0) {
unlink(tmpname);
+ }
#else
fd = mkstemp(tmpname);
if (fd >= 0) {
@@ -102,32 +103,29 @@ int create_tmpfile_cloexec(char *tmpname)
*/
int os_create_anonymous_file(off_t size) {
static const char template[] = "/wlroots-shared-XXXXXX";
- const char *path;
- char *name;
- int fd;
- int ret;
- path = getenv("XDG_RUNTIME_DIR");
+ const char *path = getenv("XDG_RUNTIME_DIR");
if (!path) {
errno = ENOENT;
return -1;
}
- name = malloc(strlen(path) + sizeof(template));
- if (!name)
+ char *name = malloc(strlen(path) + sizeof(template));
+ if (!name) {
return -1;
+ }
strcpy(name, path);
strcat(name, template);
- fd = create_tmpfile_cloexec(name);
-
+ int fd = create_tmpfile_cloexec(name);
free(name);
-
- if (fd < 0)
+ if (fd < 0) {
return -1;
+ }
-#ifdef HAVE_POSIX_FALLOCATE
+#ifdef WLR_HAS_POSIX_FALLOCATE
+ int ret;
do {
ret = posix_fallocate(fd, 0, size);
} while (ret == EINTR);
@@ -137,6 +135,7 @@ int os_create_anonymous_file(off_t size) {
return -1;
}
#else
+ int ret;
do {
ret = ftruncate(fd, size);
} while (ret < 0 && errno == EINTR);
diff --git a/wlroots.syms b/wlroots.syms
index ba085d0f..3176f874 100644
--- a/wlroots.syms
+++ b/wlroots.syms
@@ -1,4 +1,4 @@
-WLROOTS_0_0_0 {
+{
global:
wlr_*;
_wlr_log;
diff --git a/xwayland/meson.build b/xwayland/meson.build
index ec486f58..0bd88924 100644
--- a/xwayland/meson.build
+++ b/xwayland/meson.build
@@ -1,3 +1,32 @@
+xwayland_libs = []
+xwayland_required = [
+ 'xcb',
+ 'xcb-composite',
+ 'xcb-render',
+ 'xcb-xfixes',
+]
+xwayland_optional = [
+ 'xcb-errors',
+ 'xcb-icccm',
+]
+
+foreach lib : xwayland_required
+ dep = dependency(lib, required: get_option('xwayland'))
+ if not dep.found()
+ subdir_done()
+ endif
+
+ xwayland_libs += dep
+endforeach
+
+foreach lib : xwayland_optional
+ dep = dependency(lib, required: get_option(lib))
+ if dep.found()
+ xwayland_libs += dep
+ conf_data.set('WLR_HAS_' + lib.underscorify().to_upper(), true)
+ endif
+endforeach
+
lib_wlr_xwayland = static_library(
'wlr_xwayland',
files(
@@ -12,14 +41,11 @@ lib_wlr_xwayland = static_library(
include_directories: wlr_inc,
dependencies: [
wayland_server,
- xcb,
- xcb_composite,
- xcb_xfixes,
- xcb_image,
- xcb_render,
- xcb_icccm,
- xcb_errors,
+ xwayland_libs,
xkbcommon,
pixman,
],
)
+
+wlr_parts += lib_wlr_xwayland
+conf_data.set('WLR_HAS_XWAYLAND', true)
diff --git a/xwayland/xwayland.c b/xwayland/xwayland.c
index 1068b942..fe09ea5e 100644
--- a/xwayland/xwayland.c
+++ b/xwayland/xwayland.c
@@ -74,6 +74,7 @@ static int fill_arg(char ***argv, const char *fmt, ...) {
return len;
}
+_Noreturn
static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) {
if (unset_cloexec(wlr_xwayland->x_fd[0]) ||
unset_cloexec(wlr_xwayland->x_fd[1]) ||
@@ -123,9 +124,26 @@ static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) {
wlr_xwayland->wl_fd[1], wlr_xwayland->display, wlr_xwayland->x_fd[0],
wlr_xwayland->x_fd[1], wlr_xwayland->wm_fd[1]);
- // TODO: close stdout/err depending on log level
+ // Closes stdout/stderr depending on log verbosity
+ enum wlr_log_importance verbosity = wlr_log_get_verbosity();
+ int devnull = open("/dev/null", O_WRONLY | O_CREAT, 0666);
+ if (devnull < 0) {
+ wlr_log_errno(WLR_ERROR, "XWayland: failed to open /dev/null");
+ _exit(EXIT_FAILURE);
+ }
+ if (verbosity < WLR_INFO) {
+ dup2(devnull, STDOUT_FILENO);
+ }
+ if (verbosity < WLR_ERROR) {
+ dup2(devnull, STDERR_FILENO);
+ }
+ // This returns if and only if the call fails
execvp("Xwayland", argv);
+
+ wlr_log_errno(WLR_ERROR, "failed to exec Xwayland");
+ close(devnull);
+ _exit(EXIT_FAILURE);
}
static void xwayland_finish_server(struct wlr_xwayland *wlr_xwayland) {
@@ -346,8 +364,6 @@ static bool xwayland_start_server(struct wlr_xwayland *wlr_xwayland) {
sigprocmask(SIG_BLOCK, &sigset, NULL);
if ((pid = fork()) == 0) {
exec_xwayland(wlr_xwayland);
- wlr_log_errno(WLR_ERROR, "failed to exec Xwayland");
- _exit(EXIT_FAILURE);
}
if (pid < 0) {
wlr_log_errno(WLR_ERROR, "second fork failed");
@@ -390,6 +406,10 @@ static bool xwayland_start_server_lazy(struct wlr_xwayland *wlr_xwayland) {
}
void wlr_xwayland_destroy(struct wlr_xwayland *wlr_xwayland) {
+ if (!wlr_xwayland) {
+ return;
+ }
+
wlr_xwayland_set_seat(wlr_xwayland, NULL);
xwayland_finish_server(wlr_xwayland);
xwayland_finish_display(wlr_xwayland);
diff --git a/xwayland/xwm.c b/xwayland/xwm.c
index bee3a005..9c803543 100644
--- a/xwayland/xwm.c
+++ b/xwayland/xwm.c
@@ -24,6 +24,7 @@ const char *atom_map[ATOM_LAST] = {
"WM_HINTS",
"WM_NORMAL_HINTS",
"WM_SIZE_HINTS",
+ "WM_WINDOW_ROLE",
"_MOTIF_WM_HINTS",
"UTF8_STRING",
"WM_S0",
@@ -39,6 +40,7 @@ const char *atom_map[ATOM_LAST] = {
"_NET_WM_MOVERESIZE",
"_NET_WM_NAME",
"_NET_SUPPORTING_WM_CHECK",
+ "_NET_WM_STATE_MODAL",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_STATE_MAXIMIZED_VERT",
"_NET_WM_STATE_MAXIMIZED_HORZ",
@@ -147,13 +149,17 @@ static struct wlr_xwayland_surface *xwayland_surface_create(
wl_signal_init(&surface->events.request_resize);
wl_signal_init(&surface->events.request_maximize);
wl_signal_init(&surface->events.request_fullscreen);
+ wl_signal_init(&surface->events.request_activate);
wl_signal_init(&surface->events.map);
wl_signal_init(&surface->events.unmap);
wl_signal_init(&surface->events.set_class);
+ wl_signal_init(&surface->events.set_role);
wl_signal_init(&surface->events.set_title);
wl_signal_init(&surface->events.set_parent);
wl_signal_init(&surface->events.set_pid);
wl_signal_init(&surface->events.set_window_type);
+ wl_signal_init(&surface->events.set_hints);
+ wl_signal_init(&surface->events.set_override_redirect);
wl_signal_init(&surface->events.ping_timeout);
xcb_get_geometry_reply_t *geometry_reply =
@@ -240,8 +246,7 @@ static void xwm_send_focus_window(struct wlr_xwm *xwm,
XCB_CONFIG_WINDOW_STACK_MODE, values);
}
-
-void xwm_surface_activate(struct wlr_xwm *xwm,
+static void xwm_surface_activate(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface) {
if (xwm->focus_surface == xsurface ||
(xsurface && xsurface->override_redirect)) {
@@ -267,6 +272,9 @@ static void xsurface_set_net_wm_state(struct wlr_xwayland_surface *xsurface) {
int i;
i = 0;
+ if (xsurface->modal) {
+ property[i++] = xwm->atoms[_NET_WM_STATE_MODAL];
+ }
if (xsurface->fullscreen) {
property[i++] = xwm->atoms[_NET_WM_STATE_FULLSCREEN];
}
@@ -321,6 +329,7 @@ static void xwayland_surface_destroy(
free(xsurface->title);
free(xsurface->class);
free(xsurface->instance);
+ free(xsurface->role);
free(xsurface->window_type);
free(xsurface->protocols);
free(xsurface->hints);
@@ -359,6 +368,28 @@ static void read_surface_class(struct wlr_xwm *xwm,
wlr_signal_emit_safe(&surface->events.set_class, surface);
}
+static void read_surface_role(struct wlr_xwm *xwm,
+ struct wlr_xwayland_surface *xsurface,
+ xcb_get_property_reply_t *reply) {
+ if (reply->type != XCB_ATOM_STRING &&
+ reply->type != xwm->atoms[UTF8_STRING]) {
+ return;
+ }
+
+ size_t len = xcb_get_property_value_length(reply);
+ char *role = xcb_get_property_value(reply);
+
+ free(xsurface->role);
+ if (len > 0) {
+ xsurface->role = strndup(role, len);
+ } else {
+ xsurface->role = NULL;
+ }
+
+ wlr_log(WLR_DEBUG, "XCB_ATOM_WM_WINDOW_ROLE: %s", xsurface->role);
+ wlr_signal_emit_safe(&xsurface->events.set_role, xsurface);
+}
+
static void read_surface_title(struct wlr_xwm *xwm,
struct wlr_xwayland_surface *xsurface,
xcb_get_property_reply_t *reply) {
@@ -492,6 +523,7 @@ static void read_surface_hints(struct wlr_xwm *xwm,
xsurface->hints_urgency = xcb_icccm_wm_hints_get_urgency(&hints);
wlr_log(WLR_DEBUG, "WM_HINTS (%d)", reply->value_len);
+ wlr_signal_emit_safe(&xsurface->events.set_hints, xsurface);
}
#else
static void read_surface_hints(struct wlr_xwm *xwm,
@@ -573,7 +605,9 @@ static void read_surface_net_wm_state(struct wlr_xwm *xwm,
xsurface->fullscreen = 0;
xcb_atom_t *atom = xcb_get_property_value(reply);
for (uint32_t i = 0; i < reply->value_len; i++) {
- if (atom[i] == xwm->atoms[_NET_WM_STATE_FULLSCREEN]) {
+ if (atom[i] == xwm->atoms[_NET_WM_STATE_MODAL]) {
+ xsurface->modal = true;
+ } else if (atom[i] == xwm->atoms[_NET_WM_STATE_FULLSCREEN]) {
xsurface->fullscreen = true;
} else if (atom[i] == xwm->atoms[_NET_WM_STATE_MAXIMIZED_VERT]) {
xsurface->maximized_vert = true;
@@ -629,6 +663,8 @@ static void read_surface_property(struct wlr_xwm *xwm,
read_surface_normal_hints(xwm, xsurface, reply);
} else if (property == xwm->atoms[MOTIF_WM_HINTS]) {
read_surface_motif_hints(xwm, xsurface, reply);
+ } else if (property == xwm->atoms[WM_WINDOW_ROLE]) {
+ read_surface_role(xwm, xsurface, reply);
} else {
char *prop_name = xwm_get_atom_name(xwm, property);
wlr_log(WLR_DEBUG, "unhandled X11 property %u (%s) for window %u",
@@ -652,9 +688,27 @@ static void xwayland_surface_role_commit(struct wlr_surface *wlr_surface) {
}
}
+static void xwayland_surface_role_precommit(struct wlr_surface *wlr_surface) {
+ assert(wlr_surface->role == &xwayland_surface_role);
+ struct wlr_xwayland_surface *surface = wlr_surface->role_data;
+ if (surface == NULL) {
+ return;
+ }
+
+ if (wlr_surface->pending.committed & WLR_SURFACE_STATE_BUFFER &&
+ wlr_surface->pending.buffer_resource == NULL) {
+ // This is a NULL commit
+ if (surface->mapped) {
+ wlr_signal_emit_safe(&surface->events.unmap, surface);
+ surface->mapped = false;
+ }
+ }
+}
+
static const struct wlr_surface_role xwayland_surface_role = {
.name = "wlr_xwayland_surface",
.commit = xwayland_surface_role_commit,
+ .precommit = xwayland_surface_role_precommit,
};
static void handle_surface_destroy(struct wl_listener *listener, void *data) {
@@ -764,9 +818,7 @@ static void xwm_handle_configure_request(struct wlr_xwm *xwm,
static void xwm_handle_configure_notify(struct wlr_xwm *xwm,
xcb_configure_notify_event_t *ev) {
- struct wlr_xwayland_surface *xsurface =
- lookup_surface(xwm, ev->window);
-
+ struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, ev->window);
if (!xsurface) {
return;
}
@@ -775,6 +827,11 @@ static void xwm_handle_configure_notify(struct wlr_xwm *xwm,
xsurface->y = ev->y;
xsurface->width = ev->width;
xsurface->height = ev->height;
+
+ if (xsurface->override_redirect != ev->override_redirect) {
+ xsurface->override_redirect = ev->override_redirect;
+ wlr_signal_emit_safe(&xsurface->events.set_override_redirect, xsurface);
+ }
}
#define ICCCM_WITHDRAWN_STATE 0
@@ -814,6 +871,15 @@ static void xwm_handle_map_request(struct wlr_xwm *xwm,
static void xwm_handle_map_notify(struct wlr_xwm *xwm,
xcb_map_notify_event_t *ev) {
wlr_log(WLR_DEBUG, "XCB_MAP_NOTIFY (%u)", ev->window);
+ struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, ev->window);
+ if (!xsurface) {
+ return;
+ }
+
+ if (xsurface->override_redirect != ev->override_redirect) {
+ xsurface->override_redirect = ev->override_redirect;
+ wlr_signal_emit_safe(&xsurface->events.set_override_redirect, xsurface);
+ }
}
static void xwm_handle_unmap_notify(struct wlr_xwm *xwm,
@@ -996,7 +1062,10 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm,
for (size_t i = 0; i < 2; ++i) {
uint32_t property = client_message->data.data32[1 + i];
- if (property == xwm->atoms[_NET_WM_STATE_FULLSCREEN] &&
+ if (property == xwm->atoms[_NET_WM_STATE_MODAL] &&
+ update_state(action, &xsurface->modal)) {
+ xsurface_set_net_wm_state(xsurface);
+ } else if (property == xwm->atoms[_NET_WM_STATE_FULLSCREEN] &&
update_state(action, &xsurface->fullscreen)) {
xsurface_set_net_wm_state(xsurface);
} else if (property == xwm->atoms[_NET_WM_STATE_MAXIMIZED_VERT] &&
@@ -1055,6 +1124,15 @@ static void xwm_handle_wm_protocols_message(struct wlr_xwm *xwm,
}
}
+static void xwm_handle_net_active_window_message(struct wlr_xwm *xwm,
+ xcb_client_message_event_t *ev) {
+ struct wlr_xwayland_surface *surface = lookup_surface(xwm, ev->window);
+ if (surface == NULL) {
+ return;
+ }
+ wlr_signal_emit_safe(&surface->events.request_activate, surface);
+}
+
static void xwm_handle_client_message(struct wlr_xwm *xwm,
xcb_client_message_event_t *ev) {
wlr_log(WLR_DEBUG, "XCB_CLIENT_MESSAGE (%u)", ev->window);
@@ -1067,6 +1145,8 @@ static void xwm_handle_client_message(struct wlr_xwm *xwm,
xwm_handle_net_wm_moveresize_message(xwm, ev);
} else if (ev->type == xwm->atoms[WM_PROTOCOLS]) {
xwm_handle_wm_protocols_message(xwm, ev);
+ } else if (ev->type == xwm->atoms[_NET_ACTIVE_WINDOW]) {
+ xwm_handle_net_active_window_message(xwm, ev);
} else if (!xwm_handle_selection_client_message(xwm, ev)) {
char *type_name = xwm_get_atom_name(xwm, ev->type);
wlr_log(WLR_DEBUG, "unhandled x11 client message %u (%s)", ev->type,
@@ -1598,6 +1678,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) {
xwm->atoms[NET_WM_STATE],
xwm->atoms[_NET_ACTIVE_WINDOW],
xwm->atoms[_NET_WM_MOVERESIZE],
+ xwm->atoms[_NET_WM_STATE_MODAL],
xwm->atoms[_NET_WM_STATE_FULLSCREEN],
xwm->atoms[_NET_WM_STATE_MAXIMIZED_VERT],
xwm->atoms[_NET_WM_STATE_MAXIMIZED_HORZ],
@@ -1659,8 +1740,22 @@ bool xwm_atoms_contains(struct wlr_xwm *xwm, xcb_atom_t *atoms,
return false;
}
-bool wlr_xwayland_surface_is_unmanaged(
+void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface) {
+ xcb_client_message_data_t data = { 0 };
+ data.data32[0] = surface->xwm->atoms[_NET_WM_PING];
+ data.data32[1] = XCB_CURRENT_TIME;
+ data.data32[2] = surface->window_id;
+
+ xwm_send_wm_message(surface, &data, XCB_EVENT_MASK_NO_EVENT);
+
+ wl_event_source_timer_update(surface->ping_timer,
+ surface->xwm->ping_timeout);
+ surface->pinging = true;
+}
+
+bool wlr_xwayland_or_surface_wants_focus(
const struct wlr_xwayland_surface *surface) {
+ bool ret = true;
static enum atom_name needles[] = {
NET_WM_WINDOW_TYPE_COMBO,
NET_WM_WINDOW_TYPE_DND,
@@ -1672,26 +1767,12 @@ bool wlr_xwayland_surface_is_unmanaged(
NET_WM_WINDOW_TYPE_TOOLTIP,
NET_WM_WINDOW_TYPE_UTILITY,
};
-
for (size_t i = 0; i < sizeof(needles) / sizeof(needles[0]); ++i) {
if (xwm_atoms_contains(surface->xwm, surface->window_type,
surface->window_type_len, needles[i])) {
- return true;
+ ret = false;
}
}
- return false;
-}
-
-void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface) {
- xcb_client_message_data_t data = { 0 };
- data.data32[0] = surface->xwm->atoms[_NET_WM_PING];
- data.data32[1] = XCB_CURRENT_TIME;
- data.data32[2] = surface->window_id;
-
- xwm_send_wm_message(surface, &data, XCB_EVENT_MASK_NO_EVENT);
-
- wl_event_source_timer_update(surface->ping_timer,
- surface->xwm->ping_timeout);
- surface->pinging = true;
+ return ret;
}