Merge branch 'master' into modifier-fixes

This commit is contained in:
Tony Crisci 2018-01-17 08:27:47 -05:00
commit 43896af90f
41 changed files with 765 additions and 103 deletions

View file

@ -53,7 +53,7 @@ struct wlr_egl *wlr_backend_get_egl(struct wlr_backend *backend) {
} }
static struct wlr_backend *attempt_wl_backend(struct wl_display *display) { static struct wlr_backend *attempt_wl_backend(struct wl_display *display) {
struct wlr_backend *backend = wlr_wl_backend_create(display); struct wlr_backend *backend = wlr_wl_backend_create(display, NULL);
if (backend) { if (backend) {
int outputs = 1; int outputs = 1;
const char *_outputs = getenv("WLR_WL_OUTPUTS"); const char *_outputs = getenv("WLR_WL_OUTPUTS");

View file

@ -33,7 +33,6 @@ static bool atomic_end(int drm_fd, struct atomic *atom) {
} }
uint32_t flags = DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK; uint32_t flags = DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_NONBLOCK;
if (drmModeAtomicCommit(drm_fd, atom->req, flags, NULL)) { if (drmModeAtomicCommit(drm_fd, atom->req, flags, NULL)) {
wlr_log_errno(L_ERROR, "Atomic test failed"); wlr_log_errno(L_ERROR, "Atomic test failed");
drmModeAtomicSetCursor(atom->req, atom->cursor); drmModeAtomicSetCursor(atom->req, atom->cursor);
@ -44,13 +43,11 @@ static bool atomic_end(int drm_fd, struct atomic *atom) {
} }
static bool atomic_commit(int drm_fd, struct atomic *atom, static bool atomic_commit(int drm_fd, struct atomic *atom,
struct wlr_drm_connector *conn, uint32_t flag, bool modeset) { struct wlr_drm_connector *conn, uint32_t flags, bool modeset) {
if (atom->failed) { if (atom->failed) {
return false; return false;
} }
uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | flag;
int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, conn); int ret = drmModeAtomicCommit(drm_fd, atom->req, flags, conn);
if (ret) { if (ret) {
wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)",
@ -59,7 +56,8 @@ static bool atomic_commit(int drm_fd, struct atomic *atom,
// Try to commit without new changes // Try to commit without new changes
drmModeAtomicSetCursor(atom->req, atom->cursor); drmModeAtomicSetCursor(atom->req, atom->cursor);
if (drmModeAtomicCommit(drm_fd, atom->req, flags, conn)) { if (drmModeAtomicCommit(drm_fd, atom->req, flags, conn)) {
wlr_log_errno(L_ERROR, "%s: Atomic commit failed (%s)", wlr_log_errno(L_ERROR,
"%s: Atomic commit without new changes failed (%s)",
conn->output.name, modeset ? "modeset" : "pageflip"); conn->output.name, modeset ? "modeset" : "pageflip");
} }
} }
@ -100,8 +98,8 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm,
struct wlr_drm_connector *conn, struct wlr_drm_connector *conn,
struct wlr_drm_crtc *crtc, struct wlr_drm_crtc *crtc,
uint32_t fb_id, drmModeModeInfo *mode) { uint32_t fb_id, drmModeModeInfo *mode) {
if (mode) { if (mode != NULL) {
if (crtc->mode_id) { if (crtc->mode_id != 0) {
drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id);
} }
@ -111,26 +109,38 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm,
} }
} }
struct atomic atom; uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT;
if (mode != NULL) {
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
} else {
flags |= DRM_MODE_ATOMIC_NONBLOCK;
}
struct atomic atom;
atomic_begin(crtc, &atom); atomic_begin(crtc, &atom);
atomic_add(&atom, conn->id, conn->props.crtc_id, crtc->id); atomic_add(&atom, conn->id, conn->props.crtc_id, crtc->id);
atomic_add(&atom, crtc->id, crtc->props.mode_id, crtc->mode_id); atomic_add(&atom, crtc->id, crtc->props.mode_id, crtc->mode_id);
atomic_add(&atom, crtc->id, crtc->props.active, 1); atomic_add(&atom, crtc->id, crtc->props.active, 1);
set_plane_props(&atom, crtc->primary, crtc->id, fb_id, true); set_plane_props(&atom, crtc->primary, crtc->id, fb_id, true);
return atomic_commit(drm->fd, &atom, conn, return atomic_commit(drm->fd, &atom, conn, flags, mode);
mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : DRM_MODE_ATOMIC_NONBLOCK,
mode);
} }
static void atomic_conn_enable(struct wlr_drm_backend *drm, static bool atomic_conn_enable(struct wlr_drm_backend *drm,
struct wlr_drm_connector *conn, bool enable) { struct wlr_drm_connector *conn, bool enable) {
struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_crtc *crtc = conn->crtc;
struct atomic atom;
struct atomic atom;
atomic_begin(crtc, &atom); atomic_begin(crtc, &atom);
atomic_add(&atom, crtc->id, crtc->props.active, enable); atomic_add(&atom, crtc->id, crtc->props.active, enable);
atomic_end(drm->fd, &atom); if (enable) {
atomic_add(&atom, conn->id, conn->props.crtc_id, crtc->id);
atomic_add(&atom, crtc->id, crtc->props.mode_id, crtc->mode_id);
} else {
atomic_add(&atom, conn->id, conn->props.crtc_id, 0);
atomic_add(&atom, crtc->id, crtc->props.mode_id, 0);
}
return atomic_commit(drm->fd, &atom, conn, DRM_MODE_ATOMIC_ALLOW_MODESET,
true);
} }
bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm, bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm,
@ -167,6 +177,10 @@ bool legacy_crtc_move_cursor(struct wlr_drm_backend *drm,
static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm, static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm,
struct wlr_drm_crtc *crtc, int x, int y) { struct wlr_drm_crtc *crtc, int x, int y) {
if (!crtc || !crtc->cursor) {
return true;
}
struct wlr_drm_plane *plane = crtc->cursor; struct wlr_drm_plane *plane = crtc->cursor;
// We can't use atomic operations on fake planes // We can't use atomic operations on fake planes
if (plane->id == 0) { if (plane->id == 0) {

View file

@ -252,11 +252,16 @@ static void wlr_drm_connector_enable(struct wlr_output *output, bool enable) {
} }
struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend; struct wlr_drm_backend *drm = (struct wlr_drm_backend *)output->backend;
drm->iface->conn_enable(drm, conn, enable); bool ok = drm->iface->conn_enable(drm, conn, enable);
if (!ok) {
return;
}
if (enable) { if (enable) {
wlr_drm_connector_start_renderer(conn); wlr_drm_connector_start_renderer(conn);
} }
wlr_output_update_enabled(&conn->output, enable);
} }
static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in, static void realloc_planes(struct wlr_drm_backend *drm, const uint32_t *crtc_in,
@ -722,7 +727,8 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) {
drmModeFreeConnector(drm_conn); drmModeFreeConnector(drm_conn);
continue; continue;
} }
wlr_output_init(&wlr_conn->output, &drm->backend, &output_impl); wlr_output_init(&wlr_conn->output, &drm->backend, &output_impl,
drm->display);
struct wl_event_loop *ev = wl_display_get_event_loop(drm->display); struct wl_event_loop *ev = wl_display_get_event_loop(drm->display);
wlr_conn->retry_pageflip = wl_event_loop_add_timer(ev, retry_pageflip, wlr_conn->retry_pageflip = wl_event_loop_add_timer(ev, retry_pageflip,
@ -792,7 +798,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) {
wl_list_insert(&wlr_conn->output.modes, &mode->wlr_mode.link); wl_list_insert(&wlr_conn->output.modes, &mode->wlr_mode.link);
} }
wlr_output_create_global(&wlr_conn->output, drm->display); wlr_output_update_enabled(&wlr_conn->output, true);
wlr_conn->state = WLR_DRM_CONN_NEEDS_MODESET; wlr_conn->state = WLR_DRM_CONN_NEEDS_MODESET;
wlr_log(L_INFO, "Sending modesetting signal for '%s'", wlr_log(L_INFO, "Sending modesetting signal for '%s'",
@ -802,7 +808,7 @@ void wlr_drm_scan_connectors(struct wlr_drm_backend *drm) {
drm_conn->connection != DRM_MODE_CONNECTED) { drm_conn->connection != DRM_MODE_CONNECTED) {
wlr_log(L_INFO, "'%s' disconnected", wlr_conn->output.name); wlr_log(L_INFO, "'%s' disconnected", wlr_conn->output.name);
wlr_output_destroy_global(&wlr_conn->output); wlr_output_update_enabled(&wlr_conn->output, false);
wlr_drm_connector_cleanup(wlr_conn); wlr_drm_connector_cleanup(wlr_conn);
} }

View file

@ -25,10 +25,11 @@ static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm,
return true; return true;
} }
static void legacy_conn_enable(struct wlr_drm_backend *drm, static bool legacy_conn_enable(struct wlr_drm_backend *drm,
struct wlr_drm_connector *conn, bool enable) { struct wlr_drm_connector *conn, bool enable) {
drmModeConnectorSetProperty(drm->fd, conn->id, conn->props.dpms, int ret = drmModeConnectorSetProperty(drm->fd, conn->id, conn->props.dpms,
enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF); enable ? DRM_MODE_DPMS_ON : DRM_MODE_DPMS_OFF);
return ret >= 0;
} }
bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm, bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm,

View file

@ -15,7 +15,7 @@ static bool backend_start(struct wlr_backend *wlr_backend) {
struct wlr_headless_output *output; struct wlr_headless_output *output;
wl_list_for_each(output, &backend->outputs, link) { wl_list_for_each(output, &backend->outputs, link) {
wl_event_source_timer_update(output->frame_timer, output->frame_delay); wl_event_source_timer_update(output->frame_timer, output->frame_delay);
wlr_output_create_global(&output->wlr_output, backend->display); wlr_output_update_enabled(&output->wlr_output, true);
wl_signal_emit(&backend->backend.events.output_add, wl_signal_emit(&backend->backend.events.output_add,
&output->wlr_output); &output->wlr_output);
} }

View file

@ -105,7 +105,8 @@ struct wlr_output *wlr_headless_add_output(struct wlr_backend *wlr_backend,
return NULL; return NULL;
} }
output->backend = backend; output->backend = backend;
wlr_output_init(&output->wlr_output, &backend->backend, &output_impl); wlr_output_init(&output->wlr_output, &backend->backend, &output_impl,
backend->display);
struct wlr_output *wlr_output = &output->wlr_output; struct wlr_output *wlr_output = &output->wlr_output;
output->egl_surface = egl_create_surface(&backend->egl, width, height); output->egl_surface = egl_create_surface(&backend->egl, width, height);
@ -138,7 +139,7 @@ struct wlr_output *wlr_headless_add_output(struct wlr_backend *wlr_backend,
if (backend->started) { if (backend->started) {
wl_event_source_timer_update(output->frame_timer, output->frame_delay); wl_event_source_timer_update(output->frame_timer, output->frame_delay);
wlr_output_create_global(wlr_output, backend->display); wlr_output_update_enabled(wlr_output, true);
wl_signal_emit(&backend->backend.events.output_add, wlr_output); wl_signal_emit(&backend->backend.events.output_add, wlr_output);
} }

View file

@ -158,7 +158,7 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
wlr_wl_backend_destroy(&backend->backend); wlr_wl_backend_destroy(&backend->backend);
} }
struct wlr_backend *wlr_wl_backend_create(struct wl_display *display) { struct wlr_backend *wlr_wl_backend_create(struct wl_display *display, const char *remote) {
wlr_log(L_INFO, "Creating wayland backend"); wlr_log(L_INFO, "Creating wayland backend");
struct wlr_wl_backend *backend = calloc(1, sizeof(struct wlr_wl_backend)); struct wlr_wl_backend *backend = calloc(1, sizeof(struct wlr_wl_backend));
@ -173,7 +173,7 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display) {
backend->local_display = display; backend->local_display = display;
backend->remote_display = wl_display_connect(NULL); backend->remote_display = wl_display_connect(remote);
if (!backend->remote_display) { if (!backend->remote_display) {
wlr_log_errno(L_ERROR, "Could not connect to remote display"); wlr_log_errno(L_ERROR, "Could not connect to remote display");
return false; return false;

View file

@ -261,7 +261,8 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *_backend) {
wlr_log(L_ERROR, "Failed to allocate wlr_wl_backend_output"); wlr_log(L_ERROR, "Failed to allocate wlr_wl_backend_output");
return NULL; return NULL;
} }
wlr_output_init(&output->wlr_output, &backend->backend, &output_impl); wlr_output_init(&output->wlr_output, &backend->backend, &output_impl,
backend->local_display);
struct wlr_output *wlr_output = &output->wlr_output; struct wlr_output *wlr_output = &output->wlr_output;
wlr_output_update_custom_mode(wlr_output, 1280, 720, 0); wlr_output_update_custom_mode(wlr_output, 1280, 720, 0);
@ -325,7 +326,7 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *_backend) {
} }
wl_list_insert(&backend->outputs, &output->link); wl_list_insert(&backend->outputs, &output->link);
wlr_output_create_global(wlr_output, backend->local_display); wlr_output_update_enabled(wlr_output, true);
wl_signal_emit(&backend->backend.events.output_add, wlr_output); wl_signal_emit(&backend->backend.events.output_add, wlr_output);
return wlr_output; return wlr_output;

View file

@ -181,7 +181,8 @@ static int signal_frame(void *data) {
static void init_atom(struct wlr_x11_backend *x11, struct wlr_x11_atom *atom, static void init_atom(struct wlr_x11_backend *x11, struct wlr_x11_atom *atom,
uint8_t only_if_exists, const char *name) { uint8_t only_if_exists, const char *name) {
atom->cookie = xcb_intern_atom(x11->xcb_conn, only_if_exists, strlen(name), name); atom->cookie = xcb_intern_atom(x11->xcb_conn, only_if_exists, strlen(name),
name);
atom->reply = xcb_intern_atom_reply(x11->xcb_conn, atom->cookie, NULL); atom->reply = xcb_intern_atom_reply(x11->xcb_conn, atom->cookie, NULL);
} }
@ -201,7 +202,8 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) {
output->x11 = x11; output->x11 = x11;
wlr_output_init(&output->wlr_output, &x11->backend, &output_impl); wlr_output_init(&output->wlr_output, &x11->backend, &output_impl,
x11->wl_display);
snprintf(output->wlr_output.name, sizeof(output->wlr_output.name), "X11-1"); snprintf(output->wlr_output.name, sizeof(output->wlr_output.name), "X11-1");
output->win = xcb_generate_id(x11->xcb_conn); output->win = xcb_generate_id(x11->xcb_conn);
@ -224,7 +226,7 @@ static bool wlr_x11_backend_start(struct wlr_backend *backend) {
xcb_map_window(x11->xcb_conn, output->win); xcb_map_window(x11->xcb_conn, output->win);
xcb_flush(x11->xcb_conn); xcb_flush(x11->xcb_conn);
wlr_output_create_global(&output->wlr_output, x11->wl_display); wlr_output_update_enabled(&output->wlr_output, true);
wl_signal_emit(&x11->backend.events.output_add, output); wl_signal_emit(&x11->backend.events.output_add, output);
wl_signal_emit(&x11->backend.events.input_add, &x11->keyboard_dev); wl_signal_emit(&x11->backend.events.input_add, &x11->keyboard_dev);

191
examples/idle.c Normal file
View file

@ -0,0 +1,191 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <pthread.h>
#include <wayland-client.h>
#include <wayland-client-protocol.h>
#include <idle-client-protocol.h>
#include <wlr/util/log.h>
static struct org_kde_kwin_idle *idle_manager = NULL;
static struct wl_seat *seat = NULL;
static uint32_t timeout = 0, simulate_activity_timeout = 0, close_timeout = 0;
static int run = 1;
struct thread_args {
struct wl_display *display;
struct org_kde_kwin_idle_timeout *timer;
};
static void handle_global(void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version) {
fprintf(stdout, "interfaces found: %s\n", interface);
if (strcmp(interface, "org_kde_kwin_idle") == 0) {
idle_manager = wl_registry_bind(registry, name, &org_kde_kwin_idle_interface, 1);
}
else if (strcmp(interface, "wl_seat") == 0) {
seat = wl_registry_bind(registry, name, &wl_seat_interface, 1);
}
}
static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
//TODO
}
static const struct wl_registry_listener registry_listener = {
.global = handle_global,
.global_remove = handle_global_remove,
};
static void handle_idle(void* data, struct org_kde_kwin_idle_timeout *timer) {
fprintf(stdout, "idle state\n");
}
static void handle_resume(void* data, struct org_kde_kwin_idle_timeout *timer) {
fprintf(stdout, "active state\n");
}
static const struct org_kde_kwin_idle_timeout_listener idle_timer_listener = {
.idle = handle_idle,
.resumed = handle_resume,
};
int parse_args(int argc, char *argv[]) {
int c;
while ((c = getopt(argc, argv, "c:hs:t:")) != -1) {
switch(c)
{
case 'c':
close_timeout = strtoul(optarg, NULL, 10);
break;
case 's':
simulate_activity_timeout = strtoul(optarg, NULL, 10);
break;
case 't':
timeout = strtoul(optarg, NULL, 10);
break;
case 'h':
case '?':
printf("Usage: %s [OPTIONS]\n", argv[0]);
printf(" -t seconds\t\t\tidle timeout in seconds\n");
printf(" -s seconds optional\t\tsimulate user activity after x seconds\n");
printf(" -c seconds optional\t\tclose program after x seconds\n");
printf(" -h\t\t\t\tthis help menu\n");
return 1;
default:
return 1;
}
}
return 0;
}
void *simulate_activity(void *data) {
sleep(simulate_activity_timeout);
fprintf(stdout, "simulate user activity\n");
struct thread_args *arg = data;
org_kde_kwin_idle_timeout_simulate_user_activity(arg->timer);
wl_display_roundtrip(arg->display);
return NULL;
}
void *close_program(void *data) {
sleep(close_timeout);
struct thread_args *arg = data;
org_kde_kwin_idle_timeout_release(arg->timer);
wl_display_roundtrip(arg->display);
fprintf(stdout, "close program\n");
run = 0;
return NULL;
}
void *main_loop(void *data) {
struct wl_display *display = data;
while (wl_display_dispatch(display) != -1) {
;
}
return NULL;
}
int main(int argc, char *argv[]) {
wlr_log_init(L_DEBUG, NULL);
if (parse_args(argc, argv) != 0) {
return -1;
}
if (timeout == 0) {
printf("idle timeout 0 is invalid\n");
return -1;
}
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 (idle_manager == NULL) {
fprintf(stderr, "display doesn't support idle protocol\n");
return -1;
}
if (seat== NULL) {
fprintf(stderr, "seat error\n");
return -1;
}
struct org_kde_kwin_idle_timeout *timer =
org_kde_kwin_idle_get_idle_timeout(idle_manager, seat, timeout * 1000);
if (timer == NULL) {
fprintf(stderr, "Could not create idle_timeout\n");
return -1;
}
pthread_t t1, t2, t3;
struct thread_args arg = {
.timer = timer,
.display = display,
};
if (simulate_activity_timeout != 0 && simulate_activity_timeout < close_timeout) {
if (pthread_create(&t1, NULL, &simulate_activity, (void *)&arg) != 0) {
return -1;
}
}
if (close_timeout != 0) {
if (pthread_create(&t2, NULL, &close_program, (void *)&arg) != 0) {
if (simulate_activity_timeout != 0) {
pthread_cancel(t1);
}
return -1;
}
}
org_kde_kwin_idle_timeout_add_listener(timer, &idle_timer_listener, timer);
fprintf(stdout, "waiting\n");
if (pthread_create(&t3, NULL, &main_loop, (void *)display) != 0) {
if (simulate_activity_timeout != 0) {
pthread_cancel(t1);
}
if (close_timeout != 0 ) {
pthread_cancel(t2);
}
}
if (simulate_activity_timeout != 0) {
pthread_join(t1, NULL);
}
if (close_timeout != 0) {
pthread_join(t2, NULL);
}
pthread_cancel(t3);
wl_display_disconnect(display);
return 0;
}

View file

@ -5,6 +5,8 @@ lib_shared = static_library(
include_directories: include_directories('support') include_directories: include_directories('support')
) )
threads = dependency('threads')
executable('simple', 'simple.c', dependencies: wlroots, link_with: lib_shared) executable('simple', 'simple.c', dependencies: wlroots, link_with: lib_shared)
executable('pointer', 'pointer.c', dependencies: wlroots, link_with: lib_shared) executable('pointer', 'pointer.c', dependencies: wlroots, link_with: lib_shared)
executable('touch', 'touch.c', dependencies: wlroots, link_with: lib_shared) executable('touch', 'touch.c', dependencies: wlroots, link_with: lib_shared)
@ -32,3 +34,10 @@ executable(
dependencies: [wayland_client, wlr_protos, wlroots], dependencies: [wayland_client, wlr_protos, wlroots],
link_with: lib_shared, link_with: lib_shared,
) )
executable(
'idle',
'idle.c',
dependencies: [wayland_client, wlr_protos, wlroots, threads],
link_with: lib_shared,
)

View file

@ -176,6 +176,7 @@ static void handle_input_remove(struct compositor_state *state,
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
wlr_log_init(L_DEBUG, NULL);
struct sample_state state = { struct sample_state state = {
.default_color = { 0.25f, 0.25f, 0.25f, 1 }, .default_color = { 0.25f, 0.25f, 0.25f, 1 },
.clear_color = { 0.25f, 0.25f, 0.25f, 1 }, .clear_color = { 0.25f, 0.25f, 0.25f, 1 },

View file

@ -181,6 +181,7 @@ static void handle_keyboard_key(struct keyboard_state *kbstate,
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
wlr_log_init(L_DEBUG, NULL);
struct sample_state state = {0}; struct sample_state state = {0};
state.x_vel = 500; state.x_vel = 500;

View file

@ -257,6 +257,7 @@ static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
wlr_log_init(L_DEBUG, NULL);
struct sample_state state = { struct sample_state state = {
.default_color = { 0.25f, 0.25f, 0.25f, 1 }, .default_color = { 0.25f, 0.25f, 0.25f, 1 },
.clear_color = { 0.25f, 0.25f, 0.25f, 1 }, .clear_color = { 0.25f, 0.25f, 0.25f, 1 },

View file

@ -123,6 +123,7 @@ static void handle_keyboard_key(struct keyboard_state *kbstate,
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
wlr_log_init(L_DEBUG, NULL);
struct sample_state state = {0}; struct sample_state state = {0};
state.config = parse_args(argc, argv); state.config = parse_args(argc, argv);

View file

@ -36,6 +36,7 @@
#include <sys/param.h> #include <sys/param.h>
#include <screenshooter-client-protocol.h> #include <screenshooter-client-protocol.h>
#include "util/os-compatibility.h" #include "util/os-compatibility.h"
#include <wlr/util/log.h>
static struct wl_shm *shm = NULL; static struct wl_shm *shm = NULL;
static struct orbital_screenshooter *screenshooter = NULL; static struct orbital_screenshooter *screenshooter = NULL;
@ -242,6 +243,7 @@ static int set_buffer_size(int *width, int *height) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
wlr_log_init(L_DEBUG, NULL);
struct wl_display * display = wl_display_connect(NULL); struct wl_display * display = wl_display_connect(NULL);
if (display == NULL) { if (display == NULL) {
fprintf(stderr, "failed to create display: %m\n"); fprintf(stderr, "failed to create display: %m\n");

View file

@ -44,6 +44,7 @@ void handle_output_frame(struct output_state *output, struct timespec *ts) {
} }
int main() { int main() {
wlr_log_init(L_DEBUG, NULL);
struct sample_state state = { struct sample_state state = {
.color = { 1.0, 0.0, 0.0 }, .color = { 1.0, 0.0, 0.0 },
.dec = 0, .dec = 0,

View file

@ -425,7 +425,7 @@ static void output_add_notify(struct wl_listener *listener, void *data) {
ostate->frame.notify = output_frame_notify; ostate->frame.notify = output_frame_notify;
ostate->resolution.notify = output_resolution_notify; ostate->resolution.notify = output_resolution_notify;
wl_signal_add(&output->events.frame, &ostate->frame); wl_signal_add(&output->events.frame, &ostate->frame);
wl_signal_add(&output->events.resolution, &ostate->resolution); wl_signal_add(&output->events.mode, &ostate->resolution);
wl_list_insert(&state->outputs, &ostate->link); wl_list_insert(&state->outputs, &ostate->link);
if (state->output_add_cb) { if (state->output_add_cb) {
state->output_add_cb(ostate); state->output_add_cb(ostate);

View file

@ -139,6 +139,7 @@ static void handle_pad_button(struct tablet_pad_state *pstate,
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
wlr_log_init(L_DEBUG, NULL);
struct sample_state state = { struct sample_state state = {
.tool_color = { 1, 1, 1, 1 }, .tool_color = { 1, 1, 1, 1 },
.pad_color = { 0.75, 0.75, 0.75, 1.0 } .pad_color = { 0.75, 0.75, 0.75, 1.0 }

View file

@ -94,6 +94,7 @@ static void handle_touch_motion(struct touch_state *tstate, int32_t touch_id,
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
wlr_log_init(L_DEBUG, NULL);
struct sample_state state; struct sample_state state;
wl_list_init(&state.touch_points); wl_list_init(&state.touch_points);

View file

@ -15,7 +15,7 @@ struct wlr_drm_crtc;
// Used to provide atomic or legacy DRM functions // Used to provide atomic or legacy DRM functions
struct wlr_drm_interface { struct wlr_drm_interface {
// Enable or disable DPMS for connector // Enable or disable DPMS for connector
void (*conn_enable)(struct wlr_drm_backend *drm, bool (*conn_enable)(struct wlr_drm_backend *drm,
struct wlr_drm_connector *conn, bool enable); struct wlr_drm_connector *conn, bool enable);
// Pageflip on crtc. If mode is non-NULL perform a full modeset using it. // Pageflip on crtc. If mode is non-NULL perform a full modeset using it.
bool (*crtc_pageflip)(struct wlr_drm_backend *drm, bool (*crtc_pageflip)(struct wlr_drm_backend *drm,

View file

@ -7,6 +7,7 @@
struct roots_output_config { struct roots_output_config {
char *name; char *name;
bool enable;
enum wl_output_transform transform; enum wl_output_transform transform;
int x, y; int x, y;
float scale; float scale;

View file

@ -13,6 +13,7 @@
#include <wlr/types/wlr_primary_selection.h> #include <wlr/types/wlr_primary_selection.h>
#include <wlr/types/wlr_screenshooter.h> #include <wlr/types/wlr_screenshooter.h>
#include <wlr/types/wlr_list.h> #include <wlr/types/wlr_list.h>
#include <wlr/types/wlr_idle.h>
#include "rootston/view.h" #include "rootston/view.h"
#include "rootston/config.h" #include "rootston/config.h"
@ -44,6 +45,7 @@ struct roots_desktop {
struct wlr_screenshooter *screenshooter; struct wlr_screenshooter *screenshooter;
struct wlr_server_decoration_manager *server_decoration_manager; struct wlr_server_decoration_manager *server_decoration_manager;
struct wlr_primary_selection_device_manager *primary_selection_device_manager; struct wlr_primary_selection_device_manager *primary_selection_device_manager;
struct wlr_idle *idle;
struct wl_listener output_add; struct wl_listener output_add;
struct wl_listener output_remove; struct wl_listener output_remove;

View file

@ -11,8 +11,12 @@
/** /**
* Creates a new wlr_wl_backend. This backend will be created with no outputs; * Creates a new wlr_wl_backend. This backend will be created with no outputs;
* you must use wlr_wl_output_create to add them. * you must use wlr_wl_output_create to add them.
*
* The `remote` argument is the name of the host compositor wayland socket. Set
* to NULL for the default behaviour (WAYLAND_DISPLAY env variable or wayland-0
* default)
*/ */
struct wlr_backend *wlr_wl_backend_create(struct wl_display *display); struct wlr_backend *wlr_wl_backend_create(struct wl_display *display, const char *remote);
/** /**
* Adds a new output to this backend. You may remove outputs by destroying them. * Adds a new output to this backend. You may remove outputs by destroying them.

View file

@ -26,14 +26,11 @@ struct wlr_output_impl {
}; };
void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
const struct wlr_output_impl *impl); const struct wlr_output_impl *impl, struct wl_display *display);
void wlr_output_free(struct wlr_output *output);
void wlr_output_update_mode(struct wlr_output *output, void wlr_output_update_mode(struct wlr_output *output,
struct wlr_output_mode *mode); struct wlr_output_mode *mode);
void wlr_output_update_custom_mode(struct wlr_output *output, int32_t width, void wlr_output_update_custom_mode(struct wlr_output *output, int32_t width,
int32_t height, int32_t refresh); int32_t height, int32_t refresh);
struct wl_global *wlr_output_create_global(struct wlr_output *wlr_output, void wlr_output_update_enabled(struct wlr_output *output, bool enabled);
struct wl_display *display);
void wlr_output_destroy_global(struct wlr_output *wlr_output);
#endif #endif

View file

@ -0,0 +1,51 @@
#ifndef WLR_TYPES_WLR_IDLE_H
#define WLR_TYPES_WLR_IDLE_H
#include <wayland-server.h>
#include <wlr/types/wlr_seat.h>
/**
* Idle protocol is used to create timers which will notify the client when the
* compositor does not receive any input for a given time(in milliseconds). Also
* the client will be notify when the timer receve an activity notify and already
* was in idle state. Besides this, the client is able to simulate user activity
* which will reset the timers and at any time can destroy the timer.
*/
struct wlr_idle {
struct wl_global *wl_global;
struct wl_list idle_timers; // wlr_idle_timeout::link
struct wl_event_loop *event_loop;
struct wl_listener display_destroy;
struct wl_signal activity_notify;
void *data;
};
struct wlr_idle_timeout {
struct wl_resource *resource;
struct wl_list link;
struct wlr_seat *seat;
struct wl_event_source *idle_source;
bool idle_state;
uint32_t timeout; // milliseconds
struct wl_listener input_listener;
struct wl_listener seat_destroy;
void *data;
};
struct wlr_idle *wlr_idle_create(struct wl_display *display);
void wlr_idle_destroy(struct wlr_idle *idle);
/**
* Send notification to restart all timers for the given seat. Called by
* compositor when there is an user activity event on that seat.
*/
void wlr_idle_notify_activity(struct wlr_idle *idle, struct wlr_seat *seat);
#endif

View file

@ -36,19 +36,19 @@ struct wlr_output_impl;
struct wlr_output { struct wlr_output {
const struct wlr_output_impl *impl; const struct wlr_output_impl *impl;
struct wlr_backend *backend; struct wlr_backend *backend;
struct wl_display *display;
struct wl_global *wl_global; struct wl_global *wl_global;
struct wl_list wl_resources; struct wl_list wl_resources;
uint32_t flags;
char name[16]; char name[16];
char make[48]; char make[48];
char model[16]; char model[16];
char serial[16]; char serial[16];
float scale;
int32_t width, height;
int32_t refresh; // mHz
int32_t phys_width, phys_height; // mm int32_t phys_width, phys_height; // mm
bool enabled;
float scale;
enum wl_output_subpixel subpixel; enum wl_output_subpixel subpixel;
enum wl_output_transform transform; enum wl_output_transform transform;
bool needs_swap; bool needs_swap;
@ -58,11 +58,14 @@ struct wlr_output {
// Note: some backends may have zero modes // Note: some backends may have zero modes
struct wl_list modes; struct wl_list modes;
struct wlr_output_mode *current_mode; struct wlr_output_mode *current_mode;
int32_t width, height;
int32_t refresh; // mHz
struct { struct {
struct wl_signal frame; struct wl_signal frame;
struct wl_signal swap_buffers; struct wl_signal swap_buffers;
struct wl_signal resolution; struct wl_signal enable;
struct wl_signal mode;
struct wl_signal scale; struct wl_signal scale;
struct wl_signal transform; struct wl_signal transform;
struct wl_signal destroy; struct wl_signal destroy;

View file

@ -98,9 +98,12 @@ struct wlr_xwayland_surface {
char *title; char *title;
char *class; char *class;
char *instance; char *instance;
struct wlr_xwayland_surface *parent;
pid_t pid; pid_t pid;
struct wl_list children; // wlr_xwayland_surface::parent_link
struct wlr_xwayland_surface *parent;
struct wl_list parent_link; // wlr_xwayland_surface::children
xcb_atom_t *window_type; xcb_atom_t *window_type;
size_t window_type_len; size_t window_type_len;

49
protocol/idle.xml Normal file
View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="idle">
<copyright><![CDATA[
Copyright (C) 2015 Martin Gräßlin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
]]></copyright>
<interface name="org_kde_kwin_idle" version="1">
<description summary="User idle time manager">
This interface allows to monitor user idle time on a given seat. The interface
allows to register timers which trigger after no user activity was registered
on the seat for a given interval. It notifies when user activity resumes.
This is useful for applications wanting to perform actions when the user is not
interacting with the system, e.g. chat applications setting the user as away, power
management features to dim screen, etc..
</description>
<request name="get_idle_timeout">
<arg name="id" type="new_id" interface="org_kde_kwin_idle_timeout"/>
<arg name="seat" type="object" interface="wl_seat"/>
<arg name="timeout" type="uint" summary="The idle timeout in msec"/>
</request>
</interface>
<interface name="org_kde_kwin_idle_timeout" version="1">
<request name="release" type="destructor">
<description summary="release the timeout object"/>
</request>
<request name="simulate_user_activity">
<description summary="Simulates user activity for this timeout, behaves just like real user activity on the seat"/>
</request>
<event name="idle">
<description summary="Triggered when there has not been any user activity in the requested idle time interval"/>
</event>
<event name="resumed">
<description summary="Triggered on the first user activity after an idle event"/>
</event>
</interface>
</protocol>

View file

@ -26,6 +26,7 @@ protocols = [
'gtk-primary-selection.xml', 'gtk-primary-selection.xml',
'screenshooter.xml', 'screenshooter.xml',
'server-decoration.xml', 'server-decoration.xml',
'idle.xml',
] ]
client_protocols = [ client_protocols = [
@ -34,6 +35,7 @@ client_protocols = [
'gtk-primary-selection.xml', 'gtk-primary-selection.xml',
'screenshooter.xml', 'screenshooter.xml',
'server-decoration.xml', 'server-decoration.xml',
'idle.xml',
] ]
wl_protos_src = [] wl_protos_src = []

View file

@ -263,10 +263,19 @@ static int config_ini_handler(void *user, const char *section, const char *name,
oc->name = strdup(output_name); oc->name = strdup(output_name);
oc->transform = WL_OUTPUT_TRANSFORM_NORMAL; oc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
oc->scale = 1; oc->scale = 1;
oc->enable = true;
wl_list_insert(&config->outputs, &oc->link); wl_list_insert(&config->outputs, &oc->link);
} }
if (strcmp(name, "x") == 0) { if (strcmp(name, "enable") == 0) {
if (strcasecmp(value, "true") == 0) {
oc->enable = true;
} else if (strcasecmp(value, "false") == 0) {
oc->enable = false;
} else {
wlr_log(L_ERROR, "got invalid output enable value: %s", value);
}
} else if (strcmp(name, "x") == 0) {
oc->x = strtol(value, NULL, 10); oc->x = strtol(value, NULL, 10);
} else if (strcmp(name, "y") == 0) { } else if (strcmp(name, "y") == 0) {
oc->y = strtol(value, NULL, 10); oc->y = strtol(value, NULL, 10);

View file

@ -8,6 +8,7 @@
#include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_gamma_control.h> #include <wlr/types/wlr_gamma_control.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_primary_selection.h> #include <wlr/types/wlr_primary_selection.h>
#include <wlr/types/wlr_server_decoration.h> #include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
@ -502,6 +503,7 @@ struct roots_desktop *desktop_create(struct roots_server *server,
WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT); WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT);
desktop->primary_selection_device_manager = desktop->primary_selection_device_manager =
wlr_primary_selection_device_manager_create(server->wl_display); wlr_primary_selection_device_manager_create(server->wl_display);
desktop->idle = wlr_idle_create(server->wl_display);
return desktop; return desktop;
} }

View file

@ -2,6 +2,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <stdbool.h>
#include <wayland-server.h> #include <wayland-server.h>
#include <wlr/types/wlr_input_device.h> #include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_pointer.h> #include <wlr/types/wlr_pointer.h>
@ -85,6 +86,8 @@ static void pressed_keysyms_update(xkb_keysym_t *pressed_keysyms,
static const char *exec_prefix = "exec "; static const char *exec_prefix = "exec ";
static bool outputs_enabled = true;
static void keyboard_binding_execute(struct roots_keyboard *keyboard, static void keyboard_binding_execute(struct roots_keyboard *keyboard,
const char *command) { const char *command) {
struct roots_seat *seat = keyboard->seat; struct roots_seat *seat = keyboard->seat;
@ -119,6 +122,12 @@ static void keyboard_binding_execute(struct roots_keyboard *keyboard,
} }
} else if (strcmp(command, "nop") == 0) { } else if (strcmp(command, "nop") == 0) {
wlr_log(L_DEBUG, "nop command"); wlr_log(L_DEBUG, "nop command");
} else if (strcmp(command, "toggle_outputs") == 0) {
outputs_enabled = !outputs_enabled;
struct roots_output *output;
wl_list_for_each(output, &keyboard->input->server->desktop->outputs, link) {
wlr_output_enable(output->wlr_output, outputs_enabled);
}
} else { } else {
wlr_log(L_ERROR, "unknown binding command: %s", command); wlr_log(L_ERROR, "unknown binding command: %s", command);
} }

View file

@ -37,7 +37,6 @@ int main(int argc, char **argv) {
if (server.backend == NULL) { if (server.backend == NULL) {
wlr_log(L_ERROR, "could not start backend"); wlr_log(L_ERROR, "could not start backend");
wlr_backend_destroy(server.backend);
return 1; return 1;
} }

View file

@ -169,6 +169,19 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface,
} }
} }
static void render_xwayland_children(struct wlr_xwayland_surface *surface,
struct roots_desktop *desktop, struct wlr_output *wlr_output,
struct timespec *when) {
struct wlr_xwayland_surface *child;
wl_list_for_each(child, &surface->children, parent_link) {
if (child->surface != NULL && child->added) {
render_surface(child->surface, desktop, wlr_output, when,
child->x, child->y, 0);
}
render_xwayland_children(child, desktop, wlr_output, when);
}
}
static void render_view(struct roots_view *view, struct roots_desktop *desktop, static void render_view(struct roots_view *view, struct roots_desktop *desktop,
struct wlr_output *wlr_output, struct timespec *when) { struct wlr_output *wlr_output, struct timespec *when) {
switch (view->type) { switch (view->type) {
@ -200,7 +213,7 @@ static bool has_standalone_surface(struct roots_view *view) {
case ROOTS_WL_SHELL_VIEW: case ROOTS_WL_SHELL_VIEW:
return wl_list_empty(&view->wl_shell_surface->popups); return wl_list_empty(&view->wl_shell_surface->popups);
case ROOTS_XWAYLAND_VIEW: case ROOTS_XWAYLAND_VIEW:
return true; return wl_list_empty(&view->xwayland_surface->children);
} }
return true; return true;
} }
@ -211,6 +224,10 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
struct roots_desktop *desktop = output->desktop; struct roots_desktop *desktop = output->desktop;
struct roots_server *server = desktop->server; struct roots_server *server = desktop->server;
if (!wlr_output->enabled) {
return;
}
struct timespec now; struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
@ -218,27 +235,36 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
wlr_renderer_begin(server->renderer, wlr_output); wlr_renderer_begin(server->renderer, wlr_output);
if (output->fullscreen_view != NULL) { if (output->fullscreen_view != NULL) {
struct roots_view *view = output->fullscreen_view;
// Make sure the view is centered on screen // Make sure the view is centered on screen
const struct wlr_box *output_box = const struct wlr_box *output_box =
wlr_output_layout_get_box(desktop->layout, wlr_output); wlr_output_layout_get_box(desktop->layout, wlr_output);
struct wlr_box view_box; struct wlr_box view_box;
view_get_box(output->fullscreen_view, &view_box); view_get_box(view, &view_box);
double view_x = (double)(output_box->width - view_box.width) / 2 + double view_x = (double)(output_box->width - view_box.width) / 2 +
output_box->x; output_box->x;
double view_y = (double)(output_box->height - view_box.height) / 2 + double view_y = (double)(output_box->height - view_box.height) / 2 +
output_box->y; output_box->y;
view_move(output->fullscreen_view, view_x, view_y); view_move(view, view_x, view_y);
if (has_standalone_surface(output->fullscreen_view)) { if (has_standalone_surface(view)) {
wlr_output_set_fullscreen_surface(wlr_output, wlr_output_set_fullscreen_surface(wlr_output, view->wlr_surface);
output->fullscreen_view->wlr_surface);
} else { } else {
wlr_output_set_fullscreen_surface(wlr_output, NULL); wlr_output_set_fullscreen_surface(wlr_output, NULL);
glClearColor(0, 0, 0, 0); glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
render_view(output->fullscreen_view, desktop, wlr_output, &now); render_view(view, desktop, wlr_output, &now);
// During normal rendering the xwayland window tree isn't traversed
// because all windows are rendered. Here we only want to render
// the fullscreen window's children so we have to traverse the tree.
if (view->type == ROOTS_XWAYLAND_VIEW) {
render_xwayland_children(view->xwayland_surface, desktop,
wlr_output, &now);
}
} }
wlr_renderer_end(server->renderer); wlr_renderer_end(server->renderer);
wlr_output_swap_buffers(wlr_output); wlr_output_swap_buffers(wlr_output);
@ -324,9 +350,10 @@ void output_add_notify(struct wl_listener *listener, void *data) {
wlr_log(L_DEBUG, "'%s %s %s' %"PRId32"mm x %"PRId32"mm", wlr_output->make, wlr_log(L_DEBUG, "'%s %s %s' %"PRId32"mm x %"PRId32"mm", wlr_output->make,
wlr_output->model, wlr_output->serial, wlr_output->phys_width, wlr_output->model, wlr_output->serial, wlr_output->phys_width,
wlr_output->phys_height); wlr_output->phys_height);
if (wl_list_length(&wlr_output->modes) > 0) { if (wl_list_length(&wlr_output->modes) > 0) {
struct wlr_output_mode *mode = NULL; struct wlr_output_mode *mode =
mode = wl_container_of((&wlr_output->modes)->prev, mode, link); wl_container_of((&wlr_output->modes)->prev, mode, link);
wlr_output_set_mode(wlr_output, mode); wlr_output_set_mode(wlr_output, mode);
} }
@ -341,13 +368,17 @@ void output_add_notify(struct wl_listener *listener, void *data) {
struct roots_output_config *output_config = struct roots_output_config *output_config =
roots_config_get_output(config, wlr_output); roots_config_get_output(config, wlr_output);
if (output_config) { if (output_config) {
if (output_config->mode.width) { if (output_config->enable) {
set_mode(wlr_output, output_config); 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,
output_config->y);
} else {
wlr_output_enable(wlr_output, false);
} }
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,
output_config->y);
} else { } else {
wlr_output_layout_add_auto(desktop->layout, wlr_output); wlr_output_layout_add_auto(desktop->layout, wlr_output);
} }

View file

@ -5,6 +5,7 @@
#include <wlr/config.h> #include <wlr/config.h>
#include <wlr/types/wlr_xcursor_manager.h> #include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include <wlr/types/wlr_idle.h>
#include "rootston/xcursor.h" #include "rootston/xcursor.h"
#include "rootston/input.h" #include "rootston/input.h"
#include "rootston/seat.h" #include "rootston/seat.h"
@ -14,6 +15,8 @@
static void handle_keyboard_key(struct wl_listener *listener, void *data) { static void handle_keyboard_key(struct wl_listener *listener, void *data) {
struct roots_keyboard *keyboard = struct roots_keyboard *keyboard =
wl_container_of(listener, keyboard, keyboard_key); wl_container_of(listener, keyboard, keyboard_key);
struct roots_desktop *desktop = keyboard->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, keyboard->seat->seat);
struct wlr_event_keyboard_key *event = data; struct wlr_event_keyboard_key *event = data;
roots_keyboard_handle_key(keyboard, event); roots_keyboard_handle_key(keyboard, event);
} }
@ -22,12 +25,16 @@ static void handle_keyboard_modifiers(struct wl_listener *listener,
void *data) { void *data) {
struct roots_keyboard *keyboard = struct roots_keyboard *keyboard =
wl_container_of(listener, keyboard, keyboard_modifiers); wl_container_of(listener, keyboard, keyboard_modifiers);
struct roots_desktop *desktop = keyboard->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, keyboard->seat->seat);
roots_keyboard_handle_modifiers(keyboard); roots_keyboard_handle_modifiers(keyboard);
} }
static void handle_cursor_motion(struct wl_listener *listener, void *data) { static void handle_cursor_motion(struct wl_listener *listener, void *data) {
struct roots_cursor *cursor = struct roots_cursor *cursor =
wl_container_of(listener, cursor, motion); wl_container_of(listener, cursor, motion);
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
struct wlr_event_pointer_motion *event = data; struct wlr_event_pointer_motion *event = data;
roots_cursor_handle_motion(cursor, event); roots_cursor_handle_motion(cursor, event);
} }
@ -36,6 +43,8 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener,
void *data) { void *data) {
struct roots_cursor *cursor = struct roots_cursor *cursor =
wl_container_of(listener, cursor, motion_absolute); wl_container_of(listener, cursor, motion_absolute);
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
struct wlr_event_pointer_motion_absolute *event = data; struct wlr_event_pointer_motion_absolute *event = data;
roots_cursor_handle_motion_absolute(cursor, event); roots_cursor_handle_motion_absolute(cursor, event);
} }
@ -43,6 +52,8 @@ static void handle_cursor_motion_absolute(struct wl_listener *listener,
static void handle_cursor_button(struct wl_listener *listener, void *data) { static void handle_cursor_button(struct wl_listener *listener, void *data) {
struct roots_cursor *cursor = struct roots_cursor *cursor =
wl_container_of(listener, cursor, button); wl_container_of(listener, cursor, button);
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
struct wlr_event_pointer_button *event = data; struct wlr_event_pointer_button *event = data;
roots_cursor_handle_button(cursor, event); roots_cursor_handle_button(cursor, event);
} }
@ -50,6 +61,8 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
static void handle_cursor_axis(struct wl_listener *listener, void *data) { static void handle_cursor_axis(struct wl_listener *listener, void *data) {
struct roots_cursor *cursor = struct roots_cursor *cursor =
wl_container_of(listener, cursor, axis); wl_container_of(listener, cursor, axis);
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
struct wlr_event_pointer_axis *event = data; struct wlr_event_pointer_axis *event = data;
roots_cursor_handle_axis(cursor, event); roots_cursor_handle_axis(cursor, event);
} }
@ -57,6 +70,8 @@ static void handle_cursor_axis(struct wl_listener *listener, void *data) {
static void handle_touch_down(struct wl_listener *listener, void *data) { static void handle_touch_down(struct wl_listener *listener, void *data) {
struct roots_cursor *cursor = struct roots_cursor *cursor =
wl_container_of(listener, cursor, touch_down); wl_container_of(listener, cursor, touch_down);
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
struct wlr_event_touch_down *event = data; struct wlr_event_touch_down *event = data;
roots_cursor_handle_touch_down(cursor, event); roots_cursor_handle_touch_down(cursor, event);
} }
@ -64,6 +79,8 @@ static void handle_touch_down(struct wl_listener *listener, void *data) {
static void handle_touch_up(struct wl_listener *listener, void *data) { static void handle_touch_up(struct wl_listener *listener, void *data) {
struct roots_cursor *cursor = struct roots_cursor *cursor =
wl_container_of(listener, cursor, touch_up); wl_container_of(listener, cursor, touch_up);
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
struct wlr_event_touch_up *event = data; struct wlr_event_touch_up *event = data;
roots_cursor_handle_touch_up(cursor, event); roots_cursor_handle_touch_up(cursor, event);
} }
@ -71,6 +88,8 @@ static void handle_touch_up(struct wl_listener *listener, void *data) {
static void handle_touch_motion(struct wl_listener *listener, void *data) { static void handle_touch_motion(struct wl_listener *listener, void *data) {
struct roots_cursor *cursor = struct roots_cursor *cursor =
wl_container_of(listener, cursor, touch_motion); wl_container_of(listener, cursor, touch_motion);
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
struct wlr_event_touch_motion *event = data; struct wlr_event_touch_motion *event = data;
roots_cursor_handle_touch_motion(cursor, event); roots_cursor_handle_touch_motion(cursor, event);
} }
@ -78,6 +97,8 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) {
static void handle_tool_axis(struct wl_listener *listener, void *data) { static void handle_tool_axis(struct wl_listener *listener, void *data) {
struct roots_cursor *cursor = struct roots_cursor *cursor =
wl_container_of(listener, cursor, tool_axis); wl_container_of(listener, cursor, tool_axis);
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
struct wlr_event_tablet_tool_axis *event = data; struct wlr_event_tablet_tool_axis *event = data;
roots_cursor_handle_tool_axis(cursor, event); roots_cursor_handle_tool_axis(cursor, event);
} }
@ -85,6 +106,8 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) {
static void handle_tool_tip(struct wl_listener *listener, void *data) { static void handle_tool_tip(struct wl_listener *listener, void *data) {
struct roots_cursor *cursor = struct roots_cursor *cursor =
wl_container_of(listener, cursor, tool_tip); wl_container_of(listener, cursor, tool_tip);
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
struct wlr_event_tablet_tool_tip *event = data; struct wlr_event_tablet_tool_tip *event = data;
roots_cursor_handle_tool_tip(cursor, event); roots_cursor_handle_tool_tip(cursor, event);
} }
@ -93,6 +116,8 @@ static void handle_request_set_cursor(struct wl_listener *listener,
void *data) { void *data) {
struct roots_cursor *cursor = struct roots_cursor *cursor =
wl_container_of(listener, cursor, request_set_cursor); wl_container_of(listener, cursor, request_set_cursor);
struct roots_desktop *desktop = cursor->seat->input->server->desktop;
wlr_idle_notify_activity(desktop->idle, cursor->seat->seat);
struct wlr_seat_pointer_request_set_cursor_event *event = data; struct wlr_seat_pointer_request_set_cursor_event *event = data;
roots_cursor_handle_request_set_cursor(cursor, event); roots_cursor_handle_request_set_cursor(cursor, event);
} }
@ -268,11 +293,6 @@ struct roots_seat *roots_seat_create(struct roots_input *input, char *name) {
return NULL; return NULL;
} }
wlr_seat_set_capabilities(seat->seat,
WL_SEAT_CAPABILITY_KEYBOARD |
WL_SEAT_CAPABILITY_POINTER |
WL_SEAT_CAPABILITY_TOUCH);
wl_list_insert(&input->seats, &seat->link); wl_list_insert(&input->seats, &seat->link);
seat->seat_destroy.notify = roots_seat_handle_seat_destroy; seat->seat_destroy.notify = roots_seat_handle_seat_destroy;
@ -281,6 +301,28 @@ struct roots_seat *roots_seat_create(struct roots_input *input, char *name) {
return seat; return seat;
} }
static void seat_update_capabilities(struct roots_seat *seat) {
uint32_t caps = 0;
if (!wl_list_empty(&seat->keyboards)) {
caps |= WL_SEAT_CAPABILITY_KEYBOARD;
}
if (!wl_list_empty(&seat->pointers) || !wl_list_empty(&seat->tablet_tools)) {
caps |= WL_SEAT_CAPABILITY_POINTER;
}
if (!wl_list_empty(&seat->touch)) {
caps |= WL_SEAT_CAPABILITY_TOUCH;
}
wlr_seat_set_capabilities(seat->seat, caps);
// Hide cursor if seat doesn't have pointer capability
if ((caps & WL_SEAT_CAPABILITY_POINTER) == 0) {
wlr_cursor_set_image(seat->cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
} else {
wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager,
seat->cursor->default_xcursor, seat->cursor->cursor);
}
}
static void seat_add_keyboard(struct roots_seat *seat, static void seat_add_keyboard(struct roots_seat *seat,
struct wlr_input_device *device) { struct wlr_input_device *device) {
assert(device->type == WLR_INPUT_DEVICE_KEYBOARD); assert(device->type == WLR_INPUT_DEVICE_KEYBOARD);
@ -379,6 +421,8 @@ void roots_seat_add_device(struct roots_seat *seat,
seat_add_tablet_tool(seat, device); seat_add_tablet_tool(seat, device);
break; break;
} }
seat_update_capabilities(seat);
} }
static void seat_remove_keyboard(struct roots_seat *seat, static void seat_remove_keyboard(struct roots_seat *seat,
@ -455,6 +499,8 @@ void roots_seat_remove_device(struct roots_seat *seat,
seat_remove_tablet_tool(seat, device); seat_remove_tablet_tool(seat, device);
break; break;
} }
seat_update_capabilities(seat);
} }
void roots_seat_configure_xcursor(struct roots_seat *seat) { void roots_seat_configure_xcursor(struct roots_seat *seat) {

View file

@ -6,6 +6,7 @@ lib_wlr_types = static_library(
'wlr_compositor.c', 'wlr_compositor.c',
'wlr_cursor.c', 'wlr_cursor.c',
'wlr_gamma_control.c', 'wlr_gamma_control.c',
'wlr_idle.c',
'wlr_input_device.c', 'wlr_input_device.c',
'wlr_keyboard.c', 'wlr_keyboard.c',
'wlr_list.c', 'wlr_list.c',

190
types/wlr_idle.c Normal file
View file

@ -0,0 +1,190 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-server.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/util/log.h>
#include "idle-protocol.h"
static void idle_timeout_destroy(struct wlr_idle_timeout *timer) {
wl_list_remove(&timer->input_listener.link);
wl_list_remove(&timer->seat_destroy.link);
wl_event_source_remove(timer->idle_source);
wl_list_remove(&timer->link);
wl_resource_set_user_data(timer->resource, NULL);
free(timer);
}
static int idle_notify(void *data) {
struct wlr_idle_timeout *timer = data;
timer->idle_state = true;
org_kde_kwin_idle_timeout_send_idle(timer->resource);
return 1;
}
static void handle_activity(struct wlr_idle_timeout *timer) {
// rearm the timer
wl_event_source_timer_update(timer->idle_source, timer->timeout);
// in case the previous state was sleeping send a resume event and switch state
if (timer->idle_state) {
timer->idle_state = false;
org_kde_kwin_idle_timeout_send_resumed(timer->resource);
}
}
static void handle_timer_resource_destroy(struct wl_resource *timer_resource) {
struct wlr_idle_timeout *timer = wl_resource_get_user_data(timer_resource);
if (timer != NULL) {
idle_timeout_destroy(timer);
}
}
static void handle_seat_destroy(struct wl_listener *listener, void *data) {
struct wlr_idle_timeout *timer = wl_container_of(listener, timer, seat_destroy);
if (timer != NULL) {
idle_timeout_destroy(timer);
}
}
static void release_idle_timeout(struct wl_client *client,
struct wl_resource *resource){
handle_timer_resource_destroy(resource);
}
static void simulate_activity(struct wl_client *client,
struct wl_resource *resource){
struct wlr_idle_timeout *timer = wl_resource_get_user_data(resource);
handle_activity(timer);
}
static struct org_kde_kwin_idle_timeout_interface idle_timeout_impl = {
.release = release_idle_timeout,
.simulate_user_activity = simulate_activity,
};
static void handle_input_notification(struct wl_listener *listener, void *data) {
struct wlr_idle_timeout *timer = wl_container_of(listener, timer, input_listener);
struct wlr_seat *seat = data;
if (timer->seat == seat) {
handle_activity(timer);
}
}
static void create_idle_timer(struct wl_client *client,
struct wl_resource *idle_resource,
uint32_t id,
struct wl_resource *seat_resource,
uint32_t timeout) {
struct wlr_idle *idle = wl_resource_get_user_data(idle_resource);
struct wlr_seat_client *client_seat =
wl_resource_get_user_data(seat_resource);
struct wlr_idle_timeout *timer =
calloc(1, sizeof(struct wlr_idle_timeout));
if (!timer) {
wl_resource_post_no_memory(idle_resource);
return;
}
timer->seat = client_seat->seat;
timer->timeout = timeout;
timer->idle_state = false;
timer->resource = wl_resource_create(client,
&org_kde_kwin_idle_timeout_interface,
wl_resource_get_version(idle_resource), id);
if (timer->resource == NULL) {
free(timer);
wl_resource_post_no_memory(idle_resource);
return;
}
wl_resource_set_implementation(timer->resource, &idle_timeout_impl, timer,
handle_timer_resource_destroy);
wl_list_insert(&idle->idle_timers, &timer->link);
timer->seat_destroy.notify = handle_seat_destroy;
wl_signal_add(&timer->seat->events.destroy, &timer->seat_destroy);
timer->input_listener.notify = handle_input_notification;
wl_signal_add(&idle->activity_notify, &timer->input_listener);
// create the timer
timer->idle_source =
wl_event_loop_add_timer(idle->event_loop, idle_notify, timer);
if (timer->idle_source == NULL) {
wl_list_remove(&timer->link);
wl_list_remove(&timer->input_listener.link);
wl_list_remove(&timer->seat_destroy.link);
wl_resource_set_user_data(timer->resource, NULL);
free(timer);
wl_resource_post_no_memory(idle_resource);
return;
}
// arm the timer
wl_event_source_timer_update(timer->idle_source, timer->timeout);
}
static struct org_kde_kwin_idle_interface idle_impl = {
.get_idle_timeout = create_idle_timer,
};
static void idle_bind(struct wl_client *wl_client, void *data,
uint32_t version, uint32_t id) {
struct wlr_idle *idle = data;
assert(wl_client && idle);
struct wl_resource *wl_resource = wl_resource_create(wl_client,
&org_kde_kwin_idle_interface, version, id);
if (wl_resource == NULL) {
wl_client_post_no_memory(wl_client);
return;
}
wl_resource_set_implementation(wl_resource, &idle_impl, idle, NULL);
}
void wlr_idle_destroy(struct wlr_idle *idle) {
if (!idle) {
return;
}
wl_list_remove(&idle->display_destroy.link);
struct wlr_idle_timeout *timer, *tmp;
wl_list_for_each_safe(timer, tmp, &idle->idle_timers, link) {
idle_timeout_destroy(timer);
}
wl_global_destroy(idle->wl_global);
free(idle);
}
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_idle *idle = wl_container_of(listener, idle, display_destroy);
wlr_idle_destroy(idle);
}
struct wlr_idle *wlr_idle_create(struct wl_display *display) {
struct wlr_idle *idle = calloc(1, sizeof(struct wlr_idle));
if (!idle) {
return NULL;
}
wl_list_init(&idle->idle_timers);
wl_signal_init(&idle->activity_notify);
idle->event_loop = wl_display_get_event_loop(display);
if (idle->event_loop == NULL) {
free(idle);
return NULL;
}
idle->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &idle->display_destroy);
idle->wl_global = wl_global_create(display, &org_kde_kwin_idle_interface,
1, idle, idle_bind);
if (idle->wl_global == NULL){
wl_list_remove(&idle->display_destroy.link);
free(idle);
return NULL;
}
wlr_log(L_DEBUG, "idle manager created");
return idle;
}
void wlr_idle_notify_activity(struct wlr_idle *idle, struct wlr_seat *seat) {
wl_signal_emit(&idle->activity_notify, seat);
}

View file

@ -113,38 +113,41 @@ static void wl_output_bind(struct wl_client *wl_client, void *data,
wl_output_send_to_resource(wl_resource); wl_output_send_to_resource(wl_resource);
} }
static void handle_display_destroy(struct wl_listener *listener, void *data) { static void wlr_output_create_global(struct wlr_output *output) {
struct wlr_output *output = if (output->wl_global != NULL) {
wl_container_of(listener, output, display_destroy); return;
wlr_output_destroy_global(output); }
} struct wl_global *wl_global = wl_global_create(output->display,
&wl_output_interface, 3, output, wl_output_bind);
struct wl_global *wlr_output_create_global(struct wlr_output *wlr_output, output->wl_global = wl_global;
struct wl_display *display) { }
if (wlr_output->wl_global != NULL) {
return wlr_output->wl_global; static void wlr_output_destroy_global(struct wlr_output *output) {
} if (output->wl_global == NULL) {
struct wl_global *wl_global = wl_global_create(display,
&wl_output_interface, 3, wlr_output, wl_output_bind);
wlr_output->wl_global = wl_global;
wlr_output->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &wlr_output->display_destroy);
return wl_global;
}
void wlr_output_destroy_global(struct wlr_output *wlr_output) {
if (wlr_output->wl_global == NULL) {
return; return;
} }
wl_list_remove(&wlr_output->display_destroy.link);
struct wl_resource *resource, *tmp; struct wl_resource *resource, *tmp;
wl_resource_for_each_safe(resource, tmp, &wlr_output->wl_resources) { wl_resource_for_each_safe(resource, tmp, &output->wl_resources) {
wl_resource_destroy(resource); wl_resource_destroy(resource);
} }
wl_global_destroy(wlr_output->wl_global); wl_global_destroy(output->wl_global);
wlr_output->wl_global = NULL; output->wl_global = NULL;
}
void wlr_output_update_enabled(struct wlr_output *output, bool enabled) {
if (output->enabled == enabled) {
return;
}
output->enabled = enabled;
if (enabled) {
wlr_output_create_global(output);
} else {
wlr_output_destroy_global(output);
}
wl_signal_emit(&output->events.enable, output);
} }
static void wlr_output_update_matrix(struct wlr_output *output) { static void wlr_output_update_matrix(struct wlr_output *output) {
@ -153,6 +156,10 @@ static void wlr_output_update_matrix(struct wlr_output *output) {
} }
void wlr_output_enable(struct wlr_output *output, bool enable) { void wlr_output_enable(struct wlr_output *output, bool enable) {
if (output->enabled == enable) {
return;
}
if (output->impl->enable) { if (output->impl->enable) {
output->impl->enable(output, enable); output->impl->enable(output, enable);
} }
@ -199,7 +206,7 @@ void wlr_output_update_custom_mode(struct wlr_output *output, int32_t width,
wlr_output_send_current_mode_to_resource(resource); wlr_output_send_current_mode_to_resource(resource);
} }
wl_signal_emit(&output->events.resolution, output); wl_signal_emit(&output->events.mode, output);
} }
void wlr_output_set_transform(struct wlr_output *output, void wlr_output_set_transform(struct wlr_output *output,
@ -248,11 +255,18 @@ void wlr_output_set_scale(struct wlr_output *output, float scale) {
wl_signal_emit(&output->events.scale, output); wl_signal_emit(&output->events.scale, output);
} }
static void handle_display_destroy(struct wl_listener *listener, void *data) {
struct wlr_output *output =
wl_container_of(listener, output, display_destroy);
wlr_output_destroy_global(output);
}
void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
const struct wlr_output_impl *impl) { const struct wlr_output_impl *impl, struct wl_display *display) {
assert(impl->make_current && impl->swap_buffers && impl->transform); assert(impl->make_current && impl->swap_buffers && impl->transform);
output->backend = backend; output->backend = backend;
output->impl = impl; output->impl = impl;
output->display = display;
wl_list_init(&output->modes); wl_list_init(&output->modes);
output->transform = WL_OUTPUT_TRANSFORM_NORMAL; output->transform = WL_OUTPUT_TRANSFORM_NORMAL;
output->scale = 1; output->scale = 1;
@ -260,10 +274,14 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
wl_list_init(&output->wl_resources); wl_list_init(&output->wl_resources);
wl_signal_init(&output->events.frame); wl_signal_init(&output->events.frame);
wl_signal_init(&output->events.swap_buffers); wl_signal_init(&output->events.swap_buffers);
wl_signal_init(&output->events.resolution); wl_signal_init(&output->events.enable);
wl_signal_init(&output->events.mode);
wl_signal_init(&output->events.scale); wl_signal_init(&output->events.scale);
wl_signal_init(&output->events.transform); wl_signal_init(&output->events.transform);
wl_signal_init(&output->events.destroy); wl_signal_init(&output->events.destroy);
output->display_destroy.notify = handle_display_destroy;
wl_display_add_destroy_listener(display, &output->display_destroy);
} }
void wlr_output_destroy(struct wlr_output *output) { void wlr_output_destroy(struct wlr_output *output) {
@ -271,6 +289,7 @@ void wlr_output_destroy(struct wlr_output *output) {
return; return;
} }
wl_list_remove(&output->display_destroy.link);
wlr_output_destroy_global(output); wlr_output_destroy_global(output);
wlr_output_set_fullscreen_surface(output, NULL); wlr_output_set_fullscreen_surface(output, NULL);

View file

@ -18,7 +18,7 @@ struct wlr_output_layout_output_state {
struct wlr_box _box; // should never be read directly, use the getter struct wlr_box _box; // should never be read directly, use the getter
bool auto_configured; bool auto_configured;
struct wl_listener resolution; struct wl_listener mode;
struct wl_listener scale; struct wl_listener scale;
struct wl_listener transform; struct wl_listener transform;
struct wl_listener output_destroy; struct wl_listener output_destroy;
@ -47,7 +47,7 @@ struct wlr_output_layout *wlr_output_layout_create() {
static void wlr_output_layout_output_destroy( static void wlr_output_layout_output_destroy(
struct wlr_output_layout_output *l_output) { struct wlr_output_layout_output *l_output) {
wl_signal_emit(&l_output->events.destroy, l_output); wl_signal_emit(&l_output->events.destroy, l_output);
wl_list_remove(&l_output->state->resolution.link); wl_list_remove(&l_output->state->mode.link);
wl_list_remove(&l_output->state->scale.link); wl_list_remove(&l_output->state->scale.link);
wl_list_remove(&l_output->state->transform.link); wl_list_remove(&l_output->state->transform.link);
wl_list_remove(&l_output->state->output_destroy.link); wl_list_remove(&l_output->state->output_destroy.link);
@ -132,9 +132,9 @@ static void wlr_output_layout_reconfigure(struct wlr_output_layout *layout) {
wl_signal_emit(&layout->events.change, layout); wl_signal_emit(&layout->events.change, layout);
} }
static void handle_output_resolution(struct wl_listener *listener, void *data) { static void handle_output_mode(struct wl_listener *listener, void *data) {
struct wlr_output_layout_output_state *state = struct wlr_output_layout_output_state *state =
wl_container_of(listener, state, resolution); wl_container_of(listener, state, mode);
wlr_output_layout_reconfigure(state->layout); wlr_output_layout_reconfigure(state->layout);
} }
@ -176,8 +176,8 @@ static struct wlr_output_layout_output *wlr_output_layout_output_create(
wl_signal_init(&l_output->events.destroy); wl_signal_init(&l_output->events.destroy);
wl_list_insert(&layout->outputs, &l_output->link); wl_list_insert(&layout->outputs, &l_output->link);
wl_signal_add(&output->events.resolution, &l_output->state->resolution); wl_signal_add(&output->events.mode, &l_output->state->mode);
l_output->state->resolution.notify = handle_output_resolution; l_output->state->mode.notify = handle_output_mode;
wl_signal_add(&output->events.scale, &l_output->state->scale); wl_signal_add(&output->events.scale, &l_output->state->scale);
l_output->state->scale.notify = handle_output_scale; l_output->state->scale.notify = handle_output_scale;
wl_signal_add(&output->events.transform, &l_output->state->transform); wl_signal_add(&output->events.transform, &l_output->state->transform);

View file

@ -96,6 +96,8 @@ static struct wlr_xwayland_surface *wlr_xwayland_surface_create(
surface->height = height; surface->height = height;
surface->override_redirect = override_redirect; surface->override_redirect = override_redirect;
wl_list_insert(&xwm->surfaces, &surface->link); wl_list_insert(&xwm->surfaces, &surface->link);
wl_list_init(&surface->children);
wl_list_init(&surface->parent_link);
wl_signal_init(&surface->events.destroy); wl_signal_init(&surface->events.destroy);
wl_signal_init(&surface->events.request_configure); wl_signal_init(&surface->events.request_configure);
wl_signal_init(&surface->events.request_move); wl_signal_init(&surface->events.request_move);
@ -215,6 +217,7 @@ static void wlr_xwayland_surface_destroy(
} }
wl_list_remove(&xsurface->link); wl_list_remove(&xsurface->link);
wl_list_remove(&xsurface->parent_link);
if (xsurface->surface_id) { if (xsurface->surface_id) {
wl_list_remove(&xsurface->unpaired_link); wl_list_remove(&xsurface->unpaired_link);
@ -305,6 +308,13 @@ static void read_surface_parent(struct wlr_xwm *xwm,
xsurface->parent = NULL; xsurface->parent = NULL;
} }
wl_list_remove(&xsurface->parent_link);
if (xsurface->parent != NULL) {
wl_list_insert(&xsurface->parent->children, &xsurface->parent_link);
} else {
wl_list_init(&xsurface->parent_link);
}
wlr_log(L_DEBUG, "XCB_ATOM_WM_TRANSIENT_FOR: %p", xid); wlr_log(L_DEBUG, "XCB_ATOM_WM_TRANSIENT_FOR: %p", xid);
wl_signal_emit(&xsurface->events.set_parent, xsurface); wl_signal_emit(&xsurface->events.set_parent, xsurface);
} }