commit
41a477375c
@ -0,0 +1,19 @@
|
||||
# - Find XKBCommon
|
||||
# Once done, this will define
|
||||
#
|
||||
# XKBCOMMON_FOUND - System has XKBCommon
|
||||
# XKBCOMMON_INCLUDE_DIRS - The XKBCommon include directories
|
||||
# XKBCOMMON_LIBRARIES - The libraries needed to use XKBCommon
|
||||
# XKBCOMMON_DEFINITIONS - Compiler switches required for using XKBCommon
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_XKBCOMMON QUIET xkbcommon)
|
||||
find_path(XKBCOMMON_INCLUDE_DIRS NAMES xkbcommon/xkbcommon.h HINTS ${PC_XKBCOMMON_INCLUDE_DIRS})
|
||||
find_library(XKBCOMMON_LIBRARIES NAMES xkbcommon HINTS ${PC_XKBCOMMON_LIBRARY_DIRS})
|
||||
|
||||
set(XKBCOMMON_DEFINITIONS ${PC_XKBCOMMON_CFLAGS_OTHER})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(XKBCOMMON DEFAULT_MSG XKBCOMMON_LIBRARIES XKBCOMMON_INCLUDE_DIRS)
|
||||
mark_as_advanced(XKBCOMMON_LIBRARIES XKBCOMMON_INCLUDE_DIRS)
|
||||
|
@ -0,0 +1,121 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/backend/interface.h>
|
||||
#include "backend/udev.h"
|
||||
#include "backend/libinput.h"
|
||||
#include "common/log.h"
|
||||
|
||||
static int wlr_libinput_open_restricted(const char *path,
|
||||
int flags, void *_state) {
|
||||
struct wlr_backend_state *state = _state;
|
||||
return wlr_session_open_file(state->session, path);
|
||||
}
|
||||
|
||||
static void wlr_libinput_close_restricted(int fd, void *_state) {
|
||||
struct wlr_backend_state *state = _state;
|
||||
wlr_session_close_file(state->session, fd);
|
||||
}
|
||||
|
||||
static const struct libinput_interface libinput_impl = {
|
||||
.open_restricted = wlr_libinput_open_restricted,
|
||||
.close_restricted = wlr_libinput_close_restricted
|
||||
};
|
||||
|
||||
static int wlr_libinput_readable(int fd, uint32_t mask, void *_state) {
|
||||
struct wlr_backend_state *state = _state;
|
||||
if (libinput_dispatch(state->libinput) != 0) {
|
||||
wlr_log(L_ERROR, "Failed to dispatch libinput");
|
||||
// TODO: some kind of abort?
|
||||
return 0;
|
||||
}
|
||||
struct libinput_event *event;
|
||||
while ((event = libinput_get_event(state->libinput))) {
|
||||
wlr_libinput_event(state, event);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wlr_libinput_log(struct libinput *libinput,
|
||||
enum libinput_log_priority priority, const char *fmt, va_list args) {
|
||||
_wlr_vlog(L_ERROR, fmt, args);
|
||||
}
|
||||
|
||||
static bool wlr_libinput_backend_init(struct wlr_backend_state *state) {
|
||||
wlr_log(L_DEBUG, "Initializing libinput");
|
||||
state->libinput = libinput_udev_create_context(&libinput_impl, state,
|
||||
state->udev->udev);
|
||||
if (!state->libinput) {
|
||||
wlr_log(L_ERROR, "Failed to create libinput context");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Let user customize seat used
|
||||
if (libinput_udev_assign_seat(state->libinput, "seat0") != 0) {
|
||||
wlr_log(L_ERROR, "Failed to assign libinput seat");
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: More sophisticated logging
|
||||
libinput_log_set_handler(state->libinput, wlr_libinput_log);
|
||||
libinput_log_set_priority(state->libinput, LIBINPUT_LOG_PRIORITY_ERROR);
|
||||
|
||||
struct wl_event_loop *event_loop =
|
||||
wl_display_get_event_loop(state->display);
|
||||
if (state->input_event) {
|
||||
wl_event_source_remove(state->input_event);
|
||||
}
|
||||
state->input_event = wl_event_loop_add_fd(event_loop,
|
||||
libinput_get_fd(state->libinput), WL_EVENT_READABLE,
|
||||
wlr_libinput_readable, state);
|
||||
if (!state->input_event) {
|
||||
wlr_log(L_ERROR, "Failed to create input event on event loop");
|
||||
return false;
|
||||
}
|
||||
wlr_log(L_DEBUG, "libinput sucessfully initialized");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void wlr_libinput_backend_destroy(struct wlr_backend_state *state) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
static struct wlr_backend_impl backend_impl = {
|
||||
.init = wlr_libinput_backend_init,
|
||||
.destroy = wlr_libinput_backend_destroy
|
||||
};
|
||||
|
||||
struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
|
||||
struct wlr_session *session, struct wlr_udev *udev) {
|
||||
assert(display && session && udev);
|
||||
|
||||
struct wlr_backend_state *state = calloc(1, sizeof(struct wlr_backend_state));
|
||||
if (!state) {
|
||||
wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_backend *backend = wlr_backend_create(&backend_impl, state);
|
||||
if (!backend) {
|
||||
wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
|
||||
goto error_state;
|
||||
}
|
||||
|
||||
if (!(state->devices = list_create())) {
|
||||
wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
|
||||
goto error_backend;
|
||||
}
|
||||
|
||||
state->backend = backend;
|
||||
state->session = session;
|
||||
state->udev = udev;
|
||||
state->display = display;
|
||||
|
||||
return backend;
|
||||
error_state:
|
||||
free(state);
|
||||
error_backend:
|
||||
wlr_backend_destroy(backend);
|
||||
return NULL;
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/types.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "common/log.h"
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_input_device *get_appropriate_device(
|
||||
enum wlr_input_device_type desired_type,
|
||||
struct libinput_device *device) {
|
||||
list_t *devices = libinput_device_get_user_data(device);
|
||||
if (!devices) {
|
||||
return NULL;
|
||||
}
|
||||
for (size_t i = 0; i < devices->length; ++i) {
|
||||
struct wlr_input_device *dev = devices->items[i];
|
||||
if (dev->type == desired_type) {
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void wlr_libinput_device_destroy(struct wlr_input_device_state *state) {
|
||||
libinput_device_unref(state->handle);
|
||||
free(state);
|
||||
}
|
||||
|
||||
static struct wlr_input_device_impl input_device_impl = {
|
||||
.destroy = wlr_libinput_device_destroy
|
||||
};
|
||||
|
||||
static struct wlr_input_device *allocate_device(
|
||||
struct wlr_backend_state *state, struct libinput_device *device,
|
||||
list_t *devices, enum wlr_input_device_type type) {
|
||||
int vendor = libinput_device_get_id_vendor(device);
|
||||
int product = libinput_device_get_id_product(device);
|
||||
const char *name = libinput_device_get_name(device);
|
||||
struct wlr_input_device_state *devstate =
|
||||
calloc(1, sizeof(struct wlr_input_device_state));
|
||||
devstate->handle = device;
|
||||
libinput_device_ref(device);
|
||||
struct wlr_input_device *wlr_device = wlr_input_device_create(
|
||||
type, &input_device_impl, devstate,
|
||||
name, vendor, product);
|
||||
list_add(devices, wlr_device);
|
||||
list_add(state->devices, wlr_device);
|
||||
return wlr_device;
|
||||
}
|
||||
|
||||
static void handle_device_added(struct wlr_backend_state *state,
|
||||
struct libinput_device *device) {
|
||||
assert(state && device);
|
||||
/*
|
||||
* 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(device);
|
||||
int product = libinput_device_get_id_product(device);
|
||||
const char *name = libinput_device_get_name(device);
|
||||
list_t *devices = list_create();
|
||||
wlr_log(L_DEBUG, "Added %s [%d:%d]", name, vendor, product);
|
||||
|
||||
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD)) {
|
||||
struct wlr_input_device *wlr_device = allocate_device(state,
|
||||
device, devices, WLR_INPUT_DEVICE_KEYBOARD);
|
||||
wlr_device->keyboard = wlr_libinput_keyboard_create(device);
|
||||
wl_signal_emit(&state->backend->events.input_add, wlr_device);
|
||||
}
|
||||
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) {
|
||||
struct wlr_input_device *wlr_device = allocate_device(state,
|
||||
device, devices, WLR_INPUT_DEVICE_POINTER);
|
||||
wlr_device->pointer = wlr_libinput_pointer_create(device);
|
||||
wl_signal_emit(&state->backend->events.input_add, wlr_device);
|
||||
}
|
||||
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH)) {
|
||||
struct wlr_input_device *wlr_device = allocate_device(state,
|
||||
device, devices, WLR_INPUT_DEVICE_TOUCH);
|
||||
wlr_device->touch = wlr_libinput_touch_create(device);
|
||||
wl_signal_emit(&state->backend->events.input_add, wlr_device);
|
||||
}
|
||||
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) {
|
||||
struct wlr_input_device *wlr_device = allocate_device(state,
|
||||
device, devices, WLR_INPUT_DEVICE_TABLET_TOOL);
|
||||
wlr_device->tablet_tool = wlr_libinput_tablet_tool_create(device);
|
||||
wl_signal_emit(&state->backend->events.input_add, wlr_device);
|
||||
}
|
||||
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_PAD)) {
|
||||
// TODO
|
||||
}
|
||||
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE)) {
|
||||
// TODO
|
||||
}
|
||||
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_SWITCH)) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
if (devices->length > 0) {
|
||||
libinput_device_set_user_data(device, devices);
|
||||
} else {
|
||||
list_free(devices);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_device_removed(struct wlr_backend_state *state,
|
||||
struct libinput_device *device) {
|
||||
wlr_log(L_DEBUG, "libinput device removed");
|
||||
// TODO
|
||||
}
|
||||
|
||||
void wlr_libinput_event(struct wlr_backend_state *state,
|
||||
struct libinput_event *event) {
|
||||
assert(state && event);
|
||||
struct libinput *context = libinput_event_get_context(event);
|
||||
struct libinput_device *device = libinput_event_get_device(event);
|
||||
enum libinput_event_type event_type = libinput_event_get_type(event);
|
||||
(void)context;
|
||||
switch (event_type) {
|
||||
case LIBINPUT_EVENT_DEVICE_ADDED:
|
||||
handle_device_added(state, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_DEVICE_REMOVED:
|
||||
handle_device_removed(state, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_KEYBOARD_KEY:
|
||||
handle_keyboard_key(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_MOTION:
|
||||
handle_pointer_motion(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
handle_pointer_motion_abs(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_BUTTON:
|
||||
handle_pointer_button(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_POINTER_AXIS:
|
||||
handle_pointer_axis(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
handle_touch_down(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
handle_touch_up(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION:
|
||||
handle_touch_motion(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TOUCH_CANCEL:
|
||||
handle_touch_cancel(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TOUCH_FRAME:
|
||||
// no-op (at least for now)
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
||||
handle_tablet_tool_axis(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
|
||||
handle_tablet_tool_proximity(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_TIP:
|
||||
handle_tablet_tool_tip(event, device);
|
||||
break;
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
|
||||
handle_tablet_tool_button(event, device);
|
||||
break;
|
||||
default:
|
||||
wlr_log(L_DEBUG, "Unknown libinput event %d", event_type);
|
||||
break;
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/types.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "common/log.h"
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_keyboard *wlr_libinput_keyboard_create(
|
||||
struct libinput_device *device) {
|
||||
assert(device);
|
||||
libinput_device_led_update(device, 0);
|
||||
return wlr_keyboard_create(NULL, NULL);
|
||||
}
|
||||
|
||||
void handle_keyboard_key(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_KEYBOARD, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a keyboard event for a device with no keyboards?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_keyboard *kbevent =
|
||||
libinput_event_get_keyboard_event(event);
|
||||
struct wlr_keyboard_key *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_keyboard_key));
|
||||
wlr_event->time_sec = libinput_event_keyboard_get_time(kbevent);
|
||||
wlr_event->time_usec = libinput_event_keyboard_get_time_usec(kbevent);
|
||||
wlr_event->keycode = libinput_event_keyboard_get_key(kbevent);
|
||||
enum libinput_key_state state =
|
||||
libinput_event_keyboard_get_key_state(kbevent);
|
||||
switch (state) {
|
||||
case LIBINPUT_KEY_STATE_RELEASED:
|
||||
wlr_event->state = WLR_KEY_RELEASED;
|
||||
break;
|
||||
case LIBINPUT_KEY_STATE_PRESSED:
|
||||
wlr_event->state = WLR_KEY_PRESSED;
|
||||
break;
|
||||
}
|
||||
wl_signal_emit(&dev->keyboard->events.key, wlr_event);
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/types.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "common/log.h"
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_pointer *wlr_libinput_pointer_create(
|
||||
struct libinput_device *device) {
|
||||
assert(device);
|
||||
return wlr_pointer_create(NULL, NULL);
|
||||
}
|
||||
|
||||
void handle_pointer_motion(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a pointer event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_pointer *pevent =
|
||||
libinput_event_get_pointer_event(event);
|
||||
struct wlr_pointer_motion *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_pointer_motion));
|
||||
wlr_event->time_sec = libinput_event_pointer_get_time(pevent);
|
||||
wlr_event->time_usec = 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);
|
||||
wl_signal_emit(&dev->pointer->events.motion, wlr_event);
|
||||
}
|
||||
|
||||
void handle_pointer_motion_abs(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a pointer event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_pointer *pevent =
|
||||
libinput_event_get_pointer_event(event);
|
||||
struct wlr_pointer_motion_absolute *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_pointer_motion_absolute));
|
||||
wlr_event->time_sec = libinput_event_pointer_get_time(pevent);
|
||||
wlr_event->time_usec = libinput_event_pointer_get_time_usec(pevent);
|
||||
wlr_event->x_mm = libinput_event_pointer_get_absolute_x(pevent);
|
||||
wlr_event->y_mm = libinput_event_pointer_get_absolute_y(pevent);
|
||||
libinput_device_get_size(device, &wlr_event->width_mm, &wlr_event->height_mm);
|
||||
wl_signal_emit(&dev->pointer->events.motion_absolute, wlr_event);
|
||||
}
|
||||
|
||||
void handle_pointer_button(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a pointer event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_pointer *pevent =
|
||||
libinput_event_get_pointer_event(event);
|
||||
struct wlr_pointer_button *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_pointer_button));
|
||||
wlr_event->time_sec = libinput_event_pointer_get_time(pevent);
|
||||
wlr_event->time_usec = libinput_event_pointer_get_time_usec(pevent);
|
||||
wlr_event->button = libinput_event_pointer_get_button(pevent);
|
||||
switch (libinput_event_pointer_get_button_state(pevent)) {
|
||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
||||
wlr_event->state = WLR_BUTTON_PRESSED;
|
||||
break;
|
||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
||||
wlr_event->state = WLR_BUTTON_RELEASED;
|
||||
break;
|
||||
}
|
||||
wl_signal_emit(&dev->pointer->events.button, wlr_event);
|
||||
}
|
||||
|
||||
void handle_pointer_axis(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_POINTER, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a pointer event for a device with no pointers?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_pointer *pevent =
|
||||
libinput_event_get_pointer_event(event);
|
||||
struct wlr_pointer_axis *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_pointer_axis));
|
||||
wlr_event->time_sec = libinput_event_pointer_get_time(pevent);
|
||||
wlr_event->time_usec = libinput_event_pointer_get_time_usec(pevent);
|
||||
switch (libinput_event_pointer_get_axis_source(pevent)) {
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
|
||||
wlr_event->source = WLR_AXIS_SOURCE_WHEEL;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
|
||||
wlr_event->source = WLR_AXIS_SOURCE_FINGER;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
|
||||
wlr_event->source = WLR_AXIS_SOURCE_CONTINUOUS;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
|
||||
wlr_event->source = WLR_AXIS_SOURCE_WHEEL_TILT;
|
||||
break;
|
||||
}
|
||||
enum libinput_pointer_axis axies[] = {
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(axies) / sizeof(axies[0]); ++i) {
|
||||
if (libinput_event_pointer_has_axis(pevent, axies[i])) {
|
||||
switch (axies[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, axies[i]);
|
||||
}
|
||||
wl_signal_emit(&dev->pointer->events.axis, wlr_event);
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/types.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "common/log.h"
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_tablet_tool *wlr_libinput_tablet_tool_create(
|
||||
struct libinput_device *device) {
|
||||
assert(device);
|
||||
return wlr_tablet_tool_create(NULL, NULL);
|
||||
}
|
||||
|
||||
void handle_tablet_tool_axis(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a tablet tool event for a device with no tablet tools?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_tablet_tool *tevent =
|
||||
libinput_event_get_tablet_tool_event(event);
|
||||
struct wlr_tablet_tool_axis *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_tablet_tool_axis));
|
||||
wlr_event->time_sec = libinput_event_tablet_tool_get_time(tevent);
|
||||
wlr_event->time_usec = libinput_event_tablet_tool_get_time_usec(tevent);
|
||||
libinput_device_get_size(device, &wlr_event->width_mm, &wlr_event->height_mm);
|
||||
if (libinput_event_tablet_tool_x_has_changed(tevent)) {
|
||||
wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_X;
|
||||
wlr_event->x_mm = libinput_event_tablet_tool_get_x(tevent);
|
||||
}
|
||||
if (libinput_event_tablet_tool_y_has_changed(tevent)) {
|
||||
wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_Y;
|
||||
wlr_event->y_mm = libinput_event_tablet_tool_get_y(tevent);
|
||||
}
|
||||
if (libinput_event_tablet_tool_pressure_has_changed(tevent)) {
|
||||
wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_PRESSURE;
|
||||
wlr_event->pressure = libinput_event_tablet_tool_get_pressure(tevent);
|
||||
}
|
||||
if (libinput_event_tablet_tool_distance_has_changed(tevent)) {
|
||||
wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_DISTANCE;
|
||||
wlr_event->distance = libinput_event_tablet_tool_get_distance(tevent);
|
||||
}
|
||||
if (libinput_event_tablet_tool_tilt_x_has_changed(tevent)) {
|
||||
wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_TILT_X;
|
||||
wlr_event->tilt_x = libinput_event_tablet_tool_get_tilt_x(tevent);
|
||||
}
|
||||
if (libinput_event_tablet_tool_tilt_y_has_changed(tevent)) {
|
||||
wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_TILT_Y;
|
||||
wlr_event->tilt_y = libinput_event_tablet_tool_get_tilt_y(tevent);
|
||||
}
|
||||
if (libinput_event_tablet_tool_rotation_has_changed(tevent)) {
|
||||
wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_ROTATION;
|
||||
wlr_event->rotation = libinput_event_tablet_tool_get_rotation(tevent);
|
||||
}
|
||||
if (libinput_event_tablet_tool_slider_has_changed(tevent)) {
|
||||
wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_SLIDER;
|
||||
wlr_event->slider = libinput_event_tablet_tool_get_slider_position(tevent);
|
||||
}
|
||||
if (libinput_event_tablet_tool_wheel_has_changed(tevent)) {
|
||||
wlr_event->updated_axes |= WLR_TABLET_TOOL_AXIS_WHEEL;
|
||||
wlr_event->wheel_delta = libinput_event_tablet_tool_get_wheel_delta(tevent);
|
||||
}
|
||||
wl_signal_emit(&dev->tablet_tool->events.axis, wlr_event);
|
||||
}
|
||||
|
||||
void handle_tablet_tool_proximity(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a tablet tool event for a device with no tablet tools?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_tablet_tool *tevent =
|
||||
libinput_event_get_tablet_tool_event(event);
|
||||
struct wlr_tablet_tool_proximity *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_tablet_tool_proximity));
|
||||
wlr_event->time_sec = libinput_event_tablet_tool_get_time(tevent);
|
||||
wlr_event->time_usec = libinput_event_tablet_tool_get_time_usec(tevent);
|
||||
switch (libinput_event_tablet_tool_get_proximity_state(tevent)) {
|
||||
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT:
|
||||
wlr_event->state = WLR_TABLET_TOOL_PROXIMITY_OUT;
|
||||
break;
|
||||
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN:
|
||||
wlr_event->state = WLR_TABLET_TOOL_PROXIMITY_IN;
|
||||
handle_tablet_tool_axis(event, device);
|
||||
break;
|
||||
}
|
||||
wl_signal_emit(&dev->tablet_tool->events.proximity, wlr_event);
|
||||
}
|
||||
|
||||
void handle_tablet_tool_tip(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a tablet tool event for a device with no tablet tools?");
|
||||
return;
|
||||
}
|
||||
handle_tablet_tool_axis(event, device);
|
||||
struct libinput_event_tablet_tool *tevent =
|
||||
libinput_event_get_tablet_tool_event(event);
|
||||
struct wlr_tablet_tool_tip *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_tablet_tool_tip));
|
||||
wlr_event->time_sec = libinput_event_tablet_tool_get_time(tevent);
|
||||
wlr_event->time_usec = libinput_event_tablet_tool_get_time_usec(tevent);
|
||||
switch (libinput_event_tablet_tool_get_tip_state(tevent)) {
|
||||
case LIBINPUT_TABLET_TOOL_TIP_UP:
|
||||
wlr_event->state = WLR_TABLET_TOOL_TIP_UP;
|
||||
break;
|
||||
case LIBINPUT_TABLET_TOOL_TIP_DOWN:
|
||||
wlr_event->state = WLR_TABLET_TOOL_TIP_DOWN;
|
||||
break;
|
||||
}
|
||||
wl_signal_emit(&dev->tablet_tool->events.tip, wlr_event);
|
||||
}
|
||||
|
||||
void handle_tablet_tool_button(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TABLET_TOOL, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a tablet tool event for a device with no tablet tools?");
|
||||
return;
|
||||
}
|
||||
// Tip events contain axis information. We update this information
|
||||
// before we send the proximity event
|
||||
handle_tablet_tool_axis(event, device);
|
||||
struct libinput_event_tablet_tool *tevent =
|
||||
libinput_event_get_tablet_tool_event(event);
|
||||
struct wlr_tablet_tool_button *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_tablet_tool_button));
|
||||
wlr_event->time_sec = libinput_event_tablet_tool_get_time(tevent);
|
||||
wlr_event->time_usec = libinput_event_tablet_tool_get_time_usec(tevent);
|
||||
wlr_event->button = libinput_event_tablet_tool_get_button(tevent);
|
||||
switch (libinput_event_tablet_tool_get_button_state(tevent)) {
|
||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
||||
wlr_event->state = WLR_BUTTON_RELEASED;
|
||||
break;
|
||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
||||
wlr_event->state = WLR_BUTTON_PRESSED;
|
||||
break;
|
||||
}
|
||||
wl_signal_emit(&dev->tablet_tool->events.button, wlr_event);
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/types.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "common/log.h"
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_touch *wlr_libinput_touch_create(
|
||||
struct libinput_device *device) {
|
||||
assert(device);
|
||||
return wlr_touch_create(NULL, NULL);
|
||||
}
|
||||
|
||||
void handle_touch_down(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a touch event for a device with no touch?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_touch *tevent =
|
||||
libinput_event_get_touch_event(event);
|
||||
struct wlr_touch_down *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_touch_down));
|
||||
wlr_event->time_sec = libinput_event_touch_get_time(tevent);
|
||||
wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent);
|
||||
wlr_event->slot = libinput_event_touch_get_slot(tevent);
|
||||
wlr_event->x_mm = libinput_event_touch_get_x(tevent);
|
||||
wlr_event->y_mm = libinput_event_touch_get_y(tevent);
|
||||
libinput_device_get_size(device, &wlr_event->width_mm, &wlr_event->height_mm);
|
||||
wl_signal_emit(&dev->touch->events.down, wlr_event);
|
||||
}
|
||||
|
||||
void handle_touch_up(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a touch event for a device with no touch?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_touch *tevent =
|
||||
libinput_event_get_touch_event(event);
|
||||
struct wlr_touch_up *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_touch_up));
|
||||
wlr_event->time_sec = libinput_event_touch_get_time(tevent);
|
||||
wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent);
|
||||
wlr_event->slot = libinput_event_touch_get_slot(tevent);
|
||||
wl_signal_emit(&dev->touch->events.up, wlr_event);
|
||||
}
|
||||
|
||||
void handle_touch_motion(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a touch event for a device with no touch?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_touch *tevent =
|
||||
libinput_event_get_touch_event(event);
|
||||
struct wlr_touch_motion *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_touch_motion));
|
||||
wlr_event->time_sec = libinput_event_touch_get_time(tevent);
|
||||
wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent);
|
||||
wlr_event->slot = libinput_event_touch_get_slot(tevent);
|
||||
wlr_event->x_mm = libinput_event_touch_get_x(tevent);
|
||||
wlr_event->y_mm = libinput_event_touch_get_y(tevent);
|
||||
libinput_device_get_size(device, &wlr_event->width_mm, &wlr_event->height_mm);
|
||||
wl_signal_emit(&dev->touch->events.motion, wlr_event);
|
||||
}
|
||||
|
||||
void handle_touch_cancel(struct libinput_event *event,
|
||||
struct libinput_device *device) {
|
||||
struct wlr_input_device *dev =
|
||||
get_appropriate_device(WLR_INPUT_DEVICE_TOUCH, device);
|
||||
if (!dev) {
|
||||
wlr_log(L_DEBUG, "Got a touch event for a device with no touch?");
|
||||
return;
|
||||
}
|
||||
struct libinput_event_touch *tevent =
|
||||
libinput_event_get_touch_event(event);
|
||||
struct wlr_touch_cancel *wlr_event =
|
||||
calloc(1, sizeof(struct wlr_touch_cancel));
|
||||
wlr_event->time_sec = libinput_event_touch_get_time(tevent);
|
||||
wlr_event->time_usec = libinput_event_touch_get_time_usec(tevent);
|
||||
wlr_event->slot = libinput_event_touch_get_slot(tevent);
|
||||
wl_signal_emit(&dev->touch->events.cancel, wlr_event);
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/backend/interface.h>
|
||||
#include <wlr/common/log.h>
|
||||
#include "backend/multi.h"
|
||||
#include "common/log.h"
|
||||
|
||||
struct subbackend_state {
|
||||
struct wlr_backend *backend;
|
||||
struct wlr_backend *container;
|
||||
struct wl_listener input_add;
|
||||
struct wl_listener input_remove;
|
||||
struct wl_listener output_add;
|
||||
struct wl_listener output_remove;
|
||||
};
|
||||
|
||||
static bool multi_backend_init(struct wlr_backend_state *state) {
|
||||
for (size_t i = 0; i < state->backends->length; ++i) {
|
||||
struct subbackend_state *sub = state->backends->items[i];
|
||||
if (!wlr_backend_init(sub->backend)) {
|
||||
wlr_log(L_ERROR, "Failed to initialize backend %zd", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void multi_backend_destroy(struct wlr_backend_state *state) {
|
||||
for (size_t i = 0; i < state->backends->length; ++i) {
|
||||
struct subbackend_state *sub = state->backends->items[i];
|
||||
wlr_backend_destroy(sub->backend);
|
||||
free(sub);
|
||||
}
|
||||
list_free(state->backends);
|
||||
free(state);
|
||||
}
|
||||
|
||||
struct wlr_backend_impl backend_impl = {
|
||||
.init = multi_backend_init,
|
||||
.destroy = multi_backend_destroy
|
||||
};
|
||||
|
||||
struct wlr_backend *wlr_multi_backend_create() {
|
||||
struct wlr_backend_state *state =
|
||||
calloc(1, sizeof(struct wlr_backend_state));
|
||||
if (!state) {
|
||||
wlr_log(L_ERROR, "Backend allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
state->backends = list_create();
|
||||
if (!state->backends) {
|
||||
free(state);
|
||||
wlr_log(L_ERROR, "Backend allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
struct wlr_backend *backend = wlr_backend_create(&backend_impl, state);
|
||||
state->backend = backend;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static void input_add_reemit(struct wl_listener *listener, void *data) {
|
||||
struct subbackend_state *state = wl_container_of(listener,
|
||||
state, input_add);
|
||||
wl_signal_emit(&state->container->events.input_add, data);
|
||||
}
|
||||
|
||||
static void input_remove_reemit(struct wl_listener *listener, void *data) {
|
||||
struct subbackend_state *state = wl_container_of(listener,
|
||||
state, input_remove);
|
||||
wl_signal_emit(&state->container->events.input_remove, data);
|
||||
}
|
||||
|
||||
static void output_add_reemit(struct wl_listener *listener, void *data) {
|
||||
struct subbackend_state *state = wl_container_of(listener,
|
||||
state, output_add);
|
||||
wl_signal_emit(&state->container->events.output_add, data);
|
||||
}
|
||||
|
||||
static void output_remove_reemit(struct wl_listener *listener, void *data) {
|
||||
struct subbackend_state *state = wl_container_of(listener,
|
||||
state, output_remove);
|
||||
wl_signal_emit(&state->container->events.output_remove, data);
|
||||
}
|
||||
|
||||
void wlr_multi_backend_add(struct wlr_backend *multi,
|
||||
struct wlr_backend *backend) {
|
||||
struct subbackend_state *sub = calloc(1, sizeof(struct subbackend_state));
|
||||
sub->backend = backend;
|
||||
sub->container = multi;
|
||||
|
||||
sub->input_add.notify = input_add_reemit;
|
||||
sub->input_remove.notify = input_remove_reemit;
|
||||
sub->output_add.notify = output_add_reemit;
|
||||
sub->output_remove.notify = output_remove_reemit;
|
||||
|
||||
wl_list_init(&sub->input_add.link);
|
||||
wl_list_init(&sub->input_remove.link);
|
||||
wl_list_init(&sub->output_add.link);
|
||||
wl_list_init(&sub->output_remove.link);
|
||||
|
||||
wl_signal_add(&backend->events.input_add, &sub->input_add);
|
||||
wl_signal_add(&backend->events.input_remove, &sub->input_remove);
|
||||
wl_signal_add(&backend->events.output_add, &sub->output_add);
|
||||
wl_signal_add(&backend->events.output_remove, &sub->output_remove);
|
||||
|
||||
list_add(multi->state->backends, sub);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,132 @@
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wayland-server-protocol.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <wlr/render/matrix.h>
|
||||
#include <wlr/render/gles3.h>
|
||||
#include <wlr/render.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/types.h>
|
||||
#include <math.h>
|
||||
#include "shared.h"
|
||||
#include "cat.h"
|
||||
|
||||
struct sample_state {
|
||||
struct wlr_renderer *renderer;
|
||||
struct wlr_surface *cat_texture;
|
||||
int cur_x, cur_y;
|
||||
float default_color[4];
|
||||
float clear_color[4];
|
||||
};
|
||||
|
||||
static void handle_output_frame(struct output_state *output, struct timespec *ts) {
|
||||
struct compositor_state *state = output->compositor;
|
||||
struct sample_state *sample = state->data;
|
||||
struct wlr_output *wlr_output = output->output;
|
||||
|
||||
wlr_renderer_begin(sample->renderer, wlr_output);
|
||||
glClearColor(sample->clear_color[0], sample->clear_color[1],
|
||||
sample->clear_color[2], sample->clear_color[3]);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
float matrix[16];
|
||||
wlr_surface_get_matrix(sample->cat_texture, &matrix,
|
||||
&wlr_output->transform_matrix, sample->cur_x, sample->cur_y);
|
||||
wlr_render_with_matrix(sample->renderer,
|
||||
sample->cat_texture, &matrix);
|
||||
|
||||
wlr_renderer_end(sample->renderer);
|
||||
}
|
||||
|
||||
static void handle_keyboard_key(struct keyboard_state *kbstate,
|
||||
xkb_keysym_t sym, enum wlr_key_state key_state) {
|
||||
if (sym == XKB_KEY_Escape) {
|
||||
kbstate->compositor->exit = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_pointer_motion(struct pointer_state *pstate,
|
||||
double d_x, double d_y) {
|
||||
struct sample_state *state = pstate->compositor->data;
|
||||
state->cur_x += d_x;
|
||||
state->cur_y += d_y;
|
||||
}
|
||||
|
||||
static void handle_pointer_button(struct pointer_state *pstate,
|
||||
uint32_t button, enum wlr_button_state state) {
|
||||
struct sample_state *sample = pstate->compositor->data;
|
||||
float (*color)[4];
|
||||
if (state == WLR_BUTTON_RELEASED) {
|
||||
color = &sample->default_color;
|
||||
} else {
|
||||
float red[4] = { 0.25f, 0.25f, 0.25f, 1 };
|
||||
red[button % 3] = 1;
|
||||
color = &red;
|
||||
}
|
||||
memcpy(&sample->clear_color, color, sizeof(*color));
|
||||
}
|
||||
|
||||
static void handle_pointer_axis(struct pointer_state *pstate,
|
||||
enum wlr_axis_source source,
|
||||
enum wlr_axis_orientation orientation,
|
||||
double delta) {
|
||||
struct sample_state *sample = pstate->compositor->data;
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
sample->default_color[i] += delta > 0 ? -0.05f : 0.05f;
|
||||
if (sample->default_color[i] > 1.0f) {
|
||||
sample->default_color[i] = 1.0f;
|
||||
}
|
||||
if (sample->default_color[i] < 0.0f) {
|
||||
sample->default_color[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
memcpy(&sample->clear_color, &sample->default_color,
|
||||
sizeof(sample->clear_color));
|
||||
}
|
||||
|
||||
static void handle_output_add(struct output_state *ostate) {
|
||||
struct wlr_output *wlr_output = ostate->output;
|
||||
if (!wlr_output_set_cursor(wlr_output, cat_tex.pixel_data,
|
||||
cat_tex.width * 4, cat_tex.width, cat_tex.height)) {
|
||||
fprintf(stderr, "Failed to set cursor\n");
|
||||
return;
|
||||
}
|
||||
if (!wlr_output_move_cursor(wlr_output, 0, 0)) {
|
||||
fprintf(stderr, "Failed to move cursor\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct sample_state state = {
|
||||
.default_color = { 0.25f, 0.25f, 0.25f, 1 },
|
||||
.clear_color = { 0.25f, 0.25f, 0.25f, 1 }
|
||||
};
|
||||
struct compositor_state compositor;
|
||||
|
||||
compositor_init(&compositor);
|
||||
compositor.output_add_cb = handle_output_add;
|
||||
compositor.output_frame_cb = handle_output_frame;
|
||||
compositor.keyboard_key_cb = handle_keyboard_key;
|
||||
compositor.pointer_motion_cb = handle_pointer_motion;
|
||||
compositor.pointer_button_cb = handle_pointer_button;
|
||||
compositor.pointer_axis_cb = handle_pointer_axis;
|
||||
|
||||
state.renderer = wlr_gles3_renderer_init();
|
||||
state.cat_texture = wlr_render_surface_init(state.renderer);
|
||||
wlr_surface_attach_pixels(state.cat_texture, GL_RGBA,
|
||||
cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
||||
|
||||
compositor.data = &state;
|
||||
compositor_run(&compositor);
|
||||
|
||||
wlr_surface_destroy(state.cat_texture);
|
||||
wlr_renderer_destroy(state.renderer);
|
||||
}
|
@ -0,0 +1,432 @@
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <wayland-server-protocol.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/types.h>
|
||||
#include "shared.h"
|
||||
|
||||
static void keyboard_key_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_keyboard_key *event = data;
|
||||
struct keyboard_state *kbstate = wl_container_of(listener, kbstate, key);
|
||||
uint32_t keycode = event->keycode + 8;
|
||||
enum wlr_key_state key_state = event->state;
|
||||
const xkb_keysym_t *syms;
|
||||
int nsyms = xkb_state_key_get_syms(kbstate->xkb_state, keycode, &syms);
|
||||
for (int i = 0; i < nsyms; ++i) {
|
||||
xkb_keysym_t sym = syms[i];
|
||||
char name[64];
|
||||
int l = xkb_keysym_get_name(sym, name, sizeof(name));
|
||||
if (l != -1 && l != sizeof(name)) {
|
||||
fprintf(stderr, "Key event: %s %s\n", name,
|
||||
key_state == WLR_KEY_PRESSED ? "pressed" : "released");
|
||||
}
|
||||
if (kbstate->compositor->keyboard_key_cb) {
|
||||
kbstate->compositor->keyboard_key_cb(kbstate, sym, key_state);
|
||||
}
|
||||
}
|
||||
xkb_state_update_key(kbstate->xkb_state, keycode,
|
||||
event->state == WLR_KEY_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||
}
|
||||
|
||||
static void keyboard_add(struct wlr_input_device *device, struct compositor_state *state) {
|
||||
struct keyboard_state *kbstate = calloc(sizeof(struct keyboard_state), 1);
|
||||
kbstate->device = device;
|
||||
kbstate->compositor = state;
|
||||
wl_list_init(&kbstate->key.link);
|
||||
kbstate->key.notify = keyboard_key_notify;
|
||||
wl_signal_add(&device->keyboard->events.key, &kbstate->key);
|
||||
wl_list_insert(&state->keyboards, &kbstate->link);
|
||||
|
||||
struct xkb_rule_names rules;
|
||||
memset(&rules, 0, sizeof(rules));
|
||||
rules.rules = getenv("XKB_DEFAULT_RULES");
|
||||
rules.model = getenv("XKB_DEFAULT_MODEL");
|
||||
rules.layout = getenv("XKB_DEFAULT_LAYOUT");
|
||||
rules.variant = getenv("XKB_DEFAULT_VARIANT");
|
||||
rules.options = getenv("XKB_DEFAULT_OPTIONS");
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!context) {
|
||||
fprintf(stderr, "Failed to create XKB context\n");
|
||||
exit(1);
|
||||
}
|
||||
kbstate->keymap = xkb_map_new_from_names(
|
||||
context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
if (!kbstate->keymap) {
|
||||
fprintf(stderr, "Failed to create XKB keymap\n");
|
||||
exit(1);
|
||||
}
|
||||
xkb_context_unref(context);
|
||||
kbstate->xkb_state = xkb_state_new(kbstate->keymap);
|
||||
if (!kbstate->xkb_state) {
|
||||
fprintf(stderr, "Failed to create XKB state\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void pointer_motion_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_pointer_motion *event = data;
|
||||
struct pointer_state *pstate = wl_container_of(listener, pstate, motion);
|
||||
if (pstate->compositor->pointer_motion_cb) {
|
||||
pstate->compositor->pointer_motion_cb(pstate,
|
||||
event->delta_x, event->delta_y);
|
||||
}
|
||||
}
|
||||
|
||||
static void pointer_button_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_pointer_button *event = data;
|
||||
struct pointer_state *pstate = wl_container_of(listener, pstate, button);
|
||||
if (pstate->compositor->pointer_button_cb) {
|
||||
pstate->compositor->pointer_button_cb(pstate,
|
||||
event->button, event->state);
|
||||
}
|
||||
}
|
||||
|
||||
static void pointer_axis_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_pointer_axis *event = data;
|
||||
struct pointer_state *pstate = wl_container_of(listener, pstate, axis);
|
||||
if (pstate->compositor->pointer_axis_cb) {
|
||||
pstate->compositor->pointer_axis_cb(pstate,
|
||||
event->source, event->orientation, event->delta);
|
||||
}
|
||||
}
|
||||
|
||||
static void pointer_add(struct wlr_input_device *device, struct compositor_state *state) {
|
||||
struct pointer_state *pstate = calloc(sizeof(struct pointer_state), 1);
|
||||
pstate->device = device;
|
||||
pstate->compositor = state;
|
||||
wl_list_init(&pstate->motion.link);
|
||||
wl_list_init(&pstate->motion_absolute.link);
|
||||
wl_list_init(&pstate->button.link);
|
||||
wl_list_init(&pstate->axis.link);
|
||||
pstate->motion.notify = pointer_motion_notify;
|
||||
pstate->button.notify = pointer_button_notify;
|
||||
pstate->axis.notify = pointer_axis_notify;
|
||||
wl_signal_add(&device->pointer->events.motion, &pstate->motion);
|
||||
wl_signal_add(&device->pointer->events.button, &pstate->button);
|
||||
wl_signal_add(&device->pointer->events.axis, &pstate->axis);
|
||||
wl_list_insert(&state->pointers, &pstate->link);
|
||||
}
|
||||
|
||||
static void touch_down_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_touch_down *event = data;
|
||||
struct touch_state *tstate = wl_container_of(listener, tstate, down);
|
||||
if (tstate->compositor->touch_down_cb) {
|
||||
tstate->compositor->touch_down_cb(tstate, event->slot,
|
||||
event->x_mm, event->y_mm, event->width_mm, event->height_mm);
|
||||
}
|
||||
}
|
||||
|
||||
static void touch_motion_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_touch_motion *event = data;
|
||||
struct touch_state *tstate = wl_container_of(listener, tstate, motion);
|
||||
if (tstate->compositor->touch_motion_cb) {
|
||||
tstate->compositor->touch_motion_cb(tstate, event->slot,
|
||||
event->x_mm, event->y_mm, event->width_mm, event->height_mm);
|
||||
}
|
||||
}
|
||||
|
||||
static void touch_up_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_touch_up *event = data;
|
||||
struct touch_state *tstate = wl_container_of(listener, tstate, up);
|
||||
if (tstate->compositor->touch_up_cb) {
|
||||
tstate->compositor->touch_up_cb(tstate, event->slot);
|
||||
}
|
||||
}
|
||||
|
||||
static void touch_cancel_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_touch_cancel *event = data;
|
||||
struct touch_state *tstate = wl_container_of(listener, tstate, cancel);
|
||||
if (tstate->compositor->touch_cancel_cb) {
|
||||
tstate->compositor->touch_cancel_cb(tstate, event->slot);
|
||||
}
|
||||
}
|
||||
|
||||
static void touch_add(struct wlr_input_device *device, struct compositor_state *state) {
|
||||
struct touch_state *tstate = calloc(sizeof(struct touch_state), 1);
|
||||
tstate->device = device;
|
||||
tstate->compositor = state;
|
||||
wl_list_init(&tstate->down.link);
|
||||
wl_list_init(&tstate->motion.link);
|
||||
wl_list_init(&tstate->up.link);
|
||||
wl_list_init(&tstate->cancel.link);
|
||||
tstate->down.notify = touch_down_notify;
|
||||
tstate->motion.notify = touch_motion_notify;
|
||||
tstate->up.notify = touch_up_notify;
|
||||
tstate->cancel.notify = touch_cancel_notify;
|
||||
wl_signal_add(&device->touch->events.down, &tstate->down);
|
||||
wl_signal_add(&device->touch->events.motion, &tstate->motion);
|
||||
wl_signal_add(&device->touch->events.up, &tstate->up);
|
||||
wl_signal_add(&device->touch->events.cancel, &tstate->cancel);
|
||||
wl_list_insert(&state->touch, &tstate->link);
|
||||
}
|
||||
|
||||
static void tablet_tool_axis_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_tablet_tool_axis *event = data;
|
||||
struct tablet_tool_state *tstate = wl_container_of(listener, tstate, axis);
|
||||
if (tstate->compositor->tool_axis_cb) {
|
||||
tstate->compositor->tool_axis_cb(tstate, event);
|
||||
}
|
||||
}
|
||||
|
||||
static void tablet_tool_proximity_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_tablet_tool_proximity *event = data;
|
||||
struct tablet_tool_state *tstate = wl_container_of(listener, tstate, proximity);
|
||||
if (tstate->compositor->tool_proximity_cb) {
|
||||
tstate->compositor->tool_proximity_cb(tstate, event->state);
|
||||
}
|
||||
}
|
||||
|
||||
static void tablet_tool_button_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_tablet_tool_button *event = data;
|
||||
struct tablet_tool_state *tstate = wl_container_of(listener, tstate, button);
|
||||
if (tstate->compositor->tool_button_cb) {
|
||||
tstate->compositor->tool_button_cb(tstate, event->button, event->state);
|
||||
}
|
||||
}
|
||||
|
||||
static void tablet_tool_add(struct wlr_input_device *device,
|
||||
struct compositor_state *state) {
|
||||
struct tablet_tool_state *tstate = calloc(sizeof(struct tablet_tool_state), 1);
|
||||
tstate->device = device;
|
||||
tstate->compositor = state;
|
||||
wl_list_init(&tstate->axis.link);
|
||||
wl_list_init(&tstate->proximity.link);
|
||||
wl_list_init(&tstate->tip.link);
|
||||
wl_list_init(&tstate->button.link);
|
||||
tstate->axis.notify = tablet_tool_axis_notify;
|
||||
tstate->proximity.notify = tablet_tool_proximity_notify;
|
||||
//tstate->tip.notify = tablet_tool_tip_notify;
|
||||
tstate->button.notify = tablet_tool_button_notify;
|
||||
wl_signal_add(&device->tablet_tool->events.axis, &tstate->axis);
|
||||
wl_signal_add(&device->tablet_tool->events.proximity, &tstate->proximity);
|
||||
//wl_signal_add(&device->tablet_tool->events.tip, &tstate->tip);
|
||||
wl_signal_add(&device->tablet_tool->events.button, &tstate->button);
|
||||
wl_list_insert(&state->tablet_tools, &tstate->link);
|
||||
}
|
||||
|
||||
static void input_add_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_input_device *device = data;
|
||||
struct compositor_state *state = wl_container_of(listener, state, input_add);
|
||||
switch (device->type) {
|
||||
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||
keyboard_add(device, state);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_POINTER:
|
||||
pointer_add(device, state);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TOUCH:
|
||||
touch_add(device, state);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TABLET_TOOL:
|
||||
tablet_tool_add(device, state);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void keyboard_remove(struct wlr_input_device *device, struct compositor_state *state) {
|
||||
struct keyboard_state *kbstate = NULL, *_kbstate;
|
||||
wl_list_for_each(_kbstate, &state->keyboards, link) {
|
||||
if (_kbstate->device == device) {
|
||||
kbstate = _kbstate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!kbstate) {
|
||||
return;
|
||||
}
|
||||
wl_list_remove(&kbstate->link);
|
||||
wl_list_remove(&kbstate->key.link);
|
||||
}
|
||||
|
||||
static void pointer_remove(struct wlr_input_device *device, struct compositor_state *state) {
|
||||
struct pointer_state *pstate = NULL, *_pstate;
|
||||
wl_list_for_each(_pstate, &state->pointers, link) {
|
||||
if (_pstate->device == device) {
|
||||
pstate = _pstate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!pstate) {
|
||||
return;
|
||||
}
|
||||
wl_list_remove(&pstate->link);
|
||||
wl_list_remove(&pstate->motion.link);
|
||||
//wl_list_remove(&pstate->motion_absolute.link);
|
||||
wl_list_remove(&pstate->button.link);
|
||||
wl_list_remove(&pstate->axis.link);
|
||||
}
|
||||
|
||||
static void touch_remove(struct wlr_input_device *device, struct compositor_state *state) {
|
||||
struct touch_state *tstate = NULL, *_tstate;
|
||||
wl_list_for_each(_tstate, &state->touch, link) {
|
||||
if (_tstate->device == device) {
|
||||
tstate = _tstate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!tstate) {
|
||||
return;
|
||||
}
|
||||
wl_list_remove(&tstate->link);
|
||||
wl_list_remove(&tstate->down.link);
|
||||
wl_list_remove(&tstate->motion.link);
|
||||
wl_list_remove(&tstate->up.link);
|
||||
wl_list_remove(&tstate->cancel.link);
|
||||
}
|
||||
|
||||
static void tablet_tool_remove(struct wlr_input_device *device, struct compositor_state *state) {
|
||||
struct tablet_tool_state *tstate = NULL, *_tstate;
|
||||
wl_list_for_each(_tstate, &state->tablet_tools, link) {
|
||||
if (_tstate->device == device) {
|
||||
tstate = _tstate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!tstate) {
|
||||
return;
|
||||
}
|
||||
wl_list_remove(&tstate->link);
|
||||
wl_list_remove(&tstate->axis.link);
|
||||
wl_list_remove(&tstate->proximity.link);
|
||||
//wl_list_remove(&tstate->tip.link);
|
||||
wl_list_remove(&tstate->button.link);
|
||||
}
|
||||
|
||||
static void input_remove_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_input_device *device = data;
|
||||
struct compositor_state *state = wl_container_of(listener, state, input_add);
|
||||
switch (device->type) {
|
||||
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||
keyboard_remove(device, state);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_POINTER:
|
||||
pointer_remove(device, state);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TOUCH:
|
||||
touch_remove(device, state);
|
||||
break;
|
||||
case WLR_INPUT_DEVICE_TABLET_TOOL:
|
||||
tablet_tool_remove(device, state);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||
struct output_state *output = wl_container_of(listener, output, frame);
|
||||
struct compositor_state *compositor = output->compositor;
|
||||
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
if (compositor->output_frame_cb) {
|
||||
compositor->output_frame_cb(output, &now);
|
||||
}
|
||||
|
||||
output->last_frame = now;
|
||||
compositor->last_frame = now;
|
||||
}
|
||||
|
||||
static void output_add_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_output *output = data;
|
||||
struct compositor_state *state = wl_container_of(listener, state, output_add);
|
||||
fprintf(stderr, "Output '%s' added\n", output->name);
|
||||
fprintf(stderr, "%s %s %"PRId32"mm x %"PRId32"mm\n", output->make, output->model,
|
||||
output->phys_width, output->phys_height);
|
||||
wlr_output_set_mode(output, output->modes->items[0]);
|
||||
struct output_state *ostate = calloc(1, sizeof(struct output_state));
|
||||
clock_gettime(CLOCK_MONOTONIC, &ostate->last_frame);
|
||||
ostate->output = output;
|
||||
ostate->compositor = state;
|
||||
ostate->frame.notify = output_frame_notify;
|
||||
wl_list_init(&ostate->frame.link);
|
||||
wl_signal_add(&output->events.frame, &ostate->frame);
|
||||
wl_list_insert(&state->outputs, &ostate->link);
|
||||
if (state->output_add_cb) {
|
||||
state->output_add_cb(ostate);
|
||||
}
|
||||
}
|
||||
|
||||
static void output_remove_notify(struct wl_listener *listener, void *data) {
|
||||
struct wlr_output *output = data;
|
||||
struct compositor_state *state = wl_container_of(listener, state, output_remove);
|
||||
struct output_state *ostate = NULL, *_ostate;
|
||||
wl_list_for_each(_ostate, &state->outputs, link) {
|
||||
if (_ostate->output == output) {
|
||||
ostate = _ostate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ostate) {
|
||||
return; // We are unfamiliar with this output
|
||||
}
|
||||
if (state->output_remove_cb) {
|
||||
state->output_remove_cb(ostate);
|
||||
}
|
||||
wl_list_remove(&ostate->link);
|
||||
wl_list_remove(&ostate->frame.link);
|
||||
}
|
||||
|
||||
void compositor_init(struct compositor_state *state) {
|
||||
memset(state, 0, sizeof(struct compositor_state));
|
||||
|
||||
state->display = wl_display_create();
|
||||
state->event_loop = wl_display_get_event_loop(state->display);
|
||||
state->session = wlr_session_start(state->display);
|
||||
if (!state->session
|
||||
|| !state->display
|
||||
|| !state->event_loop) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
wl_list_init(&state->keyboards);
|
||||
wl_list_init(&state->pointers);
|
||||
wl_list_init(&state->touch);
|
||||
wl_list_init(&state->tablet_tools);
|
||||
wl_list_init(&state->input_add.link);
|
||||
state->input_add.notify = input_add_notify;
|
||||
wl_list_init(&state->input_remove.link);
|
||||
state->input_remove.notify = input_remove_notify;
|
||||
|
||||
wl_list_init(&state->outputs);
|
||||
wl_list_init(&state->output_add.link);
|
||||
state->output_add.notify = output_add_notify;
|
||||
wl_list_init(&state->output_remove.link);
|
||||
state->output_remove.notify = output_remove_notify;
|
||||
|
||||
struct wlr_backend *wlr = wlr_backend_autocreate(
|
||||
state->display, state->session);
|
||||
if (!wlr) {
|
||||
exit(1);
|
||||
}
|
||||
wl_signal_add(&wlr->events.input_add, &state->input_add);
|
||||
wl_signal_add(&wlr->events.input_remove, &state->input_remove);
|
||||
wl_signal_add(&wlr->events.output_add, &state->output_add);
|
||||
wl_signal_add(&wlr->events.output_remove, &state->output_remove);
|
||||
state->backend = wlr;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &state->last_frame);
|
||||
}
|
||||
|
||||
void compositor_run(struct compositor_state *state) {
|
||||
if (!wlr_backend_init(state->backend)) {
|
||||
fprintf(stderr, "Failed to initialize backend\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (!state->exit) {
|
||||
wl_event_loop_dispatch(state->event_loop, 0);
|
||||
}
|
||||
|
||||
wlr_backend_destroy(state->backend);
|
||||
wlr_session_finish(state->session);
|
||||
wl_display_destroy(state->display);
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
#ifndef _EXAMPLE_SHARED_H
|
||||
#define _EXAMPLE_SHARED_H
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <wayland-server-protocol.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/types.h>
|
||||
|
||||
struct output_state {
|
||||
struct compositor_state *compositor;
|
||||
struct wlr_output *output;
|
||||
struct wl_listener frame;
|
||||
struct timespec last_frame;
|
||||
struct wl_list link;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct keyboard_state {
|
||||
struct compositor_state *compositor;
|
||||
struct wlr_input_device *device;
|
||||
struct wl_listener key;
|
||||
struct wl_list link;
|
||||
struct xkb_keymap *keymap;
|
||||
struct xkb_state *xkb_state;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct pointer_state {
|
||||
struct compositor_state *compositor;
|
||||
struct wlr_input_device *device;
|
||||
struct wl_listener motion;
|
||||
struct wl_listener motion_absolute;
|
||||
struct wl_listener button;
|
||||
struct wl_listener axis;
|
||||
struct wl_list link;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct touch_state {
|
||||
struct compositor_state *compositor;
|
||||
struct wlr_input_device *device;
|
||||
struct wl_listener down;
|
||||
struct wl_listener up;
|
||||
struct wl_listener motion;
|
||||
struct wl_listener cancel;
|
||||
struct wl_list link;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct tablet_tool_state {
|
||||
struct compositor_state *compositor;
|
||||
struct wlr_input_device *device;
|
||||
struct wl_listener axis;
|
||||
struct wl_listener proximity;
|
||||
struct wl_listener tip;
|
||||
struct wl_listener button;
|
||||
struct wl_list link;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct compositor_state {
|
||||
void (*output_add_cb)(struct output_state *s);
|
||||
void (*keyboard_add_cb)(struct keyboard_state *s);
|
||||
void (*output_frame_cb)(struct output_state *s, struct timespec *ts);
|
||||
void (*output_remove_cb)(struct output_state *s);
|
||||
void (*keyboard_remove_cb)(struct keyboard_state *s);
|
||||
void (*keyboard_key_cb)(struct keyboard_state *s, xkb_keysym_t sym,
|
||||
enum wlr_key_state key_state);
|
||||
void (*pointer_motion_cb)(struct pointer_state *s,
|
||||
double d_x, double d_y);
|
||||
void (*pointer_button_cb)(struct pointer_state *s,
|
||||
uint32_t button, enum wlr_button_state state);
|
||||
void (*pointer_axis_cb)(struct pointer_state *s,
|
||||
enum wlr_axis_source source,
|
||||
enum wlr_axis_orientation orientation,
|
||||
double delta);
|
||||
void (*touch_down_cb)(struct touch_state *s, int32_t slot,
|
||||
double x, double y, double width, double height);
|
||||
void (*touch_motion_cb)(struct touch_state *s, int32_t slot,
|
||||
double x, double y, double width, double height);
|
||||
void (*touch_up_cb)(struct touch_state *s, int32_t slot);
|
||||
void (*touch_cancel_cb)(struct touch_state *s, int32_t slot);
|
||||
void (*tool_axis_cb)(struct tablet_tool_state *s,
|
||||
struct wlr_tablet_tool_axis *event);
|
||||
void (*tool_proximity_cb)(struct tablet_tool_state *s,
|
||||
enum wlr_tablet_tool_proximity_state proximity);
|
||||
void (*tool_tip_cb)(struct tablet_tool_state *s,
|
||||
enum wlr_tablet_tool_tip_state state);
|
||||
void (*tool_button_cb)(struct tablet_tool_state *s,
|
||||
uint32_t button, enum wlr_button_state state);
|
||||
|
||||
struct wl_display *display;
|
||||
struct wl_event_loop *event_loop;
|
||||
struct wlr_backend *backend;
|
||||
struct wlr_session *session;
|
||||
|
||||
struct wl_list keyboards;
|
||||
struct wl_list pointers;
|
||||
struct wl_list touch;
|
||||
struct wl_list tablet_tools;
|
||||
struct wl_listener input_add;
|
||||
struct wl_listener input_remove;
|
||||
|
||||
struct timespec last_frame;
|
||||
struct wl_listener output_add;
|
||||
struct wl_listener output_remove;
|
||||
struct wl_list outputs;
|
||||
|
||||
bool exit;
|
||||
void *data;
|
||||
};
|
||||
|
||||
void compositor_init(struct compositor_state *state);
|
||||
void compositor_run(struct compositor_state *state);
|
||||
|
||||
#endif
|
@ -0,0 +1,143 @@
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wayland-server-protocol.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <wlr/render/matrix.h>
|
||||
#include <wlr/render/gles3.h>
|
||||
#include <wlr/render.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/types.h>
|
||||
#include <math.h>
|
||||
#include "shared.h"
|
||||
#include "cat.h"
|
||||
|
||||
struct sample_state {
|
||||
struct wlr_renderer *renderer;
|
||||
bool proximity, tap;
|
||||
double distance;
|
||||
double pressure;
|
||||
double x_mm, y_mm;
|
||||
double width_mm, height_mm;
|
||||
struct wl_list link;
|
||||
float tool_color[4];
|
||||
};
|
||||
|
||||
static void handle_output_frame(struct output_state *output, struct timespec *ts) {
|
||||
struct compositor_state *state = output->compositor;
|
||||
struct sample_state *sample = state->data;
|
||||
struct wlr_output *wlr_output = output->output;
|
||||
|
||||
int32_t width, height;
|
||||
wlr_output_effective_resolution(wlr_output, &width, &height);
|
||||
|
||||
wlr_renderer_begin(sample->renderer, wlr_output);
|
||||
|
||||
float matrix[16], view[16];
|
||||
float pad_color[4] = { 0.75, 0.75, 0.75, 1.0 };
|
||||
float distance = 0.8f * (1 - sample->distance);
|
||||
float tool_color[4] = { distance, distance, distance, 1 };
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
tool_color[i] *= sample->tool_color[i];
|
||||
}
|
||||
float scale = 4;
|
||||
|
||||
float pad_width = sample->width_mm * scale;
|
||||
float pad_height = sample->height_mm * scale;
|
||||
float left = width / 2.0f - pad_width / 2.0f;
|
||||
float top = height / 2.0f - pad_height / 2.0f;
|
||||
wlr_matrix_translate(&matrix, left, top, 0);
|
||||
wlr_matrix_scale(&view, pad_width, pad_height, 1);
|
||||
wlr_matrix_mul(&matrix, &view, &view);
|
||||
wlr_matrix_mul(&wlr_output->transform_matrix, &view, &matrix);
|
||||
wlr_render_colored_quad(sample->renderer, &pad_color, &matrix);
|
||||
|
||||
if (sample->proximity) {
|
||||
wlr_matrix_translate(&matrix,
|
||||
sample->x_mm * scale - 8 * (sample->pressure + 1) + left,
|
||||
sample->y_mm * scale - 8 * (sample->pressure + 1) + top, 0);
|
||||
wlr_matrix_scale(&view,
|
||||
16 * (sample->pressure + 1),
|
||||
16 * (sample->pressure + 1), 1);
|
||||
wlr_matrix_mul(&matrix, &view, &view);
|
||||
wlr_matrix_mul(&wlr_output->transform_matrix, &view, &matrix);
|
||||
wlr_render_colored_ellipse(sample->renderer, &tool_color, &matrix);
|
||||
}
|
||||
|
||||
wlr_renderer_end(sample->renderer);
|
||||
}
|
||||
|
||||
static void handle_keyboard_key(struct keyboard_state *kbstate,
|
||||
xkb_keysym_t sym, enum wlr_key_state key_state) {
|
||||
if (sym == XKB_KEY_Escape) {
|
||||
kbstate->compositor->exit = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_tool_axis(struct tablet_tool_state *tstate,
|
||||
struct wlr_tablet_tool_axis *event) {
|
||||
struct sample_state *sample = tstate->compositor->data;
|
||||
sample->width_mm = event->width_mm;
|
||||
sample->height_mm = event->height_mm;
|
||||
if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X)) {
|
||||
sample->x_mm = event->x_mm;
|
||||
}
|
||||
if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) {
|
||||
sample->y_mm = event->y_mm;
|
||||
}
|
||||
if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_DISTANCE)) {
|
||||
sample->distance = event->distance;
|
||||
}
|
||||
if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_PRESSURE)) {
|
||||
sample->pressure = event->pressure;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_tool_proximity(struct tablet_tool_state *tstate,
|
||||
enum wlr_tablet_tool_proximity_state state) {
|
||||
struct sample_state *sample = tstate->compositor->data;
|
||||
sample->proximity = state == WLR_TABLET_TOOL_PROXIMITY_IN;
|
||||
}
|
||||
|
||||
static void handle_tool_button(struct tablet_tool_state *tstate,
|
||||
uint32_t button, enum wlr_button_state state) {
|
||||
struct sample_state *sample = tstate->compositor->data;
|
||||
if (state == WLR_BUTTON_RELEASED) {
|
||||
float default_color[4] = { 1, 1, 1, 1 };
|
||||
memcpy(sample->tool_color, default_color, 4);
|
||||
} else {
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
if (button % 3 != i) {
|
||||
sample->tool_color[button % 3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct sample_state state = {
|
||||
.tool_color = { 1, 1, 1, 1 }
|
||||
};
|
||||
struct compositor_state compositor;
|
||||
|
||||
compositor_init(&compositor);
|
||||
compositor.output_frame_cb = handle_output_frame;
|
||||
compositor.keyboard_key_cb = handle_keyboard_key;
|
||||
compositor.tool_axis_cb = handle_tool_axis;
|
||||
compositor.tool_proximity_cb = handle_tool_proximity;
|
||||
compositor.tool_button_cb = handle_tool_button;
|
||||
|
||||
state.renderer = wlr_gles3_renderer_init();
|
||||
|
||||
compositor.data = &state;
|
||||
compositor_run(&compositor);
|
||||
|
||||
wlr_renderer_destroy(state.renderer);
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wayland-server-protocol.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include <wlr/render/matrix.h>
|
||||
#include <wlr/render/gles3.h>
|
||||
#include <wlr/render.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/types.h>
|
||||
#include "shared.h"
|
||||
#include "cat.h"
|
||||
|
||||
struct sample_state {
|
||||
struct wlr_renderer *renderer;
|
||||
struct wlr_surface *cat_texture;
|
||||
list_t *touch_points;
|
||||
};
|
||||
|
||||
struct touch_point {
|
||||
int32_t slot;
|
||||
double x, y;
|
||||
};
|
||||
|
||||
static void handle_output_frame(struct output_state *output, struct timespec *ts) {
|
||||
struct compositor_state *state = output->compositor;
|
||||
struct sample_state *sample = state->data;
|
||||
struct wlr_output *wlr_output = output->output;
|
||||
|
||||
int32_t width, height;
|
||||
wlr_output_effective_resolution(wlr_output, &width, &height);
|
||||
wlr_renderer_begin(sample->renderer, wlr_output);
|
||||
|
||||
float matrix[16];
|
||||
for (size_t i = 0; i < sample->touch_points->length; ++i) {
|
||||
struct touch_point *p = sample->touch_points->items[i];
|
||||
wlr_surface_get_matrix(sample->cat_texture, &matrix,
|
||||
&wlr_output->transform_matrix,
|
||||
(int)(p->x * width) - sample->cat_texture->width / 2,
|
||||
(int)(p->y * height) - sample->cat_texture->height / 2);
|
||||
wlr_render_with_matrix(sample->renderer,
|
||||
sample->cat_texture, &matrix);
|
||||
}
|
||||
|
||||
wlr_renderer_end(sample->renderer);
|
||||
}
|
||||
|
||||
static void handle_keyboard_key(struct keyboard_state *kbstate,
|
||||
xkb_keysym_t sym, enum wlr_key_state key_state) {
|
||||
if (sym == XKB_KEY_Escape) {
|
||||
kbstate->compositor->exit = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_touch_down(struct touch_state *tstate, int32_t slot,
|
||||
double x, double y, double width, double height) {
|
||||
struct sample_state *sample = tstate->compositor->data;
|
||||
struct touch_point *point = calloc(1, sizeof(struct touch_state));
|
||||
point->slot = slot;
|
||||
point->x = x / width;
|
||||
point->y = y / height;
|
||||
list_add(sample->touch_points, point);
|
||||
}
|
||||
|
||||
static void handle_touch_up(struct touch_state *tstate, int32_t slot) {
|
||||
struct sample_state *sample = tstate->compositor->data;
|
||||
for (size_t i = 0; i < sample->touch_points->length; ++i) {
|
||||
struct touch_point *point = sample->touch_points->items[i];
|
||||
if (point->slot == slot) {
|
||||
list_del(sample->touch_points, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_touch_motion(struct touch_state *tstate, int32_t slot,
|
||||
double x, double y, double width, double height) {
|
||||
struct sample_state *sample = tstate->compositor->data;
|
||||
for (size_t i = 0; i < sample->touch_points->length; ++i) {
|
||||
struct touch_point *point = sample->touch_points->items[i];
|
||||
if (point->slot == slot) {
|
||||
point->x = x / width;
|
||||
point->y = y / height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct sample_state state = {
|
||||
.touch_points = list_create()
|
||||
};
|
||||
struct compositor_state compositor;
|
||||
|
||||
compositor_init(&compositor);
|
||||
compositor.output_frame_cb = handle_output_frame;
|
||||
compositor.keyboard_key_cb = handle_keyboard_key;
|
||||
compositor.touch_down_cb = handle_touch_down;
|
||||
compositor.touch_up_cb = handle_touch_up;
|
||||
compositor.touch_motion_cb = handle_touch_motion;
|
||||
|
||||
state.renderer = wlr_gles3_renderer_init();
|
||||
state.cat_texture = wlr_render_surface_init(state.renderer);
|
||||
wlr_surface_attach_pixels(state.cat_texture, GL_RGBA,
|
||||
cat_tex.width, cat_tex.height, cat_tex.pixel_data);
|
||||
|
||||
compositor.data = &state;
|
||||
compositor_run(&compositor);
|
||||
|
||||
wlr_surface_destroy(state.cat_texture);
|
||||
wlr_renderer_destroy(state.renderer);
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
#ifndef _WLR_BACKEND_LIBINPUT_INTERNAL_H
|
||||
#define _WLR_BACKEND_LIBINPUT_INTERNAL_H
|
||||
#include <libinput.h>
|
||||
#include <wlr/backend/interface.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include "backend/udev.h"
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_backend_state {
|
||||
struct wlr_backend *backend;
|
||||
struct wlr_session *session;
|
||||
struct wlr_udev *udev;
|
||||
struct wl_display *display;
|
||||
|
||||
struct libinput *libinput;
|
||||
struct wl_event_source *input_event;
|
||||
|
||||
list_t *devices;
|
||||
};
|
||||
|
||||
struct wlr_input_device_state {
|
||||
struct libinput_device *handle;
|
||||
};
|
||||
|
||||
void wlr_libinput_event(struct wlr_backend_state *state,
|
||||
struct libinput_event *event);
|
||||
|
||||
struct wlr_input_device *get_appropriate_device(
|
||||
enum wlr_input_device_type desired_type,
|
||||
struct libinput_device *device);
|
||||
|
||||
struct wlr_keyboard *wlr_libinput_keyboard_create(
|
||||
struct libinput_device *device);
|
||||
void handle_keyboard_key(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
|
||||
struct wlr_pointer *wlr_libinput_pointer_create(
|
||||
struct libinput_device *device);
|
||||
void handle_pointer_motion(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
void handle_pointer_motion_abs(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
void handle_pointer_button(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
void handle_pointer_axis(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
|
||||
struct wlr_touch *wlr_libinput_touch_create(
|
||||
struct libinput_device *device);
|
||||
void handle_touch_down(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
void handle_touch_up(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
void handle_touch_motion(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
void handle_touch_cancel(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
|
||||
struct wlr_tablet_tool *wlr_libinput_tablet_tool_create(
|
||||
struct libinput_device *device);
|
||||
void handle_tablet_tool_axis(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
void handle_tablet_tool_proximity(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
void handle_tablet_tool_tip(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
void handle_tablet_tool_button(struct libinput_event *event,
|
||||
struct libinput_device *device);
|
||||
|
||||
#endif
|
@ -0,0 +1,13 @@
|
||||
#ifndef _WLR_MULTI_BACKEND_INTERNAL
|
||||
#define _WLR_MULTI_BACKEND_INTERNAL
|
||||
|
||||
#include <wlr/backend/interface.h>
|
||||
#include <wlr/backend/multi.h>
|
||||
#include <wlr/common/list.h>
|
||||
|
||||
struct wlr_backend_state {
|
||||
struct wlr_backend *backend;
|
||||
list_t *backends;
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,15 @@
|
||||
#ifndef WLR_BACKEND_LIBINPUT_H
|
||||
#define WLR_BACKEND_LIBINPUT_H
|
||||
|
||||
#include <libinput.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/session.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/backend/udev.h>
|
||||
#include <wlr/types.h>
|
||||
|
||||
struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
|
||||
struct wlr_session *session, struct wlr_udev *udev);
|
||||
struct libinput_device *wlr_libinput_get_device_handle(struct wlr_input_device *dev);
|
||||
|
||||
#endif
|
@ -0,0 +1,10 @@
|
||||
#ifndef _WLR_BACKEND_MULTI_H
|
||||
#define _WLR_BACKEND_MULTI_H
|
||||
|
||||
#include <wlr/backend.h>
|
||||
|
||||
struct wlr_backend *wlr_multi_backend_create();
|
||||
void wlr_multi_backend_add(struct wlr_backend *multi,
|
||||
struct wlr_backend *backend);
|
||||
|
||||
#endif
|
@ -1,28 +1,63 @@
|
||||
#include "render/gles3.h"
|
||||
#include <GLES3/gl3.h>
|
||||
|
||||
// Colored quads
|
||||
const GLchar quad_vertex_src[] =
|
||||
"uniform mat4 proj;"
|
||||
"uniform vec4 color;"
|
||||
"attribute vec2 pos;"
|
||||
"attribute vec2 texcoord;"
|
||||
"varying vec4 v_color;"
|
||||
"varying vec2 v_texcoord;"
|
||||
"void main() {"
|
||||
" gl_Position = proj * vec4(pos, 0.0, 1.0);"
|
||||
" v_color = color;"
|
||||
" v_texcoord = texcoord;"
|
||||
"}";
|
||||
|
||||
const GLchar quad_fragment_src[] =
|
||||
"precision mediump float;"
|
||||
"varying vec4 v_color;"
|
||||
"varying vec2 v_texcoord;"
|
||||
"void main() {"
|
||||
" gl_FragColor = v_color;"
|
||||
"}";
|
||||
|
||||
// Colored ellipses (TODO)
|
||||
|
||||
const GLchar ellipse_fragment_src[] =
|
||||
"precision mediump float;"
|
||||
"varying vec4 v_color;"
|
||||
"varying vec2 v_texcoord;"
|
||||
"void main() {"
|
||||
" float l = length(v_texcoord - vec2(0.5, 0.5));"
|
||||
" if (l > 0.5) discard;"
|
||||
" gl_FragColor = v_color;"
|
||||
"}";
|
||||
|
||||
// Textured quads
|
||||
const GLchar vertex_src[] =
|
||||
"uniform mat4 proj;\n"
|
||||
"attribute vec2 pos;\n"
|
||||
"attribute vec2 texcoord;\n"
|
||||
"varying vec2 v_texcoord;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = proj * vec4(pos, 0.0, 1.0);\n"
|
||||
" v_texcoord = texcoord;\n"
|
||||
"}\n";
|
||||
"uniform mat4 proj;"
|
||||
"attribute vec2 pos;"
|
||||
"attribute vec2 texcoord;"
|
||||
"varying vec2 v_texcoord;"
|
||||
"void main() {"
|
||||
" gl_Position = proj * vec4(pos, 0.0, 1.0);"
|
||||
" v_texcoord = texcoord;"
|
||||
"}";
|
||||
|
||||
const GLchar fragment_src_RGB[] =
|
||||
"precision mediump float;\n"
|
||||
"varying vec2 v_texcoord;\n"
|
||||
"uniform sampler2D tex;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);\n"
|
||||
"}\n";
|
||||
"precision mediump float;"
|
||||
"varying vec2 v_texcoord;"
|
||||
"uniform sampler2D tex;"
|
||||
"void main() {"
|
||||
" gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);"
|
||||
"}";
|
||||
|
||||
const GLchar fragment_src_RGBA[] =
|
||||
"precision mediump float;\n"
|
||||
"varying vec2 v_texcoord;\n"
|
||||
"uniform sampler2D tex;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = texture2D(tex, v_texcoord);\n"
|
||||
"}\n";
|
||||
"precision mediump float;"
|
||||
"varying vec2 v_texcoord;"
|
||||
"uniform sampler2D tex;"
|
||||
"void main() {"
|
||||
" gl_FragColor = texture2D(tex, v_texcoord);"
|
||||
"}";
|
||||
|
@ -0,0 +1,43 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/types.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include "common/log.h"
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_input_device *wlr_input_device_create(
|
||||
enum wlr_input_device_type type,
|
||||
struct wlr_input_device_impl *impl,
|
||||
struct wlr_input_device_state *state,
|
||||
const char *name, int vendor, int product) {
|
||||
struct wlr_input_device *dev = calloc(1, sizeof(struct wlr_input_device));
|
||||
dev->type = type;
|
||||
dev->impl = impl;
|
||||
dev->state = state;
|
||||
dev->name = strdup(name);
|
||||
dev->vendor = vendor;
|
||||
dev->product = product;
|
||||
return dev;
|
||||
}
|
||||
|
||||
void wlr_input_device_destroy(struct wlr_input_device *dev) {
|
||||
if (!dev) return;
|
||||
if (dev->impl && dev->impl->destroy && dev->state) {
|
||||
dev->impl->destroy(dev->state);
|
||||
}
|
||||
if (dev->_device) {
|
||||
switch (dev->type) {
|
||||
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||
wlr_keyboard_destroy(dev->keyboard);
|
||||
break;
|
||||
default:
|
||||
wlr_log(L_DEBUG, "Warning: leaking memory %p %p %d",
|
||||
dev->_device, dev, dev->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(dev->name);
|
||||
free(dev);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/types.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_keyboard *wlr_keyboard_create(struct wlr_keyboard_impl *impl,
|
||||
struct wlr_keyboard_state *state) {
|
||||
struct wlr_keyboard *kb = calloc(1, sizeof(struct wlr_keyboard));
|
||||
kb->impl = impl;
|
||||
kb->state = state;
|
||||
wl_signal_init(&kb->events.key);
|
||||
return kb;
|
||||
}
|
||||
|
||||
void wlr_keyboard_destroy(struct wlr_keyboard *kb) {
|
||||
if (!kb) return;
|
||||
if (kb->impl) {
|
||||
kb->impl->destroy(kb->state);
|
||||
}
|
||||
free(kb);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/types.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_pointer *wlr_pointer_create(struct wlr_pointer_impl *impl,
|
||||
struct wlr_pointer_state *state) {
|
||||
struct wlr_pointer *pointer = calloc(1, sizeof(struct wlr_pointer));
|
||||
pointer->impl = impl;
|
||||
pointer->state = state;
|
||||
wl_signal_init(&pointer->events.motion);
|
||||
wl_signal_init(&pointer->events.motion_absolute);
|
||||
wl_signal_init(&pointer->events.button);
|
||||
wl_signal_init(&pointer->events.axis);
|
||||
return pointer;
|
||||
}
|
||||
|
||||
void wlr_pointer_destroy(struct wlr_pointer *pointer) {
|
||||
if (!pointer) return;
|
||||
if (pointer->impl) {
|
||||
pointer->impl->destroy(pointer->state);
|
||||
}
|
||||
free(pointer);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/types.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_tablet_tool *wlr_tablet_tool_create(struct wlr_tablet_tool_impl *impl,
|
||||
struct wlr_tablet_tool_state *state) {
|
||||
struct wlr_tablet_tool *tool = calloc(1, sizeof(struct wlr_tablet_tool));
|
||||
tool->impl = impl;
|
||||
tool->state = state;
|
||||
wl_signal_init(&tool->events.axis);
|
||||
wl_signal_init(&tool->events.proximity);
|
||||
wl_signal_init(&tool->events.tip);
|
||||
wl_signal_init(&tool->events.button);
|
||||
return tool;
|
||||
}
|
||||
|
||||
void wlr_tablet_tool_destroy(struct wlr_tablet_tool *tool) {
|
||||
if (!tool) return;
|
||||
if (tool->impl) {
|
||||
tool->impl->destroy(tool->state);
|
||||
}
|
||||
free(tool);
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/types.h>
|
||||
#include <wlr/common/list.h>
|
||||
#include "types.h"
|
||||
|
||||
struct wlr_touch *wlr_touch_create(struct wlr_touch_impl *impl,
|
||||
struct wlr_touch_state *state) {
|
||||
struct wlr_touch *touch = calloc(1, sizeof(struct wlr_touch));
|
||||
touch->impl = impl;
|
||||
touch->state = state;
|
||||
wl_signal_init(&touch->events.down);
|
||||
wl_signal_init(&touch->events.up);
|
||||
wl_signal_init(&touch->events.motion);
|
||||
wl_signal_init(&touch->events.cancel);
|
||||
return touch;
|
||||
}
|
||||
|
||||
void wlr_touch_destroy(struct wlr_touch *touch) {
|
||||
if (!touch) return;
|
||||
if (touch->impl) {
|
||||
touch->impl->destroy(touch->state);
|
||||
}
|
||||
free(touch);
|
||||
}
|
Loading…
Reference in new issue