aboutsummaryrefslogtreecommitdiff
path: root/rootston/roots_cursor.c
diff options
context:
space:
mode:
authorTony Crisci <tony@dubstepdish.com>2017-11-07 15:56:11 -0500
committerTony Crisci <tony@dubstepdish.com>2017-11-07 15:56:11 -0500
commit09c60924235805d07b7915ba879685545a3442aa (patch)
treed2fab6464daa8e91b0c79a0fbbc3d8373261a0d2 /rootston/roots_cursor.c
parent2280928bb2859b8a5e71e81b99a396ff7a3f9efa (diff)
multiseat: somewhat working
Diffstat (limited to 'rootston/roots_cursor.c')
-rw-r--r--rootston/roots_cursor.c239
1 files changed, 230 insertions, 9 deletions
diff --git a/rootston/roots_cursor.c b/rootston/roots_cursor.c
index 72eff996..92c0cc9e 100644
--- a/rootston/roots_cursor.c
+++ b/rootston/roots_cursor.c
@@ -1,4 +1,11 @@
+#define _XOPEN_SOURCE 700
#include <stdlib.h>
+#include <math.h>
+#ifdef __linux__
+#include <linux/input-event-codes.h>
+#elif __FreeBSD__
+#include <dev/evdev/input-event-codes.h>
+#endif
#include <wlr/util/log.h>
#include "rootston/cursor.h"
@@ -19,47 +26,261 @@ void roots_cursor_destroy(struct roots_cursor *cursor) {
// TODO
}
+static void cursor_set_xcursor_image(struct roots_cursor *cursor,
+ struct wlr_xcursor_image *image) {
+ wlr_cursor_set_image(cursor->cursor, image->buffer, image->width,
+ image->width, image->height, image->hotspot_x, image->hotspot_y);
+}
+
+static void roots_cursor_update_position(struct roots_cursor *cursor, uint32_t time) {
+ struct roots_desktop *desktop = cursor->seat->input->server->desktop;
+ struct roots_seat *seat = cursor->seat;
+ struct roots_view *view;
+ struct wlr_surface *surface;
+ double sx, sy;
+ switch (cursor->mode) {
+ case ROOTS_CURSOR_PASSTHROUGH:
+ view = view_at(desktop, cursor->cursor->x, cursor->cursor->y,
+ &surface, &sx, &sy);
+ bool set_compositor_cursor = !view && cursor->cursor_client;
+ if (view) {
+ struct wl_client *view_client =
+ wl_resource_get_client(view->wlr_surface->resource);
+ set_compositor_cursor = view_client != cursor->cursor_client;
+ }
+ if (set_compositor_cursor) {
+ struct wlr_xcursor *xcursor = get_default_xcursor(cursor->xcursor_theme);
+ cursor_set_xcursor_image(cursor, xcursor->images[0]);
+ cursor->cursor_client = NULL;
+ }
+ if (view) {
+ wlr_seat_pointer_notify_enter(seat->seat, surface, sx, sy);
+ wlr_seat_pointer_notify_motion(seat->seat, time, sx, sy);
+ } else {
+ wlr_seat_pointer_clear_focus(seat->seat);
+ }
+ break;
+ case ROOTS_CURSOR_MOVE:
+ if (seat->focus) {
+ double dx = cursor->cursor->x - cursor->offs_x;
+ double dy = cursor->cursor->y - cursor->offs_y;
+ view_move(seat->focus, cursor->view_x + dx,
+ cursor->view_y + dy);
+ }
+ break;
+ case ROOTS_CURSOR_RESIZE:
+ if (seat->focus) {
+ double dx = cursor->cursor->x - cursor->offs_x;
+ double dy = cursor->cursor->y - cursor->offs_y;
+ double active_x = seat->focus->x;
+ double active_y = seat->focus->y;
+ int width = cursor->view_width;
+ int height = cursor->view_height;
+ if (cursor->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_TOP) {
+ active_y = cursor->view_y + dy;
+ height -= dy;
+ if (height < 0) {
+ active_y += height;
+ }
+ } else if (cursor->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_BOTTOM) {
+ height += dy;
+ }
+ if (cursor->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_LEFT) {
+ active_x = cursor->view_x + dx;
+ width -= dx;
+ if (width < 0) {
+ active_x += width;
+ }
+ } else if (cursor->resize_edges & ROOTS_CURSOR_RESIZE_EDGE_RIGHT) {
+ width += dx;
+ }
+
+ if (width < 0) {
+ width = 0;
+ }
+ if (height < 0) {
+ height = 0;
+ }
+
+ if (active_x != seat->focus->x ||
+ active_y != seat->focus->y) {
+ view_move_resize(seat->focus, active_x, active_y,
+ width, height);
+ } else {
+ view_resize(seat->focus, width, height);
+ }
+ }
+ break;
+ case ROOTS_CURSOR_ROTATE:
+ if (seat->focus) {
+ struct roots_view *view = seat->focus;
+ int ox = view->x + view->wlr_surface->current->width/2,
+ oy = view->y + view->wlr_surface->current->height/2;
+ int ux = cursor->offs_x - ox,
+ uy = cursor->offs_y - oy;
+ int vx = cursor->cursor->x - ox,
+ vy = cursor->cursor->y - oy;
+ float angle = atan2(vx*uy - vy*ux, vx*ux + vy*uy);
+ int steps = 12;
+ angle = round(angle/M_PI*steps) / (steps/M_PI);
+ view->rotation = cursor->view_rotation + angle;
+ }
+ break;
+ }
+
+}
+
+static void roots_cursor_press_button(struct roots_cursor *cursor,
+ struct wlr_input_device *device, uint32_t time, uint32_t button,
+ uint32_t state) {
+ struct roots_seat *seat = cursor->seat;
+ struct roots_desktop *desktop = seat->input->server->desktop;
+ struct wlr_surface *surface;
+ double sx, sy;
+ struct roots_view *view = view_at(desktop,
+ cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
+
+ if (state == WLR_BUTTON_PRESSED && view && roots_seat_has_meta_pressed(seat)) {
+ // TODO
+ roots_seat_focus_view(seat, view);
+
+ uint32_t edges;
+ switch (button) {
+ case BTN_LEFT:
+ // TODO
+ roots_seat_begin_move(seat, view);
+ break;
+ case BTN_RIGHT:
+ edges = 0;
+ if (sx < view->wlr_surface->current->width/2) {
+ edges |= ROOTS_CURSOR_RESIZE_EDGE_LEFT;
+ } else {
+ edges |= ROOTS_CURSOR_RESIZE_EDGE_RIGHT;
+ }
+ if (sy < view->wlr_surface->current->height/2) {
+ edges |= ROOTS_CURSOR_RESIZE_EDGE_TOP;
+ } else {
+ edges |= ROOTS_CURSOR_RESIZE_EDGE_BOTTOM;
+ }
+ roots_seat_begin_resize(seat, view, edges);
+ break;
+ case BTN_MIDDLE:
+ roots_seat_begin_rotate(seat, view);
+ break;
+ }
+ return;
+ }
+
+ // TODO
+ uint32_t serial =
+ wlr_seat_pointer_notify_button(seat->seat, time, button, state);
+
+ int i;
+ switch (state) {
+ case WLR_BUTTON_RELEASED:
+ seat->cursor->mode = ROOTS_CURSOR_PASSTHROUGH;
+ roots_cursor_update_position(cursor, time);
+ break;
+ case WLR_BUTTON_PRESSED:
+ // TODO
+ i = cursor->input_events_idx;
+ cursor->input_events[i].serial = serial;
+ cursor->input_events[i].cursor = cursor->cursor;
+ cursor->input_events[i].device = device;
+ cursor->input_events_idx = (i + 1)
+ % (sizeof(cursor->input_events) / sizeof(cursor->input_events[0]));
+ roots_seat_focus_view(seat, view);
+ break;
+ }
+}
+
void roots_cursor_handle_motion(struct roots_cursor *cursor,
struct wlr_event_pointer_motion *event) {
- wlr_log(L_DEBUG, "TODO: cursor handle motion");
+ wlr_cursor_move(cursor->cursor, event->device,
+ event->delta_x, event->delta_y);
+ roots_cursor_update_position(cursor, event->time_msec);
}
void roots_cursor_handle_motion_absolute(struct roots_cursor *cursor,
struct wlr_event_pointer_motion_absolute *event) {
- wlr_log(L_DEBUG, "TODO: cursor handle motion absolute");
+ wlr_cursor_warp_absolute(cursor->cursor, event->device,
+ event->x_mm / event->width_mm, event->y_mm / event->height_mm);
+ roots_cursor_update_position(cursor, event->time_msec);
}
void roots_cursor_handle_button(struct roots_cursor *cursor,
struct wlr_event_pointer_button *event) {
- wlr_log(L_DEBUG, "TODO: cursor handle button");
+ roots_cursor_press_button(cursor, event->device, event->time_msec,
+ event->button, event->state);
}
void roots_cursor_handle_axis(struct roots_cursor *cursor,
struct wlr_event_pointer_axis *event) {
- wlr_log(L_DEBUG, "TODO: cursor handle axis");
+ wlr_seat_pointer_notify_axis(cursor->seat->seat, event->time_msec,
+ event->orientation, event->delta);
}
void roots_cursor_handle_touch_down(struct roots_cursor *cursor,
struct wlr_event_touch_down *event) {
- wlr_log(L_DEBUG, "TODO: cursor handle touch down");
+ struct roots_touch_point *point =
+ calloc(1, sizeof(struct roots_touch_point));
+ if (!point) {
+ wlr_log(L_ERROR, "could not allocate memory for touch point");
+ return;
+ }
+
+ point->device = event->device->data;
+ point->slot = event->slot;
+ point->x = event->x_mm / event->width_mm;
+ point->y = event->y_mm / event->height_mm;
+ wlr_cursor_warp_absolute(cursor->cursor, event->device, point->x, point->y);
+ roots_cursor_update_position(cursor, event->time_msec);
+ wl_list_insert(&cursor->touch_points, &point->link);
+ roots_cursor_press_button(cursor, event->device,
+ event->time_msec, BTN_LEFT, 1);
}
void roots_cursor_handle_touch_up(struct roots_cursor *cursor,
struct wlr_event_touch_up *event) {
- wlr_log(L_DEBUG, "TODO: cursor handle touch up");
+ struct roots_touch_point *point;
+ wl_list_for_each(point, &cursor->touch_points, link) {
+ if (point->slot == event->slot) {
+ wl_list_remove(&point->link);
+ free(point);
+ break;
+ }
+ }
+ roots_cursor_press_button(cursor, event->device,
+ event->time_msec, BTN_LEFT, 0);
}
void roots_cursor_handle_touch_motion(struct roots_cursor *cursor,
struct wlr_event_touch_motion *event) {
- wlr_log(L_DEBUG, "TODO: cursor handle touch motion");
+ struct roots_touch_point *point;
+ wl_list_for_each(point, &cursor->touch_points, link) {
+ if (point->slot == event->slot) {
+ point->x = event->x_mm / event->width_mm;
+ point->y = event->y_mm / event->height_mm;
+ wlr_cursor_warp_absolute(cursor->cursor, event->device,
+ point->x, point->y);
+ roots_cursor_update_position(cursor, event->time_msec);
+ break;
+ }
+ }
}
void roots_cursor_handle_tool_axis(struct roots_cursor *cursor,
struct wlr_event_tablet_tool_axis *event) {
- wlr_log(L_DEBUG, "TODO: cursor handle tool axis");
+ if ((event->updated_axes & WLR_TABLET_TOOL_AXIS_X) &&
+ (event->updated_axes & WLR_TABLET_TOOL_AXIS_Y)) {
+ wlr_cursor_warp_absolute(cursor->cursor, event->device,
+ event->x_mm / event->width_mm, event->y_mm / event->height_mm);
+ roots_cursor_update_position(cursor, event->time_msec);
+ }
}
void roots_cursor_handle_tool_tip(struct roots_cursor *cursor,
struct wlr_event_tablet_tool_tip *event) {
- wlr_log(L_DEBUG, "TODO: cursor handle tool tip");
+ roots_cursor_press_button(cursor, event->device,
+ event->time_msec, BTN_LEFT, event->state);
}