wio

a wayland wm stylised after plan9 rio - forked from git.sr.ht/~srcmpwn/wio
git clone git://src.gearsix.net/wio
Log | Files | Refs | Atom | Submodules | README | LICENSE

commit bd54842bdf91f241faf7c47968711200c478a4ce
parent 85ecbdbfed768ecab277850e3f7b5653c5fc2dfa
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed, 24 Apr 2019 23:35:27 -0400

Implement interactive move

Diffstat:
Minclude/server.h | 25+++++++++++++++++++++++++
Minput.c | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mmain.c | 7++++---
Moutput.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) {