mirror of
				https://codeberg.org/dwl/dwl.git
				synced 2025-10-30 19:44:17 +00:00 
			
		
		
		
	
						commit
						45a2e25d6d
					
				| @ -51,6 +51,9 @@ static const int repeat_delay = 600; | ||||
| 	{ MODKEY|WLR_MODIFIER_SHIFT, SKEY,           tag,             {.ui = 1 << TAG} }, \ | ||||
| 	{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } | ||||
| 
 | ||||
| /* helper for spawning shell commands in the pre dwm-5.0 fashion */ | ||||
| #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } | ||||
| 
 | ||||
| /* commands */ | ||||
| static const char *termcmd[]  = { "alacritty", NULL }; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										180
									
								
								dwl.c
									
									
									
									
									
								
							
							
						
						
									
										180
									
								
								dwl.c
									
									
									
									
									
								
							| @ -17,6 +17,7 @@ | ||||
| #include <wlr/types/wlr_cursor.h> | ||||
| #include <wlr/types/wlr_data_device.h> | ||||
| #include <wlr/types/wlr_export_dmabuf_v1.h> | ||||
| #include <wlr/types/wlr_gamma_control_v1.h> | ||||
| #include <wlr/types/wlr_input_device.h> | ||||
| #include <wlr/types/wlr_keyboard.h> | ||||
| #include <wlr/types/wlr_matrix.h> | ||||
| @ -40,6 +41,8 @@ | ||||
| #endif | ||||
| 
 | ||||
| /* macros */ | ||||
| #define BARF(fmt, ...)		do { fprintf(stderr, fmt "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); } while (0) | ||||
| #define EBARF(fmt, ...)		BARF(fmt ": %s", ##__VA_ARGS__, strerror(errno)) | ||||
| #define MAX(A, B)               ((A) > (B) ? (A) : (B)) | ||||
| #define MIN(A, B)               ((A) < (B) ? (A) : (B)) | ||||
| #define CLEANMASK(mask)         (mask & ~WLR_MODIFIER_CAPS) | ||||
| @ -55,9 +58,9 @@ | ||||
| 
 | ||||
| /* enums */ | ||||
| enum { CurNormal, CurMove, CurResize }; /* cursor */ | ||||
| #ifdef XWAYLAND | ||||
| enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar, | ||||
| 	NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */ | ||||
| #ifdef XWAYLAND | ||||
| enum { XDGShell, X11Managed, X11Unmanaged }; /* client types */ | ||||
| #endif | ||||
| 
 | ||||
| @ -177,6 +180,7 @@ static void arrange(Monitor *m); | ||||
| static void axisnotify(struct wl_listener *listener, void *data); | ||||
| static void buttonpress(struct wl_listener *listener, void *data); | ||||
| static void chvt(const Arg *arg); | ||||
| static void cleanup(void); | ||||
| static void cleanupkeyboard(struct wl_listener *listener, void *data); | ||||
| static void cleanupmon(struct wl_listener *listener, void *data); | ||||
| static void commitnotify(struct wl_listener *listener, void *data); | ||||
| @ -224,6 +228,7 @@ static void setlayout(const Arg *arg); | ||||
| static void setmfact(const Arg *arg); | ||||
| static void setmon(Client *c, Monitor *m, unsigned int newtags); | ||||
| static void setup(void); | ||||
| static void sigchld(int unused); | ||||
| static void spawn(const Arg *arg); | ||||
| static void tag(const Arg *arg); | ||||
| static void tagmon(const Arg *arg); | ||||
| @ -286,6 +291,7 @@ static Atom getatom(xcb_connection_t *xc, const char *name); | ||||
| static void renderindependents(struct wlr_output *output, struct timespec *now); | ||||
| static void updatewindowtype(Client *c); | ||||
| static void xwaylandready(struct wl_listener *listener, void *data); | ||||
| static Client *xytoindependent(double x, double y); | ||||
| static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11}; | ||||
| static struct wl_listener xwayland_ready = {.notify = xwaylandready}; | ||||
| static struct wlr_xwayland *xwayland; | ||||
| @ -327,8 +333,8 @@ applyrules(Client *c) | ||||
| 	/* rule matching */ | ||||
| 	c->isfloating = 0; | ||||
| #ifdef XWAYLAND | ||||
| 	updatewindowtype(c); | ||||
| 	if (c->type != XDGShell) { | ||||
| 		updatewindowtype(c); | ||||
| 		appid = c->surface.xwayland->class; | ||||
| 		title = c->surface.xwayland->title; | ||||
| 	} else | ||||
| @ -427,10 +433,21 @@ buttonpress(struct wl_listener *listener, void *data) | ||||
| void | ||||
| chvt(const Arg *arg) | ||||
| { | ||||
| 	struct wlr_session *s = wlr_backend_get_session(backend); | ||||
| 	if (!s) | ||||
| 		return; | ||||
| 	wlr_session_change_vt(s, arg->ui); | ||||
| 	wlr_session_change_vt(wlr_backend_get_session(backend), arg->ui); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| cleanup(void) | ||||
| { | ||||
| #ifdef XWAYLAND | ||||
| 	wlr_xwayland_destroy(xwayland); | ||||
| #endif | ||||
| 	wl_display_destroy_clients(dpy); | ||||
| 	wl_display_destroy(dpy); | ||||
| 
 | ||||
| 	wlr_xcursor_manager_destroy(cursor_mgr); | ||||
| 	wlr_cursor_destroy(cursor); | ||||
| 	wlr_output_layout_destroy(output_layout); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| @ -971,7 +988,16 @@ motionnotify(uint32_t time) | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| #ifdef XWAYLAND | ||||
| 	/* Find an independent under the pointer and send the event along. */ | ||||
| 	if ((c = xytoindependent(cursor->x, cursor->y))) { | ||||
| 		surface = wlr_surface_surface_at(c->surface.xwayland->surface, | ||||
| 				cursor->x - c->surface.xwayland->x - c->bw, | ||||
| 				cursor->y - c->surface.xwayland->y - c->bw, &sx, &sy); | ||||
| 
 | ||||
| 	/* Otherwise, find the client under the pointer and send the event along. */ | ||||
| 	} else | ||||
| #endif | ||||
| 	if ((c = xytoclient(cursor->x, cursor->y))) { | ||||
| #ifdef XWAYLAND | ||||
| 		if (c->type != XDGShell) | ||||
| @ -1060,6 +1086,12 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, | ||||
| 	/* Otherwise, let the client know that the mouse cursor has entered one
 | ||||
| 	 * of its surfaces, and make keyboard focus follow if desired. */ | ||||
| 	wlr_seat_pointer_notify_enter(seat, surface, sx, sy); | ||||
| 
 | ||||
| #if XWAYLAND | ||||
| 	if (c->type == X11Unmanaged) | ||||
| 		return; | ||||
| #endif | ||||
| 
 | ||||
| 	if (sloppyfocus) | ||||
| 		focusclient(selclient(), c, 0); | ||||
| } | ||||
| @ -1266,20 +1298,13 @@ run(char *startup_cmd) | ||||
| 
 | ||||
| 	/* Add a Unix socket to the Wayland display. */ | ||||
| 	const char *socket = wl_display_add_socket_auto(dpy); | ||||
| 	if (!socket) { | ||||
| 		perror("startup: display_add_socket_auto"); | ||||
| 		wlr_backend_destroy(backend); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 	if (!socket) | ||||
| 		BARF("startup: display_add_socket_auto"); | ||||
| 
 | ||||
| 	/* Start the backend. This will enumerate outputs and inputs, become the DRM
 | ||||
| 	 * master, etc */ | ||||
| 	if (!wlr_backend_start(backend)) { | ||||
| 		perror("startup: backend_start"); | ||||
| 		wlr_backend_destroy(backend); | ||||
| 		wl_display_destroy(dpy); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 	if (!wlr_backend_start(backend)) | ||||
| 		BARF("startup: backend_start"); | ||||
| 
 | ||||
| 	/* Now that outputs are initialized, choose initial selmon based on
 | ||||
| 	 * cursor position, and set default cursor image */ | ||||
| @ -1297,24 +1322,17 @@ run(char *startup_cmd) | ||||
| 	setenv("WAYLAND_DISPLAY", socket, 1); | ||||
| 	if (startup_cmd) { | ||||
| 		startup_pid = fork(); | ||||
| 		if (startup_pid < 0) { | ||||
| 			perror("startup: fork"); | ||||
| 			wl_display_destroy(dpy); | ||||
| 			exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 		if (startup_pid < 0) | ||||
| 			EBARF("startup: fork"); | ||||
| 		if (startup_pid == 0) { | ||||
| 			execl("/bin/sh", "/bin/sh", "-c", startup_cmd, (void *)NULL); | ||||
| 			perror("startup: execl"); | ||||
| 			wl_display_destroy(dpy); | ||||
| 			exit(EXIT_FAILURE); | ||||
| 			EBARF("startup: execl"); | ||||
| 		} | ||||
| 	} | ||||
| 	/* Run the Wayland event loop. This does not return until you exit the
 | ||||
| 	 * compositor. Starting the backend rigged up all of the necessary event | ||||
| 	 * loop configuration to listen to libinput events, DRM events, generate | ||||
| 	 * frame events at the refresh rate, and so on. */ | ||||
| 	wlr_log(WLR_INFO, "Running Wayland compositor on WAYLAND_DISPLAY=%s", | ||||
| 			socket); | ||||
| 	wl_display_run(dpy); | ||||
| 
 | ||||
| 	if (startup_cmd) { | ||||
| @ -1445,6 +1463,13 @@ setsel(struct wl_listener *listener, void *data) | ||||
| void | ||||
| setup(void) | ||||
| { | ||||
| 	/* The Wayland display is managed by libwayland. It handles accepting
 | ||||
| 	 * clients from the Unix socket, manging Wayland globals, and so on. */ | ||||
| 	dpy = wl_display_create(); | ||||
| 
 | ||||
| 	/* clean up child processes immediately */ | ||||
| 	sigchld(0); | ||||
| 
 | ||||
| 	/* The backend is a wlroots feature which abstracts the underlying input and
 | ||||
| 	 * output hardware. The autocreate option will choose the most suitable | ||||
| 	 * backend based on the current environment, such as opening an X11 window | ||||
| @ -1453,7 +1478,8 @@ setup(void) | ||||
| 	 * backend uses the renderer, for example, to fall back to software cursors | ||||
| 	 * if the backend does not support hardware cursors (some older GPUs | ||||
| 	 * don't). */ | ||||
| 	backend = wlr_backend_autocreate(dpy, NULL); | ||||
| 	if (!(backend = wlr_backend_autocreate(dpy, NULL))) | ||||
| 		BARF("couldn't create backend"); | ||||
| 
 | ||||
| 	/* If we don't provide a renderer, autocreate makes a GLES2 renderer for us.
 | ||||
| 	 * The renderer is responsible for defining the various pixel formats it | ||||
| @ -1471,6 +1497,7 @@ setup(void) | ||||
| 	wlr_export_dmabuf_manager_v1_create(dpy); | ||||
| 	wlr_screencopy_manager_v1_create(dpy); | ||||
| 	wlr_data_device_manager_create(dpy); | ||||
| 	wlr_gamma_control_manager_v1_create(dpy); | ||||
| 	wlr_primary_selection_v1_device_manager_create(dpy); | ||||
| 	wlr_viewporter_create(dpy); | ||||
| 
 | ||||
| @ -1566,15 +1593,22 @@ setup(void) | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void | ||||
| sigchld(int unused) | ||||
| { | ||||
| 	if (signal(SIGCHLD, sigchld) == SIG_ERR) | ||||
| 		EBARF("can't install SIGCHLD handler"); | ||||
| 	while (0 < waitpid(-1, NULL, WNOHANG)) | ||||
| 		; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| spawn(const Arg *arg) | ||||
| { | ||||
| 	if (fork() == 0) { | ||||
| 		setsid(); | ||||
| 		execvp(((char **)arg->v)[0], (char **)arg->v); | ||||
| 		fprintf(stderr, "dwl: execvp %s", ((char **)arg->v)[0]); | ||||
| 		perror(" failed"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 		EBARF("dwl: execvp %s failed", ((char **)arg->v)[0]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -1827,14 +1861,12 @@ void | ||||
| updatewindowtype(Client *c) | ||||
| { | ||||
| 	size_t i; | ||||
| 
 | ||||
| 	if (c->type != XDGShell) | ||||
| 		for (i = 0; i < c->surface.xwayland->window_type_len; i++) | ||||
| 			if (c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeDialog] || | ||||
| 					c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeSplash] || | ||||
| 					c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeToolbar] || | ||||
| 					c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeUtility]) | ||||
| 				c->isfloating = 1; | ||||
| 	for (i = 0; i < c->surface.xwayland->window_type_len; i++) | ||||
| 		if (c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeDialog] || | ||||
| 				c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeSplash] || | ||||
| 				c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeToolbar] || | ||||
| 				c->surface.xwayland->window_type[i] == netatom[NetWMWindowTypeUtility]) | ||||
| 			c->isfloating = 1; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| @ -1859,65 +1891,53 @@ xwaylandready(struct wl_listener *listener, void *data) | ||||
| 
 | ||||
| 	xcb_disconnect(xc); | ||||
| } | ||||
| 
 | ||||
| Client * | ||||
| xytoindependent(double x, double y) | ||||
| { | ||||
| 	/* Find the topmost visible independent at point (x, y).
 | ||||
| 	 * For independents, the most recently created can be used as the "top". | ||||
| 	 * We rely on the X11 convention of unmapping unmanaged when the "owning" | ||||
| 	 * client loses focus, which ensures that unmanaged are only visible on | ||||
| 	 * the current tag. */ | ||||
| 	Client *c; | ||||
| 	struct wlr_box geom; | ||||
| 	wl_list_for_each_reverse(c, &independents, link) { | ||||
| 		geom.x = c->surface.xwayland->x; | ||||
| 		geom.y = c->surface.xwayland->y; | ||||
| 		geom.width = c->surface.xwayland->width; | ||||
| 		geom.height = c->surface.xwayland->height; | ||||
| 		if (wlr_box_contains_point(&geom, x, y)) | ||||
| 			return c; | ||||
| 	} | ||||
| 	return NULL; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
| 	char *startup_cmd = NULL; | ||||
| 	enum wlr_log_importance loglevel = WLR_ERROR; | ||||
| 
 | ||||
| 	int c; | ||||
| 	while ((c = getopt(argc, argv, "qvds:h")) != -1) { | ||||
| 		switch (c) { | ||||
| 		case 'q': | ||||
| 			loglevel = WLR_SILENT; | ||||
| 			break; | ||||
| 		case 'v': | ||||
| 			loglevel = WLR_INFO; | ||||
| 			break; | ||||
| 		case 'd': | ||||
| 			loglevel = WLR_DEBUG; | ||||
| 			break; | ||||
| 		case 's': | ||||
| 
 | ||||
| 	while ((c = getopt(argc, argv, "s:h")) != -1) { | ||||
| 		if (c == 's') | ||||
| 			startup_cmd = optarg; | ||||
| 			break; | ||||
| 		default: | ||||
| 		else | ||||
| 			goto usage; | ||||
| 		} | ||||
| 	} | ||||
| 	if (optind < argc) | ||||
| 		goto usage; | ||||
| 	wlr_log_init(loglevel, NULL); | ||||
| 
 | ||||
| 	// Wayland requires XDG_RUNTIME_DIR for creating its communications
 | ||||
| 	// socket
 | ||||
| 	if (!getenv("XDG_RUNTIME_DIR")) { | ||||
| 		fprintf(stderr, "XDG_RUNTIME_DIR must be set\n"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 
 | ||||
| 	/* The Wayland display is managed by libwayland. It handles accepting
 | ||||
| 	 * clients from the Unix socket, manging Wayland globals, and so on. */ | ||||
| 	dpy = wl_display_create(); | ||||
| 
 | ||||
| 	if (!getenv("XDG_RUNTIME_DIR")) | ||||
| 		BARF("XDG_RUNTIME_DIR must be set"); | ||||
| 	setup(); | ||||
| 	run(startup_cmd); | ||||
| 
 | ||||
| 	/* Once wl_display_run returns, we shut down the server. */ | ||||
| #ifdef XWAYLAND | ||||
| 	wlr_xwayland_destroy(xwayland); | ||||
| #endif | ||||
| 	wl_display_destroy_clients(dpy); | ||||
| 	wl_display_destroy(dpy); | ||||
| 
 | ||||
| 	wlr_xcursor_manager_destroy(cursor_mgr); | ||||
| 	wlr_cursor_destroy(cursor); | ||||
| 	wlr_output_layout_destroy(output_layout); | ||||
| 
 | ||||
| 	cleanup(); | ||||
| 	return EXIT_SUCCESS; | ||||
| 
 | ||||
| usage: | ||||
| 	printf("Usage: %s [-qvd] [-s startup command]\n", argv[0]); | ||||
| 	return EXIT_FAILURE; | ||||
| 	BARF("Usage: %s [-s startup command]", argv[0]); | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Bonicgamer
						Bonicgamer