Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

Fix VT switching with libinput backend #18

Merged
merged 4 commits into from
Jun 21, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 18 additions & 36 deletions backend/drm/backend.c
Original file line number Diff line number Diff line change
@@ -40,36 +40,24 @@ static struct wlr_backend_impl backend_impl = {
.destroy = wlr_drm_backend_destroy
};

static void device_paused(struct wl_listener *listener, void *data) {
struct wlr_backend_state *drm = wl_container_of(listener, drm, device_paused);
struct device_arg *arg = data;

// TODO: Actually pause the renderer or something.
// We currently just expect it to fail its next pageflip.

if (arg->dev == drm->dev) {
static void session_signal(struct wl_listener *listener, void *data) {
struct wlr_backend_state *drm = wl_container_of(listener, drm, session_signal);
struct wlr_session *session = data;

if (session->active) {
wlr_log(L_INFO, "DRM fd resumed");

for (size_t i = 0; i < drm->outputs->length; ++i) {
struct wlr_output_state *output = drm->outputs->items[i];
wlr_drm_output_start_renderer(output);
}
} else {
wlr_log(L_INFO, "DRM fd paused");
}
}

static void device_resumed(struct wl_listener *listener, void *data) {
struct wlr_backend_state *drm = wl_container_of(listener, drm, device_resumed);
struct device_arg *arg = data;

if (arg->dev != drm->dev) {
return;
}

if (dup2(arg->fd, drm->fd) < 0) {
wlr_log(L_ERROR, "dup2 failed: %s", strerror(errno));
return;
}

wlr_log(L_INFO, "DRM fd resumed");

for (size_t i = 0; i < drm->outputs->length; ++i) {
struct wlr_output_state *output = drm->outputs->items[i];
wlr_drm_output_start_renderer(output);
for (size_t i = 0; i < drm->outputs->length; ++i) {
struct wlr_output_state *output = drm->outputs->items[i];
wlr_drm_output_pause_renderer(output);
}
}
}

@@ -139,14 +127,8 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
goto error_fd;
}

wl_list_init(&state->device_paused.link);
wl_list_init(&state->device_paused.link);

state->device_paused.notify = device_paused;
state->device_resumed.notify = device_resumed;

wl_signal_add(&session->device_paused, &state->device_paused);
wl_signal_add(&session->device_resumed, &state->device_resumed);
state->session_signal.notify = session_signal;
wl_signal_add(&session->session_signal, &state->session_signal);

// TODO: what is the difference between the per-output renderer and this
// one?
17 changes: 16 additions & 1 deletion backend/drm/drm.c
Original file line number Diff line number Diff line change
@@ -116,6 +116,21 @@ static void wlr_drm_output_end(struct wlr_output_state *output) {
output->bo[0] = bo;
}

void wlr_drm_output_pause_renderer(struct wlr_output_state *output) {
if (output->state != DRM_OUTPUT_CONNECTED) {
return;
}

if (output->bo[1]) {
gbm_surface_release_buffer(output->gbm, output->bo[1]);
output->bo[1] = NULL;
}
if (output->bo[0]) {
gbm_surface_release_buffer(output->gbm, output->bo[0]);
output->bo[0] = NULL;
}
}

void wlr_drm_output_start_renderer(struct wlr_output_state *output) {
if (output->state != DRM_OUTPUT_CONNECTED) {
return;
@@ -608,7 +623,7 @@ static void page_flip_handler(int fd, unsigned seq,
}

output->pageflip_pending = false;
if (output->state == DRM_OUTPUT_CONNECTED) {
if (output->state == DRM_OUTPUT_CONNECTED && state->session->active) {
wlr_drm_output_begin(output);
wl_signal_emit(&output->wlr_output->events.frame, output->wlr_output);
wlr_drm_output_end(output);
18 changes: 18 additions & 0 deletions backend/libinput/backend.c
Original file line number Diff line number Diff line change
@@ -86,6 +86,21 @@ static struct wlr_backend_impl backend_impl = {
.destroy = wlr_libinput_backend_destroy
};

static void session_signal(struct wl_listener *listener, void *data) {
struct wlr_backend_state *backend = wl_container_of(listener, backend, session_signal);
struct wlr_session *session = data;

if (!backend->libinput) {
return;
}

if (session->active) {
libinput_resume(backend->libinput);
} else {
libinput_suspend(backend->libinput);
}
}

struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
struct wlr_session *session, struct wlr_udev *udev) {
assert(display && session && udev);
@@ -112,6 +127,9 @@ struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
state->udev = udev;
state->display = display;

state->session_signal.notify = session_signal;
wl_signal_add(&session->session_signal, &state->session_signal);

return backend;
error_state:
free(state);
2 changes: 2 additions & 0 deletions example/pointer.c
Original file line number Diff line number Diff line change
@@ -50,6 +50,8 @@ static void handle_keyboard_key(struct keyboard_state *kbstate,
xkb_keysym_t sym, enum wlr_key_state key_state) {
if (sym == XKB_KEY_Escape) {
kbstate->compositor->exit = true;
} else if (key_state == WLR_KEY_PRESSED && sym >= XKB_KEY_F1 && sym <= XKB_KEY_F12) {
wlr_session_change_vt(kbstate->compositor->session, sym - XKB_KEY_F1 + 1);
}
}

4 changes: 4 additions & 0 deletions example/rotation.c
Original file line number Diff line number Diff line change
@@ -123,6 +123,10 @@ static void handle_keyboard_key(struct keyboard_state *kbstate,
update_velocities(kbstate->compositor, 0, 16);
break;
}

if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F12) {
wlr_session_change_vt(kbstate->compositor->session, sym - XKB_KEY_F1 + 1);
}
}
}

2 changes: 2 additions & 0 deletions example/simple.c
Original file line number Diff line number Diff line change
@@ -42,6 +42,8 @@ static void handle_keyboard_key(struct keyboard_state *kbstate,
xkb_keysym_t sym, enum wlr_key_state key_state) {
if (sym == XKB_KEY_Escape) {
kbstate->compositor->exit = true;
} else if (key_state == WLR_KEY_PRESSED && sym >= XKB_KEY_F1 && sym <= XKB_KEY_F12) {
wlr_session_change_vt(kbstate->compositor->session, sym - XKB_KEY_F1 + 1);
}
}

2 changes: 2 additions & 0 deletions example/tablet.c
Original file line number Diff line number Diff line change
@@ -78,6 +78,8 @@ static void handle_keyboard_key(struct keyboard_state *kbstate,
xkb_keysym_t sym, enum wlr_key_state key_state) {
if (sym == XKB_KEY_Escape) {
kbstate->compositor->exit = true;
} else if (key_state == WLR_KEY_PRESSED && sym >= XKB_KEY_F1 && sym <= XKB_KEY_F12) {
wlr_session_change_vt(kbstate->compositor->session, sym - XKB_KEY_F1 + 1);
}
}

2 changes: 2 additions & 0 deletions example/touch.c
Original file line number Diff line number Diff line change
@@ -59,6 +59,8 @@ static void handle_keyboard_key(struct keyboard_state *kbstate,
xkb_keysym_t sym, enum wlr_key_state key_state) {
if (sym == XKB_KEY_Escape) {
kbstate->compositor->exit = true;
} else if (key_state == WLR_KEY_PRESSED && sym >= XKB_KEY_F1 && sym <= XKB_KEY_F12) {
wlr_session_change_vt(kbstate->compositor->session, sym - XKB_KEY_F1 + 1);
}
}

4 changes: 2 additions & 2 deletions include/backend/drm.h
Original file line number Diff line number Diff line change
@@ -34,8 +34,7 @@ struct wlr_backend_state {
struct wlr_backend *backend;
struct wl_event_source *drm_event;

struct wl_listener device_paused;
struct wl_listener device_resumed;
struct wl_listener session_signal;
struct wl_listener drm_invalidated;

uint32_t taken_crtcs;
@@ -90,5 +89,6 @@ void wlr_drm_scan_connectors(struct wlr_backend_state *state);
int wlr_drm_event(int fd, uint32_t mask, void *data);

void wlr_drm_output_start_renderer(struct wlr_output_state *output);
void wlr_drm_output_pause_renderer(struct wlr_output_state *output);

#endif
2 changes: 2 additions & 0 deletions include/backend/libinput.h
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ struct wlr_backend_state {
struct libinput *libinput;
struct wl_event_source *input_event;

struct wl_listener session_signal;

list_t *devices;
};

11 changes: 3 additions & 8 deletions include/wlr/session.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
#ifndef WLR_SESSION_H
#define WLR_SESSION_H

#include <stdbool.h>
#include <wayland-server.h>
#include <sys/types.h>

struct session_impl;

// Passed to the listeners of device_paused/resumed
struct device_arg {
dev_t dev;
int fd; // Only for device_resumed
};

struct wlr_session {
const struct session_impl *impl;

struct wl_signal device_paused;
struct wl_signal device_resumed;
bool active;
struct wl_signal session_signal;
};

struct wlr_session *wlr_session_start(struct wl_display *disp);
4 changes: 2 additions & 2 deletions session/direct.c
Original file line number Diff line number Diff line change
@@ -45,8 +45,8 @@ static struct wlr_session *direct_session_start(struct wl_display *disp) {
wlr_log(L_INFO, "Successfully loaded direct session");

session->base.impl = &session_direct;
wl_signal_init(&session->base.device_paused);
wl_signal_init(&session->base.device_resumed);
session->base.active = true;
wl_signal_init(&session->base.session_signal);
return &session->base;
}

58 changes: 35 additions & 23 deletions session/logind.c
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@
#include <wlr/session/interface.h>
#include "common/log.h"

enum { DRM_MAJOR = 226 };

const struct session_impl session_logind;

struct logind_session {
@@ -25,6 +27,8 @@ struct logind_session {
char *id;
char *path;
char *seat;

int drm_fd;
};

static int logind_take_device(struct wlr_session *restrict base,
@@ -58,7 +62,7 @@ static int logind_take_device(struct wlr_session *restrict base,
goto error;
}

// The original fd seem to be closed when the message is freed
// The original fd seems to be closed when the message is freed
// so we just clone it.
fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
if (fd == -1) {
@@ -67,6 +71,10 @@ static int logind_take_device(struct wlr_session *restrict base,
goto error;
}

if (major(st.st_rdev) == DRM_MAJOR) {
session->drm_fd = fd;
}

error:
sd_bus_error_free(&error);
sd_bus_message_unref(msg);
@@ -93,6 +101,10 @@ static void logind_release_device(struct wlr_session *base, int fd) {
wlr_log(L_ERROR, "Failed to release device '%d'", fd);
}

if (major(st.st_rdev) == DRM_MAJOR) {
session->drm_fd = -1;
}

sd_bus_error_free(&error);
sd_bus_message_unref(msg);
}
@@ -185,38 +197,38 @@ static int session_removed(sd_bus_message *msg, void *userdata, sd_bus_error *re
}

static int pause_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_error) {
wlr_log(L_INFO, "PauseDevice signal received");
struct logind_session *session = userdata;
int ret;

uint32_t major, minor;
ret = sd_bus_message_read(msg, "uu", &major, &minor);
const char *type;
ret = sd_bus_message_read(msg, "uus", &major, &minor, &type);
if (ret < 0) {
wlr_log(L_ERROR, "Failed to parse D-Bus response for PauseDevice: %s",
strerror(-ret));
goto error;
}

struct device_arg arg = {
.dev = makedev(major, minor),
.fd = -1,
};

wl_signal_emit(&session->base.device_paused, &arg);
if (major == DRM_MAJOR) {
session->base.active = false;
wl_signal_emit(&session->base.session_signal, session);
}

ret = sd_bus_call_method(session->bus, "org.freedesktop.login1",
session->path, "org.freedesktop.login1.Session", "PauseDeviceComplete",
ret_error, &msg, "uu", major, minor);
if (ret < 0) {
wlr_log(L_ERROR, "Failed to send PauseDeviceComplete signal");
if (strcmp(type, "pause") == 0) {
ret = sd_bus_call_method(session->bus, "org.freedesktop.login1",
session->path, "org.freedesktop.login1.Session", "PauseDeviceComplete",
ret_error, &msg, "uu", major, minor);
if (ret < 0) {
wlr_log(L_ERROR, "Failed to send PauseDeviceComplete signal: %s",
strerror(-ret));
}
}

error:
return 0;
}

static int resume_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_error) {
wlr_log(L_INFO, "ResumeDevice signal received");
struct logind_session *session = userdata;
int ret;

@@ -229,12 +241,11 @@ static int resume_device(sd_bus_message *msg, void *userdata, sd_bus_error *ret_
goto error;
}

struct device_arg arg = {
.dev = makedev(major, minor),
.fd = fd,
};

wl_signal_emit(&session->base.device_resumed, &arg);
if (major == DRM_MAJOR) {
dup2(fd, session->drm_fd);
session->base.active = true;
wl_signal_emit(&session->base.session_signal, session);
}

error:
return 0;
@@ -334,9 +345,10 @@ static struct wlr_session *logind_session_start(struct wl_display *disp) {

wlr_log(L_INFO, "Successfully loaded logind session");

session->drm_fd = -1;
session->base.impl = &session_logind;
wl_signal_init(&session->base.device_paused);
wl_signal_init(&session->base.device_resumed);
session->base.active = true;
wl_signal_init(&session->base.session_signal);
return &session->base;

error_bus: