mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-14 08:22:25 -04:00
Merge branch 'rhpd' into 'master'
backend/session: Add rapid hotplug detection See merge request wlroots/wlroots!4633
This commit is contained in:
commit
3c661edf3c
3 changed files with 82 additions and 27 deletions
|
|
@ -16,6 +16,7 @@
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
#include "backend/session/session.h"
|
#include "backend/session/session.h"
|
||||||
#include "util/time.h"
|
#include "util/time.h"
|
||||||
|
#include "util/env.h"
|
||||||
|
|
||||||
#include <libseat.h>
|
#include <libseat.h>
|
||||||
|
|
||||||
|
|
@ -166,31 +167,11 @@ static void read_udev_change_event(struct wlr_device_change_event *event,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_udev_event(int fd, uint32_t mask, void *data) {
|
static int handle_udev_event(const char *sysname, const char *devnode, const char *action,
|
||||||
struct wlr_session *session = data;
|
struct wlr_session *session, struct udev_device *udev_dev, void *data) {
|
||||||
|
|
||||||
struct udev_device *udev_dev = udev_monitor_receive_device(session->mon);
|
|
||||||
if (!udev_dev) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *sysname = udev_device_get_sysname(udev_dev);
|
|
||||||
const char *devnode = udev_device_get_devnode(udev_dev);
|
|
||||||
const char *action = udev_device_get_action(udev_dev);
|
|
||||||
wlr_log(WLR_DEBUG, "udev event for %s (%s)", sysname, action);
|
wlr_log(WLR_DEBUG, "udev event for %s (%s)", sysname, action);
|
||||||
|
|
||||||
if (!is_drm_card(sysname) || !action || !devnode) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *seat = udev_device_get_property_value(udev_dev, "ID_SEAT");
|
|
||||||
if (!seat) {
|
|
||||||
seat = "seat0";
|
|
||||||
}
|
|
||||||
if (session->seat[0] != '\0' && strcmp(session->seat, seat) != 0) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(action, "add") == 0) {
|
if (strcmp(action, "add") == 0) {
|
||||||
wlr_log(WLR_DEBUG, "DRM device %s added", sysname);
|
wlr_log(WLR_DEBUG, "DRM device %s added", sysname);
|
||||||
struct wlr_session_add_event event = {
|
struct wlr_session_add_event event = {
|
||||||
|
|
@ -206,10 +187,19 @@ static int handle_udev_event(int fd, uint32_t mask, void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(action, "change") == 0) {
|
if (strcmp(action, "change") == 0) {
|
||||||
wlr_log(WLR_DEBUG, "DRM device %s changed", sysname);
|
bool double_uevent_occured;
|
||||||
struct wlr_device_change_event event = {0};
|
if (env_parse_bool("WLR_RAPID_HOTPLUG_PREVENT")) {
|
||||||
read_udev_change_event(&event, udev_dev);
|
double_uevent_occured = check_double_uevent(sysname, devnode, action, data);
|
||||||
wl_signal_emit_mutable(&dev->events.change, &event);
|
} else {
|
||||||
|
double_uevent_occured = false;
|
||||||
|
}
|
||||||
|
if (!double_uevent_occured) {
|
||||||
|
wlr_log(WLR_DEBUG, "Resuming change event for DRM device %s", sysname);
|
||||||
|
wlr_log(WLR_DEBUG, "DRM device %s changed", sysname);
|
||||||
|
struct wlr_device_change_event event = {0};
|
||||||
|
read_udev_change_event(&event, udev_dev);
|
||||||
|
wl_signal_emit_mutable(&dev->events.change, &event);
|
||||||
|
}
|
||||||
} else if (strcmp(action, "remove") == 0) {
|
} else if (strcmp(action, "remove") == 0) {
|
||||||
wlr_log(WLR_DEBUG, "DRM device %s removed", sysname);
|
wlr_log(WLR_DEBUG, "DRM device %s removed", sysname);
|
||||||
wl_signal_emit_mutable(&dev->events.remove, NULL);
|
wl_signal_emit_mutable(&dev->events.remove, NULL);
|
||||||
|
|
@ -220,11 +210,69 @@ static int handle_udev_event(int fd, uint32_t mask, void *data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int handle_udev_event_buffer(int fd, uint32_t mask, void *data) {
|
||||||
|
struct wlr_session *session = data;
|
||||||
|
|
||||||
|
struct udev_device *udev_dev = udev_monitor_receive_device(session->mon);
|
||||||
|
if (!udev_dev) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *sysname = udev_device_get_sysname(udev_dev);
|
||||||
|
const char *devnode = udev_device_get_devnode(udev_dev);
|
||||||
|
const char *action = udev_device_get_action(udev_dev);
|
||||||
|
|
||||||
|
if (!is_drm_card(sysname) || !action || !devnode) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *seat = udev_device_get_property_value(udev_dev, "ID_SEAT");
|
||||||
|
if (!seat) {
|
||||||
|
seat = "seat0";
|
||||||
|
}
|
||||||
|
if (session->seat[0] != '\0' && strcmp(session->seat, seat) != 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_udev_event(sysname, devnode, action, session, udev_dev, data);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
udev_device_unref(udev_dev);
|
udev_device_unref(udev_dev);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool check_double_uevent(const char *stored_sysname, const char *stored_devnode,
|
||||||
|
const char *stored_action, void *data) {
|
||||||
|
bool double_uevent_occured = false;
|
||||||
|
|
||||||
|
wlr_log(WLR_DEBUG, "Sleeping to wait for potential hot-plugs");
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
struct wlr_session *session = data;
|
||||||
|
struct udev_device *udev_dev = udev_monitor_receive_device(session->mon);
|
||||||
|
|
||||||
|
const char *sysname = udev_device_get_sysname(udev_dev);
|
||||||
|
const char *devnode = udev_device_get_devnode(udev_dev);
|
||||||
|
const char *action = udev_device_get_action(udev_dev);
|
||||||
|
|
||||||
|
if(sysname != NULL && devnode != NULL && action != NULL) {
|
||||||
|
if (strcmp(stored_sysname, sysname) == 0 && strcmp(stored_devnode, devnode) == 0
|
||||||
|
&& strcmp(stored_action, action) == 0) {
|
||||||
|
wlr_log(WLR_DEBUG, "DRM device %s double uevent ignored", sysname);
|
||||||
|
double_uevent_occured = true;
|
||||||
|
} else {
|
||||||
|
handle_udev_event(sysname, devnode, action, session, udev_dev, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
udev_device_unref(udev_dev);
|
||||||
|
|
||||||
|
return double_uevent_occured;
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_event_loop_destroy(struct wl_listener *listener, void *data) {
|
static void handle_event_loop_destroy(struct wl_listener *listener, void *data) {
|
||||||
struct wlr_session *session =
|
struct wlr_session *session =
|
||||||
wl_container_of(listener, session, event_loop_destroy);
|
wl_container_of(listener, session, event_loop_destroy);
|
||||||
|
|
@ -267,7 +315,7 @@ struct wlr_session *wlr_session_create(struct wl_event_loop *event_loop) {
|
||||||
int fd = udev_monitor_get_fd(session->mon);
|
int fd = udev_monitor_get_fd(session->mon);
|
||||||
|
|
||||||
session->udev_event = wl_event_loop_add_fd(event_loop, fd,
|
session->udev_event = wl_event_loop_add_fd(event_loop, fd,
|
||||||
WL_EVENT_READABLE, handle_udev_event, session);
|
WL_EVENT_READABLE, handle_udev_event_buffer, session);
|
||||||
if (!session->udev_event) {
|
if (!session->udev_event) {
|
||||||
wlr_log_errno(WLR_ERROR, "Failed to create udev event source");
|
wlr_log_errno(WLR_ERROR, "Failed to create udev event source");
|
||||||
goto error_mon;
|
goto error_mon;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,10 @@ wlroots reads these environment variables
|
||||||
and Vulkan
|
and Vulkan
|
||||||
* *WLR_EGL_NO_MODIFIERS*: set to 1 to disable format modifiers in EGL, this can
|
* *WLR_EGL_NO_MODIFIERS*: set to 1 to disable format modifiers in EGL, this can
|
||||||
be used to understand and work around driver bugs.
|
be used to understand and work around driver bugs.
|
||||||
|
* *WLR_RAPID_HOTPLUG_PREVENT*: set to 1 to wait after an output device hotplug
|
||||||
|
in case another occurs immediately after, and if so, ignore both. This is to
|
||||||
|
work around monitors that implement DisplayPort's "deep sleep" feature, but
|
||||||
|
causes a second delay for each change event due to waiting.
|
||||||
|
|
||||||
## DRM backend
|
## DRM backend
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ int libseat_session_open_device(struct wlr_session *base, const char *path);
|
||||||
void libseat_session_close_device(struct wlr_session *base, int fd);
|
void libseat_session_close_device(struct wlr_session *base, int fd);
|
||||||
bool libseat_change_vt(struct wlr_session *base, unsigned vt);
|
bool libseat_change_vt(struct wlr_session *base, unsigned vt);
|
||||||
|
|
||||||
|
bool check_double_uevent(const char *stored_sysname, const char *stored_devnode,
|
||||||
|
const char *stored_action, void *data);
|
||||||
|
|
||||||
void session_init(struct wlr_session *session);
|
void session_init(struct wlr_session *session);
|
||||||
|
|
||||||
struct wlr_device *session_open_if_kms(struct wlr_session *restrict session,
|
struct wlr_device *session_open_if_kms(struct wlr_session *restrict session,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue