multiseat handling
This commit is contained in:
parent
8c959d60a1
commit
bc35014269
@ -50,8 +50,10 @@ struct wl_deleter;
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
using wl_unique_ptr = std::unique_ptr<T, wl_deleter<T>>;
|
using wl_unique_ptr = std::unique_ptr<T, wl_deleter<T>>;
|
||||||
|
|
||||||
WL_DELETER(wl_surface, wl_surface_destroy);
|
|
||||||
WL_DELETER(zwlr_layer_surface_v1, zwlr_layer_surface_v1_destroy);
|
|
||||||
WL_DELETER(wl_buffer, wl_buffer_destroy);
|
WL_DELETER(wl_buffer, wl_buffer_destroy);
|
||||||
WL_DELETER(wl_output, wl_output_release);
|
WL_DELETER(wl_output, wl_output_release);
|
||||||
|
WL_DELETER(wl_pointer, wl_pointer_release);
|
||||||
|
WL_DELETER(wl_seat, wl_seat_release);
|
||||||
|
WL_DELETER(wl_surface, wl_surface_destroy);
|
||||||
WL_DELETER(znet_tapesoftware_dwl_wm_monitor_v1, znet_tapesoftware_dwl_wm_monitor_v1_release);
|
WL_DELETER(znet_tapesoftware_dwl_wm_monitor_v1, znet_tapesoftware_dwl_wm_monitor_v1_release);
|
||||||
|
WL_DELETER(zwlr_layer_surface_v1, zwlr_layer_surface_v1_destroy);
|
||||||
|
135
src/main.cpp
135
src/main.cpp
@ -11,6 +11,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <linux/input-event-codes.h>
|
#include <linux/input-event-codes.h>
|
||||||
|
#include <list>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
@ -30,6 +31,17 @@ struct Monitor {
|
|||||||
std::optional<Bar> bar;
|
std::optional<Bar> bar;
|
||||||
bool created;
|
bool created;
|
||||||
};
|
};
|
||||||
|
struct SeatPointer {
|
||||||
|
wl_unique_ptr<wl_pointer> wlPointer;
|
||||||
|
Bar *focusedBar;
|
||||||
|
int x, y;
|
||||||
|
std::vector<int> btns;
|
||||||
|
};
|
||||||
|
struct Seat {
|
||||||
|
uint32_t name;
|
||||||
|
wl_unique_ptr<wl_seat> wlSeat;
|
||||||
|
std::optional<SeatPointer> pointer;
|
||||||
|
};
|
||||||
|
|
||||||
static void waylandFlush();
|
static void waylandFlush();
|
||||||
static void waylandWriteReady();
|
static void waylandWriteReady();
|
||||||
@ -46,8 +58,11 @@ znet_tapesoftware_dwl_wm_v1 *dwlWm;
|
|||||||
std::vector<QString> tagNames;
|
std::vector<QString> tagNames;
|
||||||
std::vector<QString> layoutNames;
|
std::vector<QString> layoutNames;
|
||||||
static xdg_wm_base *xdgWmBase;
|
static xdg_wm_base *xdgWmBase;
|
||||||
|
static wl_surface *cursorSurface;
|
||||||
|
static wl_cursor_image *cursorImage;
|
||||||
static bool ready;
|
static bool ready;
|
||||||
static std::vector<Monitor> monitors;
|
static std::list<Monitor> monitors;
|
||||||
|
static std::list<Seat> seats;
|
||||||
static QString lastStatus;
|
static QString lastStatus;
|
||||||
static std::string statusFifoName;
|
static std::string statusFifoName;
|
||||||
static int statusFifoFd {-1};
|
static int statusFifoFd {-1};
|
||||||
@ -74,15 +89,6 @@ static const struct xdg_wm_base_listener xdgWmBaseListener = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SeatState {
|
|
||||||
wl_pointer *pointer;
|
|
||||||
wl_surface *cursorSurface;
|
|
||||||
wl_cursor_image *cursorImage;
|
|
||||||
Bar *focusedBar;
|
|
||||||
int x, y;
|
|
||||||
std::vector<int> btns;
|
|
||||||
};
|
|
||||||
static SeatState seatState;
|
|
||||||
static Bar* barFromSurface(const wl_surface *surface)
|
static Bar* barFromSurface(const wl_surface *surface)
|
||||||
{
|
{
|
||||||
auto mon = std::find_if(begin(monitors), end(monitors), [surface](const Monitor &mon) {
|
auto mon = std::find_if(begin(monitors), end(monitors), [surface](const Monitor &mon) {
|
||||||
@ -91,58 +97,66 @@ static Bar* barFromSurface(const wl_surface *surface)
|
|||||||
return mon != end(monitors) && mon->bar ? &*mon->bar : nullptr;
|
return mon != end(monitors) && mon->bar ? &*mon->bar : nullptr;
|
||||||
}
|
}
|
||||||
static const struct wl_pointer_listener pointerListener = {
|
static const struct wl_pointer_listener pointerListener = {
|
||||||
.enter = [](void*, wl_pointer *pointer, uint32_t serial,
|
.enter = [](void *sp, wl_pointer *pointer, uint32_t serial,
|
||||||
wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
|
wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
|
||||||
{
|
{
|
||||||
seatState.focusedBar = barFromSurface(surface);
|
auto& seat = *static_cast<Seat*>(sp);
|
||||||
wl_pointer_set_cursor(pointer, serial, seatState.cursorSurface,
|
seat.pointer->focusedBar = barFromSurface(surface);
|
||||||
seatState.cursorImage->hotspot_x, seatState.cursorImage->hotspot_y);
|
if (!cursorImage) {
|
||||||
|
auto cursorTheme = wl_cursor_theme_load(NULL, 24, shm);
|
||||||
|
cursorImage = wl_cursor_theme_get_cursor(cursorTheme, "left_ptr")->images[0];
|
||||||
|
cursorSurface = wl_compositor_create_surface(compositor);
|
||||||
|
wl_surface_attach(cursorSurface, wl_cursor_image_get_buffer(cursorImage), 0, 0);
|
||||||
|
wl_surface_commit(cursorSurface);
|
||||||
|
}
|
||||||
|
wl_pointer_set_cursor(pointer, serial, cursorSurface,
|
||||||
|
cursorImage->hotspot_x, cursorImage->hotspot_y);
|
||||||
},
|
},
|
||||||
.leave = [](void*, wl_pointer*, uint32_t serial, wl_surface*) {
|
.leave = [](void *sp, wl_pointer*, uint32_t serial, wl_surface*) {
|
||||||
seatState.focusedBar = nullptr;
|
auto& seat = *static_cast<Seat*>(sp);
|
||||||
|
seat.pointer->focusedBar = nullptr;
|
||||||
},
|
},
|
||||||
.motion = [](void*, wl_pointer*, uint32_t, wl_fixed_t x, wl_fixed_t y) {
|
.motion = [](void *sp, wl_pointer*, uint32_t, wl_fixed_t x, wl_fixed_t y) {
|
||||||
seatState.x = wl_fixed_to_int(x);
|
auto& seat = *static_cast<Seat*>(sp);
|
||||||
seatState.y = wl_fixed_to_int(y);
|
seat.pointer->x = wl_fixed_to_int(x);
|
||||||
|
seat.pointer->y = wl_fixed_to_int(y);
|
||||||
},
|
},
|
||||||
.button = [](void*, wl_pointer*, uint32_t, uint32_t, uint32_t button, uint32_t pressed) {
|
.button = [](void *sp, wl_pointer*, uint32_t, uint32_t, uint32_t button, uint32_t pressed) {
|
||||||
auto it = std::find(begin(seatState.btns), end(seatState.btns), button);
|
auto& seat = *static_cast<Seat*>(sp);
|
||||||
if (pressed == WL_POINTER_BUTTON_STATE_PRESSED && it == end(seatState.btns)) {
|
auto it = std::find(begin(seat.pointer->btns), end(seat.pointer->btns), button);
|
||||||
seatState.btns.push_back(button);
|
if (pressed == WL_POINTER_BUTTON_STATE_PRESSED && it == end(seat.pointer->btns)) {
|
||||||
} else if (pressed == WL_POINTER_BUTTON_STATE_RELEASED && it != end(seatState.btns)) {
|
seat.pointer->btns.push_back(button);
|
||||||
seatState.btns.erase(it);
|
} else if (pressed == WL_POINTER_BUTTON_STATE_RELEASED && it != end(seat.pointer->btns)) {
|
||||||
|
seat.pointer->btns.erase(it);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.axis = [](void*, wl_pointer*, uint32_t, uint32_t, wl_fixed_t) { },
|
.axis = [](void *sp, wl_pointer*, uint32_t, uint32_t, wl_fixed_t) { },
|
||||||
.frame = [](void*, wl_pointer*) {
|
.frame = [](void *sp, wl_pointer*) {
|
||||||
if (!seatState.focusedBar) return;
|
auto& seat = *static_cast<Seat*>(sp);
|
||||||
for (auto btn : seatState.btns) {
|
if (!seat.pointer->focusedBar) return;
|
||||||
seatState.focusedBar->click(seatState.x, seatState.y, btn, 0);
|
for (auto btn : seat.pointer->btns) {
|
||||||
|
seat.pointer->focusedBar->click(seat.pointer->x, seat.pointer->y, btn, 0);
|
||||||
}
|
}
|
||||||
seatState.btns.clear();
|
seat.pointer->btns.clear();
|
||||||
},
|
},
|
||||||
.axis_source = [](void*, wl_pointer*, uint32_t) { },
|
.axis_source = [](void*, wl_pointer*, uint32_t) { },
|
||||||
.axis_stop = [](void*, wl_pointer*, uint32_t, uint32_t) { },
|
.axis_stop = [](void*, wl_pointer*, uint32_t, uint32_t) { },
|
||||||
.axis_discrete = [](void*, wl_pointer*, uint32_t, int32_t) { },
|
.axis_discrete = [](void*, wl_pointer*, uint32_t, int32_t) { },
|
||||||
};
|
};
|
||||||
|
|
||||||
static wl_seat *seat;
|
|
||||||
static const struct wl_seat_listener seatListener = {
|
static const struct wl_seat_listener seatListener = {
|
||||||
[](void*, wl_seat*, uint32_t cap)
|
.capabilities = [](void *sp, wl_seat*, uint32_t cap)
|
||||||
{
|
{
|
||||||
if (!seatState.pointer && WL_SEAT_CAPABILITY_POINTER) {
|
auto& seat = *static_cast<Seat*>(sp);
|
||||||
auto cursorTheme = wl_cursor_theme_load(NULL, 24, shm);
|
auto hasPointer = cap & WL_SEAT_CAPABILITY_POINTER;
|
||||||
auto cursorImage = wl_cursor_theme_get_cursor(cursorTheme, "left_ptr")->images[0];
|
if (!seat.pointer && hasPointer) {
|
||||||
seatState.cursorImage = cursorImage;
|
seat.pointer.emplace(SeatPointer {wl_unique_ptr<wl_pointer> {wl_seat_get_pointer(seat.wlSeat.get())}});
|
||||||
seatState.cursorSurface = wl_compositor_create_surface(compositor);
|
wl_pointer_add_listener(seat.pointer->wlPointer.get(), &pointerListener, &seat);
|
||||||
wl_surface_attach(seatState.cursorSurface,
|
} else if (seat.pointer && !hasPointer) {
|
||||||
wl_cursor_image_get_buffer(cursorImage), 0, 0);
|
seat.pointer.reset();
|
||||||
wl_surface_commit(seatState.cursorSurface);
|
|
||||||
seatState.pointer = wl_seat_get_pointer(seat);
|
|
||||||
wl_pointer_add_listener(seatState.pointer, &pointerListener, nullptr);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[](void*, wl_seat*, const char *name) { }
|
.name = [](void*, wl_seat*, const char *name) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct znet_tapesoftware_dwl_wm_v1_listener dwlWmListener = {
|
static const struct znet_tapesoftware_dwl_wm_v1_listener dwlWmListener = {
|
||||||
@ -189,19 +203,11 @@ static void setupMonitor(Monitor &monitor) {
|
|||||||
znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor.get(), &dwlWmMonitorListener, &monitor);
|
znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor.get(), &dwlWmMonitorListener, &monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onOutput(uint32_t name, wl_output *output) {
|
|
||||||
auto& m = monitors.emplace_back(Monitor {name, wl_unique_ptr<wl_output> {output}});
|
|
||||||
if (ready) {
|
|
||||||
setupMonitor(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// called after we have received the initial batch of globals
|
// called after we have received the initial batch of globals
|
||||||
static void onReady()
|
static void onReady()
|
||||||
{
|
{
|
||||||
requireGlobal(compositor, "wl_compositor");
|
requireGlobal(compositor, "wl_compositor");
|
||||||
requireGlobal(shm, "wl_shm");
|
requireGlobal(shm, "wl_shm");
|
||||||
requireGlobal(seat, "wl_seat");
|
|
||||||
requireGlobal(wlrLayerShell, "zwlr_layer_shell_v1");
|
requireGlobal(wlrLayerShell, "zwlr_layer_shell_v1");
|
||||||
requireGlobal(dwlWm, "znet_tapesoftware_dwl_wm_v1");
|
requireGlobal(dwlWm, "znet_tapesoftware_dwl_wm_v1");
|
||||||
setupStatusFifo();
|
setupStatusFifo();
|
||||||
@ -280,22 +286,27 @@ static void registryHandleGlobal(void*, wl_registry *registry, uint32_t name, co
|
|||||||
xdg_wm_base_add_listener(xdgWmBase, &xdgWmBaseListener, nullptr);
|
xdg_wm_base_add_listener(xdgWmBase, &xdgWmBaseListener, nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (seat == nullptr && reg.handle(seat, wl_seat_interface, 7)) {
|
|
||||||
wl_seat_add_listener(seat, &seatListener, nullptr);
|
|
||||||
}
|
|
||||||
if (wl_output *output; reg.handle(output, wl_output_interface, 1)) {
|
|
||||||
onOutput(name, output);
|
|
||||||
}
|
|
||||||
if (reg.handle(dwlWm, znet_tapesoftware_dwl_wm_v1_interface, 1)) {
|
if (reg.handle(dwlWm, znet_tapesoftware_dwl_wm_v1_interface, 1)) {
|
||||||
znet_tapesoftware_dwl_wm_v1_add_listener(dwlWm, &dwlWmListener, nullptr);
|
znet_tapesoftware_dwl_wm_v1_add_listener(dwlWm, &dwlWmListener, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wl_seat *wlSeat; reg.handle(wlSeat, wl_seat_interface, 7)) {
|
||||||
|
auto& seat = seats.emplace_back(Seat {name, wl_unique_ptr<wl_seat> {wlSeat}});
|
||||||
|
wl_seat_add_listener(wlSeat, &seatListener, &seat);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wl_output *output; reg.handle(output, wl_output_interface, 1)) {
|
||||||
|
auto& m = monitors.emplace_back(Monitor {name, wl_unique_ptr<wl_output> {output}});
|
||||||
|
if (ready) {
|
||||||
|
setupMonitor(m);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void registryHandleRemove(void*, wl_registry *registry, uint32_t name)
|
static void registryHandleRemove(void*, wl_registry *registry, uint32_t name)
|
||||||
{
|
{
|
||||||
auto it = std::find_if(begin(monitors), end(monitors), [name](const Monitor &m) { return m.name == name; });
|
monitors.remove_if([name](const Monitor &mon) { return mon.name == name; });
|
||||||
if (it != end(monitors)) {
|
seats.remove_if([name](const Seat &seat) { return seat.name == name; });
|
||||||
monitors.erase(it);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
static const struct wl_registry_listener registry_listener = {
|
static const struct wl_registry_listener registry_listener = {
|
||||||
.global = registryHandleGlobal,
|
.global = registryHandleGlobal,
|
||||||
|
Loading…
Reference in New Issue
Block a user