mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-06-19 14:33:00 -04:00
Merge gitlab.freedesktop.org:wlroots/wlroots
This commit is contained in:
commit
26f6fab4eb
275 changed files with 7472 additions and 5463 deletions
|
|
@ -17,7 +17,7 @@
|
|||
#include "backend/backend.h"
|
||||
#include "backend/multi.h"
|
||||
#include "render/allocator/allocator.h"
|
||||
#include "util/signal.h"
|
||||
#include "util/env.h"
|
||||
|
||||
#if WLR_HAS_DRM_BACKEND
|
||||
#include <wlr/backend/drm.h>
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
void wlr_backend_init(struct wlr_backend *backend,
|
||||
const struct wlr_backend_impl *impl) {
|
||||
assert(backend);
|
||||
memset(backend, 0, sizeof(*backend));
|
||||
backend->impl = impl;
|
||||
wl_signal_init(&backend->events.destroy);
|
||||
wl_signal_init(&backend->events.new_input);
|
||||
|
|
@ -44,7 +44,7 @@ void wlr_backend_init(struct wlr_backend *backend,
|
|||
}
|
||||
|
||||
void wlr_backend_finish(struct wlr_backend *backend) {
|
||||
wlr_signal_emit_safe(&backend->events.destroy, backend);
|
||||
wl_signal_emit_mutable(&backend->events.destroy, backend);
|
||||
}
|
||||
|
||||
bool wlr_backend_start(struct wlr_backend *backend) {
|
||||
|
|
@ -365,8 +365,7 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) {
|
|||
}
|
||||
wlr_multi_backend_add(backend, libinput);
|
||||
#else
|
||||
const char *no_devs = getenv("WLR_LIBINPUT_NO_DEVICES");
|
||||
if (no_devs && strcmp(no_devs, "1") == 0) {
|
||||
if (env_parse_bool("WLR_LIBINPUT_NO_DEVICES")) {
|
||||
wlr_log(WLR_INFO, "WLR_LIBINPUT_NO_DEVICES is set, "
|
||||
"starting without libinput backend");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
|
@ -6,6 +8,41 @@
|
|||
#include "backend/drm/iface.h"
|
||||
#include "backend/drm/util.h"
|
||||
|
||||
static char *atomic_commit_flags_str(uint32_t flags) {
|
||||
const char *const l[] = {
|
||||
(flags & DRM_MODE_PAGE_FLIP_EVENT) ? "PAGE_FLIP_EVENT" : NULL,
|
||||
(flags & DRM_MODE_PAGE_FLIP_ASYNC) ? "PAGE_FLIP_ASYNC" : NULL,
|
||||
(flags & DRM_MODE_ATOMIC_TEST_ONLY) ? "ATOMIC_TEST_ONLY" : NULL,
|
||||
(flags & DRM_MODE_ATOMIC_NONBLOCK) ? "ATOMIC_NONBLOCK" : NULL,
|
||||
(flags & DRM_MODE_ATOMIC_ALLOW_MODESET) ? "ATOMIC_ALLOW_MODESET" : NULL,
|
||||
};
|
||||
|
||||
char *buf = NULL;
|
||||
size_t size = 0;
|
||||
FILE *f = open_memstream(&buf, &size);
|
||||
if (f == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(l) / sizeof(l[0]); i++) {
|
||||
if (l[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (ftell(f) > 0) {
|
||||
fprintf(f, " | ");
|
||||
}
|
||||
fprintf(f, "%s", l[i]);
|
||||
}
|
||||
|
||||
if (ftell(f) == 0) {
|
||||
fprintf(f, "none");
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct atomic {
|
||||
drmModeAtomicReq *req;
|
||||
bool failed;
|
||||
|
|
@ -33,9 +70,11 @@ static bool atomic_commit(struct atomic *atom,
|
|||
if (ret != 0) {
|
||||
wlr_drm_conn_log_errno(conn,
|
||||
(flags & DRM_MODE_ATOMIC_TEST_ONLY) ? WLR_DEBUG : WLR_ERROR,
|
||||
"Atomic %s failed (%s)",
|
||||
(flags & DRM_MODE_ATOMIC_TEST_ONLY) ? "test" : "commit",
|
||||
(flags & DRM_MODE_ATOMIC_ALLOW_MODESET) ? "modeset" : "pageflip");
|
||||
"Atomic commit failed");
|
||||
char *flags_str = atomic_commit_flags_str(flags);
|
||||
wlr_log(WLR_DEBUG, "(Atomic commit flags: %s)",
|
||||
flags_str ? flags_str : "<error>");
|
||||
free(flags_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -217,8 +256,10 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn,
|
|||
bool prev_vrr_enabled =
|
||||
output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED;
|
||||
bool vrr_enabled = prev_vrr_enabled;
|
||||
if ((state->base->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) &&
|
||||
drm_connector_supports_vrr(conn)) {
|
||||
if ((state->base->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED)) {
|
||||
if (!drm_connector_supports_vrr(conn)) {
|
||||
return false;
|
||||
}
|
||||
vrr_enabled = state->base->adaptive_sync_enabled;
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +268,12 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn,
|
|||
}
|
||||
if (modeset) {
|
||||
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
} else if (!test_only) {
|
||||
} else if (!test_only && (state->base->committed & WLR_OUTPUT_STATE_BUFFER)) {
|
||||
// The wlr_output API requires non-modeset commits with a new buffer to
|
||||
// wait for the frame event. However compositors often perform
|
||||
// non-modesets commits without a new buffer without waiting for the
|
||||
// frame event. In that case we need to make the KMS commit blocking,
|
||||
// otherwise the kernel will error out with EBUSY.
|
||||
flags |= DRM_MODE_ATOMIC_NONBLOCK;
|
||||
}
|
||||
|
||||
|
|
@ -238,6 +284,13 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn,
|
|||
atomic_add(&atom, conn->id, conn->props.link_status,
|
||||
DRM_MODE_LINK_STATUS_GOOD);
|
||||
}
|
||||
if (active && conn->props.content_type != 0) {
|
||||
atomic_add(&atom, conn->id, conn->props.content_type,
|
||||
DRM_MODE_CONTENT_TYPE_GRAPHICS);
|
||||
}
|
||||
if (active && conn->props.max_bpc != 0 && conn->max_bpc > 0) {
|
||||
atomic_add(&atom, conn->id, conn->props.max_bpc, conn->max_bpc);
|
||||
}
|
||||
atomic_add(&atom, crtc->id, crtc->props.mode_id, mode_id);
|
||||
atomic_add(&atom, crtc->id, crtc->props.active, active);
|
||||
if (active) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <libudev.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -12,7 +13,6 @@
|
|||
#include <wlr/util/log.h>
|
||||
#include <xf86drm.h>
|
||||
#include "backend/drm/drm.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
struct wlr_drm_backend *get_drm_backend_from_backend(
|
||||
struct wlr_backend *wlr_backend) {
|
||||
|
|
@ -58,6 +58,7 @@ static void backend_destroy(struct wlr_backend *backend) {
|
|||
|
||||
finish_drm_resources(drm);
|
||||
|
||||
udev_hwdb_unref(drm->hwdb);
|
||||
free(drm->name);
|
||||
wlr_session_close_file(drm->session, drm->dev);
|
||||
wl_event_source_remove(drm->drm_event);
|
||||
|
|
@ -172,6 +173,23 @@ static void handle_parent_destroy(struct wl_listener *listener, void *data) {
|
|||
backend_destroy(&drm->backend);
|
||||
}
|
||||
|
||||
static struct udev_hwdb *create_udev_hwdb(void) {
|
||||
struct udev *udev = udev_new();
|
||||
if (!udev) {
|
||||
wlr_log(WLR_ERROR, "udev_new failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct udev_hwdb *hwdb = udev_hwdb_new(udev);
|
||||
udev_unref(udev);
|
||||
if (!hwdb) {
|
||||
wlr_log(WLR_ERROR, "udev_hwdb_new failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hwdb;
|
||||
}
|
||||
|
||||
struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
|
||||
struct wlr_session *session, struct wlr_device *dev,
|
||||
struct wlr_backend *parent) {
|
||||
|
|
@ -226,6 +244,12 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
|
|||
drm->session_active.notify = handle_session_active;
|
||||
wl_signal_add(&session->events.active, &drm->session_active);
|
||||
|
||||
drm->hwdb = create_udev_hwdb();
|
||||
if (!drm->hwdb) {
|
||||
wlr_log(WLR_INFO, "Failed to load udev_hwdb, "
|
||||
"falling back to PnP IDs instead of manufacturer names");
|
||||
}
|
||||
|
||||
if (!check_drm_features(drm)) {
|
||||
goto error_event;
|
||||
}
|
||||
|
|
@ -250,15 +274,17 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
|
|||
goto error_mgpu_renderer;
|
||||
}
|
||||
|
||||
// Force a linear layout. In case explicit modifiers aren't supported,
|
||||
// the meaning of implicit modifiers changes from one GPU to the other.
|
||||
// In case explicit modifiers are supported, we still have no guarantee
|
||||
// that the buffer producer will support these, so they might fallback
|
||||
// to implicit modifiers.
|
||||
// Forbid implicit modifiers, because their meaning changes from one
|
||||
// GPU to another.
|
||||
for (size_t i = 0; i < texture_formats->len; i++) {
|
||||
const struct wlr_drm_format *fmt = texture_formats->formats[i];
|
||||
wlr_drm_format_set_add(&drm->mgpu_formats, fmt->format,
|
||||
DRM_FORMAT_MOD_LINEAR);
|
||||
for (size_t j = 0; j < fmt->len; j++) {
|
||||
uint64_t mod = fmt->modifiers[j];
|
||||
if (mod == DRM_FORMAT_MOD_INVALID) {
|
||||
continue;
|
||||
}
|
||||
wlr_drm_format_set_add(&drm->mgpu_formats, fmt->format, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -275,6 +301,7 @@ error_mgpu_renderer:
|
|||
error_resources:
|
||||
finish_drm_resources(drm);
|
||||
error_event:
|
||||
udev_hwdb_unref(drm->hwdb);
|
||||
wl_list_remove(&drm->session_active.link);
|
||||
wl_event_source_remove(drm->drm_event);
|
||||
error_fd:
|
||||
|
|
|
|||
|
|
@ -29,14 +29,18 @@
|
|||
#include "render/drm_format_set.h"
|
||||
#include "render/swapchain.h"
|
||||
#include "render/wlr_renderer.h"
|
||||
#include "util/signal.h"
|
||||
#include "util/env.h"
|
||||
|
||||
static const uint32_t SUPPORTED_OUTPUT_STATE =
|
||||
WLR_OUTPUT_STATE_BACKEND_OPTIONAL |
|
||||
// Output state which needs a KMS commit to be applied
|
||||
static const uint32_t COMMIT_OUTPUT_STATE =
|
||||
WLR_OUTPUT_STATE_BUFFER |
|
||||
WLR_OUTPUT_STATE_MODE |
|
||||
WLR_OUTPUT_STATE_ENABLED |
|
||||
WLR_OUTPUT_STATE_GAMMA_LUT;
|
||||
WLR_OUTPUT_STATE_GAMMA_LUT |
|
||||
WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED;
|
||||
|
||||
static const uint32_t SUPPORTED_OUTPUT_STATE =
|
||||
WLR_OUTPUT_STATE_BACKEND_OPTIONAL | COMMIT_OUTPUT_STATE;
|
||||
|
||||
bool check_drm_features(struct wlr_drm_backend *drm) {
|
||||
if (drmGetCap(drm->fd, DRM_CAP_CURSOR_WIDTH, &drm->cursor_width)) {
|
||||
|
|
@ -72,8 +76,7 @@ bool check_drm_features(struct wlr_drm_backend *drm) {
|
|||
return false;
|
||||
}
|
||||
|
||||
const char *no_atomic = getenv("WLR_DRM_NO_ATOMIC");
|
||||
if (no_atomic && strcmp(no_atomic, "1") == 0) {
|
||||
if (env_parse_bool("WLR_DRM_NO_ATOMIC")) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"WLR_DRM_NO_ATOMIC set, forcing legacy DRM interface");
|
||||
drm->iface = &legacy_iface;
|
||||
|
|
@ -89,8 +92,7 @@ bool check_drm_features(struct wlr_drm_backend *drm) {
|
|||
int ret = drmGetCap(drm->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
|
||||
drm->clock = (ret == 0 && cap == 1) ? CLOCK_MONOTONIC : CLOCK_REALTIME;
|
||||
|
||||
const char *no_modifiers = getenv("WLR_DRM_NO_MODIFIERS");
|
||||
if (no_modifiers != NULL && strcmp(no_modifiers, "1") == 0) {
|
||||
if (env_parse_bool("WLR_DRM_NO_MODIFIERS")) {
|
||||
wlr_log(WLR_DEBUG, "WLR_DRM_NO_MODIFIERS set, disabling modifiers");
|
||||
} else {
|
||||
ret = drmGetCap(drm->fd, DRM_CAP_ADDFB2_MODIFIERS, &cap);
|
||||
|
|
@ -380,6 +382,7 @@ static bool drm_crtc_page_flip(struct wlr_drm_connector *conn,
|
|||
static void drm_connector_state_init(struct wlr_drm_connector_state *state,
|
||||
struct wlr_drm_connector *conn,
|
||||
const struct wlr_output_state *base) {
|
||||
memset(state, 0, sizeof(*state));
|
||||
state->base = base;
|
||||
state->modeset = base->committed &
|
||||
(WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_MODE);
|
||||
|
|
@ -458,37 +461,48 @@ static bool drm_connector_set_pending_fb(struct wlr_drm_connector *conn,
|
|||
|
||||
static bool drm_connector_alloc_crtc(struct wlr_drm_connector *conn);
|
||||
|
||||
static bool drm_connector_test(struct wlr_output *output) {
|
||||
static bool drm_connector_test(struct wlr_output *output,
|
||||
const struct wlr_output_state *state) {
|
||||
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
|
||||
|
||||
if (!conn->backend->session->active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t unsupported = output->pending.committed & ~SUPPORTED_OUTPUT_STATE;
|
||||
uint32_t unsupported = state->committed & ~SUPPORTED_OUTPUT_STATE;
|
||||
if (unsupported != 0) {
|
||||
wlr_log(WLR_DEBUG, "Unsupported output state fields: 0x%"PRIx32,
|
||||
unsupported);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((output->pending.committed & WLR_OUTPUT_STATE_ENABLED) &&
|
||||
output->pending.enabled) {
|
||||
if ((state->committed & COMMIT_OUTPUT_STATE) == 0) {
|
||||
// This commit doesn't change the KMS state
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled) {
|
||||
if (output->current_mode == NULL &&
|
||||
!(output->pending.committed & WLR_OUTPUT_STATE_MODE)) {
|
||||
!(state->committed & WLR_OUTPUT_STATE_MODE)) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
||||
"Can't enable an output without a mode");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED) &&
|
||||
state->adaptive_sync_enabled &&
|
||||
!drm_connector_supports_vrr(conn)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wlr_drm_connector_state pending = {0};
|
||||
drm_connector_state_init(&pending, conn, &output->pending);
|
||||
drm_connector_state_init(&pending, conn, state);
|
||||
|
||||
if (pending.active) {
|
||||
if ((output->pending.committed &
|
||||
if ((state->committed &
|
||||
(WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_MODE)) &&
|
||||
!(output->pending.committed & WLR_OUTPUT_STATE_BUFFER)) {
|
||||
!(state->committed & WLR_OUTPUT_STATE_BUFFER)) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
||||
"Can't enable an output without a buffer");
|
||||
return false;
|
||||
|
|
@ -513,7 +527,7 @@ static bool drm_connector_test(struct wlr_output *output) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
if (!drm_connector_set_pending_fb(conn, pending.base)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -559,6 +573,11 @@ bool drm_connector_commit_state(struct wlr_drm_connector *conn,
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((base->committed & COMMIT_OUTPUT_STATE) == 0) {
|
||||
// This commit doesn't change the KMS state
|
||||
return true;
|
||||
}
|
||||
|
||||
struct wlr_drm_connector_state pending = {0};
|
||||
drm_connector_state_init(&pending, conn, base);
|
||||
|
||||
|
|
@ -596,14 +615,15 @@ bool drm_connector_commit_state(struct wlr_drm_connector *conn,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool drm_connector_commit(struct wlr_output *output) {
|
||||
static bool drm_connector_commit(struct wlr_output *output,
|
||||
const struct wlr_output_state *state) {
|
||||
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
|
||||
|
||||
if (!drm_connector_test(output)) {
|
||||
if (!drm_connector_test(output, state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return drm_connector_commit_state(conn, &output->pending);
|
||||
return drm_connector_commit_state(conn, state);
|
||||
}
|
||||
|
||||
size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm,
|
||||
|
|
@ -692,8 +712,7 @@ static bool drm_connector_set_mode(struct wlr_drm_connector *conn,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (conn->status != WLR_DRM_CONN_CONNECTED
|
||||
&& conn->status != WLR_DRM_CONN_NEEDS_MODESET) {
|
||||
if (conn->status != DRM_MODE_CONNECTED) {
|
||||
wlr_drm_conn_log(conn, WLR_ERROR,
|
||||
"Cannot modeset a disconnected output");
|
||||
return false;
|
||||
|
|
@ -720,7 +739,6 @@ static bool drm_connector_set_mode(struct wlr_drm_connector *conn,
|
|||
return false;
|
||||
}
|
||||
|
||||
conn->status = WLR_DRM_CONN_CONNECTED;
|
||||
wlr_output_update_mode(&conn->output, wlr_mode);
|
||||
wlr_output_update_enabled(&conn->output, true);
|
||||
conn->desired_enabled = true;
|
||||
|
|
@ -892,7 +910,7 @@ static void drm_connector_destroy_output(struct wlr_output *output) {
|
|||
|
||||
dealloc_crtc(conn);
|
||||
|
||||
conn->status = WLR_DRM_CONN_DISCONNECTED;
|
||||
conn->status = DRM_MODE_DISCONNECTED;
|
||||
conn->desired_enabled = false;
|
||||
conn->possible_crtcs = 0;
|
||||
conn->pending_page_flip_crtc = 0;
|
||||
|
|
@ -1071,9 +1089,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) {
|
|||
|
||||
// Only search CRTCs for user-enabled outputs (that are already
|
||||
// connected or in need of a modeset)
|
||||
if ((conn->status == WLR_DRM_CONN_CONNECTED ||
|
||||
conn->status == WLR_DRM_CONN_NEEDS_MODESET) &&
|
||||
conn->desired_enabled) {
|
||||
if (conn->status == DRM_MODE_CONNECTED && conn->desired_enabled) {
|
||||
connector_constraints[i] = conn->possible_crtcs;
|
||||
} else {
|
||||
// Will always fail to match anything
|
||||
|
|
@ -1104,8 +1120,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) {
|
|||
*/
|
||||
for (size_t i = 0; i < num_outputs; ++i) {
|
||||
struct wlr_drm_connector *conn = connectors[i];
|
||||
if (conn->status == WLR_DRM_CONN_CONNECTED &&
|
||||
conn->desired_enabled &&
|
||||
if (conn->status == DRM_MODE_CONNECTED && conn->output.enabled &&
|
||||
connector_match[i] == -1) {
|
||||
wlr_log(WLR_DEBUG, "Could not match a CRTC for previously connected output; "
|
||||
"keeping old configuration");
|
||||
|
|
@ -1132,7 +1147,6 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) {
|
|||
if (connector_match[i] == -1) {
|
||||
if (prev_enabled) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG, "Output has lost its CRTC");
|
||||
conn->status = WLR_DRM_CONN_NEEDS_MODESET;
|
||||
wlr_output_update_enabled(&conn->output, false);
|
||||
wlr_output_update_mode(&conn->output, NULL);
|
||||
}
|
||||
|
|
@ -1142,42 +1156,17 @@ static void realloc_crtcs(struct wlr_drm_backend *drm) {
|
|||
conn->crtc = &drm->crtcs[connector_match[i]];
|
||||
|
||||
// Only realloc buffers if we have actually been modeset
|
||||
if (conn->status != WLR_DRM_CONN_CONNECTED) {
|
||||
if (conn->status != DRM_MODE_CONNECTED || !conn->output.enabled) {
|
||||
continue;
|
||||
}
|
||||
wlr_output_damage_whole(&conn->output);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_possible_crtcs(int fd, const drmModeConnector *conn) {
|
||||
uint32_t possible_crtcs = 0;
|
||||
|
||||
for (int i = 0; i < conn->count_encoders; ++i) {
|
||||
drmModeEncoder *enc = drmModeGetEncoder(fd, conn->encoders[i]);
|
||||
if (!enc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
possible_crtcs |= enc->possible_crtcs;
|
||||
|
||||
drmModeFreeEncoder(enc);
|
||||
}
|
||||
|
||||
return possible_crtcs;
|
||||
}
|
||||
|
||||
static void disconnect_drm_connector(struct wlr_drm_connector *conn);
|
||||
|
||||
void scan_drm_connectors(struct wlr_drm_backend *drm,
|
||||
struct wlr_device_hotplug_event *event) {
|
||||
/*
|
||||
* This GPU is not really a modesetting device.
|
||||
* It's just being used as a renderer.
|
||||
*/
|
||||
if (drm->num_crtcs == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event != NULL && event->connector_id != 0) {
|
||||
wlr_log(WLR_INFO, "Scanning DRM connector %"PRIu32" on %s",
|
||||
event->connector_id, drm->name);
|
||||
|
|
@ -1240,12 +1229,17 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
|
|||
}
|
||||
|
||||
wlr_conn->backend = drm;
|
||||
wlr_conn->status = WLR_DRM_CONN_DISCONNECTED;
|
||||
wlr_conn->status = DRM_MODE_DISCONNECTED;
|
||||
wlr_conn->id = drm_conn->connector_id;
|
||||
|
||||
const char *conn_name =
|
||||
drmModeGetConnectorTypeName(drm_conn->connector_type);
|
||||
if (conn_name == NULL) {
|
||||
conn_name = "Unknown";
|
||||
}
|
||||
|
||||
snprintf(wlr_conn->name, sizeof(wlr_conn->name),
|
||||
"%s-%"PRIu32, conn_get_name(drm_conn->connector_type),
|
||||
drm_conn->connector_type_id);
|
||||
"%s-%"PRIu32, conn_name, drm_conn->connector_type_id);
|
||||
|
||||
wl_list_insert(drm->outputs.prev, &wlr_conn->link);
|
||||
wlr_log(WLR_INFO, "Found connector '%s'", wlr_conn->name);
|
||||
|
|
@ -1282,7 +1276,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
|
|||
}
|
||||
}
|
||||
|
||||
if (wlr_conn->status == WLR_DRM_CONN_DISCONNECTED &&
|
||||
if (wlr_conn->status == DRM_MODE_DISCONNECTED &&
|
||||
drm_conn->connection == DRM_MODE_CONNECTED) {
|
||||
wlr_log(WLR_INFO, "'%s' connected", wlr_conn->name);
|
||||
wlr_log(WLR_DEBUG, "Current CRTC: %d",
|
||||
|
|
@ -1310,16 +1304,24 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
|
|||
wlr_conn->output.non_desktop = non_desktop;
|
||||
}
|
||||
|
||||
wlr_conn->max_bpc = 0;
|
||||
if (wlr_conn->props.max_bpc != 0) {
|
||||
if (!introspect_drm_prop_range(drm->fd, wlr_conn->props.max_bpc,
|
||||
NULL, &wlr_conn->max_bpc)) {
|
||||
wlr_log(WLR_ERROR, "Failed to introspect 'max bpc' property");
|
||||
}
|
||||
}
|
||||
|
||||
size_t edid_len = 0;
|
||||
uint8_t *edid = get_drm_prop_blob(drm->fd,
|
||||
wlr_conn->id, wlr_conn->props.edid, &edid_len);
|
||||
parse_edid(&wlr_conn->output, edid_len, edid);
|
||||
parse_edid(wlr_conn, edid_len, edid);
|
||||
free(edid);
|
||||
|
||||
size_t tile_len = 0;
|
||||
uint8_t *tile = get_drm_prop_blob(drm->fd,
|
||||
wlr_conn->id, wlr_conn->props.tile, &tile_len);
|
||||
parse_tile(&wlr_conn->output, tile_len, tile);
|
||||
parse_tile(wlr_conn, tile_len, tile);
|
||||
free(tile);
|
||||
|
||||
char *subconnector = NULL;
|
||||
|
|
@ -1334,9 +1336,13 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
|
|||
|
||||
struct wlr_output *output = &wlr_conn->output;
|
||||
char description[128];
|
||||
snprintf(description, sizeof(description), "%s %s %s (%s%s%s)",
|
||||
output->make, output->model, output->serial, output->name,
|
||||
subconnector ? " via " : "", subconnector ? subconnector : "");
|
||||
snprintf(description, sizeof(description), "%s %s%s%s (%s%s%s)",
|
||||
output->make, output->model,
|
||||
output->serial ? " " : "",
|
||||
output->serial ? output->serial : "",
|
||||
output->name,
|
||||
subconnector ? " via " : "",
|
||||
subconnector ? subconnector : "");
|
||||
wlr_output_set_description(output, description);
|
||||
|
||||
free(subconnector);
|
||||
|
|
@ -1371,7 +1377,8 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
|
|||
wl_list_insert(wlr_conn->output.modes.prev, &mode->wlr_mode.link);
|
||||
}
|
||||
|
||||
wlr_conn->possible_crtcs = get_possible_crtcs(drm->fd, drm_conn);
|
||||
wlr_conn->possible_crtcs =
|
||||
drmModeConnectorGetPossibleCrtcs(drm->fd, drm_conn);
|
||||
if (wlr_conn->possible_crtcs == 0) {
|
||||
wlr_drm_conn_log(wlr_conn, WLR_ERROR, "No CRTC possible");
|
||||
}
|
||||
|
|
@ -1381,10 +1388,9 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
|
|||
wlr_output_update_enabled(&wlr_conn->output, wlr_conn->crtc != NULL);
|
||||
wlr_conn->desired_enabled = true;
|
||||
|
||||
wlr_conn->status = WLR_DRM_CONN_NEEDS_MODESET;
|
||||
wlr_conn->status = DRM_MODE_CONNECTED;
|
||||
new_outputs[new_outputs_len++] = wlr_conn;
|
||||
} else if ((wlr_conn->status == WLR_DRM_CONN_CONNECTED ||
|
||||
wlr_conn->status == WLR_DRM_CONN_NEEDS_MODESET) &&
|
||||
} else if (wlr_conn->status == DRM_MODE_CONNECTED &&
|
||||
drm_conn->connection != DRM_MODE_CONNECTED) {
|
||||
wlr_log(WLR_INFO, "'%s' disconnected", wlr_conn->name);
|
||||
disconnect_drm_connector(wlr_conn);
|
||||
|
|
@ -1416,7 +1422,7 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
|
|||
struct wlr_drm_connector *conn = new_outputs[i];
|
||||
|
||||
wlr_drm_conn_log(conn, WLR_INFO, "Requesting modeset");
|
||||
wlr_signal_emit_safe(&drm->backend.events.new_output,
|
||||
wl_signal_emit_mutable(&drm->backend.events.new_output,
|
||||
&conn->output);
|
||||
}
|
||||
}
|
||||
|
|
@ -1474,7 +1480,7 @@ static void handle_page_flip(int fd, unsigned seq,
|
|||
|
||||
conn->pending_page_flip_crtc = 0;
|
||||
|
||||
if (conn->status != WLR_DRM_CONN_CONNECTED || conn->crtc == NULL) {
|
||||
if (conn->status != DRM_MODE_CONNECTED || conn->crtc == NULL) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
||||
"Ignoring page-flip event for disabled connector");
|
||||
return;
|
||||
|
|
@ -1537,7 +1543,7 @@ int handle_drm_event(int fd, uint32_t mask, void *data) {
|
|||
}
|
||||
|
||||
static void disconnect_drm_connector(struct wlr_drm_connector *conn) {
|
||||
if (conn->status == WLR_DRM_CONN_DISCONNECTED) {
|
||||
if (conn->status == DRM_MODE_DISCONNECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1545,7 +1551,7 @@ static void disconnect_drm_connector(struct wlr_drm_connector *conn) {
|
|||
// our wlr_drm_connector.
|
||||
wlr_output_destroy(&conn->output);
|
||||
|
||||
assert(conn->status == WLR_DRM_CONN_DISCONNECTED);
|
||||
assert(conn->status == DRM_MODE_DISCONNECTED);
|
||||
}
|
||||
|
||||
void destroy_drm_connector(struct wlr_drm_connector *conn) {
|
||||
|
|
@ -1635,7 +1641,7 @@ struct wlr_drm_lease *wlr_drm_create_lease(struct wlr_output **outputs,
|
|||
wl_signal_init(&lease->events.destroy);
|
||||
|
||||
wlr_log(WLR_DEBUG, "Issuing DRM lease with %d objects", n_objects);
|
||||
int lease_fd = drmModeCreateLease(drm->fd, objects, n_objects, 0,
|
||||
int lease_fd = drmModeCreateLease(drm->fd, objects, n_objects, O_CLOEXEC,
|
||||
&lease->lessee_id);
|
||||
if (lease_fd < 0) {
|
||||
free(lease);
|
||||
|
|
@ -1669,7 +1675,7 @@ void wlr_drm_lease_terminate(struct wlr_drm_lease *lease) {
|
|||
void drm_lease_destroy(struct wlr_drm_lease *lease) {
|
||||
struct wlr_drm_backend *drm = lease->backend;
|
||||
|
||||
wlr_signal_emit_safe(&lease->events.destroy, NULL);
|
||||
wl_signal_emit_mutable(&lease->events.destroy, NULL);
|
||||
|
||||
struct wlr_drm_connector *conn;
|
||||
wl_list_for_each(conn, &drm->outputs, link) {
|
||||
|
|
|
|||
|
|
@ -115,8 +115,10 @@ static bool legacy_crtc_commit(struct wlr_drm_connector *conn,
|
|||
}
|
||||
}
|
||||
|
||||
if ((state->base->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) &&
|
||||
drm_connector_supports_vrr(conn)) {
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) {
|
||||
if (!drm_connector_supports_vrr(conn)) {
|
||||
return false;
|
||||
}
|
||||
if (drmModeObjectSetProperty(drm->fd, crtc->id, DRM_MODE_OBJECT_CRTC,
|
||||
crtc->props.vrr_enabled,
|
||||
state->base->adaptive_sync_enabled) != 0) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -25,7 +26,9 @@ static const struct prop_info connector_info[] = {
|
|||
{ "EDID", INDEX(edid) },
|
||||
{ "PATH", INDEX(path) },
|
||||
{ "TILE", INDEX(tile) },
|
||||
{ "content type", INDEX(content_type) },
|
||||
{ "link-status", INDEX(link_status) },
|
||||
{ "max bpc", INDEX(max_bpc) },
|
||||
{ "non-desktop", INDEX(non_desktop) },
|
||||
{ "panel orientation", INDEX(panel_orientation) },
|
||||
{ "subconnector", INDEX(subconnector) },
|
||||
|
|
@ -181,3 +184,28 @@ char *get_drm_prop_enum(int fd, uint32_t obj, uint32_t prop_id) {
|
|||
|
||||
return str;
|
||||
}
|
||||
|
||||
bool introspect_drm_prop_range(int fd, uint32_t prop_id,
|
||||
uint64_t *min, uint64_t *max) {
|
||||
drmModePropertyRes *prop = drmModeGetProperty(fd, prop_id);
|
||||
if (!prop) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (drmModeGetPropertyType(prop) != DRM_MODE_PROP_RANGE) {
|
||||
drmModeFreeProperty(prop);
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(prop->count_values == 2);
|
||||
|
||||
if (min != NULL) {
|
||||
*min = prop->values[0];
|
||||
}
|
||||
if (max != NULL) {
|
||||
*max = prop->values[1];
|
||||
}
|
||||
|
||||
drmModeFreeProperty(prop);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,31 +48,6 @@ void finish_drm_renderer(struct wlr_drm_renderer *renderer) {
|
|||
wlr_renderer_destroy(renderer->wlr_rend);
|
||||
}
|
||||
|
||||
bool init_drm_surface(struct wlr_drm_surface *surf,
|
||||
struct wlr_drm_renderer *renderer, uint32_t width, uint32_t height,
|
||||
const struct wlr_drm_format *drm_format) {
|
||||
if (surf->width == width && surf->height == height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
surf->renderer = renderer;
|
||||
surf->width = width;
|
||||
surf->height = height;
|
||||
|
||||
wlr_swapchain_destroy(surf->swapchain);
|
||||
surf->swapchain = NULL;
|
||||
|
||||
surf->swapchain = wlr_swapchain_create(renderer->allocator, width, height,
|
||||
drm_format);
|
||||
if (surf->swapchain == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to create swapchain");
|
||||
memset(surf, 0, sizeof(*surf));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void finish_drm_surface(struct wlr_drm_surface *surf) {
|
||||
if (!surf || !surf->renderer) {
|
||||
return;
|
||||
|
|
@ -83,12 +58,34 @@ static void finish_drm_surface(struct wlr_drm_surface *surf) {
|
|||
memset(surf, 0, sizeof(*surf));
|
||||
}
|
||||
|
||||
bool init_drm_surface(struct wlr_drm_surface *surf,
|
||||
struct wlr_drm_renderer *renderer, int width, int height,
|
||||
const struct wlr_drm_format *drm_format) {
|
||||
if (surf->swapchain != NULL && surf->swapchain->width == width &&
|
||||
surf->swapchain->height == height) {
|
||||
return true;
|
||||
}
|
||||
|
||||
finish_drm_surface(surf);
|
||||
|
||||
surf->swapchain = wlr_swapchain_create(renderer->allocator, width, height,
|
||||
drm_format);
|
||||
if (surf->swapchain == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to create swapchain");
|
||||
return false;
|
||||
}
|
||||
|
||||
surf->renderer = renderer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
||||
struct wlr_buffer *buffer) {
|
||||
struct wlr_renderer *renderer = surf->renderer->wlr_rend;
|
||||
|
||||
if (surf->width != (uint32_t)buffer->width ||
|
||||
surf->height != (uint32_t)buffer->height) {
|
||||
if (surf->swapchain->width != buffer->width ||
|
||||
surf->swapchain->height != buffer->height) {
|
||||
wlr_log(WLR_ERROR, "Surface size doesn't match buffer size");
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -106,7 +103,7 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
|||
|
||||
float mat[9];
|
||||
wlr_matrix_identity(mat);
|
||||
wlr_matrix_scale(mat, surf->width, surf->height);
|
||||
wlr_matrix_scale(mat, surf->swapchain->width, surf->swapchain->height);
|
||||
|
||||
if (!wlr_renderer_begin_with_buffer(renderer, dst)) {
|
||||
wlr_buffer_unlock(dst);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <assert.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <drm_mode.h>
|
||||
#include <drm.h>
|
||||
#include <libudev.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/drm/drm.h"
|
||||
#include "backend/drm/util.h"
|
||||
|
||||
int32_t calculate_refresh_rate(const drmModeModeInfo *mode) {
|
||||
|
|
@ -26,125 +30,93 @@ int32_t calculate_refresh_rate(const drmModeModeInfo *mode) {
|
|||
return refresh;
|
||||
}
|
||||
|
||||
// Constructed from http://edid.tv/manufacturer
|
||||
static const char *get_manufacturer(uint16_t id) {
|
||||
#define ID(a, b, c) ((a & 0x1f) << 10) | ((b & 0x1f) << 5) | (c & 0x1f)
|
||||
switch (id) {
|
||||
case ID('A', 'A', 'A'): return "Avolites Ltd";
|
||||
case ID('A', 'C', 'I'): return "Ancor Communications Inc";
|
||||
case ID('A', 'C', 'R'): return "Acer Technologies";
|
||||
case ID('A', 'D', 'A'): return "Addi-Data GmbH";
|
||||
case ID('A', 'P', 'P'): return "Apple Computer Inc";
|
||||
case ID('A', 'S', 'K'): return "Ask A/S";
|
||||
case ID('A', 'V', 'T'): return "Avtek (Electronics) Pty Ltd";
|
||||
case ID('B', 'N', 'O'): return "Bang & Olufsen";
|
||||
case ID('B', 'N', 'Q'): return "BenQ Corporation";
|
||||
case ID('C', 'M', 'N'): return "Chimei Innolux Corporation";
|
||||
case ID('C', 'M', 'O'): return "Chi Mei Optoelectronics corp.";
|
||||
case ID('C', 'R', 'O'): return "Extraordinary Technologies PTY Limited";
|
||||
case ID('D', 'E', 'L'): return "Dell Inc.";
|
||||
case ID('D', 'G', 'C'): return "Data General Corporation";
|
||||
case ID('D', 'O', 'N'): return "DENON, Ltd.";
|
||||
case ID('E', 'N', 'C'): return "Eizo Nanao Corporation";
|
||||
case ID('E', 'P', 'H'): return "Epiphan Systems Inc.";
|
||||
case ID('E', 'X', 'P'): return "Data Export Corporation";
|
||||
case ID('F', 'N', 'I'): return "Funai Electric Co., Ltd.";
|
||||
case ID('F', 'U', 'S'): return "Fujitsu Siemens Computers GmbH";
|
||||
case ID('G', 'S', 'M'): return "Goldstar Company Ltd";
|
||||
case ID('H', 'I', 'Q'): return "Kaohsiung Opto Electronics Americas, Inc.";
|
||||
case ID('H', 'S', 'D'): return "HannStar Display Corp";
|
||||
case ID('H', 'T', 'C'): return "Hitachi Ltd";
|
||||
case ID('H', 'W', 'P'): return "Hewlett Packard";
|
||||
case ID('I', 'N', 'T'): return "Interphase Corporation";
|
||||
case ID('I', 'N', 'X'): return "Communications Supply Corporation (A division of WESCO)";
|
||||
case ID('I', 'T', 'E'): return "Integrated Tech Express Inc";
|
||||
case ID('I', 'V', 'M'): return "Iiyama North America";
|
||||
case ID('L', 'E', 'N'): return "Lenovo Group Limited";
|
||||
case ID('M', 'A', 'X'): return "Rogen Tech Distribution Inc";
|
||||
case ID('M', 'E', 'G'): return "Abeam Tech Ltd";
|
||||
case ID('M', 'E', 'I'): return "Panasonic Industry Company";
|
||||
case ID('M', 'T', 'C'): return "Mars-Tech Corporation";
|
||||
case ID('M', 'T', 'X'): return "Matrox";
|
||||
case ID('N', 'E', 'C'): return "NEC Corporation";
|
||||
case ID('N', 'E', 'X'): return "Nexgen Mediatech Inc.";
|
||||
case ID('O', 'N', 'K'): return "ONKYO Corporation";
|
||||
case ID('O', 'R', 'N'): return "ORION ELECTRIC CO., LTD.";
|
||||
case ID('O', 'T', 'M'): return "Optoma Corporation";
|
||||
case ID('O', 'V', 'R'): return "Oculus VR, Inc.";
|
||||
case ID('P', 'H', 'L'): return "Philips Consumer Electronics Company";
|
||||
case ID('P', 'I', 'O'): return "Pioneer Electronic Corporation";
|
||||
case ID('P', 'N', 'R'): return "Planar Systems, Inc.";
|
||||
case ID('Q', 'D', 'S'): return "Quanta Display Inc.";
|
||||
case ID('R', 'A', 'T'): return "Rent-A-Tech";
|
||||
case ID('R', 'E', 'N'): return "Renesas Technology Corp.";
|
||||
case ID('S', 'A', 'M'): return "Samsung Electric Company";
|
||||
case ID('S', 'A', 'N'): return "Sanyo Electric Co., Ltd.";
|
||||
case ID('S', 'E', 'C'): return "Seiko Epson Corporation";
|
||||
case ID('S', 'H', 'P'): return "Sharp Corporation";
|
||||
case ID('S', 'I', 'I'): return "Silicon Image, Inc.";
|
||||
case ID('S', 'N', 'Y'): return "Sony";
|
||||
case ID('S', 'T', 'D'): return "STD Computer Inc";
|
||||
case ID('S', 'V', 'S'): return "SVSI";
|
||||
case ID('S', 'Y', 'N'): return "Synaptics Inc";
|
||||
case ID('T', 'C', 'L'): return "Technical Concepts Ltd";
|
||||
case ID('T', 'O', 'P'): return "Orion Communications Co., Ltd.";
|
||||
case ID('T', 'S', 'B'): return "Toshiba America Info Systems Inc";
|
||||
case ID('T', 'S', 'T'): return "Transtream Inc";
|
||||
case ID('U', 'N', 'K'): return "Unknown";
|
||||
case ID('V', 'E', 'S'): return "Vestel Elektronik Sanayi ve Ticaret A. S.";
|
||||
case ID('V', 'I', 'T'): return "Visitech AS";
|
||||
case ID('V', 'I', 'Z'): return "VIZIO, Inc";
|
||||
case ID('V', 'L', 'V'): return "Valve";
|
||||
case ID('V', 'S', 'C'): return "ViewSonic Corporation";
|
||||
case ID('Y', 'M', 'H'): return "Yamaha Corporation";
|
||||
default: return "Unknown";
|
||||
static const char *get_manufacturer(struct udev_hwdb *hwdb, uint16_t code) {
|
||||
static char pnp_id[4];
|
||||
|
||||
// The ASCII 3-letter manufacturer PnP ID is encoded in 5-bit codes
|
||||
pnp_id[0] = ((code >> 10) & 0x1F) + '@';
|
||||
pnp_id[1] = ((code >> 5) & 0x1F) + '@';
|
||||
pnp_id[2] = ((code >> 0) & 0x1F) + '@';
|
||||
pnp_id[3] = '\0';
|
||||
|
||||
if (hwdb == NULL) {
|
||||
return pnp_id;
|
||||
}
|
||||
#undef ID
|
||||
|
||||
char query[32];
|
||||
snprintf(query, sizeof(query), "acpi:%s:", pnp_id);
|
||||
struct udev_list_entry *acpi_entry =
|
||||
udev_hwdb_get_properties_list_entry(hwdb, query, 0);
|
||||
if (acpi_entry == NULL) {
|
||||
return pnp_id;
|
||||
}
|
||||
|
||||
struct udev_list_entry *vendor_entry =
|
||||
udev_list_entry_get_by_name(acpi_entry, "ID_VENDOR_FROM_DATABASE");
|
||||
if (vendor_entry == NULL) {
|
||||
return pnp_id;
|
||||
}
|
||||
|
||||
return udev_list_entry_get_value(vendor_entry);
|
||||
}
|
||||
|
||||
/* See https://en.wikipedia.org/wiki/Extended_Display_Identification_Data for layout of EDID data.
|
||||
* We don't parse the EDID properly. We just expect to receive valid data.
|
||||
*/
|
||||
void parse_edid(struct wlr_output *restrict output, size_t len, const uint8_t *data) {
|
||||
void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) {
|
||||
struct wlr_output *output = &conn->output;
|
||||
|
||||
free(output->make);
|
||||
free(output->model);
|
||||
free(output->serial);
|
||||
output->make = NULL;
|
||||
output->model = NULL;
|
||||
output->serial = NULL;
|
||||
|
||||
if (!data || len < 128) {
|
||||
snprintf(output->make, sizeof(output->make), "<Unknown>");
|
||||
snprintf(output->model, sizeof(output->model), "<Unknown>");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t id = (data[8] << 8) | data[9];
|
||||
snprintf(output->make, sizeof(output->make), "%s", get_manufacturer(id));
|
||||
output->make = strdup(get_manufacturer(conn->backend->hwdb, id));
|
||||
|
||||
uint16_t model = data[10] | (data[11] << 8);
|
||||
snprintf(output->model, sizeof(output->model), "0x%04X", model);
|
||||
char model_str[32];
|
||||
snprintf(model_str, sizeof(model_str), "0x%04" PRIX16, model);
|
||||
|
||||
uint32_t serial = data[12] | (data[13] << 8) | (data[14] << 8) | (data[15] << 8);
|
||||
snprintf(output->serial, sizeof(output->serial), "0x%08X", serial);
|
||||
char serial_str[32];
|
||||
if (serial != 0) {
|
||||
snprintf(serial_str, sizeof(serial_str), "0x%08" PRIX32, serial);
|
||||
} else {
|
||||
serial_str[0] = '\0';
|
||||
}
|
||||
|
||||
for (size_t i = 72; i <= 108; i += 18) {
|
||||
uint16_t flag = (data[i] << 8) | data[i + 1];
|
||||
if (flag == 0 && data[i + 3] == 0xFC) {
|
||||
sprintf(output->model, "%.13s", &data[i + 5]);
|
||||
snprintf(model_str, sizeof(model_str), "%.13s", &data[i + 5]);
|
||||
|
||||
// Monitor names are terminated by newline if they're too short
|
||||
char *nl = strchr(output->model, '\n');
|
||||
char *nl = strchr(model_str, '\n');
|
||||
if (nl) {
|
||||
*nl = '\0';
|
||||
}
|
||||
} else if (flag == 0 && data[i + 3] == 0xFF) {
|
||||
sprintf(output->serial, "%.13s", &data[i + 5]);
|
||||
snprintf(serial_str, sizeof(serial_str), "%.13s", &data[i + 5]);
|
||||
|
||||
// Monitor serial numbers are terminated by newline if they're too
|
||||
// short
|
||||
char *nl = strchr(output->serial, '\n');
|
||||
char* nl = strchr(serial_str, '\n');
|
||||
|
||||
if (nl) {
|
||||
*nl = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parse_tile(struct wlr_output *restrict output, size_t len, const uint8_t *data) {
|
||||
void parse_tile(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) {
|
||||
struct wlr_output *output = &conn->output;
|
||||
if (len > 0) {
|
||||
int ret;
|
||||
ret = sscanf((char*)data, "%d:%d:%d:%d:%d:%d:%d:%d",
|
||||
|
|
@ -207,6 +179,9 @@ const char *conn_get_name(uint32_t type_id) {
|
|||
case DRM_MODE_CONNECTOR_USB: return "USB";
|
||||
#endif
|
||||
default: return "Unknown";
|
||||
output->model = strdup(model_str);
|
||||
if (serial_str[0] != '\0') {
|
||||
output->serial = strdup(serial_str);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#include <wlr/interfaces/wlr_output.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/headless.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
struct wlr_headless_backend *headless_backend_from_backend(
|
||||
struct wlr_backend *wlr_backend) {
|
||||
|
|
@ -20,7 +19,7 @@ static bool backend_start(struct wlr_backend *wlr_backend) {
|
|||
wl_list_for_each(output, &backend->outputs, link) {
|
||||
wl_event_source_timer_update(output->frame_timer, output->frame_delay);
|
||||
wlr_output_update_enabled(&output->wlr_output, true);
|
||||
wlr_signal_emit_safe(&backend->backend.events.new_output,
|
||||
wl_signal_emit_mutable(&backend->backend.events.new_output,
|
||||
&output->wlr_output);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#include <wlr/interfaces/wlr_output.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/headless.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
static const uint32_t SUPPORTED_OUTPUT_STATE =
|
||||
WLR_OUTPUT_STATE_BACKEND_OPTIONAL |
|
||||
|
|
@ -29,40 +28,41 @@ static bool output_set_custom_mode(struct wlr_headless_output *output,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool output_test(struct wlr_output *wlr_output) {
|
||||
uint32_t unsupported =
|
||||
wlr_output->pending.committed & ~SUPPORTED_OUTPUT_STATE;
|
||||
static bool output_test(struct wlr_output *wlr_output,
|
||||
const struct wlr_output_state *state) {
|
||||
uint32_t unsupported = state->committed & ~SUPPORTED_OUTPUT_STATE;
|
||||
if (unsupported != 0) {
|
||||
wlr_log(WLR_DEBUG, "Unsupported output state fields: 0x%"PRIx32,
|
||||
unsupported);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
|
||||
assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
|
||||
if (state->committed & WLR_OUTPUT_STATE_MODE) {
|
||||
assert(state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool output_commit(struct wlr_output *wlr_output) {
|
||||
static bool output_commit(struct wlr_output *wlr_output,
|
||||
const struct wlr_output_state *state) {
|
||||
struct wlr_headless_output *output =
|
||||
headless_output_from_output(wlr_output);
|
||||
|
||||
if (!output_test(wlr_output)) {
|
||||
if (!output_test(wlr_output, state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
|
||||
if (state->committed & WLR_OUTPUT_STATE_MODE) {
|
||||
if (!output_set_custom_mode(output,
|
||||
wlr_output->pending.custom_mode.width,
|
||||
wlr_output->pending.custom_mode.height,
|
||||
wlr_output->pending.custom_mode.refresh)) {
|
||||
state->custom_mode.width,
|
||||
state->custom_mode.height,
|
||||
state->custom_mode.refresh)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
struct wlr_output_event_present present_event = {
|
||||
.commit_seq = wlr_output->commit_seq + 1,
|
||||
.presented = true,
|
||||
|
|
@ -70,6 +70,8 @@ static bool output_commit(struct wlr_output *wlr_output) {
|
|||
wlr_output_send_present(wlr_output, &present_event);
|
||||
}
|
||||
|
||||
wl_event_source_timer_update(output->frame_timer, output->frame_delay);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +95,6 @@ bool wlr_output_is_headless(struct wlr_output *wlr_output) {
|
|||
static int signal_frame(void *data) {
|
||||
struct wlr_headless_output *output = data;
|
||||
wlr_output_send_frame(&output->wlr_output);
|
||||
wl_event_source_timer_update(output->frame_timer, output->frame_delay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -114,8 +115,6 @@ struct wlr_output *wlr_headless_add_output(struct wlr_backend *wlr_backend,
|
|||
struct wlr_output *wlr_output = &output->wlr_output;
|
||||
|
||||
output_set_custom_mode(output, width, height, 0);
|
||||
strncpy(wlr_output->make, "headless", sizeof(wlr_output->make));
|
||||
strncpy(wlr_output->model, "headless", sizeof(wlr_output->model));
|
||||
|
||||
char name[64];
|
||||
snprintf(name, sizeof(name), "HEADLESS-%zu", ++backend->last_output_num);
|
||||
|
|
@ -134,7 +133,7 @@ struct wlr_output *wlr_headless_add_output(struct wlr_backend *wlr_backend,
|
|||
if (backend->started) {
|
||||
wl_event_source_timer_update(output->frame_timer, output->frame_delay);
|
||||
wlr_output_update_enabled(wlr_output, true);
|
||||
wlr_signal_emit_safe(&backend->backend.events.new_output, wlr_output);
|
||||
wl_signal_emit_mutable(&backend->backend.events.new_output, wlr_output);
|
||||
}
|
||||
|
||||
return wlr_output;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include <wlr/backend/session.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "util/signal.h"
|
||||
#include "util/env.h"
|
||||
|
||||
static struct wlr_libinput_backend *get_libinput_backend_from_backend(
|
||||
struct wlr_backend *wlr_backend) {
|
||||
|
|
@ -104,15 +104,10 @@ static bool backend_start(struct wlr_backend *wlr_backend) {
|
|||
libinput_log_set_priority(backend->libinput_context, LIBINPUT_LOG_PRIORITY_ERROR);
|
||||
|
||||
int libinput_fd = libinput_get_fd(backend->libinput_context);
|
||||
char *no_devs = getenv("WLR_LIBINPUT_NO_DEVICES");
|
||||
if (no_devs) {
|
||||
if (strcmp(no_devs, "1") != 0) {
|
||||
no_devs = NULL;
|
||||
}
|
||||
}
|
||||
if (!no_devs && backend->wlr_device_lists.size == 0) {
|
||||
|
||||
if (!env_parse_bool("WLR_LIBINPUT_NO_DEVICES") && wl_list_empty(&backend->devices)) {
|
||||
handle_libinput_readable(libinput_fd, WL_EVENT_READABLE, backend);
|
||||
if (backend->wlr_device_lists.size == 0) {
|
||||
if (wl_list_empty(&backend->devices)) {
|
||||
wlr_log(WLR_ERROR, "libinput initialization failed, no input devices");
|
||||
wlr_log(WLR_ERROR, "Set WLR_LIBINPUT_NO_DEVICES=1 to suppress this check");
|
||||
return false;
|
||||
|
|
@ -141,13 +136,9 @@ static void backend_destroy(struct wlr_backend *wlr_backend) {
|
|||
struct wlr_libinput_backend *backend =
|
||||
get_libinput_backend_from_backend(wlr_backend);
|
||||
|
||||
struct wl_list **wlr_devices_ptr;
|
||||
wl_array_for_each(wlr_devices_ptr, &backend->wlr_device_lists) {
|
||||
struct wlr_libinput_input_device *dev, *tmp;
|
||||
wl_list_for_each_safe(dev, tmp, *wlr_devices_ptr, link) {
|
||||
destroy_libinput_input_device(dev);
|
||||
}
|
||||
free(*wlr_devices_ptr);
|
||||
struct wlr_libinput_input_device *dev, *tmp;
|
||||
wl_list_for_each_safe(dev, tmp, &backend->devices, link) {
|
||||
destroy_libinput_input_device(dev);
|
||||
}
|
||||
|
||||
wlr_backend_finish(wlr_backend);
|
||||
|
|
@ -156,7 +147,6 @@ static void backend_destroy(struct wlr_backend *wlr_backend) {
|
|||
wl_list_remove(&backend->session_destroy.link);
|
||||
wl_list_remove(&backend->session_signal.link);
|
||||
|
||||
wl_array_release(&backend->wlr_device_lists);
|
||||
if (backend->input_event) {
|
||||
wl_event_source_remove(backend->input_event);
|
||||
}
|
||||
|
|
@ -211,7 +201,7 @@ struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
|
|||
}
|
||||
wlr_backend_init(&backend->backend, &backend_impl);
|
||||
|
||||
wl_array_init(&backend->wlr_device_lists);
|
||||
wl_list_init(&backend->devices);
|
||||
|
||||
backend->session = session;
|
||||
backend->display = display;
|
||||
|
|
@ -230,8 +220,27 @@ struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
|
|||
|
||||
struct libinput_device *wlr_libinput_get_device_handle(
|
||||
struct wlr_input_device *wlr_dev) {
|
||||
struct wlr_libinput_input_device *dev =
|
||||
(struct wlr_libinput_input_device *)wlr_dev;
|
||||
struct wlr_libinput_input_device *dev = NULL;
|
||||
switch (wlr_dev->type) {
|
||||
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||
dev = device_from_keyboard(wlr_keyboard_from_input_device(wlr_dev));
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_POINTER:
|
||||
dev = device_from_pointer(wlr_pointer_from_input_device(wlr_dev));
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_SWITCH:
|
||||
dev = device_from_switch(wlr_switch_from_input_device(wlr_dev));
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TOUCH:
|
||||
dev = device_from_touch(wlr_touch_from_input_device(wlr_dev));
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TABLET_TOOL:
|
||||
dev = device_from_tablet(wlr_tablet_from_input_device(wlr_dev));
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TABLET_PAD:
|
||||
dev = device_from_tablet_pad(wlr_tablet_pad_from_input_device(wlr_dev));
|
||||
break;
|
||||
}
|
||||
return dev->handle;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,87 +1,62 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <assert.h>
|
||||
|
||||
#include <libinput.h>
|
||||
#include <stdlib.h>
|
||||
#include <wayland-util.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/interfaces/wlr_keyboard.h>
|
||||
#include <wlr/interfaces/wlr_pointer.h>
|
||||
#include <wlr/interfaces/wlr_touch.h>
|
||||
#include <wlr/interfaces/wlr_tablet_tool.h>
|
||||
#include <wlr/interfaces/wlr_tablet_pad.h>
|
||||
#include <wlr/interfaces/wlr_switch.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "util/array.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
struct wlr_input_device *get_appropriate_device(
|
||||
enum wlr_input_device_type desired_type,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wl_list *wlr_devices = libinput_device_get_user_data(libinput_dev);
|
||||
if (!wlr_devices) {
|
||||
return NULL;
|
||||
void destroy_libinput_input_device(struct wlr_libinput_input_device *dev) {
|
||||
if (dev->keyboard.impl) {
|
||||
wlr_keyboard_finish(&dev->keyboard);
|
||||
}
|
||||
struct wlr_libinput_input_device *dev;
|
||||
wl_list_for_each(dev, wlr_devices, link) {
|
||||
if (dev->wlr_input_device.type == desired_type) {
|
||||
return &dev->wlr_input_device;
|
||||
}
|
||||
if (dev->pointer.impl) {
|
||||
wlr_pointer_finish(&dev->pointer);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void destroy_libinput_input_device(struct wlr_libinput_input_device *dev)
|
||||
{
|
||||
/**
|
||||
* TODO remove the redundant wlr_input_device from wlr_libinput_input_device
|
||||
* wlr_libinput_input_device::wlr_input_device is not owned by its input
|
||||
* device type, which means we have 2 wlr_input_device to cleanup
|
||||
*/
|
||||
if (dev->wlr_input_device._device) {
|
||||
wlr_input_device_destroy(&dev->wlr_input_device);
|
||||
if (dev->switch_device.impl) {
|
||||
wlr_switch_finish(&dev->switch_device);
|
||||
}
|
||||
if (dev->touch.impl) {
|
||||
wlr_touch_finish(&dev->touch);
|
||||
}
|
||||
if (dev->tablet.impl) {
|
||||
finish_device_tablet(dev);
|
||||
}
|
||||
if (dev->tablet_pad.impl) {
|
||||
finish_device_tablet_pad(dev);
|
||||
}
|
||||
wlr_input_device_finish(&dev->wlr_input_device);
|
||||
|
||||
libinput_device_unref(dev->handle);
|
||||
wl_list_remove(&dev->link);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static struct wlr_input_device *allocate_device(
|
||||
struct wlr_libinput_backend *backend,
|
||||
struct libinput_device *libinput_dev, struct wl_list *wlr_devices,
|
||||
enum wlr_input_device_type type) {
|
||||
const char *name = libinput_device_get_name(libinput_dev);
|
||||
struct wlr_libinput_input_device *dev =
|
||||
calloc(1, sizeof(struct wlr_libinput_input_device));
|
||||
if (dev == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
struct wlr_input_device *wlr_dev = &dev->wlr_input_device;
|
||||
libinput_device_get_size(libinput_dev,
|
||||
&wlr_dev->width_mm, &wlr_dev->height_mm);
|
||||
const char *output_name = libinput_device_get_output_name(libinput_dev);
|
||||
if (output_name != NULL) {
|
||||
wlr_dev->output_name = strdup(output_name);
|
||||
}
|
||||
wl_list_insert(wlr_devices, &dev->link);
|
||||
dev->handle = libinput_dev;
|
||||
libinput_device_ref(libinput_dev);
|
||||
wlr_input_device_init(wlr_dev, type, name);
|
||||
wlr_dev->vendor = libinput_device_get_id_vendor(libinput_dev);
|
||||
wlr_dev->product = libinput_device_get_id_product(libinput_dev);
|
||||
return wlr_dev;
|
||||
}
|
||||
|
||||
bool wlr_input_device_is_libinput(struct wlr_input_device *wlr_dev) {
|
||||
switch (wlr_dev->type) {
|
||||
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||
return wlr_dev->keyboard->impl == &libinput_keyboard_impl;
|
||||
return wlr_keyboard_from_input_device(wlr_dev)->impl ==
|
||||
&libinput_keyboard_impl;
|
||||
case WLR_INPUT_DEVICE_POINTER:
|
||||
return wlr_dev->pointer->impl == &libinput_pointer_impl;
|
||||
return wlr_pointer_from_input_device(wlr_dev)->impl ==
|
||||
&libinput_pointer_impl;
|
||||
case WLR_INPUT_DEVICE_TOUCH:
|
||||
return wlr_dev->touch->impl == &libinput_touch_impl;
|
||||
return wlr_touch_from_input_device(wlr_dev)->impl ==
|
||||
&libinput_touch_impl;
|
||||
case WLR_INPUT_DEVICE_TABLET_TOOL:
|
||||
return wlr_dev->tablet->impl == &libinput_tablet_impl;
|
||||
return wlr_tablet_from_input_device(wlr_dev)-> impl ==
|
||||
&libinput_tablet_impl;
|
||||
case WLR_INPUT_DEVICE_TABLET_PAD:
|
||||
return wlr_dev->tablet_pad->impl == &libinput_tablet_pad_impl;
|
||||
return wlr_tablet_pad_from_input_device(wlr_dev)->impl ==
|
||||
&libinput_tablet_pad_impl;
|
||||
case WLR_INPUT_DEVICE_SWITCH:
|
||||
return wlr_dev->switch_device->impl == &libinput_switch_impl;
|
||||
return wlr_switch_from_input_device(wlr_dev)->impl ==
|
||||
&libinput_switch_impl;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -89,165 +64,96 @@ bool wlr_input_device_is_libinput(struct wlr_input_device *wlr_dev) {
|
|||
|
||||
static void handle_device_added(struct wlr_libinput_backend *backend,
|
||||
struct libinput_device *libinput_dev) {
|
||||
/*
|
||||
* Note: the wlr API exposes only devices with a single capability, because
|
||||
* that meshes better with how Wayland does things and is a bit simpler.
|
||||
* However, libinput devices often have multiple capabilities - in such
|
||||
* cases we have to create several devices.
|
||||
*/
|
||||
int vendor = libinput_device_get_id_vendor(libinput_dev);
|
||||
int product = libinput_device_get_id_product(libinput_dev);
|
||||
const char *name = libinput_device_get_name(libinput_dev);
|
||||
struct wl_list *wlr_devices = calloc(1, sizeof(struct wl_list));
|
||||
if (!wlr_devices) {
|
||||
wlr_log(WLR_ERROR, "Allocation failed");
|
||||
wlr_log(WLR_DEBUG, "Adding %s [%d:%d]", name, vendor, product);
|
||||
|
||||
struct wlr_libinput_input_device *dev =
|
||||
calloc(1, sizeof(struct wlr_libinput_input_device));
|
||||
if (dev == NULL) {
|
||||
wlr_log_errno(WLR_ERROR, "failed to allocate wlr_libinput_input_device");
|
||||
return;
|
||||
}
|
||||
wl_list_init(wlr_devices);
|
||||
wlr_log(WLR_DEBUG, "Added %s [%d:%d]", name, vendor, product);
|
||||
|
||||
dev->handle = libinput_dev;
|
||||
libinput_device_ref(libinput_dev);
|
||||
libinput_device_set_user_data(libinput_dev, dev);
|
||||
|
||||
wl_list_insert(&backend->devices, &dev->link);
|
||||
|
||||
if (libinput_device_has_capability(
|
||||
libinput_dev, LIBINPUT_DEVICE_CAP_KEYBOARD)) {
|
||||
struct wlr_input_device *wlr_dev = allocate_device(backend,
|
||||
libinput_dev, wlr_devices, WLR_INPUT_DEVICE_KEYBOARD);
|
||||
if (!wlr_dev) {
|
||||
goto fail;
|
||||
}
|
||||
wlr_dev->keyboard = create_libinput_keyboard(libinput_dev);
|
||||
if (!wlr_dev->keyboard) {
|
||||
free(wlr_dev);
|
||||
goto fail;
|
||||
}
|
||||
wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev);
|
||||
init_device_keyboard(dev);
|
||||
|
||||
wl_signal_emit_mutable(&backend->backend.events.new_input,
|
||||
&dev->keyboard.base);
|
||||
}
|
||||
|
||||
if (libinput_device_has_capability(
|
||||
libinput_dev, LIBINPUT_DEVICE_CAP_POINTER)) {
|
||||
struct wlr_input_device *wlr_dev = allocate_device(backend,
|
||||
libinput_dev, wlr_devices, WLR_INPUT_DEVICE_POINTER);
|
||||
if (!wlr_dev) {
|
||||
goto fail;
|
||||
}
|
||||
wlr_dev->pointer = create_libinput_pointer(libinput_dev);
|
||||
if (!wlr_dev->pointer) {
|
||||
free(wlr_dev);
|
||||
goto fail;
|
||||
}
|
||||
wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev);
|
||||
}
|
||||
if (libinput_device_has_capability(
|
||||
libinput_dev, LIBINPUT_DEVICE_CAP_TOUCH)) {
|
||||
struct wlr_input_device *wlr_dev = allocate_device(backend,
|
||||
libinput_dev, wlr_devices, WLR_INPUT_DEVICE_TOUCH);
|
||||
if (!wlr_dev) {
|
||||
goto fail;
|
||||
}
|
||||
wlr_dev->touch = create_libinput_touch(libinput_dev);
|
||||
if (!wlr_dev->touch) {
|
||||
free(wlr_dev);
|
||||
goto fail;
|
||||
}
|
||||
wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev);
|
||||
}
|
||||
if (libinput_device_has_capability(libinput_dev,
|
||||
LIBINPUT_DEVICE_CAP_TABLET_TOOL)) {
|
||||
struct wlr_input_device *wlr_dev = allocate_device(backend,
|
||||
libinput_dev, wlr_devices, WLR_INPUT_DEVICE_TABLET_TOOL);
|
||||
if (!wlr_dev) {
|
||||
goto fail;
|
||||
}
|
||||
wlr_dev->tablet = create_libinput_tablet(libinput_dev);
|
||||
if (!wlr_dev->tablet) {
|
||||
free(wlr_dev);
|
||||
goto fail;
|
||||
}
|
||||
wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev);
|
||||
}
|
||||
if (libinput_device_has_capability(
|
||||
libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) {
|
||||
struct wlr_input_device *wlr_dev = allocate_device(backend,
|
||||
libinput_dev, wlr_devices, WLR_INPUT_DEVICE_TABLET_PAD);
|
||||
if (!wlr_dev) {
|
||||
goto fail;
|
||||
}
|
||||
wlr_dev->tablet_pad = create_libinput_tablet_pad(libinput_dev);
|
||||
if (!wlr_dev->tablet_pad) {
|
||||
free(wlr_dev);
|
||||
goto fail;
|
||||
}
|
||||
wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev);
|
||||
}
|
||||
if (libinput_device_has_capability(
|
||||
libinput_dev, LIBINPUT_DEVICE_CAP_GESTURE)) {
|
||||
// TODO
|
||||
init_device_pointer(dev);
|
||||
|
||||
wl_signal_emit_mutable(&backend->backend.events.new_input,
|
||||
&dev->pointer.base);
|
||||
}
|
||||
|
||||
if (libinput_device_has_capability(
|
||||
libinput_dev, LIBINPUT_DEVICE_CAP_SWITCH)) {
|
||||
struct wlr_input_device *wlr_dev = allocate_device(backend,
|
||||
libinput_dev, wlr_devices, WLR_INPUT_DEVICE_SWITCH);
|
||||
if (!wlr_dev) {
|
||||
goto fail;
|
||||
}
|
||||
wlr_dev->switch_device = create_libinput_switch(libinput_dev);
|
||||
if (!wlr_dev->switch_device) {
|
||||
free(wlr_dev);
|
||||
goto fail;
|
||||
}
|
||||
wlr_signal_emit_safe(&backend->backend.events.new_input, wlr_dev);
|
||||
init_device_switch(dev);
|
||||
wl_signal_emit_mutable(&backend->backend.events.new_input,
|
||||
&dev->switch_device.base);
|
||||
}
|
||||
|
||||
if (!wl_list_empty(wlr_devices)) {
|
||||
struct wl_list **dst = wl_array_add(&backend->wlr_device_lists, sizeof(wlr_devices));
|
||||
if (!dst) {
|
||||
goto fail;
|
||||
}
|
||||
*dst = wlr_devices;
|
||||
|
||||
libinput_device_set_user_data(libinput_dev, wlr_devices);
|
||||
} else {
|
||||
free(wlr_devices);
|
||||
if (libinput_device_has_capability(
|
||||
libinput_dev, LIBINPUT_DEVICE_CAP_TOUCH)) {
|
||||
init_device_touch(dev);
|
||||
wl_signal_emit_mutable(&backend->backend.events.new_input,
|
||||
&dev->touch.base);
|
||||
}
|
||||
return;
|
||||
|
||||
fail:
|
||||
wlr_log(WLR_ERROR, "Could not allocate new device");
|
||||
struct wlr_libinput_input_device *dev, *tmp_dev;
|
||||
wl_list_for_each_safe(dev, tmp_dev, wlr_devices, link) {
|
||||
free(dev);
|
||||
if (libinput_device_has_capability(libinput_dev,
|
||||
LIBINPUT_DEVICE_CAP_TABLET_TOOL)) {
|
||||
init_device_tablet(dev);
|
||||
wl_signal_emit_mutable(&backend->backend.events.new_input,
|
||||
&dev->tablet.base);
|
||||
}
|
||||
|
||||
if (libinput_device_has_capability(
|
||||
libinput_dev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) {
|
||||
init_device_tablet_pad(dev);
|
||||
wl_signal_emit_mutable(&backend->backend.events.new_input,
|
||||
&dev->tablet_pad.base);
|
||||
}
|
||||
|
||||
if (libinput_device_has_capability(
|
||||
libinput_dev, LIBINPUT_DEVICE_CAP_GESTURE)) {
|
||||
wlr_log(WLR_DEBUG, "libinput gesture not handled");
|
||||
}
|
||||
free(wlr_devices);
|
||||
}
|
||||
|
||||
static void handle_device_removed(struct wlr_libinput_backend *backend,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wl_list *wlr_devices = libinput_device_get_user_data(libinput_dev);
|
||||
int vendor = libinput_device_get_id_vendor(libinput_dev);
|
||||
int product = libinput_device_get_id_product(libinput_dev);
|
||||
const char *name = libinput_device_get_name(libinput_dev);
|
||||
wlr_log(WLR_DEBUG, "Removing %s [%d:%d]", name, vendor, product);
|
||||
if (!wlr_devices) {
|
||||
|
||||
struct wlr_libinput_input_device *dev =
|
||||
libinput_device_get_user_data(libinput_dev);
|
||||
if (dev == NULL) {
|
||||
wlr_log(WLR_ERROR, "libinput_device has no wlr_libinput_input_device");
|
||||
return;
|
||||
}
|
||||
struct wlr_libinput_input_device *dev, *tmp_dev;
|
||||
wl_list_for_each_safe(dev, tmp_dev, wlr_devices, link) {
|
||||
destroy_libinput_input_device(dev);
|
||||
}
|
||||
size_t i = 0;
|
||||
struct wl_list **ptr;
|
||||
wl_array_for_each(ptr, &backend->wlr_device_lists) {
|
||||
struct wl_list *iter = *ptr;
|
||||
if (iter == wlr_devices) {
|
||||
array_remove_at(&backend->wlr_device_lists,
|
||||
i * sizeof(struct wl_list *), sizeof(struct wl_list *));
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
free(wlr_devices);
|
||||
|
||||
destroy_libinput_input_device(dev);
|
||||
}
|
||||
|
||||
void handle_libinput_event(struct wlr_libinput_backend *backend,
|
||||
struct libinput_event *event) {
|
||||
struct libinput_device *libinput_dev = libinput_event_get_device(event);
|
||||
struct wlr_libinput_input_device *dev =
|
||||
libinput_device_get_user_data(libinput_dev);
|
||||
enum libinput_event_type event_type = libinput_event_get_type(event);
|
||||
switch (event_type) {
|
||||
case LIBINPUT_EVENT_DEVICE_ADDED:
|
||||
|
|
@ -257,83 +163,100 @@ void handle_libinput_event(struct wlr_libinput_backend *backend,
|
|||
handle_device_removed(backend, libinput_dev);
|
||||
break;
|
||||
case LIBINPUT_EVENT_KEYBOARD_KEY:
|
||||
handle_keyboard_key(event, libinput_dev);
|
||||
handle_keyboard_key(event, &dev->keyboard);
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_MOTION:
|
||||
handle_pointer_motion(event, libinput_dev);
|
||||
handle_pointer_motion(event, &dev->pointer);
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
handle_pointer_motion_abs(event, libinput_dev);
|
||||
handle_pointer_motion_abs(event, &dev->pointer);
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_BUTTON:
|
||||
handle_pointer_button(event, libinput_dev);
|
||||
handle_pointer_button(event, &dev->pointer);
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_AXIS:
|
||||
handle_pointer_axis(event, libinput_dev);
|
||||
#if !LIBINPUT_HAS_SCROLL_VALUE120
|
||||
/* This event must be ignored in favour of the SCROLL_* events */
|
||||
handle_pointer_axis(event, &dev->pointer);
|
||||
#endif
|
||||
break;
|
||||
#if LIBINPUT_HAS_SCROLL_VALUE120
|
||||
case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
|
||||
handle_pointer_axis_value120(event, &dev->pointer,
|
||||
WLR_AXIS_SOURCE_WHEEL);
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
|
||||
handle_pointer_axis_value120(event, &dev->pointer,
|
||||
WLR_AXIS_SOURCE_FINGER);
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
|
||||
handle_pointer_axis_value120(event, &dev->pointer,
|
||||
WLR_AXIS_SOURCE_CONTINUOUS);
|
||||
break;
|
||||
#endif
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
handle_touch_down(event, libinput_dev);
|
||||
handle_touch_down(event, &dev->touch);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
handle_touch_up(event, libinput_dev);
|
||||
handle_touch_up(event, &dev->touch);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION:
|
||||
handle_touch_motion(event, libinput_dev);
|
||||
handle_touch_motion(event, &dev->touch);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TOUCH_CANCEL:
|
||||
handle_touch_cancel(event, libinput_dev);
|
||||
handle_touch_cancel(event, &dev->touch);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TOUCH_FRAME:
|
||||
handle_touch_frame(event, libinput_dev);
|
||||
handle_touch_frame(event, &dev->touch);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
||||
handle_tablet_tool_axis(event, libinput_dev);
|
||||
handle_tablet_tool_axis(event, &dev->tablet);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
|
||||
handle_tablet_tool_proximity(event, libinput_dev);
|
||||
handle_tablet_tool_proximity(event, &dev->tablet);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_TIP:
|
||||
handle_tablet_tool_tip(event, libinput_dev);
|
||||
handle_tablet_tool_tip(event, &dev->tablet);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
|
||||
handle_tablet_tool_button(event, libinput_dev);
|
||||
handle_tablet_tool_button(event, &dev->tablet);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
|
||||
handle_tablet_pad_button(event, libinput_dev);
|
||||
handle_tablet_pad_button(event, &dev->tablet_pad);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_RING:
|
||||
handle_tablet_pad_ring(event, libinput_dev);
|
||||
handle_tablet_pad_ring(event, &dev->tablet_pad);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_PAD_STRIP:
|
||||
handle_tablet_pad_strip(event, libinput_dev);
|
||||
handle_tablet_pad_strip(event, &dev->tablet_pad);
|
||||
break;
|
||||
case LIBINPUT_EVENT_SWITCH_TOGGLE:
|
||||
handle_switch_toggle(event, libinput_dev);
|
||||
handle_switch_toggle(event, &dev->switch_device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
|
||||
handle_pointer_swipe_begin(event, libinput_dev);
|
||||
handle_pointer_swipe_begin(event, &dev->pointer);
|
||||
break;
|
||||
case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
|
||||
handle_pointer_swipe_update(event, libinput_dev);
|
||||
handle_pointer_swipe_update(event, &dev->pointer);
|
||||
break;
|
||||
case LIBINPUT_EVENT_GESTURE_SWIPE_END:
|
||||
handle_pointer_swipe_end(event, libinput_dev);
|
||||
handle_pointer_swipe_end(event, &dev->pointer);
|
||||
break;
|
||||
case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
|
||||
handle_pointer_pinch_begin(event, libinput_dev);
|
||||
handle_pointer_pinch_begin(event, &dev->pointer);
|
||||
break;
|
||||
case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
|
||||
handle_pointer_pinch_update(event, libinput_dev);
|
||||
handle_pointer_pinch_update(event, &dev->pointer);
|
||||
break;
|
||||
case LIBINPUT_EVENT_GESTURE_PINCH_END:
|
||||
handle_pointer_pinch_end(event, libinput_dev);
|
||||
handle_pointer_pinch_end(event, &dev->pointer);
|
||||
break;
|
||||
#if LIBINPUT_HAS_HOLD_GESTURES
|
||||
case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
|
||||
handle_pointer_hold_begin(event, libinput_dev);
|
||||
handle_pointer_hold_begin(event, &dev->pointer);
|
||||
break;
|
||||
case LIBINPUT_EVENT_GESTURE_HOLD_END:
|
||||
handle_pointer_hold_end(event, libinput_dev);
|
||||
handle_pointer_hold_end(event, &dev->pointer);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -1,70 +1,42 @@
|
|||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <wlr/interfaces/wlr_keyboard.h>
|
||||
#include "backend/libinput.h"
|
||||
|
||||
struct wlr_libinput_keyboard {
|
||||
struct wlr_keyboard wlr_keyboard;
|
||||
struct libinput_device *libinput_dev;
|
||||
};
|
||||
struct wlr_libinput_input_device *device_from_keyboard(
|
||||
struct wlr_keyboard *kb) {
|
||||
assert(kb->impl == &libinput_keyboard_impl);
|
||||
|
||||
static struct wlr_libinput_keyboard *get_libinput_keyboard_from_keyboard(
|
||||
struct wlr_keyboard *wlr_kb) {
|
||||
assert(wlr_kb->impl == &libinput_keyboard_impl);
|
||||
return (struct wlr_libinput_keyboard *)wlr_kb;
|
||||
struct wlr_libinput_input_device *dev = wl_container_of(kb, dev, keyboard);
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void keyboard_set_leds(struct wlr_keyboard *wlr_kb, uint32_t leds) {
|
||||
struct wlr_libinput_keyboard *kb =
|
||||
get_libinput_keyboard_from_keyboard(wlr_kb);
|
||||
libinput_device_led_update(kb->libinput_dev, leds);
|
||||
}
|
||||
|
||||
static void keyboard_destroy(struct wlr_keyboard *wlr_kb) {
|
||||
struct wlr_libinput_keyboard *kb =
|
||||
get_libinput_keyboard_from_keyboard(wlr_kb);
|
||||
libinput_device_unref(kb->libinput_dev);
|
||||
free(kb);
|
||||
struct wlr_libinput_input_device *dev = device_from_keyboard(wlr_kb);
|
||||
libinput_device_led_update(dev->handle, leds);
|
||||
}
|
||||
|
||||
const struct wlr_keyboard_impl libinput_keyboard_impl = {
|
||||
.destroy = keyboard_destroy,
|
||||
.name = "libinput-keyboard",
|
||||
.led_update = keyboard_set_leds
|
||||
};
|
||||
|
||||
struct wlr_keyboard *create_libinput_keyboard(
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_libinput_keyboard *kb =
|
||||
calloc(1, sizeof(struct wlr_libinput_keyboard));
|
||||
if (kb == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
kb->libinput_dev = libinput_dev;
|
||||
libinput_device_ref(libinput_dev);
|
||||
libinput_device_led_update(libinput_dev, 0);
|
||||
struct wlr_keyboard *wlr_kb = &kb->wlr_keyboard;
|
||||
const char *name = libinput_device_get_name(libinput_dev);
|
||||
void init_device_keyboard(struct wlr_libinput_input_device *dev) {
|
||||
const char *name = libinput_device_get_name(dev->handle);
|
||||
struct wlr_keyboard *wlr_kb = &dev->keyboard;
|
||||
wlr_keyboard_init(wlr_kb, &libinput_keyboard_impl, name);
|
||||
wlr_kb->base.vendor = libinput_device_get_id_vendor(libinput_dev);
|
||||
wlr_kb->base.product = libinput_device_get_id_product(libinput_dev);
|
||||
return wlr_kb;
|
||||
wlr_kb->base.vendor = libinput_device_get_id_vendor(dev->handle);
|
||||
wlr_kb->base.product = libinput_device_get_id_product(dev->handle);
|
||||
|
||||
libinput_device_led_update(dev->handle, 0);
|
||||
}
|
||||
|
||||
void handle_keyboard_key(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_KEYBOARD, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Got a keyboard event for a device with no keyboards?");
|
||||
return;
|
||||
}
|
||||
struct wlr_keyboard *kb) {
|
||||
struct libinput_event_keyboard *kbevent =
|
||||
libinput_event_get_keyboard_event(event);
|
||||
struct wlr_event_keyboard_key wlr_event = { 0 };
|
||||
struct wlr_keyboard_key_event wlr_event = { 0 };
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_keyboard_get_time_usec(kbevent));
|
||||
wlr_event.keycode = libinput_event_keyboard_get_key(kbevent);
|
||||
|
|
@ -79,5 +51,5 @@ void handle_keyboard_key(struct libinput_event *event,
|
|||
break;
|
||||
}
|
||||
wlr_event.update_state = true;
|
||||
wlr_keyboard_notify_key(wlr_dev->keyboard, &wlr_event);
|
||||
wlr_keyboard_notify_key(kb, &wlr_event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ wlr_files += files(
|
|||
features += { 'libinput-backend': true }
|
||||
wlr_deps += libinput
|
||||
|
||||
# libinput hold gestures are available since 1.19.0
|
||||
add_project_arguments(
|
||||
# libinput hold gestures and high resolution scroll are available since 1.19.0
|
||||
add_project_arguments([
|
||||
'-DLIBINPUT_HAS_HOLD_GESTURES=@0@'.format(libinput.version().version_compare('>=1.19.0').to_int()),
|
||||
language: 'c',
|
||||
)
|
||||
'-DLIBINPUT_HAS_SCROLL_VALUE120=@0@'.format(libinput.version().version_compare('>=1.19.0').to_int()),
|
||||
], language: 'c')
|
||||
|
|
|
|||
|
|
@ -1,83 +1,65 @@
|
|||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <wlr/interfaces/wlr_pointer.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
const struct wlr_pointer_impl libinput_pointer_impl = {0};
|
||||
const struct wlr_pointer_impl libinput_pointer_impl = {
|
||||
.name = "libinput-pointer",
|
||||
};
|
||||
|
||||
struct wlr_pointer *create_libinput_pointer(
|
||||
struct libinput_device *libinput_dev) {
|
||||
assert(libinput_dev);
|
||||
struct wlr_pointer *wlr_pointer = calloc(1, sizeof(struct wlr_pointer));
|
||||
if (!wlr_pointer) {
|
||||
wlr_log(WLR_ERROR, "Unable to allocate wlr_pointer");
|
||||
return NULL;
|
||||
}
|
||||
const char *name = libinput_device_get_name(libinput_dev);
|
||||
void init_device_pointer(struct wlr_libinput_input_device *dev) {
|
||||
const char *name = libinput_device_get_name(dev->handle);
|
||||
struct wlr_pointer *wlr_pointer = &dev->pointer;
|
||||
wlr_pointer_init(wlr_pointer, &libinput_pointer_impl, name);
|
||||
wlr_pointer->base.vendor = libinput_device_get_id_vendor(libinput_dev);
|
||||
wlr_pointer->base.product = libinput_device_get_id_product(libinput_dev);
|
||||
return wlr_pointer;
|
||||
wlr_pointer->base.vendor = libinput_device_get_id_vendor(dev->handle);
|
||||
wlr_pointer->base.product = libinput_device_get_id_product(dev->handle);
|
||||
}
|
||||
|
||||
struct wlr_libinput_input_device *device_from_pointer(
|
||||
struct wlr_pointer *wlr_pointer) {
|
||||
assert(wlr_pointer->impl == &libinput_pointer_impl);
|
||||
|
||||
struct wlr_libinput_input_device *dev =
|
||||
wl_container_of(wlr_pointer, dev, pointer);
|
||||
return dev;
|
||||
}
|
||||
|
||||
void handle_pointer_motion(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_pointer *pevent =
|
||||
libinput_event_get_pointer_event(event);
|
||||
struct wlr_event_pointer_motion wlr_event = { 0 };
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_pointer_motion_event wlr_event = { 0 };
|
||||
wlr_event.pointer = pointer;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_pointer_get_time_usec(pevent));
|
||||
wlr_event.delta_x = libinput_event_pointer_get_dx(pevent);
|
||||
wlr_event.delta_y = libinput_event_pointer_get_dy(pevent);
|
||||
wlr_event.unaccel_dx = libinput_event_pointer_get_dx_unaccelerated(pevent);
|
||||
wlr_event.unaccel_dy = libinput_event_pointer_get_dy_unaccelerated(pevent);
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.motion, &wlr_event);
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer);
|
||||
wl_signal_emit_mutable(&pointer->events.motion, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
||||
}
|
||||
|
||||
void handle_pointer_motion_abs(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_pointer *pevent =
|
||||
libinput_event_get_pointer_event(event);
|
||||
struct wlr_event_pointer_motion_absolute wlr_event = { 0 };
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_pointer_motion_absolute_event wlr_event = { 0 };
|
||||
wlr_event.pointer = pointer;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_pointer_get_time_usec(pevent));
|
||||
wlr_event.x = libinput_event_pointer_get_absolute_x_transformed(pevent, 1);
|
||||
wlr_event.y = libinput_event_pointer_get_absolute_y_transformed(pevent, 1);
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.motion_absolute, &wlr_event);
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer);
|
||||
wl_signal_emit_mutable(&pointer->events.motion_absolute, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
||||
}
|
||||
|
||||
void handle_pointer_button(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_pointer *pevent =
|
||||
libinput_event_get_pointer_event(event);
|
||||
struct wlr_event_pointer_button wlr_event = { 0 };
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_pointer_button_event wlr_event = { 0 };
|
||||
wlr_event.pointer = pointer;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_pointer_get_time_usec(pevent));
|
||||
wlr_event.button = libinput_event_pointer_get_button(pevent);
|
||||
|
|
@ -89,22 +71,16 @@ void handle_pointer_button(struct libinput_event *event,
|
|||
wlr_event.state = WLR_BUTTON_RELEASED;
|
||||
break;
|
||||
}
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.button, &wlr_event);
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer);
|
||||
wl_signal_emit_mutable(&pointer->events.button, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
||||
}
|
||||
|
||||
void handle_pointer_axis(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_pointer *pevent =
|
||||
libinput_event_get_pointer_event(event);
|
||||
struct wlr_event_pointer_axis wlr_event = { 0 };
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_pointer_axis_event wlr_event = { 0 };
|
||||
wlr_event.pointer = pointer;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_pointer_get_time_usec(pevent));
|
||||
switch (libinput_event_pointer_get_axis_source(pevent)) {
|
||||
|
|
@ -126,115 +102,127 @@ void handle_pointer_axis(struct libinput_event *event,
|
|||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(axes) / sizeof(axes[0]); ++i) {
|
||||
if (libinput_event_pointer_has_axis(pevent, axes[i])) {
|
||||
switch (axes[i]) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
wlr_event.orientation = WLR_AXIS_ORIENTATION_VERTICAL;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
wlr_event.orientation = WLR_AXIS_ORIENTATION_HORIZONTAL;
|
||||
break;
|
||||
}
|
||||
wlr_event.delta =
|
||||
libinput_event_pointer_get_axis_value(pevent, axes[i]);
|
||||
wlr_event.delta_discrete =
|
||||
libinput_event_pointer_get_axis_value_discrete(pevent, axes[i]);
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.axis, &wlr_event);
|
||||
if (!libinput_event_pointer_has_axis(pevent, axes[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (axes[i]) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
wlr_event.orientation = WLR_AXIS_ORIENTATION_VERTICAL;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
wlr_event.orientation = WLR_AXIS_ORIENTATION_HORIZONTAL;
|
||||
break;
|
||||
}
|
||||
wlr_event.delta =
|
||||
libinput_event_pointer_get_axis_value(pevent, axes[i]);
|
||||
wlr_event.delta_discrete =
|
||||
libinput_event_pointer_get_axis_value_discrete(pevent, axes[i]);
|
||||
wlr_event.delta_discrete *= WLR_POINTER_AXIS_DISCRETE_STEP;
|
||||
wl_signal_emit_mutable(&pointer->events.axis, &wlr_event);
|
||||
}
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer);
|
||||
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
||||
}
|
||||
|
||||
void handle_pointer_swipe_begin(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?");
|
||||
return;
|
||||
#if LIBINPUT_HAS_SCROLL_VALUE120
|
||||
void handle_pointer_axis_value120(struct libinput_event *event,
|
||||
struct wlr_pointer *pointer, enum wlr_axis_source source) {
|
||||
struct libinput_event_pointer *pevent =
|
||||
libinput_event_get_pointer_event(event);
|
||||
struct wlr_pointer_axis_event wlr_event = { 0 };
|
||||
wlr_event.pointer = pointer;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_pointer_get_time_usec(pevent));
|
||||
wlr_event.source = source;
|
||||
|
||||
const enum libinput_pointer_axis axes[] = {
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(axes) / sizeof(axes[0]); ++i) {
|
||||
if (!libinput_event_pointer_has_axis(pevent, axes[i])) {
|
||||
continue;
|
||||
}
|
||||
switch (axes[i]) {
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
|
||||
wlr_event.orientation = WLR_AXIS_ORIENTATION_VERTICAL;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
|
||||
wlr_event.orientation = WLR_AXIS_ORIENTATION_HORIZONTAL;
|
||||
break;
|
||||
}
|
||||
wlr_event.delta =
|
||||
libinput_event_pointer_get_scroll_value(pevent, axes[i]);
|
||||
if (source == WLR_AXIS_SOURCE_WHEEL) {
|
||||
wlr_event.delta_discrete =
|
||||
libinput_event_pointer_get_scroll_value_v120(pevent, axes[i]);
|
||||
}
|
||||
wl_signal_emit_mutable(&pointer->events.axis, &wlr_event);
|
||||
}
|
||||
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
||||
}
|
||||
#endif
|
||||
|
||||
void handle_pointer_swipe_begin(struct libinput_event *event,
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_gesture *gevent =
|
||||
libinput_event_get_gesture_event(event);
|
||||
struct wlr_event_pointer_swipe_begin wlr_event = {
|
||||
.device = wlr_dev,
|
||||
struct wlr_pointer_swipe_begin_event wlr_event = {
|
||||
.pointer = pointer,
|
||||
.time_msec =
|
||||
usec_to_msec(libinput_event_gesture_get_time_usec(gevent)),
|
||||
.fingers = libinput_event_gesture_get_finger_count(gevent),
|
||||
};
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.swipe_begin, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.swipe_begin, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_pointer_swipe_update(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_gesture *gevent =
|
||||
libinput_event_get_gesture_event(event);
|
||||
struct wlr_event_pointer_swipe_update wlr_event = {
|
||||
.device = wlr_dev,
|
||||
struct wlr_pointer_swipe_update_event wlr_event = {
|
||||
.pointer = pointer,
|
||||
.time_msec =
|
||||
usec_to_msec(libinput_event_gesture_get_time_usec(gevent)),
|
||||
.fingers = libinput_event_gesture_get_finger_count(gevent),
|
||||
.dx = libinput_event_gesture_get_dx(gevent),
|
||||
.dy = libinput_event_gesture_get_dy(gevent),
|
||||
};
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.swipe_update, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.swipe_update, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_pointer_swipe_end(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_gesture *gevent =
|
||||
libinput_event_get_gesture_event(event);
|
||||
struct wlr_event_pointer_swipe_end wlr_event = {
|
||||
.device = wlr_dev,
|
||||
struct wlr_pointer_swipe_end_event wlr_event = {
|
||||
.pointer = pointer,
|
||||
.time_msec =
|
||||
usec_to_msec(libinput_event_gesture_get_time_usec(gevent)),
|
||||
.cancelled = libinput_event_gesture_get_cancelled(gevent),
|
||||
};
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.swipe_end, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.swipe_end, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_pointer_pinch_begin(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_gesture *gevent =
|
||||
libinput_event_get_gesture_event(event);
|
||||
struct wlr_event_pointer_pinch_begin wlr_event = {
|
||||
.device = wlr_dev,
|
||||
struct wlr_pointer_pinch_begin_event wlr_event = {
|
||||
.pointer = pointer,
|
||||
.time_msec =
|
||||
usec_to_msec(libinput_event_gesture_get_time_usec(gevent)),
|
||||
.fingers = libinput_event_gesture_get_finger_count(gevent),
|
||||
};
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.pinch_begin, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.pinch_begin, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_pointer_pinch_update(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_gesture *gevent =
|
||||
libinput_event_get_gesture_event(event);
|
||||
struct wlr_event_pointer_pinch_update wlr_event = {
|
||||
.device = wlr_dev,
|
||||
struct wlr_pointer_pinch_update_event wlr_event = {
|
||||
.pointer = pointer,
|
||||
.time_msec =
|
||||
usec_to_msec(libinput_event_gesture_get_time_usec(gevent)),
|
||||
.fingers = libinput_event_gesture_get_finger_count(gevent),
|
||||
|
|
@ -243,62 +231,44 @@ void handle_pointer_pinch_update(struct libinput_event *event,
|
|||
.scale = libinput_event_gesture_get_scale(gevent),
|
||||
.rotation = libinput_event_gesture_get_angle_delta(gevent),
|
||||
};
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.pinch_update, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.pinch_update, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_pointer_pinch_end(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_gesture *gevent =
|
||||
libinput_event_get_gesture_event(event);
|
||||
struct wlr_event_pointer_pinch_end wlr_event = {
|
||||
.device = wlr_dev,
|
||||
struct wlr_pointer_pinch_end_event wlr_event = {
|
||||
.pointer = pointer,
|
||||
.time_msec =
|
||||
usec_to_msec(libinput_event_gesture_get_time_usec(gevent)),
|
||||
.cancelled = libinput_event_gesture_get_cancelled(gevent),
|
||||
};
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.pinch_end, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.pinch_end, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_pointer_hold_begin(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_gesture *gevent =
|
||||
libinput_event_get_gesture_event(event);
|
||||
struct wlr_event_pointer_hold_begin wlr_event = {
|
||||
.device = wlr_dev,
|
||||
struct wlr_pointer_hold_begin_event wlr_event = {
|
||||
.pointer = pointer,
|
||||
.time_msec =
|
||||
usec_to_msec(libinput_event_gesture_get_time_usec(gevent)),
|
||||
.fingers = libinput_event_gesture_get_finger_count(gevent),
|
||||
};
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.hold_begin, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.hold_begin, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_pointer_hold_end(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a pointer gesture event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_gesture *gevent =
|
||||
libinput_event_get_gesture_event(event);
|
||||
struct wlr_event_pointer_hold_end wlr_event = {
|
||||
.device = wlr_dev,
|
||||
struct wlr_pointer_hold_end_event wlr_event = {
|
||||
.pointer = pointer,
|
||||
.time_msec =
|
||||
usec_to_msec(libinput_event_gesture_get_time_usec(gevent)),
|
||||
.cancelled = libinput_event_gesture_get_cancelled(gevent),
|
||||
};
|
||||
wlr_signal_emit_safe(&wlr_dev->pointer->events.hold_end, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.hold_end, &wlr_event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +1,34 @@
|
|||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/interfaces/wlr_switch.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
const struct wlr_switch_impl libinput_switch_impl;
|
||||
const struct wlr_switch_impl libinput_switch_impl = {
|
||||
.name = "libinput-switch",
|
||||
};
|
||||
|
||||
struct wlr_switch *create_libinput_switch(
|
||||
struct libinput_device *libinput_dev) {
|
||||
assert(libinput_dev);
|
||||
struct wlr_switch *wlr_switch = calloc(1, sizeof(struct wlr_switch));
|
||||
if (!wlr_switch) {
|
||||
wlr_log(WLR_ERROR, "Unable to allocate wlr_switch");
|
||||
return NULL;
|
||||
}
|
||||
const char *name = libinput_device_get_name(libinput_dev);
|
||||
void init_device_switch(struct wlr_libinput_input_device *dev) {
|
||||
const char *name = libinput_device_get_name(dev->handle);
|
||||
struct wlr_switch *wlr_switch = &dev->switch_device;
|
||||
wlr_switch_init(wlr_switch, &libinput_switch_impl, name);
|
||||
wlr_log(WLR_DEBUG, "Created switch for device %s", name);
|
||||
wlr_switch->base.vendor = libinput_device_get_id_vendor(libinput_dev);
|
||||
wlr_switch->base.product = libinput_device_get_id_product(libinput_dev);
|
||||
return wlr_switch;
|
||||
wlr_switch->base.vendor = libinput_device_get_id_vendor(dev->handle);
|
||||
wlr_switch->base.product = libinput_device_get_id_product(dev->handle);
|
||||
}
|
||||
|
||||
struct wlr_libinput_input_device *device_from_switch(
|
||||
struct wlr_switch *wlr_switch) {
|
||||
assert(wlr_switch->impl == &libinput_switch_impl);
|
||||
|
||||
struct wlr_libinput_input_device *dev =
|
||||
wl_container_of(wlr_switch, dev, switch_device);
|
||||
return dev;
|
||||
}
|
||||
|
||||
void handle_switch_toggle(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_SWITCH, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a switch event for a device with no switch?");
|
||||
return;
|
||||
}
|
||||
struct wlr_switch *wlr_switch) {
|
||||
struct libinput_event_switch *sevent =
|
||||
libinput_event_get_switch_event (event);
|
||||
struct wlr_event_switch_toggle wlr_event = { 0 };
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_switch_toggle_event wlr_event = { 0 };
|
||||
switch (libinput_event_switch_get_switch(sevent)) {
|
||||
case LIBINPUT_SWITCH_LID:
|
||||
wlr_event.switch_type = WLR_SWITCH_TYPE_LID;
|
||||
|
|
@ -56,5 +47,5 @@ void handle_switch_toggle(struct libinput_event *event,
|
|||
}
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_switch_get_time_usec(sevent));
|
||||
wlr_signal_emit_safe(&wlr_dev->switch_device->events.toggle, &wlr_event);
|
||||
wl_signal_emit_mutable(&wlr_switch->events.toggle, &wlr_event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,23 @@
|
|||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <libinput.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/interfaces/wlr_tablet_pad.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
// FIXME: Decide on how to alloc/count here
|
||||
const struct wlr_tablet_pad_impl libinput_tablet_pad_impl = {
|
||||
.name = "libinput-tablet-pad",
|
||||
};
|
||||
|
||||
static void group_destroy(struct wlr_tablet_pad_group *group) {
|
||||
free(group->buttons);
|
||||
free(group->strips);
|
||||
free(group->rings);
|
||||
free(group);
|
||||
}
|
||||
|
||||
static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad,
|
||||
struct libinput_device *device, unsigned int index) {
|
||||
struct libinput_tablet_pad_mode_group *li_group =
|
||||
|
|
@ -20,6 +25,7 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad,
|
|||
struct wlr_tablet_pad_group *group =
|
||||
calloc(1, sizeof(struct wlr_tablet_pad_group));
|
||||
if (!group) {
|
||||
wlr_log_errno(WLR_ERROR, "failed to allocate wlr_tablet_pad_group");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -29,6 +35,10 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad,
|
|||
}
|
||||
}
|
||||
group->rings = calloc(sizeof(unsigned int), group->ring_count);
|
||||
if (group->rings == NULL) {
|
||||
goto group_fail;
|
||||
}
|
||||
|
||||
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)) {
|
||||
|
|
@ -42,6 +52,9 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad,
|
|||
}
|
||||
}
|
||||
group->strips = calloc(sizeof(unsigned int), group->strip_count);
|
||||
if (group->strips == NULL) {
|
||||
goto group_fail;
|
||||
}
|
||||
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)) {
|
||||
|
|
@ -55,6 +68,9 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad,
|
|||
}
|
||||
}
|
||||
group->buttons = calloc(sizeof(unsigned int), group->button_count);
|
||||
if (group->buttons == NULL) {
|
||||
goto group_fail;
|
||||
}
|
||||
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)) {
|
||||
|
|
@ -63,56 +79,72 @@ static void add_pad_group_from_libinput(struct wlr_tablet_pad *pad,
|
|||
}
|
||||
|
||||
group->mode_count = libinput_tablet_pad_mode_group_get_num_modes(li_group);
|
||||
|
||||
libinput_tablet_pad_mode_group_ref(li_group);
|
||||
|
||||
wl_list_insert(&pad->groups, &group->link);
|
||||
return;
|
||||
|
||||
group_fail:
|
||||
wlr_log(WLR_ERROR, "failed to configure wlr_tablet_pad_group");
|
||||
group_destroy(group);
|
||||
}
|
||||
|
||||
const struct wlr_tablet_pad_impl libinput_tablet_pad_impl;
|
||||
|
||||
struct wlr_tablet_pad *create_libinput_tablet_pad(
|
||||
struct libinput_device *libinput_dev) {
|
||||
assert(libinput_dev);
|
||||
struct wlr_tablet_pad *wlr_tablet_pad =
|
||||
calloc(1, sizeof(struct wlr_tablet_pad));
|
||||
if (!wlr_tablet_pad) {
|
||||
wlr_log(WLR_ERROR, "Unable to allocate wlr_tablet_pad");
|
||||
return NULL;
|
||||
}
|
||||
const char *name = libinput_device_get_name(libinput_dev);
|
||||
void init_device_tablet_pad(struct wlr_libinput_input_device *dev) {
|
||||
struct libinput_device *handle = dev->handle;
|
||||
const char *name = libinput_device_get_name(handle);
|
||||
struct wlr_tablet_pad *wlr_tablet_pad = &dev->tablet_pad;
|
||||
wlr_tablet_pad_init(wlr_tablet_pad, &libinput_tablet_pad_impl, name);
|
||||
wlr_tablet_pad->base.vendor = libinput_device_get_id_vendor(libinput_dev);
|
||||
wlr_tablet_pad->base.product = libinput_device_get_id_product(libinput_dev);
|
||||
wlr_tablet_pad->base.vendor = libinput_device_get_id_vendor(handle);
|
||||
wlr_tablet_pad->base.product = libinput_device_get_id_product(handle);
|
||||
|
||||
wlr_tablet_pad->button_count =
|
||||
libinput_device_tablet_pad_get_num_buttons(libinput_dev);
|
||||
libinput_device_tablet_pad_get_num_buttons(handle);
|
||||
wlr_tablet_pad->ring_count =
|
||||
libinput_device_tablet_pad_get_num_rings(libinput_dev);
|
||||
libinput_device_tablet_pad_get_num_rings(handle);
|
||||
wlr_tablet_pad->strip_count =
|
||||
libinput_device_tablet_pad_get_num_strips(libinput_dev);
|
||||
libinput_device_tablet_pad_get_num_strips(handle);
|
||||
|
||||
struct udev_device *udev = libinput_device_get_udev_device(libinput_dev);
|
||||
struct udev_device *udev = libinput_device_get_udev_device(handle);
|
||||
char **dst = wl_array_add(&wlr_tablet_pad->paths, sizeof(char *));
|
||||
*dst = strdup(udev_device_get_syspath(udev));
|
||||
|
||||
int groups = libinput_device_tablet_pad_get_num_mode_groups(libinput_dev);
|
||||
int groups = libinput_device_tablet_pad_get_num_mode_groups(handle);
|
||||
for (int i = 0; i < groups; ++i) {
|
||||
add_pad_group_from_libinput(wlr_tablet_pad, libinput_dev, i);
|
||||
add_pad_group_from_libinput(wlr_tablet_pad, handle, i);
|
||||
}
|
||||
}
|
||||
|
||||
void finish_device_tablet_pad(struct wlr_libinput_input_device *dev) {
|
||||
struct wlr_tablet_pad_group *group, *tmp;
|
||||
wl_list_for_each_safe(group, tmp, &dev->tablet_pad.groups, link) {
|
||||
group_destroy(group);
|
||||
}
|
||||
|
||||
return wlr_tablet_pad;
|
||||
wlr_tablet_pad_finish(&dev->tablet_pad);
|
||||
|
||||
int groups = libinput_device_tablet_pad_get_num_mode_groups(dev->handle);
|
||||
for (int i = 0; i < groups; ++i) {
|
||||
struct libinput_tablet_pad_mode_group *li_group =
|
||||
libinput_device_tablet_pad_get_mode_group(dev->handle, i);
|
||||
libinput_tablet_pad_mode_group_unref(li_group);
|
||||
}
|
||||
}
|
||||
|
||||
struct wlr_libinput_input_device *device_from_tablet_pad(
|
||||
struct wlr_tablet_pad *wlr_tablet_pad) {
|
||||
assert(wlr_tablet_pad->impl == &libinput_tablet_pad_impl);
|
||||
|
||||
struct wlr_libinput_input_device *dev =
|
||||
wl_container_of(wlr_tablet_pad, dev, tablet_pad);
|
||||
return dev;
|
||||
}
|
||||
|
||||
void handle_tablet_pad_button(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Got a tablet pad event for a device with no tablet pad?");
|
||||
return;
|
||||
}
|
||||
struct wlr_tablet_pad *tablet_pad) {
|
||||
struct libinput_event_tablet_pad *pevent =
|
||||
libinput_event_get_tablet_pad_event(event);
|
||||
struct wlr_event_tablet_pad_button wlr_event = { 0 };
|
||||
struct wlr_tablet_pad_button_event wlr_event = { 0 };
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_tablet_pad_get_time_usec(pevent));
|
||||
wlr_event.button = libinput_event_tablet_pad_get_button_number(pevent);
|
||||
|
|
@ -127,21 +159,14 @@ void handle_tablet_pad_button(struct libinput_event *event,
|
|||
wlr_event.state = WLR_BUTTON_RELEASED;
|
||||
break;
|
||||
}
|
||||
wlr_signal_emit_safe(&wlr_dev->tablet_pad->events.button, &wlr_event);
|
||||
wl_signal_emit_mutable(&tablet_pad->events.button, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_tablet_pad_ring(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Got a tablet pad event for a device with no tablet pad?");
|
||||
return;
|
||||
}
|
||||
struct wlr_tablet_pad *tablet_pad) {
|
||||
struct libinput_event_tablet_pad *pevent =
|
||||
libinput_event_get_tablet_pad_event(event);
|
||||
struct wlr_event_tablet_pad_ring wlr_event = { 0 };
|
||||
struct wlr_tablet_pad_ring_event wlr_event = { 0 };
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_tablet_pad_get_time_usec(pevent));
|
||||
wlr_event.ring = libinput_event_tablet_pad_get_ring_number(pevent);
|
||||
|
|
@ -155,21 +180,14 @@ void handle_tablet_pad_ring(struct libinput_event *event,
|
|||
wlr_event.source = WLR_TABLET_PAD_RING_SOURCE_FINGER;
|
||||
break;
|
||||
}
|
||||
wlr_signal_emit_safe(&wlr_dev->tablet_pad->events.ring, &wlr_event);
|
||||
wl_signal_emit_mutable(&tablet_pad->events.ring, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_tablet_pad_strip(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_PAD, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Got a tablet pad event for a device with no tablet pad?");
|
||||
return;
|
||||
}
|
||||
struct wlr_tablet_pad *tablet_pad) {
|
||||
struct libinput_event_tablet_pad *pevent =
|
||||
libinput_event_get_tablet_pad_event(event);
|
||||
struct wlr_event_tablet_pad_strip wlr_event = { 0 };
|
||||
struct wlr_tablet_pad_strip_event wlr_event = { 0 };
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_tablet_pad_get_time_usec(pevent));
|
||||
wlr_event.strip = libinput_event_tablet_pad_get_strip_number(pevent);
|
||||
|
|
@ -183,5 +201,5 @@ void handle_tablet_pad_strip(struct libinput_event *event,
|
|||
wlr_event.source = WLR_TABLET_PAD_STRIP_SOURCE_FINGER;
|
||||
break;
|
||||
}
|
||||
wlr_signal_emit_safe(&wlr_dev->tablet_pad->events.strip, &wlr_event);
|
||||
wl_signal_emit_mutable(&tablet_pad->events.strip, &wlr_event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,92 +1,63 @@
|
|||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <stdlib.h>
|
||||
#include <wayland-util.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/interfaces/wlr_tablet_tool.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "util/array.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
static bool tablet_is_libinput(struct wlr_tablet *tablet) {
|
||||
return tablet->impl == &libinput_tablet_impl;
|
||||
}
|
||||
|
||||
struct wlr_libinput_tablet_tool {
|
||||
struct tablet_tool {
|
||||
struct wlr_tablet_tool wlr_tool;
|
||||
|
||||
struct libinput_tablet_tool *libinput_tool;
|
||||
|
||||
bool unique;
|
||||
// Refcount for destroy + release
|
||||
size_t pad_refs;
|
||||
struct libinput_tablet_tool *handle;
|
||||
struct wl_list link; // wlr_libinput_input_device::tablet_tools
|
||||
};
|
||||
|
||||
struct wlr_libinput_tablet {
|
||||
struct wlr_tablet wlr_tablet;
|
||||
struct wl_array tools; // struct wlr_libinput_tablet_tool *
|
||||
};
|
||||
|
||||
static void destroy_tool(struct wlr_libinput_tablet_tool *tool) {
|
||||
wlr_signal_emit_safe(&tool->wlr_tool.events.destroy, &tool->wlr_tool);
|
||||
libinput_tablet_tool_ref(tool->libinput_tool);
|
||||
libinput_tablet_tool_set_user_data(tool->libinput_tool, NULL);
|
||||
free(tool);
|
||||
}
|
||||
|
||||
static void destroy_tablet(struct wlr_tablet *wlr_tablet) {
|
||||
assert(tablet_is_libinput(wlr_tablet));
|
||||
struct wlr_libinput_tablet *tablet =
|
||||
wl_container_of(wlr_tablet, tablet, wlr_tablet);
|
||||
|
||||
struct wlr_libinput_tablet_tool **tool_ptr;
|
||||
wl_array_for_each(tool_ptr, &tablet->tools) {
|
||||
struct wlr_libinput_tablet_tool *tool = *tool_ptr;
|
||||
if (--tool->pad_refs == 0) {
|
||||
destroy_tool(tool);
|
||||
}
|
||||
}
|
||||
wl_array_release(&tablet->tools);
|
||||
|
||||
free(tablet);
|
||||
}
|
||||
|
||||
const struct wlr_tablet_impl libinput_tablet_impl = {
|
||||
.destroy = destroy_tablet,
|
||||
.name = "libinput-tablet-tool",
|
||||
};
|
||||
|
||||
struct wlr_tablet *create_libinput_tablet(
|
||||
struct libinput_device *libinput_dev) {
|
||||
assert(libinput_dev);
|
||||
struct wlr_libinput_tablet *libinput_tablet =
|
||||
calloc(1, sizeof(struct wlr_libinput_tablet));
|
||||
if (!libinput_tablet) {
|
||||
wlr_log(WLR_ERROR, "Unable to allocate wlr_tablet_tool");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_tablet *wlr_tablet = &libinput_tablet->wlr_tablet;
|
||||
const char *name = libinput_device_get_name(libinput_dev);
|
||||
|
||||
void init_device_tablet(struct wlr_libinput_input_device *dev) {
|
||||
const char *name = libinput_device_get_name(dev->handle);
|
||||
struct wlr_tablet *wlr_tablet = &dev->tablet;
|
||||
wlr_tablet_init(wlr_tablet, &libinput_tablet_impl, name);
|
||||
wlr_tablet->base.vendor = libinput_device_get_id_vendor(libinput_dev);
|
||||
wlr_tablet->base.product = libinput_device_get_id_product(libinput_dev);
|
||||
wlr_tablet->base.vendor = libinput_device_get_id_vendor(dev->handle);
|
||||
wlr_tablet->base.product = libinput_device_get_id_product(dev->handle);
|
||||
|
||||
struct udev_device *udev = libinput_device_get_udev_device(libinput_dev);
|
||||
libinput_device_get_size(dev->handle, &wlr_tablet->width_mm,
|
||||
&wlr_tablet->height_mm);
|
||||
|
||||
struct udev_device *udev = libinput_device_get_udev_device(dev->handle);
|
||||
char **dst = wl_array_add(&wlr_tablet->paths, sizeof(char *));
|
||||
*dst = strdup(udev_device_get_syspath(udev));
|
||||
|
||||
wlr_tablet->name = strdup(libinput_device_get_name(libinput_dev));
|
||||
wl_list_init(&dev->tablet_tools);
|
||||
}
|
||||
|
||||
wl_array_init(&libinput_tablet->tools);
|
||||
static void tool_destroy(struct tablet_tool *tool) {
|
||||
wl_signal_emit_mutable(&tool->wlr_tool.events.destroy, &tool->wlr_tool);
|
||||
libinput_tablet_tool_unref(tool->handle);
|
||||
libinput_tablet_tool_set_user_data(tool->handle, NULL);
|
||||
wl_list_remove(&tool->link);
|
||||
free(tool);
|
||||
}
|
||||
|
||||
return wlr_tablet;
|
||||
void finish_device_tablet(struct wlr_libinput_input_device *dev) {
|
||||
struct tablet_tool *tool, *tmp;
|
||||
wl_list_for_each_safe(tool, tmp, &dev->tablet_tools, link) {
|
||||
tool_destroy(tool);
|
||||
}
|
||||
|
||||
wlr_tablet_finish(&dev->tablet);
|
||||
}
|
||||
|
||||
struct wlr_libinput_input_device *device_from_tablet(
|
||||
struct wlr_tablet *wlr_tablet) {
|
||||
assert(wlr_tablet->impl == &libinput_tablet_impl);
|
||||
|
||||
struct wlr_libinput_input_device *dev =
|
||||
wl_container_of(wlr_tablet, dev, tablet);
|
||||
return dev;
|
||||
}
|
||||
|
||||
static enum wlr_tablet_tool_type wlr_type_from_libinput_type(
|
||||
|
|
@ -112,87 +83,54 @@ static enum wlr_tablet_tool_type wlr_type_from_libinput_type(
|
|||
abort(); // unreachable
|
||||
}
|
||||
|
||||
static struct wlr_libinput_tablet_tool *get_wlr_tablet_tool(
|
||||
struct libinput_tablet_tool *tool) {
|
||||
struct wlr_libinput_tablet_tool *ret =
|
||||
libinput_tablet_tool_get_user_data(tool);
|
||||
|
||||
if (ret) {
|
||||
return ret;
|
||||
static struct tablet_tool *get_tablet_tool(
|
||||
struct wlr_libinput_input_device *dev,
|
||||
struct libinput_tablet_tool *libinput_tool) {
|
||||
struct tablet_tool *tool =
|
||||
libinput_tablet_tool_get_user_data(libinput_tool);
|
||||
if (tool) {
|
||||
return tool;
|
||||
}
|
||||
|
||||
ret = calloc(1, sizeof(struct wlr_libinput_tablet_tool));
|
||||
if (!ret) {
|
||||
tool = calloc(1, sizeof(struct tablet_tool));
|
||||
if (tool == NULL) {
|
||||
wlr_log_errno(WLR_ERROR, "failed to allocate wlr_libinput_tablet_tool");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->libinput_tool = libinput_tablet_tool_ref(tool);
|
||||
ret->wlr_tool.pressure = libinput_tablet_tool_has_pressure(tool);
|
||||
ret->wlr_tool.distance = libinput_tablet_tool_has_distance(tool);
|
||||
ret->wlr_tool.tilt = libinput_tablet_tool_has_tilt(tool);
|
||||
ret->wlr_tool.rotation = libinput_tablet_tool_has_rotation(tool);
|
||||
ret->wlr_tool.slider = libinput_tablet_tool_has_slider(tool);
|
||||
ret->wlr_tool.wheel = libinput_tablet_tool_has_wheel(tool);
|
||||
tool->wlr_tool.type = wlr_type_from_libinput_type(
|
||||
libinput_tablet_tool_get_type(libinput_tool));
|
||||
tool->wlr_tool.hardware_serial =
|
||||
libinput_tablet_tool_get_serial(libinput_tool);
|
||||
tool->wlr_tool.hardware_wacom =
|
||||
libinput_tablet_tool_get_tool_id(libinput_tool);
|
||||
|
||||
ret->wlr_tool.hardware_serial = libinput_tablet_tool_get_serial(tool);
|
||||
ret->wlr_tool.hardware_wacom = libinput_tablet_tool_get_tool_id(tool);
|
||||
ret->wlr_tool.type = wlr_type_from_libinput_type(
|
||||
libinput_tablet_tool_get_type(tool));
|
||||
tool->wlr_tool.pressure = libinput_tablet_tool_has_pressure(libinput_tool);
|
||||
tool->wlr_tool.distance = libinput_tablet_tool_has_distance(libinput_tool);
|
||||
tool->wlr_tool.tilt = libinput_tablet_tool_has_tilt(libinput_tool);
|
||||
tool->wlr_tool.rotation = libinput_tablet_tool_has_rotation(libinput_tool);
|
||||
tool->wlr_tool.slider = libinput_tablet_tool_has_slider(libinput_tool);
|
||||
tool->wlr_tool.wheel = libinput_tablet_tool_has_wheel(libinput_tool);
|
||||
|
||||
ret->unique = libinput_tablet_tool_is_unique(tool);
|
||||
wl_signal_init(&tool->wlr_tool.events.destroy);
|
||||
|
||||
wl_signal_init(&ret->wlr_tool.events.destroy);
|
||||
tool->handle = libinput_tablet_tool_ref(libinput_tool);
|
||||
libinput_tablet_tool_set_user_data(libinput_tool, tool);
|
||||
|
||||
libinput_tablet_tool_set_user_data(tool, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ensure_tool_reference(struct wlr_libinput_tablet_tool *tool,
|
||||
struct wlr_tablet *wlr_dev) {
|
||||
assert(tablet_is_libinput(wlr_dev));
|
||||
struct wlr_libinput_tablet *tablet =
|
||||
wl_container_of(wlr_dev, tablet, wlr_tablet);
|
||||
|
||||
struct wlr_libinput_tablet_tool **tool_ptr;
|
||||
wl_array_for_each(tool_ptr, &tablet->tools) {
|
||||
if (*tool_ptr == tool) { // We already have a ref
|
||||
// XXX: We *could* optimize the tool to the front of
|
||||
// the list here, since we will probably get the next
|
||||
// couple of events from the same tool.
|
||||
// BUT the list should always be rather short (probably
|
||||
// single digit amount of tools) so it might be more
|
||||
// work than it saves
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct wlr_libinput_tablet_tool **dst =
|
||||
wl_array_add(&tablet->tools, sizeof(tool));
|
||||
if (!dst) {
|
||||
wlr_log(WLR_ERROR, "Failed to allocate memory for tracking tablet tool");
|
||||
return;
|
||||
}
|
||||
*dst = tool;
|
||||
++tool->pad_refs;
|
||||
wl_list_insert(&dev->tablet_tools, &tool->link);
|
||||
return tool;
|
||||
}
|
||||
|
||||
void handle_tablet_tool_axis(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Got a tablet tool event for a device with no tablet tools?");
|
||||
return;
|
||||
}
|
||||
struct wlr_tablet *wlr_tablet) {
|
||||
struct libinput_event_tablet_tool *tevent =
|
||||
libinput_event_get_tablet_tool_event(event);
|
||||
struct wlr_event_tablet_tool_axis wlr_event = { 0 };
|
||||
struct wlr_libinput_tablet_tool *tool = get_wlr_tablet_tool(
|
||||
libinput_event_tablet_tool_get_tool(tevent));
|
||||
ensure_tool_reference(tool, wlr_dev->tablet);
|
||||
struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet);
|
||||
struct tablet_tool *tool =
|
||||
get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent));
|
||||
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_tablet_tool_axis_event wlr_event = { 0 };
|
||||
wlr_event.tablet = wlr_tablet;
|
||||
wlr_event.tool = &tool->wlr_tool;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent));
|
||||
|
|
@ -234,27 +172,20 @@ void handle_tablet_tool_axis(struct libinput_event *event,
|
|||
wlr_event.updated_axes |= WLR_TABLET_TOOL_AXIS_WHEEL;
|
||||
wlr_event.wheel_delta = libinput_event_tablet_tool_get_wheel_delta(tevent);
|
||||
}
|
||||
wlr_signal_emit_safe(&wlr_dev->tablet->events.axis, &wlr_event);
|
||||
wl_signal_emit_mutable(&wlr_tablet->events.axis, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_tablet_tool_proximity(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Got a tablet tool event for a device with no tablet tools?");
|
||||
return;
|
||||
}
|
||||
struct wlr_tablet *wlr_tablet) {
|
||||
struct libinput_event_tablet_tool *tevent =
|
||||
libinput_event_get_tablet_tool_event(event);
|
||||
struct wlr_event_tablet_tool_proximity wlr_event = { 0 };
|
||||
struct wlr_libinput_tablet_tool *tool = get_wlr_tablet_tool(
|
||||
libinput_event_tablet_tool_get_tool(tevent));
|
||||
ensure_tool_reference(tool, wlr_dev->tablet);
|
||||
struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet);
|
||||
struct tablet_tool *tool =
|
||||
get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent));
|
||||
|
||||
struct wlr_tablet_tool_proximity_event wlr_event = { 0 };
|
||||
wlr_event.tablet = wlr_tablet;
|
||||
wlr_event.tool = &tool->wlr_tool;
|
||||
wlr_event.device = wlr_dev;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent));
|
||||
wlr_event.x = libinput_event_tablet_tool_get_x_transformed(tevent, 1);
|
||||
|
|
@ -268,56 +199,34 @@ void handle_tablet_tool_proximity(struct libinput_event *event,
|
|||
wlr_event.state = WLR_TABLET_TOOL_PROXIMITY_IN;
|
||||
break;
|
||||
}
|
||||
wlr_signal_emit_safe(&wlr_dev->tablet->events.proximity, &wlr_event);
|
||||
wl_signal_emit_mutable(&wlr_tablet->events.proximity, &wlr_event);
|
||||
|
||||
if (libinput_event_tablet_tool_get_proximity_state(tevent) ==
|
||||
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN) {
|
||||
handle_tablet_tool_axis(event, libinput_dev);
|
||||
handle_tablet_tool_axis(event, wlr_tablet);
|
||||
}
|
||||
|
||||
// If the tool is not unique, libinput will not find it again after the
|
||||
// proximity out, so we should destroy it
|
||||
if (!tool->unique &&
|
||||
libinput_event_tablet_tool_get_proximity_state(tevent) ==
|
||||
if (!libinput_tablet_tool_is_unique(tool->handle)
|
||||
&& libinput_event_tablet_tool_get_proximity_state(tevent) ==
|
||||
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT) {
|
||||
// The tool isn't unique, it can't be on multiple tablets
|
||||
assert(tool->pad_refs == 1);
|
||||
assert(tablet_is_libinput(wlr_dev->tablet));
|
||||
struct wlr_libinput_tablet *tablet =
|
||||
wl_container_of(wlr_dev->tablet, tablet, wlr_tablet);
|
||||
|
||||
size_t i = 0;
|
||||
struct wlr_libinput_tablet_tool **tool_ptr;
|
||||
wl_array_for_each(tool_ptr, &tablet->tools) {
|
||||
if (*tool_ptr == tool) {
|
||||
array_remove_at(&tablet->tools, i * sizeof(tool), sizeof(tool));
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
destroy_tool(tool);
|
||||
tool_destroy(tool);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_tablet_tool_tip(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Got a tablet tool event for a device with no tablet tools?");
|
||||
return;
|
||||
}
|
||||
handle_tablet_tool_axis(event, libinput_dev);
|
||||
struct wlr_tablet *wlr_tablet) {
|
||||
handle_tablet_tool_axis(event, wlr_tablet);
|
||||
struct libinput_event_tablet_tool *tevent =
|
||||
libinput_event_get_tablet_tool_event(event);
|
||||
struct wlr_event_tablet_tool_tip wlr_event = { 0 };
|
||||
struct wlr_libinput_tablet_tool *tool = get_wlr_tablet_tool(
|
||||
libinput_event_tablet_tool_get_tool(tevent));
|
||||
ensure_tool_reference(tool, wlr_dev->tablet);
|
||||
struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet);
|
||||
struct tablet_tool *tool =
|
||||
get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent));
|
||||
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_tablet_tool_tip_event wlr_event = { 0 };
|
||||
wlr_event.tablet = wlr_tablet;
|
||||
wlr_event.tool = &tool->wlr_tool;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent));
|
||||
|
|
@ -332,27 +241,20 @@ void handle_tablet_tool_tip(struct libinput_event *event,
|
|||
wlr_event.state = WLR_TABLET_TOOL_TIP_DOWN;
|
||||
break;
|
||||
}
|
||||
wlr_signal_emit_safe(&wlr_dev->tablet->events.tip, &wlr_event);
|
||||
wl_signal_emit_mutable(&wlr_tablet->events.tip, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_tablet_tool_button(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Got a tablet tool event for a device with no tablet tools?");
|
||||
return;
|
||||
}
|
||||
handle_tablet_tool_axis(event, libinput_dev);
|
||||
struct wlr_tablet *wlr_tablet) {
|
||||
handle_tablet_tool_axis(event, wlr_tablet);
|
||||
struct libinput_event_tablet_tool *tevent =
|
||||
libinput_event_get_tablet_tool_event(event);
|
||||
struct wlr_event_tablet_tool_button wlr_event = { 0 };
|
||||
struct wlr_libinput_tablet_tool *tool = get_wlr_tablet_tool(
|
||||
libinput_event_tablet_tool_get_tool(tevent));
|
||||
ensure_tool_reference(tool, wlr_dev->tablet);
|
||||
struct wlr_libinput_input_device *dev = device_from_tablet(wlr_tablet);
|
||||
struct tablet_tool *tool =
|
||||
get_tablet_tool(dev, libinput_event_tablet_tool_get_tool(tevent));
|
||||
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_tablet_tool_button_event wlr_event = { 0 };
|
||||
wlr_event.tablet = wlr_tablet;
|
||||
wlr_event.tool = &tool->wlr_tool;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent));
|
||||
|
|
@ -365,5 +267,5 @@ void handle_tablet_tool_button(struct libinput_event *event,
|
|||
wlr_event.state = WLR_BUTTON_PRESSED;
|
||||
break;
|
||||
}
|
||||
wlr_signal_emit_safe(&wlr_dev->tablet->events.button, &wlr_event);
|
||||
wl_signal_emit_mutable(&wlr_tablet->events.button, &wlr_event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,113 +1,85 @@
|
|||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/backend/session.h>
|
||||
#include <wlr/interfaces/wlr_touch.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
const struct wlr_touch_impl libinput_touch_impl;
|
||||
const struct wlr_touch_impl libinput_touch_impl = {
|
||||
.name = "libinput-touch",
|
||||
};
|
||||
|
||||
struct wlr_touch *create_libinput_touch(
|
||||
struct libinput_device *libinput_dev) {
|
||||
assert(libinput_dev);
|
||||
struct wlr_touch *wlr_touch = calloc(1, sizeof(struct wlr_touch));
|
||||
if (!wlr_touch) {
|
||||
wlr_log(WLR_ERROR, "Unable to allocate wlr_touch");
|
||||
return NULL;
|
||||
}
|
||||
const char *name = libinput_device_get_name(libinput_dev);
|
||||
void init_device_touch(struct wlr_libinput_input_device *dev) {
|
||||
const char *name = libinput_device_get_name(dev->handle);
|
||||
struct wlr_touch *wlr_touch = &dev->touch;
|
||||
wlr_touch_init(wlr_touch, &libinput_touch_impl, name);
|
||||
wlr_touch->base.vendor = libinput_device_get_id_vendor(libinput_dev);
|
||||
wlr_touch->base.product = libinput_device_get_id_product(libinput_dev);
|
||||
return wlr_touch;
|
||||
wlr_touch->base.vendor = libinput_device_get_id_vendor(dev->handle);
|
||||
wlr_touch->base.product = libinput_device_get_id_product(dev->handle);
|
||||
|
||||
libinput_device_get_size(dev->handle, &wlr_touch->width_mm,
|
||||
&wlr_touch->height_mm);
|
||||
}
|
||||
|
||||
struct wlr_libinput_input_device *device_from_touch(
|
||||
struct wlr_touch *wlr_touch) {
|
||||
assert(wlr_touch->impl == &libinput_touch_impl);
|
||||
|
||||
struct wlr_libinput_input_device *dev =
|
||||
wl_container_of(wlr_touch, dev, touch);
|
||||
return dev;
|
||||
}
|
||||
|
||||
void handle_touch_down(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a touch event for a device with no touch?");
|
||||
return;
|
||||
}
|
||||
struct wlr_touch *touch) {
|
||||
struct libinput_event_touch *tevent =
|
||||
libinput_event_get_touch_event(event);
|
||||
struct wlr_event_touch_down wlr_event = { 0 };
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_touch_down_event wlr_event = { 0 };
|
||||
wlr_event.touch = touch;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_touch_get_time_usec(tevent));
|
||||
wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent);
|
||||
wlr_event.x = libinput_event_touch_get_x_transformed(tevent, 1);
|
||||
wlr_event.y = libinput_event_touch_get_y_transformed(tevent, 1);
|
||||
wlr_signal_emit_safe(&wlr_dev->touch->events.down, &wlr_event);
|
||||
wl_signal_emit_mutable(&touch->events.down, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_touch_up(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a touch event for a device with no touch?");
|
||||
return;
|
||||
}
|
||||
struct wlr_touch *touch) {
|
||||
struct libinput_event_touch *tevent =
|
||||
libinput_event_get_touch_event(event);
|
||||
struct wlr_event_touch_up wlr_event = { 0 };
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_touch_up_event wlr_event = { 0 };
|
||||
wlr_event.touch = touch;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_touch_get_time_usec(tevent));
|
||||
wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent);
|
||||
wlr_signal_emit_safe(&wlr_dev->touch->events.up, &wlr_event);
|
||||
wl_signal_emit_mutable(&touch->events.up, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_touch_motion(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a touch event for a device with no touch?");
|
||||
return;
|
||||
}
|
||||
struct wlr_touch *touch) {
|
||||
struct libinput_event_touch *tevent =
|
||||
libinput_event_get_touch_event(event);
|
||||
struct wlr_event_touch_motion wlr_event = { 0 };
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_touch_motion_event wlr_event = { 0 };
|
||||
wlr_event.touch = touch;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_touch_get_time_usec(tevent));
|
||||
wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent);
|
||||
wlr_event.x = libinput_event_touch_get_x_transformed(tevent, 1);
|
||||
wlr_event.y = libinput_event_touch_get_y_transformed(tevent, 1);
|
||||
wlr_signal_emit_safe(&wlr_dev->touch->events.motion, &wlr_event);
|
||||
wl_signal_emit_mutable(&touch->events.motion, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_touch_cancel(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a touch event for a device with no touch?");
|
||||
return;
|
||||
}
|
||||
struct wlr_touch *touch) {
|
||||
struct libinput_event_touch *tevent =
|
||||
libinput_event_get_touch_event(event);
|
||||
struct wlr_event_touch_cancel wlr_event = { 0 };
|
||||
wlr_event.device = wlr_dev;
|
||||
struct wlr_touch_cancel_event wlr_event = { 0 };
|
||||
wlr_event.touch = touch;
|
||||
wlr_event.time_msec =
|
||||
usec_to_msec(libinput_event_touch_get_time_usec(tevent));
|
||||
wlr_event.touch_id = libinput_event_touch_get_seat_slot(tevent);
|
||||
wlr_signal_emit_safe(&wlr_dev->touch->events.cancel, &wlr_event);
|
||||
wl_signal_emit_mutable(&touch->events.cancel, &wlr_event);
|
||||
}
|
||||
|
||||
void handle_touch_frame(struct libinput_event *event,
|
||||
struct libinput_device *libinput_dev) {
|
||||
struct wlr_input_device *wlr_dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, libinput_dev);
|
||||
if (!wlr_dev) {
|
||||
wlr_log(WLR_DEBUG, "Got a touch event for a device with no touch?");
|
||||
return;
|
||||
}
|
||||
wlr_signal_emit_safe(&wlr_dev->touch->events.frame, NULL);
|
||||
struct wlr_touch *touch) {
|
||||
wl_signal_emit_mutable(&touch->events.frame, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#include <wlr/util/log.h>
|
||||
#include "backend/backend.h"
|
||||
#include "backend/multi.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
struct subbackend_state {
|
||||
struct wlr_backend *backend;
|
||||
|
|
@ -161,13 +160,13 @@ bool wlr_backend_is_multi(struct wlr_backend *b) {
|
|||
static void new_input_reemit(struct wl_listener *listener, void *data) {
|
||||
struct subbackend_state *state = wl_container_of(listener,
|
||||
state, new_input);
|
||||
wlr_signal_emit_safe(&state->container->events.new_input, data);
|
||||
wl_signal_emit_mutable(&state->container->events.new_input, data);
|
||||
}
|
||||
|
||||
static void new_output_reemit(struct wl_listener *listener, void *data) {
|
||||
struct subbackend_state *state = wl_container_of(listener,
|
||||
state, new_output);
|
||||
wlr_signal_emit_safe(&state->container->events.new_output, data);
|
||||
wl_signal_emit_mutable(&state->container->events.new_output, data);
|
||||
}
|
||||
|
||||
static void handle_subbackend_destroy(struct wl_listener *listener,
|
||||
|
|
@ -218,7 +217,7 @@ bool wlr_multi_backend_add(struct wlr_backend *_multi,
|
|||
wl_signal_add(&backend->events.new_output, &sub->new_output);
|
||||
sub->new_output.notify = new_output_reemit;
|
||||
|
||||
wlr_signal_emit_safe(&multi->events.backend_add, backend);
|
||||
wl_signal_emit_mutable(&multi->events.backend_add, backend);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +229,7 @@ void wlr_multi_backend_remove(struct wlr_backend *_multi,
|
|||
multi_backend_get_subbackend(multi, backend);
|
||||
|
||||
if (sub) {
|
||||
wlr_signal_emit_safe(&multi->events.backend_remove, backend);
|
||||
wl_signal_emit_mutable(&multi->events.backend_remove, backend);
|
||||
subbackend_state_destroy(sub);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include "backend/session/session.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
#include <libseat.h>
|
||||
|
||||
|
|
@ -26,13 +25,13 @@
|
|||
static void handle_enable_seat(struct libseat *seat, void *data) {
|
||||
struct wlr_session *session = data;
|
||||
session->active = true;
|
||||
wlr_signal_emit_safe(&session->events.active, NULL);
|
||||
wl_signal_emit_mutable(&session->events.active, NULL);
|
||||
}
|
||||
|
||||
static void handle_disable_seat(struct libseat *seat, void *data) {
|
||||
struct wlr_session *session = data;
|
||||
session->active = false;
|
||||
wlr_signal_emit_safe(&session->events.active, NULL);
|
||||
wl_signal_emit_mutable(&session->events.active, NULL);
|
||||
libseat_disable_seat(session->seat_handle);
|
||||
}
|
||||
|
||||
|
|
@ -198,7 +197,7 @@ static int handle_udev_event(int fd, uint32_t mask, void *data) {
|
|||
struct wlr_session_add_event event = {
|
||||
.path = devnode,
|
||||
};
|
||||
wlr_signal_emit_safe(&session->events.add_drm_card, &event);
|
||||
wl_signal_emit_mutable(&session->events.add_drm_card, &event);
|
||||
} else if (strcmp(action, "change") == 0 || strcmp(action, "remove") == 0) {
|
||||
dev_t devnum = udev_device_get_devnum(udev_dev);
|
||||
struct wlr_device *dev;
|
||||
|
|
@ -211,10 +210,10 @@ static int handle_udev_event(int fd, uint32_t mask, void *data) {
|
|||
wlr_log(WLR_DEBUG, "DRM device %s changed", sysname);
|
||||
struct wlr_device_change_event event = {0};
|
||||
read_udev_change_event(&event, udev_dev);
|
||||
wlr_signal_emit_safe(&dev->events.change, &event);
|
||||
wl_signal_emit_mutable(&dev->events.change, &event);
|
||||
} else if (strcmp(action, "remove") == 0) {
|
||||
wlr_log(WLR_DEBUG, "DRM device %s removed", sysname);
|
||||
wlr_signal_emit_safe(&dev->events.remove, NULL);
|
||||
wl_signal_emit_mutable(&dev->events.remove, NULL);
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
|
|
@ -298,7 +297,7 @@ void wlr_session_destroy(struct wlr_session *session) {
|
|||
return;
|
||||
}
|
||||
|
||||
wlr_signal_emit_safe(&session->events.destroy, session);
|
||||
wl_signal_emit_mutable(&session->events.destroy, session);
|
||||
wl_list_remove(&session->display_destroy.link);
|
||||
|
||||
wl_event_source_remove(session->udev_event);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
#include "backend/wayland.h"
|
||||
#include "render/drm_format_set.h"
|
||||
#include "render/pixel_format.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
#include "drm-client-protocol.h"
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
|
|
@ -346,8 +345,15 @@ static void registry_global(void *data, struct wl_registry *registry,
|
|||
wl->compositor = wl_registry_bind(registry, name,
|
||||
&wl_compositor_interface, 4);
|
||||
} else if (strcmp(iface, wl_seat_interface.name) == 0) {
|
||||
uint32_t target_version = version;
|
||||
if (version < 5) {
|
||||
target_version = 5;
|
||||
}
|
||||
if (version > 8) {
|
||||
target_version = 8;
|
||||
}
|
||||
struct wl_seat *wl_seat = wl_registry_bind(registry, name,
|
||||
&wl_seat_interface, 5);
|
||||
&wl_seat_interface, target_version);
|
||||
if (!create_wl_seat(wl_seat, wl)) {
|
||||
wl_seat_destroy(wl_seat);
|
||||
}
|
||||
|
|
@ -413,12 +419,16 @@ static bool backend_start(struct wlr_backend *backend) {
|
|||
|
||||
struct wlr_wl_seat *seat;
|
||||
wl_list_for_each(seat, &wl->seats, link) {
|
||||
if (seat->keyboard) {
|
||||
create_wl_keyboard(seat);
|
||||
if (seat->wl_keyboard) {
|
||||
init_seat_keyboard(seat);
|
||||
}
|
||||
|
||||
if (seat->wl_touch) {
|
||||
init_seat_touch(seat);
|
||||
}
|
||||
|
||||
if (wl->tablet_manager) {
|
||||
wl_add_tablet_seat(wl->tablet_manager, seat);
|
||||
init_seat_tablet(seat);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -441,11 +451,6 @@ static void backend_destroy(struct wlr_backend *backend) {
|
|||
wlr_output_destroy(&output->wlr_output);
|
||||
}
|
||||
|
||||
struct wlr_wl_input_device *input_device, *tmp_input_device;
|
||||
wl_list_for_each_safe(input_device, tmp_input_device, &wl->devices, link) {
|
||||
destroy_wl_input_device(input_device);
|
||||
}
|
||||
|
||||
struct wlr_wl_buffer *buffer, *tmp_buffer;
|
||||
wl_list_for_each_safe(buffer, tmp_buffer, &wl->buffers, link) {
|
||||
destroy_wl_buffer(buffer);
|
||||
|
|
@ -538,7 +543,6 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display,
|
|||
wlr_backend_init(&wl->backend, &backend_impl);
|
||||
|
||||
wl->local_display = display;
|
||||
wl_list_init(&wl->devices);
|
||||
wl_list_init(&wl->outputs);
|
||||
wl_list_init(&wl->seats);
|
||||
wl_list_init(&wl->buffers);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ wlr_files += files(
|
|||
'backend.c',
|
||||
'output.c',
|
||||
'seat.c',
|
||||
'pointer.c',
|
||||
'tablet_v2.c',
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
#include "render/pixel_format.h"
|
||||
#include "render/swapchain.h"
|
||||
#include "render/wlr_renderer.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "presentation-time-client-protocol.h"
|
||||
|
|
@ -30,7 +29,8 @@
|
|||
static const uint32_t SUPPORTED_OUTPUT_STATE =
|
||||
WLR_OUTPUT_STATE_BACKEND_OPTIONAL |
|
||||
WLR_OUTPUT_STATE_BUFFER |
|
||||
WLR_OUTPUT_STATE_MODE;
|
||||
WLR_OUTPUT_STATE_MODE |
|
||||
WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED;
|
||||
|
||||
static struct wlr_wl_output *get_wl_output_from_output(
|
||||
struct wlr_output *wlr_output) {
|
||||
|
|
@ -240,48 +240,59 @@ static struct wlr_wl_buffer *get_or_create_wl_buffer(struct wlr_wl_backend *wl,
|
|||
return create_wl_buffer(wl, wlr_buffer);
|
||||
}
|
||||
|
||||
static bool output_test(struct wlr_output *wlr_output) {
|
||||
static bool output_test(struct wlr_output *wlr_output,
|
||||
const struct wlr_output_state *state) {
|
||||
struct wlr_wl_output *output =
|
||||
get_wl_output_from_output(wlr_output);
|
||||
|
||||
uint32_t unsupported =
|
||||
wlr_output->pending.committed & ~SUPPORTED_OUTPUT_STATE;
|
||||
uint32_t unsupported = state->committed & ~SUPPORTED_OUTPUT_STATE;
|
||||
if (unsupported != 0) {
|
||||
wlr_log(WLR_DEBUG, "Unsupported output state fields: 0x%"PRIx32,
|
||||
unsupported);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
|
||||
assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
|
||||
// Adaptive sync is effectively always enabled when using the Wayland
|
||||
// backend. This is not something we have control over, so we set the state
|
||||
// to enabled on creating the output and never allow changing it.
|
||||
assert(wlr_output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED);
|
||||
if (state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) {
|
||||
if (!state->adaptive_sync_enabled) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) &&
|
||||
!test_buffer(output->backend, wlr_output->pending.buffer)) {
|
||||
if (state->committed & WLR_OUTPUT_STATE_MODE) {
|
||||
assert(state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_BUFFER) &&
|
||||
!test_buffer(output->backend, state->buffer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool output_commit(struct wlr_output *wlr_output) {
|
||||
static bool output_commit(struct wlr_output *wlr_output,
|
||||
const struct wlr_output_state *state) {
|
||||
struct wlr_wl_output *output =
|
||||
get_wl_output_from_output(wlr_output);
|
||||
|
||||
if (!output_test(wlr_output)) {
|
||||
if (!output_test(wlr_output, state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
|
||||
if (state->committed & WLR_OUTPUT_STATE_MODE) {
|
||||
if (!output_set_custom_mode(wlr_output,
|
||||
wlr_output->pending.custom_mode.width,
|
||||
wlr_output->pending.custom_mode.height,
|
||||
wlr_output->pending.custom_mode.refresh)) {
|
||||
state->custom_mode.width,
|
||||
state->custom_mode.height,
|
||||
state->custom_mode.refresh)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
struct wp_presentation_feedback *wp_feedback = NULL;
|
||||
if (output->backend->presentation != NULL) {
|
||||
wp_feedback = wp_presentation_feedback(output->backend->presentation,
|
||||
|
|
@ -289,8 +300,8 @@ static bool output_commit(struct wlr_output *wlr_output) {
|
|||
}
|
||||
|
||||
pixman_region32_t *damage = NULL;
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_DAMAGE) {
|
||||
damage = &wlr_output->pending.damage;
|
||||
if (state->committed & WLR_OUTPUT_STATE_DAMAGE) {
|
||||
damage = (pixman_region32_t *) &state->damage;
|
||||
}
|
||||
|
||||
if (output->frame_callback != NULL) {
|
||||
|
|
@ -301,7 +312,7 @@ static bool output_commit(struct wlr_output *wlr_output) {
|
|||
output->frame_callback = wl_surface_frame(output->surface);
|
||||
wl_callback_add_listener(output->frame_callback, &frame_listener, output);
|
||||
|
||||
struct wlr_buffer *wlr_buffer = wlr_output->pending.buffer;
|
||||
struct wlr_buffer *wlr_buffer = state->buffer;
|
||||
struct wlr_wl_buffer *buffer =
|
||||
get_or_create_wl_buffer(output->backend, wlr_buffer);
|
||||
if (buffer == NULL) {
|
||||
|
|
@ -436,7 +447,9 @@ void update_wl_output_cursor(struct wlr_wl_output *output) {
|
|||
if (pointer) {
|
||||
assert(pointer->output == output);
|
||||
assert(output->enter_serial);
|
||||
wl_pointer_set_cursor(pointer->wl_pointer, output->enter_serial,
|
||||
|
||||
struct wlr_wl_seat *seat = pointer->seat;
|
||||
wl_pointer_set_cursor(seat->wl_pointer, output->enter_serial,
|
||||
output->cursor.surface, output->cursor.hotspot_x,
|
||||
output->cursor.hotspot_y);
|
||||
}
|
||||
|
|
@ -518,8 +531,8 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) {
|
|||
struct wlr_output *wlr_output = &output->wlr_output;
|
||||
|
||||
wlr_output_update_custom_mode(wlr_output, 1280, 720, 0);
|
||||
strncpy(wlr_output->make, "wayland", sizeof(wlr_output->make));
|
||||
strncpy(wlr_output->model, "wayland", sizeof(wlr_output->model));
|
||||
|
||||
wlr_output->adaptive_sync_status = WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED;
|
||||
|
||||
char name[64];
|
||||
snprintf(name, sizeof(name), "WL-%zu", ++backend->last_output_num);
|
||||
|
|
@ -578,12 +591,12 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) {
|
|||
wl_list_insert(&backend->outputs, &output->link);
|
||||
wlr_output_update_enabled(wlr_output, true);
|
||||
|
||||
wlr_signal_emit_safe(&backend->backend.events.new_output, wlr_output);
|
||||
wl_signal_emit_mutable(&backend->backend.events.new_output, wlr_output);
|
||||
|
||||
struct wlr_wl_seat *seat;
|
||||
wl_list_for_each(seat, &backend->seats, link) {
|
||||
if (seat->pointer) {
|
||||
create_wl_pointer(seat, output);
|
||||
if (seat->wl_pointer) {
|
||||
create_pointer(seat, output);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
541
backend/wayland/pointer.c
Normal file
541
backend/wayland/pointer.c
Normal file
|
|
@ -0,0 +1,541 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <wayland-client.h>
|
||||
#include <wlr/interfaces/wlr_pointer.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
||||
#include "backend/wayland.h"
|
||||
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
#include "relative-pointer-unstable-v1-client-protocol.h"
|
||||
|
||||
static struct wlr_wl_pointer *output_get_pointer(struct wlr_wl_output *output,
|
||||
const struct wl_pointer *wl_pointer) {
|
||||
struct wlr_wl_seat *seat;
|
||||
wl_list_for_each(seat, &output->backend->seats, link) {
|
||||
if (seat->wl_pointer != wl_pointer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct wlr_wl_pointer *pointer;
|
||||
wl_list_for_each(pointer, &seat->pointers, link) {
|
||||
if (pointer->output == output) {
|
||||
return pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
|
||||
uint32_t serial, struct wl_surface *surface, wl_fixed_t sx,
|
||||
wl_fixed_t sy) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
if (surface == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_wl_output *output = wl_surface_get_user_data(surface);
|
||||
assert(output);
|
||||
|
||||
struct wlr_wl_pointer *pointer = output_get_pointer(output, wl_pointer);
|
||||
seat->active_pointer = pointer;
|
||||
|
||||
// Manage cursor icon/rendering on output
|
||||
struct wlr_wl_pointer *current = output->cursor.pointer;
|
||||
if (current && current != pointer) {
|
||||
wlr_log(WLR_INFO, "Ignoring seat '%s' pointer in favor of seat '%s'",
|
||||
seat->name, current->seat->name);
|
||||
return;
|
||||
}
|
||||
|
||||
output->enter_serial = serial;
|
||||
output->cursor.pointer = pointer;
|
||||
update_wl_output_cursor(output);
|
||||
}
|
||||
|
||||
static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
|
||||
uint32_t serial, struct wl_surface *surface) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
if (surface == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_wl_output *output = wl_surface_get_user_data(surface);
|
||||
assert(output);
|
||||
|
||||
if (seat->active_pointer != NULL &&
|
||||
seat->active_pointer->output == output) {
|
||||
seat->active_pointer = NULL;
|
||||
}
|
||||
|
||||
if (output->cursor.pointer == seat->active_pointer) {
|
||||
output->enter_serial = 0;
|
||||
output->cursor.pointer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
|
||||
uint32_t time, wl_fixed_t sx, wl_fixed_t sy) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_output *wlr_output = &pointer->output->wlr_output;
|
||||
struct wlr_pointer_motion_absolute_event event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.time_msec = time,
|
||||
.x = wl_fixed_to_double(sx) / wlr_output->width,
|
||||
.y = wl_fixed_to_double(sy) / wlr_output->height,
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.motion_absolute, &event);
|
||||
}
|
||||
|
||||
static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
|
||||
uint32_t serial, uint32_t time, uint32_t button, uint32_t state) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_pointer_button_event event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.button = button,
|
||||
.state = state,
|
||||
.time_msec = time,
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.button, &event);
|
||||
}
|
||||
|
||||
static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
|
||||
uint32_t time, uint32_t axis, wl_fixed_t value) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_pointer_axis_event event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.delta = wl_fixed_to_double(value),
|
||||
.delta_discrete = pointer->axis_discrete,
|
||||
.orientation = axis,
|
||||
.time_msec = time,
|
||||
.source = pointer->axis_source,
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.axis, &event);
|
||||
|
||||
pointer->axis_discrete = 0;
|
||||
}
|
||||
|
||||
static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.frame,
|
||||
&pointer->wlr_pointer);
|
||||
}
|
||||
|
||||
static void pointer_handle_axis_source(void *data,
|
||||
struct wl_pointer *wl_pointer, uint32_t axis_source) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pointer->axis_source = axis_source;
|
||||
}
|
||||
|
||||
static void pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer,
|
||||
uint32_t time, uint32_t axis) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_pointer_axis_event event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.delta = 0,
|
||||
.delta_discrete = 0,
|
||||
.orientation = axis,
|
||||
.time_msec = time,
|
||||
.source = pointer->axis_source,
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.axis, &event);
|
||||
}
|
||||
|
||||
static void pointer_handle_axis_discrete(void *data,
|
||||
struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pointer->axis_discrete = discrete * WLR_POINTER_AXIS_DISCRETE_STEP;
|
||||
}
|
||||
|
||||
static void pointer_handle_axis_value120(void *data,
|
||||
struct wl_pointer *wl_pointer, uint32_t axis, int32_t value120) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pointer->axis_discrete = value120;
|
||||
}
|
||||
|
||||
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,
|
||||
.frame = pointer_handle_frame,
|
||||
.axis_source = pointer_handle_axis_source,
|
||||
.axis_stop = pointer_handle_axis_stop,
|
||||
.axis_discrete = pointer_handle_axis_discrete,
|
||||
.axis_value120 = pointer_handle_axis_value120,
|
||||
};
|
||||
|
||||
static void gesture_swipe_begin(void *data,
|
||||
struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1,
|
||||
uint32_t serial, uint32_t time, struct wl_surface *surface,
|
||||
uint32_t fingers) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pointer->fingers = fingers;
|
||||
|
||||
struct wlr_pointer_swipe_begin_event wlr_event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.time_msec = time,
|
||||
.fingers = fingers,
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.swipe_begin, &wlr_event);
|
||||
}
|
||||
|
||||
static void gesture_swipe_update(void *data,
|
||||
struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1,
|
||||
uint32_t time, wl_fixed_t dx, wl_fixed_t dy) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_pointer_swipe_update_event wlr_event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.time_msec = time,
|
||||
.fingers = pointer->fingers,
|
||||
.dx = wl_fixed_to_double(dx),
|
||||
.dy = wl_fixed_to_double(dy),
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.swipe_update, &wlr_event);
|
||||
}
|
||||
|
||||
static void gesture_swipe_end(void *data,
|
||||
struct zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1,
|
||||
uint32_t serial, uint32_t time, int32_t cancelled) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_pointer_swipe_end_event wlr_event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.time_msec = time,
|
||||
.cancelled = cancelled,
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.swipe_end, &wlr_event);
|
||||
}
|
||||
|
||||
static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_impl = {
|
||||
.begin = gesture_swipe_begin,
|
||||
.update = gesture_swipe_update,
|
||||
.end = gesture_swipe_end,
|
||||
};
|
||||
|
||||
static void gesture_pinch_begin(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1,
|
||||
uint32_t serial, uint32_t time, struct wl_surface *surface,
|
||||
uint32_t fingers) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pointer->fingers = fingers;
|
||||
|
||||
struct wlr_pointer_pinch_begin_event wlr_event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.time_msec = time,
|
||||
.fingers = pointer->fingers,
|
||||
};
|
||||
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.pinch_begin, &wlr_event);
|
||||
}
|
||||
|
||||
static void gesture_pinch_update(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1,
|
||||
uint32_t time, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t scale,
|
||||
wl_fixed_t rotation) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_pointer_pinch_update_event wlr_event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.time_msec = time,
|
||||
.fingers = pointer->fingers,
|
||||
.dx = wl_fixed_to_double(dx),
|
||||
.dy = wl_fixed_to_double(dy),
|
||||
.scale = wl_fixed_to_double(scale),
|
||||
.rotation = wl_fixed_to_double(rotation),
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.pinch_update, &wlr_event);
|
||||
}
|
||||
|
||||
static void gesture_pinch_end(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1,
|
||||
uint32_t serial, uint32_t time, int32_t cancelled) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_pointer_pinch_end_event wlr_event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.time_msec = time,
|
||||
.cancelled = cancelled,
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.pinch_end, &wlr_event);
|
||||
}
|
||||
|
||||
static const struct zwp_pointer_gesture_pinch_v1_listener gesture_pinch_impl = {
|
||||
.begin = gesture_pinch_begin,
|
||||
.update = gesture_pinch_update,
|
||||
.end = gesture_pinch_end,
|
||||
};
|
||||
|
||||
static void gesture_hold_begin(void *data,
|
||||
struct zwp_pointer_gesture_hold_v1 *zwp_pointer_gesture_hold_v1,
|
||||
uint32_t serial, uint32_t time, struct wl_surface *surface,
|
||||
uint32_t fingers) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pointer->fingers = fingers;
|
||||
|
||||
struct wlr_pointer_hold_begin_event wlr_event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.time_msec = time,
|
||||
.fingers = fingers,
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.hold_begin, &wlr_event);
|
||||
}
|
||||
|
||||
static void gesture_hold_end(void *data,
|
||||
struct zwp_pointer_gesture_hold_v1 *zwp_pointer_gesture_hold_v1,
|
||||
uint32_t serial, uint32_t time, int32_t cancelled) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_pointer_hold_end_event wlr_event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.time_msec = time,
|
||||
.cancelled = cancelled,
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.hold_end, &wlr_event);
|
||||
}
|
||||
|
||||
static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_impl = {
|
||||
.begin = gesture_hold_begin,
|
||||
.end = gesture_hold_end,
|
||||
};
|
||||
|
||||
static void relative_pointer_handle_relative_motion(void *data,
|
||||
struct zwp_relative_pointer_v1 *relative_pointer, uint32_t utime_hi,
|
||||
uint32_t utime_lo, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_unaccel,
|
||||
wl_fixed_t dy_unaccel) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_pointer *pointer = seat->active_pointer;
|
||||
if (pointer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t time_usec = (uint64_t)utime_hi << 32 | utime_lo;
|
||||
|
||||
struct wlr_pointer_motion_event wlr_event = {
|
||||
.pointer = &pointer->wlr_pointer,
|
||||
.time_msec = (uint32_t)(time_usec / 1000),
|
||||
.delta_x = wl_fixed_to_double(dx),
|
||||
.delta_y = wl_fixed_to_double(dy),
|
||||
.unaccel_dx = wl_fixed_to_double(dx_unaccel),
|
||||
.unaccel_dy = wl_fixed_to_double(dy_unaccel),
|
||||
};
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.motion, &wlr_event);
|
||||
}
|
||||
|
||||
static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
|
||||
.relative_motion = relative_pointer_handle_relative_motion,
|
||||
};
|
||||
|
||||
const struct wlr_pointer_impl wl_pointer_impl = {
|
||||
.name = "wl-pointer",
|
||||
};
|
||||
|
||||
static void destroy_pointer(struct wlr_wl_pointer *pointer) {
|
||||
if (pointer->output->cursor.pointer == pointer) {
|
||||
pointer->output->cursor.pointer = NULL;
|
||||
}
|
||||
if (pointer->seat->active_pointer == pointer) {
|
||||
pointer->seat->active_pointer = NULL;
|
||||
}
|
||||
|
||||
wlr_pointer_finish(&pointer->wlr_pointer);
|
||||
wl_list_remove(&pointer->output_destroy.link);
|
||||
wl_list_remove(&pointer->link);
|
||||
free(pointer);
|
||||
}
|
||||
|
||||
static void pointer_output_destroy(struct wl_listener *listener, void *data) {
|
||||
struct wlr_wl_pointer *pointer =
|
||||
wl_container_of(listener, pointer, output_destroy);
|
||||
destroy_pointer(pointer);
|
||||
}
|
||||
|
||||
void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) {
|
||||
assert(seat->wl_pointer);
|
||||
|
||||
if (output_get_pointer(output, seat->wl_pointer)) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"pointer for output '%s' from seat '%s' already exists",
|
||||
output->wlr_output.name, seat->name);
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_log(WLR_DEBUG, "creating pointer for output '%s' from seat '%s'",
|
||||
output->wlr_output.name, seat->name);
|
||||
|
||||
struct wlr_wl_pointer *pointer = calloc(1, sizeof(struct wlr_wl_pointer));
|
||||
if (pointer == NULL) {
|
||||
wlr_log(WLR_ERROR, "failed to allocate wlr_wl_pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
char name[64] = {0};
|
||||
snprintf(name, sizeof(name), "wayland-pointer-%s", seat->name);
|
||||
wlr_pointer_init(&pointer->wlr_pointer, &wl_pointer_impl, name);
|
||||
|
||||
pointer->wlr_pointer.output_name = strdup(output->wlr_output.name);
|
||||
|
||||
pointer->seat = seat;
|
||||
pointer->output = output;
|
||||
|
||||
wl_signal_add(&output->wlr_output.events.destroy, &pointer->output_destroy);
|
||||
pointer->output_destroy.notify = pointer_output_destroy;
|
||||
|
||||
wl_signal_emit_mutable(&seat->backend->backend.events.new_input,
|
||||
&pointer->wlr_pointer.base);
|
||||
|
||||
wl_list_insert(&seat->pointers, &pointer->link);
|
||||
}
|
||||
|
||||
void init_seat_pointer(struct wlr_wl_seat *seat) {
|
||||
assert(seat->wl_pointer);
|
||||
|
||||
struct wlr_wl_backend *backend = seat->backend;
|
||||
|
||||
wl_list_init(&seat->pointers);
|
||||
|
||||
struct wlr_wl_output *output;
|
||||
wl_list_for_each(output, &backend->outputs, link) {
|
||||
create_pointer(seat, output);
|
||||
}
|
||||
|
||||
if (backend->zwp_pointer_gestures_v1) {
|
||||
uint32_t version = zwp_pointer_gestures_v1_get_version(
|
||||
backend->zwp_pointer_gestures_v1);
|
||||
|
||||
seat->gesture_swipe = zwp_pointer_gestures_v1_get_swipe_gesture(
|
||||
backend->zwp_pointer_gestures_v1, seat->wl_pointer);
|
||||
zwp_pointer_gesture_swipe_v1_add_listener(seat->gesture_swipe,
|
||||
&gesture_swipe_impl, seat);
|
||||
|
||||
seat->gesture_pinch = zwp_pointer_gestures_v1_get_pinch_gesture(
|
||||
backend->zwp_pointer_gestures_v1, seat->wl_pointer);
|
||||
zwp_pointer_gesture_pinch_v1_add_listener(seat->gesture_pinch,
|
||||
&gesture_pinch_impl, seat);
|
||||
|
||||
if (version >= ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE) {
|
||||
seat->gesture_hold = zwp_pointer_gestures_v1_get_hold_gesture(
|
||||
backend->zwp_pointer_gestures_v1, seat->wl_pointer);
|
||||
zwp_pointer_gesture_hold_v1_add_listener(seat->gesture_hold,
|
||||
&gesture_hold_impl, seat);
|
||||
}
|
||||
}
|
||||
|
||||
if (backend->zwp_relative_pointer_manager_v1) {
|
||||
seat->relative_pointer =
|
||||
zwp_relative_pointer_manager_v1_get_relative_pointer(
|
||||
backend->zwp_relative_pointer_manager_v1, seat->wl_pointer);
|
||||
zwp_relative_pointer_v1_add_listener(seat->relative_pointer,
|
||||
&relative_pointer_listener, seat);
|
||||
}
|
||||
|
||||
wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat);
|
||||
}
|
||||
|
||||
void finish_seat_pointer(struct wlr_wl_seat *seat) {
|
||||
assert(seat->wl_pointer);
|
||||
|
||||
wl_pointer_release(seat->wl_pointer);
|
||||
|
||||
struct wlr_wl_pointer *pointer, *tmp;
|
||||
wl_list_for_each_safe(pointer, tmp, &seat->pointers, link) {
|
||||
destroy_pointer(pointer);
|
||||
}
|
||||
|
||||
if (seat->gesture_swipe != NULL) {
|
||||
zwp_pointer_gesture_swipe_v1_destroy(seat->gesture_swipe);
|
||||
}
|
||||
if (seat->gesture_pinch != NULL) {
|
||||
zwp_pointer_gesture_pinch_v1_destroy(seat->gesture_pinch);
|
||||
}
|
||||
if (seat->gesture_hold != NULL) {
|
||||
zwp_pointer_gesture_hold_v1_destroy(seat->gesture_hold);
|
||||
}
|
||||
if (seat->relative_pointer != NULL) {
|
||||
zwp_relative_pointer_v1_destroy(seat->relative_pointer);
|
||||
}
|
||||
|
||||
seat->wl_pointer = NULL;
|
||||
seat->active_pointer = NULL;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,35 +1,24 @@
|
|||
#ifndef _POSIX_C_SOURCE
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#endif
|
||||
|
||||
#include <wayland-util.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wlr/interfaces/wlr_tablet_pad.h>
|
||||
#include <wlr/interfaces/wlr_tablet_tool.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
|
||||
#include "util/signal.h"
|
||||
#include "util/time.h"
|
||||
#include "wlr/util/log.h"
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
#include <wlr/util/log.h>
|
||||
|
||||
#include "backend/wayland.h"
|
||||
#include "util/time.h"
|
||||
|
||||
struct wlr_wl_tablet_seat {
|
||||
struct zwp_tablet_seat_v2 *tablet_seat;
|
||||
};
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
|
||||
struct wlr_wl_tablet_tool {
|
||||
struct tablet_tool {
|
||||
/* static */
|
||||
struct zwp_tablet_tool_v2 *tool;
|
||||
struct wlr_tablet_tool wlr_tool;
|
||||
struct wlr_wl_seat *seat;
|
||||
|
||||
/* semi-static */
|
||||
struct wlr_wl_output *output;
|
||||
struct wlr_wl_input_device *tablet;
|
||||
double pre_x, pre_y;
|
||||
|
||||
/* per frame */
|
||||
|
|
@ -49,11 +38,11 @@ struct wlr_wl_tablet_tool {
|
|||
bool is_down;
|
||||
};
|
||||
|
||||
struct wlr_wl_tablet_pad_ring {
|
||||
struct wl_list link; // wlr_wl_tablet_pad_group::rings
|
||||
struct tablet_pad_ring {
|
||||
struct wl_list link; // tablet_pad_group::rings
|
||||
/* static */
|
||||
struct zwp_tablet_pad_ring_v2 *ring;
|
||||
struct wlr_wl_tablet_pad_group *group;
|
||||
struct tablet_pad_group *group;
|
||||
size_t index;
|
||||
|
||||
/* per frame */
|
||||
|
|
@ -62,10 +51,10 @@ struct wlr_wl_tablet_pad_ring {
|
|||
bool stopped;
|
||||
};
|
||||
|
||||
struct wlr_wl_tablet_pad_strip {
|
||||
struct wl_list link; // wlr_wl_tablet_pad_group::strips
|
||||
struct tablet_pad_strip {
|
||||
struct wl_list link; // tablet_pad_group::strips
|
||||
struct zwp_tablet_pad_strip_v2 *strip;
|
||||
struct wlr_wl_tablet_pad_group *group;
|
||||
struct tablet_pad_group *group;
|
||||
size_t index;
|
||||
|
||||
enum wlr_tablet_pad_strip_source source;
|
||||
|
|
@ -73,43 +62,43 @@ struct wlr_wl_tablet_pad_strip {
|
|||
bool stopped;
|
||||
};
|
||||
|
||||
struct wlr_wl_tablet_pad_group {
|
||||
struct tablet_pad_group {
|
||||
struct zwp_tablet_pad_group_v2 *pad_group;
|
||||
struct wlr_tablet_pad *pad;
|
||||
unsigned int mode;
|
||||
|
||||
struct wlr_tablet_pad_group group;
|
||||
|
||||
struct wl_list rings; // wlr_wl_tablet_pad_ring::link
|
||||
struct wl_list strips; // wlr_wl_tablet_pad_strips::link
|
||||
struct wl_list rings; // tablet_pad_ring::link
|
||||
struct wl_list strips; // tablet_pad_strips::link
|
||||
};
|
||||
|
||||
static void handle_tablet_pad_ring_source(void *data,
|
||||
struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
|
||||
uint32_t source) {
|
||||
struct wlr_wl_tablet_pad_ring *ring = data;
|
||||
struct tablet_pad_ring *ring = data;
|
||||
ring->source = source;
|
||||
}
|
||||
|
||||
static void handle_tablet_pad_ring_angle(void *data,
|
||||
struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
|
||||
wl_fixed_t degrees) {
|
||||
struct wlr_wl_tablet_pad_ring *ring = data;
|
||||
struct tablet_pad_ring *ring = data;
|
||||
ring->angle = wl_fixed_to_double(degrees);
|
||||
}
|
||||
|
||||
static void handle_tablet_pad_ring_stop(void *data,
|
||||
struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2) {
|
||||
struct wlr_wl_tablet_pad_ring *ring = data;
|
||||
struct tablet_pad_ring *ring = data;
|
||||
ring->stopped = true;
|
||||
}
|
||||
|
||||
static void handle_tablet_pad_ring_frame(void *data,
|
||||
struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
|
||||
uint32_t time) {
|
||||
struct wlr_wl_tablet_pad_ring *ring = data;
|
||||
struct tablet_pad_ring *ring = data;
|
||||
|
||||
struct wlr_event_tablet_pad_ring evt = {
|
||||
struct wlr_tablet_pad_ring_event evt = {
|
||||
.time_msec = time,
|
||||
.source = ring->source,
|
||||
.ring = ring->index,
|
||||
|
|
@ -118,11 +107,11 @@ static void handle_tablet_pad_ring_frame(void *data,
|
|||
};
|
||||
|
||||
if (ring->angle >= 0) {
|
||||
wlr_signal_emit_safe(&ring->group->pad->events.ring, &evt);
|
||||
wl_signal_emit_mutable(&ring->group->pad->events.ring, &evt);
|
||||
}
|
||||
if (ring->stopped) {
|
||||
evt.position = -1;
|
||||
wlr_signal_emit_safe(&ring->group->pad->events.ring, &evt);
|
||||
wl_signal_emit_mutable(&ring->group->pad->events.ring, &evt);
|
||||
}
|
||||
|
||||
ring->angle = -1;
|
||||
|
|
@ -140,29 +129,29 @@ static const struct zwp_tablet_pad_ring_v2_listener tablet_pad_ring_listener = {
|
|||
static void handle_tablet_pad_strip_source(void *data,
|
||||
struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
|
||||
uint32_t source) {
|
||||
struct wlr_wl_tablet_pad_strip *strip = data;
|
||||
struct tablet_pad_strip *strip = data;
|
||||
strip->source = source;
|
||||
}
|
||||
|
||||
static void handle_tablet_pad_strip_position(void *data,
|
||||
struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
|
||||
uint32_t position) {
|
||||
struct wlr_wl_tablet_pad_strip *strip = data;
|
||||
struct tablet_pad_strip *strip = data;
|
||||
strip->position = (double) position / 65536.0;
|
||||
}
|
||||
|
||||
static void handle_tablet_pad_strip_stop(void *data,
|
||||
struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2) {
|
||||
struct wlr_wl_tablet_pad_strip *strip = data;
|
||||
struct tablet_pad_strip *strip = data;
|
||||
strip->stopped = true;
|
||||
}
|
||||
|
||||
static void handle_tablet_pad_strip_frame(void *data,
|
||||
struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
|
||||
uint32_t time) {
|
||||
struct wlr_wl_tablet_pad_strip *strip = data;
|
||||
struct tablet_pad_strip *strip = data;
|
||||
|
||||
struct wlr_event_tablet_pad_strip evt = {
|
||||
struct wlr_tablet_pad_strip_event evt = {
|
||||
.time_msec = time,
|
||||
.source = strip->source,
|
||||
.strip = strip->index,
|
||||
|
|
@ -171,11 +160,11 @@ static void handle_tablet_pad_strip_frame(void *data,
|
|||
};
|
||||
|
||||
if (strip->position >= 0) {
|
||||
wlr_signal_emit_safe(&strip->group->pad->events.strip, &evt);
|
||||
wl_signal_emit_mutable(&strip->group->pad->events.strip, &evt);
|
||||
}
|
||||
if (strip->stopped) {
|
||||
evt.position = -1;
|
||||
wlr_signal_emit_safe(&strip->group->pad->events.strip, &evt);
|
||||
wl_signal_emit_mutable(&strip->group->pad->events.strip, &evt);
|
||||
}
|
||||
|
||||
strip->position = -1;
|
||||
|
|
@ -193,7 +182,7 @@ static const struct zwp_tablet_pad_strip_v2_listener tablet_pad_strip_listener =
|
|||
static void handle_tablet_pad_group_buttons(void *data,
|
||||
struct zwp_tablet_pad_group_v2 *pad_group,
|
||||
struct wl_array *buttons) {
|
||||
struct wlr_wl_tablet_pad_group *group = data;
|
||||
struct tablet_pad_group *group = data;
|
||||
|
||||
free(group->group.buttons);
|
||||
group->group.buttons = calloc(1, buttons->size);
|
||||
|
|
@ -208,7 +197,7 @@ static void handle_tablet_pad_group_buttons(void *data,
|
|||
|
||||
static void handle_tablet_pad_group_modes(void *data,
|
||||
struct zwp_tablet_pad_group_v2 *pad_group, uint32_t modes) {
|
||||
struct wlr_wl_tablet_pad_group *group = data;
|
||||
struct tablet_pad_group *group = data;
|
||||
|
||||
group->group.mode_count = modes;
|
||||
}
|
||||
|
|
@ -216,9 +205,9 @@ static void handle_tablet_pad_group_modes(void *data,
|
|||
static void handle_tablet_pad_group_ring(void *data,
|
||||
struct zwp_tablet_pad_group_v2 *pad_group,
|
||||
struct zwp_tablet_pad_ring_v2 *ring) {
|
||||
struct wlr_wl_tablet_pad_group *group = data;
|
||||
struct wlr_wl_tablet_pad_ring *tablet_ring =
|
||||
calloc(1, sizeof(struct wlr_wl_tablet_pad_ring));
|
||||
struct tablet_pad_group *group = data;
|
||||
struct tablet_pad_ring *tablet_ring =
|
||||
calloc(1, sizeof(struct tablet_pad_ring));
|
||||
if (!tablet_ring) {
|
||||
zwp_tablet_pad_ring_v2_destroy(ring);
|
||||
return;
|
||||
|
|
@ -237,9 +226,9 @@ static void handle_tablet_pad_group_ring(void *data,
|
|||
static void handle_tablet_pad_group_strip(void *data,
|
||||
struct zwp_tablet_pad_group_v2 *pad_group,
|
||||
struct zwp_tablet_pad_strip_v2 *strip) {
|
||||
struct wlr_wl_tablet_pad_group *group = data;
|
||||
struct wlr_wl_tablet_pad_strip *tablet_strip =
|
||||
calloc(1, sizeof(struct wlr_wl_tablet_pad_strip));
|
||||
struct tablet_pad_group *group = data;
|
||||
struct tablet_pad_strip *tablet_strip =
|
||||
calloc(1, sizeof(struct tablet_pad_strip));
|
||||
if (!tablet_strip) {
|
||||
zwp_tablet_pad_strip_v2_destroy(strip);
|
||||
return;
|
||||
|
|
@ -263,25 +252,20 @@ static void handle_tablet_pad_group_done(void *data,
|
|||
static void handle_tablet_pad_group_mode_switch(void *data,
|
||||
struct zwp_tablet_pad_group_v2 *pad_group,
|
||||
uint32_t time, uint32_t serial, uint32_t mode) {
|
||||
struct wlr_wl_tablet_pad_group *group = data;
|
||||
struct tablet_pad_group *group = data;
|
||||
group->mode = mode;
|
||||
}
|
||||
|
||||
/* This isn't in the listener, but keep the naming scheme around since the
|
||||
* other removed functions work like this, and pad sub-resources are just a bit
|
||||
* special */
|
||||
static void handle_tablet_pad_group_removed(
|
||||
struct wlr_wl_tablet_pad_group *group) {
|
||||
|
||||
static void destroy_tablet_pad_group(struct tablet_pad_group *group) {
|
||||
/* No need to remove the ::link on strips rings as long as we do *not*
|
||||
* wl_list_remove on the wl_groups ring/strip attributes here */
|
||||
struct wlr_wl_tablet_pad_ring *ring, *tmp_ring;
|
||||
struct tablet_pad_ring *ring, *tmp_ring;
|
||||
wl_list_for_each_safe(ring, tmp_ring, &group->rings, link) {
|
||||
zwp_tablet_pad_ring_v2_destroy(ring->ring);
|
||||
free(ring);
|
||||
}
|
||||
|
||||
struct wlr_wl_tablet_pad_strip *strip, *tmp_strip;
|
||||
struct tablet_pad_strip *strip, *tmp_strip;
|
||||
wl_list_for_each_safe(strip, tmp_strip, &group->strips, link) {
|
||||
zwp_tablet_pad_strip_v2_destroy(strip->strip);
|
||||
free(strip);
|
||||
|
|
@ -289,10 +273,11 @@ static void handle_tablet_pad_group_removed(
|
|||
|
||||
zwp_tablet_pad_group_v2_destroy(group->pad_group);
|
||||
|
||||
/* While I'm pretty sure we have control over this as well, it's
|
||||
* outside the scope of a single function, so better be safe than
|
||||
* sorry */
|
||||
free(group->group.buttons);
|
||||
free(group->group.strips);
|
||||
free(group->group.rings);
|
||||
wl_list_remove(&group->group.link);
|
||||
|
||||
free(group);
|
||||
}
|
||||
|
||||
|
|
@ -308,12 +293,13 @@ static const struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener =
|
|||
static void handle_tablet_pad_group(void *data,
|
||||
struct zwp_tablet_pad_v2 *zwp_tablet_pad,
|
||||
struct zwp_tablet_pad_group_v2 *pad_group) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
struct wlr_tablet_pad *pad = dev->wlr_input_device.tablet_pad;
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_tablet_pad *pad = &seat->wlr_tablet_pad;
|
||||
|
||||
struct wlr_wl_tablet_pad_group *group =
|
||||
calloc(1, sizeof(struct wlr_wl_tablet_pad_group));
|
||||
struct tablet_pad_group *group =
|
||||
calloc(1, sizeof(struct tablet_pad_group));
|
||||
if (!group) {
|
||||
wlr_log_errno(WLR_ERROR, "failed to allocate tablet_pad_group");
|
||||
zwp_tablet_pad_group_v2_destroy(pad_group);
|
||||
return;
|
||||
}
|
||||
|
|
@ -330,20 +316,18 @@ static void handle_tablet_pad_group(void *data,
|
|||
}
|
||||
|
||||
static void handle_tablet_pad_path(void *data,
|
||||
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
|
||||
const char *path) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad;
|
||||
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, const char *path) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad;
|
||||
|
||||
char **dst = wl_array_add(&tablet_pad->paths, sizeof(char *));
|
||||
*dst = strdup(path);
|
||||
}
|
||||
|
||||
static void handle_tablet_pad_buttons(void *data,
|
||||
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
|
||||
uint32_t buttons) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad;
|
||||
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t buttons) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad;
|
||||
|
||||
tablet_pad->button_count = buttons;
|
||||
}
|
||||
|
|
@ -351,10 +335,8 @@ static void handle_tablet_pad_buttons(void *data,
|
|||
static void handle_tablet_pad_button(void *data,
|
||||
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
|
||||
uint32_t time, uint32_t button, uint32_t state) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad;
|
||||
|
||||
struct wlr_event_tablet_pad_button evt = {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_tablet_pad_button_event evt = {
|
||||
.time_msec = time,
|
||||
.button = button,
|
||||
.state = state,
|
||||
|
|
@ -362,28 +344,25 @@ static void handle_tablet_pad_button(void *data,
|
|||
.group = 0,
|
||||
};
|
||||
|
||||
wlr_signal_emit_safe(&tablet_pad->events.button, &evt);
|
||||
wl_signal_emit_mutable(&seat->wlr_tablet_pad.events.button, &evt);
|
||||
}
|
||||
|
||||
static void handle_tablet_pad_done(void *data,
|
||||
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
|
||||
wlr_signal_emit_safe(&dev->backend->backend.events.new_input,
|
||||
&dev->wlr_input_device);
|
||||
struct wlr_wl_seat *seat = data;
|
||||
wl_signal_emit_mutable(&seat->backend->backend.events.new_input,
|
||||
&seat->wlr_tablet_pad.base);
|
||||
}
|
||||
|
||||
static void handle_tablet_pad_enter(void *data,
|
||||
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
|
||||
uint32_t serial, struct zwp_tablet_v2 *tablet_p,
|
||||
struct wl_surface *surface) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad;
|
||||
struct wlr_wl_input_device *tab_dev = zwp_tablet_v2_get_user_data(tablet_p);
|
||||
struct wlr_input_device *tablet = &tab_dev->wlr_input_device;
|
||||
wlr_log(WLR_DEBUG, "Tablet: %p\n", tablet);
|
||||
struct wlr_wl_seat *seat = data;
|
||||
assert(seat->zwp_tablet_v2 == tablet_p);
|
||||
|
||||
wlr_signal_emit_safe(&tablet_pad->events.attach_tablet, tablet);
|
||||
wl_signal_emit_mutable(&seat->wlr_tablet_pad.events.attach_tablet,
|
||||
&seat->wlr_tablet_tool);
|
||||
}
|
||||
|
||||
static void handle_tablet_pad_leave(void *data,
|
||||
|
|
@ -395,23 +374,17 @@ static void handle_tablet_pad_leave(void *data,
|
|||
|
||||
static void handle_tablet_pad_removed(void *data,
|
||||
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad;
|
||||
struct wlr_wl_seat *seat = data;
|
||||
|
||||
/* This doesn't free anything, but emits the destroy signal */
|
||||
wlr_input_device_destroy(&dev->wlr_input_device);
|
||||
/* This is a bit ugly, but we need to remove it from our list */
|
||||
wl_list_remove(&dev->link);
|
||||
|
||||
struct wlr_wl_tablet_pad_group *group, *it;
|
||||
struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad;
|
||||
struct tablet_pad_group *group, *it;
|
||||
wl_list_for_each_safe(group, it, &tablet_pad->groups, group.link) {
|
||||
handle_tablet_pad_group_removed(group);
|
||||
destroy_tablet_pad_group(group);
|
||||
}
|
||||
|
||||
/* This frees */
|
||||
wlr_tablet_pad_destroy(tablet_pad);
|
||||
zwp_tablet_pad_v2_destroy(dev->resource);
|
||||
free(dev);
|
||||
wlr_tablet_pad_finish(tablet_pad);
|
||||
zwp_tablet_pad_v2_destroy(seat->zwp_tablet_pad_v2);
|
||||
seat->zwp_tablet_pad_v2 = NULL;
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = {
|
||||
|
|
@ -425,37 +398,25 @@ static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = {
|
|||
.removed = handle_tablet_pad_removed,
|
||||
};
|
||||
|
||||
const struct wlr_tablet_pad_impl tablet_pad_impl = {0};
|
||||
const struct wlr_tablet_pad_impl wl_tablet_pad_impl = {
|
||||
.name = "wl-tablet-pad",
|
||||
};
|
||||
|
||||
static void handle_pad_added(void *data,
|
||||
struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2,
|
||||
struct zwp_tablet_pad_v2 *id) {
|
||||
wlr_log(WLR_DEBUG, "New tablet pad");
|
||||
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_input_device *dev = create_wl_input_device(
|
||||
seat, WLR_INPUT_DEVICE_TABLET_PAD);
|
||||
if (!dev) {
|
||||
/* This leaks a couple of server-sent resource ids. iirc this
|
||||
* shouldn't ever be a problem, but it isn't exactly nice
|
||||
* either. */
|
||||
zwp_tablet_pad_v2_destroy(id);
|
||||
if (seat->zwp_tablet_pad_v2 != NULL) {
|
||||
wlr_log(WLR_ERROR, "zwp_tablet_pad_v2 is already present");
|
||||
return;
|
||||
}
|
||||
|
||||
dev->resource = id;
|
||||
struct wlr_input_device *wlr_dev = &dev->wlr_input_device;
|
||||
wlr_dev->tablet_pad = calloc(1, sizeof(*wlr_dev->tablet_pad));
|
||||
seat->zwp_tablet_pad_v2 = zwp_tablet_pad_v2;
|
||||
zwp_tablet_pad_v2_add_listener(zwp_tablet_pad_v2, &tablet_pad_listener,
|
||||
seat);
|
||||
|
||||
if (!wlr_dev->tablet_pad) {
|
||||
/* This leaks a couple of server-sent resource ids. iirc this
|
||||
* shouldn't ever be a problem, but it isn't exactly nice
|
||||
* either. */
|
||||
free(dev);
|
||||
zwp_tablet_pad_v2_destroy(id);
|
||||
return;
|
||||
}
|
||||
wlr_tablet_pad_init(wlr_dev->tablet_pad, &tablet_pad_impl, wlr_dev->name);
|
||||
zwp_tablet_pad_v2_add_listener(id, &tablet_pad_listener, dev);
|
||||
wlr_tablet_pad_init(&seat->wlr_tablet_pad, &wl_tablet_pad_impl,
|
||||
"wlr_tablet_v2");
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_done(void *data,
|
||||
|
|
@ -463,7 +424,8 @@ static void handle_tablet_tool_done(void *data,
|
|||
/* empty */
|
||||
}
|
||||
|
||||
static enum wlr_tablet_tool_type tablet_type_to_wlr_type(enum zwp_tablet_tool_v2_type type) {
|
||||
static enum wlr_tablet_tool_type tablet_type_to_wlr_type(
|
||||
enum zwp_tablet_tool_v2_type type) {
|
||||
switch (type) {
|
||||
case ZWP_TABLET_TOOL_V2_TYPE_PEN:
|
||||
return WLR_TABLET_TOOL_TYPE_PEN;
|
||||
|
|
@ -488,94 +450,85 @@ static enum wlr_tablet_tool_type tablet_type_to_wlr_type(enum zwp_tablet_tool_v2
|
|||
}
|
||||
|
||||
static void handle_tablet_tool_type(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
uint32_t tool_type) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
|
||||
tool->wlr_tool.type = tablet_type_to_wlr_type(tool_type);
|
||||
struct zwp_tablet_tool_v2 *id, uint32_t tool_type) {
|
||||
struct tablet_tool *tool = data;
|
||||
struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool;
|
||||
wlr_tool->type = tablet_type_to_wlr_type(tool_type);
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_serial(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
uint32_t high, uint32_t low) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
|
||||
tool->wlr_tool.hardware_serial =
|
||||
((uint64_t) high) << 32 | (uint64_t) low;
|
||||
struct zwp_tablet_tool_v2 *id, uint32_t high, uint32_t low) {
|
||||
struct tablet_tool *tool = data;
|
||||
struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool;
|
||||
wlr_tool->hardware_serial = ((uint64_t) high) << 32 | (uint64_t) low;
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_id_wacom(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
uint32_t high, uint32_t low) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
|
||||
tool->wlr_tool.hardware_wacom =
|
||||
((uint64_t) high) << 32 | (uint64_t) low;
|
||||
struct zwp_tablet_tool_v2 *id, uint32_t high, uint32_t low) {
|
||||
struct tablet_tool *tool = data;
|
||||
struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool;
|
||||
wlr_tool->hardware_wacom = ((uint64_t) high) << 32 | (uint64_t) low;
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_capability(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
uint32_t capability) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct zwp_tablet_tool_v2 *id, uint32_t capability) {
|
||||
struct tablet_tool *tool = data;
|
||||
struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool;
|
||||
|
||||
enum zwp_tablet_tool_v2_capability cap = capability;
|
||||
|
||||
switch (cap) {
|
||||
/* One event is sent for each capability */
|
||||
switch (capability) {
|
||||
case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT:
|
||||
tool->wlr_tool.tilt = true;
|
||||
wlr_tool->tilt = true;
|
||||
break;
|
||||
case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE:
|
||||
tool->wlr_tool.pressure = true;
|
||||
wlr_tool->pressure = true;
|
||||
break;
|
||||
case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE:
|
||||
tool->wlr_tool.distance = true;
|
||||
wlr_tool->distance = true;
|
||||
break;
|
||||
case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION:
|
||||
tool->wlr_tool.rotation = true;
|
||||
wlr_tool->rotation = true;
|
||||
break;
|
||||
case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER:
|
||||
tool->wlr_tool.slider = true;
|
||||
wlr_tool->slider = true;
|
||||
break;
|
||||
case ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL:
|
||||
tool->wlr_tool.wheel = true;
|
||||
wlr_tool->wheel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_proximity_in(void *data,
|
||||
struct zwp_tablet_tool_v2 *id, uint32_t serial,
|
||||
struct zwp_tablet_v2 *tablet_id,
|
||||
struct wl_surface *surface) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct zwp_tablet_v2 *tablet_id, struct wl_surface *surface) {
|
||||
struct tablet_tool *tool = data;
|
||||
assert(tablet_id == tool->seat->zwp_tablet_v2);
|
||||
|
||||
tool->is_in = true;
|
||||
tool->tablet = zwp_tablet_v2_get_user_data(tablet_id);
|
||||
tool->output = wl_surface_get_user_data(surface);
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_proximity_out(void *data,
|
||||
struct zwp_tablet_tool_v2 *id) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct tablet_tool *tool = data;
|
||||
tool->is_out = true;
|
||||
tool->output = NULL;
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_down(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
static void handle_tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *id,
|
||||
unsigned int serial) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct tablet_tool *tool = data;
|
||||
tool->is_down = true;
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_up(void *data,
|
||||
struct zwp_tablet_tool_v2 *id) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
static void handle_tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *id) {
|
||||
struct tablet_tool *tool = data;
|
||||
tool->is_up = true;
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_motion(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
static void handle_tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *id,
|
||||
wl_fixed_t x, wl_fixed_t y) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct tablet_tool *tool = data;
|
||||
struct wlr_wl_output *output = tool->output;
|
||||
assert(output);
|
||||
|
||||
|
|
@ -584,68 +537,63 @@ static void handle_tablet_tool_motion(void *data,
|
|||
}
|
||||
|
||||
static void handle_tablet_tool_pressure(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
uint32_t pressure) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct zwp_tablet_tool_v2 *id, uint32_t pressure) {
|
||||
struct tablet_tool *tool = data;
|
||||
tool->pressure = (double) pressure / 65535.0;
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_distance(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
uint32_t distance) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct zwp_tablet_tool_v2 *id, uint32_t distance) {
|
||||
struct tablet_tool *tool = data;
|
||||
tool->distance = (double) distance / 65535.0;
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_tilt(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
static void handle_tablet_tool_tilt(void *data, struct zwp_tablet_tool_v2 *id,
|
||||
wl_fixed_t x, wl_fixed_t y) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct tablet_tool *tool = data;
|
||||
tool->tilt_x = wl_fixed_to_double(x);
|
||||
tool->tilt_y = wl_fixed_to_double(y);
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_rotation(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
wl_fixed_t rotation) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct zwp_tablet_tool_v2 *id, wl_fixed_t rotation) {
|
||||
struct tablet_tool *tool = data;
|
||||
tool->rotation = wl_fixed_to_double(rotation);
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_slider(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
static void handle_tablet_tool_slider(void *data, struct zwp_tablet_tool_v2 *id,
|
||||
int slider) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct tablet_tool *tool = data;
|
||||
tool->slider = (double) slider / 65535.0;;
|
||||
}
|
||||
|
||||
// TODO: This looks wrong :/
|
||||
static void handle_tablet_tool_wheel(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
static void handle_tablet_tool_wheel(void *data, struct zwp_tablet_tool_v2 *id,
|
||||
wl_fixed_t degree, int clicks) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct tablet_tool *tool = data;
|
||||
tool->wheel_delta = wl_fixed_to_double(degree);
|
||||
}
|
||||
|
||||
static void handle_tablet_tool_button(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
uint32_t serial, uint32_t button, uint32_t state) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct wlr_tablet *tablet = tool->tablet->wlr_input_device.tablet;
|
||||
struct tablet_tool *tool = data;
|
||||
struct wlr_wl_seat *seat = tool->seat;
|
||||
struct wlr_tablet *tablet = &seat->wlr_tablet;
|
||||
|
||||
struct wlr_event_tablet_tool_button evt = {
|
||||
.device = &tool->tablet->wlr_input_device,
|
||||
.tool = &tool->wlr_tool,
|
||||
struct wlr_tablet_tool_button_event evt = {
|
||||
.tablet = tablet,
|
||||
.tool = &seat->wlr_tablet_tool,
|
||||
.time_msec = get_current_time_msec(),
|
||||
.button = button,
|
||||
.state = state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED ?
|
||||
WLR_BUTTON_RELEASED : WLR_BUTTON_PRESSED,
|
||||
};
|
||||
|
||||
wlr_signal_emit_safe(&tablet->events.button, &evt);
|
||||
wl_signal_emit_mutable(&tablet->events.button, &evt);
|
||||
}
|
||||
|
||||
static void clear_tablet_tool_values(struct wlr_wl_tablet_tool *tool) {
|
||||
static void clear_tablet_tool_values(struct tablet_tool *tool) {
|
||||
tool->is_out = tool->is_in = false;
|
||||
tool->is_up = tool->is_down = false;
|
||||
tool->x = tool->y = NAN;
|
||||
|
|
@ -660,31 +608,33 @@ static void clear_tablet_tool_values(struct wlr_wl_tablet_tool *tool) {
|
|||
static void handle_tablet_tool_frame(void *data,
|
||||
struct zwp_tablet_tool_v2 *id,
|
||||
uint32_t time) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct tablet_tool *tool = data;
|
||||
struct wlr_wl_seat *seat = tool->seat;
|
||||
|
||||
if (tool->is_out && tool->is_in) {
|
||||
/* we got a tablet tool coming in and out of proximity before
|
||||
* we could process it. Just ignore anything it did */
|
||||
goto clear_values;
|
||||
}
|
||||
struct wlr_tablet *tablet = tool->tablet->wlr_input_device.tablet;
|
||||
struct wlr_tablet *tablet = &seat->wlr_tablet;
|
||||
|
||||
if (tool->is_in) {
|
||||
struct wlr_event_tablet_tool_proximity evt = {
|
||||
.device = &tool->tablet->wlr_input_device,
|
||||
.tool = &tool->wlr_tool,
|
||||
struct wlr_tablet_tool_proximity_event evt = {
|
||||
.tablet = tablet,
|
||||
.tool = &seat->wlr_tablet_tool,
|
||||
.time_msec = time,
|
||||
.x = tool->x,
|
||||
.y = tool->y,
|
||||
.state = WLR_TABLET_TOOL_PROXIMITY_IN,
|
||||
};
|
||||
|
||||
wlr_signal_emit_safe(&tablet->events.proximity, &evt);
|
||||
wl_signal_emit_mutable(&tablet->events.proximity, &evt);
|
||||
}
|
||||
|
||||
{
|
||||
struct wlr_event_tablet_tool_axis evt = {
|
||||
.device = &tool->tablet->wlr_input_device,
|
||||
.tool = &tool->wlr_tool,
|
||||
struct wlr_tablet_tool_axis_event evt = {
|
||||
.tablet = tablet,
|
||||
.tool = &seat->wlr_tablet_tool,
|
||||
.time_msec = time,
|
||||
.updated_axes = 0,
|
||||
};
|
||||
|
|
@ -735,7 +685,7 @@ static void handle_tablet_tool_frame(void *data,
|
|||
}
|
||||
|
||||
if (evt.updated_axes) {
|
||||
wlr_signal_emit_safe(&tablet->events.axis, &evt);
|
||||
wl_signal_emit_mutable(&tablet->events.axis, &evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -745,42 +695,42 @@ static void handle_tablet_tool_frame(void *data,
|
|||
* Downside: Here we have the frame time, if we sent right away, we
|
||||
* need to generate the time */
|
||||
if (tool->is_down) {
|
||||
struct wlr_event_tablet_tool_tip evt = {
|
||||
.device = &tool->tablet->wlr_input_device,
|
||||
.tool = &tool->wlr_tool,
|
||||
struct wlr_tablet_tool_tip_event evt = {
|
||||
.tablet = tablet,
|
||||
.tool = &seat->wlr_tablet_tool,
|
||||
.time_msec = time,
|
||||
.x = tool->x,
|
||||
.y = tool->y,
|
||||
.state = WLR_TABLET_TOOL_TIP_DOWN,
|
||||
};
|
||||
|
||||
wlr_signal_emit_safe(&tablet->events.tip, &evt);
|
||||
wl_signal_emit_mutable(&tablet->events.tip, &evt);
|
||||
}
|
||||
|
||||
if (tool->is_up) {
|
||||
struct wlr_event_tablet_tool_tip evt = {
|
||||
.device = &tool->tablet->wlr_input_device,
|
||||
.tool = &tool->wlr_tool,
|
||||
struct wlr_tablet_tool_tip_event evt = {
|
||||
.tablet = tablet,
|
||||
.tool = &seat->wlr_tablet_tool,
|
||||
.time_msec = time,
|
||||
.x = tool->x,
|
||||
.y = tool->y,
|
||||
.state = WLR_TABLET_TOOL_TIP_UP,
|
||||
};
|
||||
|
||||
wlr_signal_emit_safe(&tablet->events.tip, &evt);
|
||||
wl_signal_emit_mutable(&tablet->events.tip, &evt);
|
||||
}
|
||||
|
||||
if (tool->is_out) {
|
||||
struct wlr_event_tablet_tool_proximity evt = {
|
||||
.device = &tool->tablet->wlr_input_device,
|
||||
.tool = &tool->wlr_tool,
|
||||
struct wlr_tablet_tool_proximity_event evt = {
|
||||
.tablet = tablet,
|
||||
.tool = &seat->wlr_tablet_tool,
|
||||
.time_msec = time,
|
||||
.x = tool->x,
|
||||
.y = tool->y,
|
||||
.state = WLR_TABLET_TOOL_PROXIMITY_OUT,
|
||||
};
|
||||
|
||||
wlr_signal_emit_safe(&tablet->events.proximity, &evt);
|
||||
wl_signal_emit_mutable(&tablet->events.proximity, &evt);
|
||||
}
|
||||
|
||||
clear_values:
|
||||
|
|
@ -789,10 +739,12 @@ clear_values:
|
|||
|
||||
static void handle_tablet_tool_removed(void *data,
|
||||
struct zwp_tablet_tool_v2 *id) {
|
||||
struct wlr_wl_tablet_tool *tool = data;
|
||||
struct tablet_tool *tool = data;
|
||||
struct wlr_wl_seat *seat = tool->seat;
|
||||
|
||||
zwp_tablet_tool_v2_destroy(seat->zwp_tablet_tool_v2);
|
||||
seat->zwp_tablet_tool_v2 = NULL;
|
||||
|
||||
zwp_tablet_tool_v2_destroy(tool->tool);
|
||||
wlr_signal_emit_safe(&tool->wlr_tool.events.destroy, &tool->wlr_tool);
|
||||
free(tool);
|
||||
}
|
||||
|
||||
|
|
@ -822,62 +774,71 @@ static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
|
|||
|
||||
static void handle_tool_added(void *data,
|
||||
struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2,
|
||||
struct zwp_tablet_tool_v2 *id) {
|
||||
wlr_log(WLR_DEBUG, "New tablet tool");
|
||||
struct wlr_wl_tablet_tool *tool = calloc(1, sizeof(*tool));
|
||||
if (!tool) {
|
||||
zwp_tablet_tool_v2_destroy(id);
|
||||
struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
if (seat->zwp_tablet_tool_v2 != NULL) {
|
||||
wlr_log(WLR_ERROR, "zwp_tablet_tool_v2 already present");
|
||||
return;
|
||||
}
|
||||
tool->tool = id;
|
||||
|
||||
wl_signal_init(&seat->wlr_tablet_tool.events.destroy);
|
||||
|
||||
struct tablet_tool *tool = calloc(1, sizeof(struct tablet_tool));
|
||||
if (tool == NULL) {
|
||||
wlr_log_errno(WLR_ERROR, "failed to allocate tablet_tool");
|
||||
zwp_tablet_tool_v2_destroy(zwp_tablet_tool_v2);
|
||||
return;
|
||||
}
|
||||
|
||||
tool->seat = seat;
|
||||
clear_tablet_tool_values(tool);
|
||||
wl_signal_init(&tool->wlr_tool.events.destroy);
|
||||
zwp_tablet_tool_v2_add_listener(id, &tablet_tool_listener, tool);
|
||||
|
||||
seat->zwp_tablet_tool_v2 = zwp_tablet_tool_v2;
|
||||
zwp_tablet_tool_v2_add_listener(seat->zwp_tablet_tool_v2, &tablet_tool_listener,
|
||||
tool);
|
||||
}
|
||||
|
||||
static void handle_tablet_name(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
|
||||
const char *name) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
struct wlr_tablet *tablet = dev->wlr_input_device.tablet;
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_tablet *tablet = &seat->wlr_tablet;
|
||||
|
||||
free(tablet->name);
|
||||
tablet->name = strdup(name);
|
||||
free(tablet->base.name);
|
||||
tablet->base.name = strdup(name);
|
||||
}
|
||||
|
||||
static void handle_tablet_id(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
|
||||
uint32_t vid, uint32_t pid) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
dev->wlr_input_device.vendor = vid;
|
||||
dev->wlr_input_device.product = pid;
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_tablet *tablet = &seat->wlr_tablet;
|
||||
|
||||
tablet->base.vendor = vid;
|
||||
tablet->base.product = pid;
|
||||
}
|
||||
|
||||
static void handle_tablet_path(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
|
||||
const char *path) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
struct wlr_tablet *tablet = dev->wlr_input_device.tablet;
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_tablet *tablet = &seat->wlr_tablet;
|
||||
|
||||
char **dst = wl_array_add(&tablet->paths, sizeof(char *));
|
||||
*dst = strdup(path);
|
||||
}
|
||||
|
||||
static void handle_tablet_done(void *data, struct zwp_tablet_v2 *zwp_tablet_v2) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
struct wlr_wl_seat *seat = data;
|
||||
|
||||
wlr_signal_emit_safe(&dev->backend->backend.events.new_input,
|
||||
&dev->wlr_input_device);
|
||||
wl_signal_emit_mutable(&seat->backend->backend.events.new_input,
|
||||
&seat->wlr_tablet.base);
|
||||
}
|
||||
|
||||
static void handle_tablet_removed(void *data,
|
||||
struct zwp_tablet_v2 *zwp_tablet_v2) {
|
||||
struct wlr_wl_input_device *dev = data;
|
||||
struct wlr_wl_seat *seat = data;
|
||||
|
||||
/* This doesn't free anything, but emits the destroy signal */
|
||||
wlr_input_device_destroy(&dev->wlr_input_device);
|
||||
/* This is a bit ugly, but we need to remove it from our list */
|
||||
wl_list_remove(&dev->link);
|
||||
|
||||
zwp_tablet_v2_destroy(dev->resource);
|
||||
free(dev);
|
||||
wlr_tablet_finish(&seat->wlr_tablet);
|
||||
zwp_tablet_v2_destroy(seat->zwp_tablet_v2);
|
||||
seat->zwp_tablet_v2 = NULL;
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_v2_listener tablet_listener = {
|
||||
|
|
@ -888,32 +849,23 @@ static const struct zwp_tablet_v2_listener tablet_listener = {
|
|||
.removed = handle_tablet_removed,
|
||||
};
|
||||
|
||||
const struct wlr_tablet_impl tablet_impl = {0};
|
||||
const struct wlr_tablet_impl wl_tablet_impl = {
|
||||
.name = "wl-tablet-tool",
|
||||
};
|
||||
|
||||
static void handle_tab_added(void *data,
|
||||
struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2,
|
||||
struct zwp_tablet_v2 *id) {
|
||||
wlr_log(WLR_DEBUG, "New tablet");
|
||||
struct zwp_tablet_v2 *zwp_tablet_v2) {
|
||||
struct wlr_wl_seat *seat = data;
|
||||
struct wlr_wl_input_device *dev = create_wl_input_device(
|
||||
seat, WLR_INPUT_DEVICE_TABLET_TOOL);
|
||||
|
||||
if (!dev) {
|
||||
zwp_tablet_v2_destroy(id);
|
||||
if (seat->zwp_tablet_v2 != NULL) {
|
||||
wlr_log(WLR_ERROR, "zwp_tablet_v2 already present");
|
||||
return;
|
||||
}
|
||||
dev->resource = id;
|
||||
|
||||
struct wlr_input_device *wlr_dev = &dev->wlr_input_device;
|
||||
wlr_dev->tablet = calloc(1, sizeof(*wlr_dev->tablet));
|
||||
seat->zwp_tablet_v2 = zwp_tablet_v2;
|
||||
zwp_tablet_v2_add_listener(zwp_tablet_v2, &tablet_listener, seat);
|
||||
|
||||
if (!wlr_dev->tablet) {
|
||||
zwp_tablet_v2_destroy(id);
|
||||
return;
|
||||
}
|
||||
zwp_tablet_v2_set_user_data(id, wlr_dev->tablet);
|
||||
wlr_tablet_init(wlr_dev->tablet, &tablet_impl, wlr_dev->name);
|
||||
zwp_tablet_v2_add_listener(id, &tablet_listener, dev);
|
||||
wlr_tablet_init(&seat->wlr_tablet, &wl_tablet_impl, "wlr_tablet_v2");
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = {
|
||||
|
|
@ -922,20 +874,55 @@ static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = {
|
|||
.pad_added = handle_pad_added,
|
||||
};
|
||||
|
||||
struct wlr_wl_tablet_seat *wl_add_tablet_seat(
|
||||
struct zwp_tablet_manager_v2 *manager,
|
||||
struct wlr_wl_seat *seat) {
|
||||
struct wlr_wl_tablet_seat *ret =
|
||||
calloc(1, sizeof(struct wlr_wl_tablet_seat));
|
||||
void init_seat_tablet(struct wlr_wl_seat *seat) {
|
||||
struct zwp_tablet_manager_v2 *manager = seat->backend->tablet_manager;
|
||||
assert(manager);
|
||||
|
||||
if (!(ret->tablet_seat =
|
||||
zwp_tablet_manager_v2_get_tablet_seat(manager, seat->wl_seat))) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
/**
|
||||
* TODO: multi tablet support
|
||||
* The wlr_wl_seat should support multiple tablet_v2 devices, but for
|
||||
* the sake of simplicity, it supports only one device of each.
|
||||
* If this is a feature you want/need, please open an issue on the wlroots
|
||||
* tracker here https://gitlab.freedesktop.org/wlroots/wlroots/-/issues
|
||||
*/
|
||||
|
||||
seat->zwp_tablet_seat_v2 =
|
||||
zwp_tablet_manager_v2_get_tablet_seat(manager, seat->wl_seat);
|
||||
if (seat->zwp_tablet_seat_v2 == NULL) {
|
||||
wlr_log(WLR_ERROR, "failed to get zwp_tablet_manager_v2 from seat '%s'",
|
||||
seat->name);
|
||||
return;
|
||||
}
|
||||
|
||||
zwp_tablet_seat_v2_add_listener(ret->tablet_seat,
|
||||
zwp_tablet_seat_v2_add_listener(seat->zwp_tablet_seat_v2,
|
||||
&tablet_seat_listener, seat);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void finish_seat_tablet(struct wlr_wl_seat *seat) {
|
||||
if (seat->zwp_tablet_v2 != NULL) {
|
||||
wlr_tablet_finish(&seat->wlr_tablet);
|
||||
zwp_tablet_v2_destroy(seat->zwp_tablet_v2);
|
||||
}
|
||||
|
||||
if (seat->zwp_tablet_tool_v2 != NULL) {
|
||||
struct tablet_tool *tool =
|
||||
zwp_tablet_tool_v2_get_user_data(seat->zwp_tablet_tool_v2);
|
||||
free(tool);
|
||||
|
||||
zwp_tablet_tool_v2_destroy(seat->zwp_tablet_tool_v2);
|
||||
}
|
||||
|
||||
if (seat->zwp_tablet_pad_v2 != NULL) {
|
||||
struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad;
|
||||
struct tablet_pad_group *group, *it;
|
||||
wl_list_for_each_safe(group, it, &tablet_pad->groups, group.link) {
|
||||
destroy_tablet_pad_group(group);
|
||||
}
|
||||
|
||||
wlr_tablet_pad_finish(tablet_pad);
|
||||
zwp_tablet_pad_v2_destroy(seat->zwp_tablet_pad_v2);
|
||||
}
|
||||
|
||||
zwp_tablet_seat_v2_destroy(seat->zwp_tablet_seat_v2);
|
||||
seat->zwp_tablet_seat_v2 = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include "backend/x11.h"
|
||||
#include "render/drm_format_set.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
// See dri2_format_for_depth in mesa
|
||||
const struct wlr_x11_format formats[] = {
|
||||
|
|
@ -164,7 +163,7 @@ static bool backend_start(struct wlr_backend *backend) {
|
|||
|
||||
wlr_log(WLR_INFO, "Starting X11 backend");
|
||||
|
||||
wlr_signal_emit_safe(&x11->backend.events.new_input, &x11->keyboard.base);
|
||||
wl_signal_emit_mutable(&x11->backend.events.new_input, &x11->keyboard.base);
|
||||
|
||||
for (size_t i = 0; i < x11->requested_outputs; ++i) {
|
||||
wlr_x11_output_create(&x11->backend);
|
||||
|
|
@ -185,7 +184,7 @@ static void backend_destroy(struct wlr_backend *backend) {
|
|||
wlr_output_destroy(&output->wlr_output);
|
||||
}
|
||||
|
||||
wlr_keyboard_destroy(&x11->keyboard);
|
||||
wlr_keyboard_finish(&x11->keyboard);
|
||||
|
||||
wlr_backend_finish(backend);
|
||||
|
||||
|
|
@ -637,7 +636,8 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
|
|||
}
|
||||
#endif
|
||||
|
||||
wlr_keyboard_init(&x11->keyboard, &x11_keyboard_impl, "x11-keyboard");
|
||||
wlr_keyboard_init(&x11->keyboard, &x11_keyboard_impl,
|
||||
x11_keyboard_impl.name);
|
||||
|
||||
x11->display_destroy.notify = handle_display_destroy;
|
||||
wl_display_add_destroy_listener(display, &x11->display_destroy);
|
||||
|
|
|
|||
|
|
@ -16,11 +16,10 @@
|
|||
#include <wlr/util/log.h>
|
||||
|
||||
#include "backend/x11.h"
|
||||
#include "util/signal.h"
|
||||
|
||||
static void send_key_event(struct wlr_x11_backend *x11, uint32_t key,
|
||||
enum wl_keyboard_key_state st, xcb_timestamp_t time) {
|
||||
struct wlr_event_keyboard_key ev = {
|
||||
struct wlr_keyboard_key_event ev = {
|
||||
.time_msec = time,
|
||||
.keycode = key,
|
||||
.state = st,
|
||||
|
|
@ -31,20 +30,20 @@ static void send_key_event(struct wlr_x11_backend *x11, uint32_t key,
|
|||
|
||||
static void send_button_event(struct wlr_x11_output *output, uint32_t key,
|
||||
enum wlr_button_state st, xcb_timestamp_t time) {
|
||||
struct wlr_event_pointer_button ev = {
|
||||
.device = &output->pointer.base,
|
||||
struct wlr_pointer_button_event ev = {
|
||||
.pointer = &output->pointer,
|
||||
.time_msec = time,
|
||||
.button = key,
|
||||
.state = st,
|
||||
};
|
||||
wlr_signal_emit_safe(&output->pointer.events.button, &ev);
|
||||
wlr_signal_emit_safe(&output->pointer.events.frame, &output->pointer);
|
||||
wl_signal_emit_mutable(&output->pointer.events.button, &ev);
|
||||
wl_signal_emit_mutable(&output->pointer.events.frame, &output->pointer);
|
||||
}
|
||||
|
||||
static void send_axis_event(struct wlr_x11_output *output, int32_t delta,
|
||||
xcb_timestamp_t time) {
|
||||
struct wlr_event_pointer_axis ev = {
|
||||
.device = &output->pointer.base,
|
||||
struct wlr_pointer_axis_event ev = {
|
||||
.pointer = &output->pointer,
|
||||
.time_msec = time,
|
||||
.source = WLR_AXIS_SOURCE_WHEEL,
|
||||
.orientation = WLR_AXIS_ORIENTATION_VERTICAL,
|
||||
|
|
@ -52,57 +51,57 @@ static void send_axis_event(struct wlr_x11_output *output, int32_t delta,
|
|||
.delta = delta * 15,
|
||||
.delta_discrete = delta,
|
||||
};
|
||||
wlr_signal_emit_safe(&output->pointer.events.axis, &ev);
|
||||
wlr_signal_emit_safe(&output->pointer.events.frame, &output->pointer);
|
||||
wl_signal_emit_mutable(&output->pointer.events.axis, &ev);
|
||||
wl_signal_emit_mutable(&output->pointer.events.frame, &output->pointer);
|
||||
}
|
||||
|
||||
static void send_pointer_position_event(struct wlr_x11_output *output,
|
||||
int16_t x, int16_t y, xcb_timestamp_t time) {
|
||||
struct wlr_event_pointer_motion_absolute ev = {
|
||||
.device = &output->pointer.base,
|
||||
struct wlr_pointer_motion_absolute_event ev = {
|
||||
.pointer = &output->pointer,
|
||||
.time_msec = time,
|
||||
.x = (double)x / output->wlr_output.width,
|
||||
.y = (double)y / output->wlr_output.height,
|
||||
};
|
||||
wlr_signal_emit_safe(&output->pointer.events.motion_absolute, &ev);
|
||||
wlr_signal_emit_safe(&output->pointer.events.frame, &output->pointer);
|
||||
wl_signal_emit_mutable(&output->pointer.events.motion_absolute, &ev);
|
||||
wl_signal_emit_mutable(&output->pointer.events.frame, &output->pointer);
|
||||
}
|
||||
|
||||
static void send_touch_down_event(struct wlr_x11_output *output,
|
||||
int16_t x, int16_t y, int32_t touch_id, xcb_timestamp_t time) {
|
||||
struct wlr_event_touch_down ev = {
|
||||
.device = &output->touch.base,
|
||||
struct wlr_touch_down_event ev = {
|
||||
.touch = &output->touch,
|
||||
.time_msec = time,
|
||||
.x = (double)x / output->wlr_output.width,
|
||||
.y = (double)y / output->wlr_output.height,
|
||||
.touch_id = touch_id,
|
||||
};
|
||||
wlr_signal_emit_safe(&output->touch.events.down, &ev);
|
||||
wlr_signal_emit_safe(&output->touch.events.frame, NULL);
|
||||
wl_signal_emit_mutable(&output->touch.events.down, &ev);
|
||||
wl_signal_emit_mutable(&output->touch.events.frame, NULL);
|
||||
}
|
||||
|
||||
static void send_touch_motion_event(struct wlr_x11_output *output,
|
||||
int16_t x, int16_t y, int32_t touch_id, xcb_timestamp_t time) {
|
||||
struct wlr_event_touch_motion ev = {
|
||||
.device = &output->touch.base,
|
||||
struct wlr_touch_motion_event ev = {
|
||||
.touch = &output->touch,
|
||||
.time_msec = time,
|
||||
.x = (double)x / output->wlr_output.width,
|
||||
.y = (double)y / output->wlr_output.height,
|
||||
.touch_id = touch_id,
|
||||
};
|
||||
wlr_signal_emit_safe(&output->touch.events.motion, &ev);
|
||||
wlr_signal_emit_safe(&output->touch.events.frame, NULL);
|
||||
wl_signal_emit_mutable(&output->touch.events.motion, &ev);
|
||||
wl_signal_emit_mutable(&output->touch.events.frame, NULL);
|
||||
}
|
||||
|
||||
static void send_touch_up_event(struct wlr_x11_output *output,
|
||||
int32_t touch_id, xcb_timestamp_t time) {
|
||||
struct wlr_event_touch_up ev = {
|
||||
.device = &output->touch.base,
|
||||
struct wlr_touch_up_event ev = {
|
||||
.touch = &output->touch,
|
||||
.time_msec = time,
|
||||
.touch_id = touch_id,
|
||||
};
|
||||
wlr_signal_emit_safe(&output->touch.events.up, &ev);
|
||||
wlr_signal_emit_safe(&output->touch.events.frame, NULL);
|
||||
wl_signal_emit_mutable(&output->touch.events.up, &ev);
|
||||
wl_signal_emit_mutable(&output->touch.events.frame, NULL);
|
||||
}
|
||||
|
||||
static struct wlr_x11_touchpoint *get_touchpoint_from_x11_touch_id(
|
||||
|
|
@ -285,28 +284,16 @@ void handle_x11_xinput_event(struct wlr_x11_backend *x11,
|
|||
}
|
||||
}
|
||||
|
||||
static void keyboard_destroy(struct wlr_keyboard *wlr_keyboard) {
|
||||
// Don't free the keyboard, it's on the stack
|
||||
}
|
||||
|
||||
const struct wlr_keyboard_impl x11_keyboard_impl = {
|
||||
.destroy = keyboard_destroy,
|
||||
.name = "x11-keyboard",
|
||||
};
|
||||
|
||||
static void pointer_destroy(struct wlr_pointer *wlr_pointer) {
|
||||
// Don't free the pointer, it's on the stack
|
||||
}
|
||||
|
||||
const struct wlr_pointer_impl x11_pointer_impl = {
|
||||
.destroy = pointer_destroy,
|
||||
.name = "x11-pointer",
|
||||
};
|
||||
|
||||
static void touch_destroy(struct wlr_touch *wlr_touch) {
|
||||
// Don't free the touch, it's on the stack
|
||||
}
|
||||
|
||||
const struct wlr_touch_impl x11_touch_impl = {
|
||||
.destroy = touch_destroy,
|
||||
.name = "x11-touch",
|
||||
};
|
||||
|
||||
void update_x11_pointer_position(struct wlr_x11_output *output,
|
||||
|
|
@ -329,11 +316,11 @@ void update_x11_pointer_position(struct wlr_x11_output *output,
|
|||
bool wlr_input_device_is_x11(struct wlr_input_device *wlr_dev) {
|
||||
switch (wlr_dev->type) {
|
||||
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||
return wlr_dev->keyboard->impl == &x11_keyboard_impl;
|
||||
return wlr_keyboard_from_input_device(wlr_dev)->impl == &x11_keyboard_impl;
|
||||
case WLR_INPUT_DEVICE_POINTER:
|
||||
return wlr_dev->pointer->impl == &x11_pointer_impl;
|
||||
return wlr_pointer_from_input_device(wlr_dev)->impl == &x11_pointer_impl;
|
||||
case WLR_INPUT_DEVICE_TOUCH:
|
||||
return wlr_dev->touch->impl == &x11_touch_impl;
|
||||
return wlr_touch_from_input_device(wlr_dev)->impl == &x11_touch_impl;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,24 +21,31 @@
|
|||
#include <wlr/util/log.h>
|
||||
|
||||
#include "backend/x11.h"
|
||||
#include "util/signal.h"
|
||||
#include "util/time.h"
|
||||
|
||||
static const uint32_t SUPPORTED_OUTPUT_STATE =
|
||||
WLR_OUTPUT_STATE_BACKEND_OPTIONAL |
|
||||
WLR_OUTPUT_STATE_BUFFER |
|
||||
WLR_OUTPUT_STATE_MODE;
|
||||
WLR_OUTPUT_STATE_MODE |
|
||||
WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED;
|
||||
|
||||
static void parse_xcb_setup(struct wlr_output *output,
|
||||
xcb_connection_t *xcb) {
|
||||
const xcb_setup_t *xcb_setup = xcb_get_setup(xcb);
|
||||
|
||||
snprintf(output->make, sizeof(output->make), "%.*s",
|
||||
xcb_setup_vendor_length(xcb_setup),
|
||||
xcb_setup_vendor(xcb_setup));
|
||||
snprintf(output->model, sizeof(output->model), "%"PRIu16".%"PRIu16,
|
||||
xcb_setup->protocol_major_version,
|
||||
xcb_setup->protocol_minor_version);
|
||||
output->make = calloc(1, xcb_setup_vendor_length(xcb_setup) + 1);
|
||||
if (output->make == NULL) {
|
||||
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||
return;
|
||||
}
|
||||
memcpy(output->make, xcb_setup_vendor(xcb_setup),
|
||||
xcb_setup_vendor_length(xcb_setup));
|
||||
|
||||
char model[64];
|
||||
snprintf(model, sizeof(model), "%"PRIu16".%"PRIu16,
|
||||
xcb_setup->protocol_major_version,
|
||||
xcb_setup->protocol_minor_version);
|
||||
output->model = strdup(model);
|
||||
}
|
||||
|
||||
static struct wlr_x11_output *get_x11_output_from_output(
|
||||
|
|
@ -76,8 +83,8 @@ static void output_destroy(struct wlr_output *wlr_output) {
|
|||
|
||||
pixman_region32_fini(&output->exposed);
|
||||
|
||||
wlr_pointer_destroy(&output->pointer);
|
||||
wlr_touch_destroy(&output->touch);
|
||||
wlr_pointer_finish(&output->pointer);
|
||||
wlr_touch_finish(&output->touch);
|
||||
|
||||
struct wlr_x11_buffer *buffer, *buffer_tmp;
|
||||
wl_list_for_each_safe(buffer, buffer_tmp, &output->buffers, link) {
|
||||
|
|
@ -97,17 +104,28 @@ static void output_destroy(struct wlr_output *wlr_output) {
|
|||
free(output);
|
||||
}
|
||||
|
||||
static bool output_test(struct wlr_output *wlr_output) {
|
||||
uint32_t unsupported =
|
||||
wlr_output->pending.committed & ~SUPPORTED_OUTPUT_STATE;
|
||||
static bool output_test(struct wlr_output *wlr_output,
|
||||
const struct wlr_output_state *state) {
|
||||
uint32_t unsupported = state->committed & ~SUPPORTED_OUTPUT_STATE;
|
||||
if (unsupported != 0) {
|
||||
wlr_log(WLR_DEBUG, "Unsupported output state fields: 0x%"PRIx32,
|
||||
unsupported);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
|
||||
assert(wlr_output->pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
|
||||
// All we can do to influence adaptive sync on the X11 backend is set the
|
||||
// _VARIABLE_REFRESH window property like mesa automatically does. We don't
|
||||
// have any control beyond that, so we set the state to enabled on creating
|
||||
// the output and never allow changing it (just like the Wayland backend).
|
||||
assert(wlr_output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED);
|
||||
if (state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) {
|
||||
if (!state->adaptive_sync_enabled) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (state->committed & WLR_OUTPUT_STATE_MODE) {
|
||||
assert(state->mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -250,10 +268,11 @@ static struct wlr_x11_buffer *get_or_create_x11_buffer(
|
|||
return create_x11_buffer(output, wlr_buffer);
|
||||
}
|
||||
|
||||
static bool output_commit_buffer(struct wlr_x11_output *output) {
|
||||
static bool output_commit_buffer(struct wlr_x11_output *output,
|
||||
const struct wlr_output_state *state) {
|
||||
struct wlr_x11_backend *x11 = output->x11;
|
||||
|
||||
struct wlr_buffer *buffer = output->wlr_output.pending.buffer;
|
||||
struct wlr_buffer *buffer = state->buffer;
|
||||
struct wlr_x11_buffer *x11_buffer =
|
||||
get_or_create_x11_buffer(output, buffer);
|
||||
if (!x11_buffer) {
|
||||
|
|
@ -261,8 +280,9 @@ static bool output_commit_buffer(struct wlr_x11_output *output) {
|
|||
}
|
||||
|
||||
xcb_xfixes_region_t region = XCB_NONE;
|
||||
if (output->wlr_output.pending.committed & WLR_OUTPUT_STATE_DAMAGE) {
|
||||
pixman_region32_union(&output->exposed, &output->exposed, &output->wlr_output.pending.damage);
|
||||
if (state->committed & WLR_OUTPUT_STATE_DAMAGE) {
|
||||
pixman_region32_union(&output->exposed, &output->exposed,
|
||||
(pixman_region32_t *) &state->damage);
|
||||
|
||||
int rects_len = 0;
|
||||
pixman_box32_t *rects = pixman_region32_rectangles(&output->exposed, &rects_len);
|
||||
|
|
@ -308,40 +328,26 @@ error:
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool output_commit(struct wlr_output *wlr_output) {
|
||||
static bool output_commit(struct wlr_output *wlr_output,
|
||||
const struct wlr_output_state *state) {
|
||||
struct wlr_x11_output *output = get_x11_output_from_output(wlr_output);
|
||||
struct wlr_x11_backend *x11 = output->x11;
|
||||
|
||||
if (!output_test(wlr_output)) {
|
||||
if (!output_test(wlr_output, state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_MODE) {
|
||||
if (state->committed & WLR_OUTPUT_STATE_MODE) {
|
||||
if (!output_set_custom_mode(wlr_output,
|
||||
wlr_output->pending.custom_mode.width,
|
||||
wlr_output->pending.custom_mode.height,
|
||||
wlr_output->pending.custom_mode.refresh)) {
|
||||
state->custom_mode.width,
|
||||
state->custom_mode.height,
|
||||
state->custom_mode.refresh)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED &&
|
||||
x11->atoms.variable_refresh != XCB_ATOM_NONE) {
|
||||
if (wlr_output->pending.adaptive_sync_enabled) {
|
||||
uint32_t enabled = 1;
|
||||
xcb_change_property(x11->xcb, XCB_PROP_MODE_REPLACE, output->win,
|
||||
x11->atoms.variable_refresh, XCB_ATOM_CARDINAL, 32, 1,
|
||||
&enabled);
|
||||
wlr_output->adaptive_sync_status = WLR_OUTPUT_ADAPTIVE_SYNC_UNKNOWN;
|
||||
} else {
|
||||
xcb_delete_property(x11->xcb, output->win,
|
||||
x11->atoms.variable_refresh);
|
||||
wlr_output->adaptive_sync_status = WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
if (!output_commit_buffer(output)) {
|
||||
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
if (!output_commit_buffer(output, state)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -564,6 +570,12 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
|
|||
x11->atoms.wm_protocols, XCB_ATOM_ATOM, 32, 1,
|
||||
&x11->atoms.wm_delete_window);
|
||||
|
||||
uint32_t enabled = 1;
|
||||
xcb_change_property(x11->xcb, XCB_PROP_MODE_REPLACE, output->win,
|
||||
x11->atoms.variable_refresh, XCB_ATOM_CARDINAL, 32, 1,
|
||||
&enabled);
|
||||
wlr_output->adaptive_sync_status = WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED;
|
||||
|
||||
wlr_x11_output_set_title(wlr_output, NULL);
|
||||
|
||||
xcb_map_window(x11->xcb, output->win);
|
||||
|
|
@ -574,15 +586,15 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend) {
|
|||
wlr_output_update_enabled(wlr_output, true);
|
||||
|
||||
wlr_pointer_init(&output->pointer, &x11_pointer_impl, "x11-pointer");
|
||||
output->pointer.base.output_name = strdup(wlr_output->name);
|
||||
output->pointer.output_name = strdup(wlr_output->name);
|
||||
|
||||
wlr_touch_init(&output->touch, &x11_touch_impl, "x11-touch");
|
||||
output->touch.base.output_name = strdup(wlr_output->name);
|
||||
output->touch.output_name = strdup(wlr_output->name);
|
||||
wl_list_init(&output->touchpoints);
|
||||
|
||||
wlr_signal_emit_safe(&x11->backend.events.new_output, wlr_output);
|
||||
wlr_signal_emit_safe(&x11->backend.events.new_input, &output->pointer.base);
|
||||
wlr_signal_emit_safe(&x11->backend.events.new_input, &output->touch.base);
|
||||
wl_signal_emit_mutable(&x11->backend.events.new_output, wlr_output);
|
||||
wl_signal_emit_mutable(&x11->backend.events.new_input, &output->pointer.base);
|
||||
wl_signal_emit_mutable(&x11->backend.events.new_input, &output->touch.base);
|
||||
|
||||
// Start the rendering loop by requesting the compositor to render a frame
|
||||
wlr_output_schedule_frame(wlr_output);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue