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

main.c (8506B)


      1 #define _POSIX_C_SOURCE 200809L
      2 #include <assert.h>
      3 #include <cairo/cairo.h>
      4 #include <drm_fourcc.h>
      5 #include <getopt.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 #include <time.h>
      9 #include <wayland-server.h>
     10 #include <wlr/backend.h>
     11 #include <wlr/render/wlr_renderer.h>
     12 #include <wlr/render/wlr_texture.h>
     13 #include <wlr/types/wlr_compositor.h>
     14 #include <wlr/types/wlr_data_control_v1.h>
     15 #include <wlr/types/wlr_data_device.h>
     16 #include <wlr/types/wlr_export_dmabuf_v1.h>
     17 #include <wlr/types/wlr_gamma_control_v1.h>
     18 //#include <wlr/types/wlr_gtk_primary_selection.h>
     19 #include <wlr/types/wlr_layer_shell_v1.h>
     20 #include <wlr/types/wlr_primary_selection_v1.h>
     21 #include <wlr/types/wlr_screencopy_v1.h>
     22 #include <wlr/types/wlr_seat.h>
     23 #include <wlr/types/wlr_xcursor_manager.h>
     24 #include <wlr/types/wlr_xdg_shell.h>
     25 #include <wlr/types/wlr_xdg_output_v1.h>
     26 #include <wlr/util/log.h>
     27 #include "layers.h"
     28 #include "server.h"
     29 #include "view.h"
     30 
     31 static void gen_menu_textures(struct wio_server *server) {
     32 	struct wlr_renderer *renderer = server->renderer;
     33 	cairo_surface_t *surf = cairo_image_surface_create(
     34 			CAIRO_FORMAT_ARGB32, 128, 128); // numbers pulled from ass
     35 	cairo_t *cairo = cairo_create(surf);
     36 	cairo_select_font_face(cairo, "monospace",
     37 			CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
     38 	cairo_set_font_size(cairo, 14);
     39 	cairo_set_source_rgb(cairo, 0, 0, 0);
     40 
     41 	char *text[] = { "New", "Resize", "Move", "Delete", "Hide" };
     42 	for (size_t i = 0; i < sizeof(text) / sizeof(text[0]); ++i) {
     43 		cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
     44 		cairo_paint(cairo);
     45 		cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
     46 		cairo_text_extents_t extents;
     47 		cairo_text_extents(cairo, text[i], &extents);
     48 		cairo_move_to(cairo, 0, extents.height);
     49 		cairo_show_text(cairo, text[i]);
     50 		cairo_surface_flush(surf);
     51 		unsigned char *data = cairo_image_surface_get_data(surf);
     52 		server->menu.inactive_textures[i] = wlr_texture_from_pixels(renderer,
     53 				DRM_FORMAT_ARGB8888,
     54 				cairo_image_surface_get_stride(surf),
     55 				extents.width + 2, extents.height + 2, data);
     56 	}
     57 
     58 	cairo_set_source_rgb(cairo, 1, 1, 1);
     59 	for (size_t i = 0; i < sizeof(text) / sizeof(text[0]); ++i) {
     60 		cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
     61 		cairo_paint(cairo);
     62 		cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
     63 		cairo_text_extents_t extents;
     64 		cairo_text_extents(cairo, text[i], &extents);
     65 		cairo_move_to(cairo, 0, extents.height);
     66 		cairo_show_text(cairo, text[i]);
     67 		cairo_surface_flush(surf);
     68 		unsigned char *data = cairo_image_surface_get_data(surf);
     69 		server->menu.active_textures[i] = wlr_texture_from_pixels(renderer,
     70 				DRM_FORMAT_ARGB8888,
     71 				cairo_image_surface_get_stride(surf),
     72 				extents.width + 2, extents.height + 2, data);
     73 	}
     74 
     75 	cairo_destroy(cairo);
     76 	cairo_surface_destroy(surf);
     77 }
     78 
     79 static enum wl_output_transform str_to_transform(const char *str) {
     80 	if (strcmp(str, "normal") == 0 || strcmp(str, "0") == 0) {
     81 		return WL_OUTPUT_TRANSFORM_NORMAL;
     82 	} else if (strcmp(str, "90") == 0) {
     83 		return WL_OUTPUT_TRANSFORM_90;
     84 	} else if (strcmp(str, "180") == 0) {
     85 		return WL_OUTPUT_TRANSFORM_180;
     86 	} else if (strcmp(str, "270") == 0) {
     87 		return WL_OUTPUT_TRANSFORM_270;
     88 	} else if (strcmp(str, "flipped") == 0) {
     89 		return WL_OUTPUT_TRANSFORM_FLIPPED;
     90 	} else if (strcmp(str, "flipped-90") == 0) {
     91 		return WL_OUTPUT_TRANSFORM_FLIPPED_90;
     92 	} else if (strcmp(str, "flipped-180") == 0) {
     93 		return WL_OUTPUT_TRANSFORM_FLIPPED_180;
     94 	} else if (strcmp(str, "flipped-270") == 0) {
     95 		return WL_OUTPUT_TRANSFORM_FLIPPED_270;
     96 	} else {
     97 		fprintf(stderr, "Invalid output transform %s\n", str);
     98 		exit(1);
     99 	}
    100 }
    101 
    102 int main(int argc, char **argv) {
    103 	struct wio_server server = { 0 };
    104 	server.cage = "cage -d";
    105 	server.term = "alacritty";
    106 	wlr_log_init(WLR_DEBUG, NULL);
    107 	wl_list_init(&server.output_configs);
    108 
    109 	int c;
    110 	while ((c = getopt(argc, argv, "c:t:o:h")) != -1) {
    111 		switch (c) {
    112 		case 'c':
    113 			server.cage = optarg;
    114 			break;
    115 		case 't':
    116 			server.term = optarg;
    117 			break;
    118 		case 'o':;
    119 			// name:x:y:width:height:scale:transform
    120 			struct wio_output_config *config =
    121 				calloc(1, sizeof(struct wio_output_config));
    122 			wl_list_insert(&server.output_configs, &config->link);
    123 			const char *tok = strtok(optarg, ":");
    124 			assert(tok);
    125 			config->name = strdup(tok);
    126 			tok = strtok(NULL, ":");
    127 			assert(tok);
    128 			config->x = atoi(tok);
    129 			tok = strtok(NULL, ":");
    130 			assert(tok);
    131 			config->y = atoi(tok);
    132 			tok = strtok(NULL, ":");
    133 			if (!tok) break;
    134 			config->width = atoi(tok);
    135 			tok = strtok(NULL, ":");
    136 			assert(tok);
    137 			config->height = atoi(tok);
    138 			tok = strtok(NULL, ":");
    139 			if (!tok) break;
    140 			config->scale = atoi(tok);
    141 			tok = strtok(NULL, ":");
    142 			if (!tok) break;
    143 			config->transform = str_to_transform(tok);
    144 			break;
    145 		case 'h':
    146 			printf("Usage: %s [-t <term>] [-c <cage>] [-o <output config>...]\n",
    147 					argv[0]);
    148 			return 0;
    149 		default:
    150 			fprintf(stderr, "Unrecognized option %c\n", c);
    151 			return 1;
    152 		}
    153 	}
    154 
    155 	server.wl_display = wl_display_create();
    156 	server.backend = wlr_backend_autocreate(server.wl_display);
    157 	server.renderer = wlr_backend_get_renderer(server.backend);
    158 	wlr_renderer_init_wl_display(server.renderer, server.wl_display);
    159 
    160 	wlr_compositor_create(server.wl_display, server.renderer);
    161 	wlr_data_device_manager_create(server.wl_display);
    162 
    163 	wlr_export_dmabuf_manager_v1_create(server.wl_display);
    164 	wlr_screencopy_manager_v1_create(server.wl_display);
    165 	wlr_data_control_manager_v1_create(server.wl_display);
    166 	wlr_primary_selection_v1_device_manager_create(server.wl_display);
    167 
    168 	wlr_gamma_control_manager_v1_create(server.wl_display);
    169 //	wlr_gtk_primary_selection_device_manager_create(server.wl_display);
    170 
    171 	wl_list_init(&server.outputs);
    172 	server.new_output.notify = server_new_output;
    173 	wl_signal_add(&server.backend->events.new_output, &server.new_output);
    174 
    175 	server.output_layout = wlr_output_layout_create();
    176 	wlr_xdg_output_manager_v1_create(server.wl_display, server.output_layout);
    177 
    178 	server.cursor = wlr_cursor_create();
    179 	wlr_cursor_attach_output_layout(server.cursor, server.output_layout);
    180 	server.cursor_mgr = wlr_xcursor_manager_create(NULL, 24);
    181 	wlr_xcursor_manager_load(server.cursor_mgr, 1);
    182 
    183 	struct wio_output_config *config;
    184 	wl_list_for_each(config, &server.output_configs, link) {
    185 		if (config->scale > 1){
    186 			wlr_xcursor_manager_load(server.cursor_mgr, config->scale);
    187 		}
    188 	}
    189 
    190 	server.cursor_motion.notify = server_cursor_motion;
    191 	wl_signal_add(&server.cursor->events.motion, &server.cursor_motion);
    192 	server.cursor_motion_absolute.notify = server_cursor_motion_absolute;
    193 	wl_signal_add(&server.cursor->events.motion_absolute,
    194 			&server.cursor_motion_absolute);
    195 	server.cursor_button.notify = server_cursor_button;
    196 	wl_signal_add(&server.cursor->events.button, &server.cursor_button);
    197 	server.cursor_axis.notify = server_cursor_axis;
    198 	wl_signal_add(&server.cursor->events.axis, &server.cursor_axis);
    199 	server.cursor_frame.notify = server_cursor_frame;
    200 	wl_signal_add(&server.cursor->events.frame, &server.cursor_frame);
    201 
    202 	wl_list_init(&server.inputs);
    203 	server.new_input.notify = server_new_input;
    204 	wl_signal_add(&server.backend->events.new_input, &server.new_input);
    205 
    206 	server.seat = wlr_seat_create(server.wl_display, "seat0");
    207 	server.request_cursor.notify = seat_request_cursor;
    208 	wl_signal_add(&server.seat->events.request_set_cursor,
    209 			&server.request_cursor);
    210 	wl_list_init(&server.keyboards);
    211 	wl_list_init(&server.pointers);
    212 
    213 	wl_list_init(&server.views);
    214 	server.xdg_shell = wlr_xdg_shell_create(server.wl_display);
    215 	server.new_xdg_surface.notify = server_new_xdg_surface;
    216 	wl_signal_add(&server.xdg_shell->events.new_surface,
    217 			&server.new_xdg_surface);
    218 
    219 	wl_list_init(&server.new_views);
    220 
    221 	server.layer_shell = wlr_layer_shell_v1_create(server.wl_display);
    222 	server.new_layer_surface.notify = server_new_layer_surface;
    223 	wl_signal_add(&server.layer_shell->events.new_surface,
    224 			&server.new_layer_surface);
    225 
    226 	server.menu.x = server.menu.y = -1;
    227 	gen_menu_textures(&server);
    228 	server.input_state = INPUT_STATE_NONE;
    229 
    230 	const char *socket = wl_display_add_socket_auto(server.wl_display);
    231 	if (!socket) {
    232 		wlr_backend_destroy(server.backend);
    233 		return 1;
    234 	}
    235 
    236 	if (!wlr_backend_start(server.backend)) {
    237 		wlr_backend_destroy(server.backend);
    238 		wl_display_destroy(server.wl_display);
    239 		return 1;
    240 	}
    241 
    242 	setenv("WAYLAND_DISPLAY", socket, true);
    243 	wlr_log(WLR_INFO,
    244 			"Running Wayland compositor on WAYLAND_DISPLAY=%s", socket);
    245 	wl_display_run(server.wl_display);
    246 
    247 	wl_display_destroy_clients(server.wl_display);
    248 	wl_display_destroy(server.wl_display);
    249 	return 0;
    250 }