diff options
| -rw-r--r-- | README.md | 14 | ||||
| -rw-r--r-- | client.h | 4 | ||||
| -rw-r--r-- | config.def.h | 2 | ||||
| -rw-r--r-- | config.mk | 2 | ||||
| -rw-r--r-- | dwl.1 | 124 | ||||
| -rw-r--r-- | dwl.c | 61 | 
6 files changed, 158 insertions, 49 deletions
| @@ -15,10 +15,11 @@ philosophy. Like dwm, dwl is:  ## Getting Started:  ### Latest semi-stable [release] -This is probably where you want to start. This builds against the dependent -packages' versions currently shipping in major distributions. If your -distribution's wlroots version is older, use an earlier dwl [release] or [0.x -branch]. +This is probably where you want to start. This builds against the [wlroots] +versions currently shipping in major distributions. If your +distribution's `wlroots` version is older, use an earlier dwl [release]. +The `wlroots` version against which a given `dwl` release builds is specified +with each release on the [release] page  ### Development branch [main]  Active development progresses on the `main` branch. The `main` branch is built @@ -74,7 +75,7 @@ seatd daemon.  When dwl is run with no arguments, it will launch the server and begin handling  any shortcuts configured in `config.h`. There is no status bar or other  decoration initially; these are instead clients that can be run within the -Wayland session. Do note that the default background color is black. This can be +Wayland session. Do note that the default background color is grey. This can be  modified in `config.h`.  If you would like to run a script or command automatically at startup, you can @@ -102,7 +103,7 @@ automatically, you will need to configure it prior to launching `dwl`, e.g.:  Information about selected layouts, current window title, app-id, and  selected/occupied/urgent tags is written to the stdin of the `-s` command (see -the `printstatus()` function for details).  This information can be used to +the `STATUS INFORMATION` section in `_dwl_(1)`).  This information can be used to  populate an external status bar with a script that parses the  information. Failing to read this information will cause dwl to block, so if you  do want to run a startup command that does not consume the status information, @@ -181,6 +182,7 @@ inspiration, and to the various contributors to the project, including:  - Stivvo for output management and fullscreen support, and patch maintenance +[wlroots]: https://gitlab.freedesktop.org/wlroots  [`systemd --user`]: https://wiki.archlinux.org/title/Systemd/User  [#dwl on Libera Chat]: https://web.libera.chat/?channels=#dwl  [0.7-rc1]: https://codeberg.org/dwl/dwl/releases/tag/v0.7-rc1 @@ -264,8 +264,8 @@ client_is_stopped(Client *c)  	wl_client_get_credentials(c->surface.xdg->client->client, &pid, NULL, NULL);  	if (waitid(P_PID, pid, &in, WNOHANG|WCONTINUED|WSTOPPED|WNOWAIT) < 0) { -		/* This process is not our child process, while is very unluckely that -		 * it is stopped, in order to do not skip frames assume that it is. */ +		/* This process is not our child process, while is very unlikely that +		 * it is stopped, in order to do not skip frames, assume that it is. */  		if (errno == ECHILD)  			return 1;  	} else if (in.si_pid) { diff --git a/config.def.h b/config.def.h index 66a26ea..6aa97a6 100644 --- a/config.def.h +++ b/config.def.h @@ -17,7 +17,7 @@ static const float bordercolor[]             = COLOR(0x0f1212ff);  static const float focuscolor[]            = COLOR(0x607767ff);  static const float urgentcolor[]           = COLOR(0x202222ff);  /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */ -static const float fullscreen_bg[]         = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */ +static const float fullscreen_bg[]         = {0.0f, 0.0f, 0.0f, 1.0f}; /* You can also use glsl colors */  /* tagging - TAGCOUNT must be no greater than 31 */  #define TAGCOUNT (9) @@ -11,7 +11,7 @@ DATADIR = $(PREFIX)/share  WLR_INCS = `$(PKG_CONFIG) --cflags wlroots-0.19`  WLR_LIBS = `$(PKG_CONFIG) --libs wlroots-0.19` -# Allow using an alternative wlroots installations +# Allow using an alternative wlroots installation  # This has to have all the includes required by wlroots, e.g:  # Assuming wlroots git repo is "${PWD}/wlroots" and you only ran "meson setup build && ninja -C build"  #WLR_INCS = -I/usr/include/pixman-1 -I/usr/include/elogind -I/usr/include/libdrm \ @@ -37,7 +37,7 @@ starts a shell process running  when starting.  When stopping, it sends  .Dv SIGTERM -to the child process and waits for it to exit. +to the child process group and waits for it to exit.  .Pp  Users are encouraged to customize  .Nm @@ -55,10 +55,10 @@ Move window to a single tag.  Toggle tag for window.  .It Mod-p  Spawn -.Nm wmenu-run . +.Xr wmenu-run 1 .  .It Mod-Shift-Return  Spawn -.Nm foot . +.Xr foot 1 .  .It Mod-[jk]  Move focus down/up the stack.  .It Mod-[id] @@ -100,6 +100,114 @@ Quit  .Nm .  .El  These might differ depending on your keyboard layout. +.Ss Mouse commands +.Bl -tag -width 20n -offset indent -compact +.It Mod-Button1 +Move focused window while dragging. +Tiled windows will be toggled to the floating state. +.It Mod-Button2 +Toggle focused window between floating and tiled state. +.It Mod-Button3 +Resize focused window while dragging. +Tiled windows will be toggled to the floating state. +.El +.Sh STATUS INFORMATION +.Nm +writes its status information to standard output. +If the +.Fl s +option is given, the status information is written to the standard input of the +child process instead. +.Pp +Said information has the following format: +.Bd -ragged -offset indent +.Ar <monitor> +.Ar <component> +.Ar <data> +.Ed +.Pp +.Bl -tag -width 11n -offset 0 -compact +.It Ar <monitor> +is the name given to the output. +.It Ar <component> +is one of (in order) +.Em title , +.Em appid , +.Em fullscreen , +.Em floating , +.Em selmon , +.Em tags , +.Em layout . +.It Ar <data> +changes depending on +.Ar <component> . +.Bl -tag -width 10n -compact +.It Em title +The title of the focused window on +.Ar <monitor> +or nothing if there is no focused window. +.It Em appid +The app_id of the focused window on +.Ar <monitor> +or nothing if there is no focused window. +.It Em fullscreen +Prints 1 if the focused window on +.Ar <monitor> +is in fullscreen state, otherwise prints 0. If there is no focused +window it prints nothing. +.It Em floating +Prints 1 if the focused window on +.Ar <monitor> +is in floating state, otherwise prints 0. If there is no focused +window it prints nothing. +.It Em selmon +Prints 1 if +.Ar <monitor> +is the selected monitor, otherwise prints 0. +.It Em tags +Prints four bitmasks in the following order: +.Bl -bullet -width 2n -compact +.It +Occupied tags of +.Ar <monitor> . +.It +Selected tags of +.Ar <monitor> . +.It +Tags of the focused window on +.Ar <monitor> . +.It +Tags where a window on +.Ar <monitor> +requested activation or has urgency hints. +.El +The bitmasks are 32-bit unsigned decimal integers. +.It Em layout +Prints the symbol of the current layout. +.El +.El +.Ss Examples +When there is a selected window: +.Bd -literal -offset indent +HDMI\-A\-1 title \(ti/source/repos/dwl > man \-l dwl.1 +HDMI\-A\-1 appid footclient +HDMI\-A\-1 fullscreen 0 +HDMI\-A\-1 floating 0 +HDMI\-A\-1 selmon 1 +HDMI\-A\-1 tags 271 4 4 0 +HDMI\-A\-1 layout [T] +.Ed +.Pp +When there is no selected window: +.Bd -literal -offset indent +HDMI\-A\-1 title +HDMI\-A\-1 appid +HDMI\-A\-1 fullscreen +HDMI\-A\-1 floating +HDMI\-A\-1 selmon 1 +HDMI\-A\-1 tags 271 512 0 0 +HDMI\-A\-1 layout [T] +.Ed  .Sh ENVIRONMENT  These environment variables are used by  .Nm : @@ -142,17 +250,9 @@ Start  with s6 in the background:  .Dl dwl \-s \(aqs6\-svscan <&\-\(aq  .Sh SEE ALSO +.Xr dwm 1 ,  .Xr foot 1 ,  .Xr wmenu 1 , -.Xr dwm 1 ,  .Xr xkeyboard-config 7 -.Sh CAVEATS -The child process's standard input is connected with a pipe to -.Nm . -If the child process neither reads from the pipe nor closes its -standard input, -.Nm -will freeze after a while due to it blocking when writing to the full -pipe buffer.  .Sh BUGS  All of them. @@ -499,7 +499,6 @@ applyrules(Client *c)  	const Rule *r;  	Monitor *mon = selmon, *m; -	c->isfloating = client_is_float_type(c);  	appid = client_get_appid(c);  	title = client_get_title(c); @@ -519,6 +518,8 @@ applyrules(Client *c)  		c->geom.x = (mon->w.width - c->geom.width) / 2 + mon->m.x;  		c->geom.y = (mon->w.height - c->geom.height) / 2 + mon->m.y;  	} + +	c->isfloating |= client_is_float_type(c);  	setmon(c, mon, newtags);  } @@ -571,6 +572,9 @@ arrangelayer(Monitor *m, struct wl_list *list, struct wlr_box *usable_area, int  	wl_list_for_each(l, list, link) {  		struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; +		if (!layer_surface->initialized) +			continue; +  		if (exclusive != (layer_surface->current.exclusive_zone > 0))  			continue; @@ -647,8 +651,8 @@ axisnotify(struct wl_listener *listener, void *data)  	 * for example when you move the scroll wheel. */  	struct wlr_pointer_axis_event *event = data;  	wlr_idle_notifier_v1_notify_activity(idle_notifier, seat); -	/* TODO: allow usage of scroll whell for mousebindings, it can be implemented -	 * checking the event's orientation and the delta of the event */ +	/* TODO: allow usage of scroll wheel for mousebindings, it can be implemented +	 * by checking the event's orientation and the delta of the event */  	/* Notify the client with pointer focus of the axis event. */  	wlr_seat_pointer_notify_axis(seat,  			event->time_msec, event->orientation, event->delta, @@ -760,8 +764,8 @@ cleanup(void)  	destroykeyboardgroup(&kb_group->destroy, NULL); -	/* If it's not destroyed manually it will cause a use-after-free of wlr_seat. -	 * Destroy it until it's fixed in the wlroots side */ +	/* If it's not destroyed manually, it will cause a use-after-free of wlr_seat. +	 * Destroy it until it's fixed on the wlroots side */  	wlr_backend_destroy(backend);  	wl_display_destroy(dpy); @@ -787,6 +791,8 @@ cleanupmon(struct wl_listener *listener, void *data)  	wl_list_remove(&m->frame.link);  	wl_list_remove(&m->link);  	wl_list_remove(&m->request_state.link); +	if (m->lock_surface) +		destroylocksurface(&m->destroy_lock_surface, NULL);  	m->wlr_output->data = NULL;  	wlr_output_layout_remove(output_layout, m->wlr_output);  	wlr_scene_output_destroy(m->scene_output); @@ -907,7 +913,7 @@ commitnotify(struct wl_listener *listener, void *data)  		/*  		 * Get the monitor this client will be rendered on  		 * Note that if the user set a rule in which the client is placed on -		 * a different monitor based on its title this will likely select +		 * a different monitor based on its title, this will likely select  		 * a wrong monitor.  		 */  		applyrules(c); @@ -1274,7 +1280,7 @@ cursorconstrain(struct wlr_pointer_constraint_v1 *constraint)  void  cursorframe(struct wl_listener *listener, void *data)  { -	/* This event is forwarded by the cursor when a pointer emits an frame +	/* This event is forwarded by the cursor when a pointer emits a frame  	 * event. Frame events are sent after regular pointer events to group  	 * multiple events together. For instance, two axis events may happen at the  	 * same time, in which case a frame event won't be sent in between. */ @@ -1570,7 +1576,7 @@ focusstack(const Arg *arg)  	focusclient(c, 1);  } -/* We probably should change the name of this, it sounds like +/* We probably should change the name of this: it sounds like it   * will focus the topmost client of this mon, when actually will   * only return that client */  Client * @@ -1847,8 +1853,8 @@ mapnotify(struct wl_listener *listener, void *data)  	/* Set initial monitor, tags, floating status, and focus:  	 * we always consider floating, clients that have parent and thus -	 * we set the same tags and monitor than its parent, if not -	 * try to apply rules for them */ +	 * we set the same tags and monitor as its parent. +	 * If there is no parent, apply rules */  	if ((p = client_get_parent(c))) {  		c->isfloating = 1;  		if (p->mon) { @@ -1912,8 +1918,7 @@ motionabsolute(struct wl_listener *listener, void *data)  	 * motion event, from 0..1 on each axis. This happens, for example, when  	 * wlroots is running under a Wayland window rather than KMS+DRM, and you  	 * move the mouse over the window. You could enter the window from any edge, -	 * so we have to warp the mouse there. There is also some hardware which -	 * emits these events. */ +	 * so we have to warp the mouse there. Also, some hardware emits these events. */  	struct wlr_pointer_motion_absolute_event *event = data;  	double lx, ly, dx, dy; @@ -2035,7 +2040,7 @@ moveresize(const Arg *arg)  	case CurMove:  		grabcx = (int)round(cursor->x) - grabc->geom.x;  		grabcy = (int)round(cursor->y) - grabc->geom.y; -		wlr_cursor_set_xcursor(cursor, cursor_mgr, "fleur"); +		wlr_cursor_set_xcursor(cursor, cursor_mgr, "all-scroll");  		break;  	case CurResize:  		/* Doesn't work for X11 output - the next absolute motion event @@ -2098,9 +2103,9 @@ apply_or_test:  		ok &= test ? wlr_output_test_state(wlr_output, &state)  				: wlr_output_commit_state(wlr_output, &state); -		/* Don't move monitors if position wouldn't change, this to avoid -		* wlroots marking the output as manually configured. -		* wlr_output_layout_add does not like disabled outputs */ +		/* Don't move monitors if position wouldn't change. This avoids +		 * wlroots marking the output as manually configured. +		 * wlr_output_layout_add does not like disabled outputs */  		if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y))  			wlr_output_layout_add(output_layout, wlr_output,  					config_head->state.x, config_head->state.y); @@ -2338,8 +2343,10 @@ run(char *startup_cmd)  		close(piperw[0]);  	} -	/* Mark stdout as non-blocking to avoid people who does not close stdin -	 * nor consumes it in their startup script getting dwl frozen */ +	/* Mark stdout as non-blocking to avoid the startup script +	 * causing dwl to freeze when a user neither closes stdin +	 * nor consumes standard input in his startup script */ +  	if (fd_set_nonblock(STDOUT_FILENO) < 0)  		close(STDOUT_FILENO); @@ -2350,7 +2357,7 @@ run(char *startup_cmd)  	selmon = xytomon(cursor->x, cursor->y);  	/* TODO hack to get cursor to display in its initial location (100, 100) -	 * instead of (0, 0) and then jumping. still may not be fully +	 * instead of (0, 0) and then jumping. Still may not be fully  	 * initialized, as the image/coordinates are not transformed for the  	 * monitor when displayed here */  	wlr_cursor_warp_closest(cursor, NULL, cursor->x, cursor->y); @@ -2373,7 +2380,7 @@ setcursor(struct wl_listener *listener, void *data)  	 * event, which will result in the client requesting set the cursor surface */  	if (cursor_mode != CurNormal && cursor_mode != CurPressed)  		return; -	/* This can be sent by any client, so we check to make sure this one is +	/* This can be sent by any client, so we check to make sure this one  	 * actually has pointer focus first. If so, we can tell the cursor to  	 * use the provided surface as the cursor image. It will set the  	 * hardware cursor on the output that it's currently on and continue to @@ -2389,7 +2396,7 @@ setcursorshape(struct wl_listener *listener, void *data)  	struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;  	if (cursor_mode != CurNormal && cursor_mode != CurPressed)  		return; -	/* This can be sent by any client, so we check to make sure this one is +	/* This can be sent by any client, so we check to make sure this one  	 * actually has pointer focus first. If so, we can tell the cursor to  	 * use the provided cursor shape. */  	if (event->seat_client == seat->pointer_state.focused_client) @@ -2492,7 +2499,7 @@ setpsel(struct wl_listener *listener, void *data)  {  	/* This event is raised by the seat when a client wants to set the selection,  	 * usually when the user copies something. wlroots allows compositors to -	 * ignore such requests if they so choose, but in dwl we always honor +	 * ignore such requests if they so choose, but in dwl we always honor them  	 */  	struct wlr_seat_request_set_primary_selection_event *event = data;  	wlr_seat_set_primary_selection(seat, event->source, event->serial); @@ -2503,7 +2510,7 @@ setsel(struct wl_listener *listener, void *data)  {  	/* This event is raised by the seat when a client wants to set the selection,  	 * usually when the user copies something. wlroots allows compositors to -	 * ignore such requests if they so choose, but in dwl we always honor +	 * ignore such requests if they so choose, but in dwl we always honor them  	 */  	struct wlr_seat_request_set_selection_event *event = data;  	wlr_seat_set_selection(seat, event->source, event->serial); @@ -2550,9 +2557,9 @@ setup(void)  	wl_signal_add(&drw->events.lost, &gpu_reset);  	/* Create shm, drm and linux_dmabuf interfaces by ourselves. -	 * The simplest way is call: +	 * The simplest way is to call:  	 *      wlr_renderer_init_wl_display(drw); -	 * but we need to create manually the linux_dmabuf interface to integrate it +	 * but we need to create the linux_dmabuf interface manually to integrate it  	 * with wlr_scene. */  	wlr_renderer_init_wl_shm(drw, dpy); @@ -2601,7 +2608,7 @@ setup(void)  	power_mgr = wlr_output_power_manager_v1_create(dpy);  	wl_signal_add(&power_mgr->events.set_mode, &output_power_mgr_set_mode); -	/* Creates an output layout, which a wlroots utility for working with an +	/* Creates an output layout, which is a wlroots utility for working with an  	 * arrangement of screens in a physical layout. */  	output_layout = wlr_output_layout_create(dpy);  	wl_signal_add(&output_layout->events.change, &layout_change); @@ -3279,7 +3286,7 @@ sethints(struct wl_listener *listener, void *data)  {  	Client *c = wl_container_of(listener, c, set_hints);  	struct wlr_surface *surface = client_surface(c); -	if (c == focustop(selmon)) +	if (c == focustop(selmon) || !c->surface.xwayland->hints)  		return;  	c->isurgent = xcb_icccm_wm_hints_get_urgency(c->surface.xwayland->hints); | 
