diff --git a/Makefile b/Makefile index 30fa935..dd5b4dd 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,25 @@ -PREFIX ?= /usr/local -MANDIR ?= $(PREFIX)/share/man -BIN ?= nowm +PREFIX ?= /usr/local +DESKTOP ?= /usr/share/xsessions +MANDIR ?= $(PREFIX)/share/man +BIN ?= nowm install: + @echo "Installing $(BIN) to $(PREFIX)/bin" @mkdir -p $(PREFIX)/bin - @mkdir -p $(MANDIR)/man1 - - @cp -p bin/$(BIN) $(PREFIX)/bin/ - @cp -p man/$(BIN).1 $(MANDIR)/man1/ - + @cp -p src/$(BIN) $(PREFIX)/bin/ @chmod 755 $(PREFIX)/bin/$(BIN) + + @echo "Installing $(BIN).1 to $(MANDIR)/man1" + @mkdir -p $(MANDIR)/man1 + @cp -p src/$(BIN).1 $(MANDIR)/man1/ + + @echo "Installing $(BIN).desktop to $(DESKTOP)" + @mkdir -p $(DESKTOP) + @cp -p src/$(BIN).desktop $(DESKTOP)/ uninstall: @rm -rf $(PREFIX)/bin/$(BIN) @rm -rf $(MANDIR)/man1/$(BIN).1* + @rm -rf $(DESKTOP)/$(BIN).desktop + @echo "Uninstalled $(BIN)" diff --git a/README.md b/README.md index db82c35..2c9b7fe 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ A dead simple tool to managing windows from the [tty](https://en.wikipedia.org/w Option 1: using `curl` ```sh -curl https://raw.githubusercontent.com/K4zoku/nowm/master/bin/nowm > ~/.local/bin/nowm +curl https://raw.githubusercontent.com/K4zoku/nowm/master/src/nowm > ~/.local/bin/nowm chmod +x ~/.local/bin/nowm ``` @@ -45,7 +45,7 @@ Option 2: using `git` ```sh git clone https://github.com/K4zoku/nowm.git ~/.local/share/nowm -ln -s ~/.local/share/nowm/bin/nowm ~/.local/bin/nowm +ln -s ~/.local/share/nowm/src/nowm ~/.local/bin/nowm ``` #### 📦 Package manager diff --git a/bin/nowm b/bin/nowm deleted file mode 100755 index ad180c6..0000000 --- a/bin/nowm +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh - -resize() { xdotool getwindowfocus windowsize "${1:-0}" "${2:-0}"; } - -resize_relative() { - eval "$(xdotool getwindowfocus getwindowgeometry --shell | head -n5)" - W_WIDTH=$(( WIDTH + "${1:-0}" )); W_HEIGHT=$(( HEIGHT + "${2:-0}" )) - eval "$(xdotool getdisplaygeometry --shell)" - DR_WIDTH="$(( WIDTH - X ))"; DR_HEIGHT="$(( HEIGHT - Y ))" - [ "${W_WIDTH}" -lt 1 ] && W_WIDTH=1 || [ "${W_WIDTH}" -gt "${DR_WIDTH}" ] && W_WIDTH="${DR_WIDTH}" - [ "${W_HEIGHT}" -lt 1 ] && W_HEIGHT=1 || [ "${W_HEIGHT}" -gt "${DR_HEIGHT}" ] && W_HEIGHT="${DR_HEIGHT}" - xdotool windowsize "${WINDOW}" "${W_WIDTH}" "${W_HEIGHT}" -} - -move() { xdotool getwindowfocus windowmove "${1:-0}" "${2:-0}"; } - -move_relative() { xdotool getwindowfocus windowmove --relative "${1:-0}" "${2:-0}"; } - -center() { - eval "$(xdotool getwindowfocus getwindowgeometry --shell | tail -n3 | head -n2)" - W_WIDTH="${WIDTH}"; W_HEIGHT="${HEIGHT}" - eval "$(xdotool getdisplaygeometry --shell)" - move "$(( (WIDTH - W_WIDTH) / 2 ))" "$(( (HEIGHT - W_HEIGHT) / 2 ))" -} - -snap() { - eval "$(xdotool getwindowfocus getwindowgeometry --shell | head -n5)" - W_WIDTH="${WIDTH}"; W_HEIGHT="${HEIGHT}" - eval "$(xdotool getdisplaygeometry --shell)" - case "${1:-0}" in - left) move 0 y ;; - bottom) move x "$(( HEIGHT - W_HEIGHT ))";; - top) move x 0 ;; - right) move "$(( WIDTH - W_WIDTH ))" y ;; - *) move x y ;; - esac -} - -pointer_focus() { xdotool getmouselocation windowfocus; } - -select_focus() { xdotool selectwindow windowfocus; } - -close() { xdotool getwindowfocus windowclose; } - -quit() { xdotool getwindowfocus windowquit; } - -window_kill() { xdotool getwindowfocus windowkill; } - -nowm_logout() { pkill -KILL -u "$(whoami)"; } - -nowm_main() { - NOWM_AUTOSTART="${XDG_CONFIG_HOME:-${HOME}/.config}/nowm/autostart" - [ -x "${NOWM_AUTOSTART}" ] && "${NOWM_AUTOSTART}" >/dev/null 2>&1 & - while : ; do : ; done -} - -noargs() { if [ -z "${DISPLAY}" ]; then exec startx "$(which nowm)"; else nowm_main; fi; } - -case "${1}" in - "") noargs || exit 1 ;; - resize) resize "${2}" "${3}";; - resize_relative) resize_relative "${2}" "${3}";; - move) move "${2}" "${3}";; - move_relative) move_relative "${2}" "${3}";; - center) center ;; - snap) snap "${2}" ;; - pointer_focus) pointer_focus ;; - select_focus) select_focus ;; - close) close ;; - quit) quit ;; - kill) window_kill ;; - logout) nowm_logout ;; - *) exit 1 ;; -esac diff --git a/examples/autostart b/examples/autostart deleted file mode 100644 index 8d8b7b4..0000000 --- a/examples/autostart +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -pgrep -x sxhkd || sxkhd -c "${NOWM_CONFIG_HOME}/sxhkdrc" & diff --git a/examples/hotkeys/autostart b/examples/hotkeys/autostart new file mode 100644 index 0000000..4c2b293 --- /dev/null +++ b/examples/hotkeys/autostart @@ -0,0 +1,5 @@ +#!/bin/sh + +# Stop running SXHKD and start new instance +pkill -x sxhkd +sxhkd -c "${NOWM_CONFIG_HOME}/sxhkdrc" & diff --git a/examples/sxhkdrc b/examples/hotkeys/sxhkdrc similarity index 62% rename from examples/sxhkdrc rename to examples/hotkeys/sxhkdrc index 30285bb..e8fdf71 100644 --- a/examples/sxhkdrc +++ b/examples/hotkeys/sxhkdrc @@ -4,11 +4,11 @@ # terminal super + Return - urxvt + urxvt # reload sxhkd configuration files super + Escape - pkill -USR1 -x sxhkd + pkill -USR1 -x sxhkd ################ # NOWM HOTKEYS # @@ -16,20 +16,20 @@ super + Escape # [nowm] logout super + alt + q - nowm logout + nowm logout # [nowm] move super + {Left,Down,Up,Right} - nowm move_relative {-4 0, 0 4, 0 -4, 4 0} + nowm move_relative {-10 0, 0 10, 0 -10, 10 0} # [nowm] resize -super + {a,s,w,d} - nowm resize_relative {-4 0, 0 4, 0 -4, 4 0} +super + {h,j,k,l} + nowm resize_relative {-10 0, 0 10, 0 -10, 10 0} # [nowm] window close -super + w - nowm close +alt + q + nowm close # [nowm] focus ~button1 - nowm pointer_focus + nowm pointer_focus diff --git a/man/nowm.1 b/man/nowm.1 deleted file mode 100644 index d71a322..0000000 --- a/man/nowm.1 +++ /dev/null @@ -1,42 +0,0 @@ -.TH NOWM "1" "2022" "K4zoku" "User Commands" -.SH NAME -NoWM \- Managing window without a window manager -.SH SYNOPSIS -.B nowm -.SH DESCRIPTION -A dead simple tool to managing windows from the tty, written in shell script. -.SH OPTIONS -\fBresize\fR \fBw h\fR -Shrink or grow the current window by the given w/h arguments -.TP -\fBresize_relative\fR \fBw h\fR -Shrink or grow the current window relatively by the given w/h arguments -.TP -\fBmove\fR \fBx y\fR -Shift the current window by the given x/y coordinates -.TP -\fBmove_relative\fR \fBx y\fR -Shift the current window relatively by the given x/y coordinates -.TP -\fBcenter\fR -Centers the current window. -.TP -\fBsnap\fR \fB(top|bottom|left|right)\fR -Move and resize the current window to fill the DIRECTION half of the screen -.TP -\fBpointer_focus\fR -Focus the window underneath the pointer -.TP -\fBselect_focus\fR -Focus selected window -.TP -\fBclose\fR -Destroy the window but will not try to kill the client controlling it -\fBquit\fR -Close window gracefully, this action sends a request, allowing the application to apply close confirmation mechanics -\fBkill\fR -Destroy the window and kill the client controlling it -\fBlogout\fR -Log user out -.SH REPORTING BUGS -Report bugs to https://github.com/K4zoku/nowm/issues diff --git a/package.json b/package.json index 507a4d1..f369b46 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Managing window without a window manager", "global": "true", - "scripts": ["bin/nowm"], - "files": ["man/nowm.1"], + "scripts": ["src/nowm"], + "files": ["src/nowm.1", "src/nowm.desktop"], "install": "make install" } diff --git a/src/nowm b/src/nowm new file mode 100755 index 0000000..c9dacb8 --- /dev/null +++ b/src/nowm @@ -0,0 +1,193 @@ +#!/bin/sh + +################# +# Resize window # +################# + +# By absolute size. +nowm_resize_absolute() { + xdotool getwindowfocus windowsize -- "${1:-0}" "${2:-0}" +} + +# By relative size from current size (+/-). +nowm_resize_relative() { + eval "$(xdotool getwindowfocus getwindowgeometry --shell)" + WINDOW_WIDTH=$(( WIDTH + "${1:-0}" )) + WINDOW_HEIGHT=$(( HEIGHT + "${2:-0}" )) + + eval "$(xdotool getdisplaygeometry --shell)" + DISPLAY_WIDTH="$(( WIDTH - X ))" + DISPLAY_HEIGHT="$(( HEIGHT - Y ))" + + if [ "${WINDOW_WIDTH}" -lt 1 ]; then + WINDOW_WIDTH=1 + elif [ "${WINDOW_WIDTH}" -gt "${DISPLAY_WIDTH}" ]; then + WINDOW_WIDTH="${DISPLAY_WIDTH}" + fi + + if [ "${WINDOW_HEIGHT}" -lt 1 ]; then + WINDOW_HEIGHT=1 + elif [ "${WINDOW_HEIGHT}" -gt "${DISPLAY_HEIGHT}" ]; then + WINDOW_HEIGHT="${DISPLAY_HEIGHT}" + fi + + xdotool windowsize -- "${WINDOW}" "${WINDOW_WIDTH}" "${WINDOW_HEIGHT}" +} + +# Autodetect. +nowm_resize() { + if echo "${1}" | grep -qE '^(\+|-)[0-9]+$'; then + nowm resize_relative "${1:-0}" 0 + else + nowm resize_absolute "${1:-x}" y + fi + + if echo "${2}" | grep -qE '^(\+|-)[0-9]+$'; then + nowm resize_relative 0 "${2:-0}" + else + nowm resize_absolute x "${2:-y}" + fi +} + + +############### +# Move window # +############### + +# By absolute coordinates. +nowm_move_absolute() { + xdotool getwindowfocus windowmove -- "${1:-0}" "${2:-0}" +} + +# By relative coordinates from current position. +nowm_move_relative() { + xdotool getwindowfocus windowmove --relative -- "${1:-0}" "${2:-0}" +} + +# Autodetect. +nowm_move() { + if echo "${1}" | grep -qE '^(\+|-)[0-9]+$'; then + nowm move_relative "${1:-0}" 0 + else + nowm move_absolute "${1:-x}" y + fi + + if echo "${2}" | grep -qE '^(\+|-)[0-9]+$'; then + nowm move_relative 0 "${2:-0}" + else + nowm move_absolute x "${2:-y}" + fi +} + +# Place at the center of the screen. +nowm_center() { + eval "$(xdotool getwindowfocus getwindowgeometry --shell)" + WINDOW_WIDTH="${WIDTH}" + WINDOW_HEIGHT="${HEIGHT}" + eval "$(xdotool getdisplaygeometry --shell)" + nowm move "$(( (WIDTH - WINDOW_WIDTH) / 2 ))" "$(( (HEIGHT - WINDOW_HEIGHT) / 2 ))" +} + +# Place at the side of the screen (left, right, top, bottom). +nowm_snap() { + eval "$(xdotool getwindowfocus getwindowgeometry --shell)" + WINDOW_WIDTH="${WIDTH}" + WINDOW_HEIGHT="${HEIGHT}" + eval "$(xdotool getdisplaygeometry --shell)" + case "${1:-0}" in + left) nowm move 0 y ;; + bottom) nowm move x "$(( HEIGHT - WINDOW_HEIGHT ))";; + top) nowm move x 0 ;; + right) nowm move "$(( WIDTH - WINDOW_WIDTH ))" y ;; + esac +} + + +############################## +# Manipulations with windows # +############################## + +# Focus window under cursor. +nowm_pointer_focus() { + xdotool getmouselocation windowfocus +} + +# Raise focused window. Useful in combination 'nowm pointer_focus && nowm raise'. +nowm_raise() { + xdotool getwindowfocus windowraise +} + +# Select window by clicking on it. Can be used if 'nowm_pointer_focus' does not work +nowm_select_focus() { + xdotool selectwindow windowfocus +} + +# Close focused window. Does NOT kill the child processes. +nowm_close() { + xdotool getwindowfocus windowclose +} + +#TODO +# Does nothing? Idk. +nowm_quit() { + xdotool getwindowfocus windowquit +} + +# Kill focused window. Kills the child processes too. +nowm_kill() { + xdotool getwindowfocus windowkill +} + + +################ +# NoWM session # +################ + +# Log out of the current session. +nowm_logout() { + kill "$NOWM_PID" +} + +# Start NoWM session or, if it is already running, rerun autostart script. +nowm_start() { + if [ -z "${DISPLAY}" ]; then + exec startx "$(which nowm)" + else + export NOWM_PID="$$" + NOWM_AUTOSTART="${XDG_CONFIG_HOME:-${HOME}/.config}/nowm/autostart" + [ -x "${NOWM_AUTOSTART}" ] && "${NOWM_AUTOSTART}" + sleep infinity + fi +} + +# Display help message and exit. +nowm_help() { + cat << EOF +Usage: nowm [ACTION] + +If no action is specified, then, if no graphical server is running, start one and NoWM, otherwise rerun autostart script and sleep +EOF + exit "${1:-0}" +} + + +######## +# Main # +######## + +# String of space-separated valid arguments. +valid="resize resize_absolute resize_relative move move_absolute move_relative center snap pointer_focus raise select_focus close quit kill logout help" + +# If no argument is present, start NoWM session. +if [ -z "${1}" ]; then + nowm_start + +# If argument is present and valid, run the corresponding function. +elif echo "${valid}" | grep -wq "${1}" ; then + nowm_"${1}" "${@:2}" + +# If argument is present but invalid, display error and help messages +else + echo "Invalid command: '${1}'" + nowm_help 1 +fi diff --git a/src/nowm.1 b/src/nowm.1 new file mode 100644 index 0000000..a4f6667 --- /dev/null +++ b/src/nowm.1 @@ -0,0 +1,53 @@ +.TH NOWM "1" "2022" "K4zoku" "NoWM manual" +.SH NAME +NoWM \- Managing window without a window manager +.SH SYNOPSIS +.B nowm +.SH DESCRIPTION +A dead simple tool to managing windows from the tty, written in shell script. +.SH OPTIONS +.TP +\fBresize [+-]w [+-]h\fR +Shrink or grow the current window by the given w/h arguments. If you set + or - sign before w/h then they become relative coordinates, otherwise treating them as absolute +\fBresize_absolute w h\fR +Shrink or grow the current window by the given absolute w/h arguments +.TP +\fBresize_relative w h\fR +Shrink or grow the current window by the given relative w/h arguments +.TP +\fBmove x y\fR +Shift the current window by the given x/y coordinates. If you set + or - sign before x/y then they become relative coordinates, otherwise treating them as absolute +\fBmove_absolute x y\fR +Shift the current window by the given absolute x/y coordinates +.TP +\fBmove_relative x y\fR +Shift the current window by the given relative x/y coordinates +.TP +\fBcenter\fR +Move currently focused window to the center of the screen +.TP +\fBsnap (top|bottom|left|right)\fR +Move and resize the current window to fill the DIRECTION half of the screen +.TP +\fBpointer_focus\fR +Focus the window underneath the pointer +.TP +\fBraise\fR +Raise currently focused window +.TP +\fBselect_focus\fR +Focus window using selection cursor +.TP +\fBclose\fR +Destroy the window but will not try to kill the client controlling it +.TP +\fBquit\fR +Close window gracefully, this action sends a request, allowing the application to apply close confirmation mechanics +.TP +\fBkill\fR +Destroy the window and kill the client controlling it +.TP +\fBlogout\fR +Terminate current NoWM session (also kills applications) +.SH REPORTING BUGS +Report bugs to https://github.com/K4zoku/nowm/issues \ No newline at end of file diff --git a/src/nowm.desktop b/src/nowm.desktop new file mode 100644 index 0000000..6008aa7 --- /dev/null +++ b/src/nowm.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Name=NoWM (X11) +Comment=NoWM - managing window without a window manager +Exec=nowm +TryExec=nowm +Type=XSession