view.c (5933B)
1 #include <stdlib.h> 2 #include <wayland-server.h> 3 #include <wlr/types/wlr_xdg_shell.h> 4 #include "xdg-shell-protocol.h" 5 #include "server.h" 6 #include "view.h" 7 8 static void xdg_surface_map(struct wl_listener *listener, void *data) { 9 struct wio_view *view = wl_container_of(listener, view, map); 10 struct wio_server *server = view->server; 11 wio_view_focus(view, view->xdg_surface->surface); 12 13 struct wlr_output *output = wlr_output_layout_output_at( 14 server->output_layout, server->cursor->x, server->cursor->y); 15 struct wlr_output_layout_output *layout = wlr_output_layout_get( 16 server->output_layout, output); 17 if (view->x == -1 || view->y == -1) { 18 struct wlr_surface_state *current = 19 &view->xdg_surface->surface->current; 20 int owidth, oheight; 21 wlr_output_effective_resolution(output, &owidth, &oheight); 22 wio_view_move(view, 23 layout->x + (owidth / 2 - current->width / 2), 24 layout->y + (oheight / 2 - current->height / 2)); 25 } else { 26 // Sends wl_surface_enter 27 wio_view_move(view, view->x, view->y); 28 } 29 } 30 31 static void xdg_surface_destroy(struct wl_listener *listener, void *data) { 32 struct wio_view *view = wl_container_of(listener, view, destroy); 33 wl_list_remove(&view->link); 34 free(view); 35 } 36 37 void server_new_xdg_surface(struct wl_listener *listener, void *data) { 38 struct wio_server *server = wl_container_of( 39 listener, server, new_xdg_surface); 40 struct wlr_xdg_surface *xdg_surface = data; 41 if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) { 42 return; 43 } 44 45 struct wio_view *view = calloc(1, sizeof(struct wio_view)); 46 view->server = server; 47 view->xdg_surface = xdg_surface; 48 view->x = view->y = -1; 49 50 view->destroy.notify = xdg_surface_destroy; 51 wl_signal_add(&xdg_surface->events.destroy, &view->destroy); 52 view->map.notify = xdg_surface_map; 53 wl_signal_add(&xdg_surface->events.map, &view->map); 54 55 wlr_xdg_toplevel_set_tiled(view->xdg_surface, 56 WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM); 57 58 pid_t pid; 59 uid_t uid; 60 gid_t gid; 61 struct wl_client *client = wl_resource_get_client(xdg_surface->resource); 62 wl_client_get_credentials(client, &pid, &uid, &gid); 63 struct wio_new_view *new_view; 64 wl_list_for_each(new_view, &server->new_views, link) { 65 if (new_view->pid != pid) { 66 continue; 67 } 68 view->x = new_view->box.x; 69 view->y = new_view->box.y; 70 wlr_xdg_toplevel_set_size(xdg_surface, 71 new_view->box.width, new_view->box.height); 72 wl_list_remove(&new_view->link); 73 free(new_view); 74 break; 75 } 76 77 wl_list_insert(&server->views, &view->link); 78 } 79 80 void wio_view_focus(struct wio_view *view, struct wlr_surface *surface) { 81 if (view == NULL) { 82 return; 83 } 84 struct wio_server *server = view->server; 85 struct wlr_seat *seat = server->seat; 86 struct wlr_surface *prev_surface = seat->keyboard_state.focused_surface; 87 if (prev_surface == surface) { 88 return; 89 } 90 if (prev_surface) { 91 struct wlr_xdg_surface *previous = wlr_xdg_surface_from_wlr_surface( 92 seat->keyboard_state.focused_surface); 93 wlr_xdg_toplevel_set_activated(previous, false); 94 } 95 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat); 96 wlr_xdg_toplevel_set_activated(view->xdg_surface, true); 97 wlr_seat_keyboard_notify_enter(seat, view->xdg_surface->surface, 98 keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers); 99 /* bring to front */ 100 wl_list_remove(&view->link); 101 wl_list_insert(&view->server->views, &view->link); 102 } 103 104 static bool view_at(struct wio_view *view, 105 double lx, double ly, struct wlr_surface **surface, 106 double *sx, double *sy) { 107 double view_sx = lx - view->x; 108 double view_sy = ly - view->y; 109 110 double _sx, _sy; 111 struct wlr_surface *_surface = NULL; 112 _surface = wlr_xdg_surface_surface_at( 113 view->xdg_surface, view_sx, view_sy, &_sx, &_sy); 114 115 if (_surface != NULL) { 116 *sx = _sx; 117 *sy = _sy; 118 *surface = _surface; 119 return true; 120 } 121 122 return false; 123 } 124 125 struct wio_view *wio_view_at(struct wio_server *server, double lx, double ly, 126 struct wlr_surface **surface, double *sx, double *sy, 127 int *view_area) { 128 struct wlr_box border_box = { 129 .x = 0, .y = 0, 130 .width = 0, .height = 0, 131 }; 132 struct wio_view *view; 133 wl_list_for_each(view, &server->views, link) { 134 // Surface 135 if (view_at(view, lx, ly, surface, sx, sy)) { 136 *view_area = VIEW_AREA_SURFACE; 137 return view; 138 } 139 // Top border 140 border_box.height = window_border; 141 border_box.width = view->xdg_surface->surface->current.width; 142 border_box.x = view->x; 143 border_box.y = view->y - window_border; 144 if (wlr_box_contains_point(&border_box, server->cursor->x, server->cursor->y)) { 145 *view_area = VIEW_AREA_BORDER_TOP; 146 return view; 147 } 148 149 // Right border 150 border_box.height = view->xdg_surface->surface->current.height; 151 border_box.width = window_border; 152 border_box.x = view->x + view->xdg_surface->surface->current.width; 153 border_box.y = view->y; 154 if (wlr_box_contains_point(&border_box, server->cursor->x, server->cursor->y)) { 155 *view_area = VIEW_AREA_BORDER_RIGHT; 156 return view; 157 } 158 159 // Bottom border 160 border_box.height = window_border; 161 border_box.width = view->xdg_surface->surface->current.width; 162 border_box.x = view->x; 163 border_box.y = view->y + view->xdg_surface->surface->current.height; 164 if (wlr_box_contains_point(&border_box, server->cursor->x, server->cursor->y)) { 165 *view_area = VIEW_AREA_BORDER_BOTTOM; 166 return view; 167 } 168 169 // Left border 170 border_box.height = view->xdg_surface->surface->current.height; 171 border_box.width = window_border; 172 border_box.x = view->x - window_border; 173 border_box.y = view->y; 174 if (wlr_box_contains_point(&border_box, server->cursor->x, server->cursor->y)) { 175 *view_area = VIEW_AREA_BORDER_LEFT; 176 return view; 177 } 178 } 179 return NULL; 180 } 181 182 void wio_view_move(struct wio_view *view, int x, int y) { 183 view->x = x; 184 view->y = y; 185 186 // Cheating as FUCK because I'm lazy 187 struct wio_output *output; 188 wl_list_for_each(output, &view->server->outputs, link) { 189 wlr_surface_send_enter(view->xdg_surface->surface, output->wlr_output); 190 } 191 }