Wayland: handle mouse input

This commit is contained in:
fwsmit 2020-11-22 16:56:31 +01:00
parent ed560eab4e
commit 32119a1df7
3 changed files with 115 additions and 15 deletions

View File

@ -9,7 +9,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <wayland-client.h>
#include "dbus.h"
#include "draw.h"
@ -86,6 +86,7 @@ static gboolean run(void *data)
if (active) {
gint64 now = time_monotonic_now();
gint64 sleep = queues_get_next_datachange(now);
sleep = 100000; // Make sure wayland input is handled in time FIXME
gint64 timeout_at = now + sleep;
LOG_D("Dunst: sleeping for %li ms", sleep/1000);

View File

@ -324,7 +324,7 @@ void queues_notification_close_id(int id, enum reason reason)
default:
reason_string="unknown";
}
LOG_D("Queues: Closing notification for reason: %s", reason_string);
GQueue *allqueues[] = { displayed, waiting };

View File

@ -12,6 +12,7 @@
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <linux/input-event-codes.h>
#include "protocols/xdg-output-unstable-v1-client-header.h"
#include "protocols/xdg-output-unstable-v1.h"
@ -23,6 +24,7 @@
#include "../log.h"
#include "../settings.h"
#include "../queues.h"
struct window_wl {
struct wl_surface *surface;
@ -45,6 +47,7 @@ struct wl_ctx {
struct wl_shm *shm;
struct zwlr_layer_shell_v1 *layer_shell;
struct zxdg_output_manager_v1 *xdg_output_manager;
struct wl_seat *seat;
struct wl_list outputs;
@ -56,6 +59,11 @@ struct wl_ctx {
bool configured;
bool dirty;
struct {
struct wl_pointer *wl_pointer;
int32_t x, y;
} pointer;
struct dimensions cur_dim;
int32_t width, height;
@ -112,8 +120,9 @@ static void output_handle_geometry(void *data, struct wl_output *wl_output,
int32_t x, int32_t y, int32_t phy_width, int32_t phy_height,
int32_t subpixel, const char *make, const char *model,
int32_t transform) {
//struct wl_output *output = data;
//output->subpixel = subpixel;
//TODO
/* struct wl_output *output = data; */
/* output->subpixel = subpixel; */
}
static void output_handle_scale(void *data, struct wl_output *wl_output,
@ -162,6 +171,102 @@ static void destroy_output(struct wl_output *output) {
free(output);
}
static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) {
LOG_I("Pointer handle motion");
ctx.pointer.x = wl_fixed_to_int(surface_x);
ctx.pointer.y = wl_fixed_to_int(surface_y);
}
static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, uint32_t time, uint32_t button,
uint32_t button_state) {
if (button_state == 0){
// make sure it doesn't react twice
return;
}
LOG_I("Pointer handle button %i: %i", button, button_state);
enum mouse_action *acts;
switch (button) {
case BTN_LEFT:
acts = settings.mouse_left_click;
break;
case BTN_MIDDLE:
acts = settings.mouse_middle_click;
break;
case BTN_RIGHT:
acts = settings.mouse_right_click;
break;
default:
LOG_W("Unsupported mouse button: '%d'", button);
return;
}
// TODO Extract this code into seperate function
for (int i = 0; acts[i]; i++) {
enum mouse_action act = acts[i];
if (act == MOUSE_CLOSE_ALL) {
queues_history_push_all();
return;
}
if (act == MOUSE_DO_ACTION || act == MOUSE_CLOSE_CURRENT) {
int y = settings.separator_height;
struct notification *n = NULL;
int first = true;
for (const GList *iter = queues_get_displayed(); iter;
iter = iter->next) {
n = iter->data;
if (ctx.pointer.y > y && ctx.pointer.y < y + n->displayed_height)
break;
y += n->displayed_height + settings.separator_height;
if (first)
y += settings.frame_width;
}
if (n) {
if (act == MOUSE_CLOSE_CURRENT)
queues_notification_close(n, REASON_USER);
else
notification_do_action(n);
}
}
}
}
static const struct wl_pointer_listener pointer_listener = {
.enter = noop,
.leave = noop,
.motion = pointer_handle_motion,
.button = pointer_handle_button,
.axis = noop,
};
static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
uint32_t capabilities) {
if (ctx.pointer.wl_pointer != NULL) {
wl_pointer_release(ctx.pointer.wl_pointer);
ctx.pointer.wl_pointer = NULL;
}
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
ctx.pointer.wl_pointer = wl_seat_get_pointer(wl_seat);
wl_pointer_add_listener(ctx.pointer.wl_pointer,
&pointer_listener, ctx.seat);
LOG_I("Adding pointer");
}
}
static const struct wl_seat_listener seat_listener = {
.capabilities = seat_handle_capabilities,
.name = noop,
};
// FIXME: Snipped touch handling
static void surface_handle_enter(void *data, struct wl_surface *surface,
@ -241,9 +346,8 @@ static void handle_global(void *data, struct wl_registry *registry,
ctx.layer_shell = wl_registry_bind(registry, name,
&zwlr_layer_shell_v1_interface, 1);
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
struct wl_seat *seat =
wl_registry_bind(registry, name, &wl_seat_interface, 3);
//create_seat(seat);
ctx.seat = wl_registry_bind(registry, name, &wl_seat_interface, 3);
wl_seat_add_listener(ctx.seat, &seat_listener, ctx.seat);
} else if (strcmp(interface, wl_output_interface.name) == 0) {
struct wl_output *output =
wl_registry_bind(registry, name, &wl_output_interface, 3);
@ -331,10 +435,7 @@ void finish_wayland() {
destroy_output(output);
}
//struct mako_seat *seat, *seat_tmp;
//wl_list_for_each_safe(seat, seat_tmp, &ctx.seats, link) {
// destroy_seat(seat);
//}
free(ctx.seat);
if (ctx.xdg_output_manager != NULL) {
zxdg_output_manager_v1_destroy(ctx.xdg_output_manager);
@ -346,8 +447,6 @@ void finish_wayland() {
wl_display_disconnect(ctx.display);
}
// FIXME: Snip
static struct wl_output *get_configured_output() {
struct wl_output *output;
// FIXME
@ -446,7 +545,7 @@ static void send_frame() {
else{
anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
}
// Put the window at the right position
zwlr_layer_surface_v1_set_anchor(ctx.layer_surface,
anchor);
@ -552,7 +651,7 @@ void wl_win_show(window win) {
}
void wl_win_hide(window win) {
LOG_W("Hiding window");
LOG_I("Hiding window");
ctx.cur_dim.h = 0;
set_dirty();
wl_display_roundtrip(ctx.display);