mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-03 07:17:06 -04:00
Compare commits
44 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88a8698557 | ||
|
|
2bc71d19d4 | ||
|
|
8c4a74717f | ||
|
|
6fee18f373 | ||
|
|
a34411c2fe | ||
|
|
f7e7d8f183 | ||
|
|
004806fae2 | ||
|
|
4080e2f627 | ||
|
|
d834de6167 | ||
|
|
0f9a1f1443 | ||
|
|
0280a03136 | ||
|
|
29bba098bd | ||
|
|
31dc115b9f | ||
|
|
11f5ba8bf2 | ||
|
|
b858230394 | ||
|
|
b08af09626 | ||
|
|
4279ee5091 | ||
|
|
aabe351207 | ||
|
|
878aebfb74 | ||
|
|
8c9e6b7c9f | ||
|
|
e432b7bd1c | ||
|
|
ea1ade5e5d | ||
|
|
f56a69aa76 | ||
|
|
8fc64ae8d5 | ||
|
|
761927bbbd | ||
|
|
0d20e46498 | ||
|
|
eba71d59d4 | ||
|
|
9b42c1901d | ||
|
|
7a52788929 | ||
|
|
d4009183a1 | ||
|
|
d092e40dec | ||
|
|
bb5180ce9e | ||
|
|
73aa61686f | ||
|
|
9079380498 | ||
|
|
3118ca5c3e | ||
|
|
c1938f79c3 | ||
|
|
aa904ccf06 | ||
|
|
52e1ad01e3 | ||
|
|
30c0602457 | ||
|
|
b7205866c0 | ||
|
|
f935404e68 | ||
|
|
5aa8c192a5 | ||
|
|
68dea55970 | ||
|
|
f3fe6b9a43 |
40 changed files with 463 additions and 262 deletions
|
|
@ -41,9 +41,10 @@ tasks:
|
||||||
cd wlroots/build-gcc/tinywl
|
cd wlroots/build-gcc/tinywl
|
||||||
sudo modprobe vkms
|
sudo modprobe vkms
|
||||||
udevadm settle
|
udevadm settle
|
||||||
|
card="/dev/dri/$(ls /sys/devices/faux/vkms/drm/ | grep ^card)"
|
||||||
export WLR_BACKENDS=drm
|
export WLR_BACKENDS=drm
|
||||||
export WLR_RENDERER=pixman
|
export WLR_RENDERER=pixman
|
||||||
export WLR_DRM_DEVICES=/dev/dri/by-path/platform-vkms-card
|
export WLR_DRM_DEVICES="$card"
|
||||||
export UBSAN_OPTIONS=halt_on_error=1
|
export UBSAN_OPTIONS=halt_on_error=1
|
||||||
sudo chmod ugo+rw /dev/dri/by-path/platform-vkms-card
|
sudo chmod ugo+rw "$card"
|
||||||
sudo -E seatd-launch -- ./tinywl -s 'kill $PPID' || [ $? = 143 ]
|
sudo -E seatd-launch -- ./tinywl -s 'kill $PPID' || [ $? = 143 ]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
include: https://git.sr.ht/~emersion/dalligi/blob/master/templates/multi.yml
|
include: https://gitlab.freedesktop.org/emersion/dalligi/-/raw/master/templates/multi.yml
|
||||||
alpine:
|
alpine:
|
||||||
extends: .dalligi
|
extends: .dalligi
|
||||||
pages: true
|
pages: true
|
||||||
|
|
|
||||||
|
|
@ -485,5 +485,10 @@ bool wlr_backend_commit(struct wlr_backend *backend,
|
||||||
output_apply_commit(state->output, &state->base);
|
output_apply_commit(state->output, &state->base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < states_len; i++) {
|
||||||
|
const struct wlr_backend_output_state *state = &states[i];
|
||||||
|
output_send_commit_event(state->output, &state->base);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2085,6 +2085,7 @@ int wlr_drm_backend_get_non_master_fd(struct wlr_backend *backend) {
|
||||||
|
|
||||||
if (drmIsMaster(fd) && drmDropMaster(fd) < 0) {
|
if (drmIsMaster(fd) && drmDropMaster(fd) < 0) {
|
||||||
wlr_log_errno(WLR_ERROR, "Failed to drop master");
|
wlr_log_errno(WLR_ERROR, "Failed to drop master");
|
||||||
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -249,3 +249,15 @@ void handle_libinput_event(struct wlr_libinput_backend *backend,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool button_state_from_libinput(enum libinput_button_state state, enum wlr_button_state *out) {
|
||||||
|
switch (state) {
|
||||||
|
case LIBINPUT_BUTTON_STATE_RELEASED:
|
||||||
|
*out = WLR_BUTTON_RELEASED;
|
||||||
|
return true;
|
||||||
|
case LIBINPUT_BUTTON_STATE_PRESSED:
|
||||||
|
*out = WLR_BUTTON_PRESSED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include <libinput.h>
|
#include <libinput.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wlr/interfaces/wlr_keyboard.h>
|
#include <wlr/interfaces/wlr_keyboard.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
#include "backend/libinput.h"
|
#include "backend/libinput.h"
|
||||||
|
|
||||||
struct wlr_libinput_input_device *device_from_keyboard(
|
struct wlr_libinput_input_device *device_from_keyboard(
|
||||||
|
|
@ -30,6 +31,18 @@ void init_device_keyboard(struct wlr_libinput_input_device *dev) {
|
||||||
libinput_device_led_update(dev->handle, 0);
|
libinput_device_led_update(dev->handle, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool key_state_from_libinput(enum libinput_key_state state, enum wl_keyboard_key_state *out) {
|
||||||
|
switch (state) {
|
||||||
|
case LIBINPUT_KEY_STATE_RELEASED:
|
||||||
|
*out = WL_KEYBOARD_KEY_STATE_RELEASED;
|
||||||
|
return true;
|
||||||
|
case LIBINPUT_KEY_STATE_PRESSED:
|
||||||
|
*out = WL_KEYBOARD_KEY_STATE_PRESSED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void handle_keyboard_key(struct libinput_event *event,
|
void handle_keyboard_key(struct libinput_event *event,
|
||||||
struct wlr_keyboard *kb) {
|
struct wlr_keyboard *kb) {
|
||||||
struct libinput_event_keyboard *kbevent =
|
struct libinput_event_keyboard *kbevent =
|
||||||
|
|
@ -39,13 +52,9 @@ void handle_keyboard_key(struct libinput_event *event,
|
||||||
.keycode = libinput_event_keyboard_get_key(kbevent),
|
.keycode = libinput_event_keyboard_get_key(kbevent),
|
||||||
.update_state = true,
|
.update_state = true,
|
||||||
};
|
};
|
||||||
switch (libinput_event_keyboard_get_key_state(kbevent)) {
|
if (!key_state_from_libinput(libinput_event_keyboard_get_key_state(kbevent), &wlr_event.state)) {
|
||||||
case LIBINPUT_KEY_STATE_RELEASED:
|
wlr_log(WLR_DEBUG, "Unhandled libinput key state");
|
||||||
wlr_event.state = WL_KEYBOARD_KEY_STATE_RELEASED;
|
return;
|
||||||
break;
|
|
||||||
case LIBINPUT_KEY_STATE_PRESSED:
|
|
||||||
wlr_event.state = WL_KEYBOARD_KEY_STATE_PRESSED;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
wlr_keyboard_notify_key(kb, &wlr_event);
|
wlr_keyboard_notify_key(kb, &wlr_event);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,7 @@ features += { 'libinput-backend': true }
|
||||||
wlr_deps += libinput
|
wlr_deps += libinput
|
||||||
|
|
||||||
internal_config.set10('HAVE_LIBINPUT_BUSTYPE', libinput.version().version_compare('>=1.26.0'))
|
internal_config.set10('HAVE_LIBINPUT_BUSTYPE', libinput.version().version_compare('>=1.26.0'))
|
||||||
|
internal_config.set10(
|
||||||
|
'HAVE_LIBINPUT_SWITCH_KEYPAD_SLIDE',
|
||||||
|
libinput.version().version_compare('>=1.30.901')
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <libinput.h>
|
#include <libinput.h>
|
||||||
#include <wlr/interfaces/wlr_pointer.h>
|
#include <wlr/interfaces/wlr_pointer.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
#include "backend/libinput.h"
|
#include "backend/libinput.h"
|
||||||
|
|
||||||
const struct wlr_pointer_impl libinput_pointer_impl = {
|
const struct wlr_pointer_impl libinput_pointer_impl = {
|
||||||
|
|
@ -52,6 +53,38 @@ void handle_pointer_motion_abs(struct libinput_event *event,
|
||||||
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool pointer_button_state_from_libinput(enum libinput_button_state state,
|
||||||
|
enum wl_pointer_button_state *out) {
|
||||||
|
switch (state) {
|
||||||
|
case LIBINPUT_BUTTON_STATE_PRESSED:
|
||||||
|
*out = WL_POINTER_BUTTON_STATE_PRESSED;
|
||||||
|
return true;
|
||||||
|
case LIBINPUT_BUTTON_STATE_RELEASED:
|
||||||
|
*out = WL_POINTER_BUTTON_STATE_RELEASED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool axis_source_from_libinput(enum libinput_pointer_axis_source source,
|
||||||
|
enum wl_pointer_axis_source *out) {
|
||||||
|
switch (source) {
|
||||||
|
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
|
||||||
|
*out = WL_POINTER_AXIS_SOURCE_WHEEL;
|
||||||
|
return true;
|
||||||
|
case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
|
||||||
|
*out = WL_POINTER_AXIS_SOURCE_FINGER;
|
||||||
|
return true;
|
||||||
|
case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
|
||||||
|
*out = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
|
||||||
|
return true;
|
||||||
|
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
|
||||||
|
*out = WL_POINTER_AXIS_SOURCE_WHEEL_TILT;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void handle_pointer_button(struct libinput_event *event,
|
void handle_pointer_button(struct libinput_event *event,
|
||||||
struct wlr_pointer *pointer) {
|
struct wlr_pointer *pointer) {
|
||||||
struct libinput_event_pointer *pevent =
|
struct libinput_event_pointer *pevent =
|
||||||
|
|
@ -61,13 +94,10 @@ void handle_pointer_button(struct libinput_event *event,
|
||||||
.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)),
|
.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)),
|
||||||
.button = libinput_event_pointer_get_button(pevent),
|
.button = libinput_event_pointer_get_button(pevent),
|
||||||
};
|
};
|
||||||
switch (libinput_event_pointer_get_button_state(pevent)) {
|
if (!pointer_button_state_from_libinput(libinput_event_pointer_get_button_state(pevent),
|
||||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
&wlr_event.state)) {
|
||||||
wlr_event.state = WL_POINTER_BUTTON_STATE_PRESSED;
|
wlr_log(WLR_DEBUG, "Unhandled libinput button state");
|
||||||
break;
|
return;
|
||||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
|
||||||
wlr_event.state = WL_POINTER_BUTTON_STATE_RELEASED;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
wlr_pointer_notify_button(pointer, &wlr_event);
|
wlr_pointer_notify_button(pointer, &wlr_event);
|
||||||
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
||||||
|
|
@ -81,19 +111,9 @@ void handle_pointer_axis(struct libinput_event *event,
|
||||||
.pointer = pointer,
|
.pointer = pointer,
|
||||||
.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)),
|
.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)),
|
||||||
};
|
};
|
||||||
switch (libinput_event_pointer_get_axis_source(pevent)) {
|
if (!axis_source_from_libinput(libinput_event_pointer_get_axis_source(pevent), &wlr_event.source)) {
|
||||||
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
|
wlr_log(WLR_DEBUG, "Unhandled libinput pointer axis source");
|
||||||
wlr_event.source = WL_POINTER_AXIS_SOURCE_WHEEL;
|
return;
|
||||||
break;
|
|
||||||
case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
|
|
||||||
wlr_event.source = WL_POINTER_AXIS_SOURCE_FINGER;
|
|
||||||
break;
|
|
||||||
case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
|
|
||||||
wlr_event.source = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
|
|
||||||
break;
|
|
||||||
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
|
|
||||||
wlr_event.source = WL_POINTER_AXIS_SOURCE_WHEEL_TILT;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
const enum libinput_pointer_axis axes[] = {
|
const enum libinput_pointer_axis axes[] = {
|
||||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <libinput.h>
|
#include <libinput.h>
|
||||||
#include <wlr/interfaces/wlr_switch.h>
|
#include <wlr/interfaces/wlr_switch.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
#include "backend/libinput.h"
|
#include "backend/libinput.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
const struct wlr_switch_impl libinput_switch_impl = {
|
const struct wlr_switch_impl libinput_switch_impl = {
|
||||||
.name = "libinput-switch",
|
.name = "libinput-switch",
|
||||||
|
|
@ -22,6 +24,35 @@ struct wlr_libinput_input_device *device_from_switch(
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool switch_type_from_libinput(enum libinput_switch type, enum wlr_switch_type *out) {
|
||||||
|
switch (type) {
|
||||||
|
case LIBINPUT_SWITCH_LID:
|
||||||
|
*out = WLR_SWITCH_TYPE_LID;
|
||||||
|
return true;
|
||||||
|
case LIBINPUT_SWITCH_TABLET_MODE:
|
||||||
|
*out = WLR_SWITCH_TYPE_TABLET_MODE;
|
||||||
|
return true;
|
||||||
|
#if HAVE_LIBINPUT_SWITCH_KEYPAD_SLIDE
|
||||||
|
case LIBINPUT_SWITCH_KEYPAD_SLIDE:
|
||||||
|
*out = WLR_SWITCH_TYPE_KEYPAD_SLIDE;
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool switch_state_from_libinput(enum libinput_switch_state state, enum wlr_switch_state *out) {
|
||||||
|
switch (state) {
|
||||||
|
case LIBINPUT_SWITCH_STATE_OFF:
|
||||||
|
*out = WLR_SWITCH_STATE_OFF;
|
||||||
|
return true;
|
||||||
|
case LIBINPUT_SWITCH_STATE_ON:
|
||||||
|
*out = WLR_SWITCH_STATE_ON;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void handle_switch_toggle(struct libinput_event *event,
|
void handle_switch_toggle(struct libinput_event *event,
|
||||||
struct wlr_switch *wlr_switch) {
|
struct wlr_switch *wlr_switch) {
|
||||||
struct libinput_event_switch *sevent =
|
struct libinput_event_switch *sevent =
|
||||||
|
|
@ -29,21 +60,13 @@ void handle_switch_toggle(struct libinput_event *event,
|
||||||
struct wlr_switch_toggle_event wlr_event = {
|
struct wlr_switch_toggle_event wlr_event = {
|
||||||
.time_msec = usec_to_msec(libinput_event_switch_get_time_usec(sevent)),
|
.time_msec = usec_to_msec(libinput_event_switch_get_time_usec(sevent)),
|
||||||
};
|
};
|
||||||
switch (libinput_event_switch_get_switch(sevent)) {
|
if (!switch_type_from_libinput(libinput_event_switch_get_switch(sevent), &wlr_event.switch_type)) {
|
||||||
case LIBINPUT_SWITCH_LID:
|
wlr_log(WLR_DEBUG, "Unhandled libinput switch type");
|
||||||
wlr_event.switch_type = WLR_SWITCH_TYPE_LID;
|
return;
|
||||||
break;
|
|
||||||
case LIBINPUT_SWITCH_TABLET_MODE:
|
|
||||||
wlr_event.switch_type = WLR_SWITCH_TYPE_TABLET_MODE;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
switch (libinput_event_switch_get_switch_state(sevent)) {
|
if (!switch_state_from_libinput(libinput_event_switch_get_switch_state(sevent), &wlr_event.switch_state)) {
|
||||||
case LIBINPUT_SWITCH_STATE_OFF:
|
wlr_log(WLR_DEBUG, "Unhandled libinput switch state");
|
||||||
wlr_event.switch_state = WLR_SWITCH_STATE_OFF;
|
return;
|
||||||
break;
|
|
||||||
case LIBINPUT_SWITCH_STATE_ON:
|
|
||||||
wlr_event.switch_state = WLR_SWITCH_STATE_ON;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
wl_signal_emit_mutable(&wlr_switch->events.toggle, &wlr_event);
|
wl_signal_emit_mutable(&wlr_switch->events.toggle, &wlr_event);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,7 @@ void init_device_tablet_pad(struct wlr_libinput_input_device *dev) {
|
||||||
struct udev_device *udev = libinput_device_get_udev_device(handle);
|
struct udev_device *udev = libinput_device_get_udev_device(handle);
|
||||||
char **dst = wl_array_add(&wlr_tablet_pad->paths, sizeof(char *));
|
char **dst = wl_array_add(&wlr_tablet_pad->paths, sizeof(char *));
|
||||||
*dst = strdup(udev_device_get_syspath(udev));
|
*dst = strdup(udev_device_get_syspath(udev));
|
||||||
|
udev_device_unref(udev);
|
||||||
|
|
||||||
int groups = libinput_device_tablet_pad_get_num_mode_groups(handle);
|
int groups = libinput_device_tablet_pad_get_num_mode_groups(handle);
|
||||||
for (int i = 0; i < groups; ++i) {
|
for (int i = 0; i < groups; ++i) {
|
||||||
|
|
@ -147,13 +148,9 @@ void handle_tablet_pad_button(struct libinput_event *event,
|
||||||
.group = libinput_tablet_pad_mode_group_get_index(
|
.group = libinput_tablet_pad_mode_group_get_index(
|
||||||
libinput_event_tablet_pad_get_mode_group(pevent)),
|
libinput_event_tablet_pad_get_mode_group(pevent)),
|
||||||
};
|
};
|
||||||
switch (libinput_event_tablet_pad_get_button_state(pevent)) {
|
if (!button_state_from_libinput(libinput_event_tablet_pad_get_button_state(pevent), &wlr_event.state)) {
|
||||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
wlr_log(WLR_DEBUG, "Unhandled libinput button state");
|
||||||
wlr_event.state = WLR_BUTTON_PRESSED;
|
return;
|
||||||
break;
|
|
||||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
|
||||||
wlr_event.state = WLR_BUTTON_RELEASED;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
wl_signal_emit_mutable(&tablet_pad->events.button, &wlr_event);
|
wl_signal_emit_mutable(&tablet_pad->events.button, &wlr_event);
|
||||||
}
|
}
|
||||||
|
|
@ -167,6 +164,7 @@ void handle_tablet_pad_ring(struct libinput_event *event,
|
||||||
.ring = libinput_event_tablet_pad_get_ring_number(pevent),
|
.ring = libinput_event_tablet_pad_get_ring_number(pevent),
|
||||||
.position = libinput_event_tablet_pad_get_ring_position(pevent),
|
.position = libinput_event_tablet_pad_get_ring_position(pevent),
|
||||||
.mode = libinput_event_tablet_pad_get_mode(pevent),
|
.mode = libinput_event_tablet_pad_get_mode(pevent),
|
||||||
|
.source = WLR_TABLET_PAD_RING_SOURCE_UNKNOWN,
|
||||||
};
|
};
|
||||||
switch (libinput_event_tablet_pad_get_ring_source(pevent)) {
|
switch (libinput_event_tablet_pad_get_ring_source(pevent)) {
|
||||||
case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
|
case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
|
||||||
|
|
@ -188,6 +186,7 @@ void handle_tablet_pad_strip(struct libinput_event *event,
|
||||||
.strip = libinput_event_tablet_pad_get_strip_number(pevent),
|
.strip = libinput_event_tablet_pad_get_strip_number(pevent),
|
||||||
.position = libinput_event_tablet_pad_get_strip_position(pevent),
|
.position = libinput_event_tablet_pad_get_strip_position(pevent),
|
||||||
.mode = libinput_event_tablet_pad_get_mode(pevent),
|
.mode = libinput_event_tablet_pad_get_mode(pevent),
|
||||||
|
.source = WLR_TABLET_PAD_STRIP_SOURCE_UNKNOWN,
|
||||||
};
|
};
|
||||||
switch (libinput_event_tablet_pad_get_strip_source(pevent)) {
|
switch (libinput_event_tablet_pad_get_strip_source(pevent)) {
|
||||||
case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:
|
case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ void init_device_tablet(struct wlr_libinput_input_device *dev) {
|
||||||
struct udev_device *udev = libinput_device_get_udev_device(dev->handle);
|
struct udev_device *udev = libinput_device_get_udev_device(dev->handle);
|
||||||
char **dst = wl_array_add(&wlr_tablet->paths, sizeof(char *));
|
char **dst = wl_array_add(&wlr_tablet->paths, sizeof(char *));
|
||||||
*dst = strdup(udev_device_get_syspath(udev));
|
*dst = strdup(udev_device_get_syspath(udev));
|
||||||
|
udev_device_unref(udev);
|
||||||
|
|
||||||
wl_list_init(&dev->tablet_tools);
|
wl_list_init(&dev->tablet_tools);
|
||||||
}
|
}
|
||||||
|
|
@ -67,27 +68,61 @@ struct wlr_libinput_input_device *device_from_tablet(
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum wlr_tablet_tool_type wlr_type_from_libinput_type(
|
static bool type_from_libinput(enum libinput_tablet_tool_type type,
|
||||||
enum libinput_tablet_tool_type value) {
|
enum wlr_tablet_tool_type *out) {
|
||||||
switch (value) {
|
switch (type) {
|
||||||
case LIBINPUT_TABLET_TOOL_TYPE_PEN:
|
case LIBINPUT_TABLET_TOOL_TYPE_PEN:
|
||||||
return WLR_TABLET_TOOL_TYPE_PEN;
|
*out = WLR_TABLET_TOOL_TYPE_PEN;
|
||||||
|
return true;
|
||||||
case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
|
case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
|
||||||
return WLR_TABLET_TOOL_TYPE_ERASER;
|
*out = WLR_TABLET_TOOL_TYPE_ERASER;
|
||||||
|
return true;
|
||||||
case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
|
case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
|
||||||
return WLR_TABLET_TOOL_TYPE_BRUSH;
|
*out = WLR_TABLET_TOOL_TYPE_BRUSH;
|
||||||
|
return true;
|
||||||
case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
|
case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
|
||||||
return WLR_TABLET_TOOL_TYPE_PENCIL;
|
*out = WLR_TABLET_TOOL_TYPE_PENCIL;
|
||||||
|
return true;
|
||||||
case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
|
case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
|
||||||
return WLR_TABLET_TOOL_TYPE_AIRBRUSH;
|
*out = WLR_TABLET_TOOL_TYPE_AIRBRUSH;
|
||||||
|
return true;
|
||||||
case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
|
case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
|
||||||
return WLR_TABLET_TOOL_TYPE_MOUSE;
|
*out = WLR_TABLET_TOOL_TYPE_MOUSE;
|
||||||
|
return true;
|
||||||
case LIBINPUT_TABLET_TOOL_TYPE_LENS:
|
case LIBINPUT_TABLET_TOOL_TYPE_LENS:
|
||||||
return WLR_TABLET_TOOL_TYPE_LENS;
|
*out = WLR_TABLET_TOOL_TYPE_LENS;
|
||||||
|
return true;
|
||||||
case LIBINPUT_TABLET_TOOL_TYPE_TOTEM:
|
case LIBINPUT_TABLET_TOOL_TYPE_TOTEM:
|
||||||
return WLR_TABLET_TOOL_TYPE_TOTEM;
|
*out = WLR_TABLET_TOOL_TYPE_TOTEM;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
abort(); // unreachable
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool proximity_state_from_libinput(enum libinput_tablet_tool_proximity_state state,
|
||||||
|
enum wlr_tablet_tool_proximity_state *out) {
|
||||||
|
switch (state) {
|
||||||
|
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT:
|
||||||
|
*out = WLR_TABLET_TOOL_PROXIMITY_OUT;
|
||||||
|
return true;
|
||||||
|
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN:
|
||||||
|
*out = WLR_TABLET_TOOL_PROXIMITY_IN;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tip_state_from_libinput(enum libinput_tablet_tool_tip_state state,
|
||||||
|
enum wlr_tablet_tool_tip_state *out) {
|
||||||
|
switch (state) {
|
||||||
|
case LIBINPUT_TABLET_TOOL_TIP_UP:
|
||||||
|
*out = WLR_TABLET_TOOL_TIP_UP;
|
||||||
|
return true;
|
||||||
|
case LIBINPUT_TABLET_TOOL_TIP_DOWN:
|
||||||
|
*out = WLR_TABLET_TOOL_TIP_DOWN;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tablet_tool *get_tablet_tool(
|
static struct tablet_tool *get_tablet_tool(
|
||||||
|
|
@ -99,14 +134,19 @@ static struct tablet_tool *get_tablet_tool(
|
||||||
return tool;
|
return tool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum wlr_tablet_tool_type type;
|
||||||
|
if (!type_from_libinput(libinput_tablet_tool_get_type(libinput_tool), &type)) {
|
||||||
|
wlr_log(WLR_DEBUG, "Unhandled libinput tablet tool type");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
tool = calloc(1, sizeof(*tool));
|
tool = calloc(1, sizeof(*tool));
|
||||||
if (tool == NULL) {
|
if (tool == NULL) {
|
||||||
wlr_log_errno(WLR_ERROR, "failed to allocate wlr_libinput_tablet_tool");
|
wlr_log_errno(WLR_ERROR, "failed to allocate wlr_libinput_tablet_tool");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tool->wlr_tool.type = wlr_type_from_libinput_type(
|
tool->wlr_tool.type = type;
|
||||||
libinput_tablet_tool_get_type(libinput_tool));
|
|
||||||
tool->wlr_tool.hardware_serial =
|
tool->wlr_tool.hardware_serial =
|
||||||
libinput_tablet_tool_get_serial(libinput_tool);
|
libinput_tablet_tool_get_serial(libinput_tool);
|
||||||
tool->wlr_tool.hardware_wacom =
|
tool->wlr_tool.hardware_wacom =
|
||||||
|
|
@ -198,14 +238,12 @@ void handle_tablet_tool_proximity(struct libinput_event *event,
|
||||||
.y = libinput_event_tablet_tool_get_y_transformed(tevent, 1),
|
.y = libinput_event_tablet_tool_get_y_transformed(tevent, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (libinput_event_tablet_tool_get_proximity_state(tevent)) {
|
if (!proximity_state_from_libinput(libinput_event_tablet_tool_get_proximity_state(tevent),
|
||||||
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT:
|
&wlr_event.state)) {
|
||||||
wlr_event.state = WLR_TABLET_TOOL_PROXIMITY_OUT;
|
wlr_log(WLR_DEBUG, "Unhandled libinput tablet tool proximity state");
|
||||||
break;
|
return;
|
||||||
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN:
|
|
||||||
wlr_event.state = WLR_TABLET_TOOL_PROXIMITY_IN;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_signal_emit_mutable(&wlr_tablet->events.proximity, &wlr_event);
|
wl_signal_emit_mutable(&wlr_tablet->events.proximity, &wlr_event);
|
||||||
|
|
||||||
if (libinput_event_tablet_tool_get_proximity_state(tevent) ==
|
if (libinput_event_tablet_tool_get_proximity_state(tevent) ==
|
||||||
|
|
@ -240,14 +278,11 @@ void handle_tablet_tool_tip(struct libinput_event *event,
|
||||||
.y = libinput_event_tablet_tool_get_y_transformed(tevent, 1),
|
.y = libinput_event_tablet_tool_get_y_transformed(tevent, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (libinput_event_tablet_tool_get_tip_state(tevent)) {
|
if (!tip_state_from_libinput(libinput_event_tablet_tool_get_tip_state(tevent), &wlr_event.state)) {
|
||||||
case LIBINPUT_TABLET_TOOL_TIP_UP:
|
wlr_log(WLR_DEBUG, "Unhandled libinput tablet tool tip state");
|
||||||
wlr_event.state = WLR_TABLET_TOOL_TIP_UP;
|
return;
|
||||||
break;
|
|
||||||
case LIBINPUT_TABLET_TOOL_TIP_DOWN:
|
|
||||||
wlr_event.state = WLR_TABLET_TOOL_TIP_DOWN;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_signal_emit_mutable(&wlr_tablet->events.tip, &wlr_event);
|
wl_signal_emit_mutable(&wlr_tablet->events.tip, &wlr_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,13 +301,11 @@ void handle_tablet_tool_button(struct libinput_event *event,
|
||||||
.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)),
|
.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)),
|
||||||
.button = libinput_event_tablet_tool_get_button(tevent),
|
.button = libinput_event_tablet_tool_get_button(tevent),
|
||||||
};
|
};
|
||||||
switch (libinput_event_tablet_tool_get_button_state(tevent)) {
|
|
||||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
if (!button_state_from_libinput(libinput_event_tablet_tool_get_button_state(tevent), &wlr_event.state)) {
|
||||||
wlr_event.state = WLR_BUTTON_RELEASED;
|
wlr_log(WLR_DEBUG, "Unhandled libinput button state");
|
||||||
break;
|
return;
|
||||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
|
||||||
wlr_event.state = WLR_BUTTON_PRESSED;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_signal_emit_mutable(&wlr_tablet->events.button, &wlr_event);
|
wl_signal_emit_mutable(&wlr_tablet->events.button, &wlr_event);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,15 @@ static void handle_disable_seat(struct libseat *seat, void *data) {
|
||||||
|
|
||||||
static int libseat_event(int fd, uint32_t mask, void *data) {
|
static int libseat_event(int fd, uint32_t mask, void *data) {
|
||||||
struct wlr_session *session = data;
|
struct wlr_session *session = data;
|
||||||
|
if (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR)) {
|
||||||
|
if (mask & WL_EVENT_ERROR) {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to wait for libseat event");
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_INFO, "Failed to wait for libseat event");
|
||||||
|
}
|
||||||
|
wlr_session_destroy(session);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (libseat_dispatch(session->seat_handle, 0) == -1) {
|
if (libseat_dispatch(session->seat_handle, 0) == -1) {
|
||||||
wlr_log_errno(WLR_ERROR, "Failed to dispatch libseat");
|
wlr_log_errno(WLR_ERROR, "Failed to dispatch libseat");
|
||||||
wlr_session_destroy(session);
|
wlr_session_destroy(session);
|
||||||
|
|
@ -367,7 +376,10 @@ void wlr_session_close_file(struct wlr_session *session,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(wl_list_empty(&dev->events.change.listener_list));
|
assert(wl_list_empty(&dev->events.change.listener_list));
|
||||||
assert(wl_list_empty(&dev->events.remove.listener_list));
|
// TODO: assert that the "remove" listener list is empty as well. Listeners
|
||||||
|
// will typically call wlr_session_close_file() in response, and
|
||||||
|
// wl_signal_emit_mutable() installs two phantom listeners, so we'd count
|
||||||
|
// these two.
|
||||||
|
|
||||||
close(dev->fd);
|
close(dev->fd);
|
||||||
wl_list_remove(&dev->link);
|
wl_list_remove(&dev->link);
|
||||||
|
|
|
||||||
|
|
@ -132,4 +132,6 @@ void handle_tablet_pad_ring(struct libinput_event *event,
|
||||||
void handle_tablet_pad_strip(struct libinput_event *event,
|
void handle_tablet_pad_strip(struct libinput_event *event,
|
||||||
struct wlr_tablet_pad *tablet_pad);
|
struct wlr_tablet_pad *tablet_pad);
|
||||||
|
|
||||||
|
bool button_state_from_libinput(enum libinput_button_state state, enum wlr_button_state *out);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -433,10 +433,11 @@ void vulkan_reset_command_buffer(struct wlr_vk_command_buffer *cb);
|
||||||
bool vulkan_wait_command_buffer(struct wlr_vk_command_buffer *cb,
|
bool vulkan_wait_command_buffer(struct wlr_vk_command_buffer *cb,
|
||||||
struct wlr_vk_renderer *renderer);
|
struct wlr_vk_renderer *renderer);
|
||||||
|
|
||||||
bool vulkan_sync_render_buffer(struct wlr_vk_renderer *renderer,
|
bool vulkan_sync_render_pass_release(struct wlr_vk_renderer *renderer,
|
||||||
struct wlr_vk_render_buffer *render_buffer, struct wlr_vk_command_buffer *cb,
|
struct wlr_vk_render_pass *pass);
|
||||||
struct wlr_drm_syncobj_timeline *signal_timeline, uint64_t signal_point);
|
bool vulkan_sync_foreign_texture_acquire(struct wlr_vk_texture *texture,
|
||||||
bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
|
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]);
|
||||||
|
bool vulkan_sync_render_buffer_acquire(struct wlr_vk_render_buffer *render_buffer,
|
||||||
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]);
|
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]);
|
||||||
|
|
||||||
bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer,
|
bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer,
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ void output_defer_present(struct wlr_output *output, struct wlr_output_event_pre
|
||||||
|
|
||||||
bool output_prepare_commit(struct wlr_output *output, const struct wlr_output_state *state);
|
bool output_prepare_commit(struct wlr_output *output, const struct wlr_output_state *state);
|
||||||
void output_apply_commit(struct wlr_output *output, const struct wlr_output_state *state);
|
void output_apply_commit(struct wlr_output *output, const struct wlr_output_state *state);
|
||||||
|
void output_send_commit_event(struct wlr_output *output, const struct wlr_output_state *state);
|
||||||
|
|
||||||
void output_state_get_buffer_src_box(const struct wlr_output_state *state,
|
void output_state_get_buffer_src_box(const struct wlr_output_state *state,
|
||||||
struct wlr_fbox *out);
|
struct wlr_fbox *out);
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,6 @@ struct wlr_drm_lease_connector_v1 {
|
||||||
|
|
||||||
struct wlr_output *output;
|
struct wlr_output *output;
|
||||||
struct wlr_drm_lease_device_v1 *device;
|
struct wlr_drm_lease_device_v1 *device;
|
||||||
/** NULL if no client is currently leasing this connector */
|
|
||||||
struct wlr_drm_lease_v1 *active_lease;
|
|
||||||
|
|
||||||
struct wl_list link; // wlr_drm_lease_device_v1.connectors
|
struct wl_list link; // wlr_drm_lease_device_v1.connectors
|
||||||
|
|
||||||
|
|
@ -93,9 +91,6 @@ struct wlr_drm_lease_v1 {
|
||||||
|
|
||||||
struct wlr_drm_lease_device_v1 *device;
|
struct wlr_drm_lease_device_v1 *device;
|
||||||
|
|
||||||
struct wlr_drm_lease_connector_v1 **connectors;
|
|
||||||
size_t n_connectors;
|
|
||||||
|
|
||||||
struct wl_list link; // wlr_drm_lease_device_v1.leases
|
struct wl_list link; // wlr_drm_lease_device_v1.leases
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ struct wlr_switch {
|
||||||
enum wlr_switch_type {
|
enum wlr_switch_type {
|
||||||
WLR_SWITCH_TYPE_LID,
|
WLR_SWITCH_TYPE_LID,
|
||||||
WLR_SWITCH_TYPE_TABLET_MODE,
|
WLR_SWITCH_TYPE_TABLET_MODE,
|
||||||
|
WLR_SWITCH_TYPE_KEYPAD_SLIDE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum wlr_switch_state {
|
enum wlr_switch_state {
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ struct wlr_xwm {
|
||||||
struct wl_listener drop_focus_destroy;
|
struct wl_listener drop_focus_destroy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// xwm_create takes ownership of wm_fd and will close it under all circumstances.
|
||||||
struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd);
|
struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland, int wm_fd);
|
||||||
|
|
||||||
void xwm_destroy(struct wlr_xwm *xwm);
|
void xwm_destroy(struct wlr_xwm *xwm);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
project(
|
project(
|
||||||
'wlroots',
|
'wlroots',
|
||||||
'c',
|
'c',
|
||||||
version: '0.19.0',
|
version: '0.19.3',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>=1.3',
|
meson_version: '>=1.3',
|
||||||
default_options: [
|
default_options: [
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ static struct wlr_shm_buffer *shm_buffer_from_buffer(
|
||||||
|
|
||||||
static void buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
static void buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
||||||
struct wlr_shm_buffer *buffer = shm_buffer_from_buffer(wlr_buffer);
|
struct wlr_shm_buffer *buffer = shm_buffer_from_buffer(wlr_buffer);
|
||||||
|
wlr_buffer_finish(wlr_buffer);
|
||||||
munmap(buffer->data, buffer->size);
|
munmap(buffer->data, buffer->size);
|
||||||
close(buffer->shm.fd);
|
close(buffer->shm.fd);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ static bool buffer_get_dmabuf(struct wlr_buffer *wlr_buffer, struct wlr_dmabuf_a
|
||||||
|
|
||||||
static void buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
static void buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
||||||
struct wlr_udmabuf_buffer *buffer = wl_container_of(wlr_buffer, buffer, base);
|
struct wlr_udmabuf_buffer *buffer = wl_container_of(wlr_buffer, buffer, base);
|
||||||
|
wlr_buffer_finish(wlr_buffer);
|
||||||
wlr_dmabuf_attributes_finish(&buffer->dmabuf);
|
wlr_dmabuf_attributes_finish(&buffer->dmabuf);
|
||||||
close(buffer->shm.fd);
|
close(buffer->shm.fd);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
|
||||||
20
render/egl.c
20
render/egl.c
|
|
@ -260,7 +260,8 @@ static struct wlr_egl *egl_create(void) {
|
||||||
return egl;
|
return egl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display) {
|
static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display,
|
||||||
|
bool allow_software) {
|
||||||
egl->display = display;
|
egl->display = display;
|
||||||
|
|
||||||
EGLint major, minor;
|
EGLint major, minor;
|
||||||
|
|
@ -326,9 +327,8 @@ static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display) {
|
||||||
|
|
||||||
// The only way a non-DRM device is selected is when the user
|
// The only way a non-DRM device is selected is when the user
|
||||||
// explicitly picks software rendering
|
// explicitly picks software rendering
|
||||||
if (check_egl_ext(device_exts_str, "EGL_MESA_device_software") &&
|
if (check_egl_ext(device_exts_str, "EGL_MESA_device_software")) {
|
||||||
egl->exts.EXT_device_drm) {
|
if (allow_software || env_parse_bool("WLR_RENDERER_ALLOW_SOFTWARE")) {
|
||||||
if (env_parse_bool("WLR_RENDERER_ALLOW_SOFTWARE")) {
|
|
||||||
wlr_log(WLR_INFO, "Using software rendering");
|
wlr_log(WLR_INFO, "Using software rendering");
|
||||||
} else {
|
} else {
|
||||||
wlr_log(WLR_ERROR, "Software rendering detected, please use "
|
wlr_log(WLR_ERROR, "Software rendering detected, please use "
|
||||||
|
|
@ -382,7 +382,7 @@ static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool egl_init(struct wlr_egl *egl, EGLenum platform,
|
static bool egl_init(struct wlr_egl *egl, EGLenum platform,
|
||||||
void *remote_display) {
|
void *remote_display, bool allow_software) {
|
||||||
EGLint display_attribs[3] = {0};
|
EGLint display_attribs[3] = {0};
|
||||||
size_t display_attribs_len = 0;
|
size_t display_attribs_len = 0;
|
||||||
|
|
||||||
|
|
@ -401,7 +401,7 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!egl_init_display(egl, display)) {
|
if (!egl_init_display(egl, display, allow_software)) {
|
||||||
if (egl->exts.KHR_display_reference) {
|
if (egl->exts.KHR_display_reference) {
|
||||||
eglTerminate(display);
|
eglTerminate(display);
|
||||||
}
|
}
|
||||||
|
|
@ -556,6 +556,8 @@ static int open_render_node(int drm_fd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
|
struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
|
||||||
|
bool allow_software = drm_fd < 0;
|
||||||
|
|
||||||
struct wlr_egl *egl = egl_create();
|
struct wlr_egl *egl = egl_create();
|
||||||
if (egl == NULL) {
|
if (egl == NULL) {
|
||||||
wlr_log(WLR_ERROR, "Failed to create EGL context");
|
wlr_log(WLR_ERROR, "Failed to create EGL context");
|
||||||
|
|
@ -569,7 +571,7 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
|
||||||
*/
|
*/
|
||||||
EGLDeviceEXT egl_device = get_egl_device_from_drm_fd(egl, drm_fd);
|
EGLDeviceEXT egl_device = get_egl_device_from_drm_fd(egl, drm_fd);
|
||||||
if (egl_device != EGL_NO_DEVICE_EXT) {
|
if (egl_device != EGL_NO_DEVICE_EXT) {
|
||||||
if (egl_init(egl, EGL_PLATFORM_DEVICE_EXT, egl_device)) {
|
if (egl_init(egl, EGL_PLATFORM_DEVICE_EXT, egl_device, allow_software)) {
|
||||||
wlr_log(WLR_DEBUG, "Using EGL_PLATFORM_DEVICE_EXT");
|
wlr_log(WLR_DEBUG, "Using EGL_PLATFORM_DEVICE_EXT");
|
||||||
return egl;
|
return egl;
|
||||||
}
|
}
|
||||||
|
|
@ -594,7 +596,7 @@ struct wlr_egl *wlr_egl_create_with_drm_fd(int drm_fd) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (egl_init(egl, EGL_PLATFORM_GBM_KHR, egl->gbm_device)) {
|
if (egl_init(egl, EGL_PLATFORM_GBM_KHR, egl->gbm_device, allow_software)) {
|
||||||
wlr_log(WLR_DEBUG, "Using EGL_PLATFORM_GBM_KHR");
|
wlr_log(WLR_DEBUG, "Using EGL_PLATFORM_GBM_KHR");
|
||||||
return egl;
|
return egl;
|
||||||
}
|
}
|
||||||
|
|
@ -633,7 +635,7 @@ struct wlr_egl *wlr_egl_create_with_context(EGLDisplay display,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!egl_init_display(egl, display)) {
|
if (!egl_init_display(egl, display, true)) {
|
||||||
free(egl);
|
free(egl);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ void wlr_render_pass_add_texture(struct wlr_render_pass *render_pass,
|
||||||
if (!wlr_fbox_empty(&options->src_box)) {
|
if (!wlr_fbox_empty(&options->src_box)) {
|
||||||
const struct wlr_fbox *box = &options->src_box;
|
const struct wlr_fbox *box = &options->src_box;
|
||||||
assert(box->x >= 0 && box->y >= 0 &&
|
assert(box->x >= 0 && box->y >= 0 &&
|
||||||
box->x + box->width <= options->texture->width &&
|
(uint32_t)(box->x + box->width) <= options->texture->width &&
|
||||||
box->y + box->height <= options->texture->height);
|
(uint32_t)(box->y + box->height) <= options->texture->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_pass->impl->add_texture(render_pass, options);
|
render_pass->impl->add_texture(render_pass, options);
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,40 @@ static VkSemaphore render_pass_wait_sync_file(struct wlr_vk_render_pass *pass,
|
||||||
return *sem_ptr;
|
return *sem_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool render_pass_wait_render_buffer(struct wlr_vk_render_pass *pass,
|
||||||
|
VkSemaphoreSubmitInfoKHR *render_wait, uint32_t *render_wait_len_ptr) {
|
||||||
|
int sync_file_fds[WLR_DMABUF_MAX_PLANES];
|
||||||
|
for (size_t i = 0; i < WLR_DMABUF_MAX_PLANES; i++) {
|
||||||
|
sync_file_fds[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vulkan_sync_render_buffer_acquire(pass->render_buffer, sync_file_fds)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < WLR_DMABUF_MAX_PLANES; i++) {
|
||||||
|
if (sync_file_fds[i] < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSemaphore sem = render_pass_wait_sync_file(pass, *render_wait_len_ptr, sync_file_fds[i]);
|
||||||
|
if (sem == VK_NULL_HANDLE) {
|
||||||
|
close(sync_file_fds[i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
render_wait[*render_wait_len_ptr] = (VkSemaphoreSubmitInfoKHR){
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR,
|
||||||
|
.semaphore = sem,
|
||||||
|
.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR,
|
||||||
|
};
|
||||||
|
|
||||||
|
(*render_wait_len_ptr)++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass);
|
struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass);
|
||||||
struct wlr_vk_renderer *renderer = pass->renderer;
|
struct wlr_vk_renderer *renderer = pass->renderer;
|
||||||
|
|
@ -236,7 +270,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
vkCmdEndRenderPass(render_cb->vk);
|
vkCmdEndRenderPass(render_cb->vk);
|
||||||
|
|
||||||
size_t pass_textures_len = pass->textures.size / sizeof(struct wlr_vk_render_pass_texture);
|
size_t pass_textures_len = pass->textures.size / sizeof(struct wlr_vk_render_pass_texture);
|
||||||
size_t render_wait_cap = pass_textures_len * WLR_DMABUF_MAX_PLANES;
|
size_t render_wait_cap = (1 + pass_textures_len) * WLR_DMABUF_MAX_PLANES;
|
||||||
render_wait = calloc(render_wait_cap, sizeof(*render_wait));
|
render_wait = calloc(render_wait_cap, sizeof(*render_wait));
|
||||||
if (render_wait == NULL) {
|
if (render_wait == NULL) {
|
||||||
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||||
|
|
@ -314,7 +348,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
sync_file_fds[0] = sync_file_fd;
|
sync_file_fds[0] = sync_file_fd;
|
||||||
} else {
|
} else {
|
||||||
struct wlr_vk_texture *texture = pass_texture->texture;
|
struct wlr_vk_texture *texture = pass_texture->texture;
|
||||||
if (!vulkan_sync_foreign_texture(texture, sync_file_fds)) {
|
if (!vulkan_sync_foreign_texture_acquire(texture, sync_file_fds)) {
|
||||||
wlr_log(WLR_ERROR, "Failed to wait for foreign texture DMA-BUF fence");
|
wlr_log(WLR_ERROR, "Failed to wait for foreign texture DMA-BUF fence");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -341,6 +375,10 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!render_pass_wait_render_buffer(pass, render_wait, &render_wait_len)) {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to wait for render buffer DMA-BUF fence");
|
||||||
|
}
|
||||||
|
|
||||||
// also add acquire/release barriers for the current render buffer
|
// also add acquire/release barriers for the current render buffer
|
||||||
VkImageLayout src_layout = VK_IMAGE_LAYOUT_GENERAL;
|
VkImageLayout src_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
if (pass->srgb_pathway) {
|
if (pass->srgb_pathway) {
|
||||||
|
|
@ -538,8 +576,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
||||||
wl_list_insert(&stage_cb->stage_buffers, &stage_buf->link);
|
wl_list_insert(&stage_cb->stage_buffers, &stage_buf->link);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vulkan_sync_render_buffer(renderer, render_buffer, render_cb,
|
if (!vulkan_sync_render_pass_release(renderer, pass)) {
|
||||||
pass->signal_timeline, pass->signal_point)) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to sync render buffer");
|
wlr_log(WLR_ERROR, "Failed to sync render buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,16 +66,35 @@ static struct wlr_vk_descriptor_pool *alloc_ds(
|
||||||
struct wl_list *pool_list, size_t *last_pool_size) {
|
struct wl_list *pool_list, size_t *last_pool_size) {
|
||||||
VkResult res;
|
VkResult res;
|
||||||
|
|
||||||
bool found = false;
|
VkDescriptorSetAllocateInfo ds_info = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||||
|
.descriptorSetCount = 1,
|
||||||
|
.pSetLayouts = layout,
|
||||||
|
};
|
||||||
|
|
||||||
struct wlr_vk_descriptor_pool *pool;
|
struct wlr_vk_descriptor_pool *pool;
|
||||||
wl_list_for_each(pool, pool_list, link) {
|
wl_list_for_each(pool, pool_list, link) {
|
||||||
if (pool->free > 0) {
|
if (pool->free > 0) {
|
||||||
found = true;
|
ds_info.descriptorPool = pool->pool;
|
||||||
break;
|
res = vkAllocateDescriptorSets(renderer->dev->dev, &ds_info, ds);
|
||||||
|
switch (res) {
|
||||||
|
case VK_ERROR_FRAGMENTED_POOL:
|
||||||
|
case VK_ERROR_OUT_OF_POOL_MEMORY:
|
||||||
|
// Descriptor sets with more than one descriptor can cause us
|
||||||
|
// to run out of pool memory early or lead to fragmentation
|
||||||
|
// that makes the pool unable to service our allocation
|
||||||
|
// request. Try the next pool or allocate a new one.
|
||||||
|
continue;
|
||||||
|
case VK_SUCCESS:
|
||||||
|
--pool->free;
|
||||||
|
return pool;
|
||||||
|
default:
|
||||||
|
wlr_vk_error("vkAllocateDescriptorSets", res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) { // create new pool
|
|
||||||
pool = calloc(1, sizeof(*pool));
|
pool = calloc(1, sizeof(*pool));
|
||||||
if (!pool) {
|
if (!pool) {
|
||||||
wlr_log_errno(WLR_ERROR, "allocation failed");
|
wlr_log_errno(WLR_ERROR, "allocation failed");
|
||||||
|
|
@ -111,14 +130,8 @@ static struct wlr_vk_descriptor_pool *alloc_ds(
|
||||||
|
|
||||||
*last_pool_size = count;
|
*last_pool_size = count;
|
||||||
wl_list_insert(pool_list, &pool->link);
|
wl_list_insert(pool_list, &pool->link);
|
||||||
}
|
|
||||||
|
|
||||||
VkDescriptorSetAllocateInfo ds_info = {
|
ds_info.descriptorPool = pool->pool;
|
||||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
|
||||||
.descriptorSetCount = 1,
|
|
||||||
.pSetLayouts = layout,
|
|
||||||
.descriptorPool = pool->pool,
|
|
||||||
};
|
|
||||||
res = vkAllocateDescriptorSets(renderer->dev->dev, &ds_info, ds);
|
res = vkAllocateDescriptorSets(renderer->dev->dev, &ds_info, ds);
|
||||||
if (res != VK_SUCCESS) {
|
if (res != VK_SUCCESS) {
|
||||||
wlr_vk_error("vkAllocateDescriptorSets", res);
|
wlr_vk_error("vkAllocateDescriptorSets", res);
|
||||||
|
|
@ -934,13 +947,11 @@ static struct wlr_vk_render_buffer *get_render_buffer(
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
|
static bool buffer_export_sync_file(struct wlr_vk_renderer *renderer, struct wlr_buffer *buffer,
|
||||||
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]) {
|
uint32_t flags, int sync_file_fds[static WLR_DMABUF_MAX_PLANES]) {
|
||||||
struct wlr_vk_renderer *renderer = texture->renderer;
|
|
||||||
|
|
||||||
struct wlr_dmabuf_attributes dmabuf = {0};
|
struct wlr_dmabuf_attributes dmabuf = {0};
|
||||||
if (!wlr_buffer_get_dmabuf(texture->buffer, &dmabuf)) {
|
if (!wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
|
||||||
wlr_log(WLR_ERROR, "Failed to get texture DMA-BUF");
|
wlr_log(WLR_ERROR, "wlr_buffer_get_dmabuf() failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -950,7 +961,7 @@ bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
|
||||||
for (int i = 0; i < dmabuf.n_planes; i++) {
|
for (int i = 0; i < dmabuf.n_planes; i++) {
|
||||||
struct pollfd pollfd = {
|
struct pollfd pollfd = {
|
||||||
.fd = dmabuf.fd[i],
|
.fd = dmabuf.fd[i],
|
||||||
.events = POLLIN,
|
.events = (flags & DMA_BUF_SYNC_WRITE) ? POLLOUT : POLLIN,
|
||||||
};
|
};
|
||||||
int timeout_ms = 1000;
|
int timeout_ms = 1000;
|
||||||
int ret = poll(&pollfd, 1, timeout_ms);
|
int ret = poll(&pollfd, 1, timeout_ms);
|
||||||
|
|
@ -967,7 +978,7 @@ bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < dmabuf.n_planes; i++) {
|
for (int i = 0; i < dmabuf.n_planes; i++) {
|
||||||
int sync_file_fd = dmabuf_export_sync_file(dmabuf.fd[i], DMA_BUF_SYNC_READ);
|
int sync_file_fd = dmabuf_export_sync_file(dmabuf.fd[i], flags);
|
||||||
if (sync_file_fd < 0) {
|
if (sync_file_fd < 0) {
|
||||||
wlr_log(WLR_ERROR, "Failed to extract DMA-BUF fence");
|
wlr_log(WLR_ERROR, "Failed to extract DMA-BUF fence");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -979,12 +990,40 @@ bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vulkan_sync_render_buffer(struct wlr_vk_renderer *renderer,
|
bool vulkan_sync_foreign_texture_acquire(struct wlr_vk_texture *texture,
|
||||||
struct wlr_vk_render_buffer *render_buffer, struct wlr_vk_command_buffer *cb,
|
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]) {
|
||||||
struct wlr_drm_syncobj_timeline *signal_timeline, uint64_t signal_point) {
|
return buffer_export_sync_file(texture->renderer, texture->buffer, DMA_BUF_SYNC_READ, sync_file_fds);
|
||||||
VkResult res;
|
}
|
||||||
|
|
||||||
if (!renderer->dev->implicit_sync_interop && signal_timeline == NULL) {
|
bool vulkan_sync_render_buffer_acquire(struct wlr_vk_render_buffer *render_buffer,
|
||||||
|
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]) {
|
||||||
|
return buffer_export_sync_file(render_buffer->renderer, render_buffer->wlr_buffer,
|
||||||
|
DMA_BUF_SYNC_WRITE, sync_file_fds);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool buffer_import_sync_file(struct wlr_buffer *buffer, uint32_t flags, int sync_file_fd) {
|
||||||
|
struct wlr_dmabuf_attributes dmabuf = {0};
|
||||||
|
if (!wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
|
||||||
|
wlr_log(WLR_ERROR, "wlr_buffer_get_dmabuf() failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < dmabuf.n_planes; i++) {
|
||||||
|
if (!dmabuf_import_sync_file(dmabuf.fd[i], flags,
|
||||||
|
sync_file_fd)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool vulkan_sync_render_pass_release(struct wlr_vk_renderer *renderer,
|
||||||
|
struct wlr_vk_render_pass *pass) {
|
||||||
|
VkResult res;
|
||||||
|
struct wlr_vk_command_buffer *cb = pass->command_buffer;
|
||||||
|
|
||||||
|
if (!renderer->dev->implicit_sync_interop && pass->signal_timeline == NULL) {
|
||||||
// We have no choice but to block here sadly
|
// We have no choice but to block here sadly
|
||||||
return vulkan_wait_command_buffer(cb, renderer);
|
return vulkan_wait_command_buffer(cb, renderer);
|
||||||
}
|
}
|
||||||
|
|
@ -1006,21 +1045,19 @@ bool vulkan_sync_render_buffer(struct wlr_vk_renderer *renderer,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
if (signal_timeline != NULL) {
|
if (pass->signal_timeline != NULL) {
|
||||||
if (!wlr_drm_syncobj_timeline_import_sync_file(signal_timeline,
|
if (!wlr_drm_syncobj_timeline_import_sync_file(pass->signal_timeline,
|
||||||
signal_point, sync_file_fd)) {
|
pass->signal_point, sync_file_fd)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct wlr_dmabuf_attributes dmabuf = {0};
|
if (!buffer_import_sync_file(pass->render_buffer->wlr_buffer, DMA_BUF_SYNC_WRITE, sync_file_fd)) {
|
||||||
if (!wlr_buffer_get_dmabuf(render_buffer->wlr_buffer, &dmabuf)) {
|
|
||||||
wlr_log(WLR_ERROR, "wlr_buffer_get_dmabuf failed");
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < dmabuf.n_planes; i++) {
|
struct wlr_vk_render_pass_texture *pass_texture;
|
||||||
if (!dmabuf_import_sync_file(dmabuf.fd[i], DMA_BUF_SYNC_WRITE,
|
wl_array_for_each(pass_texture, &pass->textures) {
|
||||||
sync_file_fd)) {
|
if (!buffer_import_sync_file(pass_texture->texture->buffer, DMA_BUF_SYNC_READ, sync_file_fd)) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ xdg-shell-protocol.h:
|
||||||
tinywl.o: tinywl.c xdg-shell-protocol.h
|
tinywl.o: tinywl.c xdg-shell-protocol.h
|
||||||
$(CC) -c $< -g -Werror $(CFLAGS) -I. -DWLR_USE_UNSTABLE -o $@
|
$(CC) -c $< -g -Werror $(CFLAGS) -I. -DWLR_USE_UNSTABLE -o $@
|
||||||
tinywl: tinywl.o
|
tinywl: tinywl.o
|
||||||
$(CC) $^ $> -g -Werror $(CFLAGS) $(LDFLAGS) $(LIBS) -o $@
|
$(CC) $^ -g -Werror $(CFLAGS) $(LDFLAGS) $(LIBS) -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f tinywl tinywl.o xdg-shell-protocol.h
|
rm -f tinywl tinywl.o xdg-shell-protocol.h
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,10 @@ static const struct wlr_ext_image_capture_source_v1_interface output_source_impl
|
||||||
static void source_update_buffer_constraints(struct wlr_ext_output_image_capture_source_v1 *source) {
|
static void source_update_buffer_constraints(struct wlr_ext_output_image_capture_source_v1 *source) {
|
||||||
struct wlr_output *output = source->output;
|
struct wlr_output *output = source->output;
|
||||||
|
|
||||||
|
if (!output->enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!wlr_output_configure_primary_swapchain(output, NULL, &output->swapchain)) {
|
if (!wlr_output_configure_primary_swapchain(output, NULL, &output->swapchain)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +124,8 @@ static void source_handle_output_commit(struct wl_listener *listener,
|
||||||
struct wlr_ext_output_image_capture_source_v1 *source = wl_container_of(listener, source, output_commit);
|
struct wlr_ext_output_image_capture_source_v1 *source = wl_container_of(listener, source, output_commit);
|
||||||
struct wlr_output_event_commit *event = data;
|
struct wlr_output_event_commit *event = data;
|
||||||
|
|
||||||
if (event->state->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_RENDER_FORMAT)) {
|
if (event->state->committed & (WLR_OUTPUT_STATE_MODE |
|
||||||
|
WLR_OUTPUT_STATE_RENDER_FORMAT | WLR_OUTPUT_STATE_ENABLED)) {
|
||||||
source_update_buffer_constraints(source);
|
source_update_buffer_constraints(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -283,7 +288,8 @@ static void output_cursor_source_copy_frame(struct wlr_ext_image_capture_source_
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
wlr_ext_image_copy_capture_frame_v1_ready(frame, WL_OUTPUT_TRANSFORM_NORMAL, &now);
|
wlr_ext_image_copy_capture_frame_v1_ready(frame,
|
||||||
|
cursor_source->output->transform, &now);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wlr_ext_image_capture_source_v1_interface output_cursor_source_impl = {
|
static const struct wlr_ext_image_capture_source_v1_interface output_cursor_source_impl = {
|
||||||
|
|
|
||||||
|
|
@ -288,18 +288,10 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor)
|
||||||
static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
|
static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) {
|
||||||
struct wlr_output *output = cursor->output;
|
struct wlr_output *output = cursor->output;
|
||||||
|
|
||||||
if (!output->impl->set_cursor ||
|
if (!output->impl->set_cursor || output->software_cursor_locks > 0) {
|
||||||
output->software_cursor_locks > 0) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_output_cursor *hwcur = output->hardware_cursor;
|
|
||||||
if (hwcur != NULL && hwcur != cursor) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
output->hardware_cursor = NULL;
|
|
||||||
|
|
||||||
struct wlr_texture *texture = cursor->texture;
|
struct wlr_texture *texture = cursor->texture;
|
||||||
|
|
||||||
// If the cursor was hidden or was a software cursor, the hardware
|
// If the cursor was hidden or was a software cursor, the hardware
|
||||||
|
|
@ -424,12 +416,15 @@ bool output_cursor_set_texture(struct wlr_output_cursor *cursor,
|
||||||
wl_list_init(&cursor->renderer_destroy.link);
|
wl_list_init(&cursor->renderer_destroy.link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (output->hardware_cursor == NULL || output->hardware_cursor == cursor) {
|
||||||
if (output_cursor_attempt_hardware(cursor)) {
|
if (output_cursor_attempt_hardware(cursor)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_log(WLR_DEBUG, "Falling back to software cursor on output '%s'", output->name);
|
wlr_log(WLR_DEBUG, "Falling back to software cursor on output '%s'", output->name);
|
||||||
output_disable_hardware_cursor(output);
|
output_disable_hardware_cursor(output);
|
||||||
|
}
|
||||||
|
|
||||||
output_cursor_damage_whole(cursor);
|
output_cursor_damage_whole(cursor);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -745,7 +745,9 @@ void output_apply_commit(struct wlr_output *output, const struct wlr_output_stat
|
||||||
}
|
}
|
||||||
|
|
||||||
output_apply_state(output, state);
|
output_apply_state(output, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void output_send_commit_event(struct wlr_output *output, const struct wlr_output_state *state) {
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
struct wlr_output_event_commit event = {
|
struct wlr_output_event_commit event = {
|
||||||
|
|
@ -787,6 +789,7 @@ bool wlr_output_commit_state(struct wlr_output *output,
|
||||||
}
|
}
|
||||||
|
|
||||||
output_apply_commit(output, &pending);
|
output_apply_commit(output, &pending);
|
||||||
|
output_send_commit_event(output, &pending);
|
||||||
|
|
||||||
if (new_back_buffer) {
|
if (new_back_buffer) {
|
||||||
wlr_buffer_unlock(pending.buffer);
|
wlr_buffer_unlock(pending.buffer);
|
||||||
|
|
|
||||||
|
|
@ -96,9 +96,12 @@ static void scene_buffer_unmark_client_buffer(struct wlr_scene_buffer *scene_buf
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(buffer->n_ignore_locks > 0);
|
// If the buffer was a single-pixel buffer where we cached its color
|
||||||
|
// then it won't have been marked as damage-allowed.
|
||||||
|
if (buffer->n_ignore_locks > 0) {
|
||||||
buffer->n_ignore_locks--;
|
buffer->n_ignore_locks--;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int min(int a, int b) {
|
static int min(int a, int b) {
|
||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
|
|
@ -165,7 +168,21 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) {
|
||||||
scene_buffer_unmark_client_buffer(scene_buffer);
|
scene_buffer_unmark_client_buffer(scene_buffer);
|
||||||
|
|
||||||
if (surface->buffer) {
|
if (surface->buffer) {
|
||||||
|
// If we've cached the buffer's single-pixel buffer color
|
||||||
|
// then any in-place updates to the texture wouldn't be
|
||||||
|
// reflected in rendering. So only allow in-place texture
|
||||||
|
// updates if it's not a single pixel buffer. Note that we
|
||||||
|
// can't use the cached scene_buffer->is_single_pixel_buffer
|
||||||
|
// because that's only set later on.
|
||||||
|
bool is_single_pixel_buffer = false;
|
||||||
|
if (surface->buffer->source != NULL) {
|
||||||
|
struct wlr_single_pixel_buffer_v1 *spb =
|
||||||
|
wlr_single_pixel_buffer_v1_try_from_buffer(surface->buffer->source);
|
||||||
|
is_single_pixel_buffer = spb != NULL;
|
||||||
|
}
|
||||||
|
if (!is_single_pixel_buffer) {
|
||||||
client_buffer_mark_next_can_damage(surface->buffer);
|
client_buffer_mark_next_can_damage(surface->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
struct wlr_linux_drm_syncobj_surface_v1_state *syncobj_surface_state =
|
struct wlr_linux_drm_syncobj_surface_v1_state *syncobj_surface_state =
|
||||||
wlr_linux_drm_syncobj_v1_get_surface_state(surface);
|
wlr_linux_drm_syncobj_v1_get_surface_state(surface);
|
||||||
|
|
@ -186,7 +203,8 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) {
|
||||||
&surface->buffer->base, &options);
|
&surface->buffer->base, &options);
|
||||||
|
|
||||||
if (syncobj_surface_state != NULL &&
|
if (syncobj_surface_state != NULL &&
|
||||||
(surface->current.committed & WLR_SURFACE_STATE_BUFFER)) {
|
(surface->current.committed & WLR_SURFACE_STATE_BUFFER) &&
|
||||||
|
surface->buffer->source != NULL) {
|
||||||
wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer(syncobj_surface_state,
|
wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer(syncobj_surface_state,
|
||||||
surface->buffer->source);
|
surface->buffer->source);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -530,10 +530,6 @@ static void cursor_output_cursor_update(struct wlr_cursor_output_cursor *output_
|
||||||
struct wlr_cursor *cur = output_cursor->cursor;
|
struct wlr_cursor *cur = output_cursor->cursor;
|
||||||
struct wlr_output *output = output_cursor->output_cursor->output;
|
struct wlr_output *output = output_cursor->output_cursor->output;
|
||||||
|
|
||||||
if (!output->enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor_output_cursor_reset_image(output_cursor);
|
cursor_output_cursor_reset_image(output_cursor);
|
||||||
|
|
||||||
if (cur->state->buffer != NULL) {
|
if (cur->state->buffer != NULL) {
|
||||||
|
|
@ -589,10 +585,11 @@ static void cursor_output_cursor_update(struct wlr_cursor_output_cursor *output_
|
||||||
&src_box, dst_width, dst_height, surface->current.transform,
|
&src_box, dst_width, dst_height, surface->current.transform,
|
||||||
hotspot_x, hotspot_y, wait_timeline, wait_point);
|
hotspot_x, hotspot_y, wait_timeline, wait_point);
|
||||||
|
|
||||||
if (syncobj_surface_state != NULL && surface->buffer != NULL &&
|
if (syncobj_surface_state != NULL &&
|
||||||
|
surface->buffer != NULL && surface->buffer->source != NULL &&
|
||||||
(surface->current.committed & WLR_SURFACE_STATE_BUFFER)) {
|
(surface->current.committed & WLR_SURFACE_STATE_BUFFER)) {
|
||||||
wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer(syncobj_surface_state,
|
wlr_linux_drm_syncobj_v1_state_signal_release_with_buffer(syncobj_surface_state,
|
||||||
&surface->buffer->base);
|
surface->buffer->source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output_cursor->output_cursor->visible) {
|
if (output_cursor->output_cursor->visible) {
|
||||||
|
|
|
||||||
|
|
@ -68,10 +68,6 @@ static void drm_lease_connector_v1_destroy(
|
||||||
|
|
||||||
wlr_log(WLR_DEBUG, "Destroying connector %s", connector->output->name);
|
wlr_log(WLR_DEBUG, "Destroying connector %s", connector->output->name);
|
||||||
|
|
||||||
if (connector->active_lease) {
|
|
||||||
wlr_drm_lease_terminate(connector->active_lease->drm_lease);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wl_resource *resource, *tmp;
|
struct wl_resource *resource, *tmp;
|
||||||
wl_resource_for_each_safe(resource, tmp, &connector->resources) {
|
wl_resource_for_each_safe(resource, tmp, &connector->resources) {
|
||||||
wp_drm_lease_connector_v1_send_withdrawn(resource);
|
wp_drm_lease_connector_v1_send_withdrawn(resource);
|
||||||
|
|
@ -140,14 +136,9 @@ static void lease_handle_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
wl_list_remove(&lease->destroy.link);
|
wl_list_remove(&lease->destroy.link);
|
||||||
|
|
||||||
for (size_t i = 0; i < lease->n_connectors; ++i) {
|
|
||||||
lease->connectors[i]->active_lease = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_remove(&lease->link);
|
wl_list_remove(&lease->link);
|
||||||
wl_resource_set_user_data(lease->resource, NULL);
|
wl_resource_set_user_data(lease->resource, NULL);
|
||||||
|
|
||||||
free(lease->connectors);
|
|
||||||
free(lease);
|
free(lease);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,20 +171,6 @@ struct wlr_drm_lease_v1 *wlr_drm_lease_request_v1_grant(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lease->connectors = calloc(request->n_connectors, sizeof(*lease->connectors));
|
|
||||||
if (!lease->connectors) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to allocate lease connectors list");
|
|
||||||
close(fd);
|
|
||||||
wp_drm_lease_v1_send_finished(lease->resource);
|
|
||||||
free(lease);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
lease->n_connectors = request->n_connectors;
|
|
||||||
for (size_t i = 0; i < request->n_connectors; ++i) {
|
|
||||||
lease->connectors[i] = request->connectors[i];
|
|
||||||
lease->connectors[i]->active_lease = lease;
|
|
||||||
}
|
|
||||||
|
|
||||||
lease->destroy.notify = lease_handle_destroy;
|
lease->destroy.notify = lease_handle_destroy;
|
||||||
wl_signal_add(&lease->drm_lease->events.destroy, &lease->destroy);
|
wl_signal_add(&lease->drm_lease->events.destroy, &lease->destroy);
|
||||||
|
|
||||||
|
|
@ -338,16 +315,6 @@ static void drm_lease_request_v1_handle_submit(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < request->n_connectors; ++i) {
|
|
||||||
struct wlr_drm_lease_connector_v1 *conn = request->connectors[i];
|
|
||||||
if (conn->active_lease) {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to create lease, connector %s has "
|
|
||||||
"already been leased", conn->output->name);
|
|
||||||
wp_drm_lease_v1_send_finished(lease_resource);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
request->lease_resource = lease_resource;
|
request->lease_resource = lease_resource;
|
||||||
|
|
||||||
wl_signal_emit_mutable(&request->device->manager->events.request,
|
wl_signal_emit_mutable(&request->device->manager->events.request,
|
||||||
|
|
@ -440,10 +407,6 @@ static struct wp_drm_lease_connector_v1_interface lease_connector_impl = {
|
||||||
static void drm_lease_connector_v1_send_to_client(
|
static void drm_lease_connector_v1_send_to_client(
|
||||||
struct wlr_drm_lease_connector_v1 *connector,
|
struct wlr_drm_lease_connector_v1 *connector,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
if (connector->active_lease) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wl_client *client = wl_resource_get_client(resource);
|
struct wl_client *client = wl_resource_get_client(resource);
|
||||||
|
|
||||||
uint32_t version = wl_resource_get_version(resource);
|
uint32_t version = wl_resource_get_version(resource);
|
||||||
|
|
@ -490,10 +453,12 @@ static void lease_device_bind(struct wl_client *wl_client, void *data,
|
||||||
if (!device) {
|
if (!device) {
|
||||||
wlr_log(WLR_DEBUG, "Failed to bind lease device, "
|
wlr_log(WLR_DEBUG, "Failed to bind lease device, "
|
||||||
"the wlr_drm_lease_device_v1 has been destroyed");
|
"the wlr_drm_lease_device_v1 has been destroyed");
|
||||||
|
wl_list_init(wl_resource_get_link(device_resource));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_resource_set_user_data(device_resource, device);
|
wl_resource_set_user_data(device_resource, device);
|
||||||
|
wl_list_insert(&device->resources, wl_resource_get_link(device_resource));
|
||||||
|
|
||||||
int fd = wlr_drm_backend_get_non_master_fd(device->backend);
|
int fd = wlr_drm_backend_get_non_master_fd(device->backend);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
|
@ -505,8 +470,6 @@ static void lease_device_bind(struct wl_client *wl_client, void *data,
|
||||||
wp_drm_lease_device_v1_send_drm_fd(device_resource, fd);
|
wp_drm_lease_device_v1_send_drm_fd(device_resource, fd);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
wl_list_insert(&device->resources, wl_resource_get_link(device_resource));
|
|
||||||
|
|
||||||
struct wlr_drm_lease_connector_v1 *connector;
|
struct wlr_drm_lease_connector_v1 *connector;
|
||||||
wl_list_for_each(connector, &device->connectors, link) {
|
wl_list_for_each(connector, &device->connectors, link) {
|
||||||
drm_lease_connector_v1_send_to_client(connector, device_resource);
|
drm_lease_connector_v1_send_to_client(connector, device_resource);
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ struct wlr_linux_drm_syncobj_surface_v1 {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_linux_drm_syncobj_surface_v1_commit {
|
struct wlr_linux_drm_syncobj_surface_v1_commit {
|
||||||
struct wlr_linux_drm_syncobj_surface_v1 *surface;
|
struct wlr_surface *surface;
|
||||||
struct wlr_drm_syncobj_timeline_waiter waiter;
|
struct wlr_drm_syncobj_timeline_waiter waiter;
|
||||||
uint32_t cached_seq;
|
uint32_t cached_seq;
|
||||||
|
|
||||||
|
|
@ -192,7 +192,7 @@ static struct wlr_linux_drm_syncobj_surface_v1 *surface_from_wlr_surface(
|
||||||
}
|
}
|
||||||
|
|
||||||
static void surface_commit_destroy(struct wlr_linux_drm_syncobj_surface_v1_commit *commit) {
|
static void surface_commit_destroy(struct wlr_linux_drm_syncobj_surface_v1_commit *commit) {
|
||||||
wlr_surface_unlock_cached(commit->surface->surface, commit->cached_seq);
|
wlr_surface_unlock_cached(commit->surface, commit->cached_seq);
|
||||||
wl_list_remove(&commit->surface_destroy.link);
|
wl_list_remove(&commit->surface_destroy.link);
|
||||||
wlr_drm_syncobj_timeline_waiter_finish(&commit->waiter);
|
wlr_drm_syncobj_timeline_waiter_finish(&commit->waiter);
|
||||||
free(commit);
|
free(commit);
|
||||||
|
|
@ -237,7 +237,7 @@ static bool lock_surface_commit(struct wlr_linux_drm_syncobj_surface_v1 *surface
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
commit->surface = surface;
|
commit->surface = surface->surface;
|
||||||
commit->cached_seq = wlr_surface_lock_pending(surface->surface);
|
commit->cached_seq = wlr_surface_lock_pending(surface->surface);
|
||||||
|
|
||||||
commit->surface_destroy.notify = surface_commit_handle_surface_destroy;
|
commit->surface_destroy.notify = surface_commit_handle_surface_destroy;
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ static void manager_create_transient_seat(struct wl_client *client,
|
||||||
wl_resource_set_implementation(seat->resource, &transient_seat_impl,
|
wl_resource_set_implementation(seat->resource, &transient_seat_impl,
|
||||||
seat, transient_seat_handle_resource_destroy);
|
seat, transient_seat_handle_resource_destroy);
|
||||||
|
|
||||||
|
wl_list_init(&seat->seat_destroy.link);
|
||||||
wl_signal_emit_mutable(&manager->events.create_seat, seat);
|
wl_signal_emit_mutable(&manager->events.create_seat, seat);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,11 @@ static void virtual_pointer_axis_source(struct wl_client *client,
|
||||||
if (pointer == NULL) {
|
if (pointer == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pointer->axis_event[pointer->axis].pointer = &pointer->pointer;
|
int n_axis = sizeof(pointer->axis_event) / sizeof(pointer->axis_event[0]);
|
||||||
pointer->axis_event[pointer->axis].source = source;
|
for (int i = 0; i < n_axis; i++) {
|
||||||
|
pointer->axis_event[i].pointer = &pointer->pointer;
|
||||||
|
pointer->axis_event[i].source = source;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtual_pointer_axis_stop(struct wl_client *client,
|
static void virtual_pointer_axis_stop(struct wl_client *client,
|
||||||
|
|
|
||||||
20
util/box.c
20
util/box.c
|
|
@ -19,16 +19,15 @@ void wlr_box_closest_point(const struct wlr_box *box, double x, double y,
|
||||||
//
|
//
|
||||||
// In order to be consistent with e.g. wlr_box_contains_point(),
|
// In order to be consistent with e.g. wlr_box_contains_point(),
|
||||||
// this function returns a point inside the bottom and right edges
|
// this function returns a point inside the bottom and right edges
|
||||||
// of the box by at least 1/65536 of a unit (pixel). 1/65536 is
|
// of the box by at least 1/256 of a unit (pixel). 1/256 is
|
||||||
// small enough to avoid a "dead zone" with high-resolution mice
|
// small enough to avoid a "dead zone" with high-resolution mice
|
||||||
// but large enough to avoid rounding to zero (due to loss of
|
// but large enough to avoid rounding to zero in wl_fixed_from_double().
|
||||||
// significant digits) in simple floating-point calculations.
|
|
||||||
|
|
||||||
// find the closest x point
|
// find the closest x point
|
||||||
if (x < box->x) {
|
if (x < box->x) {
|
||||||
*dest_x = box->x;
|
*dest_x = box->x;
|
||||||
} else if (x > box->x + box->width - 1/65536.0) {
|
} else if (x > box->x + box->width - 1/256.0) {
|
||||||
*dest_x = box->x + box->width - 1/65536.0;
|
*dest_x = box->x + box->width - 1/256.0;
|
||||||
} else {
|
} else {
|
||||||
*dest_x = x;
|
*dest_x = x;
|
||||||
}
|
}
|
||||||
|
|
@ -36,8 +35,8 @@ void wlr_box_closest_point(const struct wlr_box *box, double x, double y,
|
||||||
// find closest y point
|
// find closest y point
|
||||||
if (y < box->y) {
|
if (y < box->y) {
|
||||||
*dest_y = box->y;
|
*dest_y = box->y;
|
||||||
} else if (y > box->y + box->height - 1/65536.0) {
|
} else if (y > box->y + box->height - 1/256.0) {
|
||||||
*dest_y = box->y + box->height - 1/65536.0;
|
*dest_y = box->y + box->height - 1/256.0;
|
||||||
} else {
|
} else {
|
||||||
*dest_y = y;
|
*dest_y = y;
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +66,12 @@ bool wlr_box_intersection(struct wlr_box *dest, const struct wlr_box *box_a,
|
||||||
dest->width = x2 - x1;
|
dest->width = x2 - x1;
|
||||||
dest->height = y2 - y1;
|
dest->height = y2 - y1;
|
||||||
|
|
||||||
return !wlr_box_empty(dest);
|
if (wlr_box_empty(dest)) {
|
||||||
|
*dest = (struct wlr_box){0};
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_box_contains_point(const struct wlr_box *box, double x, double y) {
|
bool wlr_box_contains_point(const struct wlr_box *box, double x, double y) {
|
||||||
|
|
|
||||||
|
|
@ -602,7 +602,7 @@ xcursor_build_fullname(const char *dir, const char *subdir, const char *file)
|
||||||
static const char *
|
static const char *
|
||||||
xcursor_next_path(const char *path)
|
xcursor_next_path(const char *path)
|
||||||
{
|
{
|
||||||
char *colon = strchr(path, ':');
|
const char *colon = strchr(path, ':');
|
||||||
|
|
||||||
if (!colon)
|
if (!colon)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
|
|
@ -283,6 +283,8 @@ static bool xwm_selection_send_data(struct wlr_xwm_selection *selection,
|
||||||
int p[2];
|
int p[2];
|
||||||
if (pipe(p) == -1) {
|
if (pipe(p) == -1) {
|
||||||
wlr_log_errno(WLR_ERROR, "pipe() failed");
|
wlr_log_errno(WLR_ERROR, "pipe() failed");
|
||||||
|
wl_array_release(&transfer->source_data);
|
||||||
|
free(transfer);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ static void handle_server_start(struct wl_listener *listener, void *data) {
|
||||||
static void xwayland_mark_ready(struct wlr_xwayland *xwayland) {
|
static void xwayland_mark_ready(struct wlr_xwayland *xwayland) {
|
||||||
assert(xwayland->server->wm_fd[0] >= 0);
|
assert(xwayland->server->wm_fd[0] >= 0);
|
||||||
xwayland->xwm = xwm_create(xwayland, xwayland->server->wm_fd[0]);
|
xwayland->xwm = xwm_create(xwayland, xwayland->server->wm_fd[0]);
|
||||||
|
// xwm_create takes ownership of wm_fd[0] under all circumstances
|
||||||
|
xwayland->server->wm_fd[0] = -1;
|
||||||
|
|
||||||
if (!xwayland->xwm) {
|
if (!xwayland->xwm) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -69,6 +72,11 @@ static void handle_shell_destroy(struct wl_listener *listener, void *data) {
|
||||||
struct wlr_xwayland *xwayland =
|
struct wlr_xwayland *xwayland =
|
||||||
wl_container_of(listener, xwayland, shell_destroy);
|
wl_container_of(listener, xwayland, shell_destroy);
|
||||||
xwayland->shell_v1 = NULL;
|
xwayland->shell_v1 = NULL;
|
||||||
|
wl_list_remove(&xwayland->shell_destroy.link);
|
||||||
|
// Will remove this list in handle_shell_destroy().
|
||||||
|
// This ensures the link is always initialized and
|
||||||
|
// avoids the need to keep check conditions in sync.
|
||||||
|
wl_list_init(&xwayland->shell_destroy.link);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_xwayland_destroy(struct wlr_xwayland *xwayland) {
|
void wlr_xwayland_destroy(struct wlr_xwayland *xwayland) {
|
||||||
|
|
|
||||||
|
|
@ -2470,6 +2470,7 @@ void xwm_set_cursor(struct wlr_xwm *xwm, const uint8_t *pixels, uint32_t stride,
|
||||||
struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
|
struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
|
||||||
struct wlr_xwm *xwm = calloc(1, sizeof(*xwm));
|
struct wlr_xwm *xwm = calloc(1, sizeof(*xwm));
|
||||||
if (xwm == NULL) {
|
if (xwm == NULL) {
|
||||||
|
close(wm_fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2484,11 +2485,13 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *xwayland, int wm_fd) {
|
||||||
|
|
||||||
xwm->ping_timeout = 10000;
|
xwm->ping_timeout = 10000;
|
||||||
|
|
||||||
|
// xcb_connect_to_fd takes ownership of the FD regardless of success/failure
|
||||||
xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL);
|
xwm->xcb_conn = xcb_connect_to_fd(wm_fd, NULL);
|
||||||
|
|
||||||
int rc = xcb_connection_has_error(xwm->xcb_conn);
|
int rc = xcb_connection_has_error(xwm->xcb_conn);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
wlr_log(WLR_ERROR, "xcb connect failed: %d", rc);
|
wlr_log(WLR_ERROR, "xcb connect failed: %d", rc);
|
||||||
|
xcb_disconnect(xwm->xcb_conn);
|
||||||
free(xwm);
|
free(xwm);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue