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

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 }