commit bd54842bdf91f241faf7c47968711200c478a4ce
parent 85ecbdbfed768ecab277850e3f7b5653c5fc2dfa
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 24 Apr 2019 23:35:27 -0400
Implement interactive move
Diffstat:
M | include/server.h | | | 25 | +++++++++++++++++++++++++ |
M | input.c | | | 105 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- |
M | main.c | | | 7 | ++++--- |
M | output.c | | | 83 | +++++++++++++++++++++++++++++++++++++++++++++---------------------------------- |
4 files changed, 168 insertions(+), 52 deletions(-)
diff --git a/include/server.h b/include/server.h
@@ -12,6 +12,19 @@
#include <wlr/types/wlr_xcursor_manager.h>
#include <wlr/types/wlr_xdg_shell.h>
+enum wio_input_state {
+ INPUT_STATE_NONE = 0,
+ INPUT_STATE_MENU,
+ INPUT_STATE_NEW_START,
+ INPUT_STATE_NEW_END,
+ INPUT_STATE_MOVE_SELECT,
+ INPUT_STATE_MOVE,
+ INPUT_STATE_RESIZE_SELECT,
+ INPUT_STATE_RESIZE,
+ INPUT_STATE_DELETE_SELECT,
+ INPUT_STATE_HIDE_SELECT,
+};
+
struct wio_server {
struct wl_display *wl_display;
@@ -36,6 +49,7 @@ struct wio_server {
struct wl_listener cursor_button;
struct wl_listener cursor_axis;
struct wl_listener cursor_frame;
+ struct wl_listener request_cursor;
struct wl_listener new_xdg_surface;
@@ -44,7 +58,17 @@ struct wio_server {
int width, height;
struct wlr_texture *active_textures[5];
struct wlr_texture *inactive_textures[5];
+ int selected;
} menu;
+
+ struct {
+ int sx, sy;
+ struct wio_view *view;
+ struct wlr_surface *cursor;
+ int hotspot_x, hotspot_y;
+ } interactive;
+
+ enum wio_input_state input_state;
};
struct wio_output {
@@ -73,5 +97,6 @@ void server_cursor_motion_absolute(struct wl_listener *listener, void *data);
void server_cursor_button(struct wl_listener *listener, void *data);
void server_cursor_axis(struct wl_listener *listener, void *data);
void server_cursor_frame(struct wl_listener *listener, void *data);
+void seat_request_cursor(struct wl_listener *listener, void *data);
#endif
diff --git a/input.c b/input.c
@@ -87,8 +87,23 @@ static void process_cursor_motion(struct wio_server *server, uint32_t time) {
struct wio_view *view = wio_view_at(
server, server->cursor->x, server->cursor->y, &surface, &sx, &sy);
if (!view) {
- wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
- "left_ptr", server->cursor);
+ switch (server->input_state) {
+ case INPUT_STATE_MOVE_SELECT:
+ case INPUT_STATE_RESIZE_SELECT:
+ case INPUT_STATE_DELETE_SELECT:
+ case INPUT_STATE_HIDE_SELECT:
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "hand1", server->cursor);
+ break;
+ case INPUT_STATE_MOVE:
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "grabbing", server->cursor);
+ break;
+ default:
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "left_ptr", server->cursor);
+ break;
+ }
}
if (surface) {
bool focus_changed = seat->pointer_state.focused_surface != surface;
@@ -119,6 +134,21 @@ void server_cursor_motion_absolute(
process_cursor_motion(server, event->time_msec);
}
+static void menu_handle_button(
+ struct wio_server *server, struct wlr_event_pointer_button *event) {
+ server->menu.x = server->menu.y = -1;
+ switch (server->menu.selected) {
+ case 2:
+ server->input_state = INPUT_STATE_MOVE_SELECT;
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "hand1", server->cursor);
+ break;
+ default:
+ server->input_state = INPUT_STATE_NONE;
+ break;
+ }
+}
+
static void handle_button_internal(
struct wio_server *server, struct wlr_event_pointer_button *event) {
// TODO: open menu if the client doesn't handle the button press
@@ -127,25 +157,59 @@ static void handle_button_internal(
.x = server->menu.x, .y = server->menu.y,
.width = server->menu.width, .height = server->menu.height,
};
- if (server->menu.x != -1 && server->menu.y != -1) {
+ switch (server->input_state) {
+ case INPUT_STATE_NONE:
+ if (event->state == WLR_BUTTON_PRESSED && event->button == BTN_RIGHT) {
+ // TODO: Open over the last-used menu item
+ server->input_state = INPUT_STATE_MENU;
+ server->menu.x = server->cursor->x;
+ server->menu.y = server->cursor->y;
+ }
+ break;
+ case INPUT_STATE_MENU:
if (wlr_box_contains_point(
&menu_box, server->cursor->x, server->cursor->y)) {
- // TODO: menu_handle_button()
+ menu_handle_button(server, event);
} else {
if (event->state == WLR_BUTTON_PRESSED) {
+ server->input_state = INPUT_STATE_NONE;
server->menu.x = server->menu.y = -1;
}
}
- } else {
+ break;
+ case INPUT_STATE_MOVE_SELECT:
if (event->state == WLR_BUTTON_PRESSED) {
- switch (event->button) {
- case BTN_RIGHT:
- // TODO: Open over the last-used menu item
- server->menu.x = server->cursor->x;
- server->menu.y = server->cursor->y;
- break;
+ double sx, sy;
+ struct wlr_surface *surface = NULL;
+ struct wio_view *view = wio_view_at(server,
+ server->cursor->x, server->cursor->y, &surface, &sx, &sy);
+ if (view != NULL) {
+ server->interactive.view = view;
+ server->interactive.sx = (int)sx;
+ server->interactive.sy = (int)sy;
+ server->input_state = INPUT_STATE_MOVE;
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "grabbing", server->cursor);
+ } else {
+ server->input_state = INPUT_STATE_NONE;
+ wlr_xcursor_manager_set_cursor_image(server->cursor_mgr,
+ "left_ptr", server->cursor);
}
}
+ break;
+ case INPUT_STATE_MOVE:
+ server->interactive.view->x =
+ server->cursor->x - server->interactive.sx;
+ server->interactive.view->y =
+ server->cursor->y - server->interactive.sy;
+ server->input_state = INPUT_STATE_NONE;
+ server->interactive.view = NULL;
+ wlr_cursor_set_surface(server->cursor, server->interactive.cursor,
+ server->interactive.hotspot_x, server->interactive.hotspot_y);
+ break;
+ default:
+ // TODO
+ break;
}
}
@@ -153,12 +217,11 @@ void server_cursor_button(struct wl_listener *listener, void *data) {
struct wio_server *server =
wl_container_of(listener, server, cursor_button);
struct wlr_event_pointer_button *event = data;
- // TODO: Internal button processing (e.g. resize, menus, etc)
double sx, sy;
struct wlr_surface *surface = NULL;
struct wio_view *view = wio_view_at(
server, server->cursor->x, server->cursor->y, &surface, &sx, &sy);
- if (view) {
+ if (server->input_state == INPUT_STATE_NONE && view) {
wio_view_focus(view, surface);
} else {
handle_button_internal(server, event);
@@ -180,3 +243,19 @@ void server_cursor_frame(struct wl_listener *listener, void *data) {
wl_container_of(listener, server, cursor_frame);
wlr_seat_pointer_notify_frame(server->seat);
}
+
+void seat_request_cursor(struct wl_listener *listener, void *data) {
+ struct wio_server *server = wl_container_of(
+ listener, server, request_cursor);
+ struct wlr_seat_pointer_request_set_cursor_event *event = data;
+ struct wlr_seat_client *focused_client =
+ server->seat->pointer_state.focused_client;
+ if (focused_client == event->seat_client
+ && server->input_state == INPUT_STATE_NONE) {
+ wlr_cursor_set_surface(server->cursor, event->surface,
+ event->hotspot_x, event->hotspot_y);
+ server->interactive.cursor = event->surface;
+ server->interactive.hotspot_x = event->hotspot_x;
+ server->interactive.hotspot_y = event->hotspot_y;
+ }
+}
diff --git a/main.c b/main.c
@@ -122,9 +122,9 @@ int main(int argc, char **argv) {
wl_signal_add(&server.backend->events.new_input, &server.new_input);
server.seat = wlr_seat_create(server.wl_display, "seat0");
- //server.request_cursor.notify = seat_request_cursor; // TODO
- //wl_signal_add(&server.seat->events.request_set_cursor,
- // &server.request_cursor);
+ server.request_cursor.notify = seat_request_cursor;
+ wl_signal_add(&server.seat->events.request_set_cursor,
+ &server.request_cursor);
wl_list_init(&server.keyboards);
wl_list_init(&server.pointers);
@@ -136,6 +136,7 @@ int main(int argc, char **argv) {
server.menu.x = server.menu.y = -1;
gen_menu_textures(&server);
+ server.input_state = INPUT_STATE_NONE;
const char *socket = wl_display_add_socket_auto(server.wl_display);
if (!socket) {
diff --git a/output.c b/output.c
@@ -111,6 +111,7 @@ static void render_menu(struct wio_output *output) {
box.height = (height + margin) * scale;
if (wlr_box_contains_point(
&box, server->cursor->x, server->cursor->y)) {
+ server->menu.selected = i;
texture = server->menu.active_textures[i];
wlr_render_rect(renderer, &box, menu_selected,
output->wlr_output->transform_matrix);
@@ -132,6 +133,46 @@ static void render_menu(struct wio_output *output) {
server->menu.height = text_height;
}
+static void render_view_border(struct wlr_renderer *renderer,
+ struct wio_output *output, struct wio_view *view, int x, int y) {
+ const int border = 5;
+ float color[4];
+ if (view->xdg_surface->toplevel->current.activated) {
+ memcpy(color, active_border, sizeof(color));
+ } else {
+ memcpy(color, inactive_border, sizeof(color));
+ }
+ struct wlr_box borders;
+ // Top
+ borders.x = x - border;
+ borders.y = y - border;
+ borders.width = view->xdg_surface->surface->current.width + border * 2;
+ borders.height = border;
+ wlr_render_rect(renderer, &borders, color,
+ output->wlr_output->transform_matrix);
+ // Right
+ borders.x = x + view->xdg_surface->surface->current.width;
+ borders.y = y - border;
+ borders.width = border;
+ borders.height = view->xdg_surface->surface->current.height + border * 2;
+ wlr_render_rect(renderer, &borders, color,
+ output->wlr_output->transform_matrix);
+ // Bottom
+ borders.x = x - border;
+ borders.y = y + view->xdg_surface->surface->current.height;
+ borders.width = view->xdg_surface->surface->current.width + border * 2;
+ borders.height = border;
+ wlr_render_rect(renderer, &borders, color,
+ output->wlr_output->transform_matrix);
+ // Left
+ borders.x = x - border;
+ borders.y = y - border;
+ borders.width = border;
+ borders.height = view->xdg_surface->surface->current.height + border * 2;
+ wlr_render_rect(renderer, &borders, color,
+ output->wlr_output->transform_matrix);
+}
+
static void output_frame(struct wl_listener *listener, void *data) {
struct wio_output *output = wl_container_of(listener, output, frame);
struct wio_server *server = output->server;
@@ -161,45 +202,15 @@ static void output_frame(struct wl_listener *listener, void *data) {
.renderer = renderer,
.when = &now,
};
- const int border = 5;
- float color[4];
- if (view->xdg_surface->toplevel->current.activated) {
- memcpy(color, active_border, sizeof(color));
- } else {
- memcpy(color, inactive_border, sizeof(color));
- }
- struct wlr_box borders;
- // Top
- borders.x = view->x - border;
- borders.y = view->y - border;
- borders.width = view->xdg_surface->surface->current.width + border * 2;
- borders.height = border;
- wlr_render_rect(renderer, &borders, color,
- output->wlr_output->transform_matrix);
- // Right
- borders.x = view->x + view->xdg_surface->surface->current.width;
- borders.y = view->y - border;
- borders.width = border;
- borders.height = view->xdg_surface->surface->current.height + border * 2;
- wlr_render_rect(renderer, &borders, color,
- output->wlr_output->transform_matrix);
- // Bottom
- borders.x = view->x - border;
- borders.y = view->y + view->xdg_surface->surface->current.height;
- borders.width = view->xdg_surface->surface->current.width + border * 2;
- borders.height = border;
- wlr_render_rect(renderer, &borders, color,
- output->wlr_output->transform_matrix);
- // Left
- borders.x = view->x - border;
- borders.y = view->y - border;
- borders.width = border;
- borders.height = view->xdg_surface->surface->current.height + border * 2;
- wlr_render_rect(renderer, &borders, color,
- output->wlr_output->transform_matrix);
+ render_view_border(renderer, output, view, view->x, view->y);
wlr_xdg_surface_for_each_surface(view->xdg_surface,
render_surface, &rdata);
+ if (server->interactive.view == view) {
+ render_view_border(renderer, output, view,
+ server->cursor->x - server->interactive.sx,
+ server->cursor->y - server->interactive.sy);
+ }
}
if (server->menu.x != -1 && server->menu.y != -1) {