wio

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

view.c (raw) (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 }