update: moved to dwl compositor
This commit is contained in:
parent
7dfa33df75
commit
a3bc0af419
212 changed files with 21717 additions and 28771 deletions
|
@ -1,11 +1,9 @@
|
||||||
# Drake's Dotfiles (Suckless version)
|
# Drake's Dotfiles (Void Linux - DWL Compositor)
|
||||||
|
|
||||||
This is just a personal repository where i store all my dotfiles, you're free
|
This is just a personal repository where i store all my dotfiles, you're free
|
||||||
clone them and edit them as you wish. Part of this work was based on other
|
clone them and edit them as you wish. Part of this work was based on other
|
||||||
people's dotfiles (Distrotube for example), and it may contain scripts or
|
people's dotfiles (Distrotube for example), and it may contain scripts or
|
||||||
binaries that they made or modify.
|
binaries that they made or modify.
|
||||||
|
|
||||||
# Dependencies
|
This is a rice made specifically for Void Linux and it uses the dwl wayland
|
||||||
``` sh
|
compositor.
|
||||||
paru -S --needed bat eza feh fzf jq ripgrep maim slop cmus vifm ueberzugpp unclutter-xfixes-git lxsession picom xorg-setxkbmap xorg-xdpyinfo xdotool xorg-xinit xorg-xprop xorg-xev xorg-xrandr arandr yt-dlp ani-cli-git ytfzf-git pulsemixer pamixer alsa-utils ttf-nerd-fonts-symbols ttf-nerd-fonts-symbols-mono ttf-mononoki-nerd zathura zathura-pdf-poppler zathura-cb kvantum gruvbox-dark-gtk gruvbox-dark-icons-gtk xcursor-simp1e-gruvbox-dark j4-dmenu-desktop ffmpegthumbnailer ffmpeg btop mpv gtk-engine-murrine
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
title Arch Linux
|
|
||||||
linux /vmlinuz-linux
|
|
||||||
initrd /intel-ucode.img
|
|
||||||
initrd /initramfs-linux.img
|
|
||||||
options rd.luks.name=[uuid]=[lvm-name] root=/dev/[vg-name]/root rw quiet
|
|
|
@ -1,42 +0,0 @@
|
||||||
# Match on all types of devices but joysticks
|
|
||||||
#
|
|
||||||
# If you want to configure your devices, do not copy this file.
|
|
||||||
# Instead, use a config snippet that contains something like this:
|
|
||||||
#
|
|
||||||
# Section "InputClass"
|
|
||||||
# Identifier "something or other"
|
|
||||||
# MatchDriver "libinput"
|
|
||||||
#
|
|
||||||
# MatchIsTouchpad "on"
|
|
||||||
# ... other Match directives ...
|
|
||||||
# Option "someoption" "value"
|
|
||||||
# EndSection
|
|
||||||
#
|
|
||||||
# This applies the option any libinput device also matched by the other
|
|
||||||
# directives. See the xorg.conf(5) man page for more info on
|
|
||||||
# matching devices.
|
|
||||||
|
|
||||||
Section "InputClass"
|
|
||||||
Identifier "libinput pointer catchall"
|
|
||||||
MatchIsPointer "on"
|
|
||||||
MatchDevicePath "/dev/input/event*"
|
|
||||||
Driver "libinput"
|
|
||||||
EndSection
|
|
||||||
|
|
||||||
Section "InputClass"
|
|
||||||
Identifier "libinput keyboard catchall"
|
|
||||||
MatchIsKeyboard "on"
|
|
||||||
MatchDevicePath "/dev/input/event*"
|
|
||||||
Driver "libinput"
|
|
||||||
EndSection
|
|
||||||
|
|
||||||
Section "InputClass"
|
|
||||||
Identifier "libinput touchpad catchall"
|
|
||||||
MatchIsTouchpad "on"
|
|
||||||
MatchDevicePath "/dev/input/event*"
|
|
||||||
Option "Tapping" "on"
|
|
||||||
Option "ClickMethod" "clickfinger"
|
|
||||||
Option "NaturalScrolling" "true"
|
|
||||||
Driver "libinput"
|
|
||||||
EndSection
|
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
# vim:set ft=sh
|
|
||||||
# MODULES
|
|
||||||
# The following modules are loaded before any boot hooks are
|
|
||||||
# run. Advanced users may wish to specify all system modules
|
|
||||||
# in this array. For instance:
|
|
||||||
# MODULES=(usbhid xhci_hcd)
|
|
||||||
MODULES=(i915)
|
|
||||||
|
|
||||||
# BINARIES
|
|
||||||
# This setting includes any additional binaries a given user may
|
|
||||||
# wish into the CPIO image. This is run last, so it may be used to
|
|
||||||
# override the actual binaries included by a given hook
|
|
||||||
# BINARIES are dependency parsed, so you may safely ignore libraries
|
|
||||||
BINARIES=()
|
|
||||||
|
|
||||||
# FILES
|
|
||||||
# This setting is similar to BINARIES above, however, files are added
|
|
||||||
# as-is and are not parsed in any way. This is useful for config files.
|
|
||||||
FILES=()
|
|
||||||
|
|
||||||
# HOOKS
|
|
||||||
# This is the most important setting in this file. The HOOKS control the
|
|
||||||
# modules and scripts added to the image, and what happens at boot time.
|
|
||||||
# Order is important, and it is recommended that you do not change the
|
|
||||||
# order in which HOOKS are added. Run 'mkinitcpio -H <hook name>' for
|
|
||||||
# help on a given hook.
|
|
||||||
# 'base' is _required_ unless you know precisely what you are doing.
|
|
||||||
# 'udev' is _required_ in order to automatically load modules
|
|
||||||
# 'filesystems' is _required_ unless you specify your fs modules in MODULES
|
|
||||||
# Examples:
|
|
||||||
## This setup specifies all modules in the MODULES setting above.
|
|
||||||
## No RAID, lvm2, or encrypted root is needed.
|
|
||||||
# HOOKS=(base)
|
|
||||||
#
|
|
||||||
## This setup will autodetect all modules for your system and should
|
|
||||||
## work as a sane default
|
|
||||||
# HOOKS=(base udev autodetect modconf block filesystems fsck)
|
|
||||||
#
|
|
||||||
## This setup will generate a 'full' image which supports most systems.
|
|
||||||
## No autodetection is done.
|
|
||||||
# HOOKS=(base udev modconf block filesystems fsck)
|
|
||||||
#
|
|
||||||
## This setup assembles a mdadm array with an encrypted root file system.
|
|
||||||
## Note: See 'mkinitcpio -H mdadm_udev' for more information on RAID devices.
|
|
||||||
# HOOKS=(base udev modconf keyboard keymap consolefont block mdadm_udev encrypt filesystems fsck)
|
|
||||||
#
|
|
||||||
## This setup loads an lvm2 volume group.
|
|
||||||
# HOOKS=(base udev modconf block lvm2 filesystems fsck)
|
|
||||||
#
|
|
||||||
## NOTE: If you have /usr on a separate partition, you MUST include the
|
|
||||||
# usr and fsck hooks.
|
|
||||||
HOOKS=(base systemd autodetect keyboard modconf block sd-encrypt kms keymap consolefont lvm2 filesystems fsck)
|
|
||||||
|
|
||||||
# COMPRESSION
|
|
||||||
# Use this to compress the initramfs image. By default, zstd compression
|
|
||||||
# is used. Use 'cat' to create an uncompressed image.
|
|
||||||
#COMPRESSION="zstd"
|
|
||||||
#COMPRESSION="gzip"
|
|
||||||
#COMPRESSION="bzip2"
|
|
||||||
#COMPRESSION="lzma"
|
|
||||||
#COMPRESSION="xz"
|
|
||||||
#COMPRESSION="lzop"
|
|
||||||
#COMPRESSION="lz4"
|
|
||||||
|
|
||||||
# COMPRESSION_OPTIONS
|
|
||||||
# Additional options for the compressor
|
|
||||||
#COMPRESSION_OPTIONS=()
|
|
||||||
|
|
||||||
# MODULES_DECOMPRESS
|
|
||||||
# Decompress kernel modules during initramfs creation.
|
|
||||||
# Enable to speedup boot process, disable to save RAM
|
|
||||||
# during early userspace. Switch (yes/no).
|
|
||||||
#MODULES_DECOMPRESS="yes"
|
|
14
system/etc/sv/runsvdir-drk/run
Executable file
14
system/etc/sv/runsvdir-drk/run
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
export USER="drk"
|
||||||
|
export HOME="/home/$USER"
|
||||||
|
export XDG_RUNTIME_DIR="/run/user/$(id -u $USER)"
|
||||||
|
mkdir $XDG_RUNTIME_DIR
|
||||||
|
chown $USER:$USER $XDG_RUNTIME_DIR
|
||||||
|
|
||||||
|
groups="$(id -Gn "$USER" | tr ' ' ':')"
|
||||||
|
svdir="$HOME/.config/services"
|
||||||
|
mkdir -p "$svdir"
|
||||||
|
chown $USER:$USER "$svdir"
|
||||||
|
|
||||||
|
exec chpst -u "$USER:$groups" runsvdir "$svdir"
|
|
@ -9,28 +9,31 @@
|
||||||
# starting xsession
|
# starting xsession
|
||||||
if [ -z "$DISPLAY" ] && [ "$(tty)" = "/dev/tty1" ]
|
if [ -z "$DISPLAY" ] && [ "$(tty)" = "/dev/tty1" ]
|
||||||
then
|
then
|
||||||
startx -- vt1 -keeptty &>/dev/null
|
sh "$HOME/.winitrc"
|
||||||
logout
|
logout
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# environment variables
|
# environment variables
|
||||||
export EDITOR="~/.local/bin/lvim"
|
export EDITOR="$HOME/.local/bin/lvim"
|
||||||
export VISUAL="~/.local/bin/neovide.AppImage --neovim-bin $EDITOR"
|
export VISUAL="$HOME/.local/bin/lvim"
|
||||||
export BROWSER="qutebrowser"
|
export BROWSER="firefox"
|
||||||
export VIEWER="zathura"
|
export VIEWER="zathura"
|
||||||
|
export WM=dwl
|
||||||
|
|
||||||
|
# home folders
|
||||||
|
export XDG_DESKTOP_DIR="$HOME/Desktop"
|
||||||
|
export XDG_DOWNLOAD_DIR="$HOME/Downloads"
|
||||||
|
export XDG_TEMPLATES_DIR="$HOME/Templates"
|
||||||
|
export XDG_PUBLICSHARE_DIR="$HOME/Public"
|
||||||
|
export XDG_DOCUMENTS_DIR="$HOME/Documents"
|
||||||
|
export XDG_MUSIC_DIR="$HOME/Music"
|
||||||
|
export XDG_PICTURES_DIR="$HOME/Pictures"
|
||||||
|
export XDG_VIDEOS_DIR="$HOME/Videos"
|
||||||
|
|
||||||
# clean home
|
# clean home
|
||||||
export XDG_DATA_HOME="$HOME/.local/share"
|
export XDG_DATA_HOME="$HOME/.local/share"
|
||||||
export XDG_CACHE_HOME="$HOME/.cache"
|
export XDG_CACHE_HOME="$HOME/.cache"
|
||||||
export XDG_CONFIG_HOME="$HOME/.config"
|
export XDG_CONFIG_HOME="$HOME/.config"
|
||||||
export XDG_DESKTOP_DIR="$HOME/var/desktop"
|
|
||||||
export XDG_DOWNLOAD_DIR="$HOME/var/downloads"
|
|
||||||
export XDG_TEMPLATES_DIR="$HOME/media/documents/templates"
|
|
||||||
export XDG_PUBLICSHARE_DIR="$HOME/var/public"
|
|
||||||
export XDG_DOCUMENTS_DIR="$HOME/media/documents"
|
|
||||||
export XDG_MUSIC_DIR="$HOME/media/music"
|
|
||||||
export XDG_PICTURES_DIR="$HOME/media/pictures"
|
|
||||||
export XDG_VIDEOS_DIR="$HOME/media/videos"
|
|
||||||
export W3M_DIR="$XDG_DATA_HOME/w3m"
|
export W3M_DIR="$XDG_DATA_HOME/w3m"
|
||||||
export GTK2_RC_FILES="$HOME/.config/gtk-2.0/gtkrc-2.0"
|
export GTK2_RC_FILES="$HOME/.config/gtk-2.0/gtkrc-2.0"
|
||||||
export WGETRC="$HOME/.config/wget/wgetrc"
|
export WGETRC="$HOME/.config/wget/wgetrc"
|
||||||
|
|
|
@ -10,7 +10,8 @@ export TERM="xterm-256color" # getting proper colors
|
||||||
export HISTCONTROL=ignoredups:erasedups # no duplicate entries
|
export HISTCONTROL=ignoredups:erasedups # no duplicate entries
|
||||||
|
|
||||||
### "bat" as manpager
|
### "bat" as manpager
|
||||||
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
|
#export MANPAGER="sh -c 'col -bx | bat -p -l man'"
|
||||||
|
export PAGER="bat -p"
|
||||||
|
|
||||||
# use bash-completion, if available
|
# use bash-completion, if available
|
||||||
[[ $PS1 && -f /usr/share/bash-completion/bash_completion ]] && \
|
[[ $PS1 && -f /usr/share/bash-completion/bash_completion ]] && \
|
||||||
|
@ -289,3 +290,4 @@ function parse_git_dirty {
|
||||||
}
|
}
|
||||||
|
|
||||||
export PS1="[\[\e[31m\]\u\[\e[m\]\[\e[35m\]@\[\e[m\]\[\e[32m\]\h\[\e[m\]] [\[\e[33m\]\W\[\e[m\]\[\e[34m\]\`parse_git_branch\`\[\e[m\]] "
|
export PS1="[\[\e[31m\]\u\[\e[m\]\[\e[35m\]@\[\e[m\]\[\e[32m\]\h\[\e[m\]] [\[\e[33m\]\W\[\e[m\]\[\e[34m\]\`parse_git_branch\`\[\e[m\]] "
|
||||||
|
if [ -n "$RANGER_LEVEL" ]; then export PS1="[ranger]$PS1"; fi
|
||||||
|
|
BIN
user/.config/dunst/critical.png
Normal file
BIN
user/.config/dunst/critical.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
359
user/.config/dunst/dunstrc
Normal file
359
user/.config/dunst/dunstrc
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
[global]
|
||||||
|
### Display ###
|
||||||
|
|
||||||
|
# Which monitor should the notifications be displayed on.
|
||||||
|
monitor = 0
|
||||||
|
|
||||||
|
# Display notification on focused monitor. Possible modes are:
|
||||||
|
# mouse: follow mouse pointer
|
||||||
|
# keyboard: follow window with keyboard focus
|
||||||
|
# none: don't follow anything
|
||||||
|
#
|
||||||
|
# "keyboard" needs a window manager that exports the
|
||||||
|
# _NET_ACTIVE_WINDOW property.
|
||||||
|
# This should be the case for almost all modern window managers.
|
||||||
|
#
|
||||||
|
# If this option is set to mouse or keyboard, the monitor option
|
||||||
|
# will be ignored.
|
||||||
|
follow = mouse
|
||||||
|
|
||||||
|
# Show how many messages are currently hidden (because of geometry).
|
||||||
|
indicate_hidden = yes
|
||||||
|
|
||||||
|
# Shrink window if it's smaller than the width. Will be ignored if
|
||||||
|
# width is 0.
|
||||||
|
shrink = no
|
||||||
|
|
||||||
|
# The transparency of the window. Range: [0; 100].
|
||||||
|
# This option will only work if a compositing window manager is
|
||||||
|
# present (e.g. xcompmgr, compiz, etc.).
|
||||||
|
transparency = 30
|
||||||
|
|
||||||
|
# Draw a line of "separator_height" pixel height between two
|
||||||
|
# notifications.
|
||||||
|
# Set to 0 to disable.
|
||||||
|
separator_height = 2
|
||||||
|
|
||||||
|
# Padding between text and separator.
|
||||||
|
padding = 8
|
||||||
|
|
||||||
|
# Horizontal padding.
|
||||||
|
horizontal_padding = 8
|
||||||
|
|
||||||
|
# Defines width in pixels of frame around the notification window.
|
||||||
|
# Set to 0 to disable.
|
||||||
|
frame_width = 3
|
||||||
|
|
||||||
|
# Defines color of the frame around the notification window.
|
||||||
|
frame_color = "#fb4934"
|
||||||
|
|
||||||
|
# Define a color for the separator.
|
||||||
|
# possible values are:
|
||||||
|
# * auto: dunst tries to find a color fitting to the background;
|
||||||
|
# * foreground: use the same color as the foreground;
|
||||||
|
# * frame: use the same color as the frame;
|
||||||
|
# * anything else will be interpreted as a X color.
|
||||||
|
separator_color = auto
|
||||||
|
|
||||||
|
# Sort messages by urgency.
|
||||||
|
sort = yes
|
||||||
|
|
||||||
|
# Don't remove messages, if the user is idle (no mouse or keyboard input)
|
||||||
|
# for longer than idle_threshold seconds.
|
||||||
|
# Set to 0 to disable.
|
||||||
|
# A client can set the 'transient' hint to bypass this. See the rules
|
||||||
|
# section for how to disable this if necessary
|
||||||
|
idle_threshold = 120
|
||||||
|
|
||||||
|
### Text ###
|
||||||
|
font = mononoki Nerd Font 10
|
||||||
|
|
||||||
|
# The spacing between lines. If the height is smaller than the
|
||||||
|
# font height, it will get raised to the font height.
|
||||||
|
line_height = 0
|
||||||
|
|
||||||
|
# Possible values are:
|
||||||
|
# full: Allow a small subset of html markup in notifications:
|
||||||
|
# <b>bold</b>
|
||||||
|
# <i>italic</i>
|
||||||
|
# <s>strikethrough</s>
|
||||||
|
# <u>underline</u>
|
||||||
|
#
|
||||||
|
# For a complete reference see
|
||||||
|
# <http://developer.gnome.org/pango/stable/PangoMarkupFormat.html>.
|
||||||
|
#
|
||||||
|
# strip: This setting is provided for compatibility with some broken
|
||||||
|
# clients that send markup even though it's not enabled on the
|
||||||
|
# server. Dunst will try to strip the markup but the parsing is
|
||||||
|
# simplistic so using this option outside of matching rules for
|
||||||
|
# specific applications *IS GREATLY DISCOURAGED*.
|
||||||
|
#
|
||||||
|
# no: Disable markup parsing, incoming notifications will be treated as
|
||||||
|
# plain text. Dunst will not advertise that it has the body-markup
|
||||||
|
# capability if this is set as a global setting.
|
||||||
|
#
|
||||||
|
# It's important to note that markup inside the format option will be parsed
|
||||||
|
# regardless of what this is set to.
|
||||||
|
markup = full
|
||||||
|
|
||||||
|
# The format of the message. Possible variables are:
|
||||||
|
# %a appname
|
||||||
|
# %s summary
|
||||||
|
# %b body
|
||||||
|
# %i iconname (including its path)
|
||||||
|
# %I iconname (without its path)
|
||||||
|
# %p progress value if set ([ 0%] to [100%]) or nothing
|
||||||
|
# %n progress value if set without any extra characters
|
||||||
|
# %% Literal %
|
||||||
|
# Markup is allowed
|
||||||
|
format = "<b>%s</b>\n%b"
|
||||||
|
|
||||||
|
# Alignment of message text.
|
||||||
|
# Possible values are "left", "center" and "right".
|
||||||
|
alignment = center
|
||||||
|
|
||||||
|
# Show age of message if message is older than show_age_threshold
|
||||||
|
# seconds.
|
||||||
|
# Set to -1 to disable.
|
||||||
|
show_age_threshold = 60
|
||||||
|
|
||||||
|
# Split notifications into multiple lines if they don't fit into
|
||||||
|
# geometry.
|
||||||
|
word_wrap = yes
|
||||||
|
|
||||||
|
# When word_wrap is set to no, specify where to make an ellipsis in long lines.
|
||||||
|
# Possible values are "start", "middle" and "end".
|
||||||
|
ellipsize = middle
|
||||||
|
|
||||||
|
# Ignore newlines '\n' in notifications.
|
||||||
|
ignore_newline = no
|
||||||
|
|
||||||
|
# Stack together notifications with the same content
|
||||||
|
stack_duplicates = true
|
||||||
|
|
||||||
|
# Hide the count of stacked notifications with the same content
|
||||||
|
hide_duplicate_count = false
|
||||||
|
|
||||||
|
# Display indicators for URLs (U) and actions (A).
|
||||||
|
show_indicators = yes
|
||||||
|
|
||||||
|
### Icons ###
|
||||||
|
|
||||||
|
# Align icons left/right/off
|
||||||
|
icon_position = left
|
||||||
|
|
||||||
|
# Scale larger icons down to this size, set to 0 to disable
|
||||||
|
max_icon_size = 32
|
||||||
|
|
||||||
|
# Paths to default icons.
|
||||||
|
icon_path = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/
|
||||||
|
|
||||||
|
### History ###
|
||||||
|
|
||||||
|
# Should a notification popped up from history be sticky or timeout
|
||||||
|
# as if it would normally do.
|
||||||
|
sticky_history = yes
|
||||||
|
|
||||||
|
# Maximum amount of notifications kept in history
|
||||||
|
history_length = 20
|
||||||
|
|
||||||
|
### Misc/Advanced ###
|
||||||
|
|
||||||
|
# dmenu path.
|
||||||
|
dmenu = /usr/bin/dmenu -p dunst:
|
||||||
|
|
||||||
|
# Browser for opening urls in context menu.
|
||||||
|
browser = /usr/bin/firefox
|
||||||
|
|
||||||
|
# Always run rule-defined scripts, even if the notification is suppressed
|
||||||
|
always_run_script = true
|
||||||
|
|
||||||
|
# Define the title of the windows spawned by dunst
|
||||||
|
title = Dunst
|
||||||
|
|
||||||
|
# Define the class of the windows spawned by dunst
|
||||||
|
class = Dunst
|
||||||
|
|
||||||
|
# Define the corner radius of the notification window
|
||||||
|
# in pixel size. If the radius is 0, you have no rounded
|
||||||
|
# corners.
|
||||||
|
# The radius will be automatically lowered if it exceeds half of the
|
||||||
|
# notification height to avoid clipping text and/or icons.
|
||||||
|
corner_radius = 0
|
||||||
|
|
||||||
|
### Legacy
|
||||||
|
|
||||||
|
# Use the Xinerama extension instead of RandR for multi-monitor support.
|
||||||
|
# This setting is provided for compatibility with older nVidia drivers that
|
||||||
|
# do not support RandR and using it on systems that support RandR is highly
|
||||||
|
# discouraged.
|
||||||
|
#
|
||||||
|
# By enabling this setting dunst will not be able to detect when a monitor
|
||||||
|
# is connected or disconnected which might break follow mode if the screen
|
||||||
|
# layout changes.
|
||||||
|
force_xinerama = false
|
||||||
|
|
||||||
|
### mouse
|
||||||
|
|
||||||
|
# Defines action of mouse event
|
||||||
|
# Possible values are:
|
||||||
|
# * none: Don't do anything.
|
||||||
|
# * do_action: If the notification has exactly one action, or one is marked as default,
|
||||||
|
# invoke it. If there are multiple and no default, open the context menu.
|
||||||
|
# * close_current: Close current notification.
|
||||||
|
# * close_all: Close all notifications.
|
||||||
|
mouse_left_click = do_action
|
||||||
|
mouse_middle_click = close_all
|
||||||
|
mouse_right_click = close_current
|
||||||
|
|
||||||
|
# Experimental features that may or may not work correctly. Do not expect them
|
||||||
|
# to have a consistent behaviour across releases.
|
||||||
|
[experimental]
|
||||||
|
# Calculate the dpi to use on a per-monitor basis.
|
||||||
|
# If this setting is enabled the Xft.dpi value will be ignored and instead
|
||||||
|
# dunst will attempt to calculate an appropriate dpi value for each monitor
|
||||||
|
# using the resolution and physical size. This might be useful in setups
|
||||||
|
# where there are multiple screens with very different dpi values.
|
||||||
|
per_monitor_dpi = false
|
||||||
|
|
||||||
|
[urgency_low]
|
||||||
|
# IMPORTANT: colors have to be defined in quotation marks.
|
||||||
|
# Otherwise the "#" and following would be interpreted as a comment.
|
||||||
|
background = "#282828"
|
||||||
|
foreground = "#ebdbd2"
|
||||||
|
timeout = 5
|
||||||
|
# Icon for notifications with low urgency, uncomment to enable
|
||||||
|
icon = /home/drk/.config/dunst/normal.png
|
||||||
|
|
||||||
|
[urgency_normal]
|
||||||
|
background = "#282828"
|
||||||
|
foreground = "#ebdbd2"
|
||||||
|
timeout = 5
|
||||||
|
# Icon for notifications with normal urgency, uncomment to enable
|
||||||
|
icon = /home/drk/.config/dunst/normal.png
|
||||||
|
|
||||||
|
[urgency_critical]
|
||||||
|
background = "#900000"
|
||||||
|
foreground = "#ebdbd2"
|
||||||
|
frame_color = "#ff0000"
|
||||||
|
timeout = 5
|
||||||
|
# Icon for notifications with critical urgency, uncomment to enable
|
||||||
|
icon = /home/drk/.config/dunst/critical.png
|
||||||
|
|
||||||
|
# Every section that isn't one of the above is interpreted as a rules to
|
||||||
|
# override settings for certain messages.
|
||||||
|
#
|
||||||
|
# Messages can be matched by
|
||||||
|
# appname (discouraged, see desktop_entry)
|
||||||
|
# body
|
||||||
|
# category
|
||||||
|
# desktop_entry
|
||||||
|
# icon
|
||||||
|
# match_transient
|
||||||
|
# msg_urgency
|
||||||
|
# stack_tag
|
||||||
|
# summary
|
||||||
|
#
|
||||||
|
# and you can override the
|
||||||
|
# background
|
||||||
|
# foreground
|
||||||
|
# format
|
||||||
|
# frame_color
|
||||||
|
# fullscreen
|
||||||
|
# new_icon
|
||||||
|
# set_stack_tag
|
||||||
|
# set_transient
|
||||||
|
# timeout
|
||||||
|
# urgency
|
||||||
|
#
|
||||||
|
# Shell-like globbing will get expanded.
|
||||||
|
#
|
||||||
|
# Instead of the appname filter, it's recommended to use the desktop_entry filter.
|
||||||
|
# GLib based applications export their desktop-entry name. In comparison to the appname,
|
||||||
|
# the desktop-entry won't get localized.
|
||||||
|
#
|
||||||
|
# SCRIPTING
|
||||||
|
# You can specify a script that gets run when the rule matches by
|
||||||
|
# setting the "script" option.
|
||||||
|
# The script will be called as follows:
|
||||||
|
# script appname summary body icon urgency
|
||||||
|
# where urgency can be "LOW", "NORMAL" or "CRITICAL".
|
||||||
|
#
|
||||||
|
# NOTE: if you don't want a notification to be displayed, set the format
|
||||||
|
# to "".
|
||||||
|
# NOTE: It might be helpful to run dunst -print in a terminal in order
|
||||||
|
# to find fitting options for rules.
|
||||||
|
|
||||||
|
# Disable the transient hint so that idle_threshold cannot be bypassed from the
|
||||||
|
# client
|
||||||
|
#[transient_disable]
|
||||||
|
# match_transient = yes
|
||||||
|
# set_transient = no
|
||||||
|
#
|
||||||
|
# Make the handling of transient notifications more strict by making them not
|
||||||
|
# be placed in history.
|
||||||
|
#[transient_history_ignore]
|
||||||
|
# match_transient = yes
|
||||||
|
# history_ignore = yes
|
||||||
|
|
||||||
|
# fullscreen values
|
||||||
|
# show: show the notifications, regardless if there is a fullscreen window opened
|
||||||
|
# delay: displays the new notification, if there is no fullscreen window active
|
||||||
|
# If the notification is already drawn, it won't get undrawn.
|
||||||
|
# pushback: same as delay, but when switching into fullscreen, the notification will get
|
||||||
|
# withdrawn from screen again and will get delayed like a new notification
|
||||||
|
#[fullscreen_delay_everything]
|
||||||
|
# fullscreen = delay
|
||||||
|
#[fullscreen_show_critical]
|
||||||
|
# msg_urgency = critical
|
||||||
|
# fullscreen = show
|
||||||
|
|
||||||
|
#[espeak]
|
||||||
|
# summary = "*"
|
||||||
|
# script = dunst_espeak.sh
|
||||||
|
|
||||||
|
#[script-test]
|
||||||
|
# summary = "*script*"
|
||||||
|
# script = dunst_test.sh
|
||||||
|
|
||||||
|
#[ignore]
|
||||||
|
# # This notification will not be displayed
|
||||||
|
# summary = "foobar"
|
||||||
|
# format = ""
|
||||||
|
|
||||||
|
#[history-ignore]
|
||||||
|
# # This notification will not be saved in history
|
||||||
|
# summary = "foobar"
|
||||||
|
# history_ignore = yes
|
||||||
|
|
||||||
|
#[skip-display]
|
||||||
|
# # This notification will not be displayed, but will be included in the history
|
||||||
|
# summary = "foobar"
|
||||||
|
# skip_display = yes
|
||||||
|
|
||||||
|
#[signed_on]
|
||||||
|
# appname = Pidgin
|
||||||
|
# summary = "*signed on*"
|
||||||
|
# urgency = low
|
||||||
|
#
|
||||||
|
#[signed_off]
|
||||||
|
# appname = Pidgin
|
||||||
|
# summary = *signed off*
|
||||||
|
# urgency = low
|
||||||
|
#
|
||||||
|
#[says]
|
||||||
|
# appname = Pidgin
|
||||||
|
# summary = *says*
|
||||||
|
# urgency = critical
|
||||||
|
#
|
||||||
|
#[twitter]
|
||||||
|
# appname = Pidgin
|
||||||
|
# summary = *twitter.com*
|
||||||
|
# urgency = normal
|
||||||
|
#
|
||||||
|
#[stack-volumes]
|
||||||
|
# appname = "some_volume_notifiers"
|
||||||
|
# set_stack_tag = "volume"
|
||||||
|
#
|
||||||
|
# vim: ft=cfg
|
||||||
|
|
BIN
user/.config/dunst/normal.png
Normal file
BIN
user/.config/dunst/normal.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
|
@ -1,70 +0,0 @@
|
||||||
## ____ __
|
|
||||||
## / __ \_________ _/ /_____
|
|
||||||
## / / / / ___/ __ `/ //_/ _ \
|
|
||||||
## / /_/ / / / /_/ / ,< / __/ Clay Gomera (Drake)
|
|
||||||
## /_____/_/ \__,_/_/|_|\___/ My custom picom config
|
|
||||||
|
|
||||||
## Shadows
|
|
||||||
shadow = false;
|
|
||||||
#shadow-radius = 8;
|
|
||||||
#shadow-opacity = .90
|
|
||||||
#shadow-offset-x = -10;
|
|
||||||
#shadow-offset-y = -10;
|
|
||||||
# shadow-red = 0
|
|
||||||
# shadow-green = 0
|
|
||||||
# shadow-blue = 0
|
|
||||||
# shadow-color = "#000000"
|
|
||||||
#shadow-exclude = [
|
|
||||||
# "name = 'Notification'",
|
|
||||||
# "class_g = 'Conky'",
|
|
||||||
# "class_g ?= 'Notify-osd'",
|
|
||||||
# "class_g = 'Cairo-clock'",
|
|
||||||
# "_GTK_FRAME_EXTENTS@:c"
|
|
||||||
#];
|
|
||||||
|
|
||||||
## Fading
|
|
||||||
fading = false;
|
|
||||||
#fade-in-step = 0.05;
|
|
||||||
#fade-out-step = 0.05;
|
|
||||||
#fade-delta = 8
|
|
||||||
#fade-exclude = []
|
|
||||||
#no-fading-openclose = false
|
|
||||||
#no-fading-destroyed-argb = false
|
|
||||||
|
|
||||||
## Transparency and opacity
|
|
||||||
inactive-opacity = 1.00;
|
|
||||||
frame-opacity = 1.0;
|
|
||||||
inactive-opacity-override = false;
|
|
||||||
focus-exclude = [ "class_g = 'Cairo-clock'" ];
|
|
||||||
# opaity-rule = []
|
|
||||||
|
|
||||||
## General Settings
|
|
||||||
backend = "xrender";
|
|
||||||
vsync = true;
|
|
||||||
dbe = false;
|
|
||||||
detect-client-opacity = true;
|
|
||||||
refresh-rate = 60;
|
|
||||||
detect-transient = true;
|
|
||||||
glx-no-stencil = true;
|
|
||||||
use-damage = true;
|
|
||||||
unredir-if-possible = false;
|
|
||||||
#unredir-if-possible-exclude = [
|
|
||||||
# "class_g = 'looking-glass-client' && !focused"
|
|
||||||
#];
|
|
||||||
glx-use-copysubbuffer-mesa = true;
|
|
||||||
|
|
||||||
wintypes:
|
|
||||||
{
|
|
||||||
normal = { fade = true; full-shadow = true; };
|
|
||||||
tooltip = { fade = true; };
|
|
||||||
menu = { fade = true; };
|
|
||||||
popup_menu = { fade = true; };
|
|
||||||
dropdown_menu = { fade = true; };
|
|
||||||
utility = { fade = true; };
|
|
||||||
dialog = { fade = true; };
|
|
||||||
notify = { fade = true; };
|
|
||||||
unknown = { fade = true; };
|
|
||||||
# notification = { shadow = true; };
|
|
||||||
# dock = { shadow = false; };
|
|
||||||
};
|
|
||||||
|
|
1
user/.config/ranger/commands.py
Normal file
1
user/.config/ranger/commands.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from ranger_udisk_menu.mounter import mount
|
243
user/.config/ranger/ranger_udisk_menu/menu.py
Normal file
243
user/.config/ranger/ranger_udisk_menu/menu.py
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
# coding: utf-8
|
||||||
|
# License: The MIT License
|
||||||
|
# Author: Alexander Lutsai <sl_ru@live.com>
|
||||||
|
# Year: 2021
|
||||||
|
# Description: This script draws menu to choose, mount and unmount drives
|
||||||
|
|
||||||
|
import curses
|
||||||
|
import curses.ascii
|
||||||
|
import subprocess
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
class ChoosePartition:
|
||||||
|
blkinfo = None
|
||||||
|
screen = None
|
||||||
|
selected_partn = 1
|
||||||
|
selected_mountpoint = None
|
||||||
|
partn = 1
|
||||||
|
help_message = ["Press 'm' to mount, 'u' to unmount, 'g' to refresh",
|
||||||
|
" and 'e' to unmount, 'p' to poweroff drive, 'enter' to cd"]
|
||||||
|
message = ""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.screen = curses.initscr()
|
||||||
|
curses.start_color()
|
||||||
|
curses.curs_set(0)
|
||||||
|
curses.noecho()
|
||||||
|
curses.cbreak()
|
||||||
|
self.screen.keypad(True)
|
||||||
|
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
|
||||||
|
self.selected_partn = 1
|
||||||
|
self._read_partitions()
|
||||||
|
|
||||||
|
def _read_partitions(self):
|
||||||
|
r = subprocess.check_output(['lsblk', '--all', '--json', '-O'])
|
||||||
|
r = r.decode().replace('0B,', '\"0B\",')
|
||||||
|
self.blkinfo = json.loads(r.encode())
|
||||||
|
partn = 0
|
||||||
|
# filter for devices with children, none other are used by this script
|
||||||
|
# (this is not entirely correct, but goes beyond these lines)
|
||||||
|
self.blkinfo['blockdevices'] = [
|
||||||
|
bd
|
||||||
|
for bd in self.blkinfo['blockdevices']
|
||||||
|
if 'children' in bd]
|
||||||
|
for bd in self.blkinfo['blockdevices']:
|
||||||
|
if 'children' not in bd:
|
||||||
|
continue
|
||||||
|
for part in bd['children']:
|
||||||
|
partn += 1
|
||||||
|
|
||||||
|
self.partn = partn
|
||||||
|
if self.selected_partn > self.partn:
|
||||||
|
self.selected_partn = self.partn
|
||||||
|
if self.selected_partn <= 0:
|
||||||
|
self.selected_partn = 1
|
||||||
|
|
||||||
|
def _get_part_by_partn(self):
|
||||||
|
partn = 0
|
||||||
|
for bd in self.blkinfo['blockdevices']:
|
||||||
|
if 'children' not in bd:
|
||||||
|
continue
|
||||||
|
for part in bd['children']:
|
||||||
|
partn += 1
|
||||||
|
if self.selected_partn == partn:
|
||||||
|
return part
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _get_drive_by_partn(self):
|
||||||
|
partn = 0
|
||||||
|
for bd in self.blkinfo['blockdevices']:
|
||||||
|
if 'children' not in bd:
|
||||||
|
continue
|
||||||
|
for part in bd['children']:
|
||||||
|
partn += 1
|
||||||
|
if self.selected_partn == partn:
|
||||||
|
return bd
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _select_print_part(self, part, is_selected, i):
|
||||||
|
if not ('mountpoint' in part and
|
||||||
|
'name' in part and
|
||||||
|
'size' in part):
|
||||||
|
raise Exception('Wrong lsblk json format.' +
|
||||||
|
'No mountpoint, name or size in the partition')
|
||||||
|
label = ""
|
||||||
|
label_fields = ['label', 'partlabel', 'parttypename', 'fstype']
|
||||||
|
for f in label_fields:
|
||||||
|
if f not in part:
|
||||||
|
continue
|
||||||
|
if part[f] is not None:
|
||||||
|
label = part[f]
|
||||||
|
break
|
||||||
|
|
||||||
|
mp = None
|
||||||
|
if part['mountpoint'] is not None:
|
||||||
|
mp = part['mountpoint']
|
||||||
|
if is_selected:
|
||||||
|
self.selected_mountpoint = mp
|
||||||
|
if mp is None:
|
||||||
|
mp = "Not mounted"
|
||||||
|
|
||||||
|
s = "{name:<12} {size:<8} {label:<16} {mp}".format(
|
||||||
|
name=part['name'] if part['name'] is not None else "None",
|
||||||
|
label=label if label is not None else "None",
|
||||||
|
size=part['size'] if part['size'] is not None else "None",
|
||||||
|
mp=mp
|
||||||
|
)
|
||||||
|
self.screen.addstr(2 + i, 4, s, curses.color_pair(is_selected))
|
||||||
|
|
||||||
|
def _select_print_block_device(self, bd, i):
|
||||||
|
if not ('model' in bd and
|
||||||
|
'size' in bd or
|
||||||
|
'name' in bd):
|
||||||
|
raise Exception('Wrong lsblk json format. ' +
|
||||||
|
'No model, size or name in blockdevice')
|
||||||
|
|
||||||
|
model = bd['model'] if bd['model'] is not None else ""
|
||||||
|
size = bd['size'] if bd['size'] is not None else ""
|
||||||
|
self.screen.addstr(2 + i, 2, bd['name'] + " " + model + " " + size)
|
||||||
|
|
||||||
|
def _select_print(self, x):
|
||||||
|
self.screen.clear()
|
||||||
|
self.screen.border(0)
|
||||||
|
self.screen.addstr(1, 2, self.help_message[0])
|
||||||
|
self.screen.addstr(2, 2, self.help_message[1])
|
||||||
|
|
||||||
|
partn = 0
|
||||||
|
i = 0
|
||||||
|
if 'blockdevices' not in self.blkinfo:
|
||||||
|
raise Exception('Wrong lsblk json format. No field "blockdevices"')
|
||||||
|
for bd in self.blkinfo['blockdevices']:
|
||||||
|
i += 1
|
||||||
|
bd_selected = False
|
||||||
|
bd_i = i
|
||||||
|
self._select_print_block_device(bd, bd_i)
|
||||||
|
if 'children' not in bd:
|
||||||
|
continue
|
||||||
|
for part in bd['children']:
|
||||||
|
i += 1
|
||||||
|
partn += 1
|
||||||
|
is_selected = 0 if self.selected_partn != partn else 1
|
||||||
|
if is_selected:
|
||||||
|
bd_selected = True
|
||||||
|
self._select_print_part(part, is_selected, i)
|
||||||
|
if bd_selected:
|
||||||
|
self.screen.addstr(2 + bd_i, 1, ">")
|
||||||
|
self.screen.addstr(2 + i + 2, 4, self.message)
|
||||||
|
|
||||||
|
def _eject_all(self):
|
||||||
|
blk = None
|
||||||
|
partn = 0
|
||||||
|
for bd in self.blkinfo['blockdevices']:
|
||||||
|
if 'children' not in bd:
|
||||||
|
continue
|
||||||
|
for part in bd['children']:
|
||||||
|
partn += 1
|
||||||
|
if self.selected_partn == partn:
|
||||||
|
blk = bd
|
||||||
|
if blk is None:
|
||||||
|
return
|
||||||
|
for part in blk['children']:
|
||||||
|
self.unmount(part)
|
||||||
|
|
||||||
|
def select(self):
|
||||||
|
sel = None
|
||||||
|
x = 0
|
||||||
|
# quit when pressed `q` or `Esc` or `Ctrl+g`
|
||||||
|
while x not in (ord('q'), curses.ascii.ESC,
|
||||||
|
curses.ascii.BEL, curses.ascii.NL):
|
||||||
|
self._select_print(x)
|
||||||
|
x = self.screen.getch()
|
||||||
|
if x in (ord('j'), curses.ascii.SO, curses.KEY_DOWN):
|
||||||
|
# down
|
||||||
|
self.selected_partn += 1
|
||||||
|
if self.selected_partn > self.partn:
|
||||||
|
self.selected_partn = self.partn
|
||||||
|
elif x in (ord('k'), curses.ascii.DLE, curses.KEY_UP):
|
||||||
|
# up
|
||||||
|
self.selected_partn -= 1
|
||||||
|
if self.selected_partn <= 0:
|
||||||
|
self.selected_partn = 1
|
||||||
|
elif x == ord('e'):
|
||||||
|
sel = self._eject_all()
|
||||||
|
elif x == ord('m'):
|
||||||
|
sel = self._get_part_by_partn()
|
||||||
|
if sel is not None:
|
||||||
|
self.mount(sel)
|
||||||
|
elif x == ord('u'):
|
||||||
|
sel = self._get_part_by_partn()
|
||||||
|
if sel is not None:
|
||||||
|
self.unmount(sel)
|
||||||
|
elif x == ord('p'):
|
||||||
|
sel_drive = self._get_drive_by_partn()
|
||||||
|
if sel_drive is not None:
|
||||||
|
self.poweroff(sel_drive)
|
||||||
|
elif x == ord('g') or x == ord('r'):
|
||||||
|
self._read_partitions()
|
||||||
|
curses.endwin()
|
||||||
|
if self.selected_mountpoint is not None and x == curses.ascii.NL:
|
||||||
|
return self.selected_mountpoint
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def _udisk_mount_unmount(self, cmd, dev):
|
||||||
|
r = ""
|
||||||
|
try:
|
||||||
|
r = subprocess.run(
|
||||||
|
['udisksctl', cmd, '-b', dev], capture_output=True)
|
||||||
|
r = (r.stdout.decode(encoding="utf-8") +
|
||||||
|
r.stderr.decode(encoding="utf-8"))
|
||||||
|
self.message = r
|
||||||
|
except Exception as e:
|
||||||
|
self.message = cmd + " error: " + r + str(e)
|
||||||
|
self._read_partitions()
|
||||||
|
|
||||||
|
def get_drive_path(self, drive):
|
||||||
|
if 'path' not in drive:
|
||||||
|
drive['path'] = '/dev/' + drive['kname']
|
||||||
|
return drive['path']
|
||||||
|
|
||||||
|
def unmount(self, dev):
|
||||||
|
p = self.get_drive_path(dev)
|
||||||
|
self._udisk_mount_unmount("unmount", p)
|
||||||
|
|
||||||
|
def poweroff(self, dev):
|
||||||
|
p = self.get_drive_path(dev)
|
||||||
|
self._udisk_mount_unmount("power-off", p)
|
||||||
|
|
||||||
|
def mount(self, dev):
|
||||||
|
p = self.get_drive_path(dev)
|
||||||
|
self._udisk_mount_unmount("mount", p)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
cp = ChoosePartition()
|
||||||
|
sel = cp.select()
|
||||||
|
# print(sel)
|
||||||
|
# print(len(sys.argv))
|
||||||
|
if len(sys.argv) >= 2:
|
||||||
|
# print(sys.argv[1])
|
||||||
|
with open(sys.argv[1], 'w') as f:
|
||||||
|
f.write(sel)
|
29
user/.config/ranger/ranger_udisk_menu/mounter.py
Normal file
29
user/.config/ranger/ranger_udisk_menu/mounter.py
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
# coding: utf-8
|
||||||
|
# License: The MIT License
|
||||||
|
# Author: Alexander Lutsai <sl_ru@live.com>
|
||||||
|
# Year: 2021
|
||||||
|
# Description: This launches script that draws menu to choose, mount and unmount drives from ranger file manager
|
||||||
|
|
||||||
|
from ranger.api.commands import Command
|
||||||
|
import tempfile
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class mount(Command):
|
||||||
|
""":mount
|
||||||
|
|
||||||
|
Show menu to mount and unmount
|
||||||
|
"""
|
||||||
|
def execute(self):
|
||||||
|
""" Show menu to mount and unmount """
|
||||||
|
(f, p) = tempfile.mkstemp()
|
||||||
|
os.close(f)
|
||||||
|
self.fm.execute_console(
|
||||||
|
f"shell python3 {os.path.dirname(os.path.realpath(__file__))}/menu.py {p}"
|
||||||
|
)
|
||||||
|
with open(p, 'r') as f:
|
||||||
|
d = f.readline()
|
||||||
|
if os.path.exists(d):
|
||||||
|
self.fm.cd(d)
|
||||||
|
os.remove(p)
|
3
user/.config/ranger/rc.conf
Normal file
3
user/.config/ranger/rc.conf
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
set preview_images true
|
||||||
|
set preview_images_method iterm2
|
||||||
|
set viewmode multipane
|
284
user/.config/ranger/rifle.conf
Normal file
284
user/.config/ranger/rifle.conf
Normal file
|
@ -0,0 +1,284 @@
|
||||||
|
# vim: ft=cfg
|
||||||
|
#
|
||||||
|
# This is the configuration file of "rifle", ranger's file executor/opener.
|
||||||
|
# Each line consists of conditions and a command. For each line the conditions
|
||||||
|
# are checked and if they are met, the respective command is run.
|
||||||
|
#
|
||||||
|
# Syntax:
|
||||||
|
# <condition1> , <condition2> , ... = command
|
||||||
|
#
|
||||||
|
# The command can contain these environment variables:
|
||||||
|
# $1-$9 | The n-th selected file
|
||||||
|
# $@ | All selected files
|
||||||
|
#
|
||||||
|
# If you use the special command "ask", rifle will ask you what program to run.
|
||||||
|
#
|
||||||
|
# Prefixing a condition with "!" will negate its result.
|
||||||
|
# These conditions are currently supported:
|
||||||
|
# match <regexp> | The regexp matches $1
|
||||||
|
# ext <regexp> | The regexp matches the extension of $1
|
||||||
|
# mime <regexp> | The regexp matches the mime type of $1
|
||||||
|
# name <regexp> | The regexp matches the basename of $1
|
||||||
|
# path <regexp> | The regexp matches the absolute path of $1
|
||||||
|
# has <program> | The program is installed (i.e. located in $PATH)
|
||||||
|
# env <variable> | The environment variable "variable" is non-empty
|
||||||
|
# file | $1 is a file
|
||||||
|
# directory | $1 is a directory
|
||||||
|
# number <n> | change the number of this command to n
|
||||||
|
# terminal | stdin, stderr and stdout are connected to a terminal
|
||||||
|
# X | A graphical environment is available (darwin, Xorg, or Wayland)
|
||||||
|
#
|
||||||
|
# There are also pseudo-conditions which have a "side effect":
|
||||||
|
# flag <flags> | Change how the program is run. See below.
|
||||||
|
# label <label> | Assign a label or name to the command so it can
|
||||||
|
# | be started with :open_with <label> in ranger
|
||||||
|
# | or `rifle -p <label>` in the standalone executable.
|
||||||
|
# else | Always true.
|
||||||
|
#
|
||||||
|
# Flags are single characters which slightly transform the command:
|
||||||
|
# f | Fork the program, make it run in the background.
|
||||||
|
# | New command = setsid $command >& /dev/null &
|
||||||
|
# r | Execute the command with root permissions
|
||||||
|
# | New command = sudo $command
|
||||||
|
# t | Run the program in a new terminal. If $TERMCMD is not defined,
|
||||||
|
# | rifle will attempt to extract it from $TERM.
|
||||||
|
# | New command = $TERMCMD -e $command
|
||||||
|
# Note: The "New command" serves only as an illustration, the exact
|
||||||
|
# implementation may differ.
|
||||||
|
# Note: When using rifle in ranger, there is an additional flag "c" for
|
||||||
|
# only running the current file even if you have marked multiple files.
|
||||||
|
|
||||||
|
#-------------------------------------------
|
||||||
|
# Websites
|
||||||
|
#-------------------------------------------
|
||||||
|
# Rarely installed browsers get higher priority; It is assumed that if you
|
||||||
|
# install a rare browser, you probably use it. Firefox/konqueror/w3m on the
|
||||||
|
# other hand are often only installed as fallback browsers.
|
||||||
|
ext x?html?, has surf, X, flag f = surf -- file://"$1"
|
||||||
|
ext x?html?, has vimprobable, X, flag f = vimprobable -- "$@"
|
||||||
|
ext x?html?, has vimprobable2, X, flag f = vimprobable2 -- "$@"
|
||||||
|
ext x?html?, has qutebrowser, X, flag f = qutebrowser -- "$@"
|
||||||
|
ext x?html?, has dwb, X, flag f = dwb -- "$@"
|
||||||
|
ext x?html?, has jumanji, X, flag f = jumanji -- "$@"
|
||||||
|
ext x?html?, has luakit, X, flag f = luakit -- "$@"
|
||||||
|
ext x?html?, has uzbl, X, flag f = uzbl -- "$@"
|
||||||
|
ext x?html?, has uzbl-tabbed, X, flag f = uzbl-tabbed -- "$@"
|
||||||
|
ext x?html?, has uzbl-browser, X, flag f = uzbl-browser -- "$@"
|
||||||
|
ext x?html?, has uzbl-core, X, flag f = uzbl-core -- "$@"
|
||||||
|
ext x?html?, has midori, X, flag f = midori -- "$@"
|
||||||
|
ext x?html?, has opera, X, flag f = opera -- "$@"
|
||||||
|
ext x?html?, has firefox, X, flag f = firefox -- "$@"
|
||||||
|
ext x?html?, has seamonkey, X, flag f = seamonkey -- "$@"
|
||||||
|
ext x?html?, has iceweasel, X, flag f = iceweasel -- "$@"
|
||||||
|
ext x?html?, has chromium-browser, X, flag f = chromium-browser -- "$@"
|
||||||
|
ext x?html?, has chromium, X, flag f = chromium -- "$@"
|
||||||
|
ext x?html?, has google-chrome, X, flag f = google-chrome -- "$@"
|
||||||
|
ext x?html?, has epiphany, X, flag f = epiphany -- "$@"
|
||||||
|
ext x?html?, has konqueror, X, flag f = konqueror -- "$@"
|
||||||
|
ext x?html?, has elinks, terminal = elinks "$@"
|
||||||
|
ext x?html?, has links2, terminal = links2 "$@"
|
||||||
|
ext x?html?, has links, terminal = links "$@"
|
||||||
|
ext x?html?, has lynx, terminal = lynx -- "$@"
|
||||||
|
ext x?html?, has w3m, terminal = w3m "$@"
|
||||||
|
|
||||||
|
#-------------------------------------------
|
||||||
|
# Misc
|
||||||
|
#-------------------------------------------
|
||||||
|
# Define the "editor" for text files as first action
|
||||||
|
mime ^text, label editor = ${VISUAL:-$EDITOR} -- "$@"
|
||||||
|
mime ^text, label pager = "$PAGER" -- "$@"
|
||||||
|
!mime ^text, label editor, ext xml|json|csv|tex|py|pl|rb|js|sh|php = ${VISUAL:-$EDITOR} -- "$@"
|
||||||
|
!mime ^text, label pager, ext xml|json|csv|tex|py|pl|rb|js|sh|php = "$PAGER" -- "$@"
|
||||||
|
|
||||||
|
ext 1 = man "$1"
|
||||||
|
ext s[wmf]c, has zsnes, X = zsnes "$1"
|
||||||
|
ext s[wmf]c, has snes9x-gtk,X = snes9x-gtk "$1"
|
||||||
|
ext nes, has fceux, X = fceux "$1"
|
||||||
|
ext exe = wine "$1"
|
||||||
|
name ^[mM]akefile$ = make
|
||||||
|
|
||||||
|
#--------------------------------------------
|
||||||
|
# Scripts
|
||||||
|
#-------------------------------------------
|
||||||
|
ext py = python -- "$1"
|
||||||
|
ext pl = perl -- "$1"
|
||||||
|
ext rb = ruby -- "$1"
|
||||||
|
ext js = node -- "$1"
|
||||||
|
ext sh = sh -- "$1"
|
||||||
|
ext php = php -- "$1"
|
||||||
|
|
||||||
|
#--------------------------------------------
|
||||||
|
# Audio without X
|
||||||
|
#-------------------------------------------
|
||||||
|
mime ^audio|ogg$, terminal, has mpv = mpv -- "$@"
|
||||||
|
mime ^audio|ogg$, terminal, has mplayer2 = mplayer2 -- "$@"
|
||||||
|
mime ^audio|ogg$, terminal, has mplayer = mplayer -- "$@"
|
||||||
|
ext midi?, terminal, has wildmidi = wildmidi -- "$@"
|
||||||
|
|
||||||
|
#--------------------------------------------
|
||||||
|
# Video/Audio with a GUI
|
||||||
|
#-------------------------------------------
|
||||||
|
mime ^video|audio, has gmplayer, X, flag f = gmplayer -- "$@"
|
||||||
|
mime ^video|audio, has smplayer, X, flag f = smplayer "$@"
|
||||||
|
mime ^video, has mpv, X, flag f = mpv -- "$@"
|
||||||
|
mime ^video, has mpv, X, flag f = mpv --fs -- "$@"
|
||||||
|
mime ^video, has mplayer2, X, flag f = mplayer2 -- "$@"
|
||||||
|
mime ^video, has mplayer2, X, flag f = mplayer2 -fs -- "$@"
|
||||||
|
mime ^video, has mplayer, X, flag f = mplayer -- "$@"
|
||||||
|
mime ^video, has mplayer, X, flag f = mplayer -fs -- "$@"
|
||||||
|
mime ^video|audio, has vlc, X, flag f = vlc -- "$@"
|
||||||
|
mime ^video|audio, has totem, X, flag f = totem -- "$@"
|
||||||
|
mime ^video|audio, has totem, X, flag f = totem --fullscreen -- "$@"
|
||||||
|
|
||||||
|
#--------------------------------------------
|
||||||
|
# Video without X
|
||||||
|
#-------------------------------------------
|
||||||
|
mime ^video, terminal, !X, has mpv = mpv -- "$@"
|
||||||
|
mime ^video, terminal, !X, has mplayer2 = mplayer2 -- "$@"
|
||||||
|
mime ^video, terminal, !X, has mplayer = mplayer -- "$@"
|
||||||
|
|
||||||
|
#-------------------------------------------
|
||||||
|
# Documents
|
||||||
|
#-------------------------------------------
|
||||||
|
ext pdf, has llpp, X, flag f = llpp "$@"
|
||||||
|
ext pdf, has zathura, X, flag f = zathura -- "$@"
|
||||||
|
ext pdf, has mupdf, X, flag f = mupdf "$@"
|
||||||
|
ext pdf, has mupdf-x11,X, flag f = mupdf-x11 "$@"
|
||||||
|
ext pdf, has apvlv, X, flag f = apvlv -- "$@"
|
||||||
|
ext pdf, has xpdf, X, flag f = xpdf -- "$@"
|
||||||
|
ext pdf, has evince, X, flag f = evince -- "$@"
|
||||||
|
ext pdf, has atril, X, flag f = atril -- "$@"
|
||||||
|
ext pdf, has okular, X, flag f = okular -- "$@"
|
||||||
|
ext pdf, has epdfview, X, flag f = epdfview -- "$@"
|
||||||
|
ext pdf, has qpdfview, X, flag f = qpdfview "$@"
|
||||||
|
ext pdf, has open, X, flag f = open "$@"
|
||||||
|
|
||||||
|
ext docx?, has catdoc, terminal = catdoc -- "$@" | "$PAGER"
|
||||||
|
|
||||||
|
ext sxc|xlsx?|xlt|xlw|gnm|gnumeric, has gnumeric, X, flag f = gnumeric -- "$@"
|
||||||
|
ext sxc|xlsx?|xlt|xlw|gnm|gnumeric, has kspread, X, flag f = kspread -- "$@"
|
||||||
|
ext pptx?|od[dfgpst]|docx?|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has libreoffice, X, flag f = libreoffice "$@"
|
||||||
|
ext pptx?|od[dfgpst]|docx?|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has soffice, X, flag f = soffice "$@"
|
||||||
|
ext pptx?|od[dfgpst]|docx?|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has ooffice, X, flag f = ooffice "$@"
|
||||||
|
|
||||||
|
ext djvu, has zathura,X, flag f = zathura -- "$@"
|
||||||
|
ext djvu, has evince, X, flag f = evince -- "$@"
|
||||||
|
ext djvu, has atril, X, flag f = atril -- "$@"
|
||||||
|
ext djvu, has djview, X, flag f = djview -- "$@"
|
||||||
|
|
||||||
|
ext epub, has ebook-viewer, X, flag f = ebook-viewer -- "$@"
|
||||||
|
ext epub, has zathura, X, flag f = zathura -- "$@"
|
||||||
|
ext epub, has mupdf, X, flag f = mupdf -- "$@"
|
||||||
|
ext mobi, has ebook-viewer, X, flag f = ebook-viewer -- "$@"
|
||||||
|
|
||||||
|
ext cbr, has zathura, X, flag f = zathura -- "$@"
|
||||||
|
ext cbz, has zathura, X, flag f = zathura -- "$@"
|
||||||
|
|
||||||
|
#-------------------------------------------
|
||||||
|
# Images
|
||||||
|
#-------------------------------------------
|
||||||
|
mime ^image/svg, has inkscape, X, flag f = inkscape -- "$@"
|
||||||
|
mime ^image/svg, has display, X, flag f = display -- "$@"
|
||||||
|
|
||||||
|
mime ^image, has imv, X, flag f = imv -- "$@"
|
||||||
|
mime ^image, has pqiv, X, flag f = pqiv -- "$@"
|
||||||
|
mime ^image, has sxiv, X, flag f = sxiv -- "$@"
|
||||||
|
mime ^image, has feh, X, flag f = feh -- "$@"
|
||||||
|
mime ^image, has mirage, X, flag f = mirage -- "$@"
|
||||||
|
mime ^image, has ristretto, X, flag f = ristretto "$@"
|
||||||
|
mime ^image, has eog, X, flag f = eog -- "$@"
|
||||||
|
mime ^image, has eom, X, flag f = eom -- "$@"
|
||||||
|
mime ^image, has nomacs, X, flag f = nomacs -- "$@"
|
||||||
|
mime ^image, has geeqie, X, flag f = geeqie -- "$@"
|
||||||
|
mime ^image, has gpicview, X, flag f = gpicview -- "$@"
|
||||||
|
mime ^image, has gwenview, X, flag f = gwenview -- "$@"
|
||||||
|
mime ^image, has gimp, X, flag f = gimp -- "$@"
|
||||||
|
ext xcf, X, flag f = gimp -- "$@"
|
||||||
|
|
||||||
|
#-------------------------------------------
|
||||||
|
# Archives
|
||||||
|
#-------------------------------------------
|
||||||
|
|
||||||
|
# avoid password prompt by providing empty password
|
||||||
|
ext 7z, has 7z = 7z -p l "$@" | "$PAGER"
|
||||||
|
# This requires atool
|
||||||
|
ext ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz, has atool = atool --list --each -- "$@" | "$PAGER"
|
||||||
|
ext iso|jar|msi|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has atool = atool --list --each -- "$@" | "$PAGER"
|
||||||
|
ext 7z|ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz, has atool = atool --extract --each -- "$@"
|
||||||
|
ext iso|jar|msi|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has atool = atool --extract --each -- "$@"
|
||||||
|
|
||||||
|
# Listing and extracting archives without atool:
|
||||||
|
ext tar|gz|bz2|xz, has tar = tar vvtf "$1" | "$PAGER"
|
||||||
|
ext tar|gz|bz2|xz, has tar = for file in "$@"; do tar vvxf "$file"; done
|
||||||
|
ext bz2, has bzip2 = for file in "$@"; do bzip2 -dk "$file"; done
|
||||||
|
ext zip, has unzip = unzip -l "$1" | less
|
||||||
|
ext zip, has unzip = for file in "$@"; do unzip -d "${file%.*}" "$file"; done
|
||||||
|
ext ace, has unace = unace l "$1" | less
|
||||||
|
ext ace, has unace = for file in "$@"; do unace e "$file"; done
|
||||||
|
ext rar, has unrar = unrar l "$1" | less
|
||||||
|
ext rar, has unrar = for file in "$@"; do unrar x "$file"; done
|
||||||
|
|
||||||
|
#-------------------------------------------
|
||||||
|
# Fonts
|
||||||
|
#-------------------------------------------
|
||||||
|
mime ^font, has fontforge, X, flag f = fontforge "$@"
|
||||||
|
|
||||||
|
#-------------------------------------------
|
||||||
|
# Flag t fallback terminals
|
||||||
|
#-------------------------------------------
|
||||||
|
# Rarely installed terminal emulators get higher priority; It is assumed that
|
||||||
|
# if you install a rare terminal emulator, you probably use it.
|
||||||
|
# gnome-terminal/konsole/xterm on the other hand are often installed as part of
|
||||||
|
# a desktop environment or as fallback terminal emulators.
|
||||||
|
mime ^ranger/x-terminal-emulator, has terminology = terminology -e "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has kitty = kitty -- "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has alacritty = alacritty -e "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has sakura = sakura -e "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has lilyterm = lilyterm -e "$@"
|
||||||
|
#mime ^ranger/x-terminal-emulator, has cool-retro-term = cool-retro-term -e "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has termite = termite -x '"$@"'
|
||||||
|
#mime ^ranger/x-terminal-emulator, has yakuake = yakuake -e "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has guake = guake -ne "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has tilda = tilda -c "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has st = st -e "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has terminator = terminator -x "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has urxvt = urxvt -e "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has pantheon-terminal = pantheon-terminal -e "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has lxterminal = lxterminal -e "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has mate-terminal = mate-terminal -x "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has xfce4-terminal = xfce4-terminal -x "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has konsole = konsole -e "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has gnome-terminal = gnome-terminal -- "$@"
|
||||||
|
mime ^ranger/x-terminal-emulator, has xterm = xterm -e "$@"
|
||||||
|
|
||||||
|
#-------------------------------------------
|
||||||
|
# Misc
|
||||||
|
#-------------------------------------------
|
||||||
|
label wallpaper, number 11, mime ^image, has feh, X = feh --bg-scale "$1"
|
||||||
|
label wallpaper, number 12, mime ^image, has feh, X = feh --bg-tile "$1"
|
||||||
|
label wallpaper, number 13, mime ^image, has feh, X = feh --bg-center "$1"
|
||||||
|
label wallpaper, number 14, mime ^image, has feh, X = feh --bg-fill "$1"
|
||||||
|
|
||||||
|
#-------------------------------------------
|
||||||
|
# Generic file openers
|
||||||
|
#-------------------------------------------
|
||||||
|
label open, has xdg-open = xdg-open -- "$@"
|
||||||
|
label open, has open = open -- "$@"
|
||||||
|
|
||||||
|
# Define the editor for non-text files + pager as last action
|
||||||
|
!mime ^text, !ext xml|json|csv|tex|py|pl|rb|js|sh|php = ask
|
||||||
|
label editor, !mime ^text, !ext xml|json|csv|tex|py|pl|rb|js|sh|php = ${VISUAL:-$EDITOR} -- "$@"
|
||||||
|
label pager, !mime ^text, !ext xml|json|csv|tex|py|pl|rb|js|sh|php = "$PAGER" -- "$@"
|
||||||
|
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# The actions below are left so low down in this file on purpose, so #
|
||||||
|
# they are never triggered accidentally. #
|
||||||
|
######################################################################
|
||||||
|
|
||||||
|
# Execute a file as program/script.
|
||||||
|
mime application/x-executable = "$1"
|
||||||
|
|
||||||
|
# Move the file to trash using trash-cli.
|
||||||
|
label trash, has trash-put = trash-put -- "$@"
|
||||||
|
label trash = mkdir -p -- ${XDG_DATA_DIR:-$HOME/.ranger}/ranger-trash; mv -- "$@" ${XDG_DATA_DIR:-$HOME/.ranger}/ranger-trash
|
350
user/.config/ranger/scope.sh
Executable file
350
user/.config/ranger/scope.sh
Executable file
|
@ -0,0 +1,350 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -o noclobber -o noglob -o nounset -o pipefail
|
||||||
|
IFS=$'\n'
|
||||||
|
|
||||||
|
## If the option `use_preview_script` is set to `true`,
|
||||||
|
## then this script will be called and its output will be displayed in ranger.
|
||||||
|
## ANSI color codes are supported.
|
||||||
|
## STDIN is disabled, so interactive scripts won't work properly
|
||||||
|
|
||||||
|
## This script is considered a configuration file and must be updated manually.
|
||||||
|
## It will be left untouched if you upgrade ranger.
|
||||||
|
|
||||||
|
## Because of some automated testing we do on the script #'s for comments need
|
||||||
|
## to be doubled up. Code that is commented out, because it's an alternative for
|
||||||
|
## example, gets only one #.
|
||||||
|
|
||||||
|
## Meanings of exit codes:
|
||||||
|
## code | meaning | action of ranger
|
||||||
|
## -----+------------+-------------------------------------------
|
||||||
|
## 0 | success | Display stdout as preview
|
||||||
|
## 1 | no preview | Display no preview at all
|
||||||
|
## 2 | plain text | Display the plain content of the file
|
||||||
|
## 3 | fix width | Don't reload when width changes
|
||||||
|
## 4 | fix height | Don't reload when height changes
|
||||||
|
## 5 | fix both | Don't ever reload
|
||||||
|
## 6 | image | Display the image `$IMAGE_CACHE_PATH` points to as an image preview
|
||||||
|
## 7 | image | Display the file directly as an image
|
||||||
|
|
||||||
|
## Script arguments
|
||||||
|
FILE_PATH="${1}" # Full path of the highlighted file
|
||||||
|
PV_WIDTH="${2}" # Width of the preview pane (number of fitting characters)
|
||||||
|
## shellcheck disable=SC2034 # PV_HEIGHT is provided for convenience and unused
|
||||||
|
PV_HEIGHT="${3}" # Height of the preview pane (number of fitting characters)
|
||||||
|
IMAGE_CACHE_PATH="${4}" # Full path that should be used to cache image preview
|
||||||
|
PV_IMAGE_ENABLED="${5}" # 'True' if image previews are enabled, 'False' otherwise.
|
||||||
|
|
||||||
|
FILE_EXTENSION="${FILE_PATH##*.}"
|
||||||
|
FILE_EXTENSION_LOWER="$(printf "%s" "${FILE_EXTENSION}" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
|
||||||
|
## Settings
|
||||||
|
HIGHLIGHT_SIZE_MAX=262143 # 256KiB
|
||||||
|
HIGHLIGHT_TABWIDTH=${HIGHLIGHT_TABWIDTH:-8}
|
||||||
|
HIGHLIGHT_STYLE=${HIGHLIGHT_STYLE:-pablo}
|
||||||
|
HIGHLIGHT_OPTIONS="--replace-tabs=${HIGHLIGHT_TABWIDTH} --style=${HIGHLIGHT_STYLE} ${HIGHLIGHT_OPTIONS:-}"
|
||||||
|
PYGMENTIZE_STYLE=${PYGMENTIZE_STYLE:-autumn}
|
||||||
|
OPENSCAD_IMGSIZE=${RNGR_OPENSCAD_IMGSIZE:-1000,1000}
|
||||||
|
OPENSCAD_COLORSCHEME=${RNGR_OPENSCAD_COLORSCHEME:-Tomorrow Night}
|
||||||
|
|
||||||
|
handle_extension() {
|
||||||
|
case "${FILE_EXTENSION_LOWER}" in
|
||||||
|
## Archive
|
||||||
|
a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|\
|
||||||
|
rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)
|
||||||
|
atool --list -- "${FILE_PATH}" && exit 5
|
||||||
|
bsdtar --list --file "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
rar)
|
||||||
|
## Avoid password prompt by providing empty password
|
||||||
|
unrar lt -p- -- "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
7z)
|
||||||
|
## Avoid password prompt by providing empty password
|
||||||
|
7z l -p -- "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## PDF
|
||||||
|
pdf)
|
||||||
|
## Preview as text conversion
|
||||||
|
pdftotext -l 10 -nopgbrk -q -- "${FILE_PATH}" - | \
|
||||||
|
fmt -w "${PV_WIDTH}" && exit 5
|
||||||
|
mutool draw -F txt -i -- "${FILE_PATH}" 1-10 | \
|
||||||
|
fmt -w "${PV_WIDTH}" && exit 5
|
||||||
|
exiftool "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## BitTorrent
|
||||||
|
torrent)
|
||||||
|
transmission-show -- "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## OpenDocument
|
||||||
|
odt|ods|odp|sxw)
|
||||||
|
## Preview as text conversion
|
||||||
|
odt2txt "${FILE_PATH}" && exit 5
|
||||||
|
## Preview as markdown conversion
|
||||||
|
pandoc -s -t markdown -- "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## XLSX
|
||||||
|
xlsx)
|
||||||
|
## Preview as csv conversion
|
||||||
|
## Uses: https://github.com/dilshod/xlsx2csv
|
||||||
|
xlsx2csv -- "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## HTML
|
||||||
|
htm|html|xhtml)
|
||||||
|
## Preview as text conversion
|
||||||
|
w3m -dump "${FILE_PATH}" && exit 5
|
||||||
|
lynx -dump -- "${FILE_PATH}" && exit 5
|
||||||
|
elinks -dump "${FILE_PATH}" && exit 5
|
||||||
|
pandoc -s -t markdown -- "${FILE_PATH}" && exit 5
|
||||||
|
;;
|
||||||
|
|
||||||
|
## JSON
|
||||||
|
json)
|
||||||
|
jq --color-output . "${FILE_PATH}" && exit 5
|
||||||
|
python -m json.tool -- "${FILE_PATH}" && exit 5
|
||||||
|
;;
|
||||||
|
|
||||||
|
## Direct Stream Digital/Transfer (DSDIFF) and wavpack aren't detected
|
||||||
|
## by file(1).
|
||||||
|
dff|dsf|wv|wvc)
|
||||||
|
mediainfo "${FILE_PATH}" && exit 5
|
||||||
|
exiftool "${FILE_PATH}" && exit 5
|
||||||
|
;; # Continue with next handler on failure
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_image() {
|
||||||
|
## Size of the preview if there are multiple options or it has to be
|
||||||
|
## rendered from vector graphics. If the conversion program allows
|
||||||
|
## specifying only one dimension while keeping the aspect ratio, the width
|
||||||
|
## will be used.
|
||||||
|
local DEFAULT_SIZE="1920x1080"
|
||||||
|
|
||||||
|
local mimetype="${1}"
|
||||||
|
case "${mimetype}" in
|
||||||
|
## SVG
|
||||||
|
# image/svg+xml|image/svg)
|
||||||
|
# convert -- "${FILE_PATH}" "${IMAGE_CACHE_PATH}" && exit 6
|
||||||
|
# exit 1;;
|
||||||
|
|
||||||
|
## DjVu
|
||||||
|
# image/vnd.djvu)
|
||||||
|
# ddjvu -format=tiff -quality=90 -page=1 -size="${DEFAULT_SIZE}" \
|
||||||
|
# - "${IMAGE_CACHE_PATH}" < "${FILE_PATH}" \
|
||||||
|
# && exit 6 || exit 1;;
|
||||||
|
|
||||||
|
## Image
|
||||||
|
image/*)
|
||||||
|
local orientation
|
||||||
|
orientation="$( identify -format '%[EXIF:Orientation]\n' -- "${FILE_PATH}" )"
|
||||||
|
## If orientation data is present and the image actually
|
||||||
|
## needs rotating ("1" means no rotation)...
|
||||||
|
if [[ -n "$orientation" && "$orientation" != 1 ]]; then
|
||||||
|
## ...auto-rotate the image according to the EXIF data.
|
||||||
|
convert -- "${FILE_PATH}" -auto-orient "${IMAGE_CACHE_PATH}" && exit 6
|
||||||
|
fi
|
||||||
|
|
||||||
|
## `w3mimgdisplay` will be called for all images (unless overriden
|
||||||
|
## as above), but might fail for unsupported types.
|
||||||
|
exit 7;;
|
||||||
|
|
||||||
|
## Video
|
||||||
|
video/*)
|
||||||
|
# Thumbnail
|
||||||
|
ffmpegthumbnailer -i "${FILE_PATH}" -o "${IMAGE_CACHE_PATH}" -s 0 && exit 6
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## PDF
|
||||||
|
application/pdf)
|
||||||
|
pdftoppm -f 1 -l 1 \
|
||||||
|
-scale-to-x "${DEFAULT_SIZE%x*}" \
|
||||||
|
-scale-to-y -1 \
|
||||||
|
-singlefile \
|
||||||
|
-jpeg -tiffcompression jpeg \
|
||||||
|
-- "${FILE_PATH}" "${IMAGE_CACHE_PATH%.*}" \
|
||||||
|
&& exit 6 || exit 1;;
|
||||||
|
|
||||||
|
|
||||||
|
## ePub, MOBI, FB2 (using Calibre)
|
||||||
|
# application/epub+zip|application/x-mobipocket-ebook|\
|
||||||
|
# application/x-fictionbook+xml)
|
||||||
|
# # ePub (using https://github.com/marianosimone/epub-thumbnailer)
|
||||||
|
# epub-thumbnailer "${FILE_PATH}" "${IMAGE_CACHE_PATH}" \
|
||||||
|
# "${DEFAULT_SIZE%x*}" && exit 6
|
||||||
|
# ebook-meta --get-cover="${IMAGE_CACHE_PATH}" -- "${FILE_PATH}" \
|
||||||
|
# >/dev/null && exit 6
|
||||||
|
# exit 1;;
|
||||||
|
|
||||||
|
## Font
|
||||||
|
application/font*|application/*opentype)
|
||||||
|
preview_png="/tmp/$(basename "${IMAGE_CACHE_PATH%.*}").png"
|
||||||
|
if fontimage -o "${preview_png}" \
|
||||||
|
--pixelsize "120" \
|
||||||
|
--fontname \
|
||||||
|
--pixelsize "80" \
|
||||||
|
--text " ABCDEFGHIJKLMNOPQRSTUVWXYZ " \
|
||||||
|
--text " abcdefghijklmnopqrstuvwxyz " \
|
||||||
|
--text " 0123456789.:,;(*!?') ff fl fi ffi ffl " \
|
||||||
|
--text " The quick brown fox jumps over the lazy dog. " \
|
||||||
|
"${FILE_PATH}";
|
||||||
|
then
|
||||||
|
convert -- "${preview_png}" "${IMAGE_CACHE_PATH}" \
|
||||||
|
&& rm "${preview_png}" \
|
||||||
|
&& exit 6
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
## Preview archives using the first image inside.
|
||||||
|
## (Very useful for comic book collections for example.)
|
||||||
|
# application/zip|application/x-rar|application/x-7z-compressed|\
|
||||||
|
# application/x-xz|application/x-bzip2|application/x-gzip|application/x-tar)
|
||||||
|
# local fn=""; local fe=""
|
||||||
|
# local zip=""; local rar=""; local tar=""; local bsd=""
|
||||||
|
# case "${mimetype}" in
|
||||||
|
# application/zip) zip=1 ;;
|
||||||
|
# application/x-rar) rar=1 ;;
|
||||||
|
# application/x-7z-compressed) ;;
|
||||||
|
# *) tar=1 ;;
|
||||||
|
# esac
|
||||||
|
# { [ "$tar" ] && fn=$(tar --list --file "${FILE_PATH}"); } || \
|
||||||
|
# { fn=$(bsdtar --list --file "${FILE_PATH}") && bsd=1 && tar=""; } || \
|
||||||
|
# { [ "$rar" ] && fn=$(unrar lb -p- -- "${FILE_PATH}"); } || \
|
||||||
|
# { [ "$zip" ] && fn=$(zipinfo -1 -- "${FILE_PATH}"); } || return
|
||||||
|
#
|
||||||
|
# fn=$(echo "$fn" | python -c "import sys; import mimetypes as m; \
|
||||||
|
# [ print(l, end='') for l in sys.stdin if \
|
||||||
|
# (m.guess_type(l[:-1])[0] or '').startswith('image/') ]" |\
|
||||||
|
# sort -V | head -n 1)
|
||||||
|
# [ "$fn" = "" ] && return
|
||||||
|
# [ "$bsd" ] && fn=$(printf '%b' "$fn")
|
||||||
|
#
|
||||||
|
# [ "$tar" ] && tar --extract --to-stdout \
|
||||||
|
# --file "${FILE_PATH}" -- "$fn" > "${IMAGE_CACHE_PATH}" && exit 6
|
||||||
|
# fe=$(echo -n "$fn" | sed 's/[][*?\]/\\\0/g')
|
||||||
|
# [ "$bsd" ] && bsdtar --extract --to-stdout \
|
||||||
|
# --file "${FILE_PATH}" -- "$fe" > "${IMAGE_CACHE_PATH}" && exit 6
|
||||||
|
# [ "$bsd" ] || [ "$tar" ] && rm -- "${IMAGE_CACHE_PATH}"
|
||||||
|
# [ "$rar" ] && unrar p -p- -inul -- "${FILE_PATH}" "$fn" > \
|
||||||
|
# "${IMAGE_CACHE_PATH}" && exit 6
|
||||||
|
# [ "$zip" ] && unzip -pP "" -- "${FILE_PATH}" "$fe" > \
|
||||||
|
# "${IMAGE_CACHE_PATH}" && exit 6
|
||||||
|
# [ "$rar" ] || [ "$zip" ] && rm -- "${IMAGE_CACHE_PATH}"
|
||||||
|
# ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# openscad_image() {
|
||||||
|
# TMPPNG="$(mktemp -t XXXXXX.png)"
|
||||||
|
# openscad --colorscheme="${OPENSCAD_COLORSCHEME}" \
|
||||||
|
# --imgsize="${OPENSCAD_IMGSIZE/x/,}" \
|
||||||
|
# -o "${TMPPNG}" "${1}"
|
||||||
|
# mv "${TMPPNG}" "${IMAGE_CACHE_PATH}"
|
||||||
|
# }
|
||||||
|
|
||||||
|
# case "${FILE_EXTENSION_LOWER}" in
|
||||||
|
# ## 3D models
|
||||||
|
# ## OpenSCAD only supports png image output, and ${IMAGE_CACHE_PATH}
|
||||||
|
# ## is hardcoded as jpeg. So we make a tempfile.png and just
|
||||||
|
# ## move/rename it to jpg. This works because image libraries are
|
||||||
|
# ## smart enough to handle it.
|
||||||
|
# csg|scad)
|
||||||
|
# openscad_image "${FILE_PATH}" && exit 6
|
||||||
|
# ;;
|
||||||
|
# 3mf|amf|dxf|off|stl)
|
||||||
|
# openscad_image <(echo "import(\"${FILE_PATH}\");") && exit 6
|
||||||
|
# ;;
|
||||||
|
# esac
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_mime() {
|
||||||
|
local mimetype="${1}"
|
||||||
|
case "${mimetype}" in
|
||||||
|
## RTF and DOC
|
||||||
|
text/rtf|*msword)
|
||||||
|
## Preview as text conversion
|
||||||
|
## note: catdoc does not always work for .doc files
|
||||||
|
## catdoc: http://www.wagner.pp.ru/~vitus/software/catdoc/
|
||||||
|
catdoc -- "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## DOCX, ePub, FB2 (using markdown)
|
||||||
|
## You might want to remove "|epub" and/or "|fb2" below if you have
|
||||||
|
## uncommented other methods to preview those formats
|
||||||
|
*wordprocessingml.document|*/epub+zip|*/x-fictionbook+xml)
|
||||||
|
## Preview as markdown conversion
|
||||||
|
pandoc -s -t markdown -- "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## XLS
|
||||||
|
*ms-excel)
|
||||||
|
## Preview as csv conversion
|
||||||
|
## xls2csv comes with catdoc:
|
||||||
|
## http://www.wagner.pp.ru/~vitus/software/catdoc/
|
||||||
|
xls2csv -- "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## Text
|
||||||
|
text/* | */xml)
|
||||||
|
## Syntax highlight
|
||||||
|
if [[ "$( stat --printf='%s' -- "${FILE_PATH}" )" -gt "${HIGHLIGHT_SIZE_MAX}" ]]; then
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if [[ "$( tput colors )" -ge 256 ]]; then
|
||||||
|
local pygmentize_format='terminal256'
|
||||||
|
local highlight_format='xterm256'
|
||||||
|
else
|
||||||
|
local pygmentize_format='terminal'
|
||||||
|
local highlight_format='ansi'
|
||||||
|
fi
|
||||||
|
env HIGHLIGHT_OPTIONS="${HIGHLIGHT_OPTIONS}" highlight \
|
||||||
|
--out-format="${highlight_format}" \
|
||||||
|
--force -- "${FILE_PATH}" && exit 5
|
||||||
|
env COLORTERM=8bit bat --color=always --style="plain" \
|
||||||
|
-- "${FILE_PATH}" && exit 5
|
||||||
|
pygmentize -f "${pygmentize_format}" -O "style=${PYGMENTIZE_STYLE}"\
|
||||||
|
-- "${FILE_PATH}" && exit 5
|
||||||
|
exit 2;;
|
||||||
|
|
||||||
|
## DjVu
|
||||||
|
image/vnd.djvu)
|
||||||
|
## Preview as text conversion (requires djvulibre)
|
||||||
|
djvutxt "${FILE_PATH}" | fmt -w "${PV_WIDTH}" && exit 5
|
||||||
|
exiftool "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## Image
|
||||||
|
image/*)
|
||||||
|
## Preview as text conversion
|
||||||
|
# img2txt --gamma=0.6 --width="${PV_WIDTH}" -- "${FILE_PATH}" && exit 4
|
||||||
|
exiftool "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
|
||||||
|
## Video and audio
|
||||||
|
video/* | audio/*)
|
||||||
|
mediainfo "${FILE_PATH}" && exit 5
|
||||||
|
exiftool "${FILE_PATH}" && exit 5
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_fallback() {
|
||||||
|
echo '----- File Type Classification -----' && file --dereference --brief -- "${FILE_PATH}" && exit 5
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MIMETYPE="$( file --dereference --brief --mime-type -- "${FILE_PATH}" )"
|
||||||
|
if [[ "${PV_IMAGE_ENABLED}" == 'True' ]]; then
|
||||||
|
handle_image "${MIMETYPE}"
|
||||||
|
fi
|
||||||
|
handle_extension
|
||||||
|
handle_mime "${MIMETYPE}"
|
||||||
|
handle_fallback
|
||||||
|
|
||||||
|
exit 1
|
14
user/.config/suckless/dependencies.md
Normal file
14
user/.config/suckless/dependencies.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# dwl:
|
||||||
|
libinput, wayland, wlroots, xkbcommon, wayland-protocols, pkg-config, libxcb, libxcb-wm, xwayland
|
||||||
|
|
||||||
|
# dwl-bar:
|
||||||
|
pango, cairo, wayland, wayland-protocols
|
||||||
|
|
||||||
|
# environment:
|
||||||
|
power-profiles-daemon, pipewire, pamixer, brightnessct, playerctl, wofi, wbg, dunst, xdg-desktop-portal-wlr, wezterm, wdisplays, gsettings-desktop-schemas, wl-clipboard, cliphist, grim, slurp
|
||||||
|
|
||||||
|
# other:
|
||||||
|
imv, ranger, cmus, btop, htop, pulsemixer
|
||||||
|
|
||||||
|
# external
|
||||||
|
ani-cli, ytfzf, flix-cli, neovide
|
|
@ -1,64 +0,0 @@
|
||||||
# dmenu - dynamic menu
|
|
||||||
# See LICENSE file for copyright and license details.
|
|
||||||
|
|
||||||
include config.mk
|
|
||||||
|
|
||||||
SRC = drw.c dmenu.c stest.c util.c
|
|
||||||
OBJ = $(SRC:.c=.o)
|
|
||||||
|
|
||||||
all: options dmenu stest
|
|
||||||
|
|
||||||
options:
|
|
||||||
@echo dmenu build options:
|
|
||||||
@echo "CFLAGS = $(CFLAGS)"
|
|
||||||
@echo "LDFLAGS = $(LDFLAGS)"
|
|
||||||
@echo "CC = $(CC)"
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(CC) -c $(CFLAGS) $<
|
|
||||||
|
|
||||||
config.h:
|
|
||||||
cp config.def.h $@
|
|
||||||
|
|
||||||
$(OBJ): arg.h config.h config.mk drw.h
|
|
||||||
|
|
||||||
dmenu: dmenu.o drw.o util.o
|
|
||||||
$(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS)
|
|
||||||
|
|
||||||
stest: stest.o
|
|
||||||
$(CC) -o $@ stest.o $(LDFLAGS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f dmenu stest $(OBJ) dmenu-$(VERSION).tar.gz
|
|
||||||
|
|
||||||
dist: clean
|
|
||||||
mkdir -p dmenu-$(VERSION)
|
|
||||||
cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1\
|
|
||||||
drw.h util.h dmenu_path dmenu_run stest.1 $(SRC)\
|
|
||||||
dmenu-$(VERSION)
|
|
||||||
tar -cf dmenu-$(VERSION).tar dmenu-$(VERSION)
|
|
||||||
gzip dmenu-$(VERSION).tar
|
|
||||||
rm -rf dmenu-$(VERSION)
|
|
||||||
|
|
||||||
install: all
|
|
||||||
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
|
||||||
cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin
|
|
||||||
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu
|
|
||||||
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path
|
|
||||||
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run
|
|
||||||
chmod 755 $(DESTDIR)$(PREFIX)/bin/stest
|
|
||||||
mkdir -p $(DESTDIR)$(MANPREFIX)/man1
|
|
||||||
sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1
|
|
||||||
sed "s/VERSION/$(VERSION)/g" < stest.1 > $(DESTDIR)$(MANPREFIX)/man1/stest.1
|
|
||||||
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/dmenu.1
|
|
||||||
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stest.1
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\
|
|
||||||
$(DESTDIR)$(PREFIX)/bin/dmenu_path\
|
|
||||||
$(DESTDIR)$(PREFIX)/bin/dmenu_run\
|
|
||||||
$(DESTDIR)$(PREFIX)/bin/stest\
|
|
||||||
$(DESTDIR)$(MANPREFIX)/man1/dmenu.1\
|
|
||||||
$(DESTDIR)$(MANPREFIX)/man1/stest.1
|
|
||||||
|
|
||||||
.PHONY: all options clean dist install uninstall
|
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* Copy me if you can.
|
|
||||||
* by 20h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ARG_H__
|
|
||||||
#define ARG_H__
|
|
||||||
|
|
||||||
extern char *argv0;
|
|
||||||
|
|
||||||
/* use main(int argc, char *argv[]) */
|
|
||||||
#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
|
|
||||||
argv[0] && argv[0][0] == '-'\
|
|
||||||
&& argv[0][1];\
|
|
||||||
argc--, argv++) {\
|
|
||||||
char argc_;\
|
|
||||||
char **argv_;\
|
|
||||||
int brk_;\
|
|
||||||
if (argv[0][1] == '-' && argv[0][2] == '\0') {\
|
|
||||||
argv++;\
|
|
||||||
argc--;\
|
|
||||||
break;\
|
|
||||||
}\
|
|
||||||
for (brk_ = 0, argv[0]++, argv_ = argv;\
|
|
||||||
argv[0][0] && !brk_;\
|
|
||||||
argv[0]++) {\
|
|
||||||
if (argv_ != argv)\
|
|
||||||
break;\
|
|
||||||
argc_ = argv[0][0];\
|
|
||||||
switch (argc_)
|
|
||||||
|
|
||||||
#define ARGEND }\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ARGC() argc_
|
|
||||||
|
|
||||||
#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
|
|
||||||
((x), abort(), (char *)0) :\
|
|
||||||
(brk_ = 1, (argv[0][1] != '\0')?\
|
|
||||||
(&argv[0][1]) :\
|
|
||||||
(argc--, argv++, argv[0])))
|
|
||||||
|
|
||||||
#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
|
|
||||||
(char *)0 :\
|
|
||||||
(brk_ = 1, (argv[0][1] != '\0')?\
|
|
||||||
(&argv[0][1]) :\
|
|
||||||
(argc--, argv++, argv[0])))
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,25 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
/* Default settings; can be overriden by command line. */
|
|
||||||
|
|
||||||
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
|
|
||||||
static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */
|
|
||||||
/* -fn option overrides fonts[0]; default X11 font or font set */
|
|
||||||
static const char *fonts[] = {"Symbols Nerd Font Mono:size=10", "mononoki Nerd Font:size=12"};
|
|
||||||
static const char *prompt = NULL; /* -p option; prompt to the left of input field */
|
|
||||||
static const char *colors[SchemeLast][2] = {
|
|
||||||
/* fg bg */
|
|
||||||
[SchemeNorm] = { "#ebdbb2", "#1d2021" },
|
|
||||||
[SchemeSel] = { "#ebdbb2", "#cc241d" },
|
|
||||||
[SchemeSelHighlight] = { "#fbf1c7", "#282828" },
|
|
||||||
[SchemeNormHighlight] = { "#fbf1c7", "#282828" },
|
|
||||||
[SchemeOut] = { "#ebdbb2", "#8ec07c" },
|
|
||||||
[SchemeOutHighlight] = { "#fabd2f", "#83a598" },
|
|
||||||
};
|
|
||||||
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
|
|
||||||
static unsigned int lines = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Characters not considered part of a word while deleting words
|
|
||||||
* for example: " /?\"&[]"
|
|
||||||
*/
|
|
||||||
static const char worddelimiters[] = " ";
|
|
|
@ -1,32 +0,0 @@
|
||||||
# dmenu version
|
|
||||||
VERSION = 5.2
|
|
||||||
|
|
||||||
# paths
|
|
||||||
PREFIX = /usr/local
|
|
||||||
MANPREFIX = $(PREFIX)/share/man
|
|
||||||
|
|
||||||
X11INC = /usr/X11R6/include
|
|
||||||
X11LIB = /usr/X11R6/lib
|
|
||||||
|
|
||||||
# Xinerama, comment if you don't want it
|
|
||||||
XINERAMALIBS = -lXinerama
|
|
||||||
XINERAMAFLAGS = -DXINERAMA
|
|
||||||
|
|
||||||
# freetype
|
|
||||||
FREETYPELIBS = -lfontconfig -lXft
|
|
||||||
FREETYPEINC = /usr/include/freetype2
|
|
||||||
# OpenBSD (uncomment)
|
|
||||||
#FREETYPEINC = $(X11INC)/freetype2
|
|
||||||
#MANPREFIX = ${PREFIX}/man
|
|
||||||
|
|
||||||
# includes and libs
|
|
||||||
INCS = -I$(X11INC) -I$(FREETYPEINC)
|
|
||||||
LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm
|
|
||||||
|
|
||||||
# flags
|
|
||||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
|
|
||||||
CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS)
|
|
||||||
LDFLAGS = $(LIBS)
|
|
||||||
|
|
||||||
# compiler and linker
|
|
||||||
CC = cc
|
|
|
@ -1,197 +0,0 @@
|
||||||
.TH DMENU 1 dmenu\-VERSION
|
|
||||||
.SH NAME
|
|
||||||
dmenu \- dynamic menu
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B dmenu
|
|
||||||
.RB [ \-bfivP ]
|
|
||||||
.RB [ \-l
|
|
||||||
.IR lines ]
|
|
||||||
.RB [ \-m
|
|
||||||
.IR monitor ]
|
|
||||||
.RB [ \-p
|
|
||||||
.IR prompt ]
|
|
||||||
.RB [ \-fn
|
|
||||||
.IR font ]
|
|
||||||
.RB [ \-nb
|
|
||||||
.IR color ]
|
|
||||||
.RB [ \-nf
|
|
||||||
.IR color ]
|
|
||||||
.RB [ \-sb
|
|
||||||
.IR color ]
|
|
||||||
.RB [ \-sf
|
|
||||||
.IR color ]
|
|
||||||
.RB [ \-w
|
|
||||||
.IR windowid ]
|
|
||||||
.P
|
|
||||||
.BR dmenu_run " ..."
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.B dmenu
|
|
||||||
is a dynamic menu for X, which reads a list of newline\-separated items from
|
|
||||||
stdin. When the user selects an item and presses Return, their choice is printed
|
|
||||||
to stdout and dmenu terminates. Entering text will narrow the items to those
|
|
||||||
matching the tokens in the input.
|
|
||||||
.P
|
|
||||||
.B dmenu_run
|
|
||||||
is a script used by
|
|
||||||
.IR dwm (1)
|
|
||||||
which lists programs in the user's $PATH and runs the result in their $SHELL.
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.B \-b
|
|
||||||
dmenu appears at the bottom of the screen.
|
|
||||||
.TP
|
|
||||||
.B \-f
|
|
||||||
dmenu grabs the keyboard before reading stdin if not reading from a tty. This
|
|
||||||
is faster, but will lock up X until stdin reaches end\-of\-file.
|
|
||||||
.TP
|
|
||||||
.B \-i
|
|
||||||
dmenu matches menu items case insensitively.
|
|
||||||
.TP
|
|
||||||
.B \-P
|
|
||||||
dmenu will not directly display the keyboard input, but instead replace it with dots. All data from stdin will be ignored.
|
|
||||||
.TP
|
|
||||||
.BI \-l " lines"
|
|
||||||
dmenu lists items vertically, with the given number of lines.
|
|
||||||
.TP
|
|
||||||
.BI \-m " monitor"
|
|
||||||
dmenu is displayed on the monitor number supplied. Monitor numbers are starting
|
|
||||||
from 0.
|
|
||||||
.TP
|
|
||||||
.BI \-p " prompt"
|
|
||||||
defines the prompt to be displayed to the left of the input field.
|
|
||||||
.TP
|
|
||||||
.BI \-fn " font"
|
|
||||||
defines the font or font set used.
|
|
||||||
.TP
|
|
||||||
.BI \-nb " color"
|
|
||||||
defines the normal background color.
|
|
||||||
.IR #RGB ,
|
|
||||||
.IR #RRGGBB ,
|
|
||||||
and X color names are supported.
|
|
||||||
.TP
|
|
||||||
.BI \-nf " color"
|
|
||||||
defines the normal foreground color.
|
|
||||||
.TP
|
|
||||||
.BI \-sb " color"
|
|
||||||
defines the selected background color.
|
|
||||||
.TP
|
|
||||||
.BI \-sf " color"
|
|
||||||
defines the selected foreground color.
|
|
||||||
.TP
|
|
||||||
.B \-v
|
|
||||||
prints version information to stdout, then exits.
|
|
||||||
.TP
|
|
||||||
.BI \-w " windowid"
|
|
||||||
embed into windowid.
|
|
||||||
.SH USAGE
|
|
||||||
dmenu is completely controlled by the keyboard. Items are selected using the
|
|
||||||
arrow keys, page up, page down, home, and end.
|
|
||||||
.TP
|
|
||||||
.B Tab
|
|
||||||
Copy the selected item to the input field.
|
|
||||||
.TP
|
|
||||||
.B Return
|
|
||||||
Confirm selection. Prints the selected item to stdout and exits, returning
|
|
||||||
success.
|
|
||||||
.TP
|
|
||||||
.B Ctrl-Return
|
|
||||||
Confirm selection. Prints the selected item to stdout and continues.
|
|
||||||
.TP
|
|
||||||
.B Shift\-Return
|
|
||||||
Confirm input. Prints the input text to stdout and exits, returning success.
|
|
||||||
.TP
|
|
||||||
.B Escape
|
|
||||||
Exit without selecting an item, returning failure.
|
|
||||||
.TP
|
|
||||||
.B Ctrl-Left
|
|
||||||
Move cursor to the start of the current word
|
|
||||||
.TP
|
|
||||||
.B Ctrl-Right
|
|
||||||
Move cursor to the end of the current word
|
|
||||||
.TP
|
|
||||||
.B C\-a
|
|
||||||
Home
|
|
||||||
.TP
|
|
||||||
.B C\-b
|
|
||||||
Left
|
|
||||||
.TP
|
|
||||||
.B C\-c
|
|
||||||
Escape
|
|
||||||
.TP
|
|
||||||
.B C\-d
|
|
||||||
Delete
|
|
||||||
.TP
|
|
||||||
.B C\-e
|
|
||||||
End
|
|
||||||
.TP
|
|
||||||
.B C\-f
|
|
||||||
Right
|
|
||||||
.TP
|
|
||||||
.B C\-g
|
|
||||||
Escape
|
|
||||||
.TP
|
|
||||||
.B C\-h
|
|
||||||
Backspace
|
|
||||||
.TP
|
|
||||||
.B C\-i
|
|
||||||
Tab
|
|
||||||
.TP
|
|
||||||
.B C\-j
|
|
||||||
Return
|
|
||||||
.TP
|
|
||||||
.B C\-J
|
|
||||||
Shift-Return
|
|
||||||
.TP
|
|
||||||
.B C\-k
|
|
||||||
Delete line right
|
|
||||||
.TP
|
|
||||||
.B C\-m
|
|
||||||
Return
|
|
||||||
.TP
|
|
||||||
.B C\-M
|
|
||||||
Shift-Return
|
|
||||||
.TP
|
|
||||||
.B C\-n
|
|
||||||
Down
|
|
||||||
.TP
|
|
||||||
.B C\-p
|
|
||||||
Up
|
|
||||||
.TP
|
|
||||||
.B C\-u
|
|
||||||
Delete line left
|
|
||||||
.TP
|
|
||||||
.B C\-w
|
|
||||||
Delete word left
|
|
||||||
.TP
|
|
||||||
.B C\-y
|
|
||||||
Paste from primary X selection
|
|
||||||
.TP
|
|
||||||
.B C\-Y
|
|
||||||
Paste from X clipboard
|
|
||||||
.TP
|
|
||||||
.B M\-b
|
|
||||||
Move cursor to the start of the current word
|
|
||||||
.TP
|
|
||||||
.B M\-f
|
|
||||||
Move cursor to the end of the current word
|
|
||||||
.TP
|
|
||||||
.B M\-g
|
|
||||||
Home
|
|
||||||
.TP
|
|
||||||
.B M\-G
|
|
||||||
End
|
|
||||||
.TP
|
|
||||||
.B M\-h
|
|
||||||
Up
|
|
||||||
.TP
|
|
||||||
.B M\-j
|
|
||||||
Page down
|
|
||||||
.TP
|
|
||||||
.B M\-k
|
|
||||||
Page up
|
|
||||||
.TP
|
|
||||||
.B M\-l
|
|
||||||
Down
|
|
||||||
.SH SEE ALSO
|
|
||||||
.IR dwm (1),
|
|
||||||
.IR stest (1)
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,13 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}"
|
|
||||||
cache="$cachedir/dmenu_run"
|
|
||||||
|
|
||||||
[ ! -e "$cachedir" ] && mkdir -p "$cachedir"
|
|
||||||
|
|
||||||
IFS=:
|
|
||||||
if stest -dqr -n "$cache" $PATH; then
|
|
||||||
stest -flx $PATH | sort -u | tee "$cache"
|
|
||||||
else
|
|
||||||
cat "$cache"
|
|
||||||
fi
|
|
|
@ -1,2 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} &
|
|
|
@ -1,450 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/Xft/Xft.h>
|
|
||||||
|
|
||||||
#include "drw.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#define UTF_INVALID 0xFFFD
|
|
||||||
#define UTF_SIZ 4
|
|
||||||
|
|
||||||
static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
|
|
||||||
static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
|
|
||||||
static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000};
|
|
||||||
static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
|
|
||||||
|
|
||||||
static long
|
|
||||||
utf8decodebyte(const char c, size_t *i)
|
|
||||||
{
|
|
||||||
for (*i = 0; *i < (UTF_SIZ + 1); ++(*i))
|
|
||||||
if (((unsigned char)c & utfmask[*i]) == utfbyte[*i])
|
|
||||||
return (unsigned char)c & ~utfmask[*i];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t
|
|
||||||
utf8validate(long *u, size_t i)
|
|
||||||
{
|
|
||||||
if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF))
|
|
||||||
*u = UTF_INVALID;
|
|
||||||
for (i = 1; *u > utfmax[i]; ++i)
|
|
||||||
;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t
|
|
||||||
utf8decode(const char *c, long *u, size_t clen)
|
|
||||||
{
|
|
||||||
size_t i, j, len, type;
|
|
||||||
long udecoded;
|
|
||||||
|
|
||||||
*u = UTF_INVALID;
|
|
||||||
if (!clen)
|
|
||||||
return 0;
|
|
||||||
udecoded = utf8decodebyte(c[0], &len);
|
|
||||||
if (!BETWEEN(len, 1, UTF_SIZ))
|
|
||||||
return 1;
|
|
||||||
for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
|
|
||||||
udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type);
|
|
||||||
if (type)
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
if (j < len)
|
|
||||||
return 0;
|
|
||||||
*u = udecoded;
|
|
||||||
utf8validate(u, len);
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
Drw *
|
|
||||||
drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
|
|
||||||
{
|
|
||||||
Drw *drw = ecalloc(1, sizeof(Drw));
|
|
||||||
|
|
||||||
drw->dpy = dpy;
|
|
||||||
drw->screen = screen;
|
|
||||||
drw->root = root;
|
|
||||||
drw->w = w;
|
|
||||||
drw->h = h;
|
|
||||||
drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
|
|
||||||
drw->gc = XCreateGC(dpy, root, 0, NULL);
|
|
||||||
XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
|
|
||||||
|
|
||||||
return drw;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
drw_resize(Drw *drw, unsigned int w, unsigned int h)
|
|
||||||
{
|
|
||||||
if (!drw)
|
|
||||||
return;
|
|
||||||
|
|
||||||
drw->w = w;
|
|
||||||
drw->h = h;
|
|
||||||
if (drw->drawable)
|
|
||||||
XFreePixmap(drw->dpy, drw->drawable);
|
|
||||||
drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
drw_free(Drw *drw)
|
|
||||||
{
|
|
||||||
XFreePixmap(drw->dpy, drw->drawable);
|
|
||||||
XFreeGC(drw->dpy, drw->gc);
|
|
||||||
drw_fontset_free(drw->fonts);
|
|
||||||
free(drw);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function is an implementation detail. Library users should use
|
|
||||||
* drw_fontset_create instead.
|
|
||||||
*/
|
|
||||||
static Fnt *
|
|
||||||
xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
|
|
||||||
{
|
|
||||||
Fnt *font;
|
|
||||||
XftFont *xfont = NULL;
|
|
||||||
FcPattern *pattern = NULL;
|
|
||||||
|
|
||||||
if (fontname) {
|
|
||||||
/* Using the pattern found at font->xfont->pattern does not yield the
|
|
||||||
* same substitution results as using the pattern returned by
|
|
||||||
* FcNameParse; using the latter results in the desired fallback
|
|
||||||
* behaviour whereas the former just results in missing-character
|
|
||||||
* rectangles being drawn, at least with some fonts. */
|
|
||||||
if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
|
|
||||||
fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
|
|
||||||
fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
|
|
||||||
XftFontClose(drw->dpy, xfont);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else if (fontpattern) {
|
|
||||||
if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
|
|
||||||
fprintf(stderr, "error, cannot load font from pattern.\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
die("no font specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
font = ecalloc(1, sizeof(Fnt));
|
|
||||||
font->xfont = xfont;
|
|
||||||
font->pattern = pattern;
|
|
||||||
font->h = xfont->ascent + xfont->descent;
|
|
||||||
font->dpy = drw->dpy;
|
|
||||||
|
|
||||||
return font;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
xfont_free(Fnt *font)
|
|
||||||
{
|
|
||||||
if (!font)
|
|
||||||
return;
|
|
||||||
if (font->pattern)
|
|
||||||
FcPatternDestroy(font->pattern);
|
|
||||||
XftFontClose(font->dpy, font->xfont);
|
|
||||||
free(font);
|
|
||||||
}
|
|
||||||
|
|
||||||
Fnt*
|
|
||||||
drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
|
|
||||||
{
|
|
||||||
Fnt *cur, *ret = NULL;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (!drw || !fonts)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 1; i <= fontcount; i++) {
|
|
||||||
if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
|
|
||||||
cur->next = ret;
|
|
||||||
ret = cur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (drw->fonts = ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
drw_fontset_free(Fnt *font)
|
|
||||||
{
|
|
||||||
if (font) {
|
|
||||||
drw_fontset_free(font->next);
|
|
||||||
xfont_free(font);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
|
|
||||||
{
|
|
||||||
if (!drw || !dest || !clrname)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
|
|
||||||
DefaultColormap(drw->dpy, drw->screen),
|
|
||||||
clrname, dest))
|
|
||||||
die("error, cannot allocate color '%s'", clrname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wrapper to create color schemes. The caller has to call free(3) on the
|
|
||||||
* returned color scheme when done using it. */
|
|
||||||
Clr *
|
|
||||||
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
Clr *ret;
|
|
||||||
|
|
||||||
/* need at least two colors for a scheme */
|
|
||||||
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for (i = 0; i < clrcount; i++)
|
|
||||||
drw_clr_create(drw, &ret[i], clrnames[i]);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
drw_setfontset(Drw *drw, Fnt *set)
|
|
||||||
{
|
|
||||||
if (drw)
|
|
||||||
drw->fonts = set;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
drw_setscheme(Drw *drw, Clr *scm)
|
|
||||||
{
|
|
||||||
if (drw)
|
|
||||||
drw->scheme = scm;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert)
|
|
||||||
{
|
|
||||||
if (!drw || !drw->scheme)
|
|
||||||
return;
|
|
||||||
XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
|
|
||||||
if (filled)
|
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
|
||||||
else
|
|
||||||
XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
|
|
||||||
{
|
|
||||||
int i, ty, ellipsis_x = 0;
|
|
||||||
unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len;
|
|
||||||
XftDraw *d = NULL;
|
|
||||||
Fnt *usedfont, *curfont, *nextfont;
|
|
||||||
int utf8strlen, utf8charlen, render = x || y || w || h;
|
|
||||||
long utf8codepoint = 0;
|
|
||||||
const char *utf8str;
|
|
||||||
FcCharSet *fccharset;
|
|
||||||
FcPattern *fcpattern;
|
|
||||||
FcPattern *match;
|
|
||||||
XftResult result;
|
|
||||||
int charexists = 0, overflow = 0;
|
|
||||||
/* keep track of a couple codepoints for which we have no match. */
|
|
||||||
enum { nomatches_len = 64 };
|
|
||||||
static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
|
|
||||||
static unsigned int ellipsis_width = 0;
|
|
||||||
|
|
||||||
if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!render) {
|
|
||||||
w = invert ? invert : ~invert;
|
|
||||||
} else {
|
|
||||||
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
|
|
||||||
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
|
|
||||||
d = XftDrawCreate(drw->dpy, drw->drawable,
|
|
||||||
DefaultVisual(drw->dpy, drw->screen),
|
|
||||||
DefaultColormap(drw->dpy, drw->screen));
|
|
||||||
x += lpad;
|
|
||||||
w -= lpad;
|
|
||||||
}
|
|
||||||
|
|
||||||
usedfont = drw->fonts;
|
|
||||||
if (!ellipsis_width && render)
|
|
||||||
ellipsis_width = drw_fontset_getwidth(drw, "...");
|
|
||||||
while (1) {
|
|
||||||
ew = ellipsis_len = utf8strlen = 0;
|
|
||||||
utf8str = text;
|
|
||||||
nextfont = NULL;
|
|
||||||
while (*text) {
|
|
||||||
utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
|
|
||||||
for (curfont = drw->fonts; curfont; curfont = curfont->next) {
|
|
||||||
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
|
|
||||||
if (charexists) {
|
|
||||||
drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
|
|
||||||
if (ew + ellipsis_width <= w) {
|
|
||||||
/* keep track where the ellipsis still fits */
|
|
||||||
ellipsis_x = x + ew;
|
|
||||||
ellipsis_w = w - ew;
|
|
||||||
ellipsis_len = utf8strlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ew + tmpw > w) {
|
|
||||||
overflow = 1;
|
|
||||||
/* called from drw_fontset_getwidth_clamp():
|
|
||||||
* it wants the width AFTER the overflow
|
|
||||||
*/
|
|
||||||
if (!render)
|
|
||||||
x += tmpw;
|
|
||||||
else
|
|
||||||
utf8strlen = ellipsis_len;
|
|
||||||
} else if (curfont == usedfont) {
|
|
||||||
utf8strlen += utf8charlen;
|
|
||||||
text += utf8charlen;
|
|
||||||
ew += tmpw;
|
|
||||||
} else {
|
|
||||||
nextfont = curfont;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overflow || !charexists || nextfont)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
charexists = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (utf8strlen) {
|
|
||||||
if (render) {
|
|
||||||
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
|
|
||||||
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
|
|
||||||
usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
|
|
||||||
}
|
|
||||||
x += ew;
|
|
||||||
w -= ew;
|
|
||||||
}
|
|
||||||
if (render && overflow)
|
|
||||||
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
|
|
||||||
|
|
||||||
if (!*text || overflow) {
|
|
||||||
break;
|
|
||||||
} else if (nextfont) {
|
|
||||||
charexists = 0;
|
|
||||||
usedfont = nextfont;
|
|
||||||
} else {
|
|
||||||
/* Regardless of whether or not a fallback font is found, the
|
|
||||||
* character must be drawn. */
|
|
||||||
charexists = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < nomatches_len; ++i) {
|
|
||||||
/* avoid calling XftFontMatch if we know we won't find a match */
|
|
||||||
if (utf8codepoint == nomatches.codepoint[i])
|
|
||||||
goto no_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
fccharset = FcCharSetCreate();
|
|
||||||
FcCharSetAddChar(fccharset, utf8codepoint);
|
|
||||||
|
|
||||||
if (!drw->fonts->pattern) {
|
|
||||||
/* Refer to the comment in xfont_create for more information. */
|
|
||||||
die("the first font in the cache must be loaded from a font string.");
|
|
||||||
}
|
|
||||||
|
|
||||||
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
|
|
||||||
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
|
|
||||||
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
|
|
||||||
|
|
||||||
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
|
|
||||||
FcDefaultSubstitute(fcpattern);
|
|
||||||
match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
|
|
||||||
|
|
||||||
FcCharSetDestroy(fccharset);
|
|
||||||
FcPatternDestroy(fcpattern);
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
usedfont = xfont_create(drw, NULL, match);
|
|
||||||
if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
|
|
||||||
for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
|
|
||||||
; /* NOP */
|
|
||||||
curfont->next = usedfont;
|
|
||||||
} else {
|
|
||||||
xfont_free(usedfont);
|
|
||||||
nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
|
|
||||||
no_match:
|
|
||||||
usedfont = drw->fonts;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (d)
|
|
||||||
XftDrawDestroy(d);
|
|
||||||
|
|
||||||
return x + (render ? w : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
|
|
||||||
{
|
|
||||||
if (!drw)
|
|
||||||
return;
|
|
||||||
|
|
||||||
XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
|
|
||||||
XSync(drw->dpy, False);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
drw_fontset_getwidth(Drw *drw, const char *text)
|
|
||||||
{
|
|
||||||
if (!drw || !drw->fonts || !text)
|
|
||||||
return 0;
|
|
||||||
return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
|
|
||||||
{
|
|
||||||
unsigned int tmp = 0;
|
|
||||||
if (drw && drw->fonts && text && n)
|
|
||||||
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
|
|
||||||
return MIN(n, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
|
|
||||||
{
|
|
||||||
XGlyphInfo ext;
|
|
||||||
|
|
||||||
if (!font || !text)
|
|
||||||
return;
|
|
||||||
|
|
||||||
XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
|
|
||||||
if (w)
|
|
||||||
*w = ext.xOff;
|
|
||||||
if (h)
|
|
||||||
*h = font->h;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cur *
|
|
||||||
drw_cur_create(Drw *drw, int shape)
|
|
||||||
{
|
|
||||||
Cur *cur;
|
|
||||||
|
|
||||||
if (!drw || !(cur = ecalloc(1, sizeof(Cur))))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
cur->cursor = XCreateFontCursor(drw->dpy, shape);
|
|
||||||
|
|
||||||
return cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
drw_cur_free(Drw *drw, Cur *cursor)
|
|
||||||
{
|
|
||||||
if (!cursor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
XFreeCursor(drw->dpy, cursor->cursor);
|
|
||||||
free(cursor);
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Cursor cursor;
|
|
||||||
} Cur;
|
|
||||||
|
|
||||||
typedef struct Fnt {
|
|
||||||
Display *dpy;
|
|
||||||
unsigned int h;
|
|
||||||
XftFont *xfont;
|
|
||||||
FcPattern *pattern;
|
|
||||||
struct Fnt *next;
|
|
||||||
} Fnt;
|
|
||||||
|
|
||||||
enum { ColFg, ColBg }; /* Clr scheme index */
|
|
||||||
typedef XftColor Clr;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned int w, h;
|
|
||||||
Display *dpy;
|
|
||||||
int screen;
|
|
||||||
Window root;
|
|
||||||
Drawable drawable;
|
|
||||||
GC gc;
|
|
||||||
Clr *scheme;
|
|
||||||
Fnt *fonts;
|
|
||||||
} Drw;
|
|
||||||
|
|
||||||
/* Drawable abstraction */
|
|
||||||
Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
|
|
||||||
void drw_resize(Drw *drw, unsigned int w, unsigned int h);
|
|
||||||
void drw_free(Drw *drw);
|
|
||||||
|
|
||||||
/* Fnt abstraction */
|
|
||||||
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
|
|
||||||
void drw_fontset_free(Fnt* set);
|
|
||||||
unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
|
|
||||||
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
|
|
||||||
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
|
|
||||||
|
|
||||||
/* Colorscheme abstraction */
|
|
||||||
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
|
|
||||||
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
|
|
||||||
|
|
||||||
/* Cursor abstraction */
|
|
||||||
Cur *drw_cur_create(Drw *drw, int shape);
|
|
||||||
void drw_cur_free(Drw *drw, Cur *cursor);
|
|
||||||
|
|
||||||
/* Drawing context manipulation */
|
|
||||||
void drw_setfontset(Drw *drw, Fnt *set);
|
|
||||||
void drw_setscheme(Drw *drw, Clr *scm);
|
|
||||||
|
|
||||||
/* Drawing functions */
|
|
||||||
void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
|
|
||||||
int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
|
|
||||||
|
|
||||||
/* Map functions */
|
|
||||||
void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
|
|
|
@ -1,163 +0,0 @@
|
||||||
From 94353eb52055927d9079f3d9e33da1c954abf386 Mon Sep 17 00:00:00 2001
|
|
||||||
From: aleks <aleks.stier@icloud.com>
|
|
||||||
Date: Wed, 26 Jun 2019 13:25:10 +0200
|
|
||||||
Subject: [PATCH] Add support for fuzzy-matching
|
|
||||||
|
|
||||||
---
|
|
||||||
config.def.h | 1 +
|
|
||||||
config.mk | 2 +-
|
|
||||||
dmenu.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
3 files changed, 91 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 1edb647..51612b9 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -2,6 +2,7 @@
|
|
||||||
/* Default settings; can be overriden by command line. */
|
|
||||||
|
|
||||||
static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
|
|
||||||
+static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */
|
|
||||||
/* -fn option overrides fonts[0]; default X11 font or font set */
|
|
||||||
static const char *fonts[] = {
|
|
||||||
"monospace:size=10"
|
|
||||||
diff --git a/config.mk b/config.mk
|
|
||||||
index 0929b4a..d14309a 100644
|
|
||||||
--- a/config.mk
|
|
||||||
+++ b/config.mk
|
|
||||||
@@ -20,7 +20,7 @@ FREETYPEINC = /usr/include/freetype2
|
|
||||||
|
|
||||||
# includes and libs
|
|
||||||
INCS = -I$(X11INC) -I$(FREETYPEINC)
|
|
||||||
-LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
|
|
||||||
+LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm
|
|
||||||
|
|
||||||
# flags
|
|
||||||
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
|
|
||||||
diff --git a/dmenu.c b/dmenu.c
|
|
||||||
index 6b8f51b..96ddc98 100644
|
|
||||||
--- a/dmenu.c
|
|
||||||
+++ b/dmenu.c
|
|
||||||
@@ -1,6 +1,7 @@
|
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <locale.h>
|
|
||||||
+#include <math.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
@@ -32,6 +33,7 @@ struct item {
|
|
||||||
char *text;
|
|
||||||
struct item *left, *right;
|
|
||||||
int out;
|
|
||||||
+ double distance;
|
|
||||||
};
|
|
||||||
|
|
||||||
static char text[BUFSIZ] = "";
|
|
||||||
@@ -210,9 +212,94 @@ grabkeyboard(void)
|
|
||||||
die("cannot grab keyboard");
|
|
||||||
}
|
|
||||||
|
|
||||||
+int
|
|
||||||
+compare_distance(const void *a, const void *b)
|
|
||||||
+{
|
|
||||||
+ struct item *da = *(struct item **) a;
|
|
||||||
+ struct item *db = *(struct item **) b;
|
|
||||||
+
|
|
||||||
+ if (!db)
|
|
||||||
+ return 1;
|
|
||||||
+ if (!da)
|
|
||||||
+ return -1;
|
|
||||||
+
|
|
||||||
+ return da->distance == db->distance ? 0 : da->distance < db->distance ? -1 : 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void
|
|
||||||
+fuzzymatch(void)
|
|
||||||
+{
|
|
||||||
+ /* bang - we have so much memory */
|
|
||||||
+ struct item *it;
|
|
||||||
+ struct item **fuzzymatches = NULL;
|
|
||||||
+ char c;
|
|
||||||
+ int number_of_matches = 0, i, pidx, sidx, eidx;
|
|
||||||
+ int text_len = strlen(text), itext_len;
|
|
||||||
+
|
|
||||||
+ matches = matchend = NULL;
|
|
||||||
+
|
|
||||||
+ /* walk through all items */
|
|
||||||
+ for (it = items; it && it->text; it++) {
|
|
||||||
+ if (text_len) {
|
|
||||||
+ itext_len = strlen(it->text);
|
|
||||||
+ pidx = 0; /* pointer */
|
|
||||||
+ sidx = eidx = -1; /* start of match, end of match */
|
|
||||||
+ /* walk through item text */
|
|
||||||
+ for (i = 0; i < itext_len && (c = it->text[i]); i++) {
|
|
||||||
+ /* fuzzy match pattern */
|
|
||||||
+ if (!fstrncmp(&text[pidx], &c, 1)) {
|
|
||||||
+ if(sidx == -1)
|
|
||||||
+ sidx = i;
|
|
||||||
+ pidx++;
|
|
||||||
+ if (pidx == text_len) {
|
|
||||||
+ eidx = i;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ /* build list of matches */
|
|
||||||
+ if (eidx != -1) {
|
|
||||||
+ /* compute distance */
|
|
||||||
+ /* add penalty if match starts late (log(sidx+2))
|
|
||||||
+ * add penalty for long a match without many matching characters */
|
|
||||||
+ it->distance = log(sidx + 2) + (double)(eidx - sidx - text_len);
|
|
||||||
+ /* fprintf(stderr, "distance %s %f\n", it->text, it->distance); */
|
|
||||||
+ appenditem(it, &matches, &matchend);
|
|
||||||
+ number_of_matches++;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ appenditem(it, &matches, &matchend);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (number_of_matches) {
|
|
||||||
+ /* initialize array with matches */
|
|
||||||
+ if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*))))
|
|
||||||
+ die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item*));
|
|
||||||
+ for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) {
|
|
||||||
+ fuzzymatches[i] = it;
|
|
||||||
+ }
|
|
||||||
+ /* sort matches according to distance */
|
|
||||||
+ qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance);
|
|
||||||
+ /* rebuild list of matches */
|
|
||||||
+ matches = matchend = NULL;
|
|
||||||
+ for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \
|
|
||||||
+ it->text; i++, it = fuzzymatches[i]) {
|
|
||||||
+ appenditem(it, &matches, &matchend);
|
|
||||||
+ }
|
|
||||||
+ free(fuzzymatches);
|
|
||||||
+ }
|
|
||||||
+ curr = sel = matches;
|
|
||||||
+ calcoffsets();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void
|
|
||||||
match(void)
|
|
||||||
{
|
|
||||||
+ if (fuzzy) {
|
|
||||||
+ fuzzymatch();
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
static char **tokv = NULL;
|
|
||||||
static int tokn = 0;
|
|
||||||
|
|
||||||
@@ -702,6 +789,8 @@ main(int argc, char *argv[])
|
|
||||||
topbar = 0;
|
|
||||||
else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
|
|
||||||
fast = 1;
|
|
||||||
+ else if (!strcmp(argv[i], "-F")) /* grabs keyboard before reading stdin */
|
|
||||||
+ fuzzy = 0;
|
|
||||||
else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
|
|
||||||
fstrncmp = strncasecmp;
|
|
||||||
fstrstr = cistrstr;
|
|
||||||
--
|
|
||||||
2.22.0
|
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
From fcdc1593ed418166f20b7e691a49b1e6eefc116e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Nathaniel Evan <nathanielevan@zohomail.com>
|
|
||||||
Date: Fri, 11 Dec 2020 11:08:12 +0700
|
|
||||||
Subject: [PATCH] Highlight matched text in a different color scheme
|
|
||||||
|
|
||||||
---
|
|
||||||
config.def.h | 3 +++
|
|
||||||
dmenu.c | 44 +++++++++++++++++++++++++++++++++++++++++---
|
|
||||||
2 files changed, 44 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/config.def.h b/config.def.h
|
|
||||||
index 1edb647..79be73a 100644
|
|
||||||
--- a/config.def.h
|
|
||||||
+++ b/config.def.h
|
|
||||||
@@ -11,7 +11,10 @@ static const char *colors[SchemeLast][2] = {
|
|
||||||
/* fg bg */
|
|
||||||
[SchemeNorm] = { "#bbbbbb", "#222222" },
|
|
||||||
[SchemeSel] = { "#eeeeee", "#005577" },
|
|
||||||
+ [SchemeSelHighlight] = { "#ffc978", "#005577" },
|
|
||||||
+ [SchemeNormHighlight] = { "#ffc978", "#222222" },
|
|
||||||
[SchemeOut] = { "#000000", "#00ffff" },
|
|
||||||
+ [SchemeOutHighlight] = { "#ffc978", "#00ffff" },
|
|
||||||
};
|
|
||||||
/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
|
|
||||||
static unsigned int lines = 0;
|
|
||||||
diff --git a/dmenu.c b/dmenu.c
|
|
||||||
index 65f25ce..cce1ad1 100644
|
|
||||||
--- a/dmenu.c
|
|
||||||
+++ b/dmenu.c
|
|
||||||
@@ -26,8 +26,7 @@
|
|
||||||
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
|
|
||||||
|
|
||||||
/* enums */
|
|
||||||
-enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */
|
|
||||||
-
|
|
||||||
+enum { SchemeNorm, SchemeSel, SchemeOut, SchemeNormHighlight, SchemeSelHighlight, SchemeOutHighlight, SchemeLast }; /* color schemes */
|
|
||||||
struct item {
|
|
||||||
char *text;
|
|
||||||
struct item *left, *right;
|
|
||||||
@@ -113,6 +112,43 @@ cistrstr(const char *s, const char *sub)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void
|
|
||||||
+drawhighlights(struct item *item, int x, int y, int maxw)
|
|
||||||
+{
|
|
||||||
+ char restorechar, tokens[sizeof text], *highlight, *token;
|
|
||||||
+ int indentx, highlightlen;
|
|
||||||
+
|
|
||||||
+ drw_setscheme(drw, scheme[item == sel ? SchemeSelHighlight : item->out ? SchemeOutHighlight : SchemeNormHighlight]);
|
|
||||||
+ strcpy(tokens, text);
|
|
||||||
+ for (token = strtok(tokens, " "); token; token = strtok(NULL, " ")) {
|
|
||||||
+ highlight = fstrstr(item->text, token);
|
|
||||||
+ while (highlight) {
|
|
||||||
+ // Move item str end, calc width for highlight indent, & restore
|
|
||||||
+ highlightlen = highlight - item->text;
|
|
||||||
+ restorechar = *highlight;
|
|
||||||
+ item->text[highlightlen] = '\0';
|
|
||||||
+ indentx = TEXTW(item->text);
|
|
||||||
+ item->text[highlightlen] = restorechar;
|
|
||||||
+
|
|
||||||
+ // Move highlight str end, draw highlight, & restore
|
|
||||||
+ restorechar = highlight[strlen(token)];
|
|
||||||
+ highlight[strlen(token)] = '\0';
|
|
||||||
+ if (indentx - (lrpad / 2) - 1 < maxw)
|
|
||||||
+ drw_text(
|
|
||||||
+ drw,
|
|
||||||
+ x + indentx - (lrpad / 2) - 1,
|
|
||||||
+ y,
|
|
||||||
+ MIN(maxw - indentx, TEXTW(highlight) - lrpad),
|
|
||||||
+ bh, 0, highlight, 0
|
|
||||||
+ );
|
|
||||||
+ highlight[strlen(token)] = restorechar;
|
|
||||||
+
|
|
||||||
+ if (strlen(highlight) - strlen(token) < strlen(token)) break;
|
|
||||||
+ highlight = fstrstr(highlight + strlen(token), token);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int
|
|
||||||
drawitem(struct item *item, int x, int y, int w)
|
|
||||||
{
|
|
||||||
@@ -123,7 +159,9 @@ drawitem(struct item *item, int x, int y, int w)
|
|
||||||
else
|
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
|
|
||||||
- return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
|
|
||||||
+ int r = drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
|
|
||||||
+ drawhighlights(item, x, y, w);
|
|
||||||
+ return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
--
|
|
||||||
2.29.2
|
|
||||||
|
|
|
@ -1,144 +0,0 @@
|
||||||
diff --git a/dmenu.c b/dmenu.c
|
|
||||||
index 7cf253b..d276a94 100644
|
|
||||||
--- a/dmenu.c
|
|
||||||
+++ b/dmenu.c
|
|
||||||
@@ -528,6 +528,119 @@ draw:
|
|
||||||
drawmenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void
|
|
||||||
+buttonpress(XEvent *e)
|
|
||||||
+{
|
|
||||||
+ struct item *item;
|
|
||||||
+ XButtonPressedEvent *ev = &e->xbutton;
|
|
||||||
+ int x = 0, y = 0, h = bh, w;
|
|
||||||
+
|
|
||||||
+ if (ev->window != win)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ /* right-click: exit */
|
|
||||||
+ if (ev->button == Button3)
|
|
||||||
+ exit(1);
|
|
||||||
+
|
|
||||||
+ if (prompt && *prompt)
|
|
||||||
+ x += promptw;
|
|
||||||
+
|
|
||||||
+ /* input field */
|
|
||||||
+ w = (lines > 0 || !matches) ? mw - x : inputw;
|
|
||||||
+
|
|
||||||
+ /* left-click on input: clear input,
|
|
||||||
+ * NOTE: if there is no left-arrow the space for < is reserved so
|
|
||||||
+ * add that to the input width */
|
|
||||||
+ if (ev->button == Button1 &&
|
|
||||||
+ ((lines <= 0 && ev->x >= 0 && ev->x <= x + w +
|
|
||||||
+ ((!prev || !curr->left) ? TEXTW("<") : 0)) ||
|
|
||||||
+ (lines > 0 && ev->y >= y && ev->y <= y + h))) {
|
|
||||||
+ insert(NULL, -cursor);
|
|
||||||
+ drawmenu();
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ /* middle-mouse click: paste selection */
|
|
||||||
+ if (ev->button == Button2) {
|
|
||||||
+ XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY,
|
|
||||||
+ utf8, utf8, win, CurrentTime);
|
|
||||||
+ drawmenu();
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ /* scroll up */
|
|
||||||
+ if (ev->button == Button4 && prev) {
|
|
||||||
+ sel = curr = prev;
|
|
||||||
+ calcoffsets();
|
|
||||||
+ drawmenu();
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ /* scroll down */
|
|
||||||
+ if (ev->button == Button5 && next) {
|
|
||||||
+ sel = curr = next;
|
|
||||||
+ calcoffsets();
|
|
||||||
+ drawmenu();
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ if (ev->button != Button1)
|
|
||||||
+ return;
|
|
||||||
+ if (ev->state & ~ControlMask)
|
|
||||||
+ return;
|
|
||||||
+ if (lines > 0) {
|
|
||||||
+ /* vertical list: (ctrl)left-click on item */
|
|
||||||
+ w = mw - x;
|
|
||||||
+ for (item = curr; item != next; item = item->right) {
|
|
||||||
+ y += h;
|
|
||||||
+ if (ev->y >= y && ev->y <= (y + h)) {
|
|
||||||
+ puts(item->text);
|
|
||||||
+ if (!(ev->state & ControlMask))
|
|
||||||
+ exit(0);
|
|
||||||
+ sel = item;
|
|
||||||
+ if (sel) {
|
|
||||||
+ sel->out = 1;
|
|
||||||
+ drawmenu();
|
|
||||||
+ }
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ } else if (matches) {
|
|
||||||
+ /* left-click on left arrow */
|
|
||||||
+ x += inputw;
|
|
||||||
+ w = TEXTW("<");
|
|
||||||
+ if (prev && curr->left) {
|
|
||||||
+ if (ev->x >= x && ev->x <= x + w) {
|
|
||||||
+ sel = curr = prev;
|
|
||||||
+ calcoffsets();
|
|
||||||
+ drawmenu();
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ /* horizontal list: (ctrl)left-click on item */
|
|
||||||
+ for (item = curr; item != next; item = item->right) {
|
|
||||||
+ x += w;
|
|
||||||
+ w = MIN(TEXTW(item->text), mw - x - TEXTW(">"));
|
|
||||||
+ if (ev->x >= x && ev->x <= x + w) {
|
|
||||||
+ puts(item->text);
|
|
||||||
+ if (!(ev->state & ControlMask))
|
|
||||||
+ exit(0);
|
|
||||||
+ sel = item;
|
|
||||||
+ if (sel) {
|
|
||||||
+ sel->out = 1;
|
|
||||||
+ drawmenu();
|
|
||||||
+ }
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ /* left-click on right arrow */
|
|
||||||
+ w = TEXTW(">");
|
|
||||||
+ x = mw - w;
|
|
||||||
+ if (next && ev->x >= x && ev->x <= x + w) {
|
|
||||||
+ sel = curr = next;
|
|
||||||
+ calcoffsets();
|
|
||||||
+ drawmenu();
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void
|
|
||||||
paste(void)
|
|
||||||
{
|
|
||||||
@@ -582,6 +695,9 @@ run(void)
|
|
||||||
break;
|
|
||||||
cleanup();
|
|
||||||
exit(1);
|
|
||||||
+ case ButtonPress:
|
|
||||||
+ buttonpress(&ev);
|
|
||||||
+ break;
|
|
||||||
case Expose:
|
|
||||||
if (ev.xexpose.count == 0)
|
|
||||||
drw_map(drw, win, 0, 0, mw, mh);
|
|
||||||
@@ -679,7 +795,8 @@ setup(void)
|
|
||||||
/* create menu window */
|
|
||||||
swa.override_redirect = True;
|
|
||||||
swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
|
|
||||||
- swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
|
|
||||||
+ swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask |
|
|
||||||
+ ButtonPressMask;
|
|
||||||
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
|
|
||||||
CopyFromParent, CopyFromParent, CopyFromParent,
|
|
||||||
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
|
|
|
@ -1,53 +0,0 @@
|
||||||
diff --git a/dmenu.c b/dmenu.c
|
|
||||||
index 48d4980..7677401 100644
|
|
||||||
--- a/dmenu.c
|
|
||||||
+++ b/dmenu.c
|
|
||||||
@@ -641,6 +641,29 @@ buttonpress(XEvent *e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void
|
|
||||||
+motionevent(XButtonEvent *ev)
|
|
||||||
+{
|
|
||||||
+ struct item *it;
|
|
||||||
+ int xy, ev_xy;
|
|
||||||
+
|
|
||||||
+ if (ev->window != win || matches == 0)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ xy = lines > 0 ? bh : inputw + promptw + TEXTW("<");
|
|
||||||
+ ev_xy = lines > 0 ? ev->y : ev->x;
|
|
||||||
+ for (it = curr; it && it != next; it = it->right) {
|
|
||||||
+ int wh = lines > 0 ? bh : textw_clamp(it->text, mw - xy - TEXTW(">"));
|
|
||||||
+ if (ev_xy >= xy && ev_xy < (xy + wh)) {
|
|
||||||
+ sel = it;
|
|
||||||
+ calcoffsets();
|
|
||||||
+ drawmenu();
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ xy += wh;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void
|
|
||||||
paste(void)
|
|
||||||
{
|
|
||||||
@@ -702,6 +725,9 @@ run(void)
|
|
||||||
case ButtonPress:
|
|
||||||
buttonpress(&ev);
|
|
||||||
break;
|
|
||||||
+ case MotionNotify:
|
|
||||||
+ motionevent(&ev.xbutton);
|
|
||||||
+ break;
|
|
||||||
case Expose:
|
|
||||||
if (ev.xexpose.count == 0)
|
|
||||||
drw_map(drw, win, 0, 0, mw, mh);
|
|
||||||
@@ -800,7 +826,7 @@ setup(void)
|
|
||||||
swa.override_redirect = True;
|
|
||||||
swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
|
|
||||||
swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask |
|
|
||||||
- ButtonPressMask;
|
|
||||||
+ ButtonPressMask | PointerMotionMask;
|
|
||||||
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
|
|
||||||
CopyFromParent, CopyFromParent, CopyFromParent,
|
|
||||||
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
|
|
|
@ -1,103 +0,0 @@
|
||||||
From c4de1032bd4c247bc20b6ab92a10a8d778966679 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Mehrad Mahmoudian <m.mahmoudian@gmail.com>
|
|
||||||
Date: Tue, 4 May 2021 12:05:09 +0300
|
|
||||||
Subject: [PATCH] patched with password patch
|
|
||||||
|
|
||||||
---
|
|
||||||
dmenu.1 | 5 ++++-
|
|
||||||
dmenu.c | 21 +++++++++++++++++----
|
|
||||||
2 files changed, 21 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/dmenu.1 b/dmenu.1
|
|
||||||
index 323f93c..762f707 100644
|
|
||||||
--- a/dmenu.1
|
|
||||||
+++ b/dmenu.1
|
|
||||||
@@ -3,7 +3,7 @@
|
|
||||||
dmenu \- dynamic menu
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B dmenu
|
|
||||||
-.RB [ \-bfiv ]
|
|
||||||
+.RB [ \-bfivP ]
|
|
||||||
.RB [ \-l
|
|
||||||
.IR lines ]
|
|
||||||
.RB [ \-m
|
|
||||||
@@ -47,6 +47,9 @@ is faster, but will lock up X until stdin reaches end\-of\-file.
|
|
||||||
.B \-i
|
|
||||||
dmenu matches menu items case insensitively.
|
|
||||||
.TP
|
|
||||||
+.B \-P
|
|
||||||
+dmenu will not directly display the keyboard input, but instead replace it with dots. All data from stdin will be ignored.
|
|
||||||
+.TP
|
|
||||||
.BI \-l " lines"
|
|
||||||
dmenu lists items vertically, with the given number of lines.
|
|
||||||
.TP
|
|
||||||
diff --git a/dmenu.c b/dmenu.c
|
|
||||||
index 65f25ce..ad8f63b 100644
|
|
||||||
--- a/dmenu.c
|
|
||||||
+++ b/dmenu.c
|
|
||||||
@@ -37,7 +37,7 @@ struct item {
|
|
||||||
static char text[BUFSIZ] = "";
|
|
||||||
static char *embed;
|
|
||||||
static int bh, mw, mh;
|
|
||||||
-static int inputw = 0, promptw;
|
|
||||||
+static int inputw = 0, promptw, passwd = 0;
|
|
||||||
static int lrpad; /* sum of left and right padding */
|
|
||||||
static size_t cursor;
|
|
||||||
static struct item *items = NULL;
|
|
||||||
@@ -132,6 +132,7 @@ drawmenu(void)
|
|
||||||
unsigned int curpos;
|
|
||||||
struct item *item;
|
|
||||||
int x = 0, y = 0, w;
|
|
||||||
+ char *censort;
|
|
||||||
|
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
drw_rect(drw, 0, 0, mw, mh, 1, 1);
|
|
||||||
@@ -143,7 +144,12 @@ drawmenu(void)
|
|
||||||
/* draw input field */
|
|
||||||
w = (lines > 0 || !matches) ? mw - x : inputw;
|
|
||||||
drw_setscheme(drw, scheme[SchemeNorm]);
|
|
||||||
- drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
|
|
||||||
+ if (passwd) {
|
|
||||||
+ censort = ecalloc(1, sizeof(text));
|
|
||||||
+ memset(censort, '.', strlen(text));
|
|
||||||
+ drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0);
|
|
||||||
+ free(censort);
|
|
||||||
+ } else drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
|
|
||||||
|
|
||||||
curpos = TEXTW(text) - TEXTW(&text[cursor]);
|
|
||||||
if ((curpos += lrpad / 2 - 1) < w) {
|
|
||||||
@@ -524,6 +530,11 @@ readstdin(void)
|
|
||||||
char buf[sizeof text], *p;
|
|
||||||
size_t i, imax = 0, size = 0;
|
|
||||||
unsigned int tmpmax = 0;
|
|
||||||
+ if(passwd){
|
|
||||||
+ inputw = lines = 0;
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
|
|
||||||
/* read each line from stdin and add it to the item list */
|
|
||||||
for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
|
|
||||||
@@ -689,7 +700,7 @@ setup(void)
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
- fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
|
|
||||||
+ fputs("usage: dmenu [-bfivP] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
|
|
||||||
" [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
@@ -712,7 +723,9 @@ main(int argc, char *argv[])
|
|
||||||
else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
|
|
||||||
fstrncmp = strncasecmp;
|
|
||||||
fstrstr = cistrstr;
|
|
||||||
- } else if (i + 1 == argc)
|
|
||||||
+ } else if (!strcmp(argv[i], "-P")) /* is the input a password */
|
|
||||||
+ passwd = 1;
|
|
||||||
+ else if (i + 1 == argc)
|
|
||||||
usage();
|
|
||||||
/* these options take one argument */
|
|
||||||
else if (!strcmp(argv[i], "-l")) /* number of lines in vertical list */
|
|
||||||
--
|
|
||||||
2.31.1
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# ***This script was made by Clay Gomera (Drake)***
|
|
||||||
# - Description: A simple desktop dmenu script
|
|
||||||
# - Dependencies: dmenu, j4-dmenu-desktop
|
|
||||||
|
|
||||||
# uses j4-dmenu-desktop to launch programs by it's desktop entry
|
|
||||||
j4-dmenu-desktop --dmenu "dmenu -i -l 10 -p ' Launch:'" --no-generic
|
|
|
@ -1,27 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# ***This script was made by Clay Gomera (Drake)***
|
|
||||||
# - Description: A simple script for file editing in dmenu
|
|
||||||
# - Dependencies: dmenu, fd
|
|
||||||
|
|
||||||
##########
|
|
||||||
## main ##
|
|
||||||
##########
|
|
||||||
cd "$HOME" || exit 0
|
|
||||||
file=1
|
|
||||||
while [ "$file" ]; do
|
|
||||||
file=$(fd -LHpd 1 | dmenu -i -l 10 -p " Open file in text editor $(basename "$(pwd)")")
|
|
||||||
if [ -e "$file" ]; then
|
|
||||||
owd=$(pwd)
|
|
||||||
if [ -d "$file" ]; then
|
|
||||||
cd "$file" || exit 0
|
|
||||||
else [ -f "$file" ]
|
|
||||||
if [ "$file" ]; then
|
|
||||||
$VISUAL "$owd/$file" & # $VISUAL reffers to a global variable set in .xinitrc/.bash_profile
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
|
@ -1,43 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# List of available drives
|
|
||||||
devices=$(lsblk -lpo "name,size,type,mountpoint" --noheadings | grep -v -e "disk" -e "lvm" -e "nvme" |
|
|
||||||
awk '{if ($4=="") {print $1, "(" $2 ")", "[unmounted]"} else {print $1, "(" $2 ")", "[" $4 "]"}}')
|
|
||||||
|
|
||||||
# Main menu
|
|
||||||
selected_device=$(echo -e "${devices}" | dmenu -i -p "Drive manager" | awk '{print $1}')
|
|
||||||
|
|
||||||
# Verify if a drive is selected
|
|
||||||
if [ -n "$selected_device" ]; then
|
|
||||||
mounted_path=$(lsblk -lp | grep "${selected_device}" | awk '{print $7}')
|
|
||||||
|
|
||||||
# Verify if the drive is mounted
|
|
||||||
if [ -n "$mounted_path" ]; then
|
|
||||||
# Check if the drive is encrypted
|
|
||||||
if [ "$(lsblk -n -o TYPE "${selected_device}")" == "crypt" ]; then
|
|
||||||
crypt_device=$(echo "${selected_device}" | sed -s 's/\/dev\/mapper\///')
|
|
||||||
udisksctl unmount -b "${selected_device}"
|
|
||||||
udisksctl lock -b "$crypt_device"
|
|
||||||
notify-send "The encrypted drive was unmounted successfully"
|
|
||||||
else
|
|
||||||
# If it's mounted, unmount it
|
|
||||||
udisksctl unmount -b "$selected_device"
|
|
||||||
notify-send "The drive was unmounted successfully"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# If it's not mounted, check if it's an encrypted drive
|
|
||||||
if [ "$(lsblk -n -o FSTYPE "${selected_device}")" == "crypto_LUKS" ]; then
|
|
||||||
# If it's an encrypted drive, prompt for the passphrase and mount it
|
|
||||||
passphrase=$(echo "" | dmenu -p "Enter passphrase for ${selected_device}")
|
|
||||||
if [ -n "$passphrase" ]; then
|
|
||||||
unlocked_device=$(udisksctl unlock -b "${selected_device}" --key-file <(echo -n "$passphrase") | awk '{print $NF}' | sed 's/\.$//')
|
|
||||||
udisksctl mount -b "${unlocked_device}"
|
|
||||||
notify-send "The encrypted drive was mounted successfully"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# If it's not an encrypted drive, mount it normally
|
|
||||||
udisksctl mount -b "$selected_device"
|
|
||||||
notify-send "The drive was mounted successfully"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
|
@ -1,315 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# ***This script was made by Clay Gomera (Drake)***
|
|
||||||
# - Description: A simple screenshot/screencast dmenu script
|
|
||||||
# - Dependencies: maim, splop, ffmpeg, dmenu, libnotify
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
## Screenshot & Screencast Directory ##
|
|
||||||
#######################################
|
|
||||||
SHOTDIR="$XDG_PICTURES_DIR/Screenshots"
|
|
||||||
CASTDIR="$XDG_VIDEOS_DIR/Screencasts"
|
|
||||||
[ ! -d "$SHOTDIR" ] && [ ! -d "$CASTDIR" ] && mkdir -p "$SHOTDIR" "$CASTDIR" || echo
|
|
||||||
|
|
||||||
######################
|
|
||||||
## Format Variables ##
|
|
||||||
######################
|
|
||||||
image_formats="jpg\npng"
|
|
||||||
video_formats="mp4\nmkv"
|
|
||||||
|
|
||||||
#######################
|
|
||||||
## Main menu choices ##
|
|
||||||
#######################
|
|
||||||
mcho1=" Take a screenshot"
|
|
||||||
mcho2=" Record the screen"
|
|
||||||
mcho3=" Stop recording"
|
|
||||||
mcho4=" Exit"
|
|
||||||
mchos="$mcho1\n$mcho2\n$mcho3\n$mcho4"
|
|
||||||
|
|
||||||
##########################
|
|
||||||
## Main submenu choices ##
|
|
||||||
##########################
|
|
||||||
mscho1=" Capture the entire screen"
|
|
||||||
mscho2=" Capture the entire screen (With delay)"
|
|
||||||
mscho3=" Capture area"
|
|
||||||
mscho4=" Capture active window"
|
|
||||||
mscho5=" Exit"
|
|
||||||
mschos="$mscho1\n$mscho2\n$mscho3\n$mscho4\n$mscho5"
|
|
||||||
|
|
||||||
###############################
|
|
||||||
## Save/clip submenu choices ##
|
|
||||||
###############################
|
|
||||||
svcho1=" Copy to clipboard"
|
|
||||||
svcho2=" Save to $SHOTDIR"
|
|
||||||
svchos="$svcho1\n$svcho2"
|
|
||||||
|
|
||||||
######################
|
|
||||||
## Delay subsubmenu ##
|
|
||||||
######################
|
|
||||||
del1=" 3 sec delay"
|
|
||||||
del2=" 5 sec delay"
|
|
||||||
del3=" 10 sec delay"
|
|
||||||
dels="$del1\n$del2\n$del3"
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function will check for dependencies
|
|
||||||
#####
|
|
||||||
check_dependencies() {
|
|
||||||
local dependencies=("maim" "ffmpeg" "dmenu" "notify-send" "xclip" "xdotool")
|
|
||||||
for dep in "${dependencies[@]}"; do
|
|
||||||
if ! command -v "$dep" &>/dev/null; then
|
|
||||||
echo "$dep is required but not installed. Please install it and try again."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function uses the svchos variable to ask the user what to do with the
|
|
||||||
## screenshot
|
|
||||||
#####
|
|
||||||
fsvchos() {
|
|
||||||
svchoice=$(echo -e "$svchos" | dmenu -i -l 2 -p " What do you want to do with this screenshot?")
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function uses the dels variable to ask the user which delay option to
|
|
||||||
## choose
|
|
||||||
#####
|
|
||||||
fdel() {
|
|
||||||
del=$(echo -e "$dels" | dmenu -i -p " Select Delay")
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function allows the user to choose the screenshot format
|
|
||||||
#####
|
|
||||||
fimage_format() {
|
|
||||||
image_format=$(echo -e "$image_formats" | dmenu -i -p " Choose screenshot format")
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function allows the user to choose the recording format
|
|
||||||
#####
|
|
||||||
fvideo_format() {
|
|
||||||
video_format=$(echo -e "$video_formats" | dmenu -i -p " Choose video format")
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function does a full screen screenshot without delay, depending on what
|
|
||||||
## the user chooses on the fsvchos function, the screenshot will be saved to the
|
|
||||||
## clipboard or to $SHOTDIR
|
|
||||||
#####
|
|
||||||
shot_screen() {
|
|
||||||
fimage_format
|
|
||||||
fsvchos
|
|
||||||
if [ "$svchoice" = "$svcho1" ]; then
|
|
||||||
maim | xclip -selection clipboard -t image/"$image_format" && notify-send "Screenshot saved to clipboard"
|
|
||||||
elif [ "$svchoice" = "$svcho2" ]; then
|
|
||||||
maim -f "$image_format" "$SHOTDIR/$(date +%s).$image_format" && notify-send "Screenshot saved"
|
|
||||||
else
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function does a full screen screenshot with delay, depending on what the
|
|
||||||
## user chooses on the fsvchos function, the screenshot will be saved to the
|
|
||||||
## clipboard or to $SHOTDIR. And depending on what the user chooses on the fdel
|
|
||||||
## function, the delay will be between 3 and 10 seconds
|
|
||||||
#####
|
|
||||||
shot_screen_delay() {
|
|
||||||
fimage_format
|
|
||||||
fsvchos
|
|
||||||
fdel
|
|
||||||
case $del in
|
|
||||||
"$del1")
|
|
||||||
for i in 3 2 1
|
|
||||||
do
|
|
||||||
notify-send -d 1 "Capturing in $i.."
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
;;
|
|
||||||
"$del2")
|
|
||||||
for i in 5 4 3 2 1
|
|
||||||
do
|
|
||||||
notify-send -d 1 "Capturing in $i.."
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
;;
|
|
||||||
"$del3")
|
|
||||||
for i in 10 9 8 7 6 5 4 3 2 1
|
|
||||||
do
|
|
||||||
notify-send -d 1 "Capturing in $i.."
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ "$svchoice" = "$svcho1" ]; then
|
|
||||||
maim | xclip -selection clipboard -t image/"$image_format" && notify-send "Screenshot saved to clipboard";
|
|
||||||
elif [ "$svchoice" = "$svcho2" ]; then
|
|
||||||
maim -f "$image_format" "$SHOTDIR/$(date +%s).$image_format" && notify-send "Screenshot saved to $SHOTDIR";
|
|
||||||
else
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function allows the user to select the area on the screen to screenshot
|
|
||||||
## depending on what the user chooses on the fsvchos function, the screenshot will
|
|
||||||
## be saved to the clipboard or to $SHOTDIR
|
|
||||||
#####
|
|
||||||
shot_area() {
|
|
||||||
fimage_format
|
|
||||||
fsvchos
|
|
||||||
if [ "$svchoice" = "$svcho1" ]; then
|
|
||||||
maim -s | xclip -selection clipboard -t image/"$image_format" && notify-send "Screenshot saved to clipboard";
|
|
||||||
elif [ "$svchoice" = "$svcho2" ]; then
|
|
||||||
maim -s -f "$image_format" "$SHOTDIR/$(date +%s).$image_format" && notify-send "Screenshot saved to $SHOTDIR";
|
|
||||||
else
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function does a screenshot of the currently active window, depending
|
|
||||||
## on what the user chooses on the fsvchos function, the screenshot will be
|
|
||||||
## saved to the clipboard or to $SHOTDIR
|
|
||||||
#####
|
|
||||||
shot_window() {
|
|
||||||
fimage_format
|
|
||||||
fsvchos
|
|
||||||
if [ "$svchoice" = "$svcho1" ]; then
|
|
||||||
maim -i "$(xdotool getactivewindow)" | xclip -selection clipboard -t image/"$image_format" && notify-send "Screenshot saved to clipboard";
|
|
||||||
elif [ "$svchoice" = "$svcho2" ]; then
|
|
||||||
maim -i "$(xdotool getactivewindow)" -f "$image_format" "$SHOTDIR/$(date +%s).$image_format" && notify-send "Screenshot saved to $SHOTDIR";
|
|
||||||
else
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function uses ffmpeg to record the screen, It will check if ffmpeg is
|
|
||||||
## already running (already recording), to prevent the user from executing
|
|
||||||
## another ffmpeg instance, if it's not running, it will grab the screen
|
|
||||||
## resolution with xdpyinfo and use it to record the screen with ffmpeg.
|
|
||||||
#####
|
|
||||||
rec_screen() {
|
|
||||||
fvideo_format
|
|
||||||
if pgrep -x "ffmpeg" > /dev/null; then
|
|
||||||
notify-send "A screen recording is already in progress."
|
|
||||||
else
|
|
||||||
filename="$CASTDIR/$(date +%s).$video_format"
|
|
||||||
resolution="$(xdpyinfo | grep dimensions | awk '{print $2}')"
|
|
||||||
ffmpeg -f x11grab -s "$resolution" -i :0.0 -c:v libx264 -preset ultrafast -qp 0 "$filename" &
|
|
||||||
notify-send "Screen recording started."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function will record the screen with a given delay
|
|
||||||
#####
|
|
||||||
rec_screen_delay() {
|
|
||||||
fvideo_format
|
|
||||||
fdel
|
|
||||||
case $del in
|
|
||||||
"$del1")
|
|
||||||
for i in 3 2 1
|
|
||||||
do
|
|
||||||
notify-send -d 1 "Starting in $i.."
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
;;
|
|
||||||
"$del2")
|
|
||||||
for i in 5 4 3 2 1
|
|
||||||
do
|
|
||||||
notify-send -d 1 "Starting in $i.."
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
;;
|
|
||||||
"$del3")
|
|
||||||
for i in 10 9 8 7 6 5 4 3 2 1
|
|
||||||
do
|
|
||||||
notify-send -d 1 "Starting in $i.."
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if pgrep -x "ffmpeg" > /dev/null; then
|
|
||||||
notify-send "A screen recording is already in progress."
|
|
||||||
else
|
|
||||||
filename="$CASTDIR/$(date +%s).$video_format"
|
|
||||||
resolution="$(xdpyinfo | grep dimensions | awk '{print $2}')"
|
|
||||||
ffmpeg -f x11grab -s "$resolution" -i :0.0 -c:v libx264 -preset ultrafast -qp 0 "$filename" &
|
|
||||||
notify-send "Screen recording started"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#####
|
|
||||||
## This function stops screen recording, it first checks if ffmpeg is already
|
|
||||||
## running (already recording), to only stop a recording if there's an ffmpeg
|
|
||||||
## instance running
|
|
||||||
#####
|
|
||||||
stop_recording() {
|
|
||||||
if pgrep -x "ffmpeg" > /dev/null; then
|
|
||||||
pkill -f "ffmpeg -f x11grab"
|
|
||||||
notify-send "Screen recording stopped. Video saved to $CASTDIR"
|
|
||||||
else
|
|
||||||
notify-send "You aren't recording anything at the moment"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
##########
|
|
||||||
## main ##
|
|
||||||
##########
|
|
||||||
check_dependencies;
|
|
||||||
mchoice=$(echo -e "$mchos" | dmenu -i -l 4 -p " Screen Capture Menu") # main menu prompt
|
|
||||||
case $mchoice in
|
|
||||||
"$mcho1")
|
|
||||||
mschoice=$(echo -e "$mschos" | dmenu -i -l 9 -p " Screenshot Menu") # screenshot menu prompt
|
|
||||||
case $mschoice in
|
|
||||||
"$mscho1")
|
|
||||||
shot_screen;
|
|
||||||
;;
|
|
||||||
"$mscho2")
|
|
||||||
shot_screen_delay;
|
|
||||||
;;
|
|
||||||
"$mscho3")
|
|
||||||
shot_area;
|
|
||||||
;;
|
|
||||||
"$mscho4")
|
|
||||||
shot_window;
|
|
||||||
;;
|
|
||||||
"$mscho5")
|
|
||||||
exit 0
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"$mcho2")
|
|
||||||
mschoice=$(echo -e "$mschos" | dmenu -i -l 9 -p " Screencast Menu") # screenshot menu prompt
|
|
||||||
case $mschoice in
|
|
||||||
"$mscho1")
|
|
||||||
rec_screen;
|
|
||||||
;;
|
|
||||||
"$mscho2")
|
|
||||||
rec_screen_delay;
|
|
||||||
;;
|
|
||||||
"$mscho3")
|
|
||||||
#rec_area;
|
|
||||||
notify-send "not implemented yet"
|
|
||||||
;;
|
|
||||||
"$mscho4")
|
|
||||||
#rec_window;
|
|
||||||
notify-send "not implemented yet"
|
|
||||||
;;
|
|
||||||
"$mscho5")
|
|
||||||
exit 0
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
"$mcho3")
|
|
||||||
stop_recording;
|
|
||||||
;;
|
|
||||||
"$mcho4")
|
|
||||||
exit 0;
|
|
||||||
;;
|
|
||||||
esac
|
|
|
@ -1,49 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# ***This script was made by Clay Gomera (Drake)***
|
|
||||||
# - Description: A simple dmenu script to set the wallpaper on X
|
|
||||||
# - Dependencies: dmenu, fd, feh
|
|
||||||
|
|
||||||
##########################
|
|
||||||
## Wallpapers Directory ##
|
|
||||||
##########################
|
|
||||||
walldir="$XDG_PICTURES_DIR/Wallpapers"
|
|
||||||
cd "$walldir" || exit # we cd into $walldir in order to get only the file name on the main prompt
|
|
||||||
|
|
||||||
#######################
|
|
||||||
## Wallpaper options ##
|
|
||||||
#######################
|
|
||||||
option1="Fill"
|
|
||||||
option2="Center"
|
|
||||||
option3="Tile"
|
|
||||||
option4="Max"
|
|
||||||
option5="Scale"
|
|
||||||
options="$option1\n$option2\n$option3\n$option4\n$option5"
|
|
||||||
|
|
||||||
##########
|
|
||||||
## main ##
|
|
||||||
##########
|
|
||||||
wallpaper=$(fd -p ./ | dmenu -i -p " Select a wallpaper ") # main prompt
|
|
||||||
if [ "$wallpaper" ]; then # if the user made a choice
|
|
||||||
chosenwall=$wallpaper # reassign $wallpaper to $chosenwall
|
|
||||||
else
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
action=$(echo -e "$options" | dmenu -i -p " Chose the format ") # options prompt
|
|
||||||
case "$action" in
|
|
||||||
$option1*)
|
|
||||||
feh --bg-fill "$chosenwall";
|
|
||||||
;;
|
|
||||||
$option2*)
|
|
||||||
feh --bg-center "$chosenwall";
|
|
||||||
;;
|
|
||||||
$option3*)
|
|
||||||
feh --bg-tile "$chosenwall";
|
|
||||||
;;
|
|
||||||
$option4*)
|
|
||||||
feh --bg-max "$chosenwall";
|
|
||||||
;;
|
|
||||||
$option5*)
|
|
||||||
feh --bg-scale "$chosenwall";
|
|
||||||
;;
|
|
||||||
esac
|
|
|
@ -1,90 +0,0 @@
|
||||||
.TH STEST 1 dmenu\-VERSION
|
|
||||||
.SH NAME
|
|
||||||
stest \- filter a list of files by properties
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B stest
|
|
||||||
.RB [ -abcdefghlpqrsuwx ]
|
|
||||||
.RB [ -n
|
|
||||||
.IR file ]
|
|
||||||
.RB [ -o
|
|
||||||
.IR file ]
|
|
||||||
.RI [ file ...]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.B stest
|
|
||||||
takes a list of files and filters by the files' properties, analogous to
|
|
||||||
.IR test (1).
|
|
||||||
Files which pass all tests are printed to stdout. If no files are given, stest
|
|
||||||
reads files from stdin.
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.B \-a
|
|
||||||
Test hidden files.
|
|
||||||
.TP
|
|
||||||
.B \-b
|
|
||||||
Test that files are block specials.
|
|
||||||
.TP
|
|
||||||
.B \-c
|
|
||||||
Test that files are character specials.
|
|
||||||
.TP
|
|
||||||
.B \-d
|
|
||||||
Test that files are directories.
|
|
||||||
.TP
|
|
||||||
.B \-e
|
|
||||||
Test that files exist.
|
|
||||||
.TP
|
|
||||||
.B \-f
|
|
||||||
Test that files are regular files.
|
|
||||||
.TP
|
|
||||||
.B \-g
|
|
||||||
Test that files have their set-group-ID flag set.
|
|
||||||
.TP
|
|
||||||
.B \-h
|
|
||||||
Test that files are symbolic links.
|
|
||||||
.TP
|
|
||||||
.B \-l
|
|
||||||
Test the contents of a directory given as an argument.
|
|
||||||
.TP
|
|
||||||
.BI \-n " file"
|
|
||||||
Test that files are newer than
|
|
||||||
.IR file .
|
|
||||||
.TP
|
|
||||||
.BI \-o " file"
|
|
||||||
Test that files are older than
|
|
||||||
.IR file .
|
|
||||||
.TP
|
|
||||||
.B \-p
|
|
||||||
Test that files are named pipes.
|
|
||||||
.TP
|
|
||||||
.B \-q
|
|
||||||
No files are printed, only the exit status is returned.
|
|
||||||
.TP
|
|
||||||
.B \-r
|
|
||||||
Test that files are readable.
|
|
||||||
.TP
|
|
||||||
.B \-s
|
|
||||||
Test that files are not empty.
|
|
||||||
.TP
|
|
||||||
.B \-u
|
|
||||||
Test that files have their set-user-ID flag set.
|
|
||||||
.TP
|
|
||||||
.B \-v
|
|
||||||
Invert the sense of tests, only failing files pass.
|
|
||||||
.TP
|
|
||||||
.B \-w
|
|
||||||
Test that files are writable.
|
|
||||||
.TP
|
|
||||||
.B \-x
|
|
||||||
Test that files are executable.
|
|
||||||
.SH EXIT STATUS
|
|
||||||
.TP
|
|
||||||
.B 0
|
|
||||||
At least one file passed all tests.
|
|
||||||
.TP
|
|
||||||
.B 1
|
|
||||||
No files passed all tests.
|
|
||||||
.TP
|
|
||||||
.B 2
|
|
||||||
An error occurred.
|
|
||||||
.SH SEE ALSO
|
|
||||||
.IR dmenu (1),
|
|
||||||
.IR test (1)
|
|
|
@ -1,109 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "arg.h"
|
|
||||||
char *argv0;
|
|
||||||
|
|
||||||
#define FLAG(x) (flag[(x)-'a'])
|
|
||||||
|
|
||||||
static void test(const char *, const char *);
|
|
||||||
static void usage(void);
|
|
||||||
|
|
||||||
static int match = 0;
|
|
||||||
static int flag[26];
|
|
||||||
static struct stat old, new;
|
|
||||||
|
|
||||||
static void
|
|
||||||
test(const char *path, const char *name)
|
|
||||||
{
|
|
||||||
struct stat st, ln;
|
|
||||||
|
|
||||||
if ((!stat(path, &st) && (FLAG('a') || name[0] != '.') /* hidden files */
|
|
||||||
&& (!FLAG('b') || S_ISBLK(st.st_mode)) /* block special */
|
|
||||||
&& (!FLAG('c') || S_ISCHR(st.st_mode)) /* character special */
|
|
||||||
&& (!FLAG('d') || S_ISDIR(st.st_mode)) /* directory */
|
|
||||||
&& (!FLAG('e') || access(path, F_OK) == 0) /* exists */
|
|
||||||
&& (!FLAG('f') || S_ISREG(st.st_mode)) /* regular file */
|
|
||||||
&& (!FLAG('g') || st.st_mode & S_ISGID) /* set-group-id flag */
|
|
||||||
&& (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /* symbolic link */
|
|
||||||
&& (!FLAG('n') || st.st_mtime > new.st_mtime) /* newer than file */
|
|
||||||
&& (!FLAG('o') || st.st_mtime < old.st_mtime) /* older than file */
|
|
||||||
&& (!FLAG('p') || S_ISFIFO(st.st_mode)) /* named pipe */
|
|
||||||
&& (!FLAG('r') || access(path, R_OK) == 0) /* readable */
|
|
||||||
&& (!FLAG('s') || st.st_size > 0) /* not empty */
|
|
||||||
&& (!FLAG('u') || st.st_mode & S_ISUID) /* set-user-id flag */
|
|
||||||
&& (!FLAG('w') || access(path, W_OK) == 0) /* writable */
|
|
||||||
&& (!FLAG('x') || access(path, X_OK) == 0)) != FLAG('v')) { /* executable */
|
|
||||||
if (FLAG('q'))
|
|
||||||
exit(0);
|
|
||||||
match = 1;
|
|
||||||
puts(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "usage: %s [-abcdefghlpqrsuvwx] "
|
|
||||||
"[-n file] [-o file] [file...]\n", argv0);
|
|
||||||
exit(2); /* like test(1) return > 1 on error */
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct dirent *d;
|
|
||||||
char path[PATH_MAX], *line = NULL, *file;
|
|
||||||
size_t linesiz = 0;
|
|
||||||
ssize_t n;
|
|
||||||
DIR *dir;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
ARGBEGIN {
|
|
||||||
case 'n': /* newer than file */
|
|
||||||
case 'o': /* older than file */
|
|
||||||
file = EARGF(usage());
|
|
||||||
if (!(FLAG(ARGC()) = !stat(file, (ARGC() == 'n' ? &new : &old))))
|
|
||||||
perror(file);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* miscellaneous operators */
|
|
||||||
if (strchr("abcdefghlpqrsuvwx", ARGC()))
|
|
||||||
FLAG(ARGC()) = 1;
|
|
||||||
else
|
|
||||||
usage(); /* unknown flag */
|
|
||||||
} ARGEND;
|
|
||||||
|
|
||||||
if (!argc) {
|
|
||||||
/* read list from stdin */
|
|
||||||
while ((n = getline(&line, &linesiz, stdin)) > 0) {
|
|
||||||
if (line[n - 1] == '\n')
|
|
||||||
line[n - 1] = '\0';
|
|
||||||
test(line, line);
|
|
||||||
}
|
|
||||||
free(line);
|
|
||||||
} else {
|
|
||||||
for (; argc; argc--, argv++) {
|
|
||||||
if (FLAG('l') && (dir = opendir(*argv))) {
|
|
||||||
/* test directory contents */
|
|
||||||
while ((d = readdir(dir))) {
|
|
||||||
r = snprintf(path, sizeof path, "%s/%s",
|
|
||||||
*argv, d->d_name);
|
|
||||||
if (r >= 0 && (size_t)r < sizeof path)
|
|
||||||
test(path, d->d_name);
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
} else {
|
|
||||||
test(*argv, *argv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return match ? 0 : 1;
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
die(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vfprintf(stderr, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (fmt[0] && fmt[strlen(fmt)-1] == ':') {
|
|
||||||
fputc(' ', stderr);
|
|
||||||
perror(NULL);
|
|
||||||
} else {
|
|
||||||
fputc('\n', stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
ecalloc(size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *p;
|
|
||||||
|
|
||||||
if (!(p = calloc(nmemb, size)))
|
|
||||||
die("calloc:");
|
|
||||||
return p;
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
/* See LICENSE file for copyright and license details. */
|
|
||||||
|
|
||||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
|
||||||
#define MIN(A, B) ((A) < (B) ? (A) : (B))
|
|
||||||
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
|
|
||||||
|
|
||||||
void die(const char *fmt, ...);
|
|
||||||
void *ecalloc(size_t nmemb, size_t size);
|
|
674
user/.config/suckless/dwl-bar/LICENSE
Normal file
674
user/.config/suckless/dwl-bar/LICENSE
Normal file
|
@ -0,0 +1,674 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
87
user/.config/suckless/dwl-bar/Makefile
Normal file
87
user/.config/suckless/dwl-bar/Makefile
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
##
|
||||||
|
# dwl-bar
|
||||||
|
#
|
||||||
|
# @file
|
||||||
|
# @version 0.0
|
||||||
|
VERSION = 0.0
|
||||||
|
PKG_CONFIG = pkg-config
|
||||||
|
|
||||||
|
# paths
|
||||||
|
PREFIX = /usr/local
|
||||||
|
MANDIR = $(PREFIX)/share/man
|
||||||
|
SRCDIR = src
|
||||||
|
|
||||||
|
PKGS = wayland-client wayland-cursor pangocairo
|
||||||
|
FILES = $(SRCDIR)/main.c $(SRCDIR)/main.h $(SRCDIR)/log.c $(SRCDIR)/log.h \
|
||||||
|
$(SRCDIR)/render.c $(SRCDIR)/render.h $(SRCDIR)/event.c $(SRCDIR)/event.h \
|
||||||
|
$(SRCDIR)/util.c $(SRCDIR)/util.h $(SRCDIR)/shm.c $(SRCDIR)/shm.h \
|
||||||
|
$(SRCDIR)/input.c $(SRCDIR)/input.h $(SRCDIR)/user.c $(SRCDIR)/user.h \
|
||||||
|
$(SRCDIR)/bar.c $(SRCDIR)/bar.h $(SRCDIR)/config.h
|
||||||
|
OBJS = $(SRCDIR)/xdg-output-unstable-v1-protocol.o $(SRCDIR)/xdg-shell-protocol.o \
|
||||||
|
$(SRCDIR)/wlr-layer-shell-unstable-v1-protocol.o
|
||||||
|
OBJS := $(filter-out $(SRCDIR)/xdg-output-unstable-v1-protocol.o,$(OBJS))
|
||||||
|
OBJS += $(SRCDIR)/dwl-ipc-unstable-v2-protocol.o
|
||||||
|
|
||||||
|
## Compile Flags
|
||||||
|
CC = gcc
|
||||||
|
BARCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(CFLAGS)
|
||||||
|
BARLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS)
|
||||||
|
|
||||||
|
WAYLAND_SCANNER = `$(PKG_CONFIG) --variable=wayland_scanner wayland-scanner`
|
||||||
|
WAYLAND_PROTOCOLS = `$(PKG_CONFIG) --variable=pkgdatadir wayland-protocols`
|
||||||
|
|
||||||
|
|
||||||
|
all: dwl-bar
|
||||||
|
dwl-bar: $(FILES) $(OBJS)
|
||||||
|
$(CC) $^ $(BARLIBS) $(BARCFLAGS) -o $@
|
||||||
|
$(SRCDIR)/%.o: $(SRCDIR)/%.c $(SRCDIR)/%.h
|
||||||
|
$(CC) -c $< $(BARLIBS) $(BARCFLAGS) -o $@
|
||||||
|
|
||||||
|
$(SRCDIR)/xdg-shell-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) client-header \
|
||||||
|
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
||||||
|
$(SRCDIR)/xdg-shell-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
||||||
|
|
||||||
|
$(SRCDIR)/wlr-layer-shell-unstable-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) client-header \
|
||||||
|
protocols/wlr-layer-shell-unstable-v1.xml $@
|
||||||
|
$(SRCDIR)/wlr-layer-shell-unstable-v1-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/wlr-layer-shell-unstable-v1.xml $@
|
||||||
|
|
||||||
|
$(SRCDIR)/dwl-ipc-unstable-v2-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) client-header \
|
||||||
|
protocols/dwl-ipc-unstable-v2.xml $@
|
||||||
|
$(SRCDIR)/dwl-ipc-unstable-v2-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/dwl-ipc-unstable-v2.xml $@
|
||||||
|
|
||||||
|
$(SRCDIR)/config.h:
|
||||||
|
cp src/config.def.h $@
|
||||||
|
|
||||||
|
dev: clean $(SRCDIR)/config.h $(OBJS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f dwl-bar src/config.h src/*.o src/*-protocol.*
|
||||||
|
|
||||||
|
dist: clean
|
||||||
|
mkdir -p dwl-bar-$(VERSION)
|
||||||
|
cp -R LICENSE Makefile README.md dwl-bar.1 src protocols \
|
||||||
|
dwl-bar-$(VERSION)
|
||||||
|
tar -caf dwl-bar-$(VERSION).tar.gz dwl-bar-$(VERSION)
|
||||||
|
rm -rf dwl-bar-$(VERSION)
|
||||||
|
|
||||||
|
install: dwl-bar
|
||||||
|
mkdir -p $(PREFIX)/bin
|
||||||
|
cp -f dwl-bar $(PREFIX)/bin
|
||||||
|
chmod 755 $(PREFIX)/bin/dwl-bar
|
||||||
|
mkdir -p $(MANDIR)/man1
|
||||||
|
cp -f dwl-bar.1 $(MANDIR)/man1
|
||||||
|
chmod 644 $(MANDIR)/man1/dwl-bar.1
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm -f $(PREFIX)/bin/dwl-bar $(MANDIR)/man1/dwl-bar.1
|
||||||
|
|
||||||
|
# end
|
28
user/.config/suckless/dwl-bar/README.md
Normal file
28
user/.config/suckless/dwl-bar/README.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# dwl-bar
|
||||||
|
dwm-like bar for dwl
|
||||||
|
|
||||||
|
I believe dwl-bar provides a more dwm-like experience out of the box than other bars like somebar.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
I'm not sure what the package names will be for your distrobution, so just make sure these are generally what you have.
|
||||||
|
+ make
|
||||||
|
+ pango
|
||||||
|
+ cairo
|
||||||
|
+ wayland
|
||||||
|
+ wayland-protocols
|
||||||
|
|
||||||
|
## Compile
|
||||||
|
Compile with `make`, install with `make install`, uninstall `make uninstall`.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
Like most suckless-like software, configuration is done through `src/config.def.h` modify it to your heart's content. dwl-bar is compatible with [someblocks](https://sr.ht/~raphi/someblocks/) for status.
|
||||||
|
|
||||||
|
If you want dwl-bar to control dwl (via mouse gestures primarily) you may want to apply the [ipc](https://github.com/MadcowOG/dwl-bar/wiki/ipc) patch.
|
||||||
|
**However, do note that you will also need to apply the [ipc](https://github.com/djpohly/dwl/wiki/ipc) patch for dwl.**
|
||||||
|
|
||||||
|
For more information about patching see the [hacking](https://suckless.org/hacking/) article from suckless and the [wiki](https://github.com/MadcowOG/dwl-bar/wiki) for available patches.
|
||||||
|
|
||||||
|
## Thanks
|
||||||
|
Thanks to [raphi](https://sr.ht/~raphi/) for [somebar](https://sr.ht/~raphi/somebar/) this project borrows from it.
|
||||||
|
The ipc protocol is also just the ipc patch in [somebar's `contrib/`](https://git.sr.ht/~raphi/somebar/tree/master/item/contrib/ipc.patch).
|
||||||
|
Thanks to the swaybar contriutors and [Drew DeVault](https://github.com/ddevault) for [swaybar](https://github.com/swaywm/sway/tree/master/swaybar), I basically did a lot of this project with it open in browser.
|
33
user/.config/suckless/dwl-bar/dwl-bar.1
Normal file
33
user/.config/suckless/dwl-bar/dwl-bar.1
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
.TH dwl-bar 1
|
||||||
|
.SH NAME
|
||||||
|
dwl-bar \- dwm-like bar for dwl
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B dwl-bar
|
||||||
|
.RB [\-v]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
dwl-bar is a status bar for dwl.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.B \-h
|
||||||
|
prints help message and exits.
|
||||||
|
.TP
|
||||||
|
.B \-v
|
||||||
|
prints version and exits.
|
||||||
|
.TP
|
||||||
|
.B \-l
|
||||||
|
initiates logging
|
||||||
|
.SH USAGE
|
||||||
|
.SS Status
|
||||||
|
.TP
|
||||||
|
.B $XDG_RUNTIME_DIR/dwl-bar-x
|
||||||
|
can be written into with the prefix 'status' to change the bar's status.
|
||||||
|
.SS Mouse Commands
|
||||||
|
.TP
|
||||||
|
.B Middle Button
|
||||||
|
Click the status label to spawn a terminal.
|
||||||
|
.SH CUSTOMIZATION
|
||||||
|
dwl-bar is customized through config.def.h and (re)compiling.
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR dwl (1)
|
||||||
|
.SH BUGS
|
||||||
|
Please open an issue at https://github.com/MacowOG/dwl-bar if you encounter any bugs.
|
754
user/.config/suckless/dwl-bar/patches/ipcv2.patch
Normal file
754
user/.config/suckless/dwl-bar/patches/ipcv2.patch
Normal file
|
@ -0,0 +1,754 @@
|
||||||
|
From 6225c603eea68c4f3b7b2864e1a71cca3d6db001 Mon Sep 17 00:00:00 2001
|
||||||
|
From: MadcowOG <N/A>
|
||||||
|
Date: Fri, 28 Apr 2023 01:58:39 -0700
|
||||||
|
Subject: [PATCH] Implemented dwl-ipc-v2
|
||||||
|
|
||||||
|
---
|
||||||
|
Makefile | 16 +-
|
||||||
|
protocols/dwl-ipc-unstable-v2.xml | 181 ++++++++++++++++++++++
|
||||||
|
src/config.def.h | 6 +
|
||||||
|
src/main.c | 247 +++++++++++++-----------------
|
||||||
|
src/main.h | 7 +-
|
||||||
|
src/user.c | 24 +++
|
||||||
|
src/user.h | 4 +
|
||||||
|
7 files changed, 334 insertions(+), 151 deletions(-)
|
||||||
|
create mode 100644 protocols/dwl-ipc-unstable-v2.xml
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 9e30fa7..da7ab44 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -19,6 +19,8 @@ FILES = $(SRCDIR)/main.c $(SRCDIR)/main.h $(SRCDIR)/log.c $(SRCDIR)/log.h \
|
||||||
|
$(SRCDIR)/bar.c $(SRCDIR)/bar.h $(SRCDIR)/config.h
|
||||||
|
OBJS = $(SRCDIR)/xdg-output-unstable-v1-protocol.o $(SRCDIR)/xdg-shell-protocol.o \
|
||||||
|
$(SRCDIR)/wlr-layer-shell-unstable-v1-protocol.o
|
||||||
|
+OBJS := $(filter-out $(SRCDIR)/xdg-output-unstable-v1-protocol.o,$(OBJS))
|
||||||
|
+OBJS += $(SRCDIR)/dwl-ipc-unstable-v2-protocol.o
|
||||||
|
|
||||||
|
## Compile Flags
|
||||||
|
CC = gcc
|
||||||
|
@@ -42,13 +44,6 @@ $(SRCDIR)/xdg-shell-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
||||||
|
|
||||||
|
-$(SRCDIR)/xdg-output-unstable-v1-protocol.h:
|
||||||
|
- $(WAYLAND_SCANNER) client-header \
|
||||||
|
- $(WAYLAND_PROTOCOLS)/unstable/xdg-output/xdg-output-unstable-v1.xml $@
|
||||||
|
-$(SRCDIR)/xdg-output-unstable-v1-protocol.c:
|
||||||
|
- $(WAYLAND_SCANNER) private-code \
|
||||||
|
- $(WAYLAND_PROTOCOLS)/unstable/xdg-output/xdg-output-unstable-v1.xml $@
|
||||||
|
-
|
||||||
|
$(SRCDIR)/wlr-layer-shell-unstable-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) client-header \
|
||||||
|
protocols/wlr-layer-shell-unstable-v1.xml $@
|
||||||
|
@@ -56,6 +51,13 @@ $(SRCDIR)/wlr-layer-shell-unstable-v1-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/wlr-layer-shell-unstable-v1.xml $@
|
||||||
|
|
||||||
|
+$(SRCDIR)/dwl-ipc-unstable-v2-protocol.h:
|
||||||
|
+ $(WAYLAND_SCANNER) client-header \
|
||||||
|
+ protocols/dwl-ipc-unstable-v2.xml $@
|
||||||
|
+$(SRCDIR)/dwl-ipc-unstable-v2-protocol.c:
|
||||||
|
+ $(WAYLAND_SCANNER) private-code \
|
||||||
|
+ protocols/dwl-ipc-unstable-v2.xml $@
|
||||||
|
+
|
||||||
|
$(SRCDIR)/config.h:
|
||||||
|
cp src/config.def.h $@
|
||||||
|
|
||||||
|
diff --git a/protocols/dwl-ipc-unstable-v2.xml b/protocols/dwl-ipc-unstable-v2.xml
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..0a6e7e5
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/protocols/dwl-ipc-unstable-v2.xml
|
||||||
|
@@ -0,0 +1,181 @@
|
||||||
|
+<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
+<!--
|
||||||
|
+This is largely ripped from somebar's ipc patchset; just with some personal modifications.
|
||||||
|
+I would probably just submit raphi's patchset but I don't think that would be polite.
|
||||||
|
+-->
|
||||||
|
+<protocol name="dwl_ipc_unstable_v2">
|
||||||
|
+ <description summary="inter-proccess-communication about dwl's state">
|
||||||
|
+ This protocol allows clients to update and get updates from dwl.
|
||||||
|
+
|
||||||
|
+ Warning! The protocol described in this file is experimental and
|
||||||
|
+ backward incompatible changes may be made. Backward compatible
|
||||||
|
+ changes may be added together with the corresponding interface
|
||||||
|
+ version bump.
|
||||||
|
+ Backward incompatible changes are done by bumping the version
|
||||||
|
+ number in the protocol and interface names and resetting the
|
||||||
|
+ interface version. Once the protocol is to be declared stable,
|
||||||
|
+ the 'z' prefix and the version number in the protocol and
|
||||||
|
+ interface names are removed and the interface version number is
|
||||||
|
+ reset.
|
||||||
|
+ </description>
|
||||||
|
+
|
||||||
|
+ <interface name="zdwl_ipc_manager_v2" version="2">
|
||||||
|
+ <description summary="manage dwl state">
|
||||||
|
+ This interface is exposed as a global in wl_registry.
|
||||||
|
+
|
||||||
|
+ Clients can use this interface to get a dwl_ipc_output.
|
||||||
|
+ After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events.
|
||||||
|
+ The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client.
|
||||||
|
+ </description>
|
||||||
|
+
|
||||||
|
+ <request name="release" type="destructor">
|
||||||
|
+ <description summary="release dwl_ipc_manager">
|
||||||
|
+ Indicates that the client will not the dwl_ipc_manager object anymore.
|
||||||
|
+ Objects created through this instance are not affected.
|
||||||
|
+ </description>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <request name="get_output">
|
||||||
|
+ <description summary="get a dwl_ipc_outout for a wl_output">
|
||||||
|
+ Get a dwl_ipc_outout for the specified wl_output.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/>
|
||||||
|
+ <arg name="output" type="object" interface="wl_output"/>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <event name="tags">
|
||||||
|
+ <description summary="Announces tag amount">
|
||||||
|
+ This event is sent after binding.
|
||||||
|
+ A roundtrip after binding guarantees the client recieved all tags.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="amount" type="uint"/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="layout">
|
||||||
|
+ <description summary="Announces a layout">
|
||||||
|
+ This event is sent after binding.
|
||||||
|
+ A roundtrip after binding guarantees the client recieved all layouts.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="name" type="string"/>
|
||||||
|
+ </event>
|
||||||
|
+ </interface>
|
||||||
|
+
|
||||||
|
+ <interface name="zdwl_ipc_output_v2" version="2">
|
||||||
|
+ <description summary="control dwl output">
|
||||||
|
+ Observe and control a dwl output.
|
||||||
|
+
|
||||||
|
+ Events are double-buffered:
|
||||||
|
+ Clients should cache events and redraw when a dwl_ipc_output.frame event is sent.
|
||||||
|
+
|
||||||
|
+ Request are not double-buffered:
|
||||||
|
+ The compositor will update immediately upon request.
|
||||||
|
+ </description>
|
||||||
|
+
|
||||||
|
+ <enum name="tag_state">
|
||||||
|
+ <entry name="none" value="0" summary="no state"/>
|
||||||
|
+ <entry name="active" value="1" summary="tag is active"/>
|
||||||
|
+ <entry name="urgent" value="2" summary="tag has at least one urgent client"/>
|
||||||
|
+ </enum>
|
||||||
|
+
|
||||||
|
+ <request name="release" type="destructor">
|
||||||
|
+ <description summary="release dwl_ipc_outout">
|
||||||
|
+ Indicates to that the client no longer needs this dwl_ipc_output.
|
||||||
|
+ </description>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <event name="toggle_visibility">
|
||||||
|
+ <description summary="Toggle client visibilty">
|
||||||
|
+ Indicates the client should hide or show themselves.
|
||||||
|
+ If the client is visible then hide, if hidden then show.
|
||||||
|
+ </description>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="active">
|
||||||
|
+ <description summary="Update the selected output.">
|
||||||
|
+ Indicates if the output is active. Zero is invalid, nonzero is valid.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="active" type="uint"/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="tag">
|
||||||
|
+ <description summary="Update the state of a tag.">
|
||||||
|
+ Indicates that a tag has been updated.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="tag" type="uint" summary="Index of the tag"/>
|
||||||
|
+ <arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/>
|
||||||
|
+ <arg name="clients" type="uint" summary="The number of clients in the tag."/>
|
||||||
|
+ <arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="layout">
|
||||||
|
+ <description summary="Update the layout.">
|
||||||
|
+ Indicates a new layout is selected.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="layout" type="uint" summary="Index of the layout."/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="title">
|
||||||
|
+ <description summary="Update the title.">
|
||||||
|
+ Indicates the title has changed.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="title" type="string" summary="The new title name."/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="appid" since="1">
|
||||||
|
+ <description summary="Update the appid.">
|
||||||
|
+ Indicates the appid has changed.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="appid" type="string" summary="The new appid."/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="layout_symbol" since="1">
|
||||||
|
+ <description summary="Update the current layout symbol">
|
||||||
|
+ Indicates the layout has changed. Since layout symbols are dynamic.
|
||||||
|
+ As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying.
|
||||||
|
+ You can ignore the zdwl_ipc_output.layout event.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="layout" type="string" summary="The new layout"/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="frame">
|
||||||
|
+ <description summary="The update sequence is done.">
|
||||||
|
+ Indicates that a sequence of status updates have finished and the client should redraw.
|
||||||
|
+ </description>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <request name="set_tags">
|
||||||
|
+ <description summary="Set the active tags of this output"/>
|
||||||
|
+ <arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/>
|
||||||
|
+ <arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <request name="set_client_tags">
|
||||||
|
+ <description summary="Set the tags of the focused client.">
|
||||||
|
+ The tags are updated as follows:
|
||||||
|
+ new_tags = (current_tags AND and_tags) XOR xor_tags
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="and_tags" type="uint"/>
|
||||||
|
+ <arg name="xor_tags" type="uint"/>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <request name="set_layout">
|
||||||
|
+ <description summary="Set the layout of this output"/>
|
||||||
|
+ <arg name="index" type="uint" summary="index of a layout recieved by dwl_ipc_manager.layout"/>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <!-- Version 2 -->
|
||||||
|
+ <event name="fullscreen" since="2">
|
||||||
|
+ <description summary="Update fullscreen status">
|
||||||
|
+ Indicates if the selected client on this output is fullscreen.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="is_fullscreen" type="uint" summary="If the selected client is fullscreen. Nonzero is valid, zero invalid"/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="floating" since="2">
|
||||||
|
+ <description summary="Update the floating status">
|
||||||
|
+ Indicates if the selected client on this output is floating.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="is_floating" type="uint" summary="If the selected client is floating. Nonzero is valid, zero invalid"/>
|
||||||
|
+ </event>
|
||||||
|
+ </interface>
|
||||||
|
+</protocol>
|
||||||
|
diff --git a/src/config.def.h b/src/config.def.h
|
||||||
|
index ce34395..cc074a6 100644
|
||||||
|
--- a/src/config.def.h
|
||||||
|
+++ b/src/config.def.h
|
||||||
|
@@ -5,6 +5,7 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
|
||||||
|
+static const int show_bar = 1;
|
||||||
|
static const int bar_top = 1; /* Boolean value, non-zero is true. If not top then bottom */
|
||||||
|
static const int status_on_active = 1; /* Display the status on active monitor only. If not then on all. */
|
||||||
|
static const char *font = "Monospace 10";
|
||||||
|
@@ -45,7 +46,12 @@ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||||
|
*/
|
||||||
|
static const Binding bindings[] = {
|
||||||
|
/* Click Location, button, callback, bypass, arguments */
|
||||||
|
+ { Click_Layout, BTN_LEFT, layout, 1, {.ui = 0} },
|
||||||
|
+ { Click_Layout, BTN_RIGHT, layout, 1, {.ui = 1} },
|
||||||
|
{ Click_Status, BTN_MIDDLE, spawn, 0, {.v = terminal } },
|
||||||
|
+ { Click_Tag, BTN_MIDDLE, tag, 0, {0} },
|
||||||
|
+ { Click_Tag, BTN_RIGHT, toggle_view, 0, {0} },
|
||||||
|
+ { Click_Tag, BTN_LEFT, view, 0, {0} },
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONFIG_H_
|
||||||
|
diff --git a/src/main.c b/src/main.c
|
||||||
|
index f04d6b4..1acdd71 100644
|
||||||
|
--- a/src/main.c
|
||||||
|
+++ b/src/main.c
|
||||||
|
@@ -1,11 +1,12 @@
|
||||||
|
#include "bar.h"
|
||||||
|
+#include "config.h"
|
||||||
|
+#include "dwl-ipc-unstable-v2-protocol.h"
|
||||||
|
#include "event.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "input.h"
|
||||||
|
-#include "xdg-output-unstable-v1-protocol.h"
|
||||||
|
#include "xdg-shell-protocol.h"
|
||||||
|
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||||
|
#include <math.h>
|
||||||
|
@@ -33,7 +34,6 @@ static void fifo_handle(const char *line);
|
||||||
|
static void fifo_in(int fd, short mask, void *data);
|
||||||
|
static void fifo_setup(void);
|
||||||
|
static void monitor_destroy(struct Monitor *monitor);
|
||||||
|
-static struct Monitor *monitor_from_name(const char *name);
|
||||||
|
struct Monitor *monitor_from_surface(const struct wl_surface *surface);
|
||||||
|
static void monitor_initialize(struct Monitor *monitor);
|
||||||
|
static void monitor_update(struct Monitor *monitor);
|
||||||
|
@@ -44,19 +44,31 @@ static void registry_global_remove(void *data, struct wl_registry *registry, uin
|
||||||
|
static void run(void);
|
||||||
|
static void set_cloexec(int fd);
|
||||||
|
static void setup(void);
|
||||||
|
-static void stdin_handle(const char *line);
|
||||||
|
-static void stdin_in(int fd, short mask, void *data);
|
||||||
|
static void sigaction_handler(int _);
|
||||||
|
-static void xdg_output_name(void *data, struct zxdg_output_v1 *output, const char *name);
|
||||||
|
static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial);
|
||||||
|
+static void zdwl_ipc_manager_layout(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, const char *name);
|
||||||
|
+static void zdwl_ipc_manager_tags(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, uint32_t amount);
|
||||||
|
+static void zdwl_ipc_output_active(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t active);
|
||||||
|
+static void zdwl_ipc_output_appid(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *appid);
|
||||||
|
+static void zdwl_ipc_output_floating(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_floating);
|
||||||
|
+static void zdwl_ipc_output_frame(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2);
|
||||||
|
+static void zdwl_ipc_output_fullscreen(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_fullscreen);
|
||||||
|
+static void zdwl_ipc_output_layout(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t layout);
|
||||||
|
+static void zdwl_ipc_output_layout_symbol(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *layout);
|
||||||
|
+static void zdwl_ipc_output_tag(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2,
|
||||||
|
+ uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused);
|
||||||
|
+static void zdwl_ipc_output_title(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *title);
|
||||||
|
+static void zdwl_ipc_output_toggle_visibility(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2);
|
||||||
|
|
||||||
|
static struct xdg_wm_base *base;
|
||||||
|
struct wl_compositor *compositor;
|
||||||
|
static struct wl_display *display;
|
||||||
|
static int display_fd;
|
||||||
|
+static struct zdwl_ipc_manager_v2 *dwl_manager = NULL;
|
||||||
|
static struct Events *events;
|
||||||
|
static int fifo_fd;
|
||||||
|
static char *fifo_path;
|
||||||
|
+int layoutcount;
|
||||||
|
static struct wl_list monitors; // struct Monitor*
|
||||||
|
static struct zxdg_output_manager_v1 *output_manager;
|
||||||
|
static const struct wl_registry_listener registry_listener = {
|
||||||
|
@@ -68,12 +80,26 @@ static struct wl_list seats; // struct Seat*
|
||||||
|
static int self_pipe[2];
|
||||||
|
struct zwlr_layer_shell_v1 *shell;
|
||||||
|
struct wl_shm *shm;
|
||||||
|
-static const struct zxdg_output_v1_listener xdg_output_listener = {
|
||||||
|
- .name = xdg_output_name,
|
||||||
|
-};
|
||||||
|
+static int tagcount;
|
||||||
|
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
||||||
|
.ping = xdg_wm_base_ping,
|
||||||
|
};
|
||||||
|
+static const struct zdwl_ipc_manager_v2_listener zdwl_manager_listener = {
|
||||||
|
+ .layout = zdwl_ipc_manager_layout,
|
||||||
|
+ .tags = zdwl_ipc_manager_tags,
|
||||||
|
+};
|
||||||
|
+static const struct zdwl_ipc_output_v2_listener zdwl_output_listener = {
|
||||||
|
+ .active = zdwl_ipc_output_active,
|
||||||
|
+ .appid = zdwl_ipc_output_appid,
|
||||||
|
+ .floating = zdwl_ipc_output_floating,
|
||||||
|
+ .frame = zdwl_ipc_output_frame,
|
||||||
|
+ .fullscreen = zdwl_ipc_output_fullscreen,
|
||||||
|
+ .layout = zdwl_ipc_output_layout,
|
||||||
|
+ .layout_symbol = zdwl_ipc_output_layout_symbol,
|
||||||
|
+ .tag = zdwl_ipc_output_tag,
|
||||||
|
+ .title = zdwl_ipc_output_title,
|
||||||
|
+ .toggle_visibility = zdwl_ipc_output_toggle_visibility,
|
||||||
|
+};
|
||||||
|
|
||||||
|
void check_global(void *global, const char *name) {
|
||||||
|
if (global)
|
||||||
|
@@ -84,7 +110,7 @@ void check_global(void *global, const char *name) {
|
||||||
|
void check_globals(void) {
|
||||||
|
check_global(base, "xdg_wm_base");
|
||||||
|
check_global(compositor, "wl_compositor");
|
||||||
|
- check_global(output_manager, "zxdg_output_manager_v1");
|
||||||
|
+ check_global(dwl_manager, "zdwl_ipc_manager_v2");
|
||||||
|
check_global(shell, "zwlr_layer_shell_v1");
|
||||||
|
check_global(shm, "wl_shm");
|
||||||
|
}
|
||||||
|
@@ -95,8 +121,8 @@ void cleanup(void) {
|
||||||
|
close(fifo_fd);
|
||||||
|
unlink(fifo_path);
|
||||||
|
free(fifo_path);
|
||||||
|
- zxdg_output_manager_v1_destroy(output_manager);
|
||||||
|
zwlr_layer_shell_v1_destroy(shell);
|
||||||
|
+ zdwl_ipc_manager_v2_destroy(dwl_manager);
|
||||||
|
wl_shm_destroy(shm);
|
||||||
|
events_destroy(events);
|
||||||
|
log_destroy();
|
||||||
|
@@ -196,25 +222,16 @@ void monitor_destroy(struct Monitor *monitor) {
|
||||||
|
if (!monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
- free(monitor->xdg_name);
|
||||||
|
if (wl_output_get_version(monitor->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
|
||||||
|
wl_output_release(monitor->wl_output);
|
||||||
|
+ wl_output_release(monitor->wl_output);
|
||||||
|
+ zdwl_ipc_output_v2_destroy(monitor->dwl_output);
|
||||||
|
list_elements_destroy(monitor->hotspots, free);
|
||||||
|
pipeline_destroy(monitor->pipeline);
|
||||||
|
bar_destroy(monitor->bar);
|
||||||
|
free(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
-struct Monitor *monitor_from_name(const char *name) {
|
||||||
|
- struct Monitor *pos;
|
||||||
|
- wl_list_for_each(pos, &monitors, link) {
|
||||||
|
- if (STRING_EQUAL(name, pos->xdg_name))
|
||||||
|
- return pos;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return NULL;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
struct Monitor *monitor_from_surface(const struct wl_surface *surface) {
|
||||||
|
struct Monitor *pos;
|
||||||
|
wl_list_for_each(pos, &monitors, link) {
|
||||||
|
@@ -228,11 +245,12 @@ struct Monitor *monitor_from_surface(const struct wl_surface *surface) {
|
||||||
|
void monitor_initialize(struct Monitor *monitor) {
|
||||||
|
if (!monitor) return;
|
||||||
|
|
||||||
|
+ monitor->desired_visibility = show_bar;
|
||||||
|
monitor->hotspots = list_create(1);
|
||||||
|
monitor->pipeline = pipeline_create();
|
||||||
|
monitor->bar = bar_create(monitor->hotspots, monitor->pipeline);
|
||||||
|
if (!monitor->pipeline || !monitor->bar)
|
||||||
|
- panic("Failed to create a pipline or bar for monitor: %s", monitor->xdg_name);
|
||||||
|
+ panic("Failed to create a pipline or bar for a monitor");
|
||||||
|
monitor_update(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -240,7 +258,7 @@ void monitor_update(struct Monitor *monitor) {
|
||||||
|
if (!monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
- if (!pipeline_is_visible(monitor->pipeline)) {
|
||||||
|
+ if (!pipeline_is_visible(monitor->pipeline) && monitor->desired_visibility) {
|
||||||
|
pipeline_show(monitor->pipeline, monitor->wl_output);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@@ -267,16 +285,14 @@ void registry_global_add(void *data, struct wl_registry *registry, uint32_t name
|
||||||
|
struct Monitor *monitor = ecalloc(1, sizeof(*monitor));
|
||||||
|
monitor->wl_output = wl_registry_bind(registry, name, &wl_output_interface, 1);
|
||||||
|
monitor->wl_name = name;
|
||||||
|
- monitor->xdg_name = NULL;
|
||||||
|
- monitor->xdg_output = NULL;
|
||||||
|
+ monitor->dwl_output = NULL;
|
||||||
|
|
||||||
|
wl_list_insert(&monitors, &monitor->link);
|
||||||
|
|
||||||
|
- if (!output_manager)
|
||||||
|
- return;
|
||||||
|
+ if (!dwl_manager) return;
|
||||||
|
|
||||||
|
- monitor->xdg_output = zxdg_output_manager_v1_get_xdg_output(output_manager, monitor->wl_output);
|
||||||
|
- zxdg_output_v1_add_listener(monitor->xdg_output, &xdg_output_listener, monitor);
|
||||||
|
+ monitor->dwl_output = zdwl_ipc_manager_v2_get_output(dwl_manager, monitor->wl_output);
|
||||||
|
+ zdwl_ipc_output_v2_add_listener(monitor->dwl_output, &zdwl_output_listener, monitor);
|
||||||
|
|
||||||
|
if (!running) return;
|
||||||
|
monitor_initialize(monitor);
|
||||||
|
@@ -296,17 +312,16 @@ void registry_global_add(void *data, struct wl_registry *registry, uint32_t name
|
||||||
|
base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 2);
|
||||||
|
xdg_wm_base_add_listener(base, &xdg_wm_base_listener, NULL);
|
||||||
|
}
|
||||||
|
- else if (STRING_EQUAL(interface, zxdg_output_manager_v1_interface.name)) {
|
||||||
|
- output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, 3);
|
||||||
|
+ else if (STRING_EQUAL(interface, zdwl_ipc_manager_v2_interface.name)) {
|
||||||
|
+ dwl_manager = wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 2);
|
||||||
|
+ zdwl_ipc_manager_v2_add_listener(dwl_manager, &zdwl_manager_listener, NULL);
|
||||||
|
|
||||||
|
- struct Monitor *pos;
|
||||||
|
- wl_list_for_each(pos, &monitors, link) {
|
||||||
|
- // If the monitor is getting or has the xdg_name.
|
||||||
|
- if (pos->xdg_output || pos->xdg_name)
|
||||||
|
- continue;
|
||||||
|
+ struct Monitor *monitor;
|
||||||
|
+ wl_list_for_each(monitor, &monitors, link) {
|
||||||
|
+ if (monitor->dwl_output) continue;
|
||||||
|
|
||||||
|
- pos->xdg_output = zxdg_output_manager_v1_get_xdg_output(output_manager, pos->wl_output);
|
||||||
|
- zxdg_output_v1_add_listener(pos->xdg_output, &xdg_output_listener, pos);
|
||||||
|
+ monitor->dwl_output = zdwl_ipc_manager_v2_get_output(dwl_manager, monitor->wl_output);
|
||||||
|
+ zdwl_ipc_output_v2_add_listener(monitor->dwl_output, &zdwl_output_listener, monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (STRING_EQUAL(interface, zwlr_layer_shell_v1_interface.name))
|
||||||
|
@@ -387,6 +402,9 @@ void setup(void) {
|
||||||
|
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
+ if (tagcount != LENGTH(tags))
|
||||||
|
+ panic("We do not have the same amount of tags as dwl! Please check config.def.h!");
|
||||||
|
+
|
||||||
|
struct Monitor *monitor;
|
||||||
|
wl_list_for_each(monitor, &monitors, link) {
|
||||||
|
monitor_initialize(monitor);
|
||||||
|
@@ -398,128 +416,75 @@ void setup(void) {
|
||||||
|
events = events_create();
|
||||||
|
events_add(events, display_fd, POLLIN, NULL, display_in);
|
||||||
|
events_add(events, self_pipe[0], POLLIN, NULL, pipe_in);
|
||||||
|
- events_add(events, STDIN_FILENO, POLLIN, NULL, stdin_in);
|
||||||
|
events_add(events, fifo_fd, POLLIN, NULL, fifo_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void stdin_handle(const char *line) {
|
||||||
|
- if (!line)
|
||||||
|
- return;
|
||||||
|
+void sigaction_handler(int _) {
|
||||||
|
+ if (write(self_pipe[1], "0", 1) < 0)
|
||||||
|
+ panic("sigaction_handler");
|
||||||
|
+}
|
||||||
|
|
||||||
|
- char *name, *command;
|
||||||
|
- struct Monitor *monitor;
|
||||||
|
- unsigned long loc = 0; /* Keep track of where we are in the string `line` */
|
||||||
|
+void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) {
|
||||||
|
+ xdg_wm_base_pong(xdg_wm_base, serial);
|
||||||
|
+}
|
||||||
|
|
||||||
|
- name = to_delimiter(line, &loc, ' ');
|
||||||
|
- command = to_delimiter(line, &loc, ' ');
|
||||||
|
- monitor = monitor_from_name(name);
|
||||||
|
- if (!monitor) {
|
||||||
|
- free(name);
|
||||||
|
- free(command);
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
- free(name);
|
||||||
|
-
|
||||||
|
- if (STRING_EQUAL(command, "title")) {
|
||||||
|
- char *title = to_delimiter(line, &loc, '\n');
|
||||||
|
- if (*title == '\0') {
|
||||||
|
- bar_set_title(monitor->bar, "");
|
||||||
|
- } else
|
||||||
|
- bar_set_title(monitor->bar, title);
|
||||||
|
- free(title);
|
||||||
|
- } else if (STRING_EQUAL(command, "appid")) {
|
||||||
|
- /* Do nothing */
|
||||||
|
- } else if (STRING_EQUAL(command, "floating")) {
|
||||||
|
- char *is_floating = to_delimiter(line, &loc, '\n');
|
||||||
|
- if (*is_floating == '1')
|
||||||
|
- bar_set_floating(monitor->bar, 1);
|
||||||
|
- else
|
||||||
|
- bar_set_floating(monitor->bar, 0);
|
||||||
|
- free(is_floating);
|
||||||
|
- } else if (STRING_EQUAL(command, "fullscreen")) {
|
||||||
|
- /* Do nothing */
|
||||||
|
- } else if (STRING_EQUAL(command, "selmon")) {
|
||||||
|
- char *selmon = to_delimiter(line, &loc, '\n');
|
||||||
|
- if (*selmon == '1')
|
||||||
|
- bar_set_active(monitor->bar, 1);
|
||||||
|
- else
|
||||||
|
- bar_set_active(monitor->bar, 0);
|
||||||
|
- free(selmon);
|
||||||
|
- } else if (STRING_EQUAL(command, "tags")) {
|
||||||
|
- char *occupied_str, *tags_str, *clients_str, *urgent_str;
|
||||||
|
- int occupied, _tags, clients, urgent, i, tag_mask, state;
|
||||||
|
-
|
||||||
|
- occupied_str = to_delimiter(line, &loc, ' ');
|
||||||
|
- tags_str = to_delimiter(line, &loc, ' ');
|
||||||
|
- clients_str = to_delimiter(line, &loc, ' ');
|
||||||
|
- urgent_str = to_delimiter(line, &loc, ' ');
|
||||||
|
-
|
||||||
|
- occupied = atoi(occupied_str);
|
||||||
|
- _tags = atoi(tags_str);
|
||||||
|
- clients = atoi(clients_str);
|
||||||
|
- urgent = atoi(urgent_str);
|
||||||
|
-
|
||||||
|
- for (i = 0; i < LENGTH(tags); i++) {
|
||||||
|
- state = Tag_None;
|
||||||
|
- tag_mask = 1 << i;
|
||||||
|
-
|
||||||
|
- if (_tags & tag_mask)
|
||||||
|
- state |= Tag_Active;
|
||||||
|
- if (urgent & tag_mask)
|
||||||
|
- state |= Tag_Urgent;
|
||||||
|
-
|
||||||
|
- bar_set_tag(monitor->bar, i, state, occupied & tag_mask ? 1 : 0, clients & tag_mask ? 1 : 0);
|
||||||
|
- }
|
||||||
|
+void zdwl_ipc_manager_layout(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, const char *name) {
|
||||||
|
+ layoutcount++;
|
||||||
|
+}
|
||||||
|
|
||||||
|
- free(occupied_str);
|
||||||
|
- free(tags_str);
|
||||||
|
- free(clients_str);
|
||||||
|
- free(urgent_str);
|
||||||
|
- } else if (STRING_EQUAL(command, "layout")) {
|
||||||
|
- char *layout = to_delimiter(line, &loc, '\n');
|
||||||
|
- bar_set_layout(monitor->bar, layout);
|
||||||
|
- free(layout);
|
||||||
|
- }
|
||||||
|
+void zdwl_ipc_manager_tags(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, uint32_t amount) {
|
||||||
|
+ tagcount = amount;
|
||||||
|
+}
|
||||||
|
|
||||||
|
- free(command);
|
||||||
|
+void zdwl_ipc_output_active(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t active) {
|
||||||
|
+ struct Monitor *monitor = data;
|
||||||
|
+ bar_set_active(monitor->bar, active);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void zdwl_ipc_output_appid(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *appid) {
|
||||||
|
+ /* Nop */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void zdwl_ipc_output_floating(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_floating) {
|
||||||
|
+ struct Monitor *monitor = data;
|
||||||
|
+ bar_set_floating(monitor->bar, is_floating);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void zdwl_ipc_output_frame(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2) {
|
||||||
|
+ struct Monitor *monitor = data;
|
||||||
|
monitor_update(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void stdin_in(int fd, short mask, void *data) {
|
||||||
|
- if (mask & (POLLHUP | POLLERR)) {
|
||||||
|
- running = 0;
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
+void zdwl_ipc_output_fullscreen(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_fullscreen) {
|
||||||
|
+ /* Nop */
|
||||||
|
+}
|
||||||
|
|
||||||
|
- int new_fd = dup(fd);
|
||||||
|
- FILE *stdin_file = fdopen(new_fd, "r");
|
||||||
|
- char *buffer = NULL;
|
||||||
|
- size_t size = 0;
|
||||||
|
- while(1) {
|
||||||
|
- if (getline(&buffer, &size, stdin_file) == -1)
|
||||||
|
- break;
|
||||||
|
+void zdwl_ipc_output_layout(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t layout) {
|
||||||
|
+ struct Monitor *monitor = data;
|
||||||
|
+ monitor->layout = layout;
|
||||||
|
+}
|
||||||
|
|
||||||
|
- stdin_handle(buffer);
|
||||||
|
- }
|
||||||
|
- free(buffer);
|
||||||
|
- fclose(stdin_file);
|
||||||
|
- close(new_fd);
|
||||||
|
+void zdwl_ipc_output_layout_symbol(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *layout) {
|
||||||
|
+ struct Monitor *monitor = data;
|
||||||
|
+ bar_set_layout(monitor->bar, layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void sigaction_handler(int _) {
|
||||||
|
- if (write(self_pipe[1], "0", 1) < 0)
|
||||||
|
- panic("sigaction_handler");
|
||||||
|
+void zdwl_ipc_output_tag(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) {
|
||||||
|
+ struct Monitor *monitor = data;
|
||||||
|
+ bar_set_tag(monitor->bar, tag, state, clients ? 1 : 0, focused);
|
||||||
|
+ monitor->tags = (state & ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE) ? monitor->tags | (1 << tag) : monitor->tags & ~(1 << tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void xdg_output_name(void *data, struct zxdg_output_v1 *output, const char *name) {
|
||||||
|
+void zdwl_ipc_output_title(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *title) {
|
||||||
|
struct Monitor *monitor = data;
|
||||||
|
- monitor->xdg_name = strdup(name);
|
||||||
|
- zxdg_output_v1_destroy(output);
|
||||||
|
- monitor->xdg_output = NULL;
|
||||||
|
+ bar_set_title(monitor->bar, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) {
|
||||||
|
- xdg_wm_base_pong(xdg_wm_base, serial);
|
||||||
|
+void zdwl_ipc_output_toggle_visibility(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2) {
|
||||||
|
+ struct Monitor *monitor = data;
|
||||||
|
+ monitor->desired_visibility ^= 1;
|
||||||
|
+ pipeline_hide(monitor->pipeline);
|
||||||
|
+ monitor_update(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
diff --git a/src/main.h b/src/main.h
|
||||||
|
index 1eb15c7..85aafeb 100644
|
||||||
|
--- a/src/main.h
|
||||||
|
+++ b/src/main.h
|
||||||
|
@@ -1,7 +1,7 @@
|
||||||
|
#ifndef MAIN_H_
|
||||||
|
#define MAIN_H_
|
||||||
|
|
||||||
|
-#include "xdg-output-unstable-v1-protocol.h"
|
||||||
|
+#include "dwl-ipc-unstable-v2-protocol.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
@@ -9,11 +9,11 @@
|
||||||
|
#define VERSION 0.0
|
||||||
|
|
||||||
|
struct Monitor {
|
||||||
|
- char *xdg_name;
|
||||||
|
uint32_t wl_name;
|
||||||
|
|
||||||
|
+ unsigned int desired_visibility, tags, layout;
|
||||||
|
struct wl_output *wl_output;
|
||||||
|
- struct zxdg_output_v1 *xdg_output;
|
||||||
|
+ struct zdwl_ipc_output_v2 *dwl_output;
|
||||||
|
struct Pipeline *pipeline;
|
||||||
|
struct List *hotspots; /* struct Hotspot* */
|
||||||
|
struct Bar *bar;
|
||||||
|
@@ -28,5 +28,6 @@ struct Monitor *monitor_from_surface(const struct wl_surface *surface);
|
||||||
|
extern struct wl_compositor *compositor;
|
||||||
|
extern struct zwlr_layer_shell_v1 *shell;
|
||||||
|
extern struct wl_shm *shm;
|
||||||
|
+extern int layoutcount;
|
||||||
|
|
||||||
|
#endif // MAIN_H_
|
||||||
|
diff --git a/src/user.c b/src/user.c
|
||||||
|
index 13820e7..14bdc73 100644
|
||||||
|
--- a/src/user.c
|
||||||
|
+++ b/src/user.c
|
||||||
|
@@ -4,6 +4,18 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
+void layout(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
+ if ((monitor->layout == 0 && !arg->ui) || (monitor->layout == layoutcount-1 && arg->ui))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (arg->ui)
|
||||||
|
+ monitor->layout++;
|
||||||
|
+ else
|
||||||
|
+ monitor->layout--;
|
||||||
|
+
|
||||||
|
+ zdwl_ipc_output_v2_set_layout(monitor->dwl_output, monitor->layout);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void spawn(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
if (fork() != 0)
|
||||||
|
return;
|
||||||
|
@@ -15,3 +27,15 @@ void spawn(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
perror(" failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+void tag(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
+ zdwl_ipc_output_v2_set_client_tags(monitor->dwl_output, 0, 1<<arg->ui);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void toggle_view(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
+ zdwl_ipc_output_v2_set_tags(monitor->dwl_output, monitor->tags ^ (1<<arg->ui), 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void view(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
+ zdwl_ipc_output_v2_set_tags(monitor->dwl_output, 1<<arg->ui, 1);
|
||||||
|
+}
|
||||||
|
diff --git a/src/user.h b/src/user.h
|
||||||
|
index b4442d8..367f389 100644
|
||||||
|
--- a/src/user.h
|
||||||
|
+++ b/src/user.h
|
||||||
|
@@ -46,6 +46,10 @@ struct Binding {
|
||||||
|
const union Arg arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
+void layout(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
void spawn(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
+void tag(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
+void toggle_view(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
+void view(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
|
||||||
|
#endif // USER_H_
|
181
user/.config/suckless/dwl-bar/protocols/dwl-ipc-unstable-v2.xml
Normal file
181
user/.config/suckless/dwl-bar/protocols/dwl-ipc-unstable-v2.xml
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
This is largely ripped from somebar's ipc patchset; just with some personal modifications.
|
||||||
|
I would probably just submit raphi's patchset but I don't think that would be polite.
|
||||||
|
-->
|
||||||
|
<protocol name="dwl_ipc_unstable_v2">
|
||||||
|
<description summary="inter-proccess-communication about dwl's state">
|
||||||
|
This protocol allows clients to update and get updates from dwl.
|
||||||
|
|
||||||
|
Warning! The protocol described in this file is experimental and
|
||||||
|
backward incompatible changes may be made. Backward compatible
|
||||||
|
changes may be added together with the corresponding interface
|
||||||
|
version bump.
|
||||||
|
Backward incompatible changes are done by bumping the version
|
||||||
|
number in the protocol and interface names and resetting the
|
||||||
|
interface version. Once the protocol is to be declared stable,
|
||||||
|
the 'z' prefix and the version number in the protocol and
|
||||||
|
interface names are removed and the interface version number is
|
||||||
|
reset.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<interface name="zdwl_ipc_manager_v2" version="2">
|
||||||
|
<description summary="manage dwl state">
|
||||||
|
This interface is exposed as a global in wl_registry.
|
||||||
|
|
||||||
|
Clients can use this interface to get a dwl_ipc_output.
|
||||||
|
After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events.
|
||||||
|
The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="release" type="destructor">
|
||||||
|
<description summary="release dwl_ipc_manager">
|
||||||
|
Indicates that the client will not the dwl_ipc_manager object anymore.
|
||||||
|
Objects created through this instance are not affected.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="get_output">
|
||||||
|
<description summary="get a dwl_ipc_outout for a wl_output">
|
||||||
|
Get a dwl_ipc_outout for the specified wl_output.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/>
|
||||||
|
<arg name="output" type="object" interface="wl_output"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="tags">
|
||||||
|
<description summary="Announces tag amount">
|
||||||
|
This event is sent after binding.
|
||||||
|
A roundtrip after binding guarantees the client recieved all tags.
|
||||||
|
</description>
|
||||||
|
<arg name="amount" type="uint"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="layout">
|
||||||
|
<description summary="Announces a layout">
|
||||||
|
This event is sent after binding.
|
||||||
|
A roundtrip after binding guarantees the client recieved all layouts.
|
||||||
|
</description>
|
||||||
|
<arg name="name" type="string"/>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zdwl_ipc_output_v2" version="2">
|
||||||
|
<description summary="control dwl output">
|
||||||
|
Observe and control a dwl output.
|
||||||
|
|
||||||
|
Events are double-buffered:
|
||||||
|
Clients should cache events and redraw when a dwl_ipc_output.frame event is sent.
|
||||||
|
|
||||||
|
Request are not double-buffered:
|
||||||
|
The compositor will update immediately upon request.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<enum name="tag_state">
|
||||||
|
<entry name="none" value="0" summary="no state"/>
|
||||||
|
<entry name="active" value="1" summary="tag is active"/>
|
||||||
|
<entry name="urgent" value="2" summary="tag has at least one urgent client"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="release" type="destructor">
|
||||||
|
<description summary="release dwl_ipc_outout">
|
||||||
|
Indicates to that the client no longer needs this dwl_ipc_output.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="toggle_visibility">
|
||||||
|
<description summary="Toggle client visibilty">
|
||||||
|
Indicates the client should hide or show themselves.
|
||||||
|
If the client is visible then hide, if hidden then show.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="active">
|
||||||
|
<description summary="Update the selected output.">
|
||||||
|
Indicates if the output is active. Zero is invalid, nonzero is valid.
|
||||||
|
</description>
|
||||||
|
<arg name="active" type="uint"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="tag">
|
||||||
|
<description summary="Update the state of a tag.">
|
||||||
|
Indicates that a tag has been updated.
|
||||||
|
</description>
|
||||||
|
<arg name="tag" type="uint" summary="Index of the tag"/>
|
||||||
|
<arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/>
|
||||||
|
<arg name="clients" type="uint" summary="The number of clients in the tag."/>
|
||||||
|
<arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="layout">
|
||||||
|
<description summary="Update the layout.">
|
||||||
|
Indicates a new layout is selected.
|
||||||
|
</description>
|
||||||
|
<arg name="layout" type="uint" summary="Index of the layout."/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="title">
|
||||||
|
<description summary="Update the title.">
|
||||||
|
Indicates the title has changed.
|
||||||
|
</description>
|
||||||
|
<arg name="title" type="string" summary="The new title name."/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="appid" since="1">
|
||||||
|
<description summary="Update the appid.">
|
||||||
|
Indicates the appid has changed.
|
||||||
|
</description>
|
||||||
|
<arg name="appid" type="string" summary="The new appid."/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="layout_symbol" since="1">
|
||||||
|
<description summary="Update the current layout symbol">
|
||||||
|
Indicates the layout has changed. Since layout symbols are dynamic.
|
||||||
|
As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying.
|
||||||
|
You can ignore the zdwl_ipc_output.layout event.
|
||||||
|
</description>
|
||||||
|
<arg name="layout" type="string" summary="The new layout"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="frame">
|
||||||
|
<description summary="The update sequence is done.">
|
||||||
|
Indicates that a sequence of status updates have finished and the client should redraw.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="set_tags">
|
||||||
|
<description summary="Set the active tags of this output"/>
|
||||||
|
<arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/>
|
||||||
|
<arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_client_tags">
|
||||||
|
<description summary="Set the tags of the focused client.">
|
||||||
|
The tags are updated as follows:
|
||||||
|
new_tags = (current_tags AND and_tags) XOR xor_tags
|
||||||
|
</description>
|
||||||
|
<arg name="and_tags" type="uint"/>
|
||||||
|
<arg name="xor_tags" type="uint"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_layout">
|
||||||
|
<description summary="Set the layout of this output"/>
|
||||||
|
<arg name="index" type="uint" summary="index of a layout recieved by dwl_ipc_manager.layout"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<!-- Version 2 -->
|
||||||
|
<event name="fullscreen" since="2">
|
||||||
|
<description summary="Update fullscreen status">
|
||||||
|
Indicates if the selected client on this output is fullscreen.
|
||||||
|
</description>
|
||||||
|
<arg name="is_fullscreen" type="uint" summary="If the selected client is fullscreen. Nonzero is valid, zero invalid"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="floating" since="2">
|
||||||
|
<description summary="Update the floating status">
|
||||||
|
Indicates if the selected client on this output is floating.
|
||||||
|
</description>
|
||||||
|
<arg name="is_floating" type="uint" summary="If the selected client is floating. Nonzero is valid, zero invalid"/>
|
||||||
|
</event>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
|
@ -0,0 +1,390 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="wlr_layer_shell_unstable_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2017 Drew DeVault
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that copyright notice and this permission
|
||||||
|
notice appear in supporting documentation, and that the name of
|
||||||
|
the copyright holders not be used in advertising or publicity
|
||||||
|
pertaining to distribution of the software without specific,
|
||||||
|
written prior permission. The copyright holders make no
|
||||||
|
representations about the suitability of this software for any
|
||||||
|
purpose. It is provided "as is" without express or implied
|
||||||
|
warranty.
|
||||||
|
|
||||||
|
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||||
|
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||||
|
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||||
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||||
|
THIS SOFTWARE.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<interface name="zwlr_layer_shell_v1" version="4">
|
||||||
|
<description summary="create surfaces that are layers of the desktop">
|
||||||
|
Clients can use this interface to assign the surface_layer role to
|
||||||
|
wl_surfaces. Such surfaces are assigned to a "layer" of the output and
|
||||||
|
rendered with a defined z-depth respective to each other. They may also be
|
||||||
|
anchored to the edges and corners of a screen and specify input handling
|
||||||
|
semantics. This interface should be suitable for the implementation of
|
||||||
|
many desktop shell components, and a broad number of other applications
|
||||||
|
that interact with the desktop.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="get_layer_surface">
|
||||||
|
<description summary="create a layer_surface from a surface">
|
||||||
|
Create a layer surface for an existing surface. This assigns the role of
|
||||||
|
layer_surface, or raises a protocol error if another role is already
|
||||||
|
assigned.
|
||||||
|
|
||||||
|
Creating a layer surface from a wl_surface which has a buffer attached
|
||||||
|
or committed is a client error, and any attempts by a client to attach
|
||||||
|
or manipulate a buffer prior to the first layer_surface.configure call
|
||||||
|
must also be treated as errors.
|
||||||
|
|
||||||
|
After creating a layer_surface object and setting it up, the client
|
||||||
|
must perform an initial commit without any buffer attached.
|
||||||
|
The compositor will reply with a layer_surface.configure event.
|
||||||
|
The client must acknowledge it and is then allowed to attach a buffer
|
||||||
|
to map the surface.
|
||||||
|
|
||||||
|
You may pass NULL for output to allow the compositor to decide which
|
||||||
|
output to use. Generally this will be the one that the user most
|
||||||
|
recently interacted with.
|
||||||
|
|
||||||
|
Clients can specify a namespace that defines the purpose of the layer
|
||||||
|
surface.
|
||||||
|
</description>
|
||||||
|
<arg name="id" type="new_id" interface="zwlr_layer_surface_v1"/>
|
||||||
|
<arg name="surface" type="object" interface="wl_surface"/>
|
||||||
|
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||||
|
<arg name="layer" type="uint" enum="layer" summary="layer to add this surface to"/>
|
||||||
|
<arg name="name_space" type="string" summary="namespace for the layer surface"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="role" value="0" summary="wl_surface has another role"/>
|
||||||
|
<entry name="invalid_layer" value="1" summary="layer value is invalid"/>
|
||||||
|
<entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<enum name="layer">
|
||||||
|
<description summary="available layers for surfaces">
|
||||||
|
These values indicate which layers a surface can be rendered in. They
|
||||||
|
are ordered by z depth, bottom-most first. Traditional shell surfaces
|
||||||
|
will typically be rendered between the bottom and top layers.
|
||||||
|
Fullscreen shell surfaces are typically rendered at the top layer.
|
||||||
|
Multiple surfaces can share a single layer, and ordering within a
|
||||||
|
single layer is undefined.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<entry name="background" value="0"/>
|
||||||
|
<entry name="bottom" value="1"/>
|
||||||
|
<entry name="top" value="2"/>
|
||||||
|
<entry name="overlay" value="3"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<!-- Version 3 additions -->
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor" since="3">
|
||||||
|
<description summary="destroy the layer_shell object">
|
||||||
|
This request indicates that the client will not use the layer_shell
|
||||||
|
object any more. Objects that have been created through this instance
|
||||||
|
are not affected.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zwlr_layer_surface_v1" version="4">
|
||||||
|
<description summary="layer metadata interface">
|
||||||
|
An interface that may be implemented by a wl_surface, for surfaces that
|
||||||
|
are designed to be rendered as a layer of a stacked desktop-like
|
||||||
|
environment.
|
||||||
|
|
||||||
|
Layer surface state (layer, size, anchor, exclusive zone,
|
||||||
|
margin, interactivity) is double-buffered, and will be applied at the
|
||||||
|
time wl_surface.commit of the corresponding wl_surface is called.
|
||||||
|
|
||||||
|
Attaching a null buffer to a layer surface unmaps it.
|
||||||
|
|
||||||
|
Unmapping a layer_surface means that the surface cannot be shown by the
|
||||||
|
compositor until it is explicitly mapped again. The layer_surface
|
||||||
|
returns to the state it had right after layer_shell.get_layer_surface.
|
||||||
|
The client can re-map the surface by performing a commit without any
|
||||||
|
buffer attached, waiting for a configure event and handling it as usual.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<request name="set_size">
|
||||||
|
<description summary="sets the size of the surface">
|
||||||
|
Sets the size of the surface in surface-local coordinates. The
|
||||||
|
compositor will display the surface centered with respect to its
|
||||||
|
anchors.
|
||||||
|
|
||||||
|
If you pass 0 for either value, the compositor will assign it and
|
||||||
|
inform you of the assignment in the configure event. You must set your
|
||||||
|
anchor to opposite edges in the dimensions you omit; not doing so is a
|
||||||
|
protocol error. Both values are 0 by default.
|
||||||
|
|
||||||
|
Size is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="width" type="uint"/>
|
||||||
|
<arg name="height" type="uint"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_anchor">
|
||||||
|
<description summary="configures the anchor point of the surface">
|
||||||
|
Requests that the compositor anchor the surface to the specified edges
|
||||||
|
and corners. If two orthogonal edges are specified (e.g. 'top' and
|
||||||
|
'left'), then the anchor point will be the intersection of the edges
|
||||||
|
(e.g. the top left corner of the output); otherwise the anchor point
|
||||||
|
will be centered on that edge, or in the center if none is specified.
|
||||||
|
|
||||||
|
Anchor is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="anchor" type="uint" enum="anchor"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_exclusive_zone">
|
||||||
|
<description summary="configures the exclusive geometry of this surface">
|
||||||
|
Requests that the compositor avoids occluding an area with other
|
||||||
|
surfaces. The compositor's use of this information is
|
||||||
|
implementation-dependent - do not assume that this region will not
|
||||||
|
actually be occluded.
|
||||||
|
|
||||||
|
A positive value is only meaningful if the surface is anchored to one
|
||||||
|
edge or an edge and both perpendicular edges. If the surface is not
|
||||||
|
anchored, anchored to only two perpendicular edges (a corner), anchored
|
||||||
|
to only two parallel edges or anchored to all edges, a positive value
|
||||||
|
will be treated the same as zero.
|
||||||
|
|
||||||
|
A positive zone is the distance from the edge in surface-local
|
||||||
|
coordinates to consider exclusive.
|
||||||
|
|
||||||
|
Surfaces that do not wish to have an exclusive zone may instead specify
|
||||||
|
how they should interact with surfaces that do. If set to zero, the
|
||||||
|
surface indicates that it would like to be moved to avoid occluding
|
||||||
|
surfaces with a positive exclusive zone. If set to -1, the surface
|
||||||
|
indicates that it would not like to be moved to accommodate for other
|
||||||
|
surfaces, and the compositor should extend it all the way to the edges
|
||||||
|
it is anchored to.
|
||||||
|
|
||||||
|
For example, a panel might set its exclusive zone to 10, so that
|
||||||
|
maximized shell surfaces are not shown on top of it. A notification
|
||||||
|
might set its exclusive zone to 0, so that it is moved to avoid
|
||||||
|
occluding the panel, but shell surfaces are shown underneath it. A
|
||||||
|
wallpaper or lock screen might set their exclusive zone to -1, so that
|
||||||
|
they stretch below or over the panel.
|
||||||
|
|
||||||
|
The default value is 0.
|
||||||
|
|
||||||
|
Exclusive zone is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="zone" type="int"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="set_margin">
|
||||||
|
<description summary="sets a margin from the anchor point">
|
||||||
|
Requests that the surface be placed some distance away from the anchor
|
||||||
|
point on the output, in surface-local coordinates. Setting this value
|
||||||
|
for edges you are not anchored to has no effect.
|
||||||
|
|
||||||
|
The exclusive zone includes the margin.
|
||||||
|
|
||||||
|
Margin is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="top" type="int"/>
|
||||||
|
<arg name="right" type="int"/>
|
||||||
|
<arg name="bottom" type="int"/>
|
||||||
|
<arg name="left" type="int"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<enum name="keyboard_interactivity">
|
||||||
|
<description summary="types of keyboard interaction possible for a layer shell surface">
|
||||||
|
Types of keyboard interaction possible for layer shell surfaces. The
|
||||||
|
rationale for this is twofold: (1) some applications are not interested
|
||||||
|
in keyboard events and not allowing them to be focused can improve the
|
||||||
|
desktop experience; (2) some applications will want to take exclusive
|
||||||
|
keyboard focus.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<entry name="none" value="0">
|
||||||
|
<description summary="no keyboard focus is possible">
|
||||||
|
This value indicates that this surface is not interested in keyboard
|
||||||
|
events and the compositor should never assign it the keyboard focus.
|
||||||
|
|
||||||
|
This is the default value, set for newly created layer shell surfaces.
|
||||||
|
|
||||||
|
This is useful for e.g. desktop widgets that display information or
|
||||||
|
only have interaction with non-keyboard input devices.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
<entry name="exclusive" value="1">
|
||||||
|
<description summary="request exclusive keyboard focus">
|
||||||
|
Request exclusive keyboard focus if this surface is above the shell surface layer.
|
||||||
|
|
||||||
|
For the top and overlay layers, the seat will always give
|
||||||
|
exclusive keyboard focus to the top-most layer which has keyboard
|
||||||
|
interactivity set to exclusive. If this layer contains multiple
|
||||||
|
surfaces with keyboard interactivity set to exclusive, the compositor
|
||||||
|
determines the one receiving keyboard events in an implementation-
|
||||||
|
defined manner. In this case, no guarantee is made when this surface
|
||||||
|
will receive keyboard focus (if ever).
|
||||||
|
|
||||||
|
For the bottom and background layers, the compositor is allowed to use
|
||||||
|
normal focus semantics.
|
||||||
|
|
||||||
|
This setting is mainly intended for applications that need to ensure
|
||||||
|
they receive all keyboard events, such as a lock screen or a password
|
||||||
|
prompt.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
<entry name="on_demand" value="2" since="4">
|
||||||
|
<description summary="request regular keyboard focus semantics">
|
||||||
|
This requests the compositor to allow this surface to be focused and
|
||||||
|
unfocused by the user in an implementation-defined manner. The user
|
||||||
|
should be able to unfocus this surface even regardless of the layer
|
||||||
|
it is on.
|
||||||
|
|
||||||
|
Typically, the compositor will want to use its normal mechanism to
|
||||||
|
manage keyboard focus between layer shell surfaces with this setting
|
||||||
|
and regular toplevels on the desktop layer (e.g. click to focus).
|
||||||
|
Nevertheless, it is possible for a compositor to require a special
|
||||||
|
interaction to focus or unfocus layer shell surfaces (e.g. requiring
|
||||||
|
a click even if focus follows the mouse normally, or providing a
|
||||||
|
keybinding to switch focus between layers).
|
||||||
|
|
||||||
|
This setting is mainly intended for desktop shell components (e.g.
|
||||||
|
panels) that allow keyboard interaction. Using this option can allow
|
||||||
|
implementing a desktop shell that can be fully usable without the
|
||||||
|
mouse.
|
||||||
|
</description>
|
||||||
|
</entry>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<request name="set_keyboard_interactivity">
|
||||||
|
<description summary="requests keyboard events">
|
||||||
|
Set how keyboard events are delivered to this surface. By default,
|
||||||
|
layer shell surfaces do not receive keyboard events; this request can
|
||||||
|
be used to change this.
|
||||||
|
|
||||||
|
This setting is inherited by child surfaces set by the get_popup
|
||||||
|
request.
|
||||||
|
|
||||||
|
Layer surfaces receive pointer, touch, and tablet events normally. If
|
||||||
|
you do not want to receive them, set the input region on your surface
|
||||||
|
to an empty region.
|
||||||
|
|
||||||
|
Keyboard interactivity is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="keyboard_interactivity" type="uint" enum="keyboard_interactivity"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="get_popup">
|
||||||
|
<description summary="assign this layer_surface as an xdg_popup parent">
|
||||||
|
This assigns an xdg_popup's parent to this layer_surface. This popup
|
||||||
|
should have been created via xdg_surface::get_popup with the parent set
|
||||||
|
to NULL, and this request must be invoked before committing the popup's
|
||||||
|
initial state.
|
||||||
|
|
||||||
|
See the documentation of xdg_popup for more details about what an
|
||||||
|
xdg_popup is and how it is used.
|
||||||
|
</description>
|
||||||
|
<arg name="popup" type="object" interface="xdg_popup"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="ack_configure">
|
||||||
|
<description summary="ack a configure event">
|
||||||
|
When a configure event is received, if a client commits the
|
||||||
|
surface in response to the configure event, then the client
|
||||||
|
must make an ack_configure request sometime before the commit
|
||||||
|
request, passing along the serial of the configure event.
|
||||||
|
|
||||||
|
If the client receives multiple configure events before it
|
||||||
|
can respond to one, it only has to ack the last configure event.
|
||||||
|
|
||||||
|
A client is not required to commit immediately after sending
|
||||||
|
an ack_configure request - it may even ack_configure several times
|
||||||
|
before its next surface commit.
|
||||||
|
|
||||||
|
A client may send multiple ack_configure requests before committing, but
|
||||||
|
only the last request sent before a commit indicates which configure
|
||||||
|
event the client really is responding to.
|
||||||
|
</description>
|
||||||
|
<arg name="serial" type="uint" summary="the serial from the configure event"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="destroy the layer_surface">
|
||||||
|
This request destroys the layer surface.
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<event name="configure">
|
||||||
|
<description summary="suggest a surface change">
|
||||||
|
The configure event asks the client to resize its surface.
|
||||||
|
|
||||||
|
Clients should arrange their surface for the new states, and then send
|
||||||
|
an ack_configure request with the serial sent in this configure event at
|
||||||
|
some point before committing the new surface.
|
||||||
|
|
||||||
|
The client is free to dismiss all but the last configure event it
|
||||||
|
received.
|
||||||
|
|
||||||
|
The width and height arguments specify the size of the window in
|
||||||
|
surface-local coordinates.
|
||||||
|
|
||||||
|
The size is a hint, in the sense that the client is free to ignore it if
|
||||||
|
it doesn't resize, pick a smaller size (to satisfy aspect ratio or
|
||||||
|
resize in steps of NxM pixels). If the client picks a smaller size and
|
||||||
|
is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the
|
||||||
|
surface will be centered on this axis.
|
||||||
|
|
||||||
|
If the width or height arguments are zero, it means the client should
|
||||||
|
decide its own window dimension.
|
||||||
|
</description>
|
||||||
|
<arg name="serial" type="uint"/>
|
||||||
|
<arg name="width" type="uint"/>
|
||||||
|
<arg name="height" type="uint"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="closed">
|
||||||
|
<description summary="surface should be closed">
|
||||||
|
The closed event is sent by the compositor when the surface will no
|
||||||
|
longer be shown. The output may have been destroyed or the user may
|
||||||
|
have asked for it to be removed. Further changes to the surface will be
|
||||||
|
ignored. The client should destroy the resource after receiving this
|
||||||
|
event, and create a new surface if they so choose.
|
||||||
|
</description>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
|
||||||
|
<entry name="invalid_size" value="1" summary="size is invalid"/>
|
||||||
|
<entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
|
||||||
|
<entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<enum name="anchor" bitfield="true">
|
||||||
|
<entry name="top" value="1" summary="the top edge of the anchor rectangle"/>
|
||||||
|
<entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/>
|
||||||
|
<entry name="left" value="4" summary="the left edge of the anchor rectangle"/>
|
||||||
|
<entry name="right" value="8" summary="the right edge of the anchor rectangle"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<!-- Version 2 additions -->
|
||||||
|
|
||||||
|
<request name="set_layer" since="2">
|
||||||
|
<description summary="change the layer of the surface">
|
||||||
|
Change the layer that the surface is rendered on.
|
||||||
|
|
||||||
|
Layer is double-buffered, see wl_surface.commit.
|
||||||
|
</description>
|
||||||
|
<arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
378
user/.config/suckless/dwl-bar/src/bar.c
Normal file
378
user/.config/suckless/dwl-bar/src/bar.c
Normal file
|
@ -0,0 +1,378 @@
|
||||||
|
#include "bar.h"
|
||||||
|
#include "cairo.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "pango/pango-item.h"
|
||||||
|
#include "pango/pango-layout.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "user.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "pango/pango.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static void bar_click(struct Monitor *monitor, void *data, uint32_t button, double x, double y);
|
||||||
|
static int bar_component_add_elipses(struct BasicComponent *component, struct Pipeline *pipeline, int limit);
|
||||||
|
static struct BasicComponent *bar_component_create(struct Pipeline *pipeline);
|
||||||
|
static int bar_component_width(struct BasicComponent *component, struct Pipeline *pipeline);
|
||||||
|
static void bar_bounds(void *data, double *x, double *y, double *width, double *height);
|
||||||
|
static enum Clicked bar_get_location(struct Bar *bar, double x, double y, int *tag_index);
|
||||||
|
static void bar_layout_render(struct Pipeline *pipeline, struct Bar *bar, cairo_t *painter, int *x, int *y);
|
||||||
|
static void bar_render(struct Pipeline *pipeline, void *data, cairo_t *painter, int *x, int *y);
|
||||||
|
static void bar_tags_render(struct Pipeline *pipeline, struct Bar *bar, cairo_t *painter, int *x, int *y);
|
||||||
|
static void bar_title_render(struct Pipeline *pipeline, struct Bar *bar, cairo_t *painter, int *x, int *y);
|
||||||
|
static void bar_status_render(struct Pipeline *pipeline, struct Bar *bar, cairo_t *painter, int *x, int *y);
|
||||||
|
static int bar_width(struct Pipeline *pipeline, void *data, unsigned int future_widths);
|
||||||
|
|
||||||
|
const struct PipelineListener bar_pipeline_listener = { .render = bar_render, .width = bar_width, };
|
||||||
|
const struct HotspotListener bar_hotspot_listener = { .click = bar_click, .bounds = bar_bounds };
|
||||||
|
|
||||||
|
void bar_click(struct Monitor *monitor, void *data, uint32_t button, double x, double y) {
|
||||||
|
if (!monitor || !data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct Bar *bar = data;
|
||||||
|
const struct Binding *binding;
|
||||||
|
union Arg *argp = NULL, arg;
|
||||||
|
int tag_index = -1;
|
||||||
|
enum Clicked clicked = bar_get_location(bar, x, y, &tag_index);
|
||||||
|
|
||||||
|
if (clicked == Click_Tag) {
|
||||||
|
arg.ui = tag_index;
|
||||||
|
argp = &arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < LENGTH(bindings); i++) {
|
||||||
|
binding = &bindings[i];
|
||||||
|
if (clicked != binding->clicked || button != binding->button)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
binding->callback(monitor, (argp && !binding->bypass) ? argp : &binding->arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int bar_component_add_elipses(struct BasicComponent *component, struct Pipeline *pipeline, int limit) {
|
||||||
|
const char *current_string = pango_layout_get_text(component->layout);
|
||||||
|
char *new_string;
|
||||||
|
const int elipses_amnt = 3;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = strlen(current_string);
|
||||||
|
(((i+elipses_amnt)*pipeline->font->approx_width)+pipeline->font->height > limit && i >= 0);
|
||||||
|
i--);
|
||||||
|
|
||||||
|
if (i <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
new_string = strncpy(ecalloc(i+elipses_amnt+1, sizeof(*new_string)),
|
||||||
|
current_string, i);
|
||||||
|
new_string[i+1] = '\0';
|
||||||
|
new_string = strcat(new_string, "...");
|
||||||
|
|
||||||
|
pango_layout_set_text(component->layout, new_string, -1);
|
||||||
|
free(new_string);
|
||||||
|
return bar_component_width(component, pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BasicComponent *bar_component_create(struct Pipeline *pipeline) {
|
||||||
|
if (!pipeline)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct BasicComponent *component = basic_component_create(pipeline->context, pipeline->font->description);
|
||||||
|
component->tx = pipeline->font->height/2.0;
|
||||||
|
component->ty = 1;
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bar_component_width(struct BasicComponent *component, struct Pipeline *pipeline) {
|
||||||
|
return basic_component_text_width(component) + pipeline->font->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_bounds(void *data, double *x, double *y, double *width, double *height) {
|
||||||
|
struct Bar *bar = data;
|
||||||
|
int bar_width = 0;
|
||||||
|
struct Tag *tag;
|
||||||
|
for (int i = 0; i < LENGTH(bar->tags); i++) {
|
||||||
|
tag = &bar->tags[i];
|
||||||
|
bar_width += tag->component->width;
|
||||||
|
}
|
||||||
|
bar_width += bar->layout->width;
|
||||||
|
bar_width += bar->title->width;
|
||||||
|
bar_width += bar->status->width;
|
||||||
|
|
||||||
|
*x = bar->x;
|
||||||
|
*y = bar->y;
|
||||||
|
*width = bar_width;
|
||||||
|
*height = bar->pipeline->shm->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Clicked bar_get_location(struct Bar *bar, double x, double y, int *tag_index) {
|
||||||
|
enum Clicked clicked = Click_None;
|
||||||
|
struct Tag *tag;
|
||||||
|
|
||||||
|
for (int i = 0; i < LENGTH(bar->tags); i++) {
|
||||||
|
tag = &bar->tags[i];
|
||||||
|
if (basic_component_is_clicked(tag->component, x, y)) {
|
||||||
|
clicked = Click_Tag;
|
||||||
|
*tag_index = i;
|
||||||
|
return clicked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (basic_component_is_clicked(bar->layout, x, y))
|
||||||
|
clicked = Click_Layout;
|
||||||
|
else if (basic_component_is_clicked(bar->title, x, y))
|
||||||
|
clicked = Click_Title;
|
||||||
|
else if (basic_component_is_clicked(bar->status, x, y))
|
||||||
|
clicked = Click_Status;
|
||||||
|
|
||||||
|
return clicked;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Bar *bar_create(struct List *hotspots, struct Pipeline *pipeline) {
|
||||||
|
if (!pipeline)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct Bar *bar = ecalloc(1, sizeof(*bar));
|
||||||
|
bar->pipeline = pipeline;
|
||||||
|
bar->title = bar_component_create(pipeline);
|
||||||
|
bar->layout = bar_component_create(pipeline);
|
||||||
|
bar->status = bar_component_create(pipeline);
|
||||||
|
|
||||||
|
char *status = string_create("dwl %.1f", VERSION);
|
||||||
|
pango_layout_set_text(bar->status->layout, status, strlen(status));
|
||||||
|
free(status);
|
||||||
|
|
||||||
|
struct Tag *tag;
|
||||||
|
for (int i = 0; i < LENGTH(tags); i++) {
|
||||||
|
tag = &bar->tags[i];
|
||||||
|
*tag = (struct Tag){ 0, 0, 0,
|
||||||
|
bar_component_create(pipeline) };
|
||||||
|
pango_layout_set_text(tag->component->layout, tags[i], strlen(tags[i]));
|
||||||
|
tag->component->width = basic_component_text_width(tag->component) + pipeline->font->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipeline_add(pipeline, &bar_pipeline_listener, bar);
|
||||||
|
struct Hotspot *hotspot = list_add(hotspots, ecalloc(1, sizeof(*hotspot)));
|
||||||
|
hotspot->listener = &bar_hotspot_listener;
|
||||||
|
hotspot->data = bar;
|
||||||
|
|
||||||
|
bar->x = 0;
|
||||||
|
bar->y = 0;
|
||||||
|
|
||||||
|
return bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_destroy(struct Bar *bar) {
|
||||||
|
if (!bar) return;
|
||||||
|
|
||||||
|
basic_component_destroy(bar->title);
|
||||||
|
basic_component_destroy(bar->layout);
|
||||||
|
basic_component_destroy(bar->status);
|
||||||
|
struct Tag *tag;
|
||||||
|
for (int i = 0; i < LENGTH(bar->tags); i++) {
|
||||||
|
tag = &bar->tags[i];
|
||||||
|
basic_component_destroy(tag->component);
|
||||||
|
}
|
||||||
|
free(bar);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_layout_render(struct Pipeline *pipeline, struct Bar *bar, cairo_t *painter, int *x, int *y) {
|
||||||
|
if (!bar || !pipeline)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bar->layout->width = bar_component_width(bar->layout, pipeline);
|
||||||
|
bar->layout->height = pipeline->shm->height;
|
||||||
|
pipeline_set_colorscheme(pipeline, schemes[InActive_Scheme]);
|
||||||
|
basic_component_render(bar->layout, pipeline, painter, x, y);
|
||||||
|
|
||||||
|
*x += bar->layout->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_render(struct Pipeline *pipeline, void *data, cairo_t *painter, int *x, int *y) {
|
||||||
|
if (!pipeline || !data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct Bar *bar = data;
|
||||||
|
bar->x = *x;
|
||||||
|
bar->y = *y;
|
||||||
|
bar_tags_render(pipeline, bar, painter, x, y);
|
||||||
|
bar_layout_render(pipeline, bar, painter, x, y);
|
||||||
|
bar_title_render(pipeline, bar, painter, x, y);
|
||||||
|
bar_status_render(pipeline, bar, painter, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_tags_render(struct Pipeline *pipeline, struct Bar *bar, cairo_t *painter, int *x, int *y) {
|
||||||
|
if (!bar || !pipeline)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct Tag *tag;
|
||||||
|
for (int i = 0; i < LENGTH(bar->tags); i++) {
|
||||||
|
tag = &bar->tags[i];
|
||||||
|
|
||||||
|
if (tag->state & Tag_Active)
|
||||||
|
pipeline_set_colorscheme(pipeline, schemes[Active_Scheme]);
|
||||||
|
else if (tag->state & Tag_Urgent)
|
||||||
|
pipeline_set_colorscheme(pipeline, schemes[Urgent_Scheme]);
|
||||||
|
else
|
||||||
|
pipeline_set_colorscheme(pipeline, schemes[InActive_Scheme]);
|
||||||
|
|
||||||
|
tag->component->height = pipeline->shm->height;
|
||||||
|
basic_component_render(tag->component, pipeline, painter, x, y);
|
||||||
|
|
||||||
|
if (!tag->occupied)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Creating the occupied tag box */
|
||||||
|
int boxHeight = pipeline->font->height / 9,
|
||||||
|
boxWidth = pipeline->font->height / 6 + 1;
|
||||||
|
|
||||||
|
if (tag->has_focused) {
|
||||||
|
cairo_rectangle(painter, *x + boxHeight, boxHeight, boxWidth, boxWidth);
|
||||||
|
cairo_fill(painter);
|
||||||
|
} else {
|
||||||
|
cairo_rectangle(painter, *x + boxHeight + 0.5, boxHeight + 0.5, boxWidth, boxWidth);
|
||||||
|
cairo_set_line_width(painter, 1);
|
||||||
|
cairo_stroke(painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
*x += tag->component->width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_title_render(struct Pipeline *pipeline, struct Bar *bar, cairo_t *painter, int *x, int *y) {
|
||||||
|
if (!bar || !pipeline)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (bar->active)
|
||||||
|
pipeline_set_colorscheme(pipeline, schemes[Active_Scheme]);
|
||||||
|
else
|
||||||
|
pipeline_set_colorscheme(pipeline, schemes[InActive_Scheme]);
|
||||||
|
|
||||||
|
bar->title->width = pipeline->shm->width - *x - bar_component_width(bar->status, pipeline) - pipeline_get_future_widths(pipeline);
|
||||||
|
bar->title->height = pipeline->shm->height;
|
||||||
|
|
||||||
|
if (bar_component_width(bar->title, pipeline) > bar->title->width)
|
||||||
|
bar->title->width = bar_component_width(bar->title, pipeline);
|
||||||
|
|
||||||
|
basic_component_render(bar->title, pipeline, painter, x, y);
|
||||||
|
|
||||||
|
if (!bar->floating)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
int boxHeight = pipeline->font->height / 9,
|
||||||
|
boxWidth = pipeline->font->height / 6 + 1;
|
||||||
|
|
||||||
|
set_color(painter, grey3);
|
||||||
|
cairo_rectangle(painter, *x + boxHeight + 0.5, boxHeight + 0.5, boxWidth, boxWidth);
|
||||||
|
cairo_set_line_width(painter, 1);
|
||||||
|
cairo_stroke(painter);
|
||||||
|
|
||||||
|
done:
|
||||||
|
*x += bar->title->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_status_render(struct Pipeline *pipeline, struct Bar *bar, cairo_t *painter, int *x, int *y) {
|
||||||
|
if (!bar || !pipeline)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char *previous_status = NULL;
|
||||||
|
|
||||||
|
pipeline_set_colorscheme(pipeline, schemes[InActive_Scheme]);
|
||||||
|
if (!bar->active && status_on_active)
|
||||||
|
pipeline_set_colorscheme(pipeline, (const int *[4]){ grey1, grey1 });
|
||||||
|
|
||||||
|
bar->status->width = bar_component_width(bar->status, pipeline);
|
||||||
|
bar->status->height = pipeline->shm->height;
|
||||||
|
|
||||||
|
if (bar->status->width > (pipeline->shm->width - *x - pipeline_get_future_widths(pipeline))) {
|
||||||
|
previous_status = strdup(pango_layout_get_text(bar->status->layout));
|
||||||
|
bar->status->width = bar_component_add_elipses(bar->status, pipeline,
|
||||||
|
(pipeline->shm->width - *x - pipeline_get_future_widths(pipeline)));
|
||||||
|
if (bar->status->width == 0) {
|
||||||
|
free(previous_status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_component_render(bar->status, pipeline, painter, x, y);
|
||||||
|
|
||||||
|
if (previous_status) {
|
||||||
|
pango_layout_set_text(bar->status->layout, previous_status, -1);
|
||||||
|
free(previous_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
*x += bar->status->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_set_active(struct Bar *bar, unsigned int is_active) {
|
||||||
|
if (!bar) return;
|
||||||
|
|
||||||
|
bar->active = is_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_set_floating(struct Bar *bar, unsigned int is_floating) {
|
||||||
|
if (!bar) return;
|
||||||
|
|
||||||
|
bar->floating = is_floating;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_set_layout(struct Bar *bar, const char *text) {
|
||||||
|
if (!bar) return;
|
||||||
|
|
||||||
|
pango_layout_set_text(bar->layout->layout, text, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_set_status(struct Bar *bar, const char *text) {
|
||||||
|
if (!bar) return;
|
||||||
|
|
||||||
|
pango_layout_set_text(bar->status->layout, text, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_set_tag(struct Bar *bar, unsigned int index,
|
||||||
|
unsigned int state, unsigned int occupied, unsigned int has_focused) {
|
||||||
|
if (!bar) return;
|
||||||
|
|
||||||
|
if (!bar || index >= LENGTH(bar->tags) ) return;
|
||||||
|
|
||||||
|
struct Tag *tag = &bar->tags[index];
|
||||||
|
tag->has_focused = has_focused;
|
||||||
|
tag->occupied = occupied;
|
||||||
|
tag->state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bar_set_title(struct Bar *bar, const char *text) {
|
||||||
|
if (!bar) return;
|
||||||
|
|
||||||
|
pango_layout_set_text(bar->title->layout, text, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bar_width(struct Pipeline *pipeline, void *data, unsigned int future_widths) {
|
||||||
|
if (!data || !pipeline) return 0;
|
||||||
|
|
||||||
|
struct Bar *bar = data;
|
||||||
|
int width = 0, title_width, status_width;
|
||||||
|
|
||||||
|
for (int i = 0; i < LENGTH(bar->tags); i++)
|
||||||
|
width += bar_component_width(bar->tags[i].component, pipeline);
|
||||||
|
width += bar_component_width(bar->layout, pipeline);
|
||||||
|
|
||||||
|
title_width = pipeline->shm->width - width - bar_component_width(bar->status, pipeline) - future_widths;
|
||||||
|
if (bar_component_width(bar->title, pipeline) > bar->title->width)
|
||||||
|
title_width = bar_component_width(bar->title, pipeline);
|
||||||
|
width += title_width;
|
||||||
|
|
||||||
|
status_width = bar_component_width(bar->status, pipeline);
|
||||||
|
if (status_width > (pipeline->shm->width - width - future_widths)) {
|
||||||
|
char *previous_status = strdup(pango_layout_get_text(bar->status->layout));
|
||||||
|
bar->status->width = bar_component_add_elipses(bar->status, pipeline,
|
||||||
|
(pipeline->shm->width - width - pipeline_get_future_widths(pipeline)));
|
||||||
|
pango_layout_set_text(bar->status->layout, previous_status, -1);
|
||||||
|
free(previous_status);
|
||||||
|
}
|
||||||
|
width += status_width;
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
39
user/.config/suckless/dwl-bar/src/bar.h
Normal file
39
user/.config/suckless/dwl-bar/src/bar.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef BAR_H_
|
||||||
|
#define BAR_H_
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "render.h"
|
||||||
|
|
||||||
|
enum TagState {
|
||||||
|
Tag_None = 0,
|
||||||
|
Tag_Active = 1,
|
||||||
|
Tag_Urgent = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Tag {
|
||||||
|
unsigned int occupied, has_focused, state;
|
||||||
|
struct BasicComponent *component;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Bar {
|
||||||
|
struct Pipeline *pipeline;
|
||||||
|
struct BasicComponent *layout, *title, *status;
|
||||||
|
struct Tag tags[LENGTH(tags)];
|
||||||
|
|
||||||
|
unsigned int active, floating;
|
||||||
|
unsigned int x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Bar *bar_create(struct List *hotspots, struct Pipeline *pipeline);
|
||||||
|
void bar_destroy(struct Bar *bar);
|
||||||
|
void bar_set_active(struct Bar *bar, unsigned int is_active);
|
||||||
|
void bar_set_floating(struct Bar *bar, unsigned int is_floating);
|
||||||
|
void bar_set_layout(struct Bar *bar, const char *text);
|
||||||
|
void bar_set_status(struct Bar *bar, const char *text);
|
||||||
|
void bar_set_tag(struct Bar *bar, unsigned int index,
|
||||||
|
unsigned int state, unsigned int occupied, unsigned int focusedClient);
|
||||||
|
void bar_set_title(struct Bar *bar, const char *text);
|
||||||
|
|
||||||
|
extern const struct PipelineListener bar_pipeline_listener;
|
||||||
|
|
||||||
|
#endif // BAR_H_
|
67
user/.config/suckless/dwl-bar/src/config.def.h
Normal file
67
user/.config/suckless/dwl-bar/src/config.def.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#ifndef CONFIG_H_
|
||||||
|
#define CONFIG_H_
|
||||||
|
|
||||||
|
#include "user.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
|
||||||
|
static const int show_bar = 1;
|
||||||
|
static const int bar_top = 1; /* Boolean value, non-zero is true. If not top then bottom */
|
||||||
|
static const int status_on_active = 1; /* Display the status on active monitor only. If not then on all. */
|
||||||
|
static const char *font = "mononoki Nerd Font 12";
|
||||||
|
static const char *terminal[] = { "wezterm", NULL };
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Colors:
|
||||||
|
* Colors are in rgba format.
|
||||||
|
* The color scheming format is the same as dwm.
|
||||||
|
* We use an enum as a index for our scheme types.
|
||||||
|
*
|
||||||
|
* cyan - used in an active background
|
||||||
|
* grey3 - used in active text and urgent background
|
||||||
|
* grey1 - used in an inactive background
|
||||||
|
* grey2 - used in inactive text
|
||||||
|
*/
|
||||||
|
static const int cyan[4] = { 204, 36, 29, 255 };
|
||||||
|
static const int grey1[4] = { 29, 32, 33, 255 };
|
||||||
|
static const int grey2[4] = { 235, 219, 178, 255 };
|
||||||
|
static const int grey3[4] = { 251, 241, 199, 255 };
|
||||||
|
|
||||||
|
static const int *schemes[3][2] = {
|
||||||
|
/* Scheme Type fg, bg */
|
||||||
|
[InActive_Scheme] = {grey2, grey1},
|
||||||
|
[Active_Scheme] = {grey3, cyan},
|
||||||
|
[Urgent_Scheme] = {grey1, grey3},
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tags
|
||||||
|
* Must not exceed 31 tags and amount must match dwl's tagcount.
|
||||||
|
*/
|
||||||
|
static const char *tags[] = {
|
||||||
|
" EDT", // EDITOR
|
||||||
|
" TST", // TESTING
|
||||||
|
" WEB", // WEB BROWSER
|
||||||
|
" CHT", // CHAT
|
||||||
|
" AUD", // AUDIO TOOLS
|
||||||
|
" VID", // VIDEO
|
||||||
|
" IMG", // IMAGE/EDIT TOOLS
|
||||||
|
" OFF", // OFFICE
|
||||||
|
" GME" // GAMES
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Buttons
|
||||||
|
* See user.h for details on relevant structures.
|
||||||
|
*/
|
||||||
|
static const Binding bindings[] = {
|
||||||
|
/* Click Location, button, callback, bypass, arguments */
|
||||||
|
{ Click_Layout, BTN_LEFT, layout, 1, {.ui = 0} },
|
||||||
|
{ Click_Layout, BTN_RIGHT, layout, 1, {.ui = 1} },
|
||||||
|
{ Click_Status, BTN_MIDDLE, spawn, 0, {.v = terminal } },
|
||||||
|
{ Click_Tag, BTN_MIDDLE, tag, 0, {0} },
|
||||||
|
{ Click_Tag, BTN_RIGHT, toggle_view, 0, {0} },
|
||||||
|
{ Click_Tag, BTN_LEFT, view, 0, {0} },
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONFIG_H_
|
75
user/.config/suckless/dwl-bar/src/event.c
Normal file
75
user/.config/suckless/dwl-bar/src/event.c
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#include "event.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
|
||||||
|
void events_add(struct Events *events, int fd, short mask, void *data,
|
||||||
|
void (*callback)(int, short, void *)) {
|
||||||
|
if (!events)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (events->pollfds_length == events->pollfds_capacity) {
|
||||||
|
events->pollfds = realloc(events->pollfds, sizeof(struct pollfd) * (events->pollfds_capacity+1));
|
||||||
|
events->pollfds_capacity++;
|
||||||
|
}
|
||||||
|
events->pollfds[events->pollfds_length++] = (struct pollfd){fd, mask, 0};
|
||||||
|
|
||||||
|
struct EventCallback *backcall = list_add(events->callbacks, ecalloc(1, sizeof(*backcall)));
|
||||||
|
backcall->callback = callback;
|
||||||
|
backcall->data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Events *events_create(void) {
|
||||||
|
struct Events *events = ecalloc(1, sizeof(*events));
|
||||||
|
|
||||||
|
events->callbacks = list_create(0);
|
||||||
|
events->pollfds = NULL;
|
||||||
|
events->pollfds_length = 0;
|
||||||
|
events->pollfds_capacity = 0;
|
||||||
|
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
void events_destroy(struct Events *events) {
|
||||||
|
if (!events)
|
||||||
|
return;
|
||||||
|
|
||||||
|
list_elements_destroy(events->callbacks, free);
|
||||||
|
free(events->pollfds);
|
||||||
|
free(events);
|
||||||
|
}
|
||||||
|
|
||||||
|
void events_poll(struct Events *events) {
|
||||||
|
if (!events)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (poll(events->pollfds, events->pollfds_length, -1) <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < events->pollfds_length; i++) {
|
||||||
|
struct pollfd *pollfd = &events->pollfds[i];
|
||||||
|
struct EventCallback *callback = events->callbacks->data[i];
|
||||||
|
|
||||||
|
|
||||||
|
if (pollfd->revents & (pollfd->events | POLLHUP | POLLERR))
|
||||||
|
callback->callback(pollfd->fd, pollfd->revents, callback->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void events_remove(struct Events *events, int fd) {
|
||||||
|
if (!events)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < events->pollfds_length; i++) {
|
||||||
|
if (events->pollfds[i].fd != fd)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
free(list_remove(events->callbacks, i));
|
||||||
|
|
||||||
|
events->pollfds_length--;
|
||||||
|
memmove(&events->pollfds[i], &events->pollfds[i+1],
|
||||||
|
sizeof(struct pollfd) * (events->pollfds_length - i));
|
||||||
|
}
|
||||||
|
}
|
22
user/.config/suckless/dwl-bar/src/event.h
Normal file
22
user/.config/suckless/dwl-bar/src/event.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef EVENT_H_
|
||||||
|
#define EVENT_H_
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
struct EventCallback {
|
||||||
|
void (*callback)(int fd, short mask, void *data);
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Events {
|
||||||
|
struct List *callbacks; // struct EventCallback*
|
||||||
|
struct pollfd *pollfds;
|
||||||
|
int pollfds_length, pollfds_capacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
void events_add(struct Events *events, int fd, short mask, void *data, void (*callback)(int fd, short mask, void *data));
|
||||||
|
struct Events *events_create(void);
|
||||||
|
void events_destroy(struct Events *events);
|
||||||
|
void events_poll(struct Events *events);
|
||||||
|
void events_remove(struct Events *events, int fd);
|
||||||
|
|
||||||
|
#endif // EVENT_H_
|
408
user/.config/suckless/dwl-bar/src/input.c
Normal file
408
user/.config/suckless/dwl-bar/src/input.c
Normal file
|
@ -0,0 +1,408 @@
|
||||||
|
#include "input.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "user.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/input-event-codes.h>
|
||||||
|
#include <wayland-client-protocol.h>
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
|
||||||
|
static int button_cmp(const void *left, const void *right);
|
||||||
|
static void hotspots_process(struct Monitor* monitor, double x, double y, uint32_t button);
|
||||||
|
static void pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value);
|
||||||
|
static void pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete);
|
||||||
|
static void pointer_axis_source(void *data, struct wl_pointer *wl_pointer, uint32_t axis_source);
|
||||||
|
static void pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis);
|
||||||
|
static void pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state);
|
||||||
|
static struct Pointer *pointer_create(struct wl_seat *seat);
|
||||||
|
static void pointer_destroy(struct Pointer *pointer);
|
||||||
|
static void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y);
|
||||||
|
static void pointer_frame(void *data, struct wl_pointer *wl_pointer);
|
||||||
|
static void pointer_process_scroll(struct Pointer *pointer, unsigned int axis_index);
|
||||||
|
static void pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface);
|
||||||
|
static void pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y);
|
||||||
|
static void pointer_update_cursor(struct Pointer *pointer);
|
||||||
|
static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities);
|
||||||
|
static void seat_name(void *data, struct wl_seat *wl_seat, const char *name);
|
||||||
|
static void touch_cancel(void *data, struct wl_touch *wl_touch);
|
||||||
|
static struct Touch *touch_create(struct wl_seat *seat);
|
||||||
|
static void touch_destroy(struct Touch *touch);
|
||||||
|
static void touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y);
|
||||||
|
static void touch_frame(void *data, struct wl_touch *wl_touch);
|
||||||
|
static struct TouchPoint *touch_get_point(struct Touch *touch, int32_t id);
|
||||||
|
static void touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y);
|
||||||
|
static void touch_orientation(void *data, struct wl_touch *wl_touch, int32_t id, wl_fixed_t orientation);
|
||||||
|
static uint32_t touch_point_to_button(struct TouchPoint *point, uint32_t time);
|
||||||
|
static void touch_shape(void *data, struct wl_touch *wl_touch, int32_t id, wl_fixed_t major, wl_fixed_t minor);
|
||||||
|
static void touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id);
|
||||||
|
static uint32_t wl_axis_to_button(int axis, wl_fixed_t value);
|
||||||
|
|
||||||
|
static const struct wl_pointer_listener pointer_listener = {
|
||||||
|
.axis = pointer_axis,
|
||||||
|
.axis_discrete = pointer_axis_discrete,
|
||||||
|
.axis_source = pointer_axis_source,
|
||||||
|
.axis_stop = pointer_axis_stop,
|
||||||
|
.button = pointer_button,
|
||||||
|
.enter = pointer_enter,
|
||||||
|
.frame = pointer_frame,
|
||||||
|
.leave = pointer_leave,
|
||||||
|
.motion = pointer_motion,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct wl_seat_listener seat_listener = {
|
||||||
|
.capabilities = seat_capabilities,
|
||||||
|
.name = seat_name,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_touch_listener touch_listener = {
|
||||||
|
.cancel = touch_cancel,
|
||||||
|
.down = touch_down,
|
||||||
|
.frame = touch_frame,
|
||||||
|
.motion = touch_motion,
|
||||||
|
.orientation = touch_orientation,
|
||||||
|
.shape = touch_shape,
|
||||||
|
.up = touch_up,
|
||||||
|
};
|
||||||
|
|
||||||
|
int button_cmp(const void *left, const void *right) {
|
||||||
|
return (*(uint32_t*)left) == (*(uint32_t*)right);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis_index, wl_fixed_t value) {
|
||||||
|
struct Pointer *pointer = data;
|
||||||
|
struct Axis *axis = &pointer->axis[axis_index];
|
||||||
|
|
||||||
|
if (axis->discrete_steps == 0
|
||||||
|
&& time - axis->update_time - SCROLL_TIMEOUT)
|
||||||
|
axis->value = 0;
|
||||||
|
|
||||||
|
axis->value += value;
|
||||||
|
axis->update_time = time;
|
||||||
|
pointer->scrolled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete) {
|
||||||
|
struct Pointer *pointer = data;
|
||||||
|
|
||||||
|
pointer->axis[axis].discrete_steps += abs(discrete);
|
||||||
|
pointer->scrolled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_axis_source(void *data, struct wl_pointer *wl_pointer, uint32_t axis_source) {
|
||||||
|
/* Nop */
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) {
|
||||||
|
/* Nop */
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) {
|
||||||
|
struct Pointer *pointer = data;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
if (state == WL_POINTER_BUTTON_STATE_PRESSED && list_cmp_find(pointer->buttons, &button, button_cmp) == -1) {
|
||||||
|
uint32_t *btn = list_add(pointer->buttons, ecalloc(1, sizeof(*btn)));
|
||||||
|
*btn = button;
|
||||||
|
}
|
||||||
|
else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
|
||||||
|
(index = list_cmp_find(pointer->buttons, &button, button_cmp)) != -1) {
|
||||||
|
free(list_remove(pointer->buttons, index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Pointer *pointer_create(struct wl_seat *seat) {
|
||||||
|
if (!seat) return NULL;
|
||||||
|
|
||||||
|
struct Pointer *pointer = ecalloc(1, sizeof(*pointer));
|
||||||
|
pointer->pointer = wl_seat_get_pointer(seat);
|
||||||
|
pointer->scrolled = 0;
|
||||||
|
pointer->buttons = list_create(0);
|
||||||
|
pointer->focused_monitor = NULL;
|
||||||
|
pointer->cursor_surface = NULL;
|
||||||
|
pointer->cursor_image = NULL;
|
||||||
|
pointer->cursor_theme = NULL;
|
||||||
|
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_destroy(struct Pointer *pointer) {
|
||||||
|
if (!pointer) return;
|
||||||
|
|
||||||
|
wl_pointer_release(pointer->pointer);
|
||||||
|
wl_surface_destroy(pointer->cursor_surface);
|
||||||
|
wl_cursor_theme_destroy(pointer->cursor_theme);
|
||||||
|
list_elements_destroy(pointer->buttons, free);
|
||||||
|
free(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
|
||||||
|
struct Pointer *pointer = data;
|
||||||
|
pointer->focused_monitor = monitor_from_surface(surface);
|
||||||
|
if (!pointer->focused_monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pointer_update_cursor(pointer);
|
||||||
|
wl_pointer_set_cursor(wl_pointer, serial, pointer->cursor_surface,
|
||||||
|
pointer->cursor_image->hotspot_x, pointer->cursor_image->hotspot_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_frame(void *data, struct wl_pointer *wl_pointer) {
|
||||||
|
struct Pointer *pointer = data;
|
||||||
|
struct Monitor *monitor = pointer->focused_monitor;
|
||||||
|
if (!monitor) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < pointer->buttons->length; i++)
|
||||||
|
hotspots_process(pointer->focused_monitor, pointer->x, pointer->y,
|
||||||
|
*(uint32_t*)pointer->buttons->data[i]);
|
||||||
|
list_elements_destroy(pointer->buttons, free);
|
||||||
|
pointer->buttons = list_create(0);
|
||||||
|
|
||||||
|
if (pointer->scrolled) {
|
||||||
|
for (int i = 0; i < 2; i++)
|
||||||
|
pointer_process_scroll(pointer, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_process_scroll(struct Pointer *pointer, unsigned int axis_index) {
|
||||||
|
struct Axis *axis = &pointer->axis[axis_index];
|
||||||
|
if (axis->discrete_steps) {
|
||||||
|
for (int i = 0; i < axis->discrete_steps; i++)
|
||||||
|
hotspots_process(pointer->focused_monitor, pointer->x, pointer->y, wl_axis_to_button(axis_index, axis->value));
|
||||||
|
axis->value = 0;
|
||||||
|
axis->discrete_steps = 0;
|
||||||
|
} else {
|
||||||
|
while (abs(axis->value) > SCROLL_THRESHOLD) {
|
||||||
|
if (axis->value > 0){
|
||||||
|
hotspots_process(pointer->focused_monitor, pointer->x, pointer->y, wl_axis_to_button(axis_index, SCROLL_THRESHOLD));
|
||||||
|
axis->value -= SCROLL_THRESHOLD;
|
||||||
|
} else {
|
||||||
|
hotspots_process(pointer->focused_monitor, pointer->x, pointer->y, wl_axis_to_button(axis_index, -SCROLL_THRESHOLD));
|
||||||
|
axis->value += SCROLL_THRESHOLD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface) {
|
||||||
|
struct Pointer *pointer = data;
|
||||||
|
pointer->focused_monitor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) {
|
||||||
|
struct Pointer *pointer = data;
|
||||||
|
pointer->x = wl_fixed_to_double(surface_x);
|
||||||
|
pointer->y = wl_fixed_to_double(surface_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointer_update_cursor(struct Pointer *pointer) {
|
||||||
|
if (!pointer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!pointer->cursor_surface)
|
||||||
|
pointer->cursor_surface = wl_compositor_create_surface(compositor);
|
||||||
|
|
||||||
|
if (pointer->cursor_theme)
|
||||||
|
wl_cursor_theme_destroy(pointer->cursor_theme);
|
||||||
|
|
||||||
|
unsigned int cursor_size = 24;
|
||||||
|
const char *cursor_theme = getenv("XCURSOR_THEME");
|
||||||
|
const char *env_cursor_size = getenv("XCURSOR_SIZE");
|
||||||
|
if (env_cursor_size && strlen(env_cursor_size) > 0) {
|
||||||
|
errno = 0;
|
||||||
|
char *end;
|
||||||
|
unsigned int size = strtoul(env_cursor_size, &end, 10);
|
||||||
|
if (!*end && errno == 0)
|
||||||
|
cursor_size = size;
|
||||||
|
}
|
||||||
|
pointer->cursor_theme = wl_cursor_theme_load(cursor_theme, cursor_size, shm);
|
||||||
|
pointer->cursor_image = wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr")->images[0];
|
||||||
|
wl_surface_attach(pointer->cursor_surface, wl_cursor_image_get_buffer(pointer->cursor_image), 0, 0);
|
||||||
|
wl_surface_commit(pointer->cursor_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hotspots_process(struct Monitor* monitor, double x, double y, uint32_t button) {
|
||||||
|
struct Hotspot *hotspot;
|
||||||
|
for (int i = 0; i < monitor->hotspots->length; i++) {
|
||||||
|
hotspot = monitor->hotspots->data[i];
|
||||||
|
|
||||||
|
double hotspot_x = 0, hotspot_y = 0, hotspot_width = 0, hotspot_height = 0;
|
||||||
|
hotspot->listener->bounds(hotspot->data, &hotspot_x, &hotspot_y, &hotspot_width, &hotspot_height);
|
||||||
|
|
||||||
|
if (!( x > hotspot_x && y > hotspot_y &&
|
||||||
|
x < (hotspot_x+hotspot_width) && y < (hotspot_y+hotspot_height)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hotspot->listener->click(monitor, hotspot->data, button, x, y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities) {
|
||||||
|
struct Seat *seat = data;
|
||||||
|
int has_pointer = capabilities & WL_SEAT_CAPABILITY_POINTER,
|
||||||
|
has_touch = capabilities & WL_SEAT_CAPABILITY_TOUCH;
|
||||||
|
|
||||||
|
if (!seat->pointer && has_pointer) {
|
||||||
|
seat->pointer = pointer_create(seat->seat);
|
||||||
|
wl_pointer_add_listener(seat->pointer->pointer, &pointer_listener, seat->pointer);
|
||||||
|
}
|
||||||
|
else if (seat->pointer && !has_pointer) {
|
||||||
|
pointer_destroy(seat->pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!seat->touch && has_touch) {
|
||||||
|
seat->touch = touch_create(seat->seat);
|
||||||
|
wl_touch_add_listener(seat->touch->touch, &touch_listener, seat->touch);
|
||||||
|
}
|
||||||
|
else if (seat->touch && !has_touch) {
|
||||||
|
touch_destroy(seat->touch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void seat_destroy(struct Seat *seat) {
|
||||||
|
if (!seat) return;
|
||||||
|
|
||||||
|
pointer_destroy(seat->pointer);
|
||||||
|
touch_destroy(seat->touch);
|
||||||
|
wl_seat_release(seat->seat);
|
||||||
|
free(seat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void seat_name(void *data, struct wl_seat *wl_seat, const char *name) {
|
||||||
|
/* Nop */
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_cancel(void *data, struct wl_touch *wl_touch) {
|
||||||
|
struct Touch *touch = data;
|
||||||
|
struct TouchPoint *point;
|
||||||
|
for (int i = 0; i < LENGTH(touch->points); i++) {
|
||||||
|
point = &touch->points[i];
|
||||||
|
point->id = -1;
|
||||||
|
point->focused_monitor = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Touch *touch_create(struct wl_seat *seat) {
|
||||||
|
if (!seat) return NULL;
|
||||||
|
|
||||||
|
struct Touch *touch = ecalloc(1, sizeof(*touch));
|
||||||
|
touch->touch = wl_seat_get_touch(seat);
|
||||||
|
struct TouchPoint *point;
|
||||||
|
for (int i = 0; i < LENGTH(touch->points); i++) {
|
||||||
|
point = &touch->points[i];
|
||||||
|
point->id = -1;
|
||||||
|
point->focused_monitor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_destroy(struct Touch *touch) {
|
||||||
|
if (!touch) return;
|
||||||
|
|
||||||
|
wl_touch_release(touch->touch);
|
||||||
|
free(touch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time,
|
||||||
|
struct wl_surface *surface, int32_t id, wl_fixed_t x, wl_fixed_t y) {
|
||||||
|
struct Touch *touch = data;
|
||||||
|
struct TouchPoint *point = touch_get_point(touch, id);
|
||||||
|
if (!point)
|
||||||
|
return;
|
||||||
|
|
||||||
|
point->focused_monitor = monitor_from_surface(surface);
|
||||||
|
if (!point->focused_monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
point->id = id;
|
||||||
|
point->time = time;
|
||||||
|
point->start_x = wl_fixed_to_double(x);
|
||||||
|
point->start_y = wl_fixed_to_double(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_frame(void *data, struct wl_touch *wl_touch) {
|
||||||
|
/* Nop */
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TouchPoint *touch_get_point(struct Touch *touch, int32_t id) {
|
||||||
|
struct TouchPoint *point;
|
||||||
|
int empty_index = -1;
|
||||||
|
for (int i = 0; i < LENGTH(touch->points); i++) {
|
||||||
|
point = &touch->points[i];
|
||||||
|
if (point->id == id) {
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
if (!point->focused_monitor && point->id == -1)
|
||||||
|
empty_index = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty_index == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &touch->points[empty_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) {
|
||||||
|
struct Touch *touch = data;
|
||||||
|
struct TouchPoint *point = touch_get_point(touch, id);
|
||||||
|
if (!point)
|
||||||
|
return;
|
||||||
|
|
||||||
|
point->time = time;
|
||||||
|
point->x = wl_fixed_to_double(x);
|
||||||
|
point->y = wl_fixed_to_double(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_orientation(void *data, struct wl_touch *wl_touch, int32_t id, wl_fixed_t orientation) {
|
||||||
|
/* Nop */
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t touch_point_to_button(struct TouchPoint *point, uint32_t time) {
|
||||||
|
/* "progress" is a measure from 0..100 representing the fraction of the
|
||||||
|
* output the touch gesture has travelled, positive when moving to the right
|
||||||
|
* and negative when moving to the left. */
|
||||||
|
int progress = (int)((point->x - point->start_x) / point->focused_monitor->pipeline->shm->width * 100);
|
||||||
|
if (abs(progress) > 20)
|
||||||
|
return (progress > 0 ? Gesture_Right : Gesture_Left);
|
||||||
|
|
||||||
|
if (time - point->time < 500)
|
||||||
|
return BTN_LEFT;
|
||||||
|
if (time - point->time < 1000)
|
||||||
|
return BTN_RIGHT;
|
||||||
|
|
||||||
|
/* If hold time is longer than 1 second then it is a middle click. */
|
||||||
|
return BTN_MIDDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_shape(void *data, struct wl_touch *wl_touch, int32_t id, wl_fixed_t major, wl_fixed_t minor) {
|
||||||
|
/* Nop */
|
||||||
|
}
|
||||||
|
|
||||||
|
void touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, uint32_t time, int32_t id) {
|
||||||
|
struct Touch *touch = data;
|
||||||
|
struct TouchPoint *point = touch_get_point(touch, id);
|
||||||
|
if (!point) return;
|
||||||
|
|
||||||
|
uint32_t button = touch_point_to_button(point, time);
|
||||||
|
hotspots_process(point->focused_monitor, point->x, point->y, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t wl_axis_to_button(int axis, wl_fixed_t value) {
|
||||||
|
int negative = wl_fixed_to_double(value) < 0;
|
||||||
|
switch (axis) {
|
||||||
|
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
||||||
|
return negative ? Scroll_Up : Scroll_Down;
|
||||||
|
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
|
||||||
|
return negative ? Scroll_Left : Scroll_Right;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
68
user/.config/suckless/dwl-bar/src/input.h
Normal file
68
user/.config/suckless/dwl-bar/src/input.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#ifndef INPUT_H_
|
||||||
|
#define INPUT_H_
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "user.h"
|
||||||
|
#include <wayland-util.h>
|
||||||
|
#include <wayland-cursor.h>
|
||||||
|
|
||||||
|
#define SCROLL_TIMEOUT 1000
|
||||||
|
#define SCROLL_THRESHOLD 10000
|
||||||
|
|
||||||
|
struct TouchPoint {
|
||||||
|
int32_t id;
|
||||||
|
uint32_t time;
|
||||||
|
struct Monitor *focused_monitor;
|
||||||
|
double start_x, start_y,
|
||||||
|
x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Touch {
|
||||||
|
struct wl_touch *touch;
|
||||||
|
struct TouchPoint points[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Axis {
|
||||||
|
wl_fixed_t value;
|
||||||
|
uint32_t discrete_steps, update_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Pointer {
|
||||||
|
struct wl_pointer *pointer;
|
||||||
|
struct Monitor *focused_monitor;
|
||||||
|
|
||||||
|
struct wl_cursor_theme *cursor_theme;
|
||||||
|
struct wl_cursor_image *cursor_image;
|
||||||
|
struct wl_surface *cursor_surface;
|
||||||
|
|
||||||
|
double x, y;
|
||||||
|
struct List *buttons; /* uint32_t* */
|
||||||
|
struct Axis axis[2];
|
||||||
|
int scrolled;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Seat {
|
||||||
|
uint32_t wl_name;
|
||||||
|
struct wl_seat *seat;
|
||||||
|
struct Pointer *pointer;
|
||||||
|
struct Touch *touch;
|
||||||
|
|
||||||
|
struct wl_list link;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HotspotListener {
|
||||||
|
void (*click)(struct Monitor *monitor, void *data, uint32_t button, double x, double y);
|
||||||
|
void (*bounds)(void *data, double *x, double *y, double *width, double *height);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Hotspot {
|
||||||
|
const struct HotspotListener *listener;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct wl_seat_listener seat_listener;
|
||||||
|
|
||||||
|
void seat_destroy(struct Seat *seat);
|
||||||
|
|
||||||
|
#endif // INPUT_H_
|
44
user/.config/suckless/dwl-bar/src/log.c
Normal file
44
user/.config/suckless/dwl-bar/src/log.c
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#include "log.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
FILE *log_file = NULL;
|
||||||
|
|
||||||
|
void bar_log(enum LogLevel level, const char *fmt, ...) {
|
||||||
|
if (!log_file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
switch (level) {
|
||||||
|
case LOG_INFO:
|
||||||
|
fprintf(log_file, "[dwl-bar] info: ");
|
||||||
|
break;
|
||||||
|
case LOG_ERROR:
|
||||||
|
fprintf(log_file, "[dwl-bar] error: ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vfprintf(log_file, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
fputc('\n', log_file);
|
||||||
|
|
||||||
|
fflush(log_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_destroy(void) {
|
||||||
|
if (!log_file)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fclose(log_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
int setup_log(void) {
|
||||||
|
log_file = fopen("bar.log", "w");
|
||||||
|
if (!log_file)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bar_log(LOG_INFO, "Setup Logging");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
10
user/.config/suckless/dwl-bar/src/log.h
Normal file
10
user/.config/suckless/dwl-bar/src/log.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef LOG_H_
|
||||||
|
#define LOG_H_
|
||||||
|
|
||||||
|
enum LogLevel { LOG_INFO, LOG_ERROR };
|
||||||
|
|
||||||
|
void bar_log(enum LogLevel level, const char *fmt, ...);
|
||||||
|
void log_destroy(void);
|
||||||
|
int setup_log(void);
|
||||||
|
|
||||||
|
#endif // LOG_H_
|
532
user/.config/suckless/dwl-bar/src/main.c
Normal file
532
user/.config/suckless/dwl-bar/src/main.c
Normal file
|
@ -0,0 +1,532 @@
|
||||||
|
#include "bar.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "dwl-ipc-unstable-v2-protocol.h"
|
||||||
|
#include "event.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "xdg-shell-protocol.h"
|
||||||
|
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <wayland-client-core.h>
|
||||||
|
#include <wayland-client-protocol.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
|
||||||
|
static void check_global(void *global, const char *name);
|
||||||
|
static void check_globals(void);
|
||||||
|
static void cleanup(void);
|
||||||
|
static void display_in(int fd, short mask, void *data);
|
||||||
|
static void fifo_handle(const char *line);
|
||||||
|
static void fifo_in(int fd, short mask, void *data);
|
||||||
|
static void fifo_setup(void);
|
||||||
|
static void monitor_destroy(struct Monitor *monitor);
|
||||||
|
struct Monitor *monitor_from_surface(const struct wl_surface *surface);
|
||||||
|
static void monitor_initialize(struct Monitor *monitor);
|
||||||
|
static void monitor_update(struct Monitor *monitor);
|
||||||
|
static void pipe_in(int fd, short mask, void *data);
|
||||||
|
static void registry_global_add(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
|
const char *interface, uint32_t version);
|
||||||
|
static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name);
|
||||||
|
static void run(void);
|
||||||
|
static void set_cloexec(int fd);
|
||||||
|
static void setup(void);
|
||||||
|
static void sigaction_handler(int _);
|
||||||
|
static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial);
|
||||||
|
static void zdwl_ipc_manager_layout(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, const char *name);
|
||||||
|
static void zdwl_ipc_manager_tags(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, uint32_t amount);
|
||||||
|
static void zdwl_ipc_output_active(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t active);
|
||||||
|
static void zdwl_ipc_output_appid(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *appid);
|
||||||
|
static void zdwl_ipc_output_floating(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_floating);
|
||||||
|
static void zdwl_ipc_output_frame(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2);
|
||||||
|
static void zdwl_ipc_output_fullscreen(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_fullscreen);
|
||||||
|
static void zdwl_ipc_output_layout(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t layout);
|
||||||
|
static void zdwl_ipc_output_layout_symbol(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *layout);
|
||||||
|
static void zdwl_ipc_output_tag(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2,
|
||||||
|
uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused);
|
||||||
|
static void zdwl_ipc_output_title(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *title);
|
||||||
|
static void zdwl_ipc_output_toggle_visibility(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2);
|
||||||
|
|
||||||
|
static struct xdg_wm_base *base;
|
||||||
|
struct wl_compositor *compositor;
|
||||||
|
static struct wl_display *display;
|
||||||
|
static int display_fd;
|
||||||
|
static struct zdwl_ipc_manager_v2 *dwl_manager = NULL;
|
||||||
|
static struct Events *events;
|
||||||
|
static int fifo_fd;
|
||||||
|
static char *fifo_path;
|
||||||
|
int layoutcount;
|
||||||
|
static struct wl_list monitors; // struct Monitor*
|
||||||
|
static struct zxdg_output_manager_v1 *output_manager;
|
||||||
|
static const struct wl_registry_listener registry_listener = {
|
||||||
|
.global = registry_global_add,
|
||||||
|
.global_remove = registry_global_remove,
|
||||||
|
};
|
||||||
|
static int running = 0;
|
||||||
|
static struct wl_list seats; // struct Seat*
|
||||||
|
static int self_pipe[2];
|
||||||
|
struct zwlr_layer_shell_v1 *shell;
|
||||||
|
struct wl_shm *shm;
|
||||||
|
static int tagcount;
|
||||||
|
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
||||||
|
.ping = xdg_wm_base_ping,
|
||||||
|
};
|
||||||
|
static const struct zdwl_ipc_manager_v2_listener zdwl_manager_listener = {
|
||||||
|
.layout = zdwl_ipc_manager_layout,
|
||||||
|
.tags = zdwl_ipc_manager_tags,
|
||||||
|
};
|
||||||
|
static const struct zdwl_ipc_output_v2_listener zdwl_output_listener = {
|
||||||
|
.active = zdwl_ipc_output_active,
|
||||||
|
.appid = zdwl_ipc_output_appid,
|
||||||
|
.floating = zdwl_ipc_output_floating,
|
||||||
|
.frame = zdwl_ipc_output_frame,
|
||||||
|
.fullscreen = zdwl_ipc_output_fullscreen,
|
||||||
|
.layout = zdwl_ipc_output_layout,
|
||||||
|
.layout_symbol = zdwl_ipc_output_layout_symbol,
|
||||||
|
.tag = zdwl_ipc_output_tag,
|
||||||
|
.title = zdwl_ipc_output_title,
|
||||||
|
.toggle_visibility = zdwl_ipc_output_toggle_visibility,
|
||||||
|
};
|
||||||
|
|
||||||
|
void check_global(void *global, const char *name) {
|
||||||
|
if (global)
|
||||||
|
return;
|
||||||
|
panic("Wayland compositor did not export: %s", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_globals(void) {
|
||||||
|
check_global(base, "xdg_wm_base");
|
||||||
|
check_global(compositor, "wl_compositor");
|
||||||
|
check_global(dwl_manager, "zdwl_ipc_manager_v2");
|
||||||
|
check_global(shell, "zwlr_layer_shell_v1");
|
||||||
|
check_global(shm, "wl_shm");
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup(void) {
|
||||||
|
xdg_wm_base_destroy(base);
|
||||||
|
wl_compositor_destroy(compositor);
|
||||||
|
close(fifo_fd);
|
||||||
|
unlink(fifo_path);
|
||||||
|
free(fifo_path);
|
||||||
|
zwlr_layer_shell_v1_destroy(shell);
|
||||||
|
zdwl_ipc_manager_v2_destroy(dwl_manager);
|
||||||
|
wl_shm_destroy(shm);
|
||||||
|
events_destroy(events);
|
||||||
|
log_destroy();
|
||||||
|
|
||||||
|
struct Monitor *monitor, *tmp_monitor;
|
||||||
|
wl_list_for_each_safe(monitor, tmp_monitor, &monitors, link)
|
||||||
|
monitor_destroy(monitor);
|
||||||
|
|
||||||
|
struct Seat *seat, *tmp_seat;
|
||||||
|
wl_list_for_each_safe(seat, tmp_seat, &seats, link)
|
||||||
|
seat_destroy(seat);
|
||||||
|
|
||||||
|
wl_display_disconnect(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_in(int fd, short mask, void *data) {
|
||||||
|
if (mask & (POLLHUP | POLLERR) ||
|
||||||
|
wl_display_dispatch(display) == -1) {
|
||||||
|
running = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fifo_handle(const char *line) {
|
||||||
|
char *command;
|
||||||
|
unsigned long loc = 0;
|
||||||
|
|
||||||
|
command = to_delimiter(line, &loc, ' ');
|
||||||
|
|
||||||
|
if (STRING_EQUAL(command, "status")) {
|
||||||
|
char *status = to_delimiter(line, &loc, '\n');
|
||||||
|
struct Monitor *pos;
|
||||||
|
wl_list_for_each(pos, &monitors, link) {
|
||||||
|
bar_set_status(pos->bar, status);
|
||||||
|
pipeline_invalidate(pos->pipeline);
|
||||||
|
}
|
||||||
|
free(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fifo_in(int fd, short mask, void *data) {
|
||||||
|
if (mask & POLLERR) {
|
||||||
|
events_remove(events, fd);
|
||||||
|
char *default_status = string_create("dwl %.1f", VERSION);
|
||||||
|
struct Monitor *pos;
|
||||||
|
wl_list_for_each(pos, &monitors, link) {
|
||||||
|
bar_set_status(pos->bar, default_status);
|
||||||
|
pipeline_invalidate(pos->pipeline);
|
||||||
|
}
|
||||||
|
free(default_status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_fd = dup(fd);
|
||||||
|
FILE *fifo_file = fdopen(new_fd, "r");
|
||||||
|
char *buffer = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
while (1) {
|
||||||
|
if (getline(&buffer, &size, fifo_file) == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
fifo_handle(buffer);
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
fclose(fifo_file);
|
||||||
|
close(new_fd);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void fifo_setup(void) {
|
||||||
|
int result, i;
|
||||||
|
char *runtime_path = getenv("XDG_RUNTIME_DIR");
|
||||||
|
|
||||||
|
for (i = 0; i < 100; i++) {
|
||||||
|
fifo_path = string_create("%s/dwl-bar-%d", runtime_path, i);
|
||||||
|
|
||||||
|
result = mkfifo(fifo_path, 0666);
|
||||||
|
if (result < 0) {
|
||||||
|
if (errno != EEXIST)
|
||||||
|
panic("mkfifo");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fifo_fd = open(fifo_path, O_CLOEXEC | O_RDONLY | O_NONBLOCK)) < 0)
|
||||||
|
panic("open fifo");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("setup fifo"); /* If we get here then we couldn't setup the fifo */
|
||||||
|
}
|
||||||
|
|
||||||
|
void monitor_destroy(struct Monitor *monitor) {
|
||||||
|
if (!monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (wl_output_get_version(monitor->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
|
||||||
|
wl_output_release(monitor->wl_output);
|
||||||
|
wl_output_release(monitor->wl_output);
|
||||||
|
zdwl_ipc_output_v2_destroy(monitor->dwl_output);
|
||||||
|
list_elements_destroy(monitor->hotspots, free);
|
||||||
|
pipeline_destroy(monitor->pipeline);
|
||||||
|
bar_destroy(monitor->bar);
|
||||||
|
free(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Monitor *monitor_from_surface(const struct wl_surface *surface) {
|
||||||
|
struct Monitor *pos;
|
||||||
|
wl_list_for_each(pos, &monitors, link) {
|
||||||
|
if (pos->pipeline->surface == surface)
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void monitor_initialize(struct Monitor *monitor) {
|
||||||
|
if (!monitor) return;
|
||||||
|
|
||||||
|
monitor->desired_visibility = show_bar;
|
||||||
|
monitor->hotspots = list_create(1);
|
||||||
|
monitor->pipeline = pipeline_create();
|
||||||
|
monitor->bar = bar_create(monitor->hotspots, monitor->pipeline);
|
||||||
|
if (!monitor->pipeline || !monitor->bar)
|
||||||
|
panic("Failed to create a pipline or bar for a monitor");
|
||||||
|
monitor_update(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void monitor_update(struct Monitor *monitor) {
|
||||||
|
if (!monitor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!pipeline_is_visible(monitor->pipeline) && monitor->desired_visibility) {
|
||||||
|
pipeline_show(monitor->pipeline, monitor->wl_output);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipeline_invalidate(monitor->pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
void monitors_update(void) {
|
||||||
|
struct Monitor *monitor;
|
||||||
|
wl_list_for_each(monitor, &monitors, link) {
|
||||||
|
monitor_update(monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipe_in(int fd, short mask, void *data) {
|
||||||
|
running = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void registry_global_add(void *data, struct wl_registry *registry, uint32_t name,
|
||||||
|
const char *interface, uint32_t version) {
|
||||||
|
if (STRING_EQUAL(interface, wl_compositor_interface.name))
|
||||||
|
compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4);
|
||||||
|
else if (STRING_EQUAL(interface, wl_output_interface.name)) {
|
||||||
|
struct Monitor *monitor = ecalloc(1, sizeof(*monitor));
|
||||||
|
monitor->wl_output = wl_registry_bind(registry, name, &wl_output_interface, 1);
|
||||||
|
monitor->wl_name = name;
|
||||||
|
monitor->dwl_output = NULL;
|
||||||
|
|
||||||
|
wl_list_insert(&monitors, &monitor->link);
|
||||||
|
|
||||||
|
if (!dwl_manager) return;
|
||||||
|
|
||||||
|
monitor->dwl_output = zdwl_ipc_manager_v2_get_output(dwl_manager, monitor->wl_output);
|
||||||
|
zdwl_ipc_output_v2_add_listener(monitor->dwl_output, &zdwl_output_listener, monitor);
|
||||||
|
|
||||||
|
if (!running) return;
|
||||||
|
monitor_initialize(monitor);
|
||||||
|
}
|
||||||
|
else if (STRING_EQUAL(interface, wl_seat_interface.name)) {
|
||||||
|
struct Seat *seat = ecalloc(1, sizeof(*seat));
|
||||||
|
seat->seat = wl_registry_bind(registry, name, &wl_seat_interface, 5);
|
||||||
|
seat->wl_name = name;
|
||||||
|
seat->pointer = NULL;
|
||||||
|
seat->touch = NULL;
|
||||||
|
wl_list_insert(&seats, &seat->link);
|
||||||
|
wl_seat_add_listener(seat->seat, &seat_listener, seat);
|
||||||
|
}
|
||||||
|
else if (STRING_EQUAL(interface, wl_shm_interface.name))
|
||||||
|
shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
||||||
|
else if (STRING_EQUAL(interface, xdg_wm_base_interface.name)) {
|
||||||
|
base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 2);
|
||||||
|
xdg_wm_base_add_listener(base, &xdg_wm_base_listener, NULL);
|
||||||
|
}
|
||||||
|
else if (STRING_EQUAL(interface, zdwl_ipc_manager_v2_interface.name)) {
|
||||||
|
dwl_manager = wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 2);
|
||||||
|
zdwl_ipc_manager_v2_add_listener(dwl_manager, &zdwl_manager_listener, NULL);
|
||||||
|
|
||||||
|
struct Monitor *monitor;
|
||||||
|
wl_list_for_each(monitor, &monitors, link) {
|
||||||
|
if (monitor->dwl_output) continue;
|
||||||
|
|
||||||
|
monitor->dwl_output = zdwl_ipc_manager_v2_get_output(dwl_manager, monitor->wl_output);
|
||||||
|
zdwl_ipc_output_v2_add_listener(monitor->dwl_output, &zdwl_output_listener, monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (STRING_EQUAL(interface, zwlr_layer_shell_v1_interface.name))
|
||||||
|
shell = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
|
||||||
|
struct Monitor *monitor, *tmp_monitor;
|
||||||
|
wl_list_for_each_safe(monitor, tmp_monitor, &monitors, link) {
|
||||||
|
if (monitor->wl_name != name) continue;
|
||||||
|
wl_list_remove(&monitor->link);
|
||||||
|
monitor_destroy(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Seat *seat, *tmp_seat;
|
||||||
|
wl_list_for_each_safe(seat, tmp_seat, &seats, link) {
|
||||||
|
if (seat->wl_name != name) continue;
|
||||||
|
wl_list_remove(&seat->link);
|
||||||
|
seat_destroy(seat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run(void) {
|
||||||
|
running = 1;
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
wl_display_dispatch_pending(display);
|
||||||
|
if (wl_display_flush(display) == -1 && errno != EAGAIN)
|
||||||
|
break;
|
||||||
|
|
||||||
|
events_poll(events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_cloexec(int fd) {
|
||||||
|
int flags = fcntl(fd, F_GETFD);
|
||||||
|
if (flags == -1)
|
||||||
|
panic("F_GETFD");
|
||||||
|
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
|
||||||
|
panic("FD_SETFD");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
if (pipe(self_pipe) == -1)
|
||||||
|
panic("pipe");
|
||||||
|
|
||||||
|
set_cloexec(self_pipe[0]);
|
||||||
|
set_cloexec(self_pipe[1]);
|
||||||
|
|
||||||
|
static struct sigaction sighandle;
|
||||||
|
static struct sigaction child_sigaction;
|
||||||
|
|
||||||
|
sighandle.sa_handler = &sigaction_handler;
|
||||||
|
child_sigaction.sa_handler = SIG_IGN;
|
||||||
|
|
||||||
|
if (sigaction(SIGTERM, &sighandle, NULL) < 0)
|
||||||
|
panic("sigaction SIGTERM");
|
||||||
|
if (sigaction(SIGINT, &sighandle, NULL) < 0)
|
||||||
|
panic("sigaction SIGINT");
|
||||||
|
if (sigaction(SIGCHLD, &child_sigaction, NULL) < 0)
|
||||||
|
panic("sigaction SIGCHLD");
|
||||||
|
|
||||||
|
display = wl_display_connect(NULL);
|
||||||
|
if (!display)
|
||||||
|
panic("Failed to connect to Wayland compositor.");
|
||||||
|
display_fd = wl_display_get_fd(display);
|
||||||
|
|
||||||
|
wl_list_init(&seats);
|
||||||
|
wl_list_init(&monitors);
|
||||||
|
|
||||||
|
struct wl_registry *registry = wl_display_get_registry(display);
|
||||||
|
wl_registry_add_listener(registry, ®istry_listener, NULL);
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
fifo_setup();
|
||||||
|
|
||||||
|
check_globals();
|
||||||
|
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
if (tagcount != LENGTH(tags))
|
||||||
|
panic("We do not have the same amount of tags as dwl! Please check config.def.h!");
|
||||||
|
|
||||||
|
struct Monitor *monitor;
|
||||||
|
wl_list_for_each(monitor, &monitors, link) {
|
||||||
|
monitor_initialize(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) < 0)
|
||||||
|
panic("STDIN_FILENO O_NONBLOCK");
|
||||||
|
|
||||||
|
events = events_create();
|
||||||
|
events_add(events, display_fd, POLLIN, NULL, display_in);
|
||||||
|
events_add(events, self_pipe[0], POLLIN, NULL, pipe_in);
|
||||||
|
events_add(events, fifo_fd, POLLIN, NULL, fifo_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sigaction_handler(int _) {
|
||||||
|
if (write(self_pipe[1], "0", 1) < 0)
|
||||||
|
panic("sigaction_handler");
|
||||||
|
}
|
||||||
|
|
||||||
|
void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) {
|
||||||
|
xdg_wm_base_pong(xdg_wm_base, serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_manager_layout(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, const char *name) {
|
||||||
|
layoutcount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_manager_tags(void *data, struct zdwl_ipc_manager_v2 *zdwl_ipc_manager_v2, uint32_t amount) {
|
||||||
|
tagcount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_output_active(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t active) {
|
||||||
|
struct Monitor *monitor = data;
|
||||||
|
bar_set_active(monitor->bar, active);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_output_appid(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *appid) {
|
||||||
|
/* Nop */
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_output_floating(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_floating) {
|
||||||
|
struct Monitor *monitor = data;
|
||||||
|
bar_set_floating(monitor->bar, is_floating);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_output_frame(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2) {
|
||||||
|
struct Monitor *monitor = data;
|
||||||
|
monitor_update(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_output_fullscreen(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t is_fullscreen) {
|
||||||
|
/* Nop */
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_output_layout(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t layout) {
|
||||||
|
struct Monitor *monitor = data;
|
||||||
|
monitor->layout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_output_layout_symbol(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *layout) {
|
||||||
|
struct Monitor *monitor = data;
|
||||||
|
bar_set_layout(monitor->bar, layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_output_tag(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) {
|
||||||
|
struct Monitor *monitor = data;
|
||||||
|
bar_set_tag(monitor->bar, tag, state, clients ? 1 : 0, focused);
|
||||||
|
monitor->tags = (state & ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE) ? monitor->tags | (1 << tag) : monitor->tags & ~(1 << tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_output_title(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2, const char *title) {
|
||||||
|
struct Monitor *monitor = data;
|
||||||
|
bar_set_title(monitor->bar, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zdwl_ipc_output_toggle_visibility(void *data, struct zdwl_ipc_output_v2 *zdwl_ipc_output_v2) {
|
||||||
|
struct Monitor *monitor = data;
|
||||||
|
monitor->desired_visibility ^= 1;
|
||||||
|
pipeline_hide(monitor->pipeline);
|
||||||
|
monitor_update(monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int opt;
|
||||||
|
while((opt = getopt(argc, argv, "l")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'l':
|
||||||
|
if (!setup_log())
|
||||||
|
panic("Failed to setup logging");
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
printf("Usage: %s [-h] [-v]\n", argv[0]);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
case 'v':
|
||||||
|
printf("%s %.1f\n", argv[0], VERSION);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
case '?':
|
||||||
|
printf("Invalid Argument\n");
|
||||||
|
printf("Usage: %s [-h] [-v] [-l]\n", argv[0]);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setup();
|
||||||
|
run();
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void panic(const char *fmt, ...) {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
fprintf(stderr, "[dwl-bar] panic: ");
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (fmt[0] && fmt[strlen(fmt) - 1] == ':') {
|
||||||
|
fputc(' ', stderr);
|
||||||
|
perror(NULL);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fputc('\n', stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
33
user/.config/suckless/dwl-bar/src/main.h
Normal file
33
user/.config/suckless/dwl-bar/src/main.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef MAIN_H_
|
||||||
|
#define MAIN_H_
|
||||||
|
|
||||||
|
#include "dwl-ipc-unstable-v2-protocol.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <wayland-client.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
|
||||||
|
#define VERSION 0.0
|
||||||
|
|
||||||
|
struct Monitor {
|
||||||
|
uint32_t wl_name;
|
||||||
|
|
||||||
|
unsigned int desired_visibility, tags, layout;
|
||||||
|
struct wl_output *wl_output;
|
||||||
|
struct zdwl_ipc_output_v2 *dwl_output;
|
||||||
|
struct Pipeline *pipeline;
|
||||||
|
struct List *hotspots; /* struct Hotspot* */
|
||||||
|
struct Bar *bar;
|
||||||
|
|
||||||
|
struct wl_list link;
|
||||||
|
};
|
||||||
|
|
||||||
|
void panic(const char *fmt, ...);
|
||||||
|
void monitors_update(void);
|
||||||
|
struct Monitor *monitor_from_surface(const struct wl_surface *surface);
|
||||||
|
|
||||||
|
extern struct wl_compositor *compositor;
|
||||||
|
extern struct zwlr_layer_shell_v1 *shell;
|
||||||
|
extern struct wl_shm *shm;
|
||||||
|
extern int layoutcount;
|
||||||
|
|
||||||
|
#endif // MAIN_H_
|
272
user/.config/suckless/dwl-bar/src/render.c
Normal file
272
user/.config/suckless/dwl-bar/src/render.c
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
#include "render.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "shm.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||||
|
#include "pango/pango-layout.h"
|
||||||
|
#include "pango/pangocairo.h"
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <wayland-client-protocol.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
|
||||||
|
static struct Font *get_font(void);
|
||||||
|
static void pipeline_frame(void* data, struct wl_callback* callback, uint32_t callback_data);
|
||||||
|
static void pipeline_layer_surface(void* data, struct zwlr_layer_surface_v1* _, uint32_t serial, uint32_t width, uint32_t height);
|
||||||
|
static void pipeline_render(struct Pipeline *pipeline);
|
||||||
|
|
||||||
|
const struct wl_callback_listener frame_listener = {.done = pipeline_frame};
|
||||||
|
const struct zwlr_layer_surface_v1_listener layer_surface_listener = {.configure = pipeline_layer_surface};
|
||||||
|
|
||||||
|
struct BasicComponent *basic_component_create(PangoContext *context, PangoFontDescription *description) {
|
||||||
|
struct BasicComponent *component = ecalloc(1, sizeof(*component));
|
||||||
|
component->layout = pango_layout_new(context);
|
||||||
|
pango_layout_set_font_description(component->layout, description);
|
||||||
|
component->x = 0;
|
||||||
|
component->y = 0;
|
||||||
|
component->width = 0;
|
||||||
|
component->height = 0;
|
||||||
|
component->tx = 0;
|
||||||
|
component->ty = 0;
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
void basic_component_destroy(struct BasicComponent *component) {
|
||||||
|
if (!component)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_object_unref(component->layout);
|
||||||
|
free(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
int basic_component_is_clicked(struct BasicComponent *component, double x, double y) {
|
||||||
|
return (x > component->x && y > component->y &&
|
||||||
|
x < (component->x + component->width) && y < (component->y + component->height));
|
||||||
|
}
|
||||||
|
|
||||||
|
void basic_component_render(struct BasicComponent *component, struct Pipeline *pipeline,
|
||||||
|
cairo_t *painter, int *x, int *y) {
|
||||||
|
if (!component)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pango_cairo_update_layout(painter, component->layout);
|
||||||
|
component->x = *x;
|
||||||
|
component->y = *y;
|
||||||
|
|
||||||
|
pipeline_color_background(pipeline, painter);
|
||||||
|
cairo_rectangle(painter, *x, *y, component->width, component->height);
|
||||||
|
cairo_fill(painter);
|
||||||
|
|
||||||
|
pipeline_color_foreground(pipeline, painter);
|
||||||
|
cairo_move_to(painter, *x+component->tx, *y+component->ty);
|
||||||
|
pango_cairo_show_layout(painter, component->layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int basic_component_text_width(struct BasicComponent *component) {
|
||||||
|
if (!component)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int w;
|
||||||
|
pango_layout_get_size(component->layout, &w, NULL);
|
||||||
|
return PANGO_PIXELS(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Font *get_font(void) {
|
||||||
|
PangoFontMap* map = pango_cairo_font_map_get_default();
|
||||||
|
if (!map)
|
||||||
|
panic("font map");
|
||||||
|
|
||||||
|
PangoFontDescription* desc = pango_font_description_from_string(font);
|
||||||
|
if (!desc)
|
||||||
|
panic("font description");
|
||||||
|
|
||||||
|
PangoContext* context = pango_font_map_create_context(map);
|
||||||
|
if (!context)
|
||||||
|
panic("temp context");
|
||||||
|
|
||||||
|
PangoFont* fnt = pango_font_map_load_font(map, context, desc);
|
||||||
|
if (!fnt)
|
||||||
|
panic("font load");
|
||||||
|
|
||||||
|
PangoFontMetrics* metrics = pango_font_get_metrics(fnt, pango_language_get_default());
|
||||||
|
if (!metrics)
|
||||||
|
panic("font metrics");
|
||||||
|
|
||||||
|
struct Font *font = ecalloc(1, sizeof(*font));
|
||||||
|
font->description = desc;
|
||||||
|
font->height = PANGO_PIXELS(pango_font_metrics_get_height(metrics));
|
||||||
|
font->approx_width = PANGO_PIXELS(pango_font_metrics_get_approximate_char_width(metrics));
|
||||||
|
|
||||||
|
pango_font_metrics_unref(metrics);
|
||||||
|
g_object_unref(fnt);
|
||||||
|
g_object_unref(context);
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_add(struct Pipeline *pipeline, const struct PipelineListener *listener, void *data) {
|
||||||
|
if (!pipeline)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct PipelineCallback *callback = list_add(pipeline->callbacks, ecalloc(1, sizeof(*callback)));
|
||||||
|
callback->listener = listener;
|
||||||
|
callback->data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Pipeline *pipeline_create(void) {
|
||||||
|
struct Pipeline *pipeline = ecalloc(1, sizeof(*pipeline));
|
||||||
|
pipeline->callbacks = list_create(0);
|
||||||
|
pipeline->current = 0;
|
||||||
|
pipeline->invalid = 0;
|
||||||
|
pipeline->context = pango_font_map_create_context(pango_cairo_font_map_get_default());
|
||||||
|
pipeline->font = get_font();
|
||||||
|
pipeline->shm = NULL;
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_destroy(struct Pipeline *pipeline) {
|
||||||
|
if (!pipeline)
|
||||||
|
return;
|
||||||
|
|
||||||
|
list_elements_destroy(pipeline->callbacks, free);
|
||||||
|
g_object_unref(pipeline->context);
|
||||||
|
pango_font_description_free(pipeline->font->description);
|
||||||
|
free(pipeline->font);
|
||||||
|
shm_destroy(pipeline->shm);
|
||||||
|
wl_surface_destroy(pipeline->surface);
|
||||||
|
zwlr_layer_surface_v1_destroy(pipeline->layer_surface);
|
||||||
|
free(pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_frame(void* data, struct wl_callback* callback, uint32_t callback_data) {
|
||||||
|
pipeline_render((struct Pipeline *)data);
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipeline_get_future_widths(struct Pipeline *pipeline) {
|
||||||
|
if (!pipeline)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int width = 0;
|
||||||
|
struct PipelineCallback *callback;
|
||||||
|
for (int i = pipeline->callbacks->length-1; i > pipeline->current; i--) {
|
||||||
|
callback = pipeline->callbacks->data[i];
|
||||||
|
width += callback->listener->width(pipeline, callback->data, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_hide(struct Pipeline *pipeline) {
|
||||||
|
if (!pipeline || !pipeline_is_visible(pipeline))
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
zwlr_layer_surface_v1_destroy(pipeline->layer_surface);
|
||||||
|
wl_surface_destroy(pipeline->surface);
|
||||||
|
shm_destroy(pipeline->shm);
|
||||||
|
|
||||||
|
pipeline->layer_surface = NULL;
|
||||||
|
pipeline->surface = NULL;
|
||||||
|
pipeline->shm = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_invalidate(struct Pipeline *pipeline) {
|
||||||
|
if (!pipeline || pipeline->invalid || !pipeline_is_visible(pipeline))
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct wl_callback *callback = wl_surface_frame(pipeline->surface);
|
||||||
|
wl_callback_add_listener(callback, &frame_listener, pipeline);
|
||||||
|
wl_surface_commit(pipeline->surface);
|
||||||
|
pipeline->invalid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pipeline_is_visible(struct Pipeline *pipeline) {
|
||||||
|
if (!pipeline) return 0;
|
||||||
|
return !(!pipeline->surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_layer_surface(void* data, struct zwlr_layer_surface_v1* _,
|
||||||
|
uint32_t serial, uint32_t width, uint32_t height) {
|
||||||
|
struct Pipeline *pipeline = data;
|
||||||
|
zwlr_layer_surface_v1_ack_configure(pipeline->layer_surface, serial);
|
||||||
|
|
||||||
|
if (pipeline->shm) {
|
||||||
|
if (pipeline->shm->width == width && pipeline->shm->height == height)
|
||||||
|
return;
|
||||||
|
shm_destroy(pipeline->shm);
|
||||||
|
}
|
||||||
|
|
||||||
|
pipeline->shm = shm_create(width, height, WL_SHM_FORMAT_XRGB8888);
|
||||||
|
pipeline_render(pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_render(struct Pipeline *pipeline) {
|
||||||
|
if (!pipeline || !pipeline->shm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int x = 0, y = 0;
|
||||||
|
cairo_surface_t *image = cairo_image_surface_create_for_data(shm_data(pipeline->shm),
|
||||||
|
CAIRO_FORMAT_ARGB32, pipeline->shm->width, pipeline->shm->height, pipeline->shm->stride);
|
||||||
|
cairo_t *painter = cairo_create(image);
|
||||||
|
pango_cairo_update_context(painter, pipeline->context);
|
||||||
|
|
||||||
|
struct PipelineCallback *callback;
|
||||||
|
for (int i = 0; i < pipeline->callbacks->length; i++) {
|
||||||
|
pipeline->current = i;
|
||||||
|
callback = pipeline->callbacks->data[i];
|
||||||
|
callback->listener->render(pipeline, callback->data, painter, &x, &y);
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_surface_attach(pipeline->surface, shm_buffer(pipeline->shm), 0, 0);
|
||||||
|
wl_surface_damage(pipeline->surface, 0, 0, pipeline->shm->width, pipeline->shm->height);
|
||||||
|
wl_surface_commit(pipeline->surface);
|
||||||
|
|
||||||
|
cairo_destroy(painter);
|
||||||
|
cairo_surface_destroy(image);
|
||||||
|
|
||||||
|
shm_flip(pipeline->shm);
|
||||||
|
pipeline->invalid = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_show(struct Pipeline *pipeline, struct wl_output *output) {
|
||||||
|
if (!pipeline || !output || pipeline_is_visible(pipeline))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pipeline->surface = wl_compositor_create_surface(compositor);
|
||||||
|
pipeline->layer_surface = zwlr_layer_shell_v1_get_layer_surface(shell, pipeline->surface, output,
|
||||||
|
ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "doom.dwl-bar");
|
||||||
|
zwlr_layer_surface_v1_add_listener(pipeline->layer_surface, &layer_surface_listener, pipeline);
|
||||||
|
|
||||||
|
int anchor = bar_top ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
|
||||||
|
zwlr_layer_surface_v1_set_anchor(pipeline->layer_surface,
|
||||||
|
anchor | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT);
|
||||||
|
|
||||||
|
int height = pipeline->font->height + 2;
|
||||||
|
zwlr_layer_surface_v1_set_size(pipeline->layer_surface, 0, height);
|
||||||
|
zwlr_layer_surface_v1_set_exclusive_zone(pipeline->layer_surface, height);
|
||||||
|
wl_surface_commit(pipeline->surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_set_colorscheme(struct Pipeline* pipeline, const int **scheme) {
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
pipeline->foreground[i] = scheme[0][i];
|
||||||
|
pipeline->background[i] = scheme[1][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_color_foreground(struct Pipeline* pipeline, cairo_t *painter) {
|
||||||
|
set_color(painter, pipeline->foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pipeline_color_background(struct Pipeline* pipeline, cairo_t *painter) {
|
||||||
|
set_color(painter, pipeline->background);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_color(cairo_t *painter, const int rgba[4]) {
|
||||||
|
cairo_set_source_rgba(painter, rgba[0]/255.0, rgba[1]/255.0, rgba[2]/255.0, rgba[3]/255.0);
|
||||||
|
}
|
71
user/.config/suckless/dwl-bar/src/render.h
Normal file
71
user/.config/suckless/dwl-bar/src/render.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#ifndef RENDER_H_
|
||||||
|
#define RENDER_H_
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "shm.h"
|
||||||
|
#include "user.h"
|
||||||
|
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||||
|
#include "pango/pango-types.h"
|
||||||
|
#include <pango/pango.h>
|
||||||
|
#include <cairo.h>
|
||||||
|
|
||||||
|
struct Font {
|
||||||
|
PangoFontDescription *description;
|
||||||
|
unsigned int height, approx_width;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The render pipeline, also handles click events by keeping track of each components bounds'. */
|
||||||
|
struct Pipeline {
|
||||||
|
struct List *callbacks; /* struct PipelineCallbacks* */
|
||||||
|
int current /* The current callback we are on */,
|
||||||
|
invalid;
|
||||||
|
|
||||||
|
/* Colors */
|
||||||
|
int background[4], foreground[4];
|
||||||
|
|
||||||
|
PangoContext *context;
|
||||||
|
struct Font *font;
|
||||||
|
|
||||||
|
struct Shm *shm;
|
||||||
|
struct wl_surface *surface;
|
||||||
|
struct zwlr_layer_surface_v1 *layer_surface;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PipelineListener {
|
||||||
|
void (*render)(struct Pipeline *pipeline, void *data, cairo_t *painter, int *x, int *y);
|
||||||
|
int (*width)(struct Pipeline *pipeline, void *data, unsigned int future_widths);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PipelineCallback {
|
||||||
|
const struct PipelineListener *listener;
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Basic helper component, can be used if the only thing to be displayed is text. */
|
||||||
|
struct BasicComponent {
|
||||||
|
PangoLayout *layout;
|
||||||
|
int width, height,
|
||||||
|
x, y /* box start coordinates */,
|
||||||
|
tx, ty /* text starts coordinates, tx is added to starting x coordinates. */;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BasicComponent *basic_component_create(PangoContext *context, PangoFontDescription *description);
|
||||||
|
void basic_component_destroy(struct BasicComponent *component);
|
||||||
|
int basic_component_is_clicked(struct BasicComponent *component, double x, double y);
|
||||||
|
void basic_component_render(struct BasicComponent *component, struct Pipeline *pipeline,
|
||||||
|
cairo_t *painter, int *x, int *y);
|
||||||
|
int basic_component_text_width(struct BasicComponent *component);
|
||||||
|
void pipeline_add(struct Pipeline *pipeline, const struct PipelineListener *listener, void *data);
|
||||||
|
struct Pipeline *pipeline_create(void);
|
||||||
|
void pipeline_destroy(struct Pipeline *pipeline);
|
||||||
|
int pipeline_get_future_widths(struct Pipeline *pipeline);
|
||||||
|
void pipeline_hide(struct Pipeline *pipeline);
|
||||||
|
void pipeline_invalidate(struct Pipeline *pipeline);
|
||||||
|
int pipeline_is_visible(struct Pipeline *pipeline);
|
||||||
|
void pipeline_show(struct Pipeline *pipeline, struct wl_output *output);
|
||||||
|
void pipeline_set_colorscheme(struct Pipeline* pipeline, const int **scheme);
|
||||||
|
void pipeline_color_foreground(struct Pipeline* pipeline, cairo_t *painter);
|
||||||
|
void pipeline_color_background(struct Pipeline* pipeline, cairo_t *painter);
|
||||||
|
void set_color(cairo_t *painter, const int rgba[4]);
|
||||||
|
|
||||||
|
#endif // RENDER_H_
|
117
user/.config/suckless/dwl-bar/src/shm.c
Normal file
117
user/.config/suckless/dwl-bar/src/shm.c
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
#include "shm.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include <wayland-client-protocol.h>
|
||||||
|
|
||||||
|
#define BUFFERS 2
|
||||||
|
|
||||||
|
static int allocate_shm(int size);
|
||||||
|
static struct Buffer buffer_create(struct MemoryMapping *memmap, struct wl_shm_pool *shm,
|
||||||
|
int fd, int width, int height, int offset, enum wl_shm_format format);
|
||||||
|
static void buffer_destroy(struct Buffer *buf);
|
||||||
|
static struct MemoryMapping memory_mapping_create(int fd, int pool_size);
|
||||||
|
static void memory_mapping_destroy(struct MemoryMapping *map);
|
||||||
|
|
||||||
|
|
||||||
|
int allocate_shm(int size) {
|
||||||
|
char name[] = "wl_shm";
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if ((fd = shm_open(name, O_CREAT | O_RDWR | O_EXCL, 0600)) < 0)
|
||||||
|
panic("shm_open when allocating shm");
|
||||||
|
|
||||||
|
shm_unlink(name);
|
||||||
|
|
||||||
|
if (ftruncate(fd, size) < 0)
|
||||||
|
panic("ftruncate when allocating shm");
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct Buffer buffer_create(struct MemoryMapping *map, struct wl_shm_pool *shm,
|
||||||
|
int fd, int width, int height, int offset, enum wl_shm_format format) {
|
||||||
|
if (!map)
|
||||||
|
panic("map is null");
|
||||||
|
|
||||||
|
int stride = width * 4,
|
||||||
|
pool_size = height * stride;
|
||||||
|
struct Buffer buffer;
|
||||||
|
|
||||||
|
struct wl_buffer *wl_buffer = wl_shm_pool_create_buffer(shm, offset, width, height, stride, format);
|
||||||
|
buffer.buffer = wl_buffer;
|
||||||
|
buffer.buffer_ptr = map->ptr+offset;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void buffer_destroy(struct Buffer *buffer) {
|
||||||
|
if (!buffer) return;
|
||||||
|
wl_buffer_destroy(buffer->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MemoryMapping memory_mapping_create(int fd, int pool_size) {
|
||||||
|
struct MemoryMapping map;
|
||||||
|
void* ptr = mmap(NULL, pool_size, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_SHARED, fd, 0);
|
||||||
|
if (ptr == MAP_FAILED || !ptr) {
|
||||||
|
close(fd);
|
||||||
|
panic("MAP_FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
map.ptr = ptr;
|
||||||
|
map.size = pool_size;
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void memory_mapping_destroy(struct MemoryMapping *map) {
|
||||||
|
if (!map) return;
|
||||||
|
munmap(map->ptr, map->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Shm *shm_create(int width, int height, enum wl_shm_format format) {
|
||||||
|
struct Shm *shared_mem = calloc(1, sizeof(*shared_mem));
|
||||||
|
int i, offset,
|
||||||
|
stride = width * 4,
|
||||||
|
size = stride * height,
|
||||||
|
total = size * BUFFERS;
|
||||||
|
int fd = allocate_shm(total);
|
||||||
|
|
||||||
|
struct MemoryMapping memory = memory_mapping_create(fd, total);
|
||||||
|
struct wl_shm_pool* pool = wl_shm_create_pool(shm, fd, total);
|
||||||
|
for (i = 0; i < BUFFERS; i++) {
|
||||||
|
offset = size*i;
|
||||||
|
shared_mem->buffers[i] = buffer_create(&memory, pool, fd, width, height, offset, format);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
wl_shm_pool_destroy(pool);
|
||||||
|
|
||||||
|
shared_mem->map = memory;
|
||||||
|
shared_mem->current = 0;
|
||||||
|
|
||||||
|
shared_mem->height = height;
|
||||||
|
shared_mem->width = width;
|
||||||
|
shared_mem->stride = stride;
|
||||||
|
|
||||||
|
return shared_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shm_destroy(struct Shm *shm) {
|
||||||
|
if (!shm) return;
|
||||||
|
|
||||||
|
memory_mapping_destroy(&shm->map);
|
||||||
|
for (int i = 0; i < BUFFERS; i++)
|
||||||
|
buffer_destroy(&shm->buffers[i]);
|
||||||
|
free(shm);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *shm_data(struct Shm *shm) {
|
||||||
|
return shm->buffers[shm->current].buffer_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wl_buffer *shm_buffer(struct Shm *shm) {
|
||||||
|
return shm->buffers[shm->current].buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shm_flip(struct Shm *shm) {
|
||||||
|
shm->current = 1-shm->current;
|
||||||
|
}
|
35
user/.config/suckless/dwl-bar/src/shm.h
Normal file
35
user/.config/suckless/dwl-bar/src/shm.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef SHM_H_
|
||||||
|
#define SHM_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <wayland-client-protocol.h>
|
||||||
|
|
||||||
|
struct MemoryMapping {
|
||||||
|
void *ptr;
|
||||||
|
int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Buffer {
|
||||||
|
struct wl_buffer *buffer;
|
||||||
|
uint8_t *buffer_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Shm {
|
||||||
|
int width, height, stride, current;
|
||||||
|
struct MemoryMapping map;
|
||||||
|
struct Buffer buffers[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Shm *shm_create(int width, int height, enum wl_shm_format format);
|
||||||
|
void shm_destroy(struct Shm *shm);
|
||||||
|
uint8_t *shm_data(struct Shm *shm);
|
||||||
|
struct wl_buffer *shm_buffer(struct Shm *shm);
|
||||||
|
void shm_flip(struct Shm *shm);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SHM_H_
|
41
user/.config/suckless/dwl-bar/src/user.c
Normal file
41
user/.config/suckless/dwl-bar/src/user.c
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#include "user.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void layout(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
if ((monitor->layout == 0 && !arg->ui) || (monitor->layout == layoutcount-1 && arg->ui))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (arg->ui)
|
||||||
|
monitor->layout++;
|
||||||
|
else
|
||||||
|
monitor->layout--;
|
||||||
|
|
||||||
|
zdwl_ipc_output_v2_set_layout(monitor->dwl_output, monitor->layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spawn(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
if (fork() != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char* const* argv = arg->v;
|
||||||
|
setsid();
|
||||||
|
execvp(argv[0], argv);
|
||||||
|
fprintf(stderr, "dwl-bar: execvp %s", argv[0]);
|
||||||
|
perror(" failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tag(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
zdwl_ipc_output_v2_set_client_tags(monitor->dwl_output, 0, 1<<arg->ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle_view(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
zdwl_ipc_output_v2_set_tags(monitor->dwl_output, monitor->tags ^ (1<<arg->ui), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void view(struct Monitor *monitor, const union Arg *arg) {
|
||||||
|
zdwl_ipc_output_v2_set_tags(monitor->dwl_output, 1<<arg->ui, 1);
|
||||||
|
}
|
55
user/.config/suckless/dwl-bar/src/user.h
Normal file
55
user/.config/suckless/dwl-bar/src/user.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#ifndef USER_H_
|
||||||
|
#define USER_H_
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
typedef struct Binding Binding;
|
||||||
|
|
||||||
|
enum Clicked {
|
||||||
|
Click_None,
|
||||||
|
Click_Tag,
|
||||||
|
Click_Layout,
|
||||||
|
Click_Title,
|
||||||
|
Click_Status,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ColorScheme {
|
||||||
|
InActive_Scheme = 0,
|
||||||
|
Active_Scheme = 1,
|
||||||
|
Urgent_Scheme = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TouchGesture {
|
||||||
|
Gesture_Left,
|
||||||
|
Gesture_Right,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PointerScroll {
|
||||||
|
Scroll_Up,
|
||||||
|
Scroll_Down,
|
||||||
|
Scroll_Left,
|
||||||
|
Scroll_Right,
|
||||||
|
};
|
||||||
|
|
||||||
|
union Arg {
|
||||||
|
unsigned int ui;
|
||||||
|
int i;
|
||||||
|
const void *v;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Binding {
|
||||||
|
enum Clicked clicked;
|
||||||
|
int button;
|
||||||
|
void (*callback)(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
/* Informs the click function that they should only pass the defined arg in this binding */
|
||||||
|
unsigned int bypass;
|
||||||
|
const union Arg arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
void layout(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
void spawn(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
void tag(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
void toggle_view(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
void view(struct Monitor *monitor, const union Arg *arg);
|
||||||
|
|
||||||
|
#endif // USER_H_
|
141
user/.config/suckless/dwl-bar/src/util.c
Normal file
141
user/.config/suckless/dwl-bar/src/util.c
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
#include "util.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include <alloca.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static void list_resize(struct List *list);
|
||||||
|
|
||||||
|
void *ecalloc(size_t amnt, size_t size) {
|
||||||
|
void *p = calloc(amnt, size);
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
panic("Out of memory");
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *list_add(struct List *list, void *data) {
|
||||||
|
if (!list)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
list_resize(list);
|
||||||
|
list->data[list->length++] = data;
|
||||||
|
return list->data[list->length-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void list_copy(struct List *dest, struct List *src) {
|
||||||
|
if (!dest || !src)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < src->length; i++)
|
||||||
|
list_add(dest, src->data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct List *list_create(size_t initial_size) {
|
||||||
|
struct List *list = ecalloc(1, sizeof(*list));
|
||||||
|
|
||||||
|
list->allocated = initial_size > 10 ? initial_size : 10;
|
||||||
|
list->length = 0;
|
||||||
|
list->data = ecalloc(list->allocated, sizeof(void*));
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_cmp_find(struct List* list, const void *data, int compare(const void *left, const void *right)) {
|
||||||
|
if (!list)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < list->length; i++)
|
||||||
|
if (compare(data, list->data[i]) == 0)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void list_destroy(struct List *list) {
|
||||||
|
if (!list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
free(list->data);
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
void list_elements_destroy(struct List *list, void (*destroy)(void *data)) {
|
||||||
|
if (!list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < list->length; i++)
|
||||||
|
destroy(list->data[i]);
|
||||||
|
free(list->data);
|
||||||
|
free(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
int list_find(struct List* list, const void *data) {
|
||||||
|
if (!list)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < list->length; i++)
|
||||||
|
if (data == list->data[i])
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *list_remove(struct List *list, unsigned int index) {
|
||||||
|
if (!list || index > list->length-1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
void *tmp = list->data[index];
|
||||||
|
|
||||||
|
list->length--;
|
||||||
|
memmove(&list->data[index], &list->data[index + 1], sizeof(void*) * (list->length - index));
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void list_resize(struct List *list) {
|
||||||
|
if (list->length < list->allocated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
list->allocated *= 2;
|
||||||
|
list->data = realloc(list->data, sizeof(void*) * list->allocated);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *string_create(const char *fmt, ...) {
|
||||||
|
va_list ap, aq;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
va_copy(aq, ap);
|
||||||
|
|
||||||
|
char *str;
|
||||||
|
size_t len = vsnprintf(NULL, 0, fmt, ap) + 1;
|
||||||
|
str = ecalloc(1, len);
|
||||||
|
vsnprintf(str, len, fmt, aq);
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
va_end(aq);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *to_delimiter(const char *string, unsigned long *start_end, char delimiter) {
|
||||||
|
if (!string || !start_end)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char *output;
|
||||||
|
const char *read;
|
||||||
|
unsigned long i = 0;
|
||||||
|
|
||||||
|
for (read = string + *start_end; *read != '\0' && *read != delimiter; read++)
|
||||||
|
i++;
|
||||||
|
|
||||||
|
output = strncpy(ecalloc(i+1, sizeof(*output)),
|
||||||
|
string + *start_end, i);
|
||||||
|
output[i++] = '\0';
|
||||||
|
*start_end += i;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
29
user/.config/suckless/dwl-bar/src/util.h
Normal file
29
user/.config/suckless/dwl-bar/src/util.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef UTIL_H_
|
||||||
|
#define UTIL_H_
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
|
||||||
|
#define STRING_EQUAL(string1, string2) strcmp(string1, string2) == 0
|
||||||
|
#define STRINGN_EQUAL(string1, string2, n) strncmp(string1, string2, n) == 0
|
||||||
|
#define LENGTH(X) (sizeof X / sizeof X[0] )
|
||||||
|
|
||||||
|
struct List {
|
||||||
|
void **data;
|
||||||
|
size_t allocated, length;
|
||||||
|
};
|
||||||
|
|
||||||
|
void *ecalloc(size_t amnt, size_t size);
|
||||||
|
void *list_add(struct List *list, void *data);
|
||||||
|
void list_copy(struct List *dest, struct List *src);
|
||||||
|
struct List *list_create(size_t initial_size);
|
||||||
|
int list_cmp_find(struct List *list, const void *data, int compare(const void *left, const void *right));
|
||||||
|
void list_destroy(struct List *list);
|
||||||
|
void list_elements_destroy(struct List *list, void (*destroy)(void *data));
|
||||||
|
int list_find(struct List* list, const void *data);
|
||||||
|
void *list_remove(struct List *list, unsigned int index);
|
||||||
|
char *string_create(const char* fmt, ...);
|
||||||
|
char *to_delimiter(const char* string, ulong *start_end, char delimiter);
|
||||||
|
|
||||||
|
#endif // UTIL_H_
|
692
user/.config/suckless/dwl/LICENSE
Normal file
692
user/.config/suckless/dwl/LICENSE
Normal file
|
@ -0,0 +1,692 @@
|
||||||
|
dwl - dwm for Wayland
|
||||||
|
|
||||||
|
Copyright © 2020 dwl team
|
||||||
|
|
||||||
|
See also the files LICENSE.tinywl, LICENSE.dwm and LICENSE.sway.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
39
user/.config/suckless/dwl/LICENSE.dwm
Normal file
39
user/.config/suckless/dwl/LICENSE.dwm
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
Portions of dwl based on dwm code are used under the following license:
|
||||||
|
|
||||||
|
MIT/X Consortium License
|
||||||
|
|
||||||
|
© 2006-2019 Anselm R Garbe <anselm@garbe.ca>
|
||||||
|
© 2006-2009 Jukka Salmi <jukka at salmi dot ch>
|
||||||
|
© 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
|
||||||
|
© 2007-2011 Peter Hartlich <sgkkr at hartlich dot com>
|
||||||
|
© 2007-2009 Szabolcs Nagy <nszabolcs at gmail dot com>
|
||||||
|
© 2007-2009 Christof Musik <christof at sendfax dot de>
|
||||||
|
© 2007-2009 Premysl Hruby <dfenze at gmail dot com>
|
||||||
|
© 2007-2008 Enno Gottox Boland <gottox at s01 dot de>
|
||||||
|
© 2008 Martin Hurton <martin dot hurton at gmail dot com>
|
||||||
|
© 2008 Neale Pickett <neale dot woozle dot org>
|
||||||
|
© 2009 Mate Nagy <mnagy at port70 dot net>
|
||||||
|
© 2010-2016 Hiltjo Posthuma <hiltjo@codemadness.org>
|
||||||
|
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
|
||||||
|
© 2011 Christoph Lohmann <20h@r-36.net>
|
||||||
|
© 2015-2016 Quentin Rameau <quinq@fifth.space>
|
||||||
|
© 2015-2016 Eric Pruitt <eric.pruitt@gmail.com>
|
||||||
|
© 2016-2017 Markus Teich <markus.teich@stusta.mhn.de>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
19
user/.config/suckless/dwl/LICENSE.sway
Normal file
19
user/.config/suckless/dwl/LICENSE.sway
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (c) 2016-2017 Drew DeVault
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
127
user/.config/suckless/dwl/LICENSE.tinywl
Normal file
127
user/.config/suckless/dwl/LICENSE.tinywl
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
dwl is originally based on TinyWL, which is used under the following license:
|
||||||
|
|
||||||
|
This work is licensed under CC0, which effectively puts it in the public domain.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Creative Commons Legal Code
|
||||||
|
|
||||||
|
CC0 1.0 Universal
|
||||||
|
|
||||||
|
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||||
|
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||||
|
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||||
|
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||||
|
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||||
|
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||||
|
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||||
|
HEREUNDER.
|
||||||
|
|
||||||
|
Statement of Purpose
|
||||||
|
|
||||||
|
The laws of most jurisdictions throughout the world automatically confer
|
||||||
|
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||||
|
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||||
|
authorship and/or a database (each, a "Work").
|
||||||
|
|
||||||
|
Certain owners wish to permanently relinquish those rights to a Work for
|
||||||
|
the purpose of contributing to a commons of creative, cultural and
|
||||||
|
scientific works ("Commons") that the public can reliably and without fear
|
||||||
|
of later claims of infringement build upon, modify, incorporate in other
|
||||||
|
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||||
|
and for any purposes, including without limitation commercial purposes.
|
||||||
|
These owners may contribute to the Commons to promote the ideal of a free
|
||||||
|
culture and the further production of creative, cultural and scientific
|
||||||
|
works, or to gain reputation or greater distribution for their Work in
|
||||||
|
part through the use and efforts of others.
|
||||||
|
|
||||||
|
For these and/or other purposes and motivations, and without any
|
||||||
|
expectation of additional consideration or compensation, the person
|
||||||
|
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||||
|
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||||
|
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||||
|
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||||
|
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||||
|
|
||||||
|
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||||
|
protected by copyright and related or neighboring rights ("Copyright and
|
||||||
|
Related Rights"). Copyright and Related Rights include, but are not
|
||||||
|
limited to, the following:
|
||||||
|
|
||||||
|
i. the right to reproduce, adapt, distribute, perform, display,
|
||||||
|
communicate, and translate a Work;
|
||||||
|
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||||
|
iii. publicity and privacy rights pertaining to a person's image or
|
||||||
|
likeness depicted in a Work;
|
||||||
|
iv. rights protecting against unfair competition in regards to a Work,
|
||||||
|
subject to the limitations in paragraph 4(a), below;
|
||||||
|
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||||
|
in a Work;
|
||||||
|
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||||
|
European Parliament and of the Council of 11 March 1996 on the legal
|
||||||
|
protection of databases, and under any national implementation
|
||||||
|
thereof, including any amended or successor version of such
|
||||||
|
directive); and
|
||||||
|
vii. other similar, equivalent or corresponding rights throughout the
|
||||||
|
world based on applicable law or treaty, and any national
|
||||||
|
implementations thereof.
|
||||||
|
|
||||||
|
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||||
|
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||||
|
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||||
|
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||||
|
of action, whether now known or unknown (including existing as well as
|
||||||
|
future claims and causes of action), in the Work (i) in all territories
|
||||||
|
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||||
|
treaty (including future time extensions), (iii) in any current or future
|
||||||
|
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||||
|
including without limitation commercial, advertising or promotional
|
||||||
|
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||||
|
member of the public at large and to the detriment of Affirmer's heirs and
|
||||||
|
successors, fully intending that such Waiver shall not be subject to
|
||||||
|
revocation, rescission, cancellation, termination, or any other legal or
|
||||||
|
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||||
|
as contemplated by Affirmer's express Statement of Purpose.
|
||||||
|
|
||||||
|
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||||
|
be judged legally invalid or ineffective under applicable law, then the
|
||||||
|
Waiver shall be preserved to the maximum extent permitted taking into
|
||||||
|
account Affirmer's express Statement of Purpose. In addition, to the
|
||||||
|
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||||
|
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||||
|
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||||
|
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||||
|
maximum duration provided by applicable law or treaty (including future
|
||||||
|
time extensions), (iii) in any current or future medium and for any number
|
||||||
|
of copies, and (iv) for any purpose whatsoever, including without
|
||||||
|
limitation commercial, advertising or promotional purposes (the
|
||||||
|
"License"). The License shall be deemed effective as of the date CC0 was
|
||||||
|
applied by Affirmer to the Work. Should any part of the License for any
|
||||||
|
reason be judged legally invalid or ineffective under applicable law, such
|
||||||
|
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||||
|
of the License, and in such case Affirmer hereby affirms that he or she
|
||||||
|
will not (i) exercise any of his or her remaining Copyright and Related
|
||||||
|
Rights in the Work or (ii) assert any associated claims and causes of
|
||||||
|
action with respect to the Work, in either case contrary to Affirmer's
|
||||||
|
express Statement of Purpose.
|
||||||
|
|
||||||
|
4. Limitations and Disclaimers.
|
||||||
|
|
||||||
|
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||||
|
surrendered, licensed or otherwise affected by this document.
|
||||||
|
b. Affirmer offers the Work as-is and makes no representations or
|
||||||
|
warranties of any kind concerning the Work, express, implied,
|
||||||
|
statutory or otherwise, including without limitation warranties of
|
||||||
|
title, merchantability, fitness for a particular purpose, non
|
||||||
|
infringement, or the absence of latent or other defects, accuracy, or
|
||||||
|
the present or absence of errors, whether or not discoverable, all to
|
||||||
|
the greatest extent permissible under applicable law.
|
||||||
|
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||||
|
that may apply to the Work or any use thereof, including without
|
||||||
|
limitation any person's Copyright and Related Rights in the Work.
|
||||||
|
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||||
|
consents, permissions or other rights required for any use of the
|
||||||
|
Work.
|
||||||
|
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||||
|
party to this document and has no duty or obligation with respect to
|
||||||
|
this CC0 or use of the Work.
|
70
user/.config/suckless/dwl/Makefile
Normal file
70
user/.config/suckless/dwl/Makefile
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
.POSIX:
|
||||||
|
.SUFFIXES:
|
||||||
|
|
||||||
|
include config.mk
|
||||||
|
|
||||||
|
# flags for compiling
|
||||||
|
DWLCPPFLAGS = -I. -DWLR_USE_UNSTABLE -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XWAYLAND)
|
||||||
|
DWLDEVCFLAGS = -pedantic -Wall -Wextra -Wdeclaration-after-statement -Wno-unused-parameter -Wno-sign-compare -Wshadow -Wunused-macros\
|
||||||
|
-Werror=strict-prototypes -Werror=implicit -Werror=return-type -Werror=incompatible-pointer-types
|
||||||
|
|
||||||
|
# CFLAGS / LDFLAGS
|
||||||
|
PKGS = wlroots wayland-server xkbcommon libinput $(XLIBS)
|
||||||
|
DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS)
|
||||||
|
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS)
|
||||||
|
|
||||||
|
all: dwl
|
||||||
|
dwl: dwl.o util.o dwl-ipc-unstable-v2-protocol.o
|
||||||
|
$(CC) dwl.o util.o dwl-ipc-unstable-v2-protocol.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) -o $@
|
||||||
|
dwl.o: dwl.c config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h dwl-ipc-unstable-v2-protocol.h
|
||||||
|
util.o: util.c util.h
|
||||||
|
dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.h
|
||||||
|
|
||||||
|
# wayland-scanner is a tool which generates C headers and rigging for Wayland
|
||||||
|
# protocols, which are specified in XML. wlroots requires you to rig these up
|
||||||
|
# to your build system yourself and provide them in the include path.
|
||||||
|
WAYLAND_SCANNER = `$(PKG_CONFIG) --variable=wayland_scanner wayland-scanner`
|
||||||
|
WAYLAND_PROTOCOLS = `$(PKG_CONFIG) --variable=pkgdatadir wayland-protocols`
|
||||||
|
|
||||||
|
xdg-shell-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
$(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@
|
||||||
|
wlr-layer-shell-unstable-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
protocols/wlr-layer-shell-unstable-v1.xml $@
|
||||||
|
dwl-ipc-unstable-v2-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
protocols/dwl-ipc-unstable-v2.xml $@
|
||||||
|
dwl-ipc-unstable-v2-protocol.c:
|
||||||
|
$(WAYLAND_SCANNER) private-code \
|
||||||
|
protocols/dwl-ipc-unstable-v2.xml $@
|
||||||
|
|
||||||
|
config.h:
|
||||||
|
cp config.def.h $@
|
||||||
|
clean:
|
||||||
|
rm -f dwl *.o *-protocol.h
|
||||||
|
|
||||||
|
dist: clean
|
||||||
|
mkdir -p dwl-$(VERSION)
|
||||||
|
cp -R LICENSE* Makefile README.md client.h config.def.h\
|
||||||
|
config.mk protocols dwl.1 dwl.c util.c util.h dwl.desktop\
|
||||||
|
dwl-$(VERSION)
|
||||||
|
tar -caf dwl-$(VERSION).tar.gz dwl-$(VERSION)
|
||||||
|
rm -rf dwl-$(VERSION)
|
||||||
|
|
||||||
|
install: dwl
|
||||||
|
mkdir -p $(DESTDIR)$(PREFIX)/bin
|
||||||
|
cp -f dwl $(DESTDIR)$(PREFIX)/bin
|
||||||
|
chmod 755 $(DESTDIR)$(PREFIX)/bin/dwl
|
||||||
|
mkdir -p $(DESTDIR)$(MANDIR)/man1
|
||||||
|
cp -f dwl.1 $(DESTDIR)$(MANDIR)/man1
|
||||||
|
chmod 644 $(DESTDIR)$(MANDIR)/man1/dwl.1
|
||||||
|
mkdir -p $(DESTDIR)$(DATADIR)/wayland-sessions
|
||||||
|
cp -f dwl.desktop $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop
|
||||||
|
chmod 644 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop
|
||||||
|
uninstall:
|
||||||
|
rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop
|
||||||
|
|
||||||
|
.SUFFIXES: .c .o
|
||||||
|
.c.o:
|
||||||
|
$(CC) $(CPPFLAGS) $(DWLCFLAGS) -c $<
|
173
user/.config/suckless/dwl/README.md
Normal file
173
user/.config/suckless/dwl/README.md
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
# dwl - dwm for Wayland
|
||||||
|
|
||||||
|
Join us on our IRC channel: [#dwl on Libera Chat]
|
||||||
|
Or on our [Discord server].
|
||||||
|
|
||||||
|
dwl is a compact, hackable compositor for [Wayland] based on [wlroots]. It is
|
||||||
|
intended to fill the same space in the Wayland world that dwm does in X11,
|
||||||
|
primarily in terms of philosophy, and secondarily in terms of functionality.
|
||||||
|
Like dwm, dwl is:
|
||||||
|
|
||||||
|
- Easy to understand, hack on, and extend with patches
|
||||||
|
- One C source file (or a very small number) configurable via `config.h`
|
||||||
|
- Limited to 2200 SLOC to promote hackability
|
||||||
|
- Tied to as few external dependencies as possible
|
||||||
|
|
||||||
|
dwl is not meant to provide every feature under the sun. Instead, like dwm, it
|
||||||
|
sticks to features which are necessary, simple, and straightforward to implement
|
||||||
|
given the base on which it is built. Implemented default features are:
|
||||||
|
|
||||||
|
- Any features provided by dwm/Xlib: simple window borders, tags, keybindings,
|
||||||
|
client rules, mouse move/resize. Providing a built-in status bar is an
|
||||||
|
exception to this goal, to avoid dependencies on font rendering and/or
|
||||||
|
drawing libraries when an external bar could work well.
|
||||||
|
- Configurable multi-monitor layout support, including position and rotation
|
||||||
|
- Configurable HiDPI/multi-DPI support
|
||||||
|
- Idle-inhibit protocol which lets applications such as mpv disable idle
|
||||||
|
monitoring
|
||||||
|
- Provide information to external status bars via stdout/stdin
|
||||||
|
- Urgency hints via xdg-activate protocol
|
||||||
|
- Support screen lockers via ext-session-lock-v1 protocol
|
||||||
|
- Various Wayland protocols
|
||||||
|
- XWayland support as provided by wlroots (can be enabled in `config.mk`)
|
||||||
|
- Zero flickering - Wayland users naturally expect that "every frame is perfect"
|
||||||
|
- Layer shell popups (used by Waybar)
|
||||||
|
- Damage tracking provided by scenegraph API
|
||||||
|
|
||||||
|
Features under consideration (possibly as patches) are:
|
||||||
|
|
||||||
|
- Protocols made trivial by wlroots
|
||||||
|
- Implement the text-input and input-method protocols to support IME once ibus
|
||||||
|
implements input-method v2 (see https://github.com/ibus/ibus/pull/2256 and
|
||||||
|
https://github.com/djpohly/dwl/pull/235)
|
||||||
|
|
||||||
|
Feature *non-goals* for the main codebase include:
|
||||||
|
|
||||||
|
- Client-side decoration (any more than is necessary to tell the clients not to)
|
||||||
|
- Client-initiated window management, such as move, resize, and close, which can
|
||||||
|
be done through the compositor
|
||||||
|
- Animations and visual effects
|
||||||
|
|
||||||
|
## Building dwl
|
||||||
|
|
||||||
|
dwl has the following dependencies:
|
||||||
|
```
|
||||||
|
libinput
|
||||||
|
wayland
|
||||||
|
wlroots (compiled with the libinput backend)
|
||||||
|
xkbcommon
|
||||||
|
wayland-protocols (compile-time only)
|
||||||
|
pkg-config (compile-time only)
|
||||||
|
```
|
||||||
|
If you enable X11 support:
|
||||||
|
```
|
||||||
|
libxcb
|
||||||
|
libxcb-wm
|
||||||
|
wlroots (compiled with X11 support)
|
||||||
|
Xwayland (runtime only)
|
||||||
|
```
|
||||||
|
|
||||||
|
Simply install these (and their `-devel` versions if your distro has separate
|
||||||
|
development packages) and run `make`. If you wish to build against a Git
|
||||||
|
version of wlroots, check out the [wlroots-next branch].
|
||||||
|
|
||||||
|
To enable XWayland, you should uncomment its flags in `config.mk`.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
All configuration is done by editing `config.h` and recompiling, in the same
|
||||||
|
manner as dwm. There is no way to separately restart the window manager in
|
||||||
|
Wayland without restarting the entire display server, so any changes will take
|
||||||
|
effect the next time dwl is executed.
|
||||||
|
|
||||||
|
As in the dwm community, we encourage users to share patches they have created.
|
||||||
|
Check out the [patches page on our wiki]!
|
||||||
|
|
||||||
|
## Running dwl
|
||||||
|
|
||||||
|
dwl can be run on any of the backends supported by wlroots. This means you can
|
||||||
|
run it as a separate window inside either an X11 or Wayland session, as well
|
||||||
|
as directly from a VT console. Depending on your distro's setup, you may need
|
||||||
|
to add your user to the `video` and `input` groups before you can run dwl on
|
||||||
|
a VT. If you are using `elogind` or `systemd-logind` you need to install
|
||||||
|
polkit; otherwise you need to add yourself in the `seat` group and
|
||||||
|
enable/start the 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 background color is black.
|
||||||
|
|
||||||
|
If you would like to run a script or command automatically at startup, you can
|
||||||
|
specify the command using the `-s` option. This command will be executed as a
|
||||||
|
shell command using `/bin/sh -c`. It serves a similar function to `.xinitrc`,
|
||||||
|
but differs in that the display server will not shut down when this process
|
||||||
|
terminates. Instead, dwl will send this process a SIGTERM at shutdown and wait
|
||||||
|
for it to terminate (if it hasn't already). This makes it ideal for execing into
|
||||||
|
a user service manager like [s6], [anopa], [runit], or [`systemd --user`].
|
||||||
|
|
||||||
|
Note: The `-s` command is run as a *child process* of dwl, which means that it
|
||||||
|
does not have the ability to affect the environment of dwl or of any processes
|
||||||
|
that it spawns. If you need to set environment variables that affect the entire
|
||||||
|
dwl session, these must be set prior to running dwl. For example, Wayland
|
||||||
|
requires a valid `XDG_RUNTIME_DIR`, which is usually set up by a session manager
|
||||||
|
such as `elogind` or `systemd-logind`. If your system doesn't do this
|
||||||
|
automatically, you will need to configure it prior to launching `dwl`, e.g.:
|
||||||
|
|
||||||
|
export XDG_RUNTIME_DIR=/tmp/xdg-runtime-$(id -u)
|
||||||
|
mkdir -p $XDG_RUNTIME_DIR
|
||||||
|
dwl
|
||||||
|
|
||||||
|
### Status information
|
||||||
|
|
||||||
|
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
|
||||||
|
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, you can
|
||||||
|
close standard input with the `<&-` shell redirection, for example:
|
||||||
|
|
||||||
|
dwl -s 'foot --server <&-'
|
||||||
|
|
||||||
|
If your startup command is a shell script, you can achieve the same inside the
|
||||||
|
script with the line
|
||||||
|
|
||||||
|
exec <&-
|
||||||
|
|
||||||
|
To get a list of status bars that work with dwl consult our [wiki].
|
||||||
|
|
||||||
|
## Replacements for X applications
|
||||||
|
|
||||||
|
You can find a [list of useful resources on our wiki].
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
dwl began by extending the TinyWL example provided (CC0) by the sway/wlroots
|
||||||
|
developers. This was made possible in many cases by looking at how sway
|
||||||
|
accomplished something, then trying to do the same in as suckless a way as
|
||||||
|
possible.
|
||||||
|
|
||||||
|
Many thanks to suckless.org and the dwm developers and community for the
|
||||||
|
inspiration, and to the various contributors to the project, including:
|
||||||
|
|
||||||
|
- Alexander Courtis for the XWayland implementation
|
||||||
|
- Guido Cella for the layer-shell protocol implementation, patch maintenance,
|
||||||
|
and for helping to keep the project running
|
||||||
|
- Stivvo for output management and fullscreen support, and patch maintenance
|
||||||
|
|
||||||
|
|
||||||
|
[Discord server]: https://discord.gg/jJxZnrGPWN
|
||||||
|
[#dwl on Libera Chat]: https://web.libera.chat/?channels=#dwl
|
||||||
|
[Wayland]: https://wayland.freedesktop.org/
|
||||||
|
[wlroots]: https://gitlab.freedesktop.org/wlroots/wlroots/
|
||||||
|
[wlroots-next branch]: https://github.com/djpohly/dwl/tree/wlroots-next
|
||||||
|
[patches page on our wiki]: https://github.com/djpohly/dwl/wiki/Patches
|
||||||
|
[s6]: https://skarnet.org/software/s6/
|
||||||
|
[anopa]: https://jjacky.com/anopa/
|
||||||
|
[runit]: http://smarden.org/runit/faq.html#userservices
|
||||||
|
[`systemd --user`]: https://wiki.archlinux.org/title/Systemd/User
|
||||||
|
[wiki]: https://github.com/djpohly/dwl/wiki#compatible-status-bars
|
||||||
|
[list of useful resources on our wiki]:
|
||||||
|
https://github.com/djpohly/dwl/wiki#migrating-from-x
|
48
user/.config/suckless/dwl/bootstrap
Executable file
48
user/.config/suckless/dwl/bootstrap
Executable file
|
@ -0,0 +1,48 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# GTK Environment Variables
|
||||||
|
export GTK_THEME=gruvbox-dark-gtk
|
||||||
|
export GTK_ICON_THEME=gruvbox-dark-icons-gtk
|
||||||
|
export GTK_CURSOR_THEME=Simp1e-Gruvbox-Dark
|
||||||
|
export XCURSOR_THEME=Simp1e-Gruvbox-Dark
|
||||||
|
export XCURSOR_PATH="$HOME/.icons"
|
||||||
|
export XCURSOR_SIZE=16
|
||||||
|
|
||||||
|
# Activate dbus environment
|
||||||
|
dbus-update-activation-environment WAYLAND_DISPLAY XDG_CURRENT_DESKTOP &
|
||||||
|
|
||||||
|
# Kill any running pipewire processes
|
||||||
|
pkill pipewire
|
||||||
|
pkill pipewire-pulse
|
||||||
|
pkill wireplumber
|
||||||
|
|
||||||
|
# Run pipewire
|
||||||
|
pipewire &
|
||||||
|
pipewire-pulse &
|
||||||
|
wireplumber &
|
||||||
|
|
||||||
|
# Desktop portals and authentication agents
|
||||||
|
/usr/libexec/xdg-desktop-portal-wlr &
|
||||||
|
/usr/libexec/polkit-gnome-authentication-agent-1 &
|
||||||
|
|
||||||
|
# Clipboard manager
|
||||||
|
wl-paste --type text --watch cliphist store &
|
||||||
|
wl-paste --type image --watch cliphist store &
|
||||||
|
|
||||||
|
# Notification daemon
|
||||||
|
dunst --config "$HOME/.config/dunst/dunstrc" &
|
||||||
|
|
||||||
|
# GTK Settings
|
||||||
|
gsettings set org.gnome.desktop.interface gtk-theme 'gruvbox-dark-gtk'
|
||||||
|
gsettings set org.gnome.desktop.interface icon-theme 'gruvbox-dark-icons-gtk'
|
||||||
|
gsettings set org.gnome.desktop.interface cursor-theme 'Simp1e-Gruvbox-Dark'
|
||||||
|
gsettings set org.gnome.desktop.interface font-name 'Cantarell 10'
|
||||||
|
|
||||||
|
# Set Wallpaper
|
||||||
|
sh -c "$HOME/.wall"
|
||||||
|
|
||||||
|
# Bar
|
||||||
|
sleep 1
|
||||||
|
dwl-bar <&- &
|
||||||
|
sleep 0.1
|
||||||
|
someblocks -s "$XDG_RUNTIME_DIR/dwl-bar-0" <&-
|
402
user/.config/suckless/dwl/client.h
Normal file
402
user/.config/suckless/dwl/client.h
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
/*
|
||||||
|
* Attempt to consolidate unavoidable suck into one file, away from dwl.c. This
|
||||||
|
* file is not meant to be pretty. We use a .h file with static inline
|
||||||
|
* functions instead of a separate .c module, or function pointers like sway, so
|
||||||
|
* that they will simply compile out if the chosen #defines leave them unused.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Leave these functions first; they're used in the others */
|
||||||
|
static inline int
|
||||||
|
client_is_x11(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
return c->type == X11Managed || c->type == X11Unmanaged;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
client_get_size_hints(Client *c, struct wlr_box *max, struct wlr_box *min)
|
||||||
|
{
|
||||||
|
struct wlr_xdg_toplevel *toplevel;
|
||||||
|
struct wlr_xdg_toplevel_state *state;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
xcb_size_hints_t *size_hints = c->surface.xwayland->size_hints;
|
||||||
|
if (size_hints) {
|
||||||
|
max->width = size_hints->max_width;
|
||||||
|
max->height = size_hints->max_height;
|
||||||
|
min->width = size_hints->min_width;
|
||||||
|
min->height = size_hints->min_height;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
toplevel = c->surface.xdg->toplevel;
|
||||||
|
state = &toplevel->current;
|
||||||
|
max->width = state->max_width;
|
||||||
|
max->height = state->max_height;
|
||||||
|
min->width = state->min_width;
|
||||||
|
min->height = state->min_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct wlr_surface *
|
||||||
|
client_surface(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->surface;
|
||||||
|
#endif
|
||||||
|
return c->surface.xdg->surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
toplevel_from_wlr_surface(struct wlr_surface *s, Client **pc, LayerSurface **pl)
|
||||||
|
{
|
||||||
|
struct wlr_xdg_surface *xdg_surface;
|
||||||
|
struct wlr_surface *root_surface;
|
||||||
|
struct wlr_layer_surface_v1 *layer_surface;
|
||||||
|
Client *c = NULL;
|
||||||
|
LayerSurface *l = NULL;
|
||||||
|
int type = -1;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
struct wlr_xwayland_surface *xsurface;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
return type;
|
||||||
|
root_surface = wlr_surface_get_root_surface(s);
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (wlr_surface_is_xwayland_surface(root_surface)
|
||||||
|
&& (xsurface = wlr_xwayland_surface_from_wlr_surface(root_surface))) {
|
||||||
|
c = xsurface->data;
|
||||||
|
type = c->type;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (wlr_surface_is_layer_surface(root_surface)
|
||||||
|
&& (layer_surface = wlr_layer_surface_v1_from_wlr_surface(root_surface))) {
|
||||||
|
l = layer_surface->data;
|
||||||
|
type = LayerShell;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wlr_surface_is_xdg_surface(root_surface)
|
||||||
|
&& (xdg_surface = wlr_xdg_surface_from_wlr_surface(root_surface))) {
|
||||||
|
while (1) {
|
||||||
|
switch (xdg_surface->role) {
|
||||||
|
case WLR_XDG_SURFACE_ROLE_POPUP:
|
||||||
|
if (!xdg_surface->popup->parent)
|
||||||
|
return -1;
|
||||||
|
else if (!wlr_surface_is_xdg_surface(xdg_surface->popup->parent))
|
||||||
|
return toplevel_from_wlr_surface(xdg_surface->popup->parent, pc, pl);
|
||||||
|
|
||||||
|
xdg_surface = wlr_xdg_surface_from_wlr_surface(xdg_surface->popup->parent);
|
||||||
|
break;
|
||||||
|
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
|
||||||
|
c = xdg_surface->data;
|
||||||
|
type = c->type;
|
||||||
|
goto end;
|
||||||
|
case WLR_XDG_SURFACE_ROLE_NONE:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (pl)
|
||||||
|
*pl = l;
|
||||||
|
if (pc)
|
||||||
|
*pc = c;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The others */
|
||||||
|
static inline void
|
||||||
|
client_activate_surface(struct wlr_surface *s, int activated)
|
||||||
|
{
|
||||||
|
struct wlr_xdg_surface *surface;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
struct wlr_xwayland_surface *xsurface;
|
||||||
|
if (wlr_surface_is_xwayland_surface(s)
|
||||||
|
&& (xsurface = wlr_xwayland_surface_from_wlr_surface(s))) {
|
||||||
|
wlr_xwayland_surface_activate(xsurface, activated);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (wlr_surface_is_xdg_surface(s)
|
||||||
|
&& (surface = wlr_xdg_surface_from_wlr_surface(s))
|
||||||
|
&& surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL)
|
||||||
|
wlr_xdg_toplevel_set_activated(surface->toplevel, activated);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
client_set_bounds(Client *c, int32_t width, int32_t height)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
if (c->surface.xdg->client->shell->version >=
|
||||||
|
XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && width >= 0 && height >= 0)
|
||||||
|
return wlr_xdg_toplevel_set_bounds(c->surface.xdg->toplevel, width, height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
client_for_each_surface(Client *c, wlr_surface_iterator_func_t fn, void *data)
|
||||||
|
{
|
||||||
|
wlr_surface_for_each_surface(client_surface(c), fn, data);
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
wlr_xdg_surface_for_each_popup_surface(c->surface.xdg, fn, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *
|
||||||
|
client_get_appid(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->class;
|
||||||
|
#endif
|
||||||
|
return c->surface.xdg->toplevel->app_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
client_get_geometry(Client *c, struct wlr_box *geom)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
geom->x = c->surface.xwayland->x;
|
||||||
|
geom->y = c->surface.xwayland->y;
|
||||||
|
geom->width = c->surface.xwayland->width;
|
||||||
|
geom->height = c->surface.xwayland->height;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
wlr_xdg_surface_get_geometry(c->surface.xdg, geom);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Client *
|
||||||
|
client_get_parent(Client *c)
|
||||||
|
{
|
||||||
|
Client *p = NULL;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c) && c->surface.xwayland->parent)
|
||||||
|
toplevel_from_wlr_surface(c->surface.xwayland->parent->surface, &p, NULL);
|
||||||
|
#endif
|
||||||
|
if (c->surface.xdg->toplevel->parent)
|
||||||
|
toplevel_from_wlr_surface(c->surface.xdg->toplevel->parent->base->surface, &p, NULL);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline const char *
|
||||||
|
client_get_title(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->title;
|
||||||
|
#endif
|
||||||
|
return c->surface.xdg->toplevel->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
client_is_float_type(Client *c)
|
||||||
|
{
|
||||||
|
struct wlr_box min = {0}, max = {0};
|
||||||
|
client_get_size_hints(c, &max, &min);
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
struct wlr_xwayland_surface *surface = c->surface.xwayland;
|
||||||
|
if (surface->modal)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < surface->window_type_len; i++)
|
||||||
|
if (surface->window_type[i] == netatom[NetWMWindowTypeDialog]
|
||||||
|
|| surface->window_type[i] == netatom[NetWMWindowTypeSplash]
|
||||||
|
|| surface->window_type[i] == netatom[NetWMWindowTypeToolbar]
|
||||||
|
|| surface->window_type[i] == netatom[NetWMWindowTypeUtility])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return ((min.width > 0 || min.height > 0 || max.width > 0 || max.height > 0)
|
||||||
|
&& (min.width == max.width || min.height == max.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
client_is_mapped(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->mapped;
|
||||||
|
#endif
|
||||||
|
return c->surface.xdg->mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
client_is_rendered_on_mon(Client *c, Monitor *m)
|
||||||
|
{
|
||||||
|
/* This is needed for when you don't want to check formal assignment,
|
||||||
|
* but rather actual displaying of the pixels.
|
||||||
|
* Usually VISIBLEON suffices and is also faster. */
|
||||||
|
struct wlr_surface_output *s;
|
||||||
|
if (!c->scene->node.enabled)
|
||||||
|
return 0;
|
||||||
|
wl_list_for_each(s, &client_surface(c)->current_outputs, link)
|
||||||
|
if (s->output == m->wlr_output)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
client_is_stopped(Client *c)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
siginfo_t in = {0};
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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. */
|
||||||
|
if (errno == ECHILD)
|
||||||
|
return 1;
|
||||||
|
} else if (in.si_pid) {
|
||||||
|
if (in.si_code == CLD_STOPPED || in.si_code == CLD_TRAPPED)
|
||||||
|
return 1;
|
||||||
|
if (in.si_code == CLD_CONTINUED)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
client_is_unmanaged(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
return c->type == X11Unmanaged;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
client_notify_enter(struct wlr_surface *s, struct wlr_keyboard *kb)
|
||||||
|
{
|
||||||
|
if (kb)
|
||||||
|
wlr_seat_keyboard_notify_enter(seat, s, kb->keycodes,
|
||||||
|
kb->num_keycodes, &kb->modifiers);
|
||||||
|
else
|
||||||
|
wlr_seat_keyboard_notify_enter(seat, s, NULL, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
client_restack_surface(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
wlr_xwayland_surface_restack(c->surface.xwayland, NULL,
|
||||||
|
XCB_STACK_MODE_ABOVE);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
client_send_close(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
wlr_xwayland_surface_close(c->surface.xwayland);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
wlr_xdg_toplevel_send_close(c->surface.xdg->toplevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
client_set_border_color(Client *c, const float color[static 4])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
wlr_scene_rect_set_color(c->border[i], color);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
client_set_fullscreen(Client *c, int fullscreen)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
wlr_xwayland_surface_set_fullscreen(c->surface.xwayland, fullscreen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
wlr_xdg_toplevel_set_fullscreen(c->surface.xdg->toplevel, fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
client_set_size(Client *c, uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c)) {
|
||||||
|
wlr_xwayland_surface_configure(c->surface.xwayland,
|
||||||
|
c->geom.x, c->geom.y, width, height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (width == c->surface.xdg->toplevel->current.width
|
||||||
|
&& height ==c->surface.xdg->toplevel->current.height)
|
||||||
|
return 0;
|
||||||
|
return wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
client_set_tiled(Client *c, uint32_t edges)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
wlr_xdg_toplevel_set_tiled(c->surface.xdg->toplevel, edges);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct wlr_surface *
|
||||||
|
client_surface_at(Client *c, double cx, double cy, double *sx, double *sy)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return wlr_surface_surface_at(c->surface.xwayland->surface,
|
||||||
|
cx, cy, sx, sy);
|
||||||
|
#endif
|
||||||
|
return wlr_xdg_surface_surface_at(c->surface.xdg, cx, cy, sx, sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
client_wants_focus(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
return client_is_unmanaged(c)
|
||||||
|
&& wlr_xwayland_or_surface_wants_focus(c->surface.xwayland)
|
||||||
|
&& wlr_xwayland_icccm_input_model(c->surface.xwayland) != WLR_ICCCM_INPUT_MODEL_NONE;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
client_wants_fullscreen(Client *c)
|
||||||
|
{
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
if (client_is_x11(c))
|
||||||
|
return c->surface.xwayland->fullscreen;
|
||||||
|
#endif
|
||||||
|
return c->surface.xdg->toplevel->requested.fullscreen;
|
||||||
|
}
|
309
user/.config/suckless/dwl/config.def.h
Normal file
309
user/.config/suckless/dwl/config.def.h
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
#include "keys.h"
|
||||||
|
/* Taken from https://github.com/djpohly/dwl/issues/466 */
|
||||||
|
#define COLOR(hex) { ((hex >> 24) & 0xFF) / 255.0f, \
|
||||||
|
((hex >> 16) & 0xFF) / 255.0f, \
|
||||||
|
((hex >> 8) & 0xFF) / 255.0f, \
|
||||||
|
(hex & 0xFF) / 255.0f }
|
||||||
|
/* appearance */
|
||||||
|
static const int sloppyfocus = 1; /* focus follows mouse */
|
||||||
|
static const int mousefollowsfocus = 1; /* mouse follows focus */
|
||||||
|
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
|
||||||
|
static const int smartgaps = 0; /* 1 means no outer gap when there is only one window */
|
||||||
|
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||||
|
static const unsigned int gappx = 10; /* horiz inner gap between windows */
|
||||||
|
static const float bordercolor[] = COLOR(0x504945ff);
|
||||||
|
static const float focuscolor[] = COLOR(0xcc241dff);
|
||||||
|
static const float urgentcolor[] = COLOR(0xfb4934ff);
|
||||||
|
/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */
|
||||||
|
static const float fullscreen_bg[] = COLOR(0x1d2021ff); /* You can also use glsl colors */
|
||||||
|
static const int center_relative_to_monitor = 0; /* 0 means center floating relative to the window area */
|
||||||
|
|
||||||
|
/* Autostart */
|
||||||
|
static const char *const autostart[] = {
|
||||||
|
"./.config/suckless/dwl/bootstrap", NULL,
|
||||||
|
NULL /* terminate */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* tagging - TAGCOUNT must be no greater than 31 */
|
||||||
|
#define TAGCOUNT (9)
|
||||||
|
|
||||||
|
/* logging */
|
||||||
|
static int log_level = WLR_ERROR;
|
||||||
|
|
||||||
|
static const Rule rules[] = {
|
||||||
|
/* app_id title tags mask isfloating monitor scratchkey */
|
||||||
|
/* examples:
|
||||||
|
{ "Gimp", NULL, 0, 1, -1 },
|
||||||
|
*/
|
||||||
|
{ "^neovide$", NULL, 1 << 0, 0, -1, 0 },
|
||||||
|
{ "^emacs$", NULL, 1 << 0, 0, -1, 0 },
|
||||||
|
{ "^Code$", NULL, 1 << 0, 0, -1, 0 },
|
||||||
|
{ "^neovim$", NULL, 1 << 0, 0, -1, 0 },
|
||||||
|
{ "^virt-manager$", NULL, 1 << 1, 0, -1, 0 },
|
||||||
|
{ "^gnome-boxes$", NULL, 1 << 1, 0, -1, 0 },
|
||||||
|
{ "^Firefox$", NULL, 1 << 2, 0, -1, 0 },
|
||||||
|
{ "^Librewolf$", NULL, 1 << 2, 0, -1, 0 },
|
||||||
|
{ "^Chromium$", NULL, 1 << 2, 0, -1, 0 },
|
||||||
|
{ "^org.qutebrowser.qutebrowser$", NULL, 1 << 2, 0, -1, 0 },
|
||||||
|
{ "^Brave-browser$", NULL, 1 << 2, 0, -1, 0 },
|
||||||
|
{ "^Bitwarden$", NULL, 1 << 2, 0, -1, 0 },
|
||||||
|
{ "^org.qbittorrent.qBittorrent$", NULL, 1 << 2, 0, -1, 0 },
|
||||||
|
{ "^gomuks$", NULL, 1 << 3, 0, -1, 0 },
|
||||||
|
{ "^Signal$", NULL, 1 << 3, 0, -1, 0 },
|
||||||
|
{ "^revolt-desktop$", NULL, 1 << 3, 0, -1, 0 },
|
||||||
|
{ "^Element$", NULL, 1 << 3, 0, -1, 0 },
|
||||||
|
{ "^audacity$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^Ardour$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^carla$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^carla-control$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^hydrogen$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^guitarix$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^lsp-plugins$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^QjackCtl$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^org.rncbc.qpwgraph$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^soundconverter$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^com.github.wwmm.easyeffects$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^kid3-qt$", NULL, 1 << 4, 0, -1, 0 },
|
||||||
|
{ "^pitivi$", NULL, 1 << 5, 0, -1, 0 },
|
||||||
|
{ "^org.kde.kdenlive$", NULL, 1 << 5, 0, -1, 0 },
|
||||||
|
{ "^mpv$", NULL, 1 << 5, 1, -1, 0 },
|
||||||
|
{ "^blender$", NULL, 1 << 5, 0, -1, 0 },
|
||||||
|
{ "^com.obsproject.Studio$", NULL, 1 << 5, 0, -1, 0 },
|
||||||
|
{ "^fr.handbrake.ghb$", NULL, 1 << 5, 0, -1, 0 },
|
||||||
|
{ "^org.inkscape.Inkscape$", NULL, 1 << 6, 0, -1, 0 },
|
||||||
|
{ "^Gimp-2.10$", NULL, 1 << 6, 0, -1, 0 }, { "^xournalpp$", NULL, 1 << 6, 0, -1, 0 },
|
||||||
|
{ "^krita$", NULL, 1 << 6, 0, -1, 0 },
|
||||||
|
{ "^darktable$", NULL, 1 << 6, 0, -1, 0 },
|
||||||
|
{ "^org.kde.digikam$", NULL, 1 << 6, 0, -1, 0 },
|
||||||
|
{ "^libreoffice-writer$", NULL, 1 << 7, 0, -1, 0 },
|
||||||
|
{ "^libreoffice-calc$", NULL, 1 << 7, 0, -1, 0 },
|
||||||
|
{ "^libreoffice-impress$", NULL, 1 << 7, 0, -1, 0 },
|
||||||
|
{ "^libreoffice-base$", NULL, 1 << 7, 0, -1, 0 },
|
||||||
|
{ "^libreoffice-draw$", NULL, 1 << 7, 0, -1, 0 },
|
||||||
|
{ "^libreoffice-math$", NULL, 1 << 7, 0, -1, 0 },
|
||||||
|
{ "^soffice$", NULL, 1 << 7, 0, -1, 0 },
|
||||||
|
{ "^GeoGebra$", NULL, 1 << 7, 0, -1, 0 },
|
||||||
|
{ "^org.pwmt.zathura$", NULL, 1 << 7, 0, -1, 0 },
|
||||||
|
{ "^org.libretro.Retroarch$", NULL, 1 << 8, 0, -1, 0 },
|
||||||
|
{ "^org.github.tkashkin.gamehub$", NULL, 1 << 8, 0, -1, 0 },
|
||||||
|
{ "^DarkPlaces$", NULL, 1 << 8, 0, -1, 0 },
|
||||||
|
{ "^pyrogenesis$", NULL, 1 << 8, 0, -1, 0 },
|
||||||
|
{ "^wesnoth$", NULL, 1 << 8, 0, -1, 0 },
|
||||||
|
{ "^Steam$", NULL, 1 << 8, 0, -1, 0 },
|
||||||
|
{ "^Minetest$", NULL, 1 << 8, 0, -1, 0 },
|
||||||
|
{ "^spterm$", NULL, 0, 1, -1, 't' },
|
||||||
|
{ "^spbtop$", NULL, 0, 1, -1, 'b' },
|
||||||
|
{ "^sppuls$", NULL, 0, 1, -1, 'p' },
|
||||||
|
{ "^spcmus$", NULL, 0, 1, -1, 'm' },
|
||||||
|
{ "^sprang$", NULL, 0, 1, -1, 'v' },
|
||||||
|
{ "^spnews$", NULL, 0, 1, -1, 'r' },
|
||||||
|
{ "^spflix$", NULL, 0, 1, -1, 'f' },
|
||||||
|
{ "^spanic$", NULL, 0, 1, -1, 'a' },
|
||||||
|
{ "^spytfz$", NULL, 0, 1, -1, 'y' },
|
||||||
|
{ "^spytfm$", NULL, 0, 1, -1, 'n' },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* layout(s) */
|
||||||
|
static const Layout layouts[] = {
|
||||||
|
/* symbol arrange function */
|
||||||
|
{ "[]=", tile },
|
||||||
|
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||||
|
{ "[M]", monocle },
|
||||||
|
{ "TTT", bstack },
|
||||||
|
{ "===", bstackhoriz },
|
||||||
|
{ "|M|", centeredmaster },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* monitors */
|
||||||
|
static const MonitorRule monrules[] = {
|
||||||
|
/* name mfact nmaster scale layout rotate/reflect x y */
|
||||||
|
/* example of a HiDPI laptop monitor:
|
||||||
|
{ "eDP-1", 0.5, 1, 2, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },
|
||||||
|
*/
|
||||||
|
/* defaults */
|
||||||
|
{ NULL, 0.55, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* keyboard */
|
||||||
|
static const struct xkb_rule_names xkb_rules = {
|
||||||
|
/* can specify fields: rules, model, layout, variant, options */
|
||||||
|
/* example:
|
||||||
|
.options = "ctrl:nocaps",
|
||||||
|
*/
|
||||||
|
.options = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int repeat_rate = 25;
|
||||||
|
static const int repeat_delay = 600;
|
||||||
|
|
||||||
|
/* es will be set the first time togglekblayout is called, then us.. it is
|
||||||
|
* recommended to set the same layout in position 0 of kblayouts and in
|
||||||
|
* xkb_rules */
|
||||||
|
static const char *kblayouts[] = {"us", "es"};
|
||||||
|
|
||||||
|
/* Trackpad */
|
||||||
|
static const int tap_to_click = 1;
|
||||||
|
static const int tap_and_drag = 1;
|
||||||
|
static const int drag_lock = 1;
|
||||||
|
static const int natural_scrolling = 1;
|
||||||
|
static const int disable_while_typing = 1;
|
||||||
|
static const int left_handed = 0;
|
||||||
|
static const int middle_button_emulation = 0;
|
||||||
|
/* You can choose between:
|
||||||
|
LIBINPUT_CONFIG_SCROLL_NO_SCROLL
|
||||||
|
LIBINPUT_CONFIG_SCROLL_2FG
|
||||||
|
LIBINPUT_CONFIG_SCROLL_EDGE
|
||||||
|
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN
|
||||||
|
*/
|
||||||
|
static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
|
||||||
|
|
||||||
|
/* You can choose between:
|
||||||
|
LIBINPUT_CONFIG_CLICK_METHOD_NONE
|
||||||
|
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS
|
||||||
|
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER
|
||||||
|
*/
|
||||||
|
static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
|
||||||
|
|
||||||
|
/* You can choose between:
|
||||||
|
LIBINPUT_CONFIG_SEND_EVENTS_ENABLED
|
||||||
|
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED
|
||||||
|
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE
|
||||||
|
*/
|
||||||
|
static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
|
||||||
|
|
||||||
|
/* You can choose between:
|
||||||
|
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT
|
||||||
|
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE
|
||||||
|
*/
|
||||||
|
static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
|
||||||
|
static const double accel_speed = 0.0;
|
||||||
|
static const int cursor_timeout = 5;
|
||||||
|
|
||||||
|
/* You can choose between:
|
||||||
|
LIBINPUT_CONFIG_TAP_MAP_LRM -- 1/2/3 finger tap maps to left/right/middle
|
||||||
|
LIBINPUT_CONFIG_TAP_MAP_LMR -- 1/2/3 finger tap maps to left/middle/right
|
||||||
|
*/
|
||||||
|
static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
|
||||||
|
|
||||||
|
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
|
||||||
|
#define MODKEY WLR_MODIFIER_LOGO
|
||||||
|
|
||||||
|
#define TAGKEYS(KEY,TAG) \
|
||||||
|
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, KEY, tag, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,KEY,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[] = { "wezterm", NULL };
|
||||||
|
static const char *menucmd[] = { "wofi", "--show", "run", "-p", " Run", NULL };
|
||||||
|
static const char *dmenucmd[] = { "wofi", "--show", "drun", "-p", " Apps", NULL };
|
||||||
|
|
||||||
|
/* named scratchpads - First arg only serves to match against key in rules*/
|
||||||
|
static const char *spterm[] = { "t", "wezterm", "start", "--class", "spterm", NULL };
|
||||||
|
static const char *spbtop[] = { "b", "wezterm", "start", "--class", "spbtop", "btop", NULL };
|
||||||
|
static const char *sppuls[] = { "p", "wezterm", "start", "--class", "sppuls", "pulsemixer", NULL };
|
||||||
|
static const char *spcmus[] = { "m", "wezterm", "start", "--class", "spcmus", "cmus", NULL };
|
||||||
|
static const char *sprang[] = { "v", "wezterm", "start", "--class", "sprang", "ranger", NULL };
|
||||||
|
static const char *spnews[] = { "r", "wezterm", "start", "--class", "spnews", "newsboat", NULL };
|
||||||
|
static const char *spflix[] = { "f", "wezterm", "start", "--class", "spflix", "flix-cli", NULL };
|
||||||
|
static const char *spanic[] = { "a", "wezterm", "start", "--class", "spanic", "ani-cli", NULL };
|
||||||
|
static const char *spytfz[] = { "y", "wezterm", "start", "--class", "spytfz", "ytfzf", "-flst", NULL };
|
||||||
|
static const char *spytfm[] = { "n", "wezterm", "start", "--class", "spytfm", "ytfzf", "-mlst", NULL };
|
||||||
|
|
||||||
|
static const Key keys[] = {
|
||||||
|
/* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
|
||||||
|
/* modifier key function argument */
|
||||||
|
{ MODKEY, Key_q, killclient, {0} },
|
||||||
|
{ MODKEY, Key_Return, spawn, {.v = termcmd} },
|
||||||
|
{ MODKEY, Key_j, focusstack, {.i = +1} },
|
||||||
|
{ MODKEY, Key_k, focusstack, {.i = -1} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_j, movestack, {.i = +1} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_k, movestack, {.i = -1} },
|
||||||
|
{ MODKEY, Key_i, incnmaster, {.i = +1} },
|
||||||
|
{ MODKEY, Key_d, incnmaster, {.i = -1} },
|
||||||
|
{ MODKEY, Key_h, setmfact, {.f = -0.05} },
|
||||||
|
{ MODKEY, Key_l, setmfact, {.f = +0.05} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_Return, zoom, {0} },
|
||||||
|
{ MODKEY, Key_Tab, view, {0} },
|
||||||
|
{ MODKEY, Key_g, togglegaps, {0} },
|
||||||
|
{ MODKEY, Key_t, setlayout, {.v = &layouts[0]} },
|
||||||
|
{ MODKEY, Key_f, setlayout, {.v = &layouts[1]} },
|
||||||
|
{ MODKEY, Key_m, setlayout, {.v = &layouts[2]} },
|
||||||
|
{ MODKEY, Key_u, setlayout, {.v = &layouts[3]} },
|
||||||
|
{ MODKEY, Key_o, setlayout, {.v = &layouts[4]} },
|
||||||
|
{ MODKEY, Key_c, setlayout, {.v = &layouts[5]} },
|
||||||
|
{ MODKEY, Key_space, setlayout, {0} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_CTRL, Key_space, togglefloating, {0} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_CTRL, Key_f, togglefullscreen, {0} },
|
||||||
|
{ MODKEY, Key_b, togglebar, {0} },
|
||||||
|
{ MODKEY, Key_x, movecenter, {0} },
|
||||||
|
{ MODKEY, Key_0, view, {.ui = ~0} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_parenright, tag, {.ui = ~0} },
|
||||||
|
{ MODKEY, Key_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||||
|
{ MODKEY, Key_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_minus, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_equal, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_CTRL, Key_x, togglekblayout, {0} },
|
||||||
|
{ MODKEY, Key_e, spawn, SHCMD("$HOME/.local/bin/neovide.AppImage --neovim-bin $HOME/.local/bin/lvim") },
|
||||||
|
{ MODKEY, Key_w, spawn, SHCMD("firefox") },
|
||||||
|
{ MODKEY, Key_s, spawn, SHCMD("flatpak run org.signal.Signal") },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_r, spawn, {.v = menucmd} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_d, spawn, {.v = dmenucmd} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_d, spawn, SHCMD("pkill wofi || $HOME/.config/wofi/scripts/rs_drun") },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_i, spawn, SHCMD("pkill wofi || $HOME/.config/wofi/scripts/rs_wifi") },
|
||||||
|
{ MODKEY, Key_Print, spawn, SHCMD("pkill wofi || $HOME/.config/wofi/scripts/rs_scrot") },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_w, spawn, SHCMD("pkill wofi || $HOME/.config/wofi/scripts/rs_wall") },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_e, spawn, SHCMD("pkill wofi || $HOME/.config/wofi/scripts/rs_emoji") },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_b, spawn, SHCMD("pkill wofi || $HOME/.config/wofi/scripts/rs_blue") },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_q, spawn, SHCMD("pkill wofi || $HOME/.config/wofi/scripts/rs_power") },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, Key_c, spawn, SHCMD("pkill wofi || cliphist list | wofi --dmenu -p ' Clipboard' | cliphist decode | wl-copy") },
|
||||||
|
{ 0, Key_XF86AudioRaiseVolume, spawn, SHCMD("pamixer -i 5 && pkill -RTMIN+10 someblocks") },
|
||||||
|
{ 0, Key_XF86AudioLowerVolume, spawn, SHCMD("pamixer -d 5 && pkill -RTMIN+10 someblocks") },
|
||||||
|
{ 0, Key_XF86AudioMute, spawn, SHCMD("pamixer -t && pkill -RTMIN+10 someblocks") },
|
||||||
|
{ 0, Key_XF86AudioMicMute, spawn, SHCMD("pamixer --default-source -t && pkill -RTMIN+10 someblocks") },
|
||||||
|
{ 0, Key_XF86MonBrightnessUp, spawn, SHCMD("brightnessctl s 5%+ && pkill -RTMIN+10 someblocks") },
|
||||||
|
{ 0, Key_XF86MonBrightnessDown, spawn, SHCMD("brightnessctl s 5%- && pkill -RTMIN+10 someblocks") },
|
||||||
|
{ 0, Key_XF86Display, spawn, SHCMD("wdisplays") },
|
||||||
|
{ 0, Key_XF86AudioPause, spawn, SHCMD("playerctl play-pause") },
|
||||||
|
{ 0, Key_XF86AudioPlay, spawn, SHCMD("playerctl play-pause") },
|
||||||
|
{ 0, Key_XF86AudioNext, spawn, SHCMD("playerctl next") },
|
||||||
|
{ 0, Key_XF86AudioPrev, spawn, SHCMD("playerctl previous") },
|
||||||
|
{ 0, Key_XF86AudioStop, spawn, SHCMD("playerctl stop") },
|
||||||
|
{ 0, Key_XF86New, togglescratch, {.v = spnews } },
|
||||||
|
{ MODKEY|WLR_MODIFIER_ALT, Key_Return, togglescratch, {.v = spterm } },
|
||||||
|
{ MODKEY|WLR_MODIFIER_ALT, Key_b, togglescratch, {.v = spbtop } },
|
||||||
|
{ MODKEY|WLR_MODIFIER_ALT, Key_p, togglescratch, {.v = sppuls } },
|
||||||
|
{ MODKEY|WLR_MODIFIER_ALT, Key_m, togglescratch, {.v = spcmus } },
|
||||||
|
{ MODKEY|WLR_MODIFIER_ALT, Key_v, togglescratch, {.v = sprang } },
|
||||||
|
{ MODKEY|WLR_MODIFIER_ALT, Key_r, togglescratch, {.v = spnews } },
|
||||||
|
{ MODKEY|WLR_MODIFIER_ALT, Key_f, togglescratch, {.v = spflix } },
|
||||||
|
{ MODKEY|WLR_MODIFIER_ALT, Key_a, togglescratch, {.v = spanic } },
|
||||||
|
{ MODKEY|WLR_MODIFIER_ALT, Key_y, togglescratch, {.v = spytfz } },
|
||||||
|
{ MODKEY|WLR_MODIFIER_ALT, Key_n, togglescratch, {.v = spytfm } },
|
||||||
|
TAGKEYS( Key_1, 0 ),
|
||||||
|
TAGKEYS( Key_2, 1 ),
|
||||||
|
TAGKEYS( Key_3, 2 ),
|
||||||
|
TAGKEYS( Key_4, 3 ),
|
||||||
|
TAGKEYS( Key_5, 4 ),
|
||||||
|
TAGKEYS( Key_6, 5 ),
|
||||||
|
TAGKEYS( Key_7, 6 ),
|
||||||
|
TAGKEYS( Key_8, 7 ),
|
||||||
|
TAGKEYS( Key_9, 8 ),
|
||||||
|
|
||||||
|
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
|
||||||
|
{ WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,Key_BackSpace, quit, {0} },
|
||||||
|
#define CHVT(KEY,n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT, KEY, chvt, {.ui = (n)} }
|
||||||
|
CHVT(Key_F1, 1), CHVT(Key_F2, 2), CHVT(Key_F3, 3), CHVT(Key_F4, 4),
|
||||||
|
CHVT(Key_F5, 5), CHVT(Key_F6, 6), CHVT(Key_F7, 7), CHVT(Key_F8, 8),
|
||||||
|
CHVT(Key_F9, 9), CHVT(Key_F10, 10), CHVT(Key_F11, 11), CHVT(Key_F12, 12),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Button buttons[] = {
|
||||||
|
{ MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} },
|
||||||
|
{ MODKEY, BTN_MIDDLE, togglefloating, {0} },
|
||||||
|
{ MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} },
|
||||||
|
};
|
13
user/.config/suckless/dwl/config.mk
Normal file
13
user/.config/suckless/dwl/config.mk
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
_VERSION = 0.4
|
||||||
|
VERSION = `git describe --tags --dirty 2>/dev/null || echo $(_VERSION)`
|
||||||
|
|
||||||
|
PKG_CONFIG = pkg-config
|
||||||
|
|
||||||
|
# paths
|
||||||
|
PREFIX = /usr/local
|
||||||
|
MANDIR = $(PREFIX)/share/man
|
||||||
|
DATADIR = $(PREFIX)/share
|
||||||
|
|
||||||
|
# XWayland support
|
||||||
|
XWAYLAND = -DXWAYLAND
|
||||||
|
XLIBS = xcb xcb-icccm
|
70
user/.config/suckless/dwl/dwl-ipc-unstable-v2-protocol.c
Normal file
70
user/.config/suckless/dwl/dwl-ipc-unstable-v2-protocol.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/* Generated by wayland-scanner 1.22.0 */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "wayland-util.h"
|
||||||
|
|
||||||
|
#ifndef __has_attribute
|
||||||
|
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
|
||||||
|
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
|
||||||
|
#else
|
||||||
|
#define WL_PRIVATE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern const struct wl_interface wl_output_interface;
|
||||||
|
extern const struct wl_interface zdwl_ipc_output_v2_interface;
|
||||||
|
|
||||||
|
static const struct wl_interface *dwl_ipc_unstable_v2_types[] = {
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&zdwl_ipc_output_v2_interface,
|
||||||
|
&wl_output_interface,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message zdwl_ipc_manager_v2_requests[] = {
|
||||||
|
{ "release", "", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "get_output", "no", dwl_ipc_unstable_v2_types + 4 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message zdwl_ipc_manager_v2_events[] = {
|
||||||
|
{ "tags", "u", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "layout", "s", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
WL_PRIVATE const struct wl_interface zdwl_ipc_manager_v2_interface = {
|
||||||
|
"zdwl_ipc_manager_v2", 2,
|
||||||
|
2, zdwl_ipc_manager_v2_requests,
|
||||||
|
2, zdwl_ipc_manager_v2_events,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message zdwl_ipc_output_v2_requests[] = {
|
||||||
|
{ "release", "", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "set_tags", "uu", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "set_client_tags", "uu", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "set_layout", "u", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct wl_message zdwl_ipc_output_v2_events[] = {
|
||||||
|
{ "toggle_visibility", "", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "active", "u", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "tag", "uuuu", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "layout", "u", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "title", "s", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "appid", "s", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "layout_symbol", "s", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "frame", "", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "fullscreen", "2u", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
{ "floating", "2u", dwl_ipc_unstable_v2_types + 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
WL_PRIVATE const struct wl_interface zdwl_ipc_output_v2_interface = {
|
||||||
|
"zdwl_ipc_output_v2", 2,
|
||||||
|
4, zdwl_ipc_output_v2_requests,
|
||||||
|
10, zdwl_ipc_output_v2_events,
|
||||||
|
};
|
||||||
|
|
158
user/.config/suckless/dwl/dwl.1
Normal file
158
user/.config/suckless/dwl/dwl.1
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
.Dd January 8, 2021
|
||||||
|
.Dt DWL 1
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm dwl
|
||||||
|
.Nd dwm for Wayland
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl v
|
||||||
|
.Op Fl d
|
||||||
|
.Op Fl s Ar startup command
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
is a Wayland compositor based on wlroots.
|
||||||
|
It is intended to fill the same space in the Wayland world that
|
||||||
|
.Nm dwm
|
||||||
|
does for X11.
|
||||||
|
.Pp
|
||||||
|
When given the
|
||||||
|
.Fl v
|
||||||
|
option,
|
||||||
|
.Nm
|
||||||
|
writes its name and version to standard error and exits unsuccessfully.
|
||||||
|
.Pp
|
||||||
|
When given the
|
||||||
|
.Fl d
|
||||||
|
option,
|
||||||
|
.Nm
|
||||||
|
enables full wlroots logging, including debug information.
|
||||||
|
.Pp
|
||||||
|
When given the
|
||||||
|
.Fl s
|
||||||
|
option,
|
||||||
|
.Nm
|
||||||
|
starts a shell process running
|
||||||
|
.Ar command
|
||||||
|
when starting.
|
||||||
|
When stopping, it sends
|
||||||
|
.Dv SIGTERM
|
||||||
|
to the child process and waits for it to exit.
|
||||||
|
.Pp
|
||||||
|
Users are encouraged to customize
|
||||||
|
.Nm
|
||||||
|
by editing the sources, in particular
|
||||||
|
.Pa config.h .
|
||||||
|
The default key bindings are as follows:
|
||||||
|
.Bl -tag -width 20n -offset indent -compact
|
||||||
|
.It Mod-[1-9]
|
||||||
|
Show only all windows with a tag.
|
||||||
|
.It Mod-Ctrl-[1-9]
|
||||||
|
Show all windows with a tag.
|
||||||
|
.It Mod-Shift-[1-9]
|
||||||
|
Move window to a single tag.
|
||||||
|
.It Mod-Ctrl-Shift-[1-9]
|
||||||
|
Toggle tag for window.
|
||||||
|
.It Mod-p
|
||||||
|
Spawn
|
||||||
|
.Nm bemenu-run .
|
||||||
|
.It Mod-Shift-Return
|
||||||
|
Spawn
|
||||||
|
.Nm foot .
|
||||||
|
.It Mod-[jk]
|
||||||
|
Move focus down/up the stack.
|
||||||
|
.It Mod-[id]
|
||||||
|
Increase/decrease number of windows in master area.
|
||||||
|
.It Mod-[hl]
|
||||||
|
Decrease/increase master area.
|
||||||
|
.It Mod-Return
|
||||||
|
Move window on top of stack or switch top of stack with second window.
|
||||||
|
.It Mod-Tab
|
||||||
|
Show only all windows with previous tag.
|
||||||
|
.It Mod-Shift-c
|
||||||
|
Close window.
|
||||||
|
.It Mod-t
|
||||||
|
Switch to tabbed layout.
|
||||||
|
.It Mod-f
|
||||||
|
Switch to floating layout.
|
||||||
|
.It Mod-m
|
||||||
|
Switch to monocle layout.
|
||||||
|
.It Mod-Space
|
||||||
|
Switch to previous layout.
|
||||||
|
.It Mod-Shift-Space
|
||||||
|
Toggle floating state of window.
|
||||||
|
.It Mod-e
|
||||||
|
Toggle fullscreen state of window.
|
||||||
|
.It Mod-0
|
||||||
|
Show all windows.
|
||||||
|
.It Mod-Shift-0
|
||||||
|
Set all tags for window.
|
||||||
|
.It Mod-,
|
||||||
|
Move focus to previous monitor.
|
||||||
|
.It Mod-.
|
||||||
|
Move focus to next monitor.
|
||||||
|
.It Mod-Shift-,
|
||||||
|
Move window to previous monitor.
|
||||||
|
.It Mod-Shift-.
|
||||||
|
Move window to next monitor.
|
||||||
|
.It Mod-Shift-q
|
||||||
|
Quit
|
||||||
|
.Nm .
|
||||||
|
.El
|
||||||
|
These might differ depending on your keyboard layout.
|
||||||
|
.Sh ENVIRONMENT
|
||||||
|
These environment variables are used by
|
||||||
|
.Nm :
|
||||||
|
.Bl -tag -width XDG_RUNTIME_DIR
|
||||||
|
.It Ev XDG_RUNTIME_DIR
|
||||||
|
A directory where temporary user files, such as the Wayland socket,
|
||||||
|
are stored.
|
||||||
|
.It Ev XDG_CONFIG_DIR
|
||||||
|
A directory containing configuration of various programs and
|
||||||
|
libraries, including libxkbcommon.
|
||||||
|
.It Ev DISPLAY , WAYLAND_DISPLAY , WAYLAND_SOCKET
|
||||||
|
Tell how to connect to an underlying X11 or Wayland server.
|
||||||
|
.It Ev WLR_*
|
||||||
|
Various variables specific to wlroots.
|
||||||
|
.It Ev XKB_* , XLOCALEDIR , XCOMPOSEFILE
|
||||||
|
Various variables specific to libxkbcommon.
|
||||||
|
.It Ev XCURSOR_PATH
|
||||||
|
List of directories to search for XCursor themes in.
|
||||||
|
.It Ev HOME
|
||||||
|
A directory where there are always dear files there for you.
|
||||||
|
Waiting for you to clean them up.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
These are set by
|
||||||
|
.Nm :
|
||||||
|
.Bl -tag -width WAYLAND_DISPLAY
|
||||||
|
.It Ev WAYLAND_DISPLAY
|
||||||
|
Tell how to connect to
|
||||||
|
.Nm .
|
||||||
|
.It Ev DISPLAY
|
||||||
|
If using
|
||||||
|
.Nm Xwayland ,
|
||||||
|
tell how to connect to the
|
||||||
|
.Nm Xwayland
|
||||||
|
server.
|
||||||
|
.El
|
||||||
|
.Sh EXAMPLES
|
||||||
|
Start
|
||||||
|
.Nm
|
||||||
|
with s6 in the background:
|
||||||
|
.Dl dwl -s 's6-svscan <&-'
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr foot 1 ,
|
||||||
|
.Xr bemenu 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.
|
3583
user/.config/suckless/dwl/dwl.c
Normal file
3583
user/.config/suckless/dwl/dwl.c
Normal file
File diff suppressed because it is too large
Load diff
3579
user/.config/suckless/dwl/dwl.c.orig
Normal file
3579
user/.config/suckless/dwl/dwl.c.orig
Normal file
File diff suppressed because it is too large
Load diff
5
user/.config/suckless/dwl/dwl.desktop
Normal file
5
user/.config/suckless/dwl/dwl.desktop
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=dwl
|
||||||
|
Comment=dwm for Wayland
|
||||||
|
Exec=dwl
|
||||||
|
Type=Application
|
82
user/.config/suckless/dwl/generate-keys.c
Normal file
82
user/.config/suckless/dwl/generate-keys.c
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/******************************************************************
|
||||||
|
* Copyright 2023 Leonardo Hernández Hernández
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the “Software”), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
******************************************************************/
|
||||||
|
|
||||||
|
/* cc -lxkbcommon -o generate-keys generate-keys.c */
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
struct xkb_context *context;
|
||||||
|
/* Allow generate keys with a different layout and variant.
|
||||||
|
* You can also use XKB_DEFAULT_* environmental variables and let this as is */
|
||||||
|
struct xkb_rule_names rules = {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
struct xkb_keymap *keymap;
|
||||||
|
struct xkb_state *state;
|
||||||
|
xkb_keycode_t keycode, min_keycode, max_keycode;
|
||||||
|
int i, nsyms;
|
||||||
|
const xkb_keysym_t *syms;
|
||||||
|
char keyname[64];
|
||||||
|
FILE *f = fopen("keys.h", "w");
|
||||||
|
if (!f) {
|
||||||
|
perror("Couldn't open keys.h");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(context = xkb_context_new(XKB_CONTEXT_NO_FLAGS))) {
|
||||||
|
fputs("Couldn't create xkbcommon context\n", stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(keymap = xkb_keymap_new_from_names(context, &rules,
|
||||||
|
XKB_KEYMAP_COMPILE_NO_FLAGS))) {
|
||||||
|
fputs("Couldn't create xkbcommon keymap\n", stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(state = xkb_state_new(keymap))) {
|
||||||
|
fputs("Couldn't create xkbcommon state\n", stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
min_keycode = xkb_keymap_min_keycode(keymap);
|
||||||
|
max_keycode = xkb_keymap_max_keycode(keymap);
|
||||||
|
|
||||||
|
for (keycode = min_keycode; keycode <= max_keycode; keycode++) {
|
||||||
|
nsyms = xkb_state_key_get_syms(state, keycode, &syms);
|
||||||
|
for (i = 0; i < nsyms; i++) {
|
||||||
|
xkb_keysym_get_name(syms[i], keyname, sizeof(keyname) / sizeof(keyname[0]));
|
||||||
|
fprintf(f, "#define Key_%-24s %d\n", keyname, keycode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xkb_state_unref(state);
|
||||||
|
xkb_keymap_unref(keymap);
|
||||||
|
xkb_context_unref(context);
|
||||||
|
}
|
242
user/.config/suckless/dwl/keys.h
Normal file
242
user/.config/suckless/dwl/keys.h
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
/* You can use the macros within this file
|
||||||
|
* instead of search the keycodes yourself
|
||||||
|
* with wev or something like that
|
||||||
|
* Also probably you search this:
|
||||||
|
* Key_XF86AudioMute
|
||||||
|
* Key_XF86AudioLowerVolume
|
||||||
|
* Key_XF86AudioRaiseVolume
|
||||||
|
* Key_XF86MonBrightnessDown
|
||||||
|
* Key_XF86MonBrightnessUp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define Key_Escape 9
|
||||||
|
#define Key_1 10
|
||||||
|
#define Key_2 11
|
||||||
|
#define Key_3 12
|
||||||
|
#define Key_4 13
|
||||||
|
#define Key_5 14
|
||||||
|
#define Key_6 15
|
||||||
|
#define Key_7 16
|
||||||
|
#define Key_8 17
|
||||||
|
#define Key_9 18
|
||||||
|
#define Key_0 19
|
||||||
|
#define Key_minus 20
|
||||||
|
#define Key_equal 21
|
||||||
|
#define Key_BackSpace 22
|
||||||
|
#define Key_Tab 23
|
||||||
|
#define Key_q 24
|
||||||
|
#define Key_w 25
|
||||||
|
#define Key_e 26
|
||||||
|
#define Key_r 27
|
||||||
|
#define Key_t 28
|
||||||
|
#define Key_y 29
|
||||||
|
#define Key_u 30
|
||||||
|
#define Key_i 31
|
||||||
|
#define Key_o 32
|
||||||
|
#define Key_p 33
|
||||||
|
#define Key_bracketleft 34
|
||||||
|
#define Key_bracketright 35
|
||||||
|
#define Key_Return 36
|
||||||
|
#define Key_Control_L 37
|
||||||
|
#define Key_a 38
|
||||||
|
#define Key_s 39
|
||||||
|
#define Key_d 40
|
||||||
|
#define Key_f 41
|
||||||
|
#define Key_g 42
|
||||||
|
#define Key_h 43
|
||||||
|
#define Key_j 44
|
||||||
|
#define Key_k 45
|
||||||
|
#define Key_l 46
|
||||||
|
#define Key_semicolon 47
|
||||||
|
#define Key_apostrophe 48
|
||||||
|
#define Key_grave 49
|
||||||
|
#define Key_Shift_L 50
|
||||||
|
#define Key_backslash 51
|
||||||
|
#define Key_z 52
|
||||||
|
#define Key_x 53
|
||||||
|
#define Key_c 54
|
||||||
|
#define Key_v 55
|
||||||
|
#define Key_b 56
|
||||||
|
#define Key_n 57
|
||||||
|
#define Key_m 58
|
||||||
|
#define Key_comma 59
|
||||||
|
#define Key_period 60
|
||||||
|
#define Key_slash 61
|
||||||
|
#define Key_Shift_R 62
|
||||||
|
#define Key_KP_Multiply 63
|
||||||
|
#define Key_Alt_L 64
|
||||||
|
#define Key_space 65
|
||||||
|
#define Key_Caps_Lock 66
|
||||||
|
#define Key_F1 67
|
||||||
|
#define Key_F2 68
|
||||||
|
#define Key_F3 69
|
||||||
|
#define Key_F4 70
|
||||||
|
#define Key_F5 71
|
||||||
|
#define Key_F6 72
|
||||||
|
#define Key_F7 73
|
||||||
|
#define Key_F8 74
|
||||||
|
#define Key_F9 75
|
||||||
|
#define Key_F10 76
|
||||||
|
#define Key_Num_Lock 77
|
||||||
|
#define Key_Scroll_Lock 78
|
||||||
|
#define Key_KP_Home 79
|
||||||
|
#define Key_KP_7 Key_KP_Home
|
||||||
|
#define Key_KP_Up 80
|
||||||
|
#define Key_KP_8 Key_KP_Up
|
||||||
|
#define Key_KP_Prior 81
|
||||||
|
#define Key_KP_9 Key_KP_Prior
|
||||||
|
#define Key_KP_Subtract 82
|
||||||
|
#define Key_KP_Left 83
|
||||||
|
#define Key_KP_4 Key_KP_Left
|
||||||
|
#define Key_KP_Begin 84
|
||||||
|
#define Key_KP_5 Key_KP_Begin
|
||||||
|
#define Key_KP_Right 85
|
||||||
|
#define Key_KP_6 Key_KP_Right
|
||||||
|
#define Key_KP_Add 86
|
||||||
|
#define Key_KP_End 87
|
||||||
|
#define Key_KP_1 Key_KP_End
|
||||||
|
#define Key_KP_Down 88
|
||||||
|
#define Key_KP_2 Key_KP_Down
|
||||||
|
#define Key_KP_Next 89
|
||||||
|
#define Key_KP_3 Key_KP_Next
|
||||||
|
#define Key_KP_Insert 90
|
||||||
|
#define Key_KP_0 Key_KP_Insert
|
||||||
|
#define Key_KP_Delete 91
|
||||||
|
#define Key_KP_Period Key_KP_Insert
|
||||||
|
#define Key_ISO_Level3_Shift 92
|
||||||
|
#define Key_less 94
|
||||||
|
#define Key_F11 95
|
||||||
|
#define Key_F12 96
|
||||||
|
#define Key_Katakana 98
|
||||||
|
#define Key_Hiragana 99
|
||||||
|
#define Key_Henkan_Mode 100
|
||||||
|
#define Key_Hiragana_Katakana 101
|
||||||
|
#define Key_Muhenkan 102
|
||||||
|
#define Key_KP_Enter 104
|
||||||
|
#define Key_Control_R 105
|
||||||
|
#define Key_KP_Divide 106
|
||||||
|
#define Key_Print 107
|
||||||
|
#define Key_Alt_R 108
|
||||||
|
#define Key_Linefeed 109
|
||||||
|
#define Key_Home 110
|
||||||
|
#define Key_Up 111
|
||||||
|
#define Key_Prior 112
|
||||||
|
#define Key_Left 113
|
||||||
|
#define Key_Right 114
|
||||||
|
#define Key_End 115
|
||||||
|
#define Key_Down 116
|
||||||
|
#define Key_Next 117
|
||||||
|
#define Key_Insert 118
|
||||||
|
#define Key_Delete 119
|
||||||
|
#define Key_XF86AudioMute 121
|
||||||
|
#define Key_XF86AudioLowerVolume 122
|
||||||
|
#define Key_XF86AudioRaiseVolume 123
|
||||||
|
#define Key_XF86PowerOff 124
|
||||||
|
#define Key_KP_Equal 125
|
||||||
|
#define Key_plusminus 126
|
||||||
|
#define Key_Pause 127
|
||||||
|
#define Key_XF86LaunchA 128
|
||||||
|
#define Key_KP_Decimal 129
|
||||||
|
#define Key_Hangul 130
|
||||||
|
#define Key_Hangul_Hanja 131
|
||||||
|
#define Key_Super_L 133
|
||||||
|
#define Key_Super_R 134
|
||||||
|
#define Key_Menu 135
|
||||||
|
#define Key_Cancel 136
|
||||||
|
#define Key_Redo 137
|
||||||
|
#define Key_SunProps 138
|
||||||
|
#define Key_Undo 139
|
||||||
|
#define Key_SunFront 140
|
||||||
|
#define Key_XF86Copy 141
|
||||||
|
#define Key_XF86Open 142
|
||||||
|
#define Key_XF86Paste 143
|
||||||
|
#define Key_Find 144
|
||||||
|
#define Key_XF86Cut 145
|
||||||
|
#define Key_Help 146
|
||||||
|
#define Key_XF86MenuKB 147
|
||||||
|
#define Key_XF86Calculator 148
|
||||||
|
#define Key_XF86Sleep 150
|
||||||
|
#define Key_XF86WakeUp 151
|
||||||
|
#define Key_XF86Explorer 152
|
||||||
|
#define Key_XF86Send 153
|
||||||
|
#define Key_XF86Xfer 155
|
||||||
|
#define Key_XF86Launch1 156
|
||||||
|
#define Key_XF86Launch2 157
|
||||||
|
#define Key_XF86WWW 158
|
||||||
|
#define Key_XF86DOS 159
|
||||||
|
#define Key_XF86ScreenSaver 160
|
||||||
|
#define Key_XF86RotateWindows 161
|
||||||
|
#define Key_XF86TaskPane 162
|
||||||
|
#define Key_XF86Mail 163
|
||||||
|
#define Key_XF86Favorites 164
|
||||||
|
#define Key_XF86MyComputer 165
|
||||||
|
#define Key_XF86Back 166
|
||||||
|
#define Key_XF86Forward 167
|
||||||
|
#define Key_XF86Eject1 169
|
||||||
|
#define Key_XF86Eject2 170
|
||||||
|
#define Key_XF86AudioNext 171
|
||||||
|
#define Key_XF86AudioPlay 172
|
||||||
|
#define Key_XF86AudioPrev 173
|
||||||
|
#define Key_XF86AudioStop 174
|
||||||
|
#define Key_XF86AudioRecord 175
|
||||||
|
#define Key_XF86AudioRewind 176
|
||||||
|
#define Key_XF86Phone 177
|
||||||
|
#define Key_XF86Tools 179
|
||||||
|
#define Key_XF86HomePage 180
|
||||||
|
#define Key_XF86Reload 181
|
||||||
|
#define Key_XF86Close 182
|
||||||
|
#define Key_XF86ScrollUp 185
|
||||||
|
#define Key_XF86ScrollDown 186
|
||||||
|
#define Key_parenleft 187
|
||||||
|
#define Key_parenright 188
|
||||||
|
#define Key_XF86New 189
|
||||||
|
#define Key_Redo2 190
|
||||||
|
#define Key_XF86Tools2 191
|
||||||
|
#define Key_XF86Launch5 192
|
||||||
|
#define Key_XF86Launch6 193
|
||||||
|
#define Key_XF86Launch7 194
|
||||||
|
#define Key_XF86Launch8 195
|
||||||
|
#define Key_XF86Launch9 196
|
||||||
|
#define Key_XF86AudioMicMute 198
|
||||||
|
#define Key_XF86TouchpadToggle 199
|
||||||
|
#define Key_XF86TouchpadOn 200
|
||||||
|
#define Key_XF86TouchpadOff 201
|
||||||
|
#define Key_Mode_switch 203
|
||||||
|
#define Key_XF86AudioPlay2 208
|
||||||
|
#define Key_XF86AudioPause 209
|
||||||
|
#define Key_XF86Launch3 210
|
||||||
|
#define Key_XF86Launch4 211
|
||||||
|
#define Key_XF86LaunchB 212
|
||||||
|
#define Key_XF86Suspend 213
|
||||||
|
#define Key_XF86Close2 214
|
||||||
|
#define Key_XF86AudioPlay3 215
|
||||||
|
#define Key_XF86AudioForward 216
|
||||||
|
#define Key_Print2 218
|
||||||
|
#define Key_XF86WebCam 220
|
||||||
|
#define Key_XF86AudioPreset 221
|
||||||
|
#define Key_XF86Mail2 223
|
||||||
|
#define Key_XF86Messenger 224
|
||||||
|
#define Key_XF86Search 225
|
||||||
|
#define Key_XF86Go 226
|
||||||
|
#define Key_XF86Finance 227
|
||||||
|
#define Key_XF86Game 228
|
||||||
|
#define Key_XF86Shop 229
|
||||||
|
#define Key_Cancel2 231
|
||||||
|
#define Key_XF86MonBrightnessDown 232
|
||||||
|
#define Key_XF86MonBrightnessUp 233
|
||||||
|
#define Key_XF86AudioMedia 234
|
||||||
|
#define Key_XF86Display 235
|
||||||
|
#define Key_XF86KbdLightOnOff 236
|
||||||
|
#define Key_XF86KbdBrightnessDown 237
|
||||||
|
#define Key_XF86KbdBrightnessUp 238
|
||||||
|
#define Key_XF86Send2 239
|
||||||
|
#define Key_XF86Reply 240
|
||||||
|
#define Key_XF86MailForward 241
|
||||||
|
#define Key_XF86Save 242
|
||||||
|
#define Key_XF86Documents 243
|
||||||
|
#define Key_XF86Battery 244
|
||||||
|
#define Key_XF86Bluetooth 245
|
||||||
|
#define Key_XF86WLAN 246
|
||||||
|
#define Key_XF86MonBrightnessCycle 251
|
||||||
|
#define Key_XF86WWAN 254
|
||||||
|
#define Key_XF86RFKill 255
|
33
user/.config/suckless/dwl/patches/alwayscenter.patch
Normal file
33
user/.config/suckless/dwl/patches/alwayscenter.patch
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
From 21c79e306889d1d318f8d8e9cf835c1d234faccf Mon Sep 17 00:00:00 2001
|
||||||
|
From: mortezadadgar <mortezadadgar97@gmail.com>
|
||||||
|
Date: Sat, 2 Sep 2023 12:33:00 +0330
|
||||||
|
Subject: [PATCH] Always center client window
|
||||||
|
|
||||||
|
Apply to parent windows as well.
|
||||||
|
---
|
||||||
|
dwl.c | 5 ++++-
|
||||||
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 4ff5c37f7..24697d5d4 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -1536,7 +1536,7 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
/* Called when the surface is mapped, or ready to display on-screen. */
|
||||||
|
Client *p, *w, *c = wl_container_of(listener, c, map);
|
||||||
|
- Monitor *m;
|
||||||
|
+ Monitor *m = selmon;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Create scene tree for this client and its border */
|
||||||
|
@@ -1582,6 +1582,9 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||||
|
wl_list_insert(&clients, &c->link);
|
||||||
|
wl_list_insert(&fstack, &c->flink);
|
||||||
|
|
||||||
|
+ c->geom.x = (m->w.width - c->geom.width) / 2 + m->m.x;
|
||||||
|
+ c->geom.y = (m->w.height - c->geom.height) / 2 + m->m.y;
|
||||||
|
+
|
||||||
|
/* 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
|
26
user/.config/suckless/dwl/patches/attachbottom.patch
Normal file
26
user/.config/suckless/dwl/patches/attachbottom.patch
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
From 396531c8e7905cb226be0a4c3cddc60726fa2794 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dmitry Zakharchenko <dmitz@disroot.org>
|
||||||
|
Date: Tue, 3 Jan 2023 20:01:34 +0200
|
||||||
|
Subject: [PATCH] attachbottom: sync with 0.4
|
||||||
|
|
||||||
|
---
|
||||||
|
dwl.c | 6 +++++-
|
||||||
|
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 19bb6ce34..7f940c45f 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -1511,7 +1511,11 @@ mapnotify(struct wl_listener *listener, void *data)
|
||||||
|
c->geom.height += 2 * c->bw;
|
||||||
|
|
||||||
|
/* Insert this client into client lists. */
|
||||||
|
- wl_list_insert(&clients, &c->link);
|
||||||
|
+ if (clients.prev)
|
||||||
|
+ // tile at the bottom
|
||||||
|
+ wl_list_insert(clients.prev, &c->link);
|
||||||
|
+ else
|
||||||
|
+ wl_list_insert(&clients, &c->link);
|
||||||
|
wl_list_insert(&fstack, &c->flink);
|
||||||
|
|
||||||
|
/* Set initial monitor, tags, floating status, and focus:
|
145
user/.config/suckless/dwl/patches/autostart.patch
Normal file
145
user/.config/suckless/dwl/patches/autostart.patch
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
From db02755bfff9c29927ed33ea70b459e33f565ba1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?=
|
||||||
|
<leohdz172@proton.me>
|
||||||
|
Date: Sat, 8 Jul 2023 17:11:36 -0600
|
||||||
|
Subject: [PATCH] port autostart patch from dwm
|
||||||
|
|
||||||
|
https://dwm.suckless.org/patches/cool_autostart/
|
||||||
|
---
|
||||||
|
config.def.h | 6 ++++++
|
||||||
|
dwl.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||||
|
2 files changed, 60 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 447ba0051..3cf694c7b 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -7,6 +7,12 @@ static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0};
|
||||||
|
/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */
|
||||||
|
static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
|
||||||
|
|
||||||
|
+/* Autostart */
|
||||||
|
+static const char *const autostart[] = {
|
||||||
|
+ "wbg", "/path/to/your/image", NULL,
|
||||||
|
+ NULL /* terminate */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/* tagging - tagcount must be no greater than 31 */
|
||||||
|
static const int tagcount = 9;
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 4ff5c37f7..6a2e7b645 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -227,6 +227,7 @@ static void arrange(Monitor *m);
|
||||||
|
static void arrangelayer(Monitor *m, struct wl_list *list,
|
||||||
|
struct wlr_box *usable_area, int exclusive);
|
||||||
|
static void arrangelayers(Monitor *m);
|
||||||
|
+static void autostartexec(void);
|
||||||
|
static void axisnotify(struct wl_listener *listener, void *data);
|
||||||
|
static void buttonpress(struct wl_listener *listener, void *data);
|
||||||
|
static void chvt(const Arg *arg);
|
||||||
|
@@ -413,6 +414,9 @@ static Atom netatom[NetLast];
|
||||||
|
/* attempt to encapsulate suck into one file */
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
+static pid_t *autostart_pids;
|
||||||
|
+static size_t autostart_len;
|
||||||
|
+
|
||||||
|
/* function implementations */
|
||||||
|
void
|
||||||
|
applybounds(Client *c, struct wlr_box *bbox)
|
||||||
|
@@ -553,6 +557,27 @@ arrangelayers(Monitor *m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+autostartexec(void) {
|
||||||
|
+ const char *const *p;
|
||||||
|
+ size_t i = 0;
|
||||||
|
+
|
||||||
|
+ /* count entries */
|
||||||
|
+ for (p = autostart; *p; autostart_len++, p++)
|
||||||
|
+ while (*++p);
|
||||||
|
+
|
||||||
|
+ autostart_pids = calloc(autostart_len, sizeof(pid_t));
|
||||||
|
+ for (p = autostart; *p; i++, p++) {
|
||||||
|
+ if ((autostart_pids[i] = fork()) == 0) {
|
||||||
|
+ setsid();
|
||||||
|
+ execvp(*p, (char *const *)p);
|
||||||
|
+ die("dwl: execvp %s:", *p);
|
||||||
|
+ }
|
||||||
|
+ /* skip arguments */
|
||||||
|
+ while (*++p);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
axisnotify(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
@@ -652,10 +677,20 @@ checkidleinhibitor(struct wlr_surface *exclude)
|
||||||
|
void
|
||||||
|
cleanup(void)
|
||||||
|
{
|
||||||
|
+ size_t i;
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
wlr_xwayland_destroy(xwayland);
|
||||||
|
#endif
|
||||||
|
wl_display_destroy_clients(dpy);
|
||||||
|
+
|
||||||
|
+ /* kill child processes */
|
||||||
|
+ for (i = 0; i < autostart_len; i++) {
|
||||||
|
+ if (0 < autostart_pids[i]) {
|
||||||
|
+ kill(autostart_pids[i], SIGTERM);
|
||||||
|
+ waitpid(autostart_pids[i], NULL, 0);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (child_pid > 0) {
|
||||||
|
kill(child_pid, SIGTERM);
|
||||||
|
waitpid(child_pid, NULL, 0);
|
||||||
|
@@ -1333,18 +1368,31 @@ void
|
||||||
|
handlesig(int signo)
|
||||||
|
{
|
||||||
|
if (signo == SIGCHLD) {
|
||||||
|
-#ifdef XWAYLAND
|
||||||
|
siginfo_t in;
|
||||||
|
/* wlroots expects to reap the XWayland process itself, so we
|
||||||
|
* use WNOWAIT to keep the child waitable until we know it's not
|
||||||
|
* XWayland.
|
||||||
|
*/
|
||||||
|
while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
|
||||||
|
- && (!xwayland || in.si_pid != xwayland->server->pid))
|
||||||
|
- waitpid(in.si_pid, NULL, 0);
|
||||||
|
-#else
|
||||||
|
- while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||||
|
+#ifdef XWAYLAND
|
||||||
|
+ && (!xwayland || in.si_pid != xwayland->server->pid)
|
||||||
|
#endif
|
||||||
|
+ ) {
|
||||||
|
+ pid_t *p, *lim;
|
||||||
|
+ waitpid(in.si_pid, NULL, 0);
|
||||||
|
+ if (in.si_pid == child_pid)
|
||||||
|
+ child_pid = -1;
|
||||||
|
+ if (!(p = autostart_pids))
|
||||||
|
+ continue;
|
||||||
|
+ lim = &p[autostart_len];
|
||||||
|
+
|
||||||
|
+ for (; p < lim; p++) {
|
||||||
|
+ if (*p == in.si_pid) {
|
||||||
|
+ *p = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
} else if (signo == SIGINT || signo == SIGTERM) {
|
||||||
|
quit(NULL);
|
||||||
|
}
|
||||||
|
@@ -1964,6 +2012,7 @@ run(char *startup_cmd)
|
||||||
|
die("startup: backend_start");
|
||||||
|
|
||||||
|
/* Now that the socket exists and the backend is started, run the startup command */
|
||||||
|
+ autostartexec();
|
||||||
|
if (startup_cmd) {
|
||||||
|
int piperw[2];
|
||||||
|
if (pipe(piperw) < 0)
|
138
user/.config/suckless/dwl/patches/bottomstack.patch
Normal file
138
user/.config/suckless/dwl/patches/bottomstack.patch
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
From 68c6138afe15c3834260a0655eeee89f8103481a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Abanoub <abanoubsameh@protonmail.com>
|
||||||
|
Date: Wed, 21 Jun 2023 17:55:00 +0300
|
||||||
|
Subject: [PATCH] bottomstack
|
||||||
|
|
||||||
|
---
|
||||||
|
config.def.h | 4 +++
|
||||||
|
dwl.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 88 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 447ba0051..0651a7e3a 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -24,6 +24,8 @@ static const Layout layouts[] = {
|
||||||
|
{ "[]=", tile },
|
||||||
|
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||||
|
{ "[M]", monocle },
|
||||||
|
+ { "TTT", bstack },
|
||||||
|
+ { "===", bstackhoriz },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* monitors */
|
||||||
|
@@ -123,6 +125,8 @@ static const Key keys[] = {
|
||||||
|
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||||
|
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||||
|
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||||
|
+ { MODKEY, XKB_KEY_u, setlayout, {.v = &layouts[3]} },
|
||||||
|
+ { MODKEY, XKB_KEY_o, setlayout, {.v = &layouts[4]} },
|
||||||
|
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||||
|
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index da3a51613..285c74477 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -50,6 +50,7 @@
|
||||||
|
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
||||||
|
#include <wlr/types/wlr_xdg_output_v1.h>
|
||||||
|
#include <wlr/types/wlr_xdg_shell.h>
|
||||||
|
+#include <wlr/util/box.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
@@ -319,6 +320,8 @@ static Monitor *xytomon(double x, double y);
|
||||||
|
static struct wlr_scene_node *xytonode(double x, double y, struct wlr_surface **psurface,
|
||||||
|
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||||
|
static void zoom(const Arg *arg);
|
||||||
|
+static void bstack(Monitor *m);
|
||||||
|
+static void bstackhoriz(Monitor *m);
|
||||||
|
|
||||||
|
/* variables */
|
||||||
|
static const char broken[] = "broken";
|
||||||
|
@@ -2841,3 +2844,84 @@ main(int argc, char *argv[])
|
||||||
|
usage:
|
||||||
|
die("Usage: %s [-v] [-s startup command]", argv[0]);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+bstack(Monitor *m)
|
||||||
|
+{
|
||||||
|
+ int w, h, mh, mx, tx, ty, tw;
|
||||||
|
+ unsigned int i, n = 0;
|
||||||
|
+ Client *c;
|
||||||
|
+
|
||||||
|
+ wl_list_for_each(c, &clients, link)
|
||||||
|
+ if (VISIBLEON(c, m) && !c->isfloating)
|
||||||
|
+ n++;
|
||||||
|
+ if (n == 0)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (n > m->nmaster) {
|
||||||
|
+ mh = m->nmaster ? m->mfact * m->w.height : 0;
|
||||||
|
+ tw = m->w.width / (n - m->nmaster);
|
||||||
|
+ ty = m->w.y + mh;
|
||||||
|
+ } else {
|
||||||
|
+ mh = m->w.height;
|
||||||
|
+ tw = m->w.width;
|
||||||
|
+ ty = m->w.y;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ i = mx = 0;
|
||||||
|
+ tx = m-> w.x;
|
||||||
|
+ wl_list_for_each(c, &clients, link) {
|
||||||
|
+ if (!VISIBLEON(c, m) || c->isfloating)
|
||||||
|
+ continue;
|
||||||
|
+ if (i < m->nmaster) {
|
||||||
|
+ w = (m->w.width - mx) / (MIN(n, m->nmaster) - i);
|
||||||
|
+ resize(c, (struct wlr_box) { .x = m->w.x + mx, .y = m->w.y, .width = w - (2 * c->bw), .height = mh - (2 * c->bw) }, 0);
|
||||||
|
+ mx += c->geom.width;
|
||||||
|
+ } else {
|
||||||
|
+ h = m->w.height - mh;
|
||||||
|
+ resize(c, (struct wlr_box) { .x = tx, .y = ty, .width = tw - (2 * c->bw), .height = h - (2 * c->bw) }, 0);
|
||||||
|
+ if (tw != m->w.width)
|
||||||
|
+ tx += c->geom.width;
|
||||||
|
+ }
|
||||||
|
+ i++;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+bstackhoriz(Monitor *m) {
|
||||||
|
+ int w, mh, mx, tx, ty, th;
|
||||||
|
+ unsigned int i, n = 0;
|
||||||
|
+ Client *c;
|
||||||
|
+
|
||||||
|
+ wl_list_for_each(c, &clients, link)
|
||||||
|
+ if (VISIBLEON(c, m) && !c->isfloating)
|
||||||
|
+ n ++;
|
||||||
|
+ if (n == 0)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (n > m->nmaster) {
|
||||||
|
+ mh = m->nmaster ? m->mfact * m->w.height : 0;
|
||||||
|
+ th = (m->w.height - mh) / (n - m->nmaster);
|
||||||
|
+ ty = m->w.y + mh;
|
||||||
|
+ } else {
|
||||||
|
+ th = mh = m->w.height;
|
||||||
|
+ ty = m->w.y;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ i = mx = 0;
|
||||||
|
+ tx = m-> w.x;
|
||||||
|
+ wl_list_for_each(c, &clients, link) {
|
||||||
|
+ if (!VISIBLEON(c,m) || c->isfloating)
|
||||||
|
+ continue;
|
||||||
|
+ if (i < m->nmaster) {
|
||||||
|
+ w = (m->w.width - mx) / (MIN(n, m->nmaster) - i);
|
||||||
|
+ resize(c, (struct wlr_box) { .x = m->w.x + mx, .y = m->w.y, .width = w - (2 * c->bw), .height = mh - (2 * c->bw) }, 0);
|
||||||
|
+ mx += c->geom.width;
|
||||||
|
+ } else {
|
||||||
|
+ resize(c, (struct wlr_box) { .x = tx, .y = ty, .width = m->w.width - (2 * c->bw), .height = th - (2 * c->bw) }, 0);
|
||||||
|
+ if (th != m->w.height)
|
||||||
|
+ ty += c->geom.height;
|
||||||
|
+ }
|
||||||
|
+ i++;
|
||||||
|
+ }
|
||||||
|
+}
|
132
user/.config/suckless/dwl/patches/centeredmaster.patch
Normal file
132
user/.config/suckless/dwl/patches/centeredmaster.patch
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
From 05d0c5ed12520e0400d0e5ec685c74f013ce9a7f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
|
||||||
|
Date: Fri, 19 May 2023 00:55:24 +0200
|
||||||
|
Subject: [PATCH] Add centeredmaster layout
|
||||||
|
|
||||||
|
This is a port of centeredmaster patch for dwm:
|
||||||
|
https://dwm.suckless.org/patches/centeredmaster
|
||||||
|
|
||||||
|
centeredmaster centers the nmaster area on screen, using mfact * monitor
|
||||||
|
width & height, with the stacked windows distributed to the left and
|
||||||
|
right. It can be selected with [Alt]+[c].
|
||||||
|
|
||||||
|
With one and two clients in master respectively this results in:
|
||||||
|
|
||||||
|
+------------------------------+ +------------------------------+
|
||||||
|
|+--------++--------++--------+| |+--------++--------++--------+|
|
||||||
|
|| || || || || || || ||
|
||||||
|
|| || || || || || M1 || ||
|
||||||
|
|| || || || || || || ||
|
||||||
|
|| S2 || M || S1 || || |+--------+| ||
|
||||||
|
|| || || || || |+--------+| ||
|
||||||
|
|| || || || || || || ||
|
||||||
|
|| || || || || || M2 || ||
|
||||||
|
|| || || || || || || ||
|
||||||
|
|+--------++--------++--------+| |+--------++--------++--------+|
|
||||||
|
+------------------------------+ +------------------------------+
|
||||||
|
---
|
||||||
|
config.def.h | 2 ++
|
||||||
|
dwl.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 65 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index c6a495048..23605e1a5 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -24,6 +24,7 @@ static const Layout layouts[] = {
|
||||||
|
{ "[]=", tile },
|
||||||
|
{ "><>", NULL }, /* no layout function means floating behavior */
|
||||||
|
{ "[M]", monocle },
|
||||||
|
+ { "|M|", centeredmaster },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* monitors */
|
||||||
|
@@ -123,6 +124,7 @@ static const Key keys[] = {
|
||||||
|
{ MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||||
|
{ MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||||
|
{ MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||||
|
+ { MODKEY, XKB_KEY_c, setlayout, {.v = &layouts[3]} },
|
||||||
|
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||||
|
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index b7436bb4f..7cbb3680b 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -229,6 +229,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
|
||||||
|
static void arrangelayers(Monitor *m);
|
||||||
|
static void axisnotify(struct wl_listener *listener, void *data);
|
||||||
|
static void buttonpress(struct wl_listener *listener, void *data);
|
||||||
|
+static void centeredmaster(Monitor *m);
|
||||||
|
static void chvt(const Arg *arg);
|
||||||
|
static void checkidleinhibitor(struct wlr_surface *exclude);
|
||||||
|
static void cleanup(void);
|
||||||
|
@@ -622,6 +623,68 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||||
|
event->time_msec, event->button, event->state);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+centeredmaster(Monitor *m)
|
||||||
|
+{
|
||||||
|
+ unsigned int i, n, h, mw, mx, my, oty, ety, tw;
|
||||||
|
+ Client *c;
|
||||||
|
+
|
||||||
|
+ n = 0;
|
||||||
|
+ wl_list_for_each(c, &clients, link)
|
||||||
|
+ if (VISIBLEON(c, m) && !c->isfloating && !c->isfullscreen)
|
||||||
|
+ n++;
|
||||||
|
+ if (n == 0)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ /* initialize areas */
|
||||||
|
+ mw = m->w.width;
|
||||||
|
+ mx = 0;
|
||||||
|
+ my = 0;
|
||||||
|
+ tw = mw;
|
||||||
|
+
|
||||||
|
+ if (n > m->nmaster) {
|
||||||
|
+ /* go mfact box in the center if more than nmaster clients */
|
||||||
|
+ mw = m->nmaster ? m->w.width * m->mfact : 0;
|
||||||
|
+ tw = m->w.width - mw;
|
||||||
|
+
|
||||||
|
+ if (n - m->nmaster > 1) {
|
||||||
|
+ /* only one client */
|
||||||
|
+ mx = (m->w.width - mw) / 2;
|
||||||
|
+ tw = (m->w.width - mw) / 2;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ i = 0;
|
||||||
|
+ oty = 0;
|
||||||
|
+ ety = 0;
|
||||||
|
+ wl_list_for_each(c, &clients, link) {
|
||||||
|
+ if (!VISIBLEON(c, m) || c->isfloating || c->isfullscreen)
|
||||||
|
+ continue;
|
||||||
|
+ if (i < m->nmaster) {
|
||||||
|
+ /* nmaster clients are stacked vertically, in the center
|
||||||
|
+ * of the screen */
|
||||||
|
+ h = (m->w.height - my) / (MIN(n, m->nmaster) - i);
|
||||||
|
+ resize(c, (struct wlr_box){.x = m->w.x + mx, .y = m->w.y + my, .width = mw,
|
||||||
|
+ .height = h}, 0);
|
||||||
|
+ my += c->geom.height;
|
||||||
|
+ } else {
|
||||||
|
+ /* stack clients are stacked vertically */
|
||||||
|
+ if ((i - m->nmaster) % 2) {
|
||||||
|
+ h = (m->w.height - ety) / ( (1 + n - i) / 2);
|
||||||
|
+ resize(c, (struct wlr_box){.x = m->w.x, .y = m->w.y + ety, .width = tw,
|
||||||
|
+ .height = h}, 0);
|
||||||
|
+ ety += c->geom.height;
|
||||||
|
+ } else {
|
||||||
|
+ h = (m->w.height - oty) / ((1 + n - i) / 2);
|
||||||
|
+ resize(c, (struct wlr_box){.x = m->w.x + mx + mw, .y = m->w.y + oty, .width = tw,
|
||||||
|
+ .height = h}, 0);
|
||||||
|
+ oty += c->geom.height;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ i++;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
chvt(const Arg *arg)
|
||||||
|
{
|
66
user/.config/suckless/dwl/patches/float-border-color.patch
Normal file
66
user/.config/suckless/dwl/patches/float-border-color.patch
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
From a0bc203213e2359f6717e269081a346666279d8d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Palanix <palanixyt@gmail.com>
|
||||||
|
Date: Sat, 26 Mar 2022 14:24:54 +0100
|
||||||
|
Subject: [PATCH] Implement an extra color for floating clients
|
||||||
|
|
||||||
|
---
|
||||||
|
config.def.h | 1 +
|
||||||
|
dwl.c | 18 +++++++++++++++---
|
||||||
|
2 files changed, 16 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 447ba0051..6a79241bc 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -3,6 +3,7 @@ static const int sloppyfocus = 1; /* focus follows mouse */
|
||||||
|
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
|
||||||
|
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||||
|
static const float bordercolor[] = {0.5, 0.5, 0.5, 1.0};
|
||||||
|
+static const float floatcolor[] = {1.0, 0.0, 0.0, 0.0};
|
||||||
|
static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0};
|
||||||
|
/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */
|
||||||
|
static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index b5e146d10..78f252eb5 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -613,6 +613,7 @@ buttonpress(struct wl_listener *listener, void *data)
|
||||||
|
/* Drop the window off on its new monitor */
|
||||||
|
selmon = xytomon(cursor->x, cursor->y);
|
||||||
|
setmon(grabc, selmon, 0);
|
||||||
|
+ grabc = NULL;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
cursor_mode = CurNormal;
|
||||||
|
@@ -1255,10 +1256,15 @@ focusclient(Client *c, int lift)
|
||||||
|
/* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg
|
||||||
|
* and probably other clients */
|
||||||
|
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
|
||||||
|
- for (i = 0; i < 4; i++)
|
||||||
|
- wlr_scene_rect_set_color(old_c->border[i], bordercolor);
|
||||||
|
+ if (old_c->isfloating) {
|
||||||
|
+ for (i = 0; i < 4; i++)
|
||||||
|
+ wlr_scene_rect_set_color(old_c->border[i], floatcolor);
|
||||||
|
+ } else {
|
||||||
|
+ for (i = 0; i < 4; i++)
|
||||||
|
+ wlr_scene_rect_set_color(old_c->border[i], bordercolor);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- client_activate_surface(old, 0);
|
||||||
|
+ client_activate_surface(old, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printstatus();
|
||||||
|
@@ -2036,6 +2042,12 @@ setfloating(Client *c, int floating)
|
||||||
|
{
|
||||||
|
c->isfloating = floating;
|
||||||
|
wlr_scene_node_reparent(&c->scene->node, layers[c->isfloating ? LyrFloat : LyrTile]);
|
||||||
|
+ if (!grabc)
|
||||||
|
+ if (floating)
|
||||||
|
+ for (int i = 0; i < 4; i++) {
|
||||||
|
+ wlr_scene_rect_set_color(c->border[i], floatcolor);
|
||||||
|
+ wlr_scene_node_lower_to_bottom(&c->border[i]->node);
|
||||||
|
+ }
|
||||||
|
arrange(c->mon);
|
||||||
|
printstatus();
|
||||||
|
}
|
574
user/.config/suckless/dwl/patches/ipc-v2-fixed.patch
Normal file
574
user/.config/suckless/dwl/patches/ipc-v2-fixed.patch
Normal file
|
@ -0,0 +1,574 @@
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 5320e42..c13557c 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -14,10 +14,11 @@ DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CF
|
||||||
|
LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` $(LIBS)
|
||||||
|
|
||||||
|
all: dwl
|
||||||
|
-dwl: dwl.o util.o
|
||||||
|
- $(CC) dwl.o util.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) -o $@
|
||||||
|
-dwl.o: dwl.c config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h
|
||||||
|
+dwl: dwl.o util.o dwl-ipc-unstable-v2-protocol.o
|
||||||
|
+ $(CC) dwl.o util.o dwl-ipc-unstable-v2-protocol.o $(LDLIBS) $(LDFLAGS) $(DWLCFLAGS) -o $@
|
||||||
|
+dwl.o: dwl.c config.mk config.h client.h xdg-shell-protocol.h wlr-layer-shell-unstable-v1-protocol.h dwl-ipc-unstable-v2-protocol.h
|
||||||
|
util.o: util.c util.h
|
||||||
|
+dwl-ipc-unstable-v2-protocol.o: dwl-ipc-unstable-v2-protocol.h
|
||||||
|
|
||||||
|
# wayland-scanner is a tool which generates C headers and rigging for Wayland
|
||||||
|
# protocols, which are specified in XML. wlroots requires you to rig these up
|
||||||
|
@@ -31,6 +32,12 @@ xdg-shell-protocol.h:
|
||||||
|
wlr-layer-shell-unstable-v1-protocol.h:
|
||||||
|
$(WAYLAND_SCANNER) server-header \
|
||||||
|
protocols/wlr-layer-shell-unstable-v1.xml $@
|
||||||
|
+dwl-ipc-unstable-v2-protocol.h:
|
||||||
|
+ $(WAYLAND_SCANNER) server-header \
|
||||||
|
+ protocols/dwl-ipc-unstable-v2.xml $@
|
||||||
|
+dwl-ipc-unstable-v2-protocol.c:
|
||||||
|
+ $(WAYLAND_SCANNER) private-code \
|
||||||
|
+ protocols/dwl-ipc-unstable-v2.xml $@
|
||||||
|
|
||||||
|
config.h:
|
||||||
|
cp config.def.h $@
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 4e30885..f285840 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -120,6 +120,7 @@ static const Key keys[] = {
|
||||||
|
/* modifier key function argument */
|
||||||
|
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||||
|
+ { MODKEY, XKB_KEY_b, togglebar, {0}},
|
||||||
|
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
||||||
|
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||||
|
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index a7d41b0..e507e31 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -58,6 +58,7 @@
|
||||||
|
#include <xcb/xcb_icccm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#include "dwl-ipc-unstable-v2-protocol.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
/* macros */
|
||||||
|
@@ -128,6 +129,12 @@ typedef struct {
|
||||||
|
uint32_t resize; /* configure serial of a pending resize */
|
||||||
|
} Client;
|
||||||
|
|
||||||
|
+typedef struct {
|
||||||
|
+ struct wl_list link;
|
||||||
|
+ struct wl_resource *resource;
|
||||||
|
+ Monitor *mon;
|
||||||
|
+} DwlIpcOutput;
|
||||||
|
+
|
||||||
|
typedef struct {
|
||||||
|
uint32_t mod;
|
||||||
|
xkb_keysym_t keysym;
|
||||||
|
@@ -174,6 +181,7 @@ typedef struct {
|
||||||
|
|
||||||
|
struct Monitor {
|
||||||
|
struct wl_list link;
|
||||||
|
+ struct wl_list dwl_ipc_outputs;
|
||||||
|
struct wlr_output *wlr_output;
|
||||||
|
struct wlr_scene_output *scene_output;
|
||||||
|
struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */
|
||||||
|
@@ -255,6 +263,17 @@ static void destroynotify(struct wl_listener *listener, void *data);
|
||||||
|
static void destroysessionlock(struct wl_listener *listener, void *data);
|
||||||
|
static void destroysessionmgr(struct wl_listener *listener, void *data);
|
||||||
|
static Monitor *dirtomon(enum wlr_direction dir);
|
||||||
|
+static void dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id);
|
||||||
|
+static void dwl_ipc_manager_destroy(struct wl_resource *resource);
|
||||||
|
+static void dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output);
|
||||||
|
+static void dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource);
|
||||||
|
+static void dwl_ipc_output_destroy(struct wl_resource *resource);
|
||||||
|
+static void dwl_ipc_output_printstatus(Monitor *monitor);
|
||||||
|
+static void dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output);
|
||||||
|
+static void dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags);
|
||||||
|
+static void dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index);
|
||||||
|
+static void dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset);
|
||||||
|
+static void dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource);
|
||||||
|
static void focusclient(Client *c, int lift);
|
||||||
|
static void focusmon(const Arg *arg);
|
||||||
|
static void focusstack(const Arg *arg);
|
||||||
|
@@ -302,6 +321,7 @@ static void startdrag(struct wl_listener *listener, void *data);
|
||||||
|
static void tag(const Arg *arg);
|
||||||
|
static void tagmon(const Arg *arg);
|
||||||
|
static void tile(Monitor *m);
|
||||||
|
+static void togglebar(const Arg *arg);
|
||||||
|
static void togglefloating(const Arg *arg);
|
||||||
|
static void togglefullscreen(const Arg *arg);
|
||||||
|
static void toggletag(const Arg *arg);
|
||||||
|
@@ -374,6 +394,8 @@ static struct wl_listener cursor_frame = {.notify = cursorframe};
|
||||||
|
static struct wl_listener cursor_motion = {.notify = motionrelative};
|
||||||
|
static struct wl_listener cursor_motion_absolute = {.notify = motionabsolute};
|
||||||
|
static struct wl_listener drag_icon_destroy = {.notify = destroydragicon};
|
||||||
|
+static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {.release = dwl_ipc_manager_release, .get_output = dwl_ipc_manager_get_output};
|
||||||
|
+static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {.release = dwl_ipc_output_release, .set_tags = dwl_ipc_output_set_tags, .set_layout = dwl_ipc_output_set_layout, .set_client_tags = dwl_ipc_output_set_client_tags};
|
||||||
|
static struct wl_listener idle_inhibitor_create = {.notify = createidleinhibitor};
|
||||||
|
static struct wl_listener idle_inhibitor_destroy = {.notify = destroyidleinhibitor};
|
||||||
|
static struct wl_listener layout_change = {.notify = updatemons};
|
||||||
|
@@ -691,6 +713,9 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||||
|
LayerSurface *l, *tmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
+ DwlIpcOutput *ipc_output, *ipc_output_tmp;
|
||||||
|
+ wl_list_for_each_safe(ipc_output, ipc_output_tmp, &m->dwl_ipc_outputs, link)
|
||||||
|
+ wl_resource_destroy(ipc_output->resource);
|
||||||
|
for (i = 0; i <= ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY; i++)
|
||||||
|
wl_list_for_each_safe(l, tmp, &m->layers[i], link)
|
||||||
|
wlr_layer_surface_v1_destroy(l->layer_surface);
|
||||||
|
@@ -902,6 +927,7 @@ createmon(struct wl_listener *listener, void *data)
|
||||||
|
Monitor *m = wlr_output->data = ecalloc(1, sizeof(*m));
|
||||||
|
m->wlr_output = wlr_output;
|
||||||
|
|
||||||
|
+ wl_list_init(&m->dwl_ipc_outputs);
|
||||||
|
wlr_output_init_render(wlr_output, alloc, drw);
|
||||||
|
|
||||||
|
/* Initialize monitor state using configured rules */
|
||||||
|
@@ -1195,6 +1221,190 @@ dirtomon(enum wlr_direction dir)
|
||||||
|
return selmon;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+dwl_ipc_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
|
||||||
|
+{
|
||||||
|
+ struct wl_resource *manager_resource = wl_resource_create(client, &zdwl_ipc_manager_v2_interface, version, id);
|
||||||
|
+ if (!manager_resource) {
|
||||||
|
+ wl_client_post_no_memory(client);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ wl_resource_set_implementation(manager_resource, &dwl_manager_implementation, NULL, dwl_ipc_manager_destroy);
|
||||||
|
+
|
||||||
|
+ zdwl_ipc_manager_v2_send_tags(manager_resource, TAGCOUNT);
|
||||||
|
+
|
||||||
|
+ for (int i = 0; i < LENGTH(layouts); i++)
|
||||||
|
+ zdwl_ipc_manager_v2_send_layout(manager_resource, layouts[i].symbol);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+dwl_ipc_manager_destroy(struct wl_resource *resource)
|
||||||
|
+{
|
||||||
|
+ /* No state to destroy */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+dwl_ipc_manager_get_output(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *output)
|
||||||
|
+{
|
||||||
|
+ DwlIpcOutput *ipc_output;
|
||||||
|
+ Monitor *monitor = wlr_output_from_resource(output)->data;
|
||||||
|
+ struct wl_resource *output_resource = wl_resource_create(client, &zdwl_ipc_output_v2_interface, wl_resource_get_version(resource), id);
|
||||||
|
+ if (!output_resource)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ ipc_output = ecalloc(1, sizeof(*ipc_output));
|
||||||
|
+ ipc_output->resource = output_resource;
|
||||||
|
+ ipc_output->mon = monitor;
|
||||||
|
+ wl_resource_set_implementation(output_resource, &dwl_output_implementation, ipc_output, dwl_ipc_output_destroy);
|
||||||
|
+ wl_list_insert(&monitor->dwl_ipc_outputs, &ipc_output->link);
|
||||||
|
+ dwl_ipc_output_printstatus_to(ipc_output);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+dwl_ipc_manager_release(struct wl_client *client, struct wl_resource *resource)
|
||||||
|
+{
|
||||||
|
+ wl_resource_destroy(resource);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+dwl_ipc_output_destroy(struct wl_resource *resource)
|
||||||
|
+{
|
||||||
|
+ DwlIpcOutput *ipc_output = wl_resource_get_user_data(resource);
|
||||||
|
+ wl_list_remove(&ipc_output->link);
|
||||||
|
+ free(ipc_output);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+dwl_ipc_output_printstatus(Monitor *monitor)
|
||||||
|
+{
|
||||||
|
+ DwlIpcOutput *ipc_output;
|
||||||
|
+ wl_list_for_each(ipc_output, &monitor->dwl_ipc_outputs, link)
|
||||||
|
+ dwl_ipc_output_printstatus_to(ipc_output);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+dwl_ipc_output_printstatus_to(DwlIpcOutput *ipc_output)
|
||||||
|
+{
|
||||||
|
+ Monitor *monitor = ipc_output->mon;
|
||||||
|
+ Client *c, *focused;
|
||||||
|
+ int tagmask, state, numclients, focused_client, tag;
|
||||||
|
+ const char *title, *appid;
|
||||||
|
+ focused = focustop(monitor);
|
||||||
|
+ zdwl_ipc_output_v2_send_active(ipc_output->resource, monitor == selmon);
|
||||||
|
+
|
||||||
|
+ for (tag = 0 ; tag < TAGCOUNT; tag++) {
|
||||||
|
+ numclients = state = focused_client = 0;
|
||||||
|
+ tagmask = 1 << tag;
|
||||||
|
+ if ((tagmask & monitor->tagset[monitor->seltags]) != 0)
|
||||||
|
+ state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_ACTIVE;
|
||||||
|
+
|
||||||
|
+ wl_list_for_each(c, &clients, link) {
|
||||||
|
+ if (c->mon != monitor)
|
||||||
|
+ continue;
|
||||||
|
+ if (!(c->tags & tagmask))
|
||||||
|
+ continue;
|
||||||
|
+ if (c == focused)
|
||||||
|
+ focused_client = 1;
|
||||||
|
+ if (c->isurgent)
|
||||||
|
+ state |= ZDWL_IPC_OUTPUT_V2_TAG_STATE_URGENT;
|
||||||
|
+
|
||||||
|
+ numclients++;
|
||||||
|
+ }
|
||||||
|
+ zdwl_ipc_output_v2_send_tag(ipc_output->resource, tag, state, numclients, focused_client);
|
||||||
|
+ }
|
||||||
|
+ title = focused ? client_get_title(focused) : "";
|
||||||
|
+ appid = focused ? client_get_appid(focused) : "";
|
||||||
|
+
|
||||||
|
+ zdwl_ipc_output_v2_send_layout(ipc_output->resource, monitor->lt[monitor->sellt] - layouts);
|
||||||
|
+ zdwl_ipc_output_v2_send_title(ipc_output->resource, title ? title : broken);
|
||||||
|
+ zdwl_ipc_output_v2_send_appid(ipc_output->resource, appid ? appid : broken);
|
||||||
|
+ zdwl_ipc_output_v2_send_layout_symbol(ipc_output->resource, monitor->ltsymbol);
|
||||||
|
+ if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FULLSCREEN_SINCE_VERSION) {
|
||||||
|
+ zdwl_ipc_output_v2_send_fullscreen(ipc_output->resource, focused ? focused->isfullscreen : 0);
|
||||||
|
+ }
|
||||||
|
+ if (wl_resource_get_version(ipc_output->resource) >= ZDWL_IPC_OUTPUT_V2_FLOATING_SINCE_VERSION) {
|
||||||
|
+ zdwl_ipc_output_v2_send_floating(ipc_output->resource, focused ? focused->isfloating : 0);
|
||||||
|
+ }
|
||||||
|
+ zdwl_ipc_output_v2_send_frame(ipc_output->resource);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+dwl_ipc_output_set_client_tags(struct wl_client *client, struct wl_resource *resource, uint32_t and_tags, uint32_t xor_tags)
|
||||||
|
+{
|
||||||
|
+ DwlIpcOutput *ipc_output;
|
||||||
|
+ Monitor *monitor;
|
||||||
|
+ Client *selected_client;
|
||||||
|
+ unsigned int newtags = 0;
|
||||||
|
+
|
||||||
|
+ ipc_output = wl_resource_get_user_data(resource);
|
||||||
|
+ if (!ipc_output)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ monitor = ipc_output->mon;
|
||||||
|
+ selected_client = focustop(monitor);
|
||||||
|
+ if (!selected_client)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ newtags = (selected_client->tags & and_tags) ^ xor_tags;
|
||||||
|
+ if (!newtags)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ selected_client->tags = newtags;
|
||||||
|
+ focusclient(focustop(selmon), 1);
|
||||||
|
+ arrange(selmon);
|
||||||
|
+ printstatus();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+dwl_ipc_output_set_layout(struct wl_client *client, struct wl_resource *resource, uint32_t index)
|
||||||
|
+{
|
||||||
|
+ DwlIpcOutput *ipc_output;
|
||||||
|
+ Monitor *monitor;
|
||||||
|
+
|
||||||
|
+ ipc_output = wl_resource_get_user_data(resource);
|
||||||
|
+ if (!ipc_output)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ monitor = ipc_output->mon;
|
||||||
|
+ if (index >= LENGTH(layouts))
|
||||||
|
+ return;
|
||||||
|
+ if (index != monitor->lt[monitor->sellt] - layouts)
|
||||||
|
+ monitor->sellt ^= 1;
|
||||||
|
+
|
||||||
|
+ monitor->lt[monitor->sellt] = &layouts[index];
|
||||||
|
+ arrange(monitor);
|
||||||
|
+ printstatus();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+dwl_ipc_output_set_tags(struct wl_client *client, struct wl_resource *resource, uint32_t tagmask, uint32_t toggle_tagset)
|
||||||
|
+{
|
||||||
|
+ DwlIpcOutput *ipc_output;
|
||||||
|
+ Monitor *monitor;
|
||||||
|
+ unsigned int newtags = tagmask & TAGMASK;
|
||||||
|
+
|
||||||
|
+ ipc_output = wl_resource_get_user_data(resource);
|
||||||
|
+ if (!ipc_output)
|
||||||
|
+ return;
|
||||||
|
+ monitor = ipc_output->mon;
|
||||||
|
+
|
||||||
|
+ if (!newtags || newtags == monitor->tagset[monitor->seltags])
|
||||||
|
+ return;
|
||||||
|
+ if (toggle_tagset)
|
||||||
|
+ monitor->seltags ^= 1;
|
||||||
|
+
|
||||||
|
+ monitor->tagset[monitor->seltags] = newtags;
|
||||||
|
+ focusclient(focustop(monitor), 1);
|
||||||
|
+ arrange(monitor);
|
||||||
|
+ printstatus();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+dwl_ipc_output_release(struct wl_client *client, struct wl_resource *resource)
|
||||||
|
+{
|
||||||
|
+ wl_resource_destroy(resource);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
focusclient(Client *c, int lift)
|
||||||
|
{
|
||||||
|
@@ -1846,41 +2056,9 @@ void
|
||||||
|
printstatus(void)
|
||||||
|
{
|
||||||
|
Monitor *m = NULL;
|
||||||
|
- Client *c;
|
||||||
|
- uint32_t occ, urg, sel;
|
||||||
|
- const char *appid, *title;
|
||||||
|
|
||||||
|
- wl_list_for_each(m, &mons, link) {
|
||||||
|
- occ = urg = 0;
|
||||||
|
- wl_list_for_each(c, &clients, link) {
|
||||||
|
- if (c->mon != m)
|
||||||
|
- continue;
|
||||||
|
- occ |= c->tags;
|
||||||
|
- if (c->isurgent)
|
||||||
|
- urg |= c->tags;
|
||||||
|
- }
|
||||||
|
- if ((c = focustop(m))) {
|
||||||
|
- title = client_get_title(c);
|
||||||
|
- appid = client_get_appid(c);
|
||||||
|
- printf("%s title %s\n", m->wlr_output->name, title ? title : broken);
|
||||||
|
- printf("%s appid %s\n", m->wlr_output->name, appid ? appid : broken);
|
||||||
|
- printf("%s fullscreen %u\n", m->wlr_output->name, c->isfullscreen);
|
||||||
|
- printf("%s floating %u\n", m->wlr_output->name, c->isfloating);
|
||||||
|
- sel = c->tags;
|
||||||
|
- } else {
|
||||||
|
- printf("%s title \n", m->wlr_output->name);
|
||||||
|
- printf("%s appid \n", m->wlr_output->name);
|
||||||
|
- printf("%s fullscreen \n", m->wlr_output->name);
|
||||||
|
- printf("%s floating \n", m->wlr_output->name);
|
||||||
|
- sel = 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- printf("%s selmon %u\n", m->wlr_output->name, m == selmon);
|
||||||
|
- printf("%s tags %u %u %u %u\n", m->wlr_output->name, occ, m->tagset[m->seltags],
|
||||||
|
- sel, urg);
|
||||||
|
- printf("%s layout %s\n", m->wlr_output->name, m->ltsymbol);
|
||||||
|
- }
|
||||||
|
- fflush(stdout);
|
||||||
|
+ wl_list_for_each(m, &mons, link)
|
||||||
|
+ dwl_ipc_output_printstatus(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
@@ -2295,6 +2473,7 @@ setup(void)
|
||||||
|
wl_signal_add(&output_mgr->events.test, &output_mgr_test);
|
||||||
|
|
||||||
|
wlr_scene_set_presentation(scene, wlr_presentation_create(dpy, backend));
|
||||||
|
+ wl_global_create(dpy, &zdwl_ipc_manager_v2_interface, 2, NULL, dwl_ipc_manager_bind);
|
||||||
|
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
/*
|
||||||
|
@@ -2389,6 +2568,13 @@ tile(Monitor *m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+togglebar(const Arg *arg) {
|
||||||
|
+ DwlIpcOutput *ipc_output;
|
||||||
|
+ wl_list_for_each(ipc_output, &selmon->dwl_ipc_outputs, link)
|
||||||
|
+ zdwl_ipc_output_v2_send_toggle_visibility(ipc_output->resource);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
togglefloating(const Arg *arg)
|
||||||
|
{
|
||||||
|
diff --git a/protocols/dwl-ipc-unstable-v2.xml b/protocols/dwl-ipc-unstable-v2.xml
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..0a6e7e5
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/protocols/dwl-ipc-unstable-v2.xml
|
||||||
|
@@ -0,0 +1,181 @@
|
||||||
|
+<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
+<!--
|
||||||
|
+This is largely ripped from somebar's ipc patchset; just with some personal modifications.
|
||||||
|
+I would probably just submit raphi's patchset but I don't think that would be polite.
|
||||||
|
+-->
|
||||||
|
+<protocol name="dwl_ipc_unstable_v2">
|
||||||
|
+ <description summary="inter-proccess-communication about dwl's state">
|
||||||
|
+ This protocol allows clients to update and get updates from dwl.
|
||||||
|
+
|
||||||
|
+ Warning! The protocol described in this file is experimental and
|
||||||
|
+ backward incompatible changes may be made. Backward compatible
|
||||||
|
+ changes may be added together with the corresponding interface
|
||||||
|
+ version bump.
|
||||||
|
+ Backward incompatible changes are done by bumping the version
|
||||||
|
+ number in the protocol and interface names and resetting the
|
||||||
|
+ interface version. Once the protocol is to be declared stable,
|
||||||
|
+ the 'z' prefix and the version number in the protocol and
|
||||||
|
+ interface names are removed and the interface version number is
|
||||||
|
+ reset.
|
||||||
|
+ </description>
|
||||||
|
+
|
||||||
|
+ <interface name="zdwl_ipc_manager_v2" version="2">
|
||||||
|
+ <description summary="manage dwl state">
|
||||||
|
+ This interface is exposed as a global in wl_registry.
|
||||||
|
+
|
||||||
|
+ Clients can use this interface to get a dwl_ipc_output.
|
||||||
|
+ After binding the client will recieve the dwl_ipc_manager.tags and dwl_ipc_manager.layout events.
|
||||||
|
+ The dwl_ipc_manager.tags and dwl_ipc_manager.layout events expose tags and layouts to the client.
|
||||||
|
+ </description>
|
||||||
|
+
|
||||||
|
+ <request name="release" type="destructor">
|
||||||
|
+ <description summary="release dwl_ipc_manager">
|
||||||
|
+ Indicates that the client will not the dwl_ipc_manager object anymore.
|
||||||
|
+ Objects created through this instance are not affected.
|
||||||
|
+ </description>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <request name="get_output">
|
||||||
|
+ <description summary="get a dwl_ipc_outout for a wl_output">
|
||||||
|
+ Get a dwl_ipc_outout for the specified wl_output.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="id" type="new_id" interface="zdwl_ipc_output_v2"/>
|
||||||
|
+ <arg name="output" type="object" interface="wl_output"/>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <event name="tags">
|
||||||
|
+ <description summary="Announces tag amount">
|
||||||
|
+ This event is sent after binding.
|
||||||
|
+ A roundtrip after binding guarantees the client recieved all tags.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="amount" type="uint"/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="layout">
|
||||||
|
+ <description summary="Announces a layout">
|
||||||
|
+ This event is sent after binding.
|
||||||
|
+ A roundtrip after binding guarantees the client recieved all layouts.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="name" type="string"/>
|
||||||
|
+ </event>
|
||||||
|
+ </interface>
|
||||||
|
+
|
||||||
|
+ <interface name="zdwl_ipc_output_v2" version="2">
|
||||||
|
+ <description summary="control dwl output">
|
||||||
|
+ Observe and control a dwl output.
|
||||||
|
+
|
||||||
|
+ Events are double-buffered:
|
||||||
|
+ Clients should cache events and redraw when a dwl_ipc_output.frame event is sent.
|
||||||
|
+
|
||||||
|
+ Request are not double-buffered:
|
||||||
|
+ The compositor will update immediately upon request.
|
||||||
|
+ </description>
|
||||||
|
+
|
||||||
|
+ <enum name="tag_state">
|
||||||
|
+ <entry name="none" value="0" summary="no state"/>
|
||||||
|
+ <entry name="active" value="1" summary="tag is active"/>
|
||||||
|
+ <entry name="urgent" value="2" summary="tag has at least one urgent client"/>
|
||||||
|
+ </enum>
|
||||||
|
+
|
||||||
|
+ <request name="release" type="destructor">
|
||||||
|
+ <description summary="release dwl_ipc_outout">
|
||||||
|
+ Indicates to that the client no longer needs this dwl_ipc_output.
|
||||||
|
+ </description>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <event name="toggle_visibility">
|
||||||
|
+ <description summary="Toggle client visibilty">
|
||||||
|
+ Indicates the client should hide or show themselves.
|
||||||
|
+ If the client is visible then hide, if hidden then show.
|
||||||
|
+ </description>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="active">
|
||||||
|
+ <description summary="Update the selected output.">
|
||||||
|
+ Indicates if the output is active. Zero is invalid, nonzero is valid.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="active" type="uint"/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="tag">
|
||||||
|
+ <description summary="Update the state of a tag.">
|
||||||
|
+ Indicates that a tag has been updated.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="tag" type="uint" summary="Index of the tag"/>
|
||||||
|
+ <arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/>
|
||||||
|
+ <arg name="clients" type="uint" summary="The number of clients in the tag."/>
|
||||||
|
+ <arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="layout">
|
||||||
|
+ <description summary="Update the layout.">
|
||||||
|
+ Indicates a new layout is selected.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="layout" type="uint" summary="Index of the layout."/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="title">
|
||||||
|
+ <description summary="Update the title.">
|
||||||
|
+ Indicates the title has changed.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="title" type="string" summary="The new title name."/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="appid" since="1">
|
||||||
|
+ <description summary="Update the appid.">
|
||||||
|
+ Indicates the appid has changed.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="appid" type="string" summary="The new appid."/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="layout_symbol" since="1">
|
||||||
|
+ <description summary="Update the current layout symbol">
|
||||||
|
+ Indicates the layout has changed. Since layout symbols are dynamic.
|
||||||
|
+ As opposed to the zdwl_ipc_manager.layout event, this should take precendence when displaying.
|
||||||
|
+ You can ignore the zdwl_ipc_output.layout event.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="layout" type="string" summary="The new layout"/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="frame">
|
||||||
|
+ <description summary="The update sequence is done.">
|
||||||
|
+ Indicates that a sequence of status updates have finished and the client should redraw.
|
||||||
|
+ </description>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <request name="set_tags">
|
||||||
|
+ <description summary="Set the active tags of this output"/>
|
||||||
|
+ <arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/>
|
||||||
|
+ <arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <request name="set_client_tags">
|
||||||
|
+ <description summary="Set the tags of the focused client.">
|
||||||
|
+ The tags are updated as follows:
|
||||||
|
+ new_tags = (current_tags AND and_tags) XOR xor_tags
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="and_tags" type="uint"/>
|
||||||
|
+ <arg name="xor_tags" type="uint"/>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <request name="set_layout">
|
||||||
|
+ <description summary="Set the layout of this output"/>
|
||||||
|
+ <arg name="index" type="uint" summary="index of a layout recieved by dwl_ipc_manager.layout"/>
|
||||||
|
+ </request>
|
||||||
|
+
|
||||||
|
+ <!-- Version 2 -->
|
||||||
|
+ <event name="fullscreen" since="2">
|
||||||
|
+ <description summary="Update fullscreen status">
|
||||||
|
+ Indicates if the selected client on this output is fullscreen.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="is_fullscreen" type="uint" summary="If the selected client is fullscreen. Nonzero is valid, zero invalid"/>
|
||||||
|
+ </event>
|
||||||
|
+
|
||||||
|
+ <event name="floating" since="2">
|
||||||
|
+ <description summary="Update the floating status">
|
||||||
|
+ Indicates if the selected client on this output is floating.
|
||||||
|
+ </description>
|
||||||
|
+ <arg name="is_floating" type="uint" summary="If the selected client is floating. Nonzero is valid, zero invalid"/>
|
||||||
|
+ </event>
|
||||||
|
+ </interface>
|
||||||
|
+</protocol>
|
578
user/.config/suckless/dwl/patches/keycodes.patch
Normal file
578
user/.config/suckless/dwl/patches/keycodes.patch
Normal file
|
@ -0,0 +1,578 @@
|
||||||
|
From 9c1bd1e2b4711bd2fbd3df38b84a7d49f58c354d Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?=
|
||||||
|
<leohdz172@proton.me>
|
||||||
|
Date: Fri, 4 Jun 2021 16:51:01 -0500
|
||||||
|
Subject: [PATCH 1/2] allow use keycodes instead keysyms
|
||||||
|
|
||||||
|
---
|
||||||
|
config.def.h | 85 +++++++++---------
|
||||||
|
dwl.c | 32 +++----
|
||||||
|
keys.h | 242 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 296 insertions(+), 63 deletions(-)
|
||||||
|
create mode 100644 keys.h
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 447ba0051..aa868d27a 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -93,11 +93,11 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
|
||||||
|
/* If you want to use the windows key for MODKEY, use WLR_MODIFIER_LOGO */
|
||||||
|
#define MODKEY WLR_MODIFIER_ALT
|
||||||
|
|
||||||
|
-#define TAGKEYS(KEY,SKEY,TAG) \
|
||||||
|
+#define TAGKEYS(KEY,TAG) \
|
||||||
|
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||||
|
{ MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \
|
||||||
|
- { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \
|
||||||
|
- { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} }
|
||||||
|
+ { MODKEY|WLR_MODIFIER_SHIFT, KEY, tag, {.ui = 1 << TAG} }, \
|
||||||
|
+ { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,KEY,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 } }
|
||||||
|
@@ -106,48 +106,49 @@ static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TA
|
||||||
|
static const char *termcmd[] = { "foot", NULL };
|
||||||
|
static const char *menucmd[] = { "bemenu-run", NULL };
|
||||||
|
|
||||||
|
+#include "keys.h"
|
||||||
|
static const Key keys[] = {
|
||||||
|
- /* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
|
||||||
|
- /* modifier key function argument */
|
||||||
|
- { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
|
||||||
|
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||||
|
- { MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
||||||
|
- { MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||||
|
- { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||||
|
- { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||||
|
- { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05} },
|
||||||
|
- { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05} },
|
||||||
|
- { MODKEY, XKB_KEY_Return, zoom, {0} },
|
||||||
|
- { MODKEY, XKB_KEY_Tab, view, {0} },
|
||||||
|
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} },
|
||||||
|
- { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} },
|
||||||
|
- { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} },
|
||||||
|
- { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} },
|
||||||
|
- { MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||||
|
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||||
|
- { MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||||
|
- { MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||||
|
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||||
|
- { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||||
|
- { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||||
|
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||||
|
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||||
|
- TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
||||||
|
- TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||||
|
- TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||||
|
- TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3),
|
||||||
|
- TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4),
|
||||||
|
- TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5),
|
||||||
|
- TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6),
|
||||||
|
- TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7),
|
||||||
|
- TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8),
|
||||||
|
- { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} },
|
||||||
|
+ /* modifier key function argument */
|
||||||
|
+ { MODKEY, Key_p, spawn, {.v = menucmd} },
|
||||||
|
+ { MODKEY|WLR_MODIFIER_SHIFT, Key_Return, spawn, {.v = termcmd} },
|
||||||
|
+ { MODKEY, Key_j, focusstack, {.i = +1} },
|
||||||
|
+ { MODKEY, Key_k, focusstack, {.i = -1} },
|
||||||
|
+ { MODKEY, Key_i, incnmaster, {.i = +1} },
|
||||||
|
+ { MODKEY, Key_d, incnmaster, {.i = -1} },
|
||||||
|
+ { MODKEY, Key_h, setmfact, {.f = -0.05} },
|
||||||
|
+ { MODKEY, Key_l, setmfact, {.f = +0.05} },
|
||||||
|
+ { MODKEY, Key_Return, zoom, {0} },
|
||||||
|
+ { MODKEY, Key_Tab, view, {0} },
|
||||||
|
+ { MODKEY|WLR_MODIFIER_SHIFT, Key_c, killclient, {0} },
|
||||||
|
+ { MODKEY, Key_t, setlayout, {.v = &layouts[0]} },
|
||||||
|
+ { MODKEY, Key_f, setlayout, {.v = &layouts[1]} },
|
||||||
|
+ { MODKEY, Key_m, setlayout, {.v = &layouts[2]} },
|
||||||
|
+ { MODKEY, Key_space, setlayout, {0} },
|
||||||
|
+ { MODKEY|WLR_MODIFIER_SHIFT, Key_space, togglefloating, {0} },
|
||||||
|
+ { MODKEY, Key_e, togglefullscreen, {0} },
|
||||||
|
+ { MODKEY, Key_0, view, {.ui = ~0} },
|
||||||
|
+ { MODKEY|WLR_MODIFIER_SHIFT, Key_0, tag, {.ui = ~0} },
|
||||||
|
+ { MODKEY, Key_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||||
|
+ { MODKEY, Key_period, focusmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||||
|
+ { MODKEY|WLR_MODIFIER_SHIFT, Key_comma, tagmon, {.i = WLR_DIRECTION_LEFT} },
|
||||||
|
+ { MODKEY|WLR_MODIFIER_SHIFT, Key_period, tagmon, {.i = WLR_DIRECTION_RIGHT} },
|
||||||
|
+ TAGKEYS( Key_1, 0),
|
||||||
|
+ TAGKEYS( Key_2, 1),
|
||||||
|
+ TAGKEYS( Key_3, 2),
|
||||||
|
+ TAGKEYS( Key_4, 3),
|
||||||
|
+ TAGKEYS( Key_5, 4),
|
||||||
|
+ TAGKEYS( Key_6, 5),
|
||||||
|
+ TAGKEYS( Key_7, 6),
|
||||||
|
+ TAGKEYS( Key_8, 7),
|
||||||
|
+ TAGKEYS( Key_9, 8),
|
||||||
|
+ { MODKEY|WLR_MODIFIER_SHIFT, Key_q, quit, {0} },
|
||||||
|
|
||||||
|
/* Ctrl-Alt-Backspace and Ctrl-Alt-Fx used to be handled by X server */
|
||||||
|
- { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_Terminate_Server, quit, {0} },
|
||||||
|
-#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} }
|
||||||
|
- CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6),
|
||||||
|
- CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12),
|
||||||
|
+ { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,Key_BackSpace, quit, {0} },
|
||||||
|
+#define CHVT(KEY,n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT, KEY, chvt, {.ui = (n)} }
|
||||||
|
+ CHVT(Key_F1, 1), CHVT(Key_F2, 2), CHVT(Key_F3, 3), CHVT(Key_F4, 4),
|
||||||
|
+ CHVT(Key_F5, 5), CHVT(Key_F6, 6), CHVT(Key_F7, 7), CHVT(Key_F8, 8),
|
||||||
|
+ CHVT(Key_F9, 9), CHVT(Key_F10, 10), CHVT(Key_F11, 11), CHVT(Key_F12, 12),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Button buttons[] = {
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 4ff5c37f7..6f0d720f1 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -130,7 +130,7 @@ typedef struct {
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t mod;
|
||||||
|
- xkb_keysym_t keysym;
|
||||||
|
+ xkb_keycode_t keycode;
|
||||||
|
void (*func)(const Arg *);
|
||||||
|
const Arg arg;
|
||||||
|
} Key;
|
||||||
|
@@ -139,9 +139,8 @@ typedef struct {
|
||||||
|
struct wl_list link;
|
||||||
|
struct wlr_keyboard *wlr_keyboard;
|
||||||
|
|
||||||
|
- int nsyms;
|
||||||
|
- const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */
|
||||||
|
- uint32_t mods; /* invalid if nsyms == 0 */
|
||||||
|
+ xkb_keycode_t keycode;
|
||||||
|
+ uint32_t mods; /* invalid if keycode == 0 */
|
||||||
|
struct wl_event_source *key_repeat_source;
|
||||||
|
|
||||||
|
struct wl_listener modifiers;
|
||||||
|
@@ -263,7 +262,7 @@ static void fullscreennotify(struct wl_listener *listener, void *data);
|
||||||
|
static void handlesig(int signo);
|
||||||
|
static void incnmaster(const Arg *arg);
|
||||||
|
static void inputdevice(struct wl_listener *listener, void *data);
|
||||||
|
-static int keybinding(uint32_t mods, xkb_keysym_t sym);
|
||||||
|
+static int keybinding(uint32_t mods, xkb_keycode_t keycode);
|
||||||
|
static void keypress(struct wl_listener *listener, void *data);
|
||||||
|
static void keypressmod(struct wl_listener *listener, void *data);
|
||||||
|
static int keyrepeat(void *data);
|
||||||
|
@@ -1390,7 +1389,7 @@ inputdevice(struct wl_listener *listener, void *data)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-keybinding(uint32_t mods, xkb_keysym_t sym)
|
||||||
|
+keybinding(uint32_t mods, xkb_keycode_t keycode)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Here we handle compositor keybindings. This is when the compositor is
|
||||||
|
@@ -1401,7 +1400,7 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
|
||||||
|
const Key *k;
|
||||||
|
for (k = keys; k < END(keys); k++) {
|
||||||
|
if (CLEANMASK(mods) == CLEANMASK(k->mod) &&
|
||||||
|
- sym == k->keysym && k->func) {
|
||||||
|
+ keycode == k->keycode && k->func) {
|
||||||
|
k->func(&k->arg);
|
||||||
|
handled = 1;
|
||||||
|
}
|
||||||
|
@@ -1412,17 +1411,12 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
|
||||||
|
void
|
||||||
|
keypress(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
- int i;
|
||||||
|
/* This event is raised when a key is pressed or released. */
|
||||||
|
Keyboard *kb = wl_container_of(listener, kb, key);
|
||||||
|
struct wlr_keyboard_key_event *event = data;
|
||||||
|
|
||||||
|
/* Translate libinput keycode -> xkbcommon */
|
||||||
|
uint32_t keycode = event->keycode + 8;
|
||||||
|
- /* Get a list of keysyms based on the keymap for this keyboard */
|
||||||
|
- const xkb_keysym_t *syms;
|
||||||
|
- int nsyms = xkb_state_key_get_syms(
|
||||||
|
- kb->wlr_keyboard->xkb_state, keycode, &syms);
|
||||||
|
|
||||||
|
int handled = 0;
|
||||||
|
uint32_t mods = wlr_keyboard_get_modifiers(kb->wlr_keyboard);
|
||||||
|
@@ -1433,17 +1427,15 @@ keypress(struct wl_listener *listener, void *data)
|
||||||
|
* attempt to process a compositor keybinding. */
|
||||||
|
if (!locked && !input_inhibit_mgr->active_inhibitor
|
||||||
|
&& event->state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||||
|
- for (i = 0; i < nsyms; i++)
|
||||||
|
- handled = keybinding(mods, syms[i]) || handled;
|
||||||
|
+ handled = keybinding(mods, keycode);
|
||||||
|
|
||||||
|
if (handled && kb->wlr_keyboard->repeat_info.delay > 0) {
|
||||||
|
kb->mods = mods;
|
||||||
|
- kb->keysyms = syms;
|
||||||
|
- kb->nsyms = nsyms;
|
||||||
|
+ kb->keycode = keycode;
|
||||||
|
wl_event_source_timer_update(kb->key_repeat_source,
|
||||||
|
kb->wlr_keyboard->repeat_info.delay);
|
||||||
|
} else {
|
||||||
|
- kb->nsyms = 0;
|
||||||
|
+ kb->keycode = 0;
|
||||||
|
wl_event_source_timer_update(kb->key_repeat_source, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1478,15 +1470,13 @@ int
|
||||||
|
keyrepeat(void *data)
|
||||||
|
{
|
||||||
|
Keyboard *kb = data;
|
||||||
|
- int i;
|
||||||
|
- if (!kb->nsyms || kb->wlr_keyboard->repeat_info.rate <= 0)
|
||||||
|
+ if (!kb->keycode || kb->wlr_keyboard->repeat_info.rate <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
wl_event_source_timer_update(kb->key_repeat_source,
|
||||||
|
1000 / kb->wlr_keyboard->repeat_info.rate);
|
||||||
|
|
||||||
|
- for (i = 0; i < kb->nsyms; i++)
|
||||||
|
- keybinding(kb->mods, kb->keysyms[i]);
|
||||||
|
+ keybinding(kb->mods, kb->keycode);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
diff --git a/keys.h b/keys.h
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..e732f8063
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/keys.h
|
||||||
|
@@ -0,0 +1,242 @@
|
||||||
|
+/* You can use the macros within this file
|
||||||
|
+ * instead of search the keycodes yourself
|
||||||
|
+ * with wev or something like that
|
||||||
|
+ * Also probably you search this:
|
||||||
|
+ * Key_XF86AudioMute
|
||||||
|
+ * Key_XF86AudioLowerVolume
|
||||||
|
+ * Key_XF86AudioRaiseVolume
|
||||||
|
+ * Key_XF86MonBrightnessDown
|
||||||
|
+ * Key_XF86MonBrightnessUp
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+#define Key_Escape 9
|
||||||
|
+#define Key_1 10
|
||||||
|
+#define Key_2 11
|
||||||
|
+#define Key_3 12
|
||||||
|
+#define Key_4 13
|
||||||
|
+#define Key_5 14
|
||||||
|
+#define Key_6 15
|
||||||
|
+#define Key_7 16
|
||||||
|
+#define Key_8 17
|
||||||
|
+#define Key_9 18
|
||||||
|
+#define Key_0 19
|
||||||
|
+#define Key_minus 20
|
||||||
|
+#define Key_equal 21
|
||||||
|
+#define Key_BackSpace 22
|
||||||
|
+#define Key_Tab 23
|
||||||
|
+#define Key_q 24
|
||||||
|
+#define Key_w 25
|
||||||
|
+#define Key_e 26
|
||||||
|
+#define Key_r 27
|
||||||
|
+#define Key_t 28
|
||||||
|
+#define Key_y 29
|
||||||
|
+#define Key_u 30
|
||||||
|
+#define Key_i 31
|
||||||
|
+#define Key_o 32
|
||||||
|
+#define Key_p 33
|
||||||
|
+#define Key_bracketleft 34
|
||||||
|
+#define Key_bracketright 35
|
||||||
|
+#define Key_Return 36
|
||||||
|
+#define Key_Control_L 37
|
||||||
|
+#define Key_a 38
|
||||||
|
+#define Key_s 39
|
||||||
|
+#define Key_d 40
|
||||||
|
+#define Key_f 41
|
||||||
|
+#define Key_g 42
|
||||||
|
+#define Key_h 43
|
||||||
|
+#define Key_j 44
|
||||||
|
+#define Key_k 45
|
||||||
|
+#define Key_l 46
|
||||||
|
+#define Key_semicolon 47
|
||||||
|
+#define Key_apostrophe 48
|
||||||
|
+#define Key_grave 49
|
||||||
|
+#define Key_Shift_L 50
|
||||||
|
+#define Key_backslash 51
|
||||||
|
+#define Key_z 52
|
||||||
|
+#define Key_x 53
|
||||||
|
+#define Key_c 54
|
||||||
|
+#define Key_v 55
|
||||||
|
+#define Key_b 56
|
||||||
|
+#define Key_n 57
|
||||||
|
+#define Key_m 58
|
||||||
|
+#define Key_comma 59
|
||||||
|
+#define Key_period 60
|
||||||
|
+#define Key_slash 61
|
||||||
|
+#define Key_Shift_R 62
|
||||||
|
+#define Key_KP_Multiply 63
|
||||||
|
+#define Key_Alt_L 64
|
||||||
|
+#define Key_space 65
|
||||||
|
+#define Key_Caps_Lock 66
|
||||||
|
+#define Key_F1 67
|
||||||
|
+#define Key_F2 68
|
||||||
|
+#define Key_F3 69
|
||||||
|
+#define Key_F4 70
|
||||||
|
+#define Key_F5 71
|
||||||
|
+#define Key_F6 72
|
||||||
|
+#define Key_F7 73
|
||||||
|
+#define Key_F8 74
|
||||||
|
+#define Key_F9 75
|
||||||
|
+#define Key_F10 76
|
||||||
|
+#define Key_Num_Lock 77
|
||||||
|
+#define Key_Scroll_Lock 78
|
||||||
|
+#define Key_KP_Home 79
|
||||||
|
+#define Key_KP_7 Key_KP_Home
|
||||||
|
+#define Key_KP_Up 80
|
||||||
|
+#define Key_KP_8 Key_KP_Up
|
||||||
|
+#define Key_KP_Prior 81
|
||||||
|
+#define Key_KP_9 Key_KP_Prior
|
||||||
|
+#define Key_KP_Subtract 82
|
||||||
|
+#define Key_KP_Left 83
|
||||||
|
+#define Key_KP_4 Key_KP_Left
|
||||||
|
+#define Key_KP_Begin 84
|
||||||
|
+#define Key_KP_5 Key_KP_Begin
|
||||||
|
+#define Key_KP_Right 85
|
||||||
|
+#define Key_KP_6 Key_KP_Right
|
||||||
|
+#define Key_KP_Add 86
|
||||||
|
+#define Key_KP_End 87
|
||||||
|
+#define Key_KP_1 Key_KP_End
|
||||||
|
+#define Key_KP_Down 88
|
||||||
|
+#define Key_KP_2 Key_KP_Down
|
||||||
|
+#define Key_KP_Next 89
|
||||||
|
+#define Key_KP_3 Key_KP_Next
|
||||||
|
+#define Key_KP_Insert 90
|
||||||
|
+#define Key_KP_0 Key_KP_Insert
|
||||||
|
+#define Key_KP_Delete 91
|
||||||
|
+#define Key_KP_Period Key_KP_Insert
|
||||||
|
+#define Key_ISO_Level3_Shift 92
|
||||||
|
+#define Key_less 94
|
||||||
|
+#define Key_F11 95
|
||||||
|
+#define Key_F12 96
|
||||||
|
+#define Key_Katakana 98
|
||||||
|
+#define Key_Hiragana 99
|
||||||
|
+#define Key_Henkan_Mode 100
|
||||||
|
+#define Key_Hiragana_Katakana 101
|
||||||
|
+#define Key_Muhenkan 102
|
||||||
|
+#define Key_KP_Enter 104
|
||||||
|
+#define Key_Control_R 105
|
||||||
|
+#define Key_KP_Divide 106
|
||||||
|
+#define Key_Print 107
|
||||||
|
+#define Key_Alt_R 108
|
||||||
|
+#define Key_Linefeed 109
|
||||||
|
+#define Key_Home 110
|
||||||
|
+#define Key_Up 111
|
||||||
|
+#define Key_Prior 112
|
||||||
|
+#define Key_Left 113
|
||||||
|
+#define Key_Right 114
|
||||||
|
+#define Key_End 115
|
||||||
|
+#define Key_Down 116
|
||||||
|
+#define Key_Next 117
|
||||||
|
+#define Key_Insert 118
|
||||||
|
+#define Key_Delete 119
|
||||||
|
+#define Key_XF86AudioMute 121
|
||||||
|
+#define Key_XF86AudioLowerVolume 122
|
||||||
|
+#define Key_XF86AudioRaiseVolume 123
|
||||||
|
+#define Key_XF86PowerOff 124
|
||||||
|
+#define Key_KP_Equal 125
|
||||||
|
+#define Key_plusminus 126
|
||||||
|
+#define Key_Pause 127
|
||||||
|
+#define Key_XF86LaunchA 128
|
||||||
|
+#define Key_KP_Decimal 129
|
||||||
|
+#define Key_Hangul 130
|
||||||
|
+#define Key_Hangul_Hanja 131
|
||||||
|
+#define Key_Super_L 133
|
||||||
|
+#define Key_Super_R 134
|
||||||
|
+#define Key_Menu 135
|
||||||
|
+#define Key_Cancel 136
|
||||||
|
+#define Key_Redo 137
|
||||||
|
+#define Key_SunProps 138
|
||||||
|
+#define Key_Undo 139
|
||||||
|
+#define Key_SunFront 140
|
||||||
|
+#define Key_XF86Copy 141
|
||||||
|
+#define Key_XF86Open 142
|
||||||
|
+#define Key_XF86Paste 143
|
||||||
|
+#define Key_Find 144
|
||||||
|
+#define Key_XF86Cut 145
|
||||||
|
+#define Key_Help 146
|
||||||
|
+#define Key_XF86MenuKB 147
|
||||||
|
+#define Key_XF86Calculator 148
|
||||||
|
+#define Key_XF86Sleep 150
|
||||||
|
+#define Key_XF86WakeUp 151
|
||||||
|
+#define Key_XF86Explorer 152
|
||||||
|
+#define Key_XF86Send 153
|
||||||
|
+#define Key_XF86Xfer 155
|
||||||
|
+#define Key_XF86Launch1 156
|
||||||
|
+#define Key_XF86Launch2 157
|
||||||
|
+#define Key_XF86WWW 158
|
||||||
|
+#define Key_XF86DOS 159
|
||||||
|
+#define Key_XF86ScreenSaver 160
|
||||||
|
+#define Key_XF86RotateWindows 161
|
||||||
|
+#define Key_XF86TaskPane 162
|
||||||
|
+#define Key_XF86Mail 163
|
||||||
|
+#define Key_XF86Favorites 164
|
||||||
|
+#define Key_XF86MyComputer 165
|
||||||
|
+#define Key_XF86Back 166
|
||||||
|
+#define Key_XF86Forward 167
|
||||||
|
+#define Key_XF86Eject1 169
|
||||||
|
+#define Key_XF86Eject2 170
|
||||||
|
+#define Key_XF86AudioNext 171
|
||||||
|
+#define Key_XF86AudioPlay 172
|
||||||
|
+#define Key_XF86AudioPrev 173
|
||||||
|
+#define Key_XF86AudioStop 174
|
||||||
|
+#define Key_XF86AudioRecord 175
|
||||||
|
+#define Key_XF86AudioRewind 176
|
||||||
|
+#define Key_XF86Phone 177
|
||||||
|
+#define Key_XF86Tools 179
|
||||||
|
+#define Key_XF86HomePage 180
|
||||||
|
+#define Key_XF86Reload 181
|
||||||
|
+#define Key_XF86Close 182
|
||||||
|
+#define Key_XF86ScrollUp 185
|
||||||
|
+#define Key_XF86ScrollDown 186
|
||||||
|
+#define Key_parenleft 187
|
||||||
|
+#define Key_parenright 188
|
||||||
|
+#define Key_XF86New 189
|
||||||
|
+#define Key_Redo2 190
|
||||||
|
+#define Key_XF86Tools2 191
|
||||||
|
+#define Key_XF86Launch5 192
|
||||||
|
+#define Key_XF86Launch6 193
|
||||||
|
+#define Key_XF86Launch7 194
|
||||||
|
+#define Key_XF86Launch8 195
|
||||||
|
+#define Key_XF86Launch9 196
|
||||||
|
+#define Key_XF86AudioMicMute 198
|
||||||
|
+#define Key_XF86TouchpadToggle 199
|
||||||
|
+#define Key_XF86TouchpadOn 200
|
||||||
|
+#define Key_XF86TouchpadOff 201
|
||||||
|
+#define Key_Mode_switch 203
|
||||||
|
+#define Key_XF86AudioPlay2 208
|
||||||
|
+#define Key_XF86AudioPause 209
|
||||||
|
+#define Key_XF86Launch3 210
|
||||||
|
+#define Key_XF86Launch4 211
|
||||||
|
+#define Key_XF86LaunchB 212
|
||||||
|
+#define Key_XF86Suspend 213
|
||||||
|
+#define Key_XF86Close2 214
|
||||||
|
+#define Key_XF86AudioPlay3 215
|
||||||
|
+#define Key_XF86AudioForward 216
|
||||||
|
+#define Key_Print2 218
|
||||||
|
+#define Key_XF86WebCam 220
|
||||||
|
+#define Key_XF86AudioPreset 221
|
||||||
|
+#define Key_XF86Mail2 223
|
||||||
|
+#define Key_XF86Messenger 224
|
||||||
|
+#define Key_XF86Search 225
|
||||||
|
+#define Key_XF86Go 226
|
||||||
|
+#define Key_XF86Finance 227
|
||||||
|
+#define Key_XF86Game 228
|
||||||
|
+#define Key_XF86Shop 229
|
||||||
|
+#define Key_Cancel2 231
|
||||||
|
+#define Key_XF86MonBrightnessDown 232
|
||||||
|
+#define Key_XF86MonBrightnessUp 233
|
||||||
|
+#define Key_XF86AudioMedia 234
|
||||||
|
+#define Key_XF86Display 235
|
||||||
|
+#define Key_XF86KbdLightOnOff 236
|
||||||
|
+#define Key_XF86KbdBrightnessDown 237
|
||||||
|
+#define Key_XF86KbdBrightnessUp 238
|
||||||
|
+#define Key_XF86Send2 239
|
||||||
|
+#define Key_XF86Reply 240
|
||||||
|
+#define Key_XF86MailForward 241
|
||||||
|
+#define Key_XF86Save 242
|
||||||
|
+#define Key_XF86Documents 243
|
||||||
|
+#define Key_XF86Battery 244
|
||||||
|
+#define Key_XF86Bluetooth 245
|
||||||
|
+#define Key_XF86WLAN 246
|
||||||
|
+#define Key_XF86MonBrightnessCycle 251
|
||||||
|
+#define Key_XF86WWAN 254
|
||||||
|
+#define Key_XF86RFKill 255
|
||||||
|
|
||||||
|
From 4cf345c85399cc19323a49b78340560ced7bf212 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Leonardo=20Hern=C3=A1ndez=20Hern=C3=A1ndez?=
|
||||||
|
<leohdz172@proton.me>
|
||||||
|
Date: Sun, 19 Mar 2023 15:50:07 -0600
|
||||||
|
Subject: [PATCH 2/2] add program to generate keys.h
|
||||||
|
|
||||||
|
---
|
||||||
|
generate-keys.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 82 insertions(+)
|
||||||
|
create mode 100644 generate-keys.c
|
||||||
|
|
||||||
|
diff --git a/generate-keys.c b/generate-keys.c
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..83458fb71
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/generate-keys.c
|
||||||
|
@@ -0,0 +1,82 @@
|
||||||
|
+/******************************************************************
|
||||||
|
+ * Copyright 2023 Leonardo Hernández Hernández
|
||||||
|
+ *
|
||||||
|
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
+ * of this software and associated documentation files (the “Software”), to
|
||||||
|
+ * deal in the Software without restriction, including without limitation the
|
||||||
|
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
+ * sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
+ * furnished to do so, subject to the following conditions:
|
||||||
|
+ *
|
||||||
|
+ * The above copyright notice and this permission notice shall be included in
|
||||||
|
+ * all copies or substantial portions of the Software.
|
||||||
|
+ *
|
||||||
|
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
+ * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
+ *
|
||||||
|
+ ******************************************************************/
|
||||||
|
+
|
||||||
|
+/* cc -lxkbcommon -o generate-keys generate-keys.c */
|
||||||
|
+
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+
|
||||||
|
+#include <xkbcommon/xkbcommon.h>
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+main(void)
|
||||||
|
+{
|
||||||
|
+ struct xkb_context *context;
|
||||||
|
+ /* Allow generate keys with a different layout and variant.
|
||||||
|
+ * You can also use XKB_DEFAULT_* environmental variables and let this as is */
|
||||||
|
+ struct xkb_rule_names rules = {
|
||||||
|
+ 0
|
||||||
|
+ };
|
||||||
|
+ struct xkb_keymap *keymap;
|
||||||
|
+ struct xkb_state *state;
|
||||||
|
+ xkb_keycode_t keycode, min_keycode, max_keycode;
|
||||||
|
+ int i, nsyms;
|
||||||
|
+ const xkb_keysym_t *syms;
|
||||||
|
+ char keyname[64];
|
||||||
|
+ FILE *f = fopen("keys.h", "w");
|
||||||
|
+ if (!f) {
|
||||||
|
+ perror("Couldn't open keys.h");
|
||||||
|
+ return EXIT_FAILURE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!(context = xkb_context_new(XKB_CONTEXT_NO_FLAGS))) {
|
||||||
|
+ fputs("Couldn't create xkbcommon context\n", stderr);
|
||||||
|
+ return EXIT_FAILURE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!(keymap = xkb_keymap_new_from_names(context, &rules,
|
||||||
|
+ XKB_KEYMAP_COMPILE_NO_FLAGS))) {
|
||||||
|
+ fputs("Couldn't create xkbcommon keymap\n", stderr);
|
||||||
|
+ return EXIT_FAILURE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!(state = xkb_state_new(keymap))) {
|
||||||
|
+ fputs("Couldn't create xkbcommon state\n", stderr);
|
||||||
|
+ return EXIT_FAILURE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ min_keycode = xkb_keymap_min_keycode(keymap);
|
||||||
|
+ max_keycode = xkb_keymap_max_keycode(keymap);
|
||||||
|
+
|
||||||
|
+ for (keycode = min_keycode; keycode <= max_keycode; keycode++) {
|
||||||
|
+ nsyms = xkb_state_key_get_syms(state, keycode, &syms);
|
||||||
|
+ for (i = 0; i < nsyms; i++) {
|
||||||
|
+ xkb_keysym_get_name(syms[i], keyname, sizeof(keyname) / sizeof(keyname[0]));
|
||||||
|
+ fprintf(f, "#define Key_%-24s %d\n", keyname, keycode);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ xkb_state_unref(state);
|
||||||
|
+ xkb_keymap_unref(keymap);
|
||||||
|
+ xkb_context_unref(context);
|
||||||
|
+}
|
159
user/.config/suckless/dwl/patches/mouse-follows-focus.patch
Normal file
159
user/.config/suckless/dwl/patches/mouse-follows-focus.patch
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
From 71e9926404962d367843d72e9a1aa70f1eaa1fe0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: 0scar <qgt268@alumni.ku.dk>
|
||||||
|
Date: Fri, 17 Mar 2023 13:26:11 +0100
|
||||||
|
Subject: [PATCH 1/3] Patch: Mouse follows focus
|
||||||
|
|
||||||
|
---
|
||||||
|
config.def.h | 1 +
|
||||||
|
dwl.c | 12 ++++++++++++
|
||||||
|
2 files changed, 13 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index c6a495048..1b66fac68 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -1,5 +1,6 @@
|
||||||
|
/* appearance */
|
||||||
|
static const int sloppyfocus = 1; /* focus follows mouse */
|
||||||
|
+static const int mousefollowsfocus = 1; /* mouse follows focus */
|
||||||
|
static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */
|
||||||
|
static const unsigned int borderpx = 1; /* border pixel of windows */
|
||||||
|
static const float bordercolor[] = {0.5, 0.5, 0.5, 1.0};
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 918852e14..ede4f3f0f 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -314,6 +314,7 @@ static void updatetitle(struct wl_listener *listener, void *data);
|
||||||
|
static void urgent(struct wl_listener *listener, void *data);
|
||||||
|
static void view(const Arg *arg);
|
||||||
|
static void virtualkeyboard(struct wl_listener *listener, void *data);
|
||||||
|
+static void warpcursortoclient(Client *c);
|
||||||
|
static Monitor *xytomon(double x, double y);
|
||||||
|
static struct wlr_scene_node *xytonode(double x, double y, struct wlr_surface **psurface,
|
||||||
|
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||||
|
@@ -1274,6 +1275,8 @@ focusclient(Client *c, int lift)
|
||||||
|
|
||||||
|
/* Activate the new client */
|
||||||
|
client_activate_surface(client_surface(c), 1);
|
||||||
|
+
|
||||||
|
+ if (mousefollowsfocus) warpcursortoclient(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
@@ -2623,6 +2626,15 @@ virtualkeyboard(struct wl_listener *listener, void *data)
|
||||||
|
createkeyboard(&keyboard->keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+warpcursortoclient(Client *c) {
|
||||||
|
+ struct wlr_box mg = c->mon->m;
|
||||||
|
+ struct wlr_box cg = c->geom;
|
||||||
|
+ wlr_cursor_warp_absolute(cursor, NULL,
|
||||||
|
+ ((double)cg.x + (double)cg.width / 2.0) / (double)mg.width,
|
||||||
|
+ ((double)cg.y + (double)cg.height / 2.0) / (double)mg.height);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
Monitor *
|
||||||
|
xytomon(double x, double y)
|
||||||
|
{
|
||||||
|
|
||||||
|
From fa0a35c0c7553b64b268670242fd89a64db17642 Mon Sep 17 00:00:00 2001
|
||||||
|
From: 0scar <qgt268@alumni.ku.dk>
|
||||||
|
Date: Sat, 18 Mar 2023 19:13:29 +0100
|
||||||
|
Subject: [PATCH 2/3] Check if client is visible
|
||||||
|
|
||||||
|
Also add motion notify.
|
||||||
|
---
|
||||||
|
dwl.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index ede4f3f0f..d4201f8b1 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -2630,9 +2630,11 @@ void
|
||||||
|
warpcursortoclient(Client *c) {
|
||||||
|
struct wlr_box mg = c->mon->m;
|
||||||
|
struct wlr_box cg = c->geom;
|
||||||
|
+ if (!VISIBLEON(c, selmon)) return;
|
||||||
|
wlr_cursor_warp_absolute(cursor, NULL,
|
||||||
|
((double)cg.x + (double)cg.width / 2.0) / (double)mg.width,
|
||||||
|
((double)cg.y + (double)cg.height / 2.0) / (double)mg.height);
|
||||||
|
+ motionnotify(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Monitor *
|
||||||
|
|
||||||
|
From 4c7510215b19c4ae7a727548ff174ad3bf3655ec Mon Sep 17 00:00:00 2001
|
||||||
|
From: 0scar <qgt268@alumni.ku.dk>
|
||||||
|
Date: Tue, 6 Jun 2023 15:38:31 +0200
|
||||||
|
Subject: [PATCH 3/3] Fix mouse jumping
|
||||||
|
|
||||||
|
---
|
||||||
|
dwl.c | 15 ++++++++++-----
|
||||||
|
1 file changed, 10 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index d4201f8b1..452ca6c32 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -486,6 +486,8 @@ arrange(Monitor *m)
|
||||||
|
if (m->lt[m->sellt]->arrange)
|
||||||
|
m->lt[m->sellt]->arrange(m);
|
||||||
|
motionnotify(0);
|
||||||
|
+
|
||||||
|
+ if (c && mousefollowsfocus) warpcursortoclient(c);
|
||||||
|
checkidleinhibitor(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1048,7 +1050,7 @@ createpointer(struct wlr_pointer *pointer)
|
||||||
|
|
||||||
|
if (libinput_device_config_scroll_get_methods(libinput_device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL)
|
||||||
|
libinput_device_config_scroll_set_method (libinput_device, scroll_method);
|
||||||
|
-
|
||||||
|
+
|
||||||
|
if (libinput_device_config_click_get_methods(libinput_device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE)
|
||||||
|
libinput_device_config_click_set_method (libinput_device, click_method);
|
||||||
|
|
||||||
|
@@ -1275,19 +1277,22 @@ focusclient(Client *c, int lift)
|
||||||
|
|
||||||
|
/* Activate the new client */
|
||||||
|
client_activate_surface(client_surface(c), 1);
|
||||||
|
-
|
||||||
|
- if (mousefollowsfocus) warpcursortoclient(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
focusmon(const Arg *arg)
|
||||||
|
{
|
||||||
|
int i = 0, nmons = wl_list_length(&mons);
|
||||||
|
+ Client *c = NULL;
|
||||||
|
if (nmons)
|
||||||
|
do /* don't switch to disabled mons */
|
||||||
|
selmon = dirtomon(arg->i);
|
||||||
|
while (!selmon->wlr_output->enabled && i++ < nmons);
|
||||||
|
- focusclient(focustop(selmon), 1);
|
||||||
|
+
|
||||||
|
+ c = focustop(selmon);
|
||||||
|
+ focusclient(c, 1);
|
||||||
|
+
|
||||||
|
+ if (mousefollowsfocus) warpcursortoclient(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
@@ -1314,6 +1319,7 @@ focusstack(const Arg *arg)
|
||||||
|
}
|
||||||
|
/* If only one client is visible on selmon, then c == sel */
|
||||||
|
focusclient(c, 1);
|
||||||
|
+ if (mousefollowsfocus) warpcursortoclient(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We probably should change the name of this, it sounds like
|
||||||
|
@@ -2634,7 +2640,6 @@ warpcursortoclient(Client *c) {
|
||||||
|
wlr_cursor_warp_absolute(cursor, NULL,
|
||||||
|
((double)cg.x + (double)cg.width / 2.0) / (double)mg.width,
|
||||||
|
((double)cg.y + (double)cg.height / 2.0) / (double)mg.height);
|
||||||
|
- motionnotify(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Monitor *
|
71
user/.config/suckless/dwl/patches/movecenter.patch
Normal file
71
user/.config/suckless/dwl/patches/movecenter.patch
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
From 09492d38f2726d4f4e77e50a8e9b507d2240e38f Mon Sep 17 00:00:00 2001
|
||||||
|
From: wochap <gean.marroquin@gmail.com>
|
||||||
|
Date: Mon, 11 Sep 2023 20:40:01 -0500
|
||||||
|
Subject: [PATCH] implement keybinding to center focused windows
|
||||||
|
|
||||||
|
---
|
||||||
|
config.def.h | 2 ++
|
||||||
|
dwl.c | 23 +++++++++++++++++++++++
|
||||||
|
2 files changed, 25 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 1677f6f12..23cb65e0f 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -6,6 +6,7 @@ static const float bordercolor[] = {0.5, 0.5, 0.5, 1.0};
|
||||||
|
static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0};
|
||||||
|
/* To conform the xdg-protocol, set the alpha to zero to restore the old behavior */
|
||||||
|
static const float fullscreen_bg[] = {0.1, 0.1, 0.1, 1.0};
|
||||||
|
+static const int center_relative_to_monitor = 0; /* 0 means center floating relative to the window area */
|
||||||
|
|
||||||
|
/* tagging - tagcount must be no greater than 31 */
|
||||||
|
#define TAGCOUNT (9)
|
||||||
|
@@ -127,6 +128,7 @@ static const Key keys[] = {
|
||||||
|
{ MODKEY, XKB_KEY_space, setlayout, {0} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} },
|
||||||
|
{ MODKEY, XKB_KEY_e, togglefullscreen, {0} },
|
||||||
|
+ { MODKEY, XKB_KEY_x, movecenter, {0} },
|
||||||
|
{ MODKEY, XKB_KEY_0, view, {.ui = ~0} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} },
|
||||||
|
{ MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} },
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 4ff5c37f7..b145f8477 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -304,6 +304,7 @@ static void tagmon(const Arg *arg);
|
||||||
|
static void tile(Monitor *m);
|
||||||
|
static void togglefloating(const Arg *arg);
|
||||||
|
static void togglefullscreen(const Arg *arg);
|
||||||
|
+static void movecenter(const Arg *arg);
|
||||||
|
static void toggletag(const Arg *arg);
|
||||||
|
static void toggleview(const Arg *arg);
|
||||||
|
static void unlocksession(struct wl_listener *listener, void *data);
|
||||||
|
@@ -2402,6 +2403,28 @@ togglefullscreen(const Arg *arg)
|
||||||
|
setfullscreen(sel, !sel->isfullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+movecenter(const Arg *arg)
|
||||||
|
+{
|
||||||
|
+ Client *c = focustop(selmon);
|
||||||
|
+ Monitor *m = selmon;
|
||||||
|
+
|
||||||
|
+ if (!m) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (c) {
|
||||||
|
+ // const int center_relative_to_monitor = arg->i;
|
||||||
|
+ struct wlr_box b = center_relative_to_monitor ? m->m : m->w;
|
||||||
|
+ resize(c, (struct wlr_box){
|
||||||
|
+ .x = (b.width - c->geom.width) / 2 + b.x,
|
||||||
|
+ .y = (b.height - c->geom.height) / 2 + b.y,
|
||||||
|
+ .width = c->geom.width,
|
||||||
|
+ .height = c->geom.height,
|
||||||
|
+ }, 1);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
toggletag(const Arg *arg)
|
||||||
|
{
|
85
user/.config/suckless/dwl/patches/movestack.patch
Normal file
85
user/.config/suckless/dwl/patches/movestack.patch
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
From 5518f76de363500a9c5b61cbcd0c7aca180e90f0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nikita Ivanov <nikita.vyach.ivanov@gmail.com>
|
||||||
|
Date: Tue, 5 Sep 2023 02:26:40 +0200
|
||||||
|
Subject: [PATCH] Allows you to move a window up and down the stack
|
||||||
|
|
||||||
|
Fix for loops bug.
|
||||||
|
---
|
||||||
|
config.def.h | 2 ++
|
||||||
|
dwl.c | 43 +++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 45 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 1677f6f12..07ee6d4c5 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -114,6 +114,8 @@ static const Key keys[] = {
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||||
|
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
||||||
|
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||||
|
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_J, movestack, {.i = +1} },
|
||||||
|
+ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_K, movestack, {.i = -1} },
|
||||||
|
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||||
|
{ MODKEY, XKB_KEY_d, incnmaster, {.i = -1} },
|
||||||
|
{ MODKEY, XKB_KEY_h, setmfact, {.f = -0.05} },
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 4ff5c37f7..f70b26411 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -273,6 +273,7 @@ static void maplayersurfacenotify(struct wl_listener *listener, void *data);
|
||||||
|
static void mapnotify(struct wl_listener *listener, void *data);
|
||||||
|
static void maximizenotify(struct wl_listener *listener, void *data);
|
||||||
|
static void monocle(Monitor *m);
|
||||||
|
+static void movestack(const Arg *arg);
|
||||||
|
static void motionabsolute(struct wl_listener *listener, void *data);
|
||||||
|
static void motionnotify(uint32_t time);
|
||||||
|
static void motionrelative(struct wl_listener *listener, void *data);
|
||||||
|
@@ -1633,6 +1634,48 @@ monocle(Monitor *m)
|
||||||
|
wlr_scene_node_raise_to_top(&c->scene->node);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+movestack(const Arg *arg)
|
||||||
|
+{
|
||||||
|
+ Client *c, *sel = focustop(selmon);
|
||||||
|
+
|
||||||
|
+ if (!sel) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (wl_list_length(&clients) <= 1) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (arg->i > 0) {
|
||||||
|
+ wl_list_for_each(c, &sel->link, link) {
|
||||||
|
+ if (&c->link == &clients) {
|
||||||
|
+ c = wl_container_of(&clients, c, link);
|
||||||
|
+ break; /* wrap past the sentinel node */
|
||||||
|
+ }
|
||||||
|
+ if (VISIBLEON(c, selmon) || &c->link == &clients) {
|
||||||
|
+ break; /* found it */
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ wl_list_for_each_reverse(c, &sel->link, link) {
|
||||||
|
+ if (&c->link == &clients) {
|
||||||
|
+ c = wl_container_of(&clients, c, link);
|
||||||
|
+ break; /* wrap past the sentinel node */
|
||||||
|
+ }
|
||||||
|
+ if (VISIBLEON(c, selmon) || &c->link == &clients) {
|
||||||
|
+ break; /* found it */
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ /* backup one client */
|
||||||
|
+ c = wl_container_of(c->link.prev, c, link);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ wl_list_remove(&sel->link);
|
||||||
|
+ wl_list_insert(&c->link, &sel->link);
|
||||||
|
+ arrange(selmon);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
motionabsolute(struct wl_listener *listener, void *data)
|
||||||
|
{
|
176
user/.config/suckless/dwl/patches/namedscratchpads.patch
Normal file
176
user/.config/suckless/dwl/patches/namedscratchpads.patch
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
From 13402c1ccead7a6775520bd1ceef31611583c965 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Louis-Michel Raynauld <louismichel@pweb.ca>
|
||||||
|
Date: Fri, 29 Jul 2022 23:09:10 -0700
|
||||||
|
Subject: [PATCH 1/2] port dwm "namedscratchpads" patch to dwl
|
||||||
|
|
||||||
|
---
|
||||||
|
config.def.h | 9 +++++++--
|
||||||
|
dwl.c | 42 ++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 49 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 190b0da41..b5f87336b 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -10,11 +10,12 @@ static const float focuscolor[] = {1.0, 0.0, 0.0, 1.0};
|
||||||
|
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
|
||||||
|
|
||||||
|
static const Rule rules[] = {
|
||||||
|
- /* app_id title tags mask isfloating monitor */
|
||||||
|
+ /* app_id title tags mask isfloating monitor scratchkey */
|
||||||
|
/* examples:
|
||||||
|
{ "Gimp", NULL, 0, 1, -1 },
|
||||||
|
*/
|
||||||
|
- { "firefox", NULL, 1 << 8, 0, -1 },
|
||||||
|
+ { "firefox", NULL, 1 << 8, 0, -1, 0 },
|
||||||
|
+ { NULL, "scratchpad", 0, 1, -1, 's' },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* layout(s) */
|
||||||
|
@@ -66,11 +67,15 @@ static const int natural_scrolling = 0;
|
||||||
|
static const char *termcmd[] = { "alacritty", NULL };
|
||||||
|
static const char *menucmd[] = { "bemenu-run", NULL };
|
||||||
|
|
||||||
|
+/* named scratchpads - First arg only serves to match against key in rules*/
|
||||||
|
+static const char *scratchpadcmd[] = { "s", "alacritty", "-t", "scratchpad", NULL };
|
||||||
|
+
|
||||||
|
static const Key keys[] = {
|
||||||
|
/* Note that Shift changes certain key codes: c -> C, 2 -> at, etc. */
|
||||||
|
/* modifier key function argument */
|
||||||
|
{ MODKEY, XKB_KEY_p, spawn, {.v = menucmd} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} },
|
||||||
|
+ { MODKEY, XKB_KEY_grave, togglescratch, {.v = scratchpadcmd } },
|
||||||
|
{ MODKEY, XKB_KEY_j, focusstack, {.i = +1} },
|
||||||
|
{ MODKEY, XKB_KEY_k, focusstack, {.i = -1} },
|
||||||
|
{ MODKEY, XKB_KEY_i, incnmaster, {.i = +1} },
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index b09fc6f92..f21488c01 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -118,6 +118,7 @@ typedef struct {
|
||||||
|
int isfloating, isurgent;
|
||||||
|
uint32_t resize; /* configure serial of a pending resize */
|
||||||
|
int isfullscreen;
|
||||||
|
+ char scratchkey;
|
||||||
|
} Client;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
@@ -198,6 +199,7 @@ typedef struct {
|
||||||
|
unsigned int tags;
|
||||||
|
int isfloating;
|
||||||
|
int monitor;
|
||||||
|
+ const char scratchkey;
|
||||||
|
} Rule;
|
||||||
|
|
||||||
|
/* function declarations */
|
||||||
|
@@ -273,12 +275,14 @@ static void setsel(struct wl_listener *listener, void *data);
|
||||||
|
static void setup(void);
|
||||||
|
static void sigchld(int unused);
|
||||||
|
static void spawn(const Arg *arg);
|
||||||
|
+static void spawnscratch(const Arg *arg);
|
||||||
|
static void startdrag(struct wl_listener *listener, void *data);
|
||||||
|
static void tag(const Arg *arg);
|
||||||
|
static void tagmon(const Arg *arg);
|
||||||
|
static void tile(Monitor *m);
|
||||||
|
static void togglefloating(const Arg *arg);
|
||||||
|
static void togglefullscreen(const Arg *arg);
|
||||||
|
+static void togglescratch(const Arg *arg);
|
||||||
|
static void toggletag(const Arg *arg);
|
||||||
|
static void toggleview(const Arg *arg);
|
||||||
|
static void unmaplayersurface(LayerSurface *layersurface);
|
||||||
|
@@ -457,6 +461,7 @@ applyrules(Client *c)
|
||||||
|
Monitor *mon = selmon, *m;
|
||||||
|
|
||||||
|
c->isfloating = client_is_float_type(c);
|
||||||
|
+ c->scratchkey = 0;
|
||||||
|
if (!(appid = client_get_appid(c)))
|
||||||
|
appid = broken;
|
||||||
|
if (!(title = client_get_title(c)))
|
||||||
|
@@ -466,6 +471,7 @@ applyrules(Client *c)
|
||||||
|
if ((!r->title || strstr(title, r->title))
|
||||||
|
&& (!r->id || strstr(appid, r->id))) {
|
||||||
|
c->isfloating = r->isfloating;
|
||||||
|
+ c->scratchkey = r->scratchkey;
|
||||||
|
newtags |= r->tags;
|
||||||
|
i = 0;
|
||||||
|
wl_list_for_each(m, &mons, link)
|
||||||
|
@@ -2092,6 +2098,16 @@ spawn(const Arg *arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+void spawnscratch(const Arg *arg)
|
||||||
|
+{
|
||||||
|
+ if (fork() == 0) {
|
||||||
|
+ dup2(STDERR_FILENO, STDOUT_FILENO);
|
||||||
|
+ setsid();
|
||||||
|
+ execvp(((char **)arg->v)[1], ((char **)arg->v)+1);
|
||||||
|
+ die("dwl: execvp %s failed:", ((char **)arg->v)[1]);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
startdrag(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
@@ -2176,6 +2192,32 @@ togglefullscreen(const Arg *arg)
|
||||||
|
setfullscreen(sel, !sel->isfullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+togglescratch(const Arg *arg)
|
||||||
|
+{
|
||||||
|
+ Client *c;
|
||||||
|
+ unsigned int found = 0;
|
||||||
|
+
|
||||||
|
+ /* search for first window that matches the scratchkey */
|
||||||
|
+ wl_list_for_each(c, &clients, link)
|
||||||
|
+ if (c->scratchkey == ((char**)arg->v)[0][0]) {
|
||||||
|
+ found = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (found) {
|
||||||
|
+ c->tags = VISIBLEON(c, selmon) ? 0 : selmon->tagset[selmon->seltags];
|
||||||
|
+ focusclient(NULL, 0);
|
||||||
|
+ if (VISIBLEON(c, selmon)) {
|
||||||
|
+ focusclient(c, 0);
|
||||||
|
+ }
|
||||||
|
+ arrange(selmon);
|
||||||
|
+
|
||||||
|
+ } else{
|
||||||
|
+ spawnscratch(arg);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
toggletag(const Arg *arg)
|
||||||
|
{
|
||||||
|
|
||||||
|
From be5e75b1bad480a7eedd81ef68cc331687fbe7cd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Louis-Michel Raynauld <louismichel@pweb.ca>
|
||||||
|
Date: Fri, 5 Aug 2022 22:20:59 -0700
|
||||||
|
Subject: [PATCH 2/2] Fix focus after hiding and make sure toggle scratchpad
|
||||||
|
appears on top of others scratchpads if any.
|
||||||
|
|
||||||
|
---
|
||||||
|
dwl.c | 7 ++-----
|
||||||
|
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index f21488c01..e0ecdb8ea 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -2207,12 +2207,9 @@ togglescratch(const Arg *arg)
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
c->tags = VISIBLEON(c, selmon) ? 0 : selmon->tagset[selmon->seltags];
|
||||||
|
- focusclient(NULL, 0);
|
||||||
|
- if (VISIBLEON(c, selmon)) {
|
||||||
|
- focusclient(c, 0);
|
||||||
|
- }
|
||||||
|
- arrange(selmon);
|
||||||
|
|
||||||
|
+ focusclient(c->tags == 0 ? focustop(selmon) : c, 1);
|
||||||
|
+ arrange(selmon);
|
||||||
|
} else{
|
||||||
|
spawnscratch(arg);
|
||||||
|
}
|
167
user/.config/suckless/dwl/patches/pertag.patch
Normal file
167
user/.config/suckless/dwl/patches/pertag.patch
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
From 8750e1255f6c8b799165186cd6cfdfa7af3ee56d Mon Sep 17 00:00:00 2001
|
||||||
|
From: mortezadadgar <mortezadadgar97@gmail.com>
|
||||||
|
Date: Sat, 26 Aug 2023 20:37:22 +0330
|
||||||
|
Subject: [PATCH] Applied pertag
|
||||||
|
|
||||||
|
---
|
||||||
|
dwl.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||||
|
1 file changed, 70 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 4ff5c37f7..6c104bbb0 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -94,6 +94,7 @@ typedef struct {
|
||||||
|
const Arg arg;
|
||||||
|
} Button;
|
||||||
|
|
||||||
|
+typedef struct Pertag Pertag;
|
||||||
|
typedef struct Monitor Monitor;
|
||||||
|
typedef struct {
|
||||||
|
/* Must keep these three elements in this order */
|
||||||
|
@@ -185,6 +186,7 @@ struct Monitor {
|
||||||
|
struct wlr_box w; /* window area, layout-relative */
|
||||||
|
struct wl_list layers[4]; /* LayerSurface::link */
|
||||||
|
const Layout *lt[2];
|
||||||
|
+ Pertag *pertag;
|
||||||
|
unsigned int seltags;
|
||||||
|
unsigned int sellt;
|
||||||
|
uint32_t tagset[2];
|
||||||
|
@@ -413,6 +415,14 @@ static Atom netatom[NetLast];
|
||||||
|
/* attempt to encapsulate suck into one file */
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
+struct Pertag {
|
||||||
|
+ unsigned int curtag, prevtag; /* current and previous tag */
|
||||||
|
+ int nmasters[TAGCOUNT + 1]; /* number of windows in master area */
|
||||||
|
+ float mfacts[TAGCOUNT + 1]; /* mfacts per tag */
|
||||||
|
+ unsigned int sellts[TAGCOUNT + 1]; /* selected layouts */
|
||||||
|
+ const Layout *ltidxs[TAGCOUNT + 1][2]; /* matrix of tags and layouts indexes */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
/* function implementations */
|
||||||
|
void
|
||||||
|
applybounds(Client *c, struct wlr_box *bbox)
|
||||||
|
@@ -703,6 +713,7 @@ cleanupmon(struct wl_listener *listener, void *data)
|
||||||
|
wlr_scene_output_destroy(m->scene_output);
|
||||||
|
wlr_scene_node_destroy(&m->fullscreen_bg->node);
|
||||||
|
|
||||||
|
+ free(m->pertag);
|
||||||
|
closemon(m);
|
||||||
|
free(m);
|
||||||
|
}
|
||||||
|
@@ -944,6 +955,18 @@ createmon(struct wl_listener *listener, void *data)
|
||||||
|
wl_list_insert(&mons, &m->link);
|
||||||
|
printstatus();
|
||||||
|
|
||||||
|
+ m->pertag = calloc(1, sizeof(Pertag));
|
||||||
|
+ m->pertag->curtag = m->pertag->prevtag = 1;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i <= TAGCOUNT; i++) {
|
||||||
|
+ m->pertag->nmasters[i] = m->nmaster;
|
||||||
|
+ m->pertag->mfacts[i] = m->mfact;
|
||||||
|
+
|
||||||
|
+ m->pertag->ltidxs[i][0] = m->lt[0];
|
||||||
|
+ m->pertag->ltidxs[i][1] = m->lt[1];
|
||||||
|
+ m->pertag->sellts[i] = m->sellt;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* The xdg-protocol specifies:
|
||||||
|
*
|
||||||
|
* If the fullscreened surface is not opaque, the compositor must make
|
||||||
|
@@ -1355,7 +1378,7 @@ incnmaster(const Arg *arg)
|
||||||
|
{
|
||||||
|
if (!arg || !selmon)
|
||||||
|
return;
|
||||||
|
- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
|
||||||
|
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2060,9 +2083,9 @@ setlayout(const Arg *arg)
|
||||||
|
if (!selmon)
|
||||||
|
return;
|
||||||
|
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
|
||||||
|
- selmon->sellt ^= 1;
|
||||||
|
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
|
||||||
|
if (arg && arg->v)
|
||||||
|
- selmon->lt[selmon->sellt] = (Layout *)arg->v;
|
||||||
|
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
|
||||||
|
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, LENGTH(selmon->ltsymbol));
|
||||||
|
arrange(selmon);
|
||||||
|
printstatus();
|
||||||
|
@@ -2079,7 +2102,7 @@ setmfact(const Arg *arg)
|
||||||
|
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
|
||||||
|
if (f < 0.1 || f > 0.9)
|
||||||
|
return;
|
||||||
|
- selmon->mfact = f;
|
||||||
|
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2423,10 +2446,30 @@ void
|
||||||
|
toggleview(const Arg *arg)
|
||||||
|
{
|
||||||
|
uint32_t newtagset = selmon ? selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK) : 0;
|
||||||
|
+ size_t i;
|
||||||
|
|
||||||
|
if (!newtagset)
|
||||||
|
return;
|
||||||
|
|
||||||
|
+ if (newtagset == ~0) {
|
||||||
|
+ selmon->pertag->prevtag = selmon->pertag->curtag;
|
||||||
|
+ selmon->pertag->curtag = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* test if the user did not select the same tag */
|
||||||
|
+ if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
|
||||||
|
+ selmon->pertag->prevtag = selmon->pertag->curtag;
|
||||||
|
+ for (i = 0; !(newtagset & 1 << i); i++) ;
|
||||||
|
+ selmon->pertag->curtag = i + 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* apply settings for this view */
|
||||||
|
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
|
||||||
|
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
|
||||||
|
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
|
||||||
|
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
|
||||||
|
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
|
||||||
|
+
|
||||||
|
selmon->tagset[selmon->seltags] = newtagset;
|
||||||
|
focusclient(focustop(selmon), 1);
|
||||||
|
arrange(selmon);
|
||||||
|
@@ -2596,11 +2639,33 @@ urgent(struct wl_listener *listener, void *data)
|
||||||
|
void
|
||||||
|
view(const Arg *arg)
|
||||||
|
{
|
||||||
|
+ size_t i, tmptag;
|
||||||
|
+
|
||||||
|
if (!selmon || (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
|
||||||
|
return;
|
||||||
|
selmon->seltags ^= 1; /* toggle sel tagset */
|
||||||
|
- if (arg->ui & TAGMASK)
|
||||||
|
+ if (arg->ui & TAGMASK) {
|
||||||
|
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
|
||||||
|
+ selmon->pertag->prevtag = selmon->pertag->curtag;
|
||||||
|
+
|
||||||
|
+ if (arg->ui == ~0)
|
||||||
|
+ selmon->pertag->curtag = 0;
|
||||||
|
+ else {
|
||||||
|
+ for (i = 0; !(arg->ui & 1 << i); i++) ;
|
||||||
|
+ selmon->pertag->curtag = i + 1;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ tmptag = selmon->pertag->prevtag;
|
||||||
|
+ selmon->pertag->prevtag = selmon->pertag->curtag;
|
||||||
|
+ selmon->pertag->curtag = tmptag;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
|
||||||
|
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
|
||||||
|
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
|
||||||
|
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
|
||||||
|
+ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
|
||||||
|
+
|
||||||
|
focusclient(focustop(selmon), 1);
|
||||||
|
arrange(selmon);
|
||||||
|
printstatus();
|
99
user/.config/suckless/dwl/patches/regexrules.patch
Normal file
99
user/.config/suckless/dwl/patches/regexrules.patch
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
From a188445accb5db9414599ad350ded195047a6661 Mon Sep 17 00:00:00 2001
|
||||||
|
From: wochap <gean.marroquin@gmail.com>
|
||||||
|
Date: Wed, 6 Sep 2023 21:25:55 -0500
|
||||||
|
Subject: [PATCH 1/2] implement regex support in rules for app_id and title
|
||||||
|
|
||||||
|
Enables the use of regular expressions for window rules "app_id" and "title"
|
||||||
|
---
|
||||||
|
config.def.h | 1 +
|
||||||
|
dwl.c | 19 +++++++++++++++++--
|
||||||
|
2 files changed, 18 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 1677f6f12..1eb646127 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -17,6 +17,7 @@ static const Rule rules[] = {
|
||||||
|
{ "Gimp", NULL, 0, 1, -1 },
|
||||||
|
*/
|
||||||
|
{ "firefox", NULL, 1 << 8, 0, -1 },
|
||||||
|
+ { "^kitty$", NULL, 0, 0, -1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* layout(s) */
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 4ff5c37f7..9c29eb4aa 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -11,6 +11,7 @@
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
+#include <regex.h>
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/backend.h>
|
||||||
|
#include <wlr/backend/libinput.h>
|
||||||
|
@@ -318,6 +319,7 @@ static Monitor *xytomon(double x, double y);
|
||||||
|
static void xytonode(double x, double y, struct wlr_surface **psurface,
|
||||||
|
Client **pc, LayerSurface **pl, double *nx, double *ny);
|
||||||
|
static void zoom(const Arg *arg);
|
||||||
|
+static int regex_match(const char *pattern, const char *str);
|
||||||
|
|
||||||
|
/* variables */
|
||||||
|
static const char broken[] = "broken";
|
||||||
|
@@ -457,8 +459,8 @@ applyrules(Client *c)
|
||||||
|
title = broken;
|
||||||
|
|
||||||
|
for (r = rules; r < END(rules); r++) {
|
||||||
|
- if ((!r->title || strstr(title, r->title))
|
||||||
|
- && (!r->id || strstr(appid, r->id))) {
|
||||||
|
+ if ((!r->title || regex_match(title, r->title))
|
||||||
|
+ && (!r->id || regex_match(appid, r->id))) {
|
||||||
|
c->isfloating = r->isfloating;
|
||||||
|
newtags |= r->tags;
|
||||||
|
i = 0;
|
||||||
|
@@ -2683,6 +2685,19 @@ zoom(const Arg *arg)
|
||||||
|
arrange(selmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
+int
|
||||||
|
+regex_match(const char *pattern, const char *str) {
|
||||||
|
+ regex_t regex;
|
||||||
|
+ int reti;
|
||||||
|
+ if (regcomp(®ex, pattern, REG_EXTENDED) != 0)
|
||||||
|
+ return 0;
|
||||||
|
+ reti = regexec(®ex, str, (size_t)0, NULL, 0);
|
||||||
|
+ regfree(®ex);
|
||||||
|
+ if (reti == 0)
|
||||||
|
+ return 1;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#ifdef XWAYLAND
|
||||||
|
void
|
||||||
|
activatex11(struct wl_listener *listener, void *data)
|
||||||
|
|
||||||
|
From d7160c26d3f0f131a6966907fef7e926c6eba781 Mon Sep 17 00:00:00 2001
|
||||||
|
From: wochap <gean.marroquin@gmail.com>
|
||||||
|
Date: Wed, 11 Oct 2023 23:09:45 -0500
|
||||||
|
Subject: [PATCH 2/2] fix typo
|
||||||
|
|
||||||
|
---
|
||||||
|
dwl.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 9c29eb4aa..41ec97ba6 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -459,8 +459,8 @@ applyrules(Client *c)
|
||||||
|
title = broken;
|
||||||
|
|
||||||
|
for (r = rules; r < END(rules); r++) {
|
||||||
|
- if ((!r->title || regex_match(title, r->title))
|
||||||
|
- && (!r->id || regex_match(appid, r->id))) {
|
||||||
|
+ if ((!r->title || regex_match(r->title, title))
|
||||||
|
+ && (!r->id || regex_match(r->id, appid))) {
|
||||||
|
c->isfloating = r->isfloating;
|
||||||
|
newtags |= r->tags;
|
||||||
|
i = 0;
|
199
user/.config/suckless/dwl/patches/toggleKbLayout.patch
Normal file
199
user/.config/suckless/dwl/patches/toggleKbLayout.patch
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
From d04df999acc1b0c0a0bdf5fe8a737e9e0fae0a2f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stivvo <stivvo01@gmail.com>
|
||||||
|
Date: Fri, 18 Sep 2020 12:56:23 +0200
|
||||||
|
Subject: [PATCH 1/2] Switch between keyboard layouts ar runtime
|
||||||
|
|
||||||
|
setkblayout() avoids to rewrite the code necessary to set the keyboard
|
||||||
|
layout in createkeyboard() and togglekblayout()
|
||||||
|
---
|
||||||
|
config.def.h | 6 ++++++
|
||||||
|
dwl.c | 38 +++++++++++++++++++++++++++++---------
|
||||||
|
2 files changed, 35 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/config.def.h b/config.def.h
|
||||||
|
index 53021cf74..b0fb9321e 100644
|
||||||
|
--- a/config.def.h
|
||||||
|
+++ b/config.def.h
|
||||||
|
@@ -44,6 +44,11 @@ static const struct xkb_rule_names xkb_rules = {
|
||||||
|
static const int repeat_rate = 25;
|
||||||
|
static const int repeat_delay = 600;
|
||||||
|
|
||||||
|
+/* gb will be set the first time togglekblayout is called, then us.. it is
|
||||||
|
+ * recommended to set the same layout in position 0 of kblayouts and in
|
||||||
|
+ * xkb_rules */
|
||||||
|
+static const char *kblayouts[] = {"us", "gb"};
|
||||||
|
+
|
||||||
|
#define MODKEY WLR_MODIFIER_ALT
|
||||||
|
#define TAGKEYS(KEY,SKEY,TAG) \
|
||||||
|
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
|
||||||
|
@@ -81,6 +86,7 @@ static const Key keys[] = {
|
||||||
|
{ MODKEY, XKB_KEY_period, focusmon, {.i = +1} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = -1} },
|
||||||
|
{ MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = +1} },
|
||||||
|
+ { MODKEY, XKB_KEY_w, togglekblayout, {0} },
|
||||||
|
TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0),
|
||||||
|
TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1),
|
||||||
|
TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2),
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 730e46a1f..5256eec0e 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -221,6 +221,7 @@ static void run(char *startup_cmd);
|
||||||
|
static void scalebox(struct wlr_box *box, float scale);
|
||||||
|
static Client *selclient(void);
|
||||||
|
static void setcursor(struct wl_listener *listener, void *data);
|
||||||
|
+static void setkblayout(Keyboard *kb, const struct xkb_rule_names *newrule);
|
||||||
|
static void setpsel(struct wl_listener *listener, void *data);
|
||||||
|
static void setsel(struct wl_listener *listener, void *data);
|
||||||
|
static void setfloating(Client *c, int floating);
|
||||||
|
@@ -234,6 +235,7 @@ static void tag(const Arg *arg);
|
||||||
|
static void tagmon(const Arg *arg);
|
||||||
|
static void tile(Monitor *m);
|
||||||
|
static void togglefloating(const Arg *arg);
|
||||||
|
+static void togglekblayout(const Arg *arg);
|
||||||
|
static void toggletag(const Arg *arg);
|
||||||
|
static void toggleview(const Arg *arg);
|
||||||
|
static void unmapnotify(struct wl_listener *listener, void *data);
|
||||||
|
@@ -261,6 +263,7 @@ static struct wlr_xcursor_manager *cursor_mgr;
|
||||||
|
|
||||||
|
static struct wlr_seat *seat;
|
||||||
|
static struct wl_list keyboards;
|
||||||
|
+static unsigned int kblayout = 0; /* index of kblayouts */
|
||||||
|
static unsigned int cursor_mode;
|
||||||
|
static Client *grabc;
|
||||||
|
static int grabcx, grabcy; /* client-relative */
|
||||||
|
@@ -480,24 +483,28 @@ commitnotify(struct wl_listener *listener, void *data)
|
||||||
|
c->resize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+setkblayout(Keyboard *kb, const struct xkb_rule_names *newrule)
|
||||||
|
+{
|
||||||
|
+ /* Prepare an XKB keymap and assign it to the keyboard. */
|
||||||
|
+ struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
+ struct xkb_keymap *keymap = xkb_map_new_from_names(context, newrule,
|
||||||
|
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
+ wlr_keyboard_set_keymap(kb->device->keyboard, keymap);
|
||||||
|
+ xkb_keymap_unref(keymap);
|
||||||
|
+ xkb_context_unref(context);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
createkeyboard(struct wlr_input_device *device)
|
||||||
|
{
|
||||||
|
- struct xkb_context *context;
|
||||||
|
- struct xkb_keymap *keymap;
|
||||||
|
Keyboard *kb;
|
||||||
|
|
||||||
|
kb = device->data = calloc(1, sizeof(*kb));
|
||||||
|
kb->device = device;
|
||||||
|
|
||||||
|
- /* Prepare an XKB keymap and assign it to the keyboard. */
|
||||||
|
- context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
- keymap = xkb_map_new_from_names(context, &xkb_rules,
|
||||||
|
- XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
+ setkblayout(kb, &xkb_rules);
|
||||||
|
|
||||||
|
- wlr_keyboard_set_keymap(device->keyboard, keymap);
|
||||||
|
- xkb_keymap_unref(keymap);
|
||||||
|
- xkb_context_unref(context);
|
||||||
|
wlr_keyboard_set_repeat_info(device->keyboard, repeat_rate, repeat_delay);
|
||||||
|
|
||||||
|
/* Here we set up listeners for keyboard events. */
|
||||||
|
@@ -1675,6 +1682,19 @@ togglefloating(const Arg *arg)
|
||||||
|
setfloating(sel, !sel->isfloating /* || sel->isfixed */);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+togglekblayout(const Arg *arg)
|
||||||
|
+{
|
||||||
|
+ Keyboard *kb;
|
||||||
|
+ struct xkb_rule_names newrule = xkb_rules;
|
||||||
|
+
|
||||||
|
+ kblayout = (kblayout + 1) % LENGTH(kblayouts);
|
||||||
|
+ newrule.layout = kblayouts[kblayout];
|
||||||
|
+ wl_list_for_each(kb, &keyboards, link) {
|
||||||
|
+ setkblayout(kb, &newrule);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
toggletag(const Arg *arg)
|
||||||
|
{
|
||||||
|
|
||||||
|
From 382ec6b9cddbde9e66a08bc11d4836327b8f084a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stivvo <stivvo01@gmail.com>
|
||||||
|
Date: Mon, 8 Mar 2021 17:19:18 +0100
|
||||||
|
Subject: [PATCH 2/2] Don't interfere with the dwl codebase
|
||||||
|
|
||||||
|
Removing setkblayout duplicates a few lines of code to avoid touch the
|
||||||
|
codebase
|
||||||
|
---
|
||||||
|
dwl.c | 34 ++++++++++++++++++----------------
|
||||||
|
1 file changed, 18 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dwl.c b/dwl.c
|
||||||
|
index 83dc16d09..4749936ff 100644
|
||||||
|
--- a/dwl.c
|
||||||
|
+++ b/dwl.c
|
||||||
|
@@ -270,7 +270,6 @@ static void run(char *startup_cmd);
|
||||||
|
static void scalebox(struct wlr_box *box, float scale);
|
||||||
|
static Client *selclient(void);
|
||||||
|
static void setcursor(struct wl_listener *listener, void *data);
|
||||||
|
-static void setkblayout(Keyboard *kb, const struct xkb_rule_names *newrule);
|
||||||
|
static void setpsel(struct wl_listener *listener, void *data);
|
||||||
|
static void setsel(struct wl_listener *listener, void *data);
|
||||||
|
static void setfloating(Client *c, int floating);
|
||||||
|
@@ -784,25 +783,22 @@ commitnotify(struct wl_listener *listener, void *data)
|
||||||
|
c->resize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void
|
||||||
|
-setkblayout(Keyboard *kb, const struct xkb_rule_names *newrule)
|
||||||
|
-{
|
||||||
|
- /* Prepare an XKB keymap and assign it to the keyboard. */
|
||||||
|
- struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
- struct xkb_keymap *keymap = xkb_map_new_from_names(context, newrule,
|
||||||
|
- XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
- wlr_keyboard_set_keymap(kb->device->keyboard, keymap);
|
||||||
|
- xkb_keymap_unref(keymap);
|
||||||
|
- xkb_context_unref(context);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
void
|
||||||
|
createkeyboard(struct wlr_input_device *device)
|
||||||
|
{
|
||||||
|
+ struct xkb_context *context;
|
||||||
|
+ struct xkb_keymap *keymap;
|
||||||
|
Keyboard *kb = device->data = calloc(1, sizeof(*kb));
|
||||||
|
kb->device = device;
|
||||||
|
|
||||||
|
- setkblayout(kb, &xkb_rules);
|
||||||
|
+ /* Prepare an XKB keymap and assign it to the keyboard. */
|
||||||
|
+ context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
+ keymap = xkb_map_new_from_names(context, &xkb_rules,
|
||||||
|
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
+
|
||||||
|
+ wlr_keyboard_set_keymap(device->keyboard, keymap);
|
||||||
|
+ xkb_keymap_unref(keymap);
|
||||||
|
+ xkb_context_unref(context);
|
||||||
|
wlr_keyboard_set_repeat_info(device->keyboard, repeat_rate, repeat_delay);
|
||||||
|
|
||||||
|
/* Here we set up listeners for keyboard events. */
|
||||||
|
@@ -2234,8 +2230,14 @@ togglekblayout(const Arg *arg)
|
||||||
|
|
||||||
|
kblayout = (kblayout + 1) % LENGTH(kblayouts);
|
||||||
|
newrule.layout = kblayouts[kblayout];
|
||||||
|
- wl_list_for_each(kb, &keyboards, link)
|
||||||
|
- setkblayout(kb, &newrule);
|
||||||
|
+ wl_list_for_each(kb, &keyboards, link) {
|
||||||
|
+ struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
+ struct xkb_keymap *keymap = xkb_map_new_from_names(context, &newrule,
|
||||||
|
+ XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
+ wlr_keyboard_set_keymap(kb->device->keyboard, keymap);
|
||||||
|
+ xkb_keymap_unref(keymap);
|
||||||
|
+ xkb_context_unref(context);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue