diff --git a/alacritty/alacritty.yml b/alacritty/alacritty.yml new file mode 100644 index 0000000..4cbd979 --- /dev/null +++ b/alacritty/alacritty.yml @@ -0,0 +1,886 @@ +# Configuration for Alacritty, the GPU enhanced terminal emulator. + +# Import additional configuration files +# +# Imports are loaded in order, skipping all missing files, with the importing +# file being loaded last. If a field is already present in a previous import, it +# will be replaced. +# +# All imports must either be absolute paths starting with `/`, or paths relative +# to the user's home directory starting with `~/`. +import: + - ~/.config/alacritty/colour-spaceship.yml + +# Any items in the `env` entry below will be added as +# environment variables. Some entries may override variables +# set by alacritty itself. +env: + # TERM variable + # + # This value is used to set the `$TERM` environment variable for + # each instance of Alacritty. If it is not present, alacritty will + # check the local terminfo database and use `alacritty` if it is + # available, otherwise `xterm-256color` is used. + TERM: alacritty + +window: + # Window dimensions (changes require restart) + # + # Number of lines/columns (not pixels) in the terminal. Both lines and columns + # must be non-zero for this to take effect. The number of columns must be at + # least `2`, while using a value of `0` for columns and lines will fall back + # to the window manager's recommended size + dimensions: + columns: 65 + lines: 18 + + # Window position (changes require restart) + # + # Specified in number of pixels. + # If the position is not set, the window manager will handle the placement. + #position: + # x: 0 + # y: 0 + + # Window padding (changes require restart) + # + # Blank space added around the window in pixels. This padding is scaled + # by DPI and the specified value is always added at both opposing sides. + padding: + x: 8 + y: 8 + + # Spread additional padding evenly around the terminal content. + #dynamic_padding: false + + # Background opacity + # + # Window opacity as a floating point number from `0.0` to `1.0`. + # The value `0.0` is completely transparent and `1.0` is opaque. + opacity: 0.45 + + # Startup Mode (changes require restart) + # + # Values for `startup_mode`: + # - Windowedhttps://raw.githubusercontent.com/alacritty/alacritty/master/alacritty.yml + # - Maximized + # - Fullscreen + # + # Values for `startup_mode` (macOS only): + # - SimpleFullscreen + #startup_mode: Windowed + + # Window title + title: Alacritty + + # Allow terminal applications to change Alacritty's window title. + dynamic_title: true + + # Window class (Linux/BSD only): + class: + # Application instance name + instance: Alacritty + # General application class + general: Alacritty + + # Decorations theme variant + # + # Override the variant of the System theme/GTK theme/Wayland client side + # decorations. Commonly supported values are `Dark`, `Light`, and `None` for + # auto pick-up. Set this to `None` to use the default theme variant. + #decorations_theme_variant: None + + # Resize increments + # + # Prefer resizing window by discrete steps equal to cell dimensions. + #resize_increments: false + +#scrolling: + # Maximum number of lines in the scrollback buffer. + # Specifying '0' will disable scrolling. + #history: 10000 + + # Scrolling distance multiplier. + #multiplier: 3 + +# Font configuration +font: + normal: + family: Fira Code + + # The `style` can be specified to pick a specific face. + #style: Regular + + # Bold font face + #bold: + # Font family + # + # If the bold family is not specified, it will fall back to the + # value specified for the normal font. + #family: monospace + + # The `style` can be specified to pick a specific face. + #style: Bold + + # Italic font face + #italic: + # Font family + # + # If the italic family is not specified, it will fall back to the + # value specified for the normal font. + #family: monospace + + # The `style` can be specified to pick a specific face. + #style: Italic + + # Bold italic font face + #bold_italic: + # Font family + # + # If the bold italic family is not specified, it will fall back to the + # value specified for the normal font. + #family: monospace + + # The `style` can be specified to pick a specific face. + #style: Bold Italic + + # Point size + size: 11 + + # Offset is the extra space around each character. `offset.y` can be thought + # of as modifying the line spacing, and `offset.x` as modifying the letter + # spacing. + #offset: + # x: 0 + # y: 0 + + # Glyph offset determines the locations of the glyphs within their cells with + # the default being at the bottom. Increasing `x` moves the glyph to the + # right, increasing `y` moves the glyph upward. + #glyph_offset: + # x: 0 + # y: 0 + + # Use built-in font for box drawing characters. + # + # If `true`, Alacritty will use a custom built-in font for box drawing + # characters (Unicode points 2500 - 259f). + # + #builtin_box_drawing: true + +# If `true`, bold text is drawn using the bright color variants. +#draw_bold_text_with_bright_colors: false + +# Colors (Tomorrow Night) +#colors: + # Default colors + #primary: + # background: '#1d1f21' + # foreground: '#c5c8c6' + + # Bright and dim foreground colors + # + # The dimmed foreground color is calculated automatically if it is not + # present. If the bright foreground color is not set, or + # `draw_bold_text_with_bright_colors` is `false`, the normal foreground + # color will be used. + #dim_foreground: '#828482' + #bright_foreground: '#eaeaea' + + # Cursor colors + # + # Colors which should be used to draw the terminal cursor. + # + # Allowed values are CellForeground/CellBackground, which reference the + # affected cell, or hexadecimal colors like #ff00ff. + #cursor: + # text: CellBackground + # cursor: CellForeground + + # Vi mode cursor colors + # + # Colors for the cursor when the vi mode is active. + # + # Allowed values are CellForeground/CellBackground, which reference the + # affected cell, or hexadecimal colors like #ff00ff. + #vi_mode_cursor: + # text: CellBackground + # cursor: CellForeground + + # Search colors + # + # Colors used for the search bar and match highlighting. + #search: + # Allowed values are CellForeground/CellBackground, which reference the + # affected cell, or hexadecimal colors like #ff00ff. + #matches: + # foreground: '#000000' + # background: '#ffffff' + #focused_match: + # foreground: '#ffffff' + # background: '#000000' + + # Keyboard hints + #hints: + # First character in the hint label + # + # Allowed values are CellForeground/CellBackground, which reference the + # affected cell, or hexadecimal colors like #ff00ff. + #start: + # foreground: '#1d1f21' + # background: '#e9ff5e' + + # All characters after the first one in the hint label + # + # Allowed values are CellForeground/CellBackground, which reference the + # affected cell, or hexadecimal colors like #ff00ff. + #end: + # foreground: '#e9ff5e' + # background: '#1d1f21' + + # Line indicator + # + # Color used for the indicator displaying the position in history during + # search and vi mode. + # + # By default, these will use the opposing primary color. + #line_indicator: + # foreground: None + # background: None + + # Footer bar + # + # Color used for the footer bar on the bottom, used by search regex input, + # hyperlink URI preview, etc. + # + #footer_bar: + # background: '#c5c8c6' + # foreground: '#1d1f21' + + # Selection colors + # + # Colors which should be used to draw the selection area. + # + # Allowed values are CellForeground/CellBackground, which reference the + # affected cell, or hexadecimal colors like #ff00ff. + #selection: + # text: CellBackground + # background: CellForeground + + # Normal colors + #normal: + # black: '#1d1f21' + # red: '#cc6666' + # green: '#b5bd68' + # yellow: '#f0c674' + # blue: '#81a2be' + # magenta: '#b294bb' + # cyan: '#8abeb7' + # white: '#c5c8c6' + + # Bright colors + #bright: + # black: '#666666' + # red: '#d54e53' + # green: '#b9ca4a' + # yellow: '#e7c547' + # blue: '#7aa6da' + # magenta: '#c397d8' + # cyan: '#70c0b1' + # white: '#eaeaea' + + # Dim colors + # + # If the dim colors are not set, they will be calculated automatically based + # on the `normal` colors. + #dim: + # black: '#131415' + # red: '#864343' + # green: '#777c44' + # yellow: '#9e824c' + # blue: '#556a7d' + # magenta: '#75617b' + # cyan: '#5b7d78' + # white: '#828482' + + # Indexed Colors + # + # The indexed colors include all colors from 16 to 256. + # When these are not set, they're filled with sensible defaults. + # + # Example: + # `- { index: 16, color: '#ff00ff' }` + # + #indexed_colors: [] + + # Transparent cell backgrounds + # + # Whether or not `window.opacity` applies to all cell backgrounds or only to + # the default background. When set to `true` all cells will be transparent + # regardless of their background color. + #transparent_background_colors: false + +# Bell +# +# The bell is rung every time the BEL control character is received. +#bell: + # Visual Bell Animation + # + # Animation effect for flashing the screen when the visual bell is rung. + # + # Values for `animation`: + # - Ease + # - EaseOut + # - EaseOutSine + # - EaseOutQuad + # - EaseOutCubic + # - EaseOutQuart + # - EaseOutQuint + # - EaseOutExpo + # - EaseOutCirc + # - Linear + #animation: EaseOutExpo + + # Duration of the visual bell flash in milliseconds. A `duration` of `0` will + # disable the visual bell animation. + #duration: 0 + + # Visual bell animation color. + #color: '#ffffff' + + # Bell Command + # + # This program is executed whenever the bell is rung. + # + # When set to `command: None`, no command will be executed. + # + # Example: + # command: + # program: notify-send + # args: ["Hello, World!"] + # + #command: None + +#selection: + # This string contains all characters that are used as separators for + # "semantic words" in Alacritty. + #semantic_escape_chars: ",│`|:\"' ()[]{}<>\t" + + # When set to `true`, selected text will be copied to the primary clipboard. + #save_to_clipboard: false + +#cursor: + # Cursor style + #style: + # Cursor shape + # + # Values for `shape`: + # - ▇ Block + # - _ Underline + # - | Beam + #shape: Block + + # Cursor blinking state + # + # Values for `blinking`: + # - Never: Prevent the cursor from ever blinking + # - Off: Disable blinking by default + # - On: Enable blinking by default + # - Always: Force the cursor to always blink + #blinking: Off + + # Vi mode cursor style + # + # If the vi mode cursor style is `None` or not specified, it will fall back to + # the style of the active value of the normal cursor. + # + # See `cursor.style` for available options. + #vi_mode_style: None + + # Cursor blinking interval in milliseconds. + #blink_interval: 750 + + # Time after which cursor stops blinking, in seconds. + # + # Specifying '0' will disable timeout for blinking. + #blink_timeout: 5 + + # If this is `true`, the cursor will be rendered as a hollow box when the + # window is not focused. + #unfocused_hollow: true + + # Thickness of the cursor relative to the cell width as floating point number + # from `0.0` to `1.0`. + #thickness: 0.15 + +# Live config reload (changes require restart) +#live_config_reload: true + +# Shell +# +# You can set `shell.program` to the path of your favorite shell, e.g. +# `/bin/fish`. Entries in `shell.args` are passed unmodified as arguments to the +# shell. +# +# Default: +# - (Linux/BSD/macOS) `$SHELL` or the user's login shell, if `$SHELL` is unset +# - (Windows) powershell +#shell: +# program: /bin/bash +# args: +# - --login + +# Startup directory +# +# Directory the shell is started in. If this is unset, or `None`, the working +# directory of the parent process will be used. +#working_directory: None + +# Offer IPC using `alacritty msg` (unix only) +#ipc_socket: true + +#mouse: + # Click settings + # + # The `double_click` and `triple_click` settings control the time + # alacritty should wait for accepting multiple clicks as one double + # or triple click. + #double_click: { threshold: 300 } + #triple_click: { threshold: 300 } + + # If this is `true`, the cursor is temporarily hidden when typing. + #hide_when_typing: false + +# Hints +# +# Terminal hints can be used to find text or hyperlink in the visible part of +# the terminal and pipe it to other applications. +#hints: + # Keys used for the hint labels. + #alphabet: "jfkdls;ahgurieowpq" + + # List with all available hints + # + # Each hint must have any of `regex` or `hyperlinks` field and either an + # `action` or a `command` field. The fields `mouse`, `binding` and + # `post_processing` are optional. + # + # The `hyperlinks` option will cause OSC 8 escape sequence hyperlinks to be + # highlighted. + # + # The fields `command`, `binding.key`, `binding.mods`, `binding.mode` and + # `mouse.mods` accept the same values as they do in the `key_bindings` section. + # + # The `mouse.enabled` field controls if the hint should be underlined while + # the mouse with all `mouse.mods` keys held or the vi mode cursor is above it. + # + # If the `post_processing` field is set to `true`, heuristics will be used to + # shorten the match if there are characters likely not to be part of the hint + # (e.g. a trailing `.`). This is most useful for URIs and applies only to + # `regex` matches. + # + # Values for `action`: + # - Copy + # Copy the hint's text to the clipboard. + # - Paste + # Paste the hint's text to the terminal or search. + # - Select + # Select the hint's text. + # - MoveViModeCursor + # Move the vi mode cursor to the beginning of the hint. + #enabled: + # - regex: "(ipfs:|ipns:|magnet:|mailto:|gemini:|gopher:|https:|http:|news:|file:|git:|ssh:|ftp:)\ + # [^\u0000-\u001F\u007F-\u009F<>\"\\s{-}\\^⟨⟩`]+" + # hyperlinks: true + # command: xdg-open + # post_processing: true + # mouse: + # enabled: true + # mods: None + # binding: + # key: U + # mods: Control|Shift + +# Mouse bindings +# +# Mouse bindings are specified as a list of objects, much like the key +# bindings further below. +# +# To trigger mouse bindings when an application running within Alacritty +# captures the mouse, the `Shift` modifier is automatically added as a +# requirement. +# +# Each mouse binding will specify a: +# +# - `mouse`: +# +# - Middle +# - Left +# - Right +# - Numeric identifier such as `5` +# +# - `action` (see key bindings for actions not exclusive to mouse mode) +# +# - Mouse exclusive actions: +# +# - ExpandSelection +# Expand the selection to the current mouse cursor location. +# +# And optionally: +# +# - `mods` (see key bindings) +#mouse_bindings: +# - { mouse: Right, action: ExpandSelection } +# - { mouse: Right, mods: Control, action: ExpandSelection } +# - { mouse: Middle, mode: ~Vi, action: PasteSelection } + +# Key bindings +# +# Key bindings are specified as a list of objects. For example, this is the +# default paste binding: +# +# `- { key: V, mods: Control|Shift, action: Paste }` +# +# Each key binding will specify a: +# +# - `key`: Identifier of the key pressed +# +# - A-Z +# - F1-F24 +# - Key0-Key9 +# +# A full list with available key codes can be found here: +# https://docs.rs/winit/*/winit/event/enum.VirtualKeyCode.html#variants +# +# Instead of using the name of the keys, the `key` field also supports using +# the scancode of the desired key. Scancodes have to be specified as a +# decimal number. This command will allow you to display the hex scancodes +# for certain keys: +# +# `showkey --scancodes`. +# +# Then exactly one of: +# +# - `chars`: Send a byte sequence to the running application +# +# The `chars` field writes the specified string to the terminal. This makes +# it possible to pass escape sequences. To find escape codes for bindings +# like `PageUp` (`"\x1b[5~"`), you can run the command `showkey -a` outside +# of tmux. Note that applications use terminfo to map escape sequences back +# to keys. It is therefore required to update the terminfo when changing an +# escape sequence. +# +# - `action`: Execute a predefined action +# +# - ToggleViMode +# - SearchForward +# Start searching toward the right of the search origin. +# - SearchBackward +# Start searching toward the left of the search origin. +# - Copy +# - Paste +# - IncreaseFontSize +# - DecreaseFontSize +# - ResetFontSize +# - ScrollPageUp +# - ScrollPageDown +# - ScrollHalfPageUp +# - ScrollHalfPageDown +# - ScrollLineUp +# - ScrollLineDown +# - ScrollToTop +# - ScrollToBottom +# - ClearHistory +# Remove the terminal's scrollback history. +# - Hide +# Hide the Alacritty window. +# - Minimize +# Minimize the Alacritty window. +# - Quit +# Quit Alacritty. +# - ToggleFullscreen +# - ToggleMaximized +# - SpawnNewInstance +# Spawn a new instance of Alacritty. +# - CreateNewWindow +# Create a new Alacritty window from the current process. +# - ClearLogNotice +# Clear Alacritty's UI warning and error notice. +# - ClearSelection +# Remove the active selection. +# - ReceiveChar +# - None +# +# - Vi mode exclusive actions: +# +# - Open +# Perform the action of the first matching hint under the vi mode cursor +# with `mouse.enabled` set to `true`. +# - ToggleNormalSelection +# - ToggleLineSelection +# - ToggleBlockSelection +# - ToggleSemanticSelection +# Toggle semantic selection based on `selection.semantic_escape_chars`. +# - CenterAroundViCursor +# Center view around vi mode cursor +# +# - Vi mode exclusive cursor motion actions: +# +# - Up +# One line up. +# - Down +# One line down. +# - Left +# One character left. +# - Right +# One character right. +# - First +# First column, or beginning of the line when already at the first column. +# - Last +# Last column, or beginning of the line when already at the last column. +# - FirstOccupied +# First non-empty cell in this terminal row, or first non-empty cell of +# the line when already at the first cell of the row. +# - High +# Top of the screen. +# - Middle +# Center of the screen. +# - Low +# Bottom of the screen. +# - SemanticLeft +# Start of the previous semantically separated word. +# - SemanticRight +# Start of the next semantically separated word. +# - SemanticLeftEnd +# End of the previous semantically separated word. +# - SemanticRightEnd +# End of the next semantically separated word. +# - WordLeft +# Start of the previous whitespace separated word. +# - WordRight +# Start of the next whitespace separated word. +# - WordLeftEnd +# End of the previous whitespace separated word. +# - WordRightEnd +# End of the next whitespace separated word. +# - Bracket +# Character matching the bracket at the cursor's location. +# - SearchNext +# Beginning of the next match. +# - SearchPrevious +# Beginning of the previous match. +# - SearchStart +# Start of the match to the left of the vi mode cursor. +# - SearchEnd +# End of the match to the right of the vi mode cursor. +# +# - Search mode exclusive actions: +# - SearchFocusNext +# Move the focus to the next search match. +# - SearchFocusPrevious +# Move the focus to the previous search match. +# - SearchConfirm +# - SearchCancel +# - SearchClear +# Reset the search regex. +# - SearchDeleteWord +# Delete the last word in the search regex. +# - SearchHistoryPrevious +# Go to the previous regex in the search history. +# - SearchHistoryNext +# Go to the next regex in the search history. +# +# - macOS exclusive actions: +# - ToggleSimpleFullscreen +# Enter fullscreen without occupying another space. +# +# - Linux/BSD exclusive actions: +# +# - CopySelection +# Copy from the selection buffer. +# - PasteSelection +# Paste from the selection buffer. +# +# - `command`: Fork and execute a specified command plus arguments +# +# The `command` field must be a map containing a `program` string and an +# `args` array of command line parameter strings. For example: +# `{ program: "alacritty", args: ["-e", "vttest"] }` +# +# And optionally: +# +# - `mods`: Key modifiers to filter binding actions +# +# - Command +# - Control +# - Option +# - Super +# - Shift +# - Alt +# +# Multiple `mods` can be combined using `|` like this: +# `mods: Control|Shift`. +# Whitespace and capitalization are relevant and must match the example. +# +# - `mode`: Indicate a binding for only specific terminal reported modes +# +# This is mainly used to send applications the correct escape sequences +# when in different modes. +# +# - AppCursor +# - AppKeypad +# - Search +# - Alt +# - Vi +# +# A `~` operator can be used before a mode to apply the binding whenever +# the mode is *not* active, e.g. `~Alt`. +# +# Bindings are always filled by default, but will be replaced when a new +# binding with the same triggers is defined. To unset a default binding, it can +# be mapped to the `ReceiveChar` action. Alternatively, you can use `None` for +# a no-op if you do not wish to receive input characters for that binding. +# +# If the same trigger is assigned to multiple actions, all of them are executed +# in the order they were defined in. +#key_bindings: + #- { key: Paste, action: Paste } + #- { key: Copy, action: Copy } + #- { key: L, mods: Control, action: ClearLogNotice } + #- { key: L, mods: Control, mode: ~Vi|~Search, chars: "\x0c" } + #- { key: PageUp, mods: Shift, mode: ~Alt, action: ScrollPageUp } + #- { key: PageDown, mods: Shift, mode: ~Alt, action: ScrollPageDown } + #- { key: Home, mods: Shift, mode: ~Alt, action: ScrollToTop } + #- { key: End, mods: Shift, mode: ~Alt, action: ScrollToBottom } + + # Vi Mode + #- { key: Space, mods: Shift|Control, mode: ~Search, action: ToggleViMode } + #- { key: Space, mods: Shift|Control, mode: Vi|~Search, action: ScrollToBottom } + #- { key: Escape, mode: Vi|~Search, action: ClearSelection } + #- { key: I, mode: Vi|~Search, action: ToggleViMode } + #- { key: I, mode: Vi|~Search, action: ScrollToBottom } + #- { key: C, mods: Control, mode: Vi|~Search, action: ToggleViMode } + #- { key: Y, mods: Control, mode: Vi|~Search, action: ScrollLineUp } + #- { key: E, mods: Control, mode: Vi|~Search, action: ScrollLineDown } + #- { key: G, mode: Vi|~Search, action: ScrollToTop } + #- { key: G, mods: Shift, mode: Vi|~Search, action: ScrollToBottom } + #- { key: B, mods: Control, mode: Vi|~Search, action: ScrollPageUp } + #- { key: F, mods: Control, mode: Vi|~Search, action: ScrollPageDown } + #- { key: U, mods: Control, mode: Vi|~Search, action: ScrollHalfPageUp } + #- { key: D, mods: Control, mode: Vi|~Search, action: ScrollHalfPageDown } + #- { key: Y, mode: Vi|~Search, action: Copy } + #- { key: Y, mode: Vi|~Search, action: ClearSelection } + #- { key: Copy, mode: Vi|~Search, action: ClearSelection } + #- { key: V, mode: Vi|~Search, action: ToggleNormalSelection } + #- { key: V, mods: Shift, mode: Vi|~Search, action: ToggleLineSelection } + #- { key: V, mods: Control, mode: Vi|~Search, action: ToggleBlockSelection } + #- { key: V, mods: Alt, mode: Vi|~Search, action: ToggleSemanticSelection } + #- { key: Return, mode: Vi|~Search, action: Open } + #- { key: Z, mode: Vi|~Search, action: CenterAroundViCursor } + #- { key: K, mode: Vi|~Search, action: Up } + #- { key: J, mode: Vi|~Search, action: Down } + #- { key: H, mode: Vi|~Search, action: Left } + #- { key: L, mode: Vi|~Search, action: Right } + #- { key: Up, mode: Vi|~Search, action: Up } + #- { key: Down, mode: Vi|~Search, action: Down } + #- { key: Left, mode: Vi|~Search, action: Left } + #- { key: Right, mode: Vi|~Search, action: Right } + #- { key: Key0, mode: Vi|~Search, action: First } + #- { key: Key4, mods: Shift, mode: Vi|~Search, action: Last } + #- { key: Key6, mods: Shift, mode: Vi|~Search, action: FirstOccupied } + #- { key: H, mods: Shift, mode: Vi|~Search, action: High } + #- { key: M, mods: Shift, mode: Vi|~Search, action: Middle } + #- { key: L, mods: Shift, mode: Vi|~Search, action: Low } + #- { key: B, mode: Vi|~Search, action: SemanticLeft } + #- { key: W, mode: Vi|~Search, action: SemanticRight } + #- { key: E, mode: Vi|~Search, action: SemanticRightEnd } + #- { key: B, mods: Shift, mode: Vi|~Search, action: WordLeft } + #- { key: W, mods: Shift, mode: Vi|~Search, action: WordRight } + #- { key: E, mods: Shift, mode: Vi|~Search, action: WordRightEnd } + #- { key: Key5, mods: Shift, mode: Vi|~Search, action: Bracket } + #- { key: Slash, mode: Vi|~Search, action: SearchForward } + #- { key: Slash, mods: Shift, mode: Vi|~Search, action: SearchBackward } + #- { key: N, mode: Vi|~Search, action: SearchNext } + #- { key: N, mods: Shift, mode: Vi|~Search, action: SearchPrevious } + + # Search Mode + #- { key: Return, mode: Search|Vi, action: SearchConfirm } + #- { key: Escape, mode: Search, action: SearchCancel } + #- { key: C, mods: Control, mode: Search, action: SearchCancel } + #- { key: U, mods: Control, mode: Search, action: SearchClear } + #- { key: W, mods: Control, mode: Search, action: SearchDeleteWord } + #- { key: P, mods: Control, mode: Search, action: SearchHistoryPrevious } + #- { key: N, mods: Control, mode: Search, action: SearchHistoryNext } + #- { key: Up, mode: Search, action: SearchHistoryPrevious } + #- { key: Down, mode: Search, action: SearchHistoryNext } + #- { key: Return, mode: Search|~Vi, action: SearchFocusNext } + #- { key: Return, mods: Shift, mode: Search|~Vi, action: SearchFocusPrevious } + + # (Windows, Linux, and BSD only) + #- { key: V, mods: Control|Shift, mode: ~Vi, action: Paste } + #- { key: C, mods: Control|Shift, action: Copy } + #- { key: F, mods: Control|Shift, mode: ~Search, action: SearchForward } + #- { key: B, mods: Control|Shift, mode: ~Search, action: SearchBackward } + #- { key: C, mods: Control|Shift, mode: Vi|~Search, action: ClearSelection } + #- { key: Insert, mods: Shift, action: PasteSelection } + #- { key: Key0, mods: Control, action: ResetFontSize } + #- { key: Equals, mods: Control, action: IncreaseFontSize } + #- { key: Plus, mods: Control, action: IncreaseFontSize } + #- { key: NumpadAdd, mods: Control, action: IncreaseFontSize } + #- { key: Minus, mods: Control, action: DecreaseFontSize } + #- { key: NumpadSubtract, mods: Control, action: DecreaseFontSize } + + # (Windows only) + #- { key: Return, mods: Alt, action: ToggleFullscreen } + + # (macOS only) + #- { key: K, mods: Command, mode: ~Vi|~Search, chars: "\x0c" } + #- { key: K, mods: Command, mode: ~Vi|~Search, action: ClearHistory } + #- { key: Key0, mods: Command, action: ResetFontSize } + #- { key: Equals, mods: Command, action: IncreaseFontSize } + #- { key: Plus, mods: Command, action: IncreaseFontSize } + #- { key: NumpadAdd, mods: Command, action: IncreaseFontSize } + #- { key: Minus, mods: Command, action: DecreaseFontSize } + #- { key: NumpadSubtract, mods: Command, action: DecreaseFontSize } + #- { key: V, mods: Command, action: Paste } + #- { key: C, mods: Command, action: Copy } + #- { key: C, mods: Command, mode: Vi|~Search, action: ClearSelection } + #- { key: H, mods: Command, action: Hide } + #- { key: H, mods: Command|Alt, action: HideOtherApplications } + #- { key: M, mods: Command, action: Minimize } + #- { key: Q, mods: Command, action: Quit } + #- { key: W, mods: Command, action: Quit } + #- { key: N, mods: Command, action: CreateNewWindow } + #- { key: F, mods: Command|Control, action: ToggleFullscreen } + #- { key: F, mods: Command, mode: ~Search, action: SearchForward } + #- { key: B, mods: Command, mode: ~Search, action: SearchBackward } + +#debug: + # Display the time it takes to redraw each frame. + #render_timer: false + + # Keep the log file after quitting Alacritty. + #persistent_logging: false + + # Log level + # + # Values for `log_level`: + # - Off + # - Error + # - Warn + # - Info + # - Debug + # - Trace + #log_level: Warn + + # Renderer override. + # - glsl3 + # - gles2 + # - gles2_pure + #renderer: None + + # Print all received window events. + #print_events: false + + # Highlight window damage information. + #highlight_damage: false diff --git a/alacritty/colour-spaceship.yml b/alacritty/colour-spaceship.yml new file mode 100644 index 0000000..d3249f1 --- /dev/null +++ b/alacritty/colour-spaceship.yml @@ -0,0 +1,27 @@ +colors: + # Default colors + primary: + background: '0xffffff' + foreground: '0x233871' + + # Normal colors + normal: + black: '0xe1e1e1' + red: '0x9e5244' + green: '0x687036' + yellow: '0xb4744d' + blue: '0x2d5278' + magenta: '0x6c3e8f' + cyan: '0x2d6848' + white: '0x5b6c99' + + # Bright colors + bright: + black: '0xababab' + red: '0xe17461' + green: '0xcee161' + yellow: '0xe1b661' + blue: '0x4693e0' + magenta: '0xa961e1' + cyan: '0x61e19c' + white: '0x233871' diff --git a/awesome/README.md b/awesome/README.md new file mode 100644 index 0000000..729d6d0 --- /dev/null +++ b/awesome/README.md @@ -0,0 +1,9 @@ +# awesome config +## Deps +- picom +- pactl (fc38 `pulseaudio-utils`) +## Credits +### Widgets/modules/etc I use +- `volume_widget` comes from [streetturtle's widgets](https://github.com/streetturtle/awesome-wm-widgets) (MIT // 2017) +### Other people's dotfiles I took from lol +- Modularization is from [epsi-rns' awesome dotfiles](https://gitlab.com/epsi-rns/dotfiles) (MIT // 2014-2019 E. R. Nurwijayadi) diff --git a/awesome/awesome-wm-widgets/.luacheckrc b/awesome/awesome-wm-widgets/.luacheckrc new file mode 100644 index 0000000..e4f47fa --- /dev/null +++ b/awesome/awesome-wm-widgets/.luacheckrc @@ -0,0 +1,24 @@ +self = false + +globals = { + "screen", + "mouse", + "root", + "client" +} + +read_globals = { + "awesome", + "button", + "dbus", + "drawable", + "drawin", + "key", + "keygrabber", + "mousegrabber", + "selection", + "tag", + "window", + "table.unpack", + "math.atan2", +} \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/calendar-widget/README.md b/awesome/awesome-wm-widgets/calendar-widget/README.md new file mode 100644 index 0000000..b663a18 --- /dev/null +++ b/awesome/awesome-wm-widgets/calendar-widget/README.md @@ -0,0 +1,89 @@ +# Calendar Widget + +Calendar widget for Awesome WM - slightly improved version of the `wibox.widget.calendar`. + +## Features + + +### Customization + +| Name | Default | Description | +|---|---|---| +| theme | `naughty` | The theme to use | +| placement | `top` | The position of the popup | +| radius | 8 | The popup radius | +| start_sunday | false | Start the week on Sunday | + + - themes: + + | Name | Screenshot | + |---|---| + | nord | ![nord_theme](./nord.png) | + | outrun | ![outrun_theme](./outrun.png) | + | light | ![outrun_theme](./light.png) | + | dark | ![outrun_theme](./dark.png) | + | naughty (default) | from local theme | + + - setup widget placement + + top center - in case you clock is centered: + + ![calendar_top](./calendar_top.png) + + top right - for default awesome config: + + ![calendar_top_right](./calendar_top_right.png) + + bottom right - in case your wibar at the bottom: + + ![calendar_bottom_right](./calendar_bottom_right.png) + + - setup first day of week + + By setting `start_sunday` to true: + ![calendar_start_sunday](./calendar_start_sunday.png) + + - mouse support: + move to the next and previous month. Using mouse buttons or scroll wheel. + + You can configure this by specifying the button to move to next/previous. + Usually these are configured as follows. If you want to use other mouse buttons, you can find their number using `xev`. + + | number | button | + |--------|---------------| + | 4 | scroll up | + | 5 | scroll down | + | 1 | left click | + | 2 | right click | + | 3 | middles click | + + By default `previous_month_button` is 5, `next_month_button` is 4. + + +## How to use + +This widget needs an 'anchor' - another widget which triggers visibility of the calendar. Default `mytextclock` is the perfect candidate! +Just after mytextclock is instantiated, create the widget and add the mouse listener to it. + +```lua +local calendar_widget = require("awesome-wm-widgets.calendar-widget.calendar") +-- ... +-- Create a textclock widget +mytextclock = wibox.widget.textclock() +-- default +local cw = calendar_widget() +-- or customized +local cw = calendar_widget({ + theme = 'outrun', + placement = 'bottom_right', + start_sunday = true, + radius = 8, +-- with customized next/previous (see table above) + previous_month_button = 1, + next_month_button = 3, +}) +mytextclock:connect_signal("button::press", + function(_, _, _, button) + if button == 1 then cw.toggle() end + end) +``` diff --git a/awesome/awesome-wm-widgets/calendar-widget/calendar.lua b/awesome/awesome-wm-widgets/calendar-widget/calendar.lua new file mode 100644 index 0000000..bc4a877 --- /dev/null +++ b/awesome/awesome-wm-widgets/calendar-widget/calendar.lua @@ -0,0 +1,258 @@ +------------------------------------------------- +-- Calendar Widget for Awesome Window Manager +-- Shows the current month and supports scroll up/down to switch month +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/calendar-widget + +-- @author Pavel Makhov +-- @copyright 2019 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local beautiful = require("beautiful") +local wibox = require("wibox") +local gears = require("gears") +local naughty = require("naughty") + +local calendar_widget = {} + +local function worker(user_args) + + local calendar_themes = { + nord = { + bg = '#2E3440', + fg = '#D8DEE9', + focus_date_bg = '#88C0D0', + focus_date_fg = '#000000', + weekend_day_bg = '#3B4252', + weekday_fg = '#88C0D0', + header_fg = '#E5E9F0', + border = '#4C566A' + }, + outrun = { + bg = '#0d0221', + fg = '#D8DEE9', + focus_date_bg = '#650d89', + focus_date_fg = '#2de6e2', + weekend_day_bg = '#261447', + weekday_fg = '#2de6e2', + header_fg = '#f6019d', + border = '#261447' + }, + dark = { + bg = '#000000', + fg = '#ffffff', + focus_date_bg = '#ffffff', + focus_date_fg = '#000000', + weekend_day_bg = '#444444', + weekday_fg = '#ffffff', + header_fg = '#ffffff', + border = '#333333' + }, + light = { + bg = '#ffffff', + fg = '#000000', + focus_date_bg = '#000000', + focus_date_fg = '#ffffff', + weekend_day_bg = '#AAAAAA', + weekday_fg = '#000000', + header_fg = '#000000', + border = '#CCCCCC' + }, + monokai = { + bg = '#272822', + fg = '#F8F8F2', + focus_date_bg = '#AE81FF', + focus_date_fg = '#ffffff', + weekend_day_bg = '#75715E', + weekday_fg = '#FD971F', + header_fg = '#F92672', + border = '#75715E' + }, + naughty = { + bg = beautiful.notification_bg or beautiful.bg, + fg = beautiful.notification_fg or beautiful.fg, + focus_date_bg = beautiful.notification_fg or beautiful.fg, + focus_date_fg = beautiful.notification_bg or beautiful.bg, + weekend_day_bg = beautiful.bg_focus, + weekday_fg = beautiful.fg, + header_fg = beautiful.fg, + border = beautiful.border_normal + } + + } + + local args = user_args or {} + + if args.theme ~= nil and calendar_themes[args.theme] == nil then + naughty.notify({ + preset = naughty.config.presets.critical, + title = 'Calendar Widget', + text = 'Theme "' .. args.theme .. '" not found, fallback to default'}) + args.theme = 'naughty' + end + + local theme = args.theme or 'naughty' + local placement = args.placement or 'top' + local radius = args.radius or 8 + local next_month_button = args.next_month_button or 4 + local previous_month_button = args.previous_month_button or 5 + local start_sunday = args.start_sunday or false + + local styles = {} + local function rounded_shape(size) + return function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, size) + end + end + + styles.month = { + padding = 4, + bg_color = calendar_themes[theme].bg, + border_width = 0, + } + + styles.normal = { + markup = function(t) return t end, + shape = rounded_shape(4) + } + + styles.focus = { + fg_color = calendar_themes[theme].focus_date_fg, + bg_color = calendar_themes[theme].focus_date_bg, + markup = function(t) return '' .. t .. '' end, + shape = rounded_shape(4) + } + + styles.header = { + fg_color = calendar_themes[theme].header_fg, + bg_color = calendar_themes[theme].bg, + markup = function(t) return '' .. t .. '' end + } + + styles.weekday = { + fg_color = calendar_themes[theme].weekday_fg, + bg_color = calendar_themes[theme].bg, + markup = function(t) return '' .. t .. '' end, + } + + local function decorate_cell(widget, flag, date) + if flag == 'monthheader' and not styles.monthheader then + flag = 'header' + end + + -- highlight only today's day + if flag == 'focus' then + local today = os.date('*t') + if not (today.month == date.month and today.year == date.year) then + flag = 'normal' + end + end + + local props = styles[flag] or {} + if props.markup and widget.get_text and widget.set_markup then + widget:set_markup(props.markup(widget:get_text())) + end + -- Change bg color for weekends + local d = { year = date.year, month = (date.month or 1), day = (date.day or 1) } + local weekday = tonumber(os.date('%w', os.time(d))) + local default_bg = (weekday == 0 or weekday == 6) + and calendar_themes[theme].weekend_day_bg + or calendar_themes[theme].bg + local ret = wibox.widget { + { + { + widget, + halign = 'center', + widget = wibox.container.place + }, + margins = (props.padding or 2) + (props.border_width or 0), + widget = wibox.container.margin + }, + shape = props.shape, + shape_border_color = props.border_color or '#000000', + shape_border_width = props.border_width or 0, + fg = props.fg_color or calendar_themes[theme].fg, + bg = props.bg_color or default_bg, + widget = wibox.container.background + } + + return ret + end + + local cal = wibox.widget { + date = os.date('*t'), + font = beautiful.get_font(), + fn_embed = decorate_cell, + long_weekdays = true, + start_sunday = start_sunday, + widget = wibox.widget.calendar.month + } + + local popup = awful.popup { + ontop = true, + visible = false, + shape = rounded_shape(radius), + offset = { y = 5 }, + border_width = 1, + border_color = calendar_themes[theme].border, + widget = cal + } + + popup:buttons( + awful.util.table.join( + awful.button({}, next_month_button, function() + local a = cal:get_date() + a.month = a.month + 1 + cal:set_date(nil) + cal:set_date(a) + popup:set_widget(cal) + end), + awful.button({}, previous_month_button, function() + local a = cal:get_date() + a.month = a.month - 1 + cal:set_date(nil) + cal:set_date(a) + popup:set_widget(cal) + end) + ) + ) + + function calendar_widget.toggle() + + if popup.visible then + -- to faster render the calendar refresh it and just hide + cal:set_date(nil) -- the new date is not set without removing the old one + cal:set_date(os.date('*t')) + popup:set_widget(nil) -- just in case + popup:set_widget(cal) + popup.visible = not popup.visible + else + if placement == 'top' then + awful.placement.top(popup, { margins = { top = 30 }, parent = awful.screen.focused() }) + elseif placement == 'top_right' then + awful.placement.top_right(popup, { margins = { top = 30, right = 10}, parent = awful.screen.focused() }) + elseif placement == 'top_left' then + awful.placement.top_left(popup, { margins = { top = 30, left = 10}, parent = awful.screen.focused() }) + elseif placement == 'bottom_right' then + awful.placement.bottom_right(popup, { margins = { bottom = 30, right = 10}, + parent = awful.screen.focused() }) + elseif placement == 'bottom_left' then + awful.placement.bottom_left(popup, { margins = { bottom = 30, left = 10}, + parent = awful.screen.focused() }) + else + awful.placement.top(popup, { margins = { top = 30 }, parent = awful.screen.focused() }) + end + + popup.visible = true + + end + end + + return calendar_widget + +end + +return setmetatable(calendar_widget, { __call = function(_, ...) + return worker(...) +end }) diff --git a/awesome/awesome-wm-widgets/calendar-widget/calendar_bottom_right.png b/awesome/awesome-wm-widgets/calendar-widget/calendar_bottom_right.png new file mode 100644 index 0000000..2bc2e82 Binary files /dev/null and b/awesome/awesome-wm-widgets/calendar-widget/calendar_bottom_right.png differ diff --git a/awesome/awesome-wm-widgets/calendar-widget/calendar_start_sunday.png b/awesome/awesome-wm-widgets/calendar-widget/calendar_start_sunday.png new file mode 100644 index 0000000..126a218 Binary files /dev/null and b/awesome/awesome-wm-widgets/calendar-widget/calendar_start_sunday.png differ diff --git a/awesome/awesome-wm-widgets/calendar-widget/calendar_top.png b/awesome/awesome-wm-widgets/calendar-widget/calendar_top.png new file mode 100644 index 0000000..3e6b66b Binary files /dev/null and b/awesome/awesome-wm-widgets/calendar-widget/calendar_top.png differ diff --git a/awesome/awesome-wm-widgets/calendar-widget/calendar_top_right.png b/awesome/awesome-wm-widgets/calendar-widget/calendar_top_right.png new file mode 100644 index 0000000..4a29022 Binary files /dev/null and b/awesome/awesome-wm-widgets/calendar-widget/calendar_top_right.png differ diff --git a/awesome/awesome-wm-widgets/calendar-widget/dark.png b/awesome/awesome-wm-widgets/calendar-widget/dark.png new file mode 100644 index 0000000..540289f Binary files /dev/null and b/awesome/awesome-wm-widgets/calendar-widget/dark.png differ diff --git a/awesome/awesome-wm-widgets/calendar-widget/light.png b/awesome/awesome-wm-widgets/calendar-widget/light.png new file mode 100644 index 0000000..ab675d1 Binary files /dev/null and b/awesome/awesome-wm-widgets/calendar-widget/light.png differ diff --git a/awesome/awesome-wm-widgets/calendar-widget/nord.png b/awesome/awesome-wm-widgets/calendar-widget/nord.png new file mode 100644 index 0000000..94f9f7e Binary files /dev/null and b/awesome/awesome-wm-widgets/calendar-widget/nord.png differ diff --git a/awesome/awesome-wm-widgets/calendar-widget/outrun.png b/awesome/awesome-wm-widgets/calendar-widget/outrun.png new file mode 100644 index 0000000..d59c123 Binary files /dev/null and b/awesome/awesome-wm-widgets/calendar-widget/outrun.png differ diff --git a/awesome/awesome-wm-widgets/cpu-widget/README.md b/awesome/awesome-wm-widgets/cpu-widget/README.md new file mode 100644 index 0000000..b323f9b --- /dev/null +++ b/awesome/awesome-wm-widgets/cpu-widget/README.md @@ -0,0 +1,71 @@ +# CPU widget + +[![GitHub issues by-label](https://img.shields.io/github/issues-raw/streetturtle/awesome-wm-widgets/cpu)](https://github.com/streetturtle/awesome-wm-widgets/labels/cpu) + +This widget shows the average CPU load among all cores of the machine: + +![screenshot](./cpu.gif) + +## How it works + +To measure the load I took Paul Colby's bash [script](http://colby.id.au/calculating-cpu-usage-from-proc-stat/) and rewrote it in Lua, which was quite simple. +So awesome simply reads the first line of /proc/stat: + +```bash +$ cat /proc/stat | grep '^cpu ' +cpu 197294 718 50102 2002182 3844 0 2724 0 0 0 +``` + +and calculates the percentage. + +## Customization + +It is possible to customize widget by providing a table with all or some of the following config parameters: + +| Name | Default | Description | +|---|---|---| +| `width` | 50 | Width of the widget | +| `step_width` | 2 | Width of the step | +| `step_spacing` | 1 | Space size between steps | +| `color` | `beautiful.fg_normal` | Color of the graph | +| `enable_kill_button` | `false` | Show button which kills the process | +| `process_info_max_length` | `-1` | Truncate the process information. Some processes may have a very long list of parameters which won't fit in the screen, this options allows to truncate it to the given length. | +| `timeout` | 1 | How often in seconds the widget refreshes | + +### Example + +```lua +cpu_widget({ + width = 70, + step_width = 2, + step_spacing = 0, + color = '#434c5e' +}) +``` + +The config above results in the following widget: + +![custom](./custom.png) + +## Installation + +Clone/download repo and use widget in **rc.lua**: + +```lua +local cpu_widget = require("awesome-wm-widgets.cpu-widget.cpu-widget") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + -- default + cpu_widget(), + -- or custom + cpu_widget({ + width = 70, + step_width = 2, + step_spacing = 0, + color = '#434c5e' + }) + ... +``` diff --git a/awesome/awesome-wm-widgets/cpu-widget/cpu-widget.lua b/awesome/awesome-wm-widgets/cpu-widget/cpu-widget.lua new file mode 100644 index 0000000..11debe8 --- /dev/null +++ b/awesome/awesome-wm-widgets/cpu-widget/cpu-widget.lua @@ -0,0 +1,339 @@ +------------------------------------------------- +-- CPU Widget for Awesome Window Manager +-- Shows the current CPU utilization +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/cpu-widget + +-- @author Pavel Makhov +-- @copyright 2020 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local watch = require("awful.widget.watch") +local wibox = require("wibox") +local beautiful = require("beautiful") +local gears = require("gears") + +local CMD = [[sh -c "grep '^cpu.' /proc/stat; ps -eo '%p|%c|%C|' -o "%mem" -o '|%a' --sort=-%cpu ]] + .. [[| head -11 | tail -n +2"]] + +-- A smaller command, less resource intensive, used when popup is not shown. +local CMD_slim = [[grep --max-count=1 '^cpu.' /proc/stat]] + +local HOME_DIR = os.getenv("HOME") +local WIDGET_DIR = HOME_DIR .. '/.config/awesome/awesome-wm-widgets/cpu-widget' + +local cpu_widget = {} +local cpu_rows = { + spacing = 4, + layout = wibox.layout.fixed.vertical, +} +local is_update = true +local process_rows = { + layout = wibox.layout.fixed.vertical, +} + +-- Splits the string by separator +-- @return table with separated substrings +local function split(string_to_split, separator) + if separator == nil then separator = "%s" end + local t = {} + + for str in string.gmatch(string_to_split, "([^".. separator .."]+)") do + table.insert(t, str) + end + + return t +end + +-- Checks if a string starts with a another string +local function starts_with(str, start) + return str:sub(1, #start) == start +end + + +local function create_textbox(args) + return wibox.widget{ + text = args.text, + align = args.align or 'left', + markup = args.markup, + forced_width = args.forced_width or 40, + widget = wibox.widget.textbox + } +end + +local function create_process_header(params) + local res = wibox.widget{ + create_textbox{markup = 'PID'}, + create_textbox{markup = 'Name'}, + { + create_textbox{markup = '%CPU'}, + create_textbox{markup = '%MEM'}, + params.with_action_column and create_textbox{forced_width = 20} or nil, + layout = wibox.layout.align.horizontal + }, + layout = wibox.layout.ratio.horizontal + } + res:ajust_ratio(2, 0.2, 0.47, 0.33) + + return res +end + +local function create_kill_process_button() + return wibox.widget{ + { + id = "icon", + image = WIDGET_DIR .. '/window-close-symbolic.svg', + resize = false, + opacity = 0.1, + widget = wibox.widget.imagebox + }, + widget = wibox.container.background + } +end + +local function worker(user_args) + + local args = user_args or {} + + local width = args.width or 50 + local step_width = args.step_width or 2 + local step_spacing = args.step_spacing or 1 + local color = args.color or beautiful.fg_normal + local background_color = args.background_color or "#00000000" + local enable_kill_button = args.enable_kill_button or false + local process_info_max_length = args.process_info_max_length or -1 + local timeout = args.timeout or 1 + + local cpugraph_widget = wibox.widget { + max_value = 100, + background_color = background_color, + forced_width = width, + step_width = step_width, + step_spacing = step_spacing, + widget = wibox.widget.graph, + color = "linear:0,0:0,20:0,#FF0000:0.3,#FFFF00:0.6," .. color + } + + -- This timer periodically executes the heavy command while the popup is open. + -- It is stopped when the popup is closed and only the slim command is run then. + -- This greatly improves performance while the popup is closed at the small cost + -- of a slightly longer popup opening time. + local popup_timer = gears.timer { + timeout = timeout + } + + local popup = awful.popup{ + ontop = true, + visible = false, + shape = gears.shape.rounded_rect, + border_width = 1, + border_color = beautiful.bg_normal, + maximum_width = 300, + offset = { y = 5 }, + widget = {} + } + + -- Do not update process rows when mouse cursor is over the widget + popup:connect_signal("mouse::enter", function() is_update = false end) + popup:connect_signal("mouse::leave", function() is_update = true end) + + cpugraph_widget:buttons( + awful.util.table.join( + awful.button({}, 1, function() + if popup.visible then + popup.visible = not popup.visible + -- When the popup is not visible, stop the timer + popup_timer:stop() + else + popup:move_next_to(mouse.current_widget_geometry) + -- Restart the timer, when the popup becomes visible + -- Emit the signal to start the timer directly and not wait the timeout first + popup_timer:start() + popup_timer:emit_signal("timeout") + end + end) + ) + ) + + --- By default graph widget goes from left to right, so we mirror it and push up a bit + cpu_widget = wibox.widget { + { + cpugraph_widget, + reflection = {horizontal = true}, + layout = wibox.container.mirror + }, + bottom = 2, + color = background_color, + widget = wibox.container.margin + } + + -- This part runs constantly, also when the popup is closed. + -- It updates the graph widget in the bar. + local maincpu = {} + watch(CMD_slim, timeout, function(widget, stdout) + + local _, user, nice, system, idle, iowait, irq, softirq, steal, _, _ = + stdout:match('(%w+)%s+(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)') + + local total = user + nice + system + idle + iowait + irq + softirq + steal + + local diff_idle = idle - tonumber(maincpu['idle_prev'] == nil and 0 or maincpu['idle_prev']) + local diff_total = total - tonumber(maincpu['total_prev'] == nil and 0 or maincpu['total_prev']) + local diff_usage = (1000 * (diff_total - diff_idle) / diff_total + 5) / 10 + + maincpu['total_prev'] = total + maincpu['idle_prev'] = idle + + widget:add_value(diff_usage) + end, + cpugraph_widget + ) + + -- This part runs whenever the timer is fired. + -- It therefore only runs when the popup is open. + local cpus = {} + popup_timer:connect_signal('timeout', function() + awful.spawn.easy_async(CMD, function(stdout, _, _, _) + local i = 1 + local j = 1 + for line in stdout:gmatch("[^\r\n]+") do + if starts_with(line, 'cpu') then + + if cpus[i] == nil then cpus[i] = {} end + + local name, user, nice, system, idle, iowait, irq, softirq, steal, _, _ = + line:match('(%w+)%s+(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)') + + local total = user + nice + system + idle + iowait + irq + softirq + steal + + local diff_idle = idle - tonumber(cpus[i]['idle_prev'] == nil and 0 or cpus[i]['idle_prev']) + local diff_total = total - tonumber(cpus[i]['total_prev'] == nil and 0 or cpus[i]['total_prev']) + local diff_usage = (1000 * (diff_total - diff_idle) / diff_total + 5) / 10 + + cpus[i]['total_prev'] = total + cpus[i]['idle_prev'] = idle + + local row = wibox.widget + { + create_textbox{text = name}, + create_textbox{text = math.floor(diff_usage) .. '%'}, + { + max_value = 100, + value = diff_usage, + forced_height = 20, + forced_width = 150, + paddings = 1, + margins = 4, + border_width = 1, + border_color = beautiful.bg_focus, + background_color = beautiful.bg_normal, + bar_border_width = 1, + bar_border_color = beautiful.bg_focus, + color = "linear:150,0:0,0:0,#D08770:0.3,#BF616A:0.6," .. beautiful.fg_normal, + widget = wibox.widget.progressbar, + + }, + layout = wibox.layout.ratio.horizontal + } + row:ajust_ratio(2, 0.15, 0.15, 0.7) + cpu_rows[i] = row + i = i + 1 + else + if is_update == true then + + local columns = split(line, '|') + + local pid = columns[1] + local comm = columns[2] + local cpu = columns[3] + local mem = columns[4] + local cmd = columns[5] + + local kill_proccess_button = enable_kill_button and create_kill_process_button() or nil + + local pid_name_rest = wibox.widget{ + create_textbox{text = pid}, + create_textbox{text = comm}, + { + create_textbox{text = cpu, align = 'center'}, + create_textbox{text = mem, align = 'center'}, + kill_proccess_button, + layout = wibox.layout.fixed.horizontal + }, + layout = wibox.layout.ratio.horizontal + } + pid_name_rest:ajust_ratio(2, 0.2, 0.47, 0.33) + + local row = wibox.widget { + { + pid_name_rest, + top = 4, + bottom = 4, + widget = wibox.container.margin + }, + widget = wibox.container.background + } + + row:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end) + row:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end) + + if enable_kill_button then + row:connect_signal("mouse::enter", function() kill_proccess_button.icon.opacity = 1 end) + row:connect_signal("mouse::leave", function() kill_proccess_button.icon.opacity = 0.1 end) + + kill_proccess_button:buttons( + awful.util.table.join( awful.button({}, 1, function() + row:set_bg('#ff0000') + awful.spawn.with_shell('kill -9 ' .. pid) + end) ) ) + end + + awful.tooltip { + objects = { row }, + mode = 'outside', + preferred_positions = {'bottom'}, + timer_function = function() + local text = cmd + if process_info_max_length > 0 and text:len() > process_info_max_length then + text = text:sub(0, process_info_max_length - 3) .. '...' + end + + return text + :gsub('%s%-', '\n\t-') -- put arguments on a new line + :gsub(':/', '\n\t\t:/') -- java classpath uses : to separate jars + end, + } + + process_rows[j] = row + + j = j + 1 + end + + end + end + popup:setup { + { + cpu_rows, + { + orientation = 'horizontal', + forced_height = 15, + color = beautiful.bg_focus, + widget = wibox.widget.separator + }, + create_process_header{with_action_column = enable_kill_button}, + process_rows, + layout = wibox.layout.fixed.vertical, + }, + margins = 8, + widget = wibox.container.margin + } + end) + end) + + return cpu_widget +end + +return setmetatable(cpu_widget, { __call = function(_, ...) + return worker(...) +end }) diff --git a/awesome/awesome-wm-widgets/cpu-widget/cpu.gif b/awesome/awesome-wm-widgets/cpu-widget/cpu.gif new file mode 100644 index 0000000..cb97262 Binary files /dev/null and b/awesome/awesome-wm-widgets/cpu-widget/cpu.gif differ diff --git a/awesome/awesome-wm-widgets/cpu-widget/cpu.png b/awesome/awesome-wm-widgets/cpu-widget/cpu.png new file mode 100644 index 0000000..96ba29f Binary files /dev/null and b/awesome/awesome-wm-widgets/cpu-widget/cpu.png differ diff --git a/awesome/awesome-wm-widgets/cpu-widget/custom.png b/awesome/awesome-wm-widgets/cpu-widget/custom.png new file mode 100644 index 0000000..be275e4 Binary files /dev/null and b/awesome/awesome-wm-widgets/cpu-widget/custom.png differ diff --git a/awesome/awesome-wm-widgets/cpu-widget/window-close-symbolic.svg b/awesome/awesome-wm-widgets/cpu-widget/window-close-symbolic.svg new file mode 100644 index 0000000..46ff888 --- /dev/null +++ b/awesome/awesome-wm-widgets/cpu-widget/window-close-symbolic.svg @@ -0,0 +1,95 @@ + + + + + + + + Gnome Symbolic Icon Theme + + + + image/svg+xml + + Gnome Symbolic Icon Theme + + + + + + + + + + + + + + + + + + diff --git a/awesome/awesome-wm-widgets/email-widget/README.md b/awesome/awesome-wm-widgets/email-widget/README.md new file mode 100644 index 0000000..510792d --- /dev/null +++ b/awesome/awesome-wm-widgets/email-widget/README.md @@ -0,0 +1,36 @@ +# Email widget + +This widget consists of an icon with counter which shows number of unread emails: ![email icon](./em-wid-1.png) +and a popup message which appears when mouse hovers over an icon: ![email popup](./em-wid-2.png) + +Note that widget uses the Arc icon theme, so it should be [installed](https://github.com/horst3180/arc-icon-theme#installation) first under **/usr/share/icons/Arc/** folder. + +## Installation + +To install it put **email.lua** and **email-widget** folder under **~/.config/awesome**. Then + + - in **email.lua** change path to python scripts; + - in python scripts add your credentials (note that password should be encrypted using pgp for example); + - add widget to awesome: + +```lua +local email_widget, email_icon = require("email") + +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + email_icon, + email_widget, + ... +``` + +## How it works + +This widget uses the output of two python scripts, first is called every 20 seconds - it returns number of unread emails and second is called when mouse hovers over an icon and displays content of those emails. For both of them you'll need to provide your credentials and imap server. For testing, they can simply be called from console: + +``` bash +python ~/.config/awesome/email/count_unread_emails.py +python ~/.config/awesome/email/read_emails.py +``` diff --git a/awesome/awesome-wm-widgets/email-widget/count_unread_emails.py b/awesome/awesome-wm-widgets/email-widget/count_unread_emails.py new file mode 100644 index 0000000..a843814 --- /dev/null +++ b/awesome/awesome-wm-widgets/email-widget/count_unread_emails.py @@ -0,0 +1,16 @@ +#!/usr/bin/python + +import imaplib +import re + +M=imaplib.IMAP4_SSL("mail.teenagemutantninjaturtles.com", 993) +M.login("mickey@tmnt.com","cowabunga") + +status, counts = M.status("INBOX","(MESSAGES UNSEEN)") + +if status == "OK": + unread = re.search(r'UNSEEN\s(\d+)', counts[0].decode('utf-8')).group(1) +else: + unread = "N/A" + +print(unread) diff --git a/awesome/awesome-wm-widgets/email-widget/em-wid-1.png b/awesome/awesome-wm-widgets/email-widget/em-wid-1.png new file mode 100644 index 0000000..5290ea8 Binary files /dev/null and b/awesome/awesome-wm-widgets/email-widget/em-wid-1.png differ diff --git a/awesome/awesome-wm-widgets/email-widget/em-wid-2.png b/awesome/awesome-wm-widgets/email-widget/em-wid-2.png new file mode 100644 index 0000000..0a0fd3a Binary files /dev/null and b/awesome/awesome-wm-widgets/email-widget/em-wid-2.png differ diff --git a/awesome/awesome-wm-widgets/email-widget/email.lua b/awesome/awesome-wm-widgets/email-widget/email.lua new file mode 100644 index 0000000..df80678 --- /dev/null +++ b/awesome/awesome-wm-widgets/email-widget/email.lua @@ -0,0 +1,44 @@ +local wibox = require("wibox") +local awful = require("awful") +local naughty = require("naughty") +local watch = require("awful.widget.watch") + +local path_to_icons = "/usr/share/icons/Arc/actions/22/" + +local email_widget = wibox.widget.textbox() +email_widget:set_font('Play 9') + +local email_icon = wibox.widget.imagebox() +email_icon:set_image(path_to_icons .. "/mail-mark-new.png") + +watch( + "python /home//.config/awesome/email-widget/count_unread_emails.py", 20, + function(_, stdout) + local unread_emails_num = tonumber(stdout) or 0 + if (unread_emails_num > 0) then + email_icon:set_image(path_to_icons .. "/mail-mark-unread.png") + email_widget:set_text(stdout) + elseif (unread_emails_num == 0) then + email_icon:set_image(path_to_icons .. "/mail-message-new.png") + email_widget:set_text("") + end + end +) + + +local function show_emails() + awful.spawn.easy_async([[bash -c 'python /home//.config/awesome/email-widget/read_unread_emails.py']], + function(stdout) + naughty.notify{ + text = stdout, + title = "Unread Emails", + timeout = 5, hover_timeout = 0.5, + width = 400, + } + end + ) +end + +email_icon:connect_signal("mouse::enter", function() show_emails() end) + +return email_widget, email_icon diff --git a/awesome/awesome-wm-widgets/email-widget/read_unread_emails.py b/awesome/awesome-wm-widgets/email-widget/read_unread_emails.py new file mode 100644 index 0000000..fda8188 --- /dev/null +++ b/awesome/awesome-wm-widgets/email-widget/read_unread_emails.py @@ -0,0 +1,44 @@ +#!/usr/bin/python + +import imaplib +import email +import datetime + +def process_mailbox(M): + rv, data = M.search(None, "(UNSEEN)") + if rv != 'OK': + print "No messages found!" + return + + for num in data[0].split(): + rv, data = M.fetch(num, '(BODY.PEEK[])') + if rv != 'OK': + print "ERROR getting message", num + return + msg = email.message_from_bytes(data[0][1]) + for header in [ 'From', 'Subject', 'Date' ]: + hdr = email.header.make_header(email.header.decode_header(msg[header])) + if header == 'Date': + date_tuple = email.utils.parsedate_tz(str(hdr)) + if date_tuple: + local_date = datetime.datetime.fromtimestamp(email.utils.mktime_tz(date_tuple)) + print("{}: {}".format(header, local_date.strftime("%a, %d %b %Y %H:%M:%S"))) + else: + print('{}: {}'.format(header, hdr)) + # with code below you can process text of email + # if msg.is_multipart(): + # for payload in msg.get_payload(): + # if payload.get_content_maintype() == 'text': + # print payload.get_payload() + # else: + # print msg.get_payload() + + +M=imaplib.IMAP4_SSL("mail.teenagemutantninjaturtles.com", 993) +M.login("mickey@tmnt.com","cowabunga") + +rv, data = M.select("INBOX") +if rv == 'OK': + process_mailbox(M) +M.close() +M.logout() diff --git a/awesome/awesome-wm-widgets/fs-widget/README.md b/awesome/awesome-wm-widgets/fs-widget/README.md new file mode 100644 index 0000000..4657e9e --- /dev/null +++ b/awesome/awesome-wm-widgets/fs-widget/README.md @@ -0,0 +1,29 @@ +# Filesystem Widget + +This widget shows file system disk space usage which is based on the `df` output. When clicked another widget appears with more detailed information. By default, it monitors the "/" mount. It can be configured with a list of mounts to monitor though only the first will show in the wibar. To have multiple mounts displayed on the wibar simply define multiple `fs_widgets` with different mounts as arguments. + +![](./screenshot.png) + +## Customizations + +It is possible to customize widget by providing a table with all or some of the following config parameters: + +| Name | Default | Description | +|---|---|---| +| `mounts` | `{'/'}` | Table with mounts to monitor, check the output from a `df` command for available options (column 'Mounted on') | +| `timeout` | 60 | How often in seconds the widget refreshes | + +## Installation + +Clone/download repo and use the widget in **rc.lua**: + +```lua + local fs_widget = require("awesome-wm-widgets.fs-widget.fs-widget") + ... + s.mywibox:setup { + s.mytasklist, -- Middle widget + { -- Right widgets + fs_widget(), --default + fs_widget({ mounts = { '/', '/mnt/music' } }), -- multiple mounts + ... +``` diff --git a/awesome/awesome-wm-widgets/fs-widget/fs-widget.lua b/awesome/awesome-wm-widgets/fs-widget/fs-widget.lua new file mode 100644 index 0000000..ca76193 --- /dev/null +++ b/awesome/awesome-wm-widgets/fs-widget/fs-widget.lua @@ -0,0 +1,190 @@ +local awful = require("awful") +local watch = require("awful.widget.watch") +local wibox = require("wibox") +local beautiful = require("beautiful") +local gears = require("gears") + +local storage_bar_widget = {} + +--- Table with widget configuration, consists of three sections: +--- - general - general configuration +--- - widget - configuration of the widget displayed on the wibar +--- - popup - configuration of the popup +local config = {} + +-- general +config.mounts = { '/' } +config.refresh_rate = 60 + +-- wibar widget +config.widget_width = 40 +config.widget_bar_color = '#aaaaaa' +config.widget_onclick_bg = '#ff0000' +config.widget_border_color = '#535d6c66' +config.widget_background_color = '#22222233' + +-- popup +config.popup_bg = '#22222233' +config.popup_border_width = 1 +config.popup_border_color = '#535d6c66' +config.popup_bar_color = '#aaaaaa' +config.popup_bar_background_color = '#22222233' +config.popup_bar_border_color = '#535d6c66' + +local function worker(user_args) + local args = user_args or {} + + -- Setup config for the widget instance. + -- The `_config` table will keep the first existing value after checking + -- in this order: user parameter > beautiful > module default. + local _config = {} + for prop, value in pairs(config) do + _config[prop] = args[prop] or beautiful[prop] or value + end + + storage_bar_widget = wibox.widget { + { + id = 'progressbar', + color = _config.widget_bar_color, + max_value = 100, + forced_height = 20, + forced_width = _config.widget_width, + paddings = 2, + margins = 4, + border_width = 1, + border_radius = 2, + border_color = _config.widget_border_color, + background_color = _config.widget_background_color, + widget = wibox.widget.progressbar + }, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end, + widget = wibox.container.background, + set_value = function(self, new_value) + self:get_children_by_id("progressbar")[1].value = new_value + end + } + + local disk_rows = { + { widget = wibox.widget.textbox }, + spacing = 4, + layout = wibox.layout.fixed.vertical, + } + + local disk_header = wibox.widget { + { + markup = 'Mount', + forced_width = 150, + align = 'left', + widget = wibox.widget.textbox, + }, + { + markup = 'Used', + align = 'left', + widget = wibox.widget.textbox, + }, + layout = wibox.layout.ratio.horizontal + } + disk_header:ajust_ratio(1, 0, 0.3, 0.7) + + local popup = awful.popup { + bg = _config.popup_bg, + ontop = true, + visible = false, + shape = gears.shape.rounded_rect, + border_width = _config.popup_border_width, + border_color = _config.popup_border_color, + maximum_width = 400, + offset = { y = 5 }, + widget = {} + } + + storage_bar_widget:buttons( + awful.util.table.join( + awful.button({}, 1, function() + if popup.visible then + popup.visible = not popup.visible + storage_bar_widget:set_bg('#00000000') + else + storage_bar_widget:set_bg(_config.widget_background_color) + popup:move_next_to(mouse.current_widget_geometry) + end + end) + ) + ) + + local disks = {} + watch([[bash -c "df | tail -n +2"]], _config.refresh_rate, + function(widget, stdout) + for line in stdout:gmatch("[^\r\n$]+") do + local filesystem, size, used, avail, perc, mount = + line:match('([%p%w]+)%s+([%d%w]+)%s+([%d%w]+)%s+([%d%w]+)%s+([%d]+)%%%s+([%p%w]+)') + + disks[mount] = {} + disks[mount].filesystem = filesystem + disks[mount].size = size + disks[mount].used = used + disks[mount].avail = avail + disks[mount].perc = perc + disks[mount].mount = mount + + if disks[mount].mount == _config.mounts[1] then + widget:set_value(tonumber(disks[mount].perc)) + end + end + + for k, v in ipairs(_config.mounts) do + + local row = wibox.widget { + { + text = disks[v].mount, + forced_width = 150, + widget = wibox.widget.textbox + }, + { + color = _config.popup_bar_color, + max_value = 100, + value = tonumber(disks[v].perc), + forced_height = 20, + paddings = 1, + margins = 4, + border_width = 1, + border_color = _config.popup_bar_border_color, + background_color = _config.popup_bar_background_color, + bar_border_width = 1, + bar_border_color = _config.popup_bar_border_color, + widget = wibox.widget.progressbar, + }, + { + text = math.floor(disks[v].used / 1024 / 1024) + .. '/' + .. math.floor(disks[v].size / 1024 / 1024) .. 'GB(' + .. math.floor(disks[v].perc) .. '%)', + widget = wibox.widget.textbox + }, + layout = wibox.layout.ratio.horizontal + } + row:ajust_ratio(2, 0.3, 0.3, 0.4) + + disk_rows[k] = row + end + popup:setup { + { + disk_header, + disk_rows, + layout = wibox.layout.fixed.vertical, + }, + margins = 8, + widget = wibox.container.margin + } + end, + storage_bar_widget + ) + + return storage_bar_widget +end + +return setmetatable(storage_bar_widget, { __call = function(_, ...) + return worker(...) +end }) diff --git a/awesome/awesome-wm-widgets/fs-widget/screenshot.png b/awesome/awesome-wm-widgets/fs-widget/screenshot.png new file mode 100644 index 0000000..41e6ccc Binary files /dev/null and b/awesome/awesome-wm-widgets/fs-widget/screenshot.png differ diff --git a/awesome/awesome-wm-widgets/logout-menu-widget/README.md b/awesome/awesome-wm-widgets/logout-menu-widget/README.md new file mode 100644 index 0000000..6f8ca27 --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-menu-widget/README.md @@ -0,0 +1,45 @@ +# Logout Menu Widget + +This widget shows a menu with options to log out from the current session, lock, reboot, suspend and power off the computer, similar to [logout-popup-widget](https://github.com/streetturtle/awesome-wm-widgets/tree/master/logout-popup-widget): + +![demo](./logout-menu.gif) + +## Installation + +Clone this repo (if not cloned yet) under **./.config/awesome/** + +```bash +cd ./.config/awesome/ +git clone https://github.com/streetturtle/awesome-wm-widgets +``` +Then add the widget to the wibar: + +```lua +local logout_menu_widget = require("awesome-wm-widgets.logout-menu-widget.logout-menu") + +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + -- default + logout_menu_widget(), + -- custom + logout_menu_widget{ + font = 'Play 14', + onlock = function() awful.spawn.with_shell('i3lock-fancy') end + } + ... +``` + +## Customization + +It is possible to customize the widget by providing a table with all or some of the following config parameters: + +| Name | Default | Description | +|---|---|---| +| `font` | `beautiful.font` | Font of the menu items | +| `onlogout` | `function() awesome.quit() end` | Function which is called when the logout item is clicked | +| `onlock` | `function() awful.spawn.with_shell("i3lock") end` | Function which is called when the lock item is clicked | +| `onreboot` | `function() awful.spawn.with_shell("reboot") end` | Function which is called when the reboot item is clicked | +| `onsuspend` | `function() awful.spawn.with_shell("systemctl suspend") end` | Function which is called when the suspend item is clicked | +| `onpoweroff` | `function() awful.spawn.with_shell("shutdown now") end` | Function which is called when the poweroff item is clicked | diff --git a/awesome/awesome-wm-widgets/logout-menu-widget/icons/lock.svg b/awesome/awesome-wm-widgets/logout-menu-widget/icons/lock.svg new file mode 100644 index 0000000..3cfa528 --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-menu-widget/icons/lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/logout-menu-widget/icons/log-out.svg b/awesome/awesome-wm-widgets/logout-menu-widget/icons/log-out.svg new file mode 100644 index 0000000..77afebb --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-menu-widget/icons/log-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/logout-menu-widget/icons/moon.svg b/awesome/awesome-wm-widgets/logout-menu-widget/icons/moon.svg new file mode 100644 index 0000000..60e6ce8 --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-menu-widget/icons/moon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/logout-menu-widget/icons/power.svg b/awesome/awesome-wm-widgets/logout-menu-widget/icons/power.svg new file mode 100644 index 0000000..68b1be8 --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-menu-widget/icons/power.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/logout-menu-widget/icons/power_w.svg b/awesome/awesome-wm-widgets/logout-menu-widget/icons/power_w.svg new file mode 100644 index 0000000..1f9c4e3 --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-menu-widget/icons/power_w.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/logout-menu-widget/icons/refresh-cw.svg b/awesome/awesome-wm-widgets/logout-menu-widget/icons/refresh-cw.svg new file mode 100644 index 0000000..39f52a5 --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-menu-widget/icons/refresh-cw.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/logout-menu-widget/logout-menu.gif b/awesome/awesome-wm-widgets/logout-menu-widget/logout-menu.gif new file mode 100644 index 0000000..9f17b51 Binary files /dev/null and b/awesome/awesome-wm-widgets/logout-menu-widget/logout-menu.gif differ diff --git a/awesome/awesome-wm-widgets/logout-menu-widget/logout-menu.lua b/awesome/awesome-wm-widgets/logout-menu-widget/logout-menu.lua new file mode 100644 index 0000000..9a634f1 --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-menu-widget/logout-menu.lua @@ -0,0 +1,136 @@ +------------------------------------------------- +-- Logout Menu Widget for Awesome Window Manager +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/logout-menu-widget + +-- @author Pavel Makhov +-- @copyright 2020 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local wibox = require("wibox") +local gears = require("gears") +local beautiful = require("beautiful") + +local HOME = os.getenv('HOME') +local ICON_DIR = HOME .. '/.config/awesome/awesome-wm-widgets/logout-menu-widget/icons/' + +local logout_menu_widget = wibox.widget { + { + { + image = ICON_DIR .. 'power_w.svg', + resize = true, + widget = wibox.widget.imagebox, + }, + margins = 4, + layout = wibox.container.margin + }, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end, + widget = wibox.container.background, +} + +local popup = awful.popup { + ontop = true, + visible = false, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end, + border_width = 1, + border_color = beautiful.bg_focus, + maximum_width = 400, + offset = { y = 5 }, + widget = {} +} + +local function worker(user_args) + local rows = { layout = wibox.layout.fixed.vertical } + + local args = user_args or {} + + local font = args.font or beautiful.font + + local onlogout = args.onlogout or function () awesome.quit() end + local onlock = args.onlock or function() awful.spawn.with_shell("i3lock") end + local onreboot = args.onreboot or function() awful.spawn.with_shell("reboot") end + local onsuspend = args.onsuspend or function() awful.spawn.with_shell("systemctl suspend") end + local onpoweroff = args.onpoweroff or function() awful.spawn.with_shell("shutdown now") end + + local menu_items = { + { name = 'Log out', icon_name = 'log-out.svg', command = onlogout }, + { name = 'Lock', icon_name = 'lock.svg', command = onlock }, + { name = 'Reboot', icon_name = 'refresh-cw.svg', command = onreboot }, + { name = 'Suspend', icon_name = 'moon.svg', command = onsuspend }, + { name = 'Power off', icon_name = 'power.svg', command = onpoweroff }, + } + + for _, item in ipairs(menu_items) do + + local row = wibox.widget { + { + { + { + image = ICON_DIR .. item.icon_name, + resize = false, + widget = wibox.widget.imagebox + }, + { + text = item.name, + font = font, + widget = wibox.widget.textbox + }, + spacing = 12, + layout = wibox.layout.fixed.horizontal + }, + margins = 8, + layout = wibox.container.margin + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + } + + row:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end) + row:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end) + + local old_cursor, old_wibox + row:connect_signal("mouse::enter", function() + local wb = mouse.current_wibox + old_cursor, old_wibox = wb.cursor, wb + wb.cursor = "hand1" + end) + row:connect_signal("mouse::leave", function() + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end) + + row:buttons(awful.util.table.join(awful.button({}, 1, function() + popup.visible = not popup.visible + item.command() + end))) + + table.insert(rows, row) + end + popup:setup(rows) + + logout_menu_widget:buttons( + awful.util.table.join( + awful.button({}, 1, function() + if popup.visible then + popup.visible = not popup.visible + logout_menu_widget:set_bg('#00000000') + else + popup:move_next_to(mouse.current_widget_geometry) + logout_menu_widget:set_bg(beautiful.bg_focus) + end + end) + ) + ) + + return logout_menu_widget + +end + +return worker diff --git a/awesome/awesome-wm-widgets/logout-popup-widget/README.md b/awesome/awesome-wm-widgets/logout-popup-widget/README.md new file mode 100644 index 0000000..d95b692 --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-popup-widget/README.md @@ -0,0 +1,84 @@ +# Logout Popup Widget + +Widget which allows performing lock, reboot, log out, power off and sleep actions. It can be called either by a shortcut, or by clicking on a widget in wibar. + +

+ screenshot +

+ +When the widget is shown, following shortcuts can be used: + - Escape - hide widget + - s - shutdown + - r - reboot + - u - suspend + - k - lock + - l - log out + +# Installation + +Clone this (if not cloned yet) and the [awesome-buttons](https://github.com/streetturtle/awesome-buttons) repos under **./.config/awesome/** + +```bash +cd ./.config/awesome/ +git clone https://github.com/streetturtle/awesome-wm-widgets +git clone https://github.com/streetturtle/awesome-buttons +``` +Then + +- to show by a shortcut - define a shortcut in `globalkeys`: + + ```lua + local logout_popup = require("awesome-wm-widgets.logout-popup-widget.logout-popup") + ... + globalkeys = gears.table.join( + ... + awful.key({ modkey }, "l", function() logout_popup.launch() end, {description = "Show logout screen", group = "custom"}), + ``` + +- to show by clicking on a widget in wibar - add widget to the wibar: + + ```lua + local logout_popup = require("awesome-wm-widgets.logout-popup-widget.logout-popup") + + s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + logout_popup.widget{}, + ... + ``` + +# Customisation + +| Name | Default | Description | +|---|---|---| +| `icon` | `power.svg` | If used as widget - the path to the widget's icon | +| `icon_size` | `40` | Size of the icon | +| `icon_margin` | `16` | Margin around the icon | +| `bg_color` | `beautiful.bg_normal` | The color the background of the | +| `accent_color` | `beautiful.bg_focus` | The color of the buttons | +| `text_color` | `beautiful.fg_normal` | The color of text | +| `label_color` | `beautiful.fg_normal` | The color of the button's label | +| `phrases` | `{'Goodbye!'}` | The table with phrase(s) to show, if more than one provided, the phrase is chosen randomly. Leave empty (`{}`) to hide the phrase | +| `onlogout` | `function() awesome.quit() end` | Function which is called when the logout button is pressed | +| `onlock` | `function() awful.spawn.with_shell("systemctl suspend") end` | Function which is called when the lock button is pressed | +| `onreboot` | `function() awful.spawn.with_shell("reboot") end` | Function which is called when the reboot button is pressed | +| `onsuspend` | `function() awful.spawn.with_shell("systemctl suspend") end` | Function which is called when the suspend button is pressed | +| `onpoweroff` | `function() awful.spawn.with_shell("shutdown now") end` | Function which is called when the poweroff button is pressed | + +Some color themes for inspiration: + +![nord](./logout-nord.png) +![outrun](./logout-outrun.png) +![dark](./logout-dark.png) +![dracula](./logout-dracula.png) + +```lua +logout.launch{ + bg_color = "#261447", accent_color = "#ff4365", text_color = '#f706cf', icon_size = 40, icon_margin = 16, -- outrun + -- bg_color = "#0b0c10", accent_color = "#1f2833", text_color = '#66fce1', -- dark + -- bg_color = "#3B4252", accent_color = "#88C0D0", text_color = '#D8DEE9', -- nord + -- bg_color = "#282a36", accent_color = "#ff79c6", phrases = {}, -- dracula, no phrase + phrases = {"exit(0)", "Don't forget to be awesome.", "Yippee ki yay!"}, +} +``` diff --git a/awesome/awesome-wm-widgets/logout-popup-widget/logout-dark.png b/awesome/awesome-wm-widgets/logout-popup-widget/logout-dark.png new file mode 100644 index 0000000..06e7c9c Binary files /dev/null and b/awesome/awesome-wm-widgets/logout-popup-widget/logout-dark.png differ diff --git a/awesome/awesome-wm-widgets/logout-popup-widget/logout-dracula.png b/awesome/awesome-wm-widgets/logout-popup-widget/logout-dracula.png new file mode 100644 index 0000000..3c61c46 Binary files /dev/null and b/awesome/awesome-wm-widgets/logout-popup-widget/logout-dracula.png differ diff --git a/awesome/awesome-wm-widgets/logout-popup-widget/logout-nord.png b/awesome/awesome-wm-widgets/logout-popup-widget/logout-nord.png new file mode 100644 index 0000000..9ab4b55 Binary files /dev/null and b/awesome/awesome-wm-widgets/logout-popup-widget/logout-nord.png differ diff --git a/awesome/awesome-wm-widgets/logout-popup-widget/logout-outrun.png b/awesome/awesome-wm-widgets/logout-popup-widget/logout-outrun.png new file mode 100644 index 0000000..9be68b5 Binary files /dev/null and b/awesome/awesome-wm-widgets/logout-popup-widget/logout-outrun.png differ diff --git a/awesome/awesome-wm-widgets/logout-popup-widget/logout-popup.lua b/awesome/awesome-wm-widgets/logout-popup-widget/logout-popup.lua new file mode 100644 index 0000000..efe6882 --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-popup-widget/logout-popup.lua @@ -0,0 +1,187 @@ +------------------------------------------------- +-- Logout widget for Awesome Window Manager +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/logout-widget + +-- @author Pavel Makhov +-- @copyright 2020 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local capi = {keygrabber = keygrabber } +local wibox = require("wibox") +local gears = require("gears") +local beautiful = require("beautiful") +local awesomebuttons = require("awesome-buttons.awesome-buttons") + + +local HOME_DIR = os.getenv("HOME") +local WIDGET_DIR = HOME_DIR .. '/.config/awesome/awesome-wm-widgets/logout-popup-widget' + + +local w = wibox { + bg = beautiful.fg_normal, + max_widget_size = 500, + ontop = true, + height = 200, + width = 400, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 8) + end +} + +local action = wibox.widget { + text = ' ', + widget = wibox.widget.textbox +} + +local phrase_widget = wibox.widget{ + align = 'center', + widget = wibox.widget.textbox +} + +local function create_button(icon_name, action_name, accent_color, label_color, onclick, icon_size, icon_margin) + + local button = awesomebuttons.with_icon { + type = 'basic', + icon = icon_name, + color = accent_color, + icon_size = icon_size, + icon_margin = icon_margin, + onclick = function() + onclick() + w.visible = false + capi.keygrabber.stop() + end + } + button:connect_signal("mouse::enter", function() + action:set_markup('' .. action_name .. '') + end) + + button:connect_signal("mouse::leave", function() action:set_markup(' ') end) + + return button +end + +local function launch(args) + args = args or {} + + local bg_color = args.bg_color or beautiful.bg_normal + local accent_color = args.accent_color or beautiful.bg_focus + local text_color = args.text_color or beautiful.fg_normal + local label_color = args.label_color or beautiful.fg_focus + local phrases = args.phrases or {'Goodbye!'} + local icon_size = args.icon_size or 40 + local icon_margin = args.icon_margin or 16 + + local onlogout = args.onlogout or function () awesome.quit() end + local onlock = args.onlock or function() awful.spawn.with_shell("i3lock") end + local onreboot = args.onreboot or function() awful.spawn.with_shell("reboot") end + local onsuspend = args.onsuspend or function() awful.spawn.with_shell("systemctl suspend") end + local onpoweroff = args.onpoweroff or function() awful.spawn.with_shell("shutdown now") end + + w:set_bg(bg_color) + if #phrases > 0 then + phrase_widget:set_markup( + '' .. phrases[ math.random( #phrases ) ] .. '') + end + + w:setup { + { + phrase_widget, + { + { + create_button('log-out', 'Log Out (l)', + accent_color, label_color, onlogout, icon_size, icon_margin), + create_button('lock', 'Lock (k)', + accent_color, label_color, onlock, icon_size, icon_margin), + create_button('refresh-cw', 'Reboot (r)', + accent_color, label_color, onreboot, icon_size, icon_margin), + create_button('moon', 'Suspend (u)', + accent_color, label_color, onsuspend, icon_size, icon_margin), + create_button('power', 'Power Off (s)', + accent_color, label_color, onpoweroff, icon_size, icon_margin), + id = 'buttons', + spacing = 8, + layout = wibox.layout.fixed.horizontal + }, + valign = 'center', + layout = wibox.container.place + }, + { + action, + haligh = 'center', + layout = wibox.container.place + }, + spacing = 32, + layout = wibox.layout.fixed.vertical + }, + id = 'a', + shape_border_width = 1, + valign = 'center', + layout = wibox.container.place + } + + w.screen = mouse.screen + w.visible = true + + awful.placement.centered(w) + capi.keygrabber.run(function(_, key, event) + if event == "release" then return end + if key then + if key == 'Escape' then + phrase_widget:set_text('') + capi.keygrabber.stop() + w.visible = false + elseif key == 's' then onpoweroff() + elseif key == 'r' then onreboot() + elseif key == 'u' then onsuspend() + elseif key == 'k' then onlock() + elseif key == 'l' then onlogout() + end + + if key == 'Escape' or string.match("srukl", key) then + phrase_widget:set_text('') + capi.keygrabber.stop() + w.visible = false + end + end + end) +end + +local function widget(args) + local icon = args.icon or WIDGET_DIR .. '/power.svg' + + local res = wibox.widget { + { + { + image = icon, + widget = wibox.widget.imagebox + }, + margins = 4, + layout = wibox.container.margin + }, + layout = wibox.layout.fixed.horizontal, + } + + res:buttons( + awful.util.table.join( + awful.button({}, 1, function() + if w.visible then + phrase_widget:set_text('') + capi.keygrabber.stop() + w.visible = false + else + launch(args) + end + end) + )) + + return res + +end + +return { + launch = launch, + widget = widget +} diff --git a/awesome/awesome-wm-widgets/logout-popup-widget/power.svg b/awesome/awesome-wm-widgets/logout-popup-widget/power.svg new file mode 100644 index 0000000..1f9c4e3 --- /dev/null +++ b/awesome/awesome-wm-widgets/logout-popup-widget/power.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/logout-popup-widget/screenshot.gif b/awesome/awesome-wm-widgets/logout-popup-widget/screenshot.gif new file mode 100644 index 0000000..4975c19 Binary files /dev/null and b/awesome/awesome-wm-widgets/logout-popup-widget/screenshot.gif differ diff --git a/awesome/awesome-wm-widgets/logout-popup-widget/screenshot.png b/awesome/awesome-wm-widgets/logout-popup-widget/screenshot.png new file mode 100644 index 0000000..74ed7f0 Binary files /dev/null and b/awesome/awesome-wm-widgets/logout-popup-widget/screenshot.png differ diff --git a/awesome/awesome-wm-widgets/mpris-widget/README.md b/awesome/awesome-wm-widgets/mpris-widget/README.md new file mode 100644 index 0000000..7efad78 --- /dev/null +++ b/awesome/awesome-wm-widgets/mpris-widget/README.md @@ -0,0 +1,26 @@ +# MPRIS Widget (In progress) + +Music Player Info widget cy @mgabs + +# Prerequisite + +Install `playerctl` (mpris implementation), should be available in repo, e.g for Ubuntu: + +```bash +sudo apt-get install playerctl +``` + +## Installation + +To use this widget clone repo under **~/.config/awesome/** and then add it in **rc.lua**: + +```lua +local mpris_widget = require("awesome-wm-widgets.mpris-widget") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + mpris_widget(), + ... +``` diff --git a/awesome/awesome-wm-widgets/mpris-widget/init.lua b/awesome/awesome-wm-widgets/mpris-widget/init.lua new file mode 100644 index 0000000..5e45ffa --- /dev/null +++ b/awesome/awesome-wm-widgets/mpris-widget/init.lua @@ -0,0 +1,187 @@ +------------------------------------------------- +-- mpris based Arc Widget for Awesome Window Manager +-- Modelled after Pavel Makhov's work +-- @author Mohammed Gaber +-- requires - playerctl +-- @copyright 2020 +------------------------------------------------- +local awful = require("awful") +local beautiful = require("beautiful") +local watch = require("awful.widget.watch") +local wibox = require("wibox") +local gears = require("gears") + +local GET_MPD_CMD = "playerctl -p %s -f '{{status}};{{xesam:artist}};{{xesam:title}}' metadata" + +local TOGGLE_MPD_CMD = "playerctl play-pause" +local NEXT_MPD_CMD = "playerctl next" +local PREV_MPD_CMD = "playerctl previous" +local LIST_PLAYERS_CMD = "playerctl -l" + +local PATH_TO_ICONS = "/usr/share/icons/Arc" +local PAUSE_ICON_NAME = PATH_TO_ICONS .. "/actions/24/player_pause.png" +local PLAY_ICON_NAME = PATH_TO_ICONS .. "/actions/24/player_play.png" +local STOP_ICON_NAME = PATH_TO_ICONS .. "/actions/24/player_stop.png" +local LIBRARY_ICON_NAME = PATH_TO_ICONS .. "/actions/24/music-library.png" + +local default_player = '' + +local icon = wibox.widget { + id = "icon", + widget = wibox.widget.imagebox, + image = PLAY_ICON_NAME +} + +local mpris_widget = wibox.widget{ + { + id = 'artist', + widget = wibox.widget.textbox + }, + { + icon, + max_value = 1, + value = 0, + thickness = 2, + start_angle = 4.71238898, -- 2pi*3/4 + forced_height = 24, + forced_width = 24, + rounded_edge = true, + bg = "#ffffff11", + paddings = 0, + widget = wibox.container.arcchart + }, + { + id = 'title', + widget = wibox.widget.textbox + }, + layout = wibox.layout.fixed.horizontal, + set_text = function(self, artist, title) + self:get_children_by_id('artist')[1]:set_text(artist) + self:get_children_by_id('title')[1]:set_text(title) + end +} + +local rows = { layout = wibox.layout.fixed.vertical } + +local popup = awful.popup{ + bg = beautiful.bg_normal, + ontop = true, + visible = false, + shape = gears.shape.rounded_rect, + border_width = 1, + border_color = beautiful.bg_focus, + maximum_width = 400, + offset = { y = 5 }, + widget = {} +} + +local function rebuild_popup() + awful.spawn.easy_async(LIST_PLAYERS_CMD, function(stdout, _, _, _) + for i = 0, #rows do rows[i]=nil end + for player_name in stdout:gmatch("[^\r\n]+") do + if player_name ~='' and player_name ~=nil then + + local checkbox = wibox.widget{ + { + checked = player_name == default_player, + color = beautiful.bg_normal, + paddings = 2, + shape = gears.shape.circle, + forced_width = 20, + forced_height = 20, + check_color = beautiful.fg_urgent, + widget = wibox.widget.checkbox + }, + valign = 'center', + layout = wibox.container.place, + } + + checkbox:connect_signal("button::press", function() + default_player = player_name + rebuild_popup() + end) + + table.insert(rows, wibox.widget { + { + { + checkbox, + { + { + text = player_name, + align = 'left', + widget = wibox.widget.textbox + }, + left = 10, + layout = wibox.container.margin + }, + spacing = 8, + layout = wibox.layout.align.horizontal + }, + margins = 4, + layout = wibox.container.margin + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + }) + end + end + end) + + popup:setup(rows) +end + +local function worker() + + -- retrieve song info + local current_song, artist, player_status + + local update_graphic = function(widget, stdout, _, _, _) + local words = gears.string.split(stdout, ';') + player_status = words[1] + artist = words[2] + current_song = words[3] + if current_song ~= nil then + if string.len(current_song) > 18 then + current_song = string.sub(current_song, 0, 9) .. ".." + end + end + + if player_status == "Playing" then + icon.image = PLAY_ICON_NAME + widget.colors = {beautiful.widget_main_color} + widget:set_text(artist, current_song) + elseif player_status == "Paused" then + icon.image = PAUSE_ICON_NAME + widget.colors = {beautiful.widget_main_color} + widget:set_text(artist, current_song) + elseif player_status == "Stopped" then + icon.image = STOP_ICON_NAME + else -- no player is running + icon.image = LIBRARY_ICON_NAME + widget.colors = {beautiful.widget_red} + end + end + + mpris_widget:buttons( + awful.util.table.join( + awful.button({}, 3, function() + if popup.visible then + popup.visible = not popup.visible + else + rebuild_popup() + popup:move_next_to(mouse.current_widget_geometry) + end + end), + awful.button({}, 4, function() awful.spawn(NEXT_MPD_CMD, false) end), + awful.button({}, 5, function() awful.spawn(PREV_MPD_CMD, false) end), + awful.button({}, 1, function() awful.spawn(TOGGLE_MPD_CMD, false) end) + ) + ) + + watch(string.format(GET_MPD_CMD, "'" .. default_player .. "'"), 1, update_graphic, mpris_widget) + + return mpris_widget + +end + +return setmetatable(mpris_widget, {__call = function(_, ...) return worker(...) end}) diff --git a/awesome/awesome-wm-widgets/net-speed-widget/README.md b/awesome/awesome-wm-widgets/net-speed-widget/README.md new file mode 100644 index 0000000..a09893e --- /dev/null +++ b/awesome/awesome-wm-widgets/net-speed-widget/README.md @@ -0,0 +1,22 @@ +# Net Speed Widget + +The widget and readme is in progress + +## Installation + +Please refer to the [installation](https://github.com/streetturtle/awesome-wm-widgets#installation) section of the repo. + +Clone repo, include widget and use it in **rc.lua**: + +```lua +local net_speed_widget = require("awesome-wm-widgets.net-speed-widget.net-speed") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + net_speed_widget(), + ... + } + ... +``` diff --git a/awesome/awesome-wm-widgets/net-speed-widget/icons/down.svg b/awesome/awesome-wm-widgets/net-speed-widget/icons/down.svg new file mode 100644 index 0000000..9a98f39 --- /dev/null +++ b/awesome/awesome-wm-widgets/net-speed-widget/icons/down.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/awesome/awesome-wm-widgets/net-speed-widget/icons/up.svg b/awesome/awesome-wm-widgets/net-speed-widget/icons/up.svg new file mode 100644 index 0000000..e3c12a7 --- /dev/null +++ b/awesome/awesome-wm-widgets/net-speed-widget/icons/up.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/awesome/awesome-wm-widgets/net-speed-widget/net-speed.lua b/awesome/awesome-wm-widgets/net-speed-widget/net-speed.lua new file mode 100644 index 0000000..6dd3b05 --- /dev/null +++ b/awesome/awesome-wm-widgets/net-speed-widget/net-speed.lua @@ -0,0 +1,126 @@ +------------------------------------------------- +-- Net Speed Widget for Awesome Window Manager +-- Shows current upload/download speed +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/net-speed-widget + +-- @author Pavel Makhov +-- @copyright 2020 Pavel Makhov +------------------------------------------------- + +local watch = require("awful.widget.watch") +local wibox = require("wibox") + +local HOME_DIR = os.getenv("HOME") +local WIDGET_DIR = HOME_DIR .. '/.config/awesome/awesome-wm-widgets/net-speed-widget/' +local ICONS_DIR = WIDGET_DIR .. 'icons/' + +local net_speed_widget = {} + +local function convert_to_h(bytes) + local speed + local dim + local bits = bytes * 8 + if bits < 1000 then + speed = bits + dim = 'b/s' + elseif bits < 1000000 then + speed = bits/1000 + dim = 'kb/s' + elseif bits < 1000000000 then + speed = bits/1000000 + dim = 'mb/s' + elseif bits < 1000000000000 then + speed = bits/1000000000 + dim = 'gb/s' + else + speed = tonumber(bits) + dim = 'b/s' + end + return math.floor(speed + 0.5) .. dim +end + +local function split(string_to_split, separator) + if separator == nil then separator = "%s" end + local t = {} + + for str in string.gmatch(string_to_split, "([^".. separator .."]+)") do + table.insert(t, str) + end + + return t +end + +local function worker(user_args) + + local args = user_args or {} + + local interface = args.interface or '*' + local timeout = args.timeout or 1 + local width = args.width or 55 + + net_speed_widget = wibox.widget { + { + id = 'rx_speed', + forced_width = width, + align = 'right', + widget = wibox.widget.textbox + }, + { + image = ICONS_DIR .. 'down.svg', + widget = wibox.widget.imagebox + }, + { + image = ICONS_DIR .. 'up.svg', + widget = wibox.widget.imagebox + }, + { + id = 'tx_speed', + forced_width = width, + align = 'left', + widget = wibox.widget.textbox + }, + layout = wibox.layout.fixed.horizontal, + set_rx_text = function(self, new_rx_speed) + self:get_children_by_id('rx_speed')[1]:set_text(tostring(new_rx_speed)) + end, + set_tx_text = function(self, new_tx_speed) + self:get_children_by_id('tx_speed')[1]:set_text(tostring(new_tx_speed)) + end + } + + -- make sure these are not shared across different worker/widgets (e.g. two monitors) + -- otherwise the speed will be randomly split among the worker in each monitor + local prev_rx = 0 + local prev_tx = 0 + + local update_widget = function(widget, stdout) + + local cur_vals = split(stdout, '\r\n') + + local cur_rx = 0 + local cur_tx = 0 + + for i, v in ipairs(cur_vals) do + if i%2 == 1 then cur_rx = cur_rx + v end + if i%2 == 0 then cur_tx = cur_tx + v end + end + + local speed_rx = (cur_rx - prev_rx) / timeout + local speed_tx = (cur_tx - prev_tx) / timeout + + widget:set_rx_text(convert_to_h(speed_rx)) + widget:set_tx_text(convert_to_h(speed_tx)) + + prev_rx = cur_rx + prev_tx = cur_tx + end + + watch(string.format([[bash -c "cat /sys/class/net/%s/statistics/*_bytes"]], interface), + timeout, update_widget, net_speed_widget) + + return net_speed_widget + +end + +return setmetatable(net_speed_widget, { __call = function(_, ...) return worker(...) end }) diff --git a/awesome/awesome-wm-widgets/pactl-widget/README.md b/awesome/awesome-wm-widgets/pactl-widget/README.md new file mode 100644 index 0000000..ad6639b --- /dev/null +++ b/awesome/awesome-wm-widgets/pactl-widget/README.md @@ -0,0 +1,55 @@ +# Pactl volume widget + +This is a volume widget that uses `pactl` only for controlling volume and +selecting sinks and sources. Hence, it can be used with PulseAudio or PipeWire +likewise, unlike the original Volume widget. + +Other than that it is heavily based on the original widget, including its +customization and icon options. For screenshots, see the original widget. + +## Installation + +Clone the repo under **~/.config/awesome/** and add widget in **rc.lua**: + +```lua +local volume_widget = require('awesome-wm-widgets.pactl-widget.volume') +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + -- default + volume_widget(), + -- customized + volume_widget{ + widget_type = 'arc' + }, +``` + +### Shortcuts + +To improve responsiveness of the widget when volume level is changed by a shortcut use corresponding methods of the widget: + +```lua +awful.key({}, "XF86AudioRaiseVolume", function () volume_widget:inc(5) end), +awful.key({}, "XF86AudioLowerVolume", function () volume_widget:dec(5) end), +awful.key({}, "XF86AudioMute", function () volume_widget:toggle() end), +``` + +## Customization + +It is possible to customize the widget by providing a table with all or some of +the following config parameters: + +### Generic parameter + +| Name | Default | Description | +|---|---|---| +| `mixer_cmd` | `pavucontrol` | command to run on middle click (e.g. a mixer program) | +| `step` | `5` | How much the volume is raised or lowered at once (in %) | +| `widget_type`| `icon_and_text`| Widget type, one of `horizontal_bar`, `vertical_bar`, `icon`, `icon_and_text`, `arc` | +| `device` | `@DEFAULT_SINK@` | Select the device name to control | +| `tooltip` | `false` | Display volume level in a tooltip when the mouse cursor hovers the widget | + +For more details on parameters depending on the chosen widget type, please +refer to the original Volume widget. diff --git a/awesome/awesome-wm-widgets/pactl-widget/pactl.lua b/awesome/awesome-wm-widgets/pactl-widget/pactl.lua new file mode 100644 index 0000000..638dc7e --- /dev/null +++ b/awesome/awesome-wm-widgets/pactl-widget/pactl.lua @@ -0,0 +1,124 @@ +local spawn = require("awful.spawn") +local utils = require("awesome-wm-widgets.pactl-widget.utils") + +local pactl = {} + + +function pactl.volume_increase(device, step) + spawn('pactl set-sink-volume ' .. device .. ' +' .. step .. '%', false) +end + +function pactl.volume_decrease(device, step) + spawn('pactl set-sink-volume ' .. device .. ' -' .. step .. '%', false) +end + +function pactl.mute_toggle(device) + spawn('pactl set-sink-mute ' .. device .. ' toggle', false) +end + +function pactl.get_volume(device) + local stdout = utils.popen_and_return('pactl get-sink-volume ' .. device) + + local volsum, volcnt = 0, 0 + for vol in string.gmatch(stdout, "(%d?%d?%d)%%") do + vol = tonumber(vol) + if vol ~= nil then + volsum = volsum + vol + volcnt = volcnt + 1 + end + end + + if volcnt == 0 then + return nil + end + + return volsum / volcnt +end + +function pactl.get_mute(device) + local stdout = utils.popen_and_return('pactl get-sink-mute ' .. device) + if string.find(stdout, "yes") then + return true + else + return false + end +end + +function pactl.get_sinks_and_sources() + local default_sink = utils.trim(utils.popen_and_return('pactl get-default-sink')) + local default_source = utils.trim(utils.popen_and_return('pactl get-default-source')) + + local sinks = {} + local sources = {} + + local device + local ports + local key + local value + local in_section + + for line in utils.popen_and_return('pactl list'):gmatch('[^\r\n]*') do + + if string.match(line, '^%a+ #') then + in_section = nil + end + + local is_sink_line = string.match(line, '^Sink #') + local is_source_line = string.match(line, '^Source #') + + if is_sink_line or is_source_line then + in_section = "main" + + device = { + id = line:match('#(%d+)'), + is_default = false + } + if is_sink_line then + table.insert(sinks, device) + else + table.insert(sources, device) + end + end + + -- Found a new subsection + if in_section ~= nil and string.match(line, '^\t%a+:$') then + in_section = utils.trim(line):lower() + in_section = string.sub(in_section, 1, #in_section-1) + + if in_section == 'ports' then + ports = {} + device['ports'] = ports + end + end + + -- Found a key-value pair + if string.match(line, "^\t*[^\t]+: ") then + local t = utils.split(line, ':') + key = utils.trim(t[1]):lower():gsub(' ', '_') + value = utils.trim(t[2]) + end + + -- Key value pair on 1st level + if in_section ~= nil and string.match(line, "^\t[^\t]+: ") then + device[key] = value + + if key == "name" and (value == default_sink or value == default_source) then + device['is_default'] = true + end + end + + -- Key value pair in ports section + if in_section == "ports" and string.match(line, "^\t\t[^\t]+: ") then + ports[key] = value + end + end + + return sinks, sources +end + +function pactl.set_default(type, name) + spawn('pactl set-default-' .. type .. ' "' .. name .. '"', false) +end + + +return pactl diff --git a/awesome/awesome-wm-widgets/pactl-widget/utils.lua b/awesome/awesome-wm-widgets/pactl-widget/utils.lua new file mode 100644 index 0000000..52e7869 --- /dev/null +++ b/awesome/awesome-wm-widgets/pactl-widget/utils.lua @@ -0,0 +1,28 @@ +local utils = {} + + +function utils.trim(str) + return string.match(str, "^%s*(.-)%s*$") +end + +function utils.split(string_to_split, separator) + if separator == nil then separator = "%s" end + local t = {} + + for str in string.gmatch(string_to_split, "([^".. separator .."]+)") do + table.insert(t, str) + end + + return t +end + +function utils.popen_and_return(cmd) + local handle = io.popen(cmd) + local result = handle:read("*a") + handle:close() + + return result +end + + +return utils diff --git a/awesome/awesome-wm-widgets/pactl-widget/volume.lua b/awesome/awesome-wm-widgets/pactl-widget/volume.lua new file mode 100644 index 0000000..1c3108c --- /dev/null +++ b/awesome/awesome-wm-widgets/pactl-widget/volume.lua @@ -0,0 +1,243 @@ +------------------------------------------------- +-- A purely pactl-based volume widget based on the original Volume widget +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/pactl-widget + +-- @author Stefan Huber +-- @copyright 2023 Stefan Huber +------------------------------------------------- + +local awful = require("awful") +local wibox = require("wibox") +local spawn = require("awful.spawn") +local gears = require("gears") +local beautiful = require("beautiful") + +local pactl = require("awesome-wm-widgets.pactl-widget.pactl") +local utils = require("awesome-wm-widgets.pactl-widget.utils") + + +local widget_types = { + icon_and_text = require("awesome-wm-widgets.volume-widget.widgets.icon-and-text-widget"), + icon = require("awesome-wm-widgets.volume-widget.widgets.icon-widget"), + arc = require("awesome-wm-widgets.volume-widget.widgets.arc-widget"), + horizontal_bar = require("awesome-wm-widgets.volume-widget.widgets.horizontal-bar-widget"), + vertical_bar = require("awesome-wm-widgets.volume-widget.widgets.vertical-bar-widget") +} +local volume = {} + +local rows = { layout = wibox.layout.fixed.vertical } + +local popup = awful.popup{ + bg = beautiful.bg_normal, + ontop = true, + visible = false, + shape = gears.shape.rounded_rect, + border_width = 1, + border_color = beautiful.bg_focus, + maximum_width = 400, + offset = { y = 5 }, + widget = {} +} + +local function build_main_line(device) + if device.active_port ~= nil and device.ports[device.active_port] ~= nil then + return device.description .. ' · ' .. utils.split(device.ports[device.active_port], " ")[1] + else + return device.description + end +end + +local function build_rows(devices, on_checkbox_click, device_type) + local device_rows = { layout = wibox.layout.fixed.vertical } + for _, device in pairs(devices) do + + local checkbox = wibox.widget { + checked = device.is_default, + color = beautiful.bg_normal, + paddings = 2, + shape = gears.shape.circle, + forced_width = 20, + forced_height = 20, + check_color = beautiful.fg_urgent, + widget = wibox.widget.checkbox + } + + checkbox:connect_signal("button::press", function() + pactl.set_default(device_type, device.name) + on_checkbox_click() + end) + + local row = wibox.widget { + { + { + { + checkbox, + valign = 'center', + layout = wibox.container.place, + }, + { + { + text = build_main_line(device), + align = 'left', + widget = wibox.widget.textbox + }, + left = 10, + layout = wibox.container.margin + }, + spacing = 8, + layout = wibox.layout.align.horizontal + }, + margins = 4, + layout = wibox.container.margin + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + } + + row:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end) + row:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end) + + local old_cursor, old_wibox + row:connect_signal("mouse::enter", function() + local wb = mouse.current_wibox + old_cursor, old_wibox = wb.cursor, wb + wb.cursor = "hand1" + end) + row:connect_signal("mouse::leave", function() + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end) + + row:connect_signal("button::press", function() + pactl.set_default(device_type, device.name) + on_checkbox_click() + end) + + table.insert(device_rows, row) + end + + return device_rows +end + +local function build_header_row(text) + return wibox.widget{ + { + markup = "" .. text .. "", + align = 'center', + widget = wibox.widget.textbox + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + } +end + +local function rebuild_popup() + for i = 0, #rows do + rows[i]=nil + end + + local sinks, sources = pactl.get_sinks_and_sources() + table.insert(rows, build_header_row("SINKS")) + table.insert(rows, build_rows(sinks, function() rebuild_popup() end, "sink")) + table.insert(rows, build_header_row("SOURCES")) + table.insert(rows, build_rows(sources, function() rebuild_popup() end, "source")) + + popup:setup(rows) +end + +local function worker(user_args) + + local args = user_args or {} + + local mixer_cmd = args.mixer_cmd or 'pavucontrol' + local widget_type = args.widget_type + local refresh_rate = args.refresh_rate or 1 + local step = args.step or 5 + local device = args.device or '@DEFAULT_SINK@' + local tooltip = args.tooltip or false + + if widget_types[widget_type] == nil then + volume.widget = widget_types['icon_and_text'].get_widget(args.icon_and_text_args) + else + volume.widget = widget_types[widget_type].get_widget(args) + end + + local function update_graphic(widget) + local vol = pactl.get_volume(device) + if vol ~= nil then + widget:set_volume_level(vol) + end + + if pactl.get_mute(device) then + widget:mute() + else + widget:unmute() + end + end + + function volume:inc(s) + pactl.volume_increase(device, s or step) + update_graphic(volume.widget) + end + + function volume:dec(s) + pactl.volume_decrease(device, s or step) + update_graphic(volume.widget) + end + + function volume:toggle() + pactl.mute_toggle(device) + update_graphic(volume.widget) + end + + function volume:popup() + if popup.visible then + popup.visible = not popup.visible + else + rebuild_popup() + popup:move_next_to(mouse.current_widget_geometry) + end + end + + function volume:mixer() + if mixer_cmd then + spawn(mixer_cmd) + end + end + + volume.widget:buttons( + awful.util.table.join( + awful.button({}, 1, function() volume:toggle() end), + awful.button({}, 2, function() volume:mixer() end), + awful.button({}, 3, function() volume:popup() end), + awful.button({}, 4, function() volume:inc() end), + awful.button({}, 5, function() volume:dec() end) + ) + ) + + gears.timer { + timeout = refresh_rate, + call_now = true, + autostart = true, + callback = function() + update_graphic(volume.widget) + end + } + + if tooltip then + awful.tooltip { + objects = { volume.widget }, + timer_function = function() + return pactl.get_volume(device) .. " %" + end, + } + end + + return volume.widget +end + + +return setmetatable(volume, { __call = function(_, ...) return worker(...) end }) diff --git a/awesome/awesome-wm-widgets/ram-widget/README.md b/awesome/awesome-wm-widgets/ram-widget/README.md new file mode 100644 index 0000000..568245b --- /dev/null +++ b/awesome/awesome-wm-widgets/ram-widget/README.md @@ -0,0 +1,41 @@ +# Ram widget + +This widget shows the RAM usage. When clicked another widget appears with more detailed information: + +![screenshot](./out.gif) + +Note: this widget is compatible with Awesome v4.3+, as it is using [awful.popup](https://awesomewm.org/doc/api/classes/awful.popup.html) + +## Customization + +It is possible to customize widget by providing a table with all or some of the following config parameters: + +| Name | Default | Description | +|---|---|---| +| `color_used` | `beautiful.bg_urgent` | Color for used RAM | +| `color_free` | `beautiful.fg_normal` | Color for free RAM | +| `color_buf` | `beautiful.border_color_active` | Color for buffers/cache | +| `widget_height` | `25` | Height of the widget | +| `widget_width` | `25` | Width of the widget | +| `widget_show_buf` | `false` | Whether to display buffers/cache separately in the tray widget. If `false`, buffers/cache are considered free RAM. | +| `timeout` | 1 | How often (in seconds) the widget refreshes | + +## Installation + +Please refer to the [installation](https://github.com/streetturtle/awesome-wm-widgets#installation) section of the repo. + +Clone repo, include widget and use it in **rc.lua**: + +```lua +local ram_widget = require("awesome-wm-widgets.ram-widget.ram-widget") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + ram_widget(), + ... + } + ... +``` + diff --git a/awesome/awesome-wm-widgets/ram-widget/out.gif b/awesome/awesome-wm-widgets/ram-widget/out.gif new file mode 100644 index 0000000..736f894 Binary files /dev/null and b/awesome/awesome-wm-widgets/ram-widget/out.gif differ diff --git a/awesome/awesome-wm-widgets/ram-widget/ram-widget.lua b/awesome/awesome-wm-widgets/ram-widget/ram-widget.lua new file mode 100644 index 0000000..867d28e --- /dev/null +++ b/awesome/awesome-wm-widgets/ram-widget/ram-widget.lua @@ -0,0 +1,108 @@ +local awful = require("awful") +local beautiful = require("beautiful") +local gears = require("gears") +local watch = require("awful.widget.watch") +local wibox = require("wibox") + + +local ramgraph_widget = {} + + +local function worker(user_args) + local args = user_args or {} + local timeout = args.timeout or 1 + local color_used = args.color_used or beautiful.bg_urgent + local color_free = args.color_free or beautiful.fg_normal + local color_buf = args.color_buf or beautiful.border_color_active + local widget_show_buf = args.widget_show_buf or false + local widget_height = args.widget_height or 25 + local widget_width = args.widget_width or 25 + + --- Main ram widget shown on wibar + ramgraph_widget = wibox.widget { + border_width = 0, + colors = { + color_used, + color_free, + color_buf, + }, + display_labels = false, + forced_height = widget_height, + forced_width = widget_width, + widget = wibox.widget.piechart + } + + --- Widget which is shown when user clicks on the ram widget + local popup = awful.popup{ + ontop = true, + visible = false, + widget = { + widget = wibox.widget.piechart, + forced_height = 200, + forced_width = 400, + colors = { + color_used, + color_free, + color_buf, -- buf_cache + }, + }, + shape = gears.shape.rounded_rect, + border_color = beautiful.border_color_active, + border_width = 1, + offset = { y = 5 }, + } + + --luacheck:ignore 231 + local total, used, free, shared, buff_cache, available, total_swap, used_swap, free_swap + + local function getPercentage(value) + return math.floor(value / (total+total_swap) * 100 + 0.5) .. '%' + end + + watch('bash -c "LANGUAGE=en_US.UTF-8 free | grep -z Mem.*Swap.*"', timeout, + function(widget, stdout) + total, used, free, shared, buff_cache, available, total_swap, used_swap, free_swap = + stdout:match('(%d+)%s*(%d+)%s*(%d+)%s*(%d+)%s*(%d+)%s*(%d+)%s*Swap:%s*(%d+)%s*(%d+)%s*(%d+)') + + if widget_show_buf then + widget.data = { used, free, buff_cache } + else + widget.data = { used, total-used } + end + + if popup.visible then + popup:get_widget().data_list = { + {'used ' .. getPercentage(used + used_swap), used + used_swap}, + {'free ' .. getPercentage(free + free_swap), free + free_swap}, + {'buff_cache ' .. getPercentage(buff_cache), buff_cache} + } + end + end, + ramgraph_widget + ) + + ramgraph_widget:buttons( + awful.util.table.join( + awful.button({}, 1, function() + popup:get_widget().data_list = { + {'used ' .. getPercentage(used + used_swap), used + used_swap}, + {'free ' .. getPercentage(free + free_swap), free + free_swap}, + {'buff_cache ' .. getPercentage(buff_cache), buff_cache} + } + + if popup.visible then + popup.visible = not popup.visible + else + popup:move_next_to(mouse.current_widget_geometry) + end + end) + ) + ) + + return ramgraph_widget +end + + +return setmetatable(ramgraph_widget, { __call = function(_, ...) + return worker(...) +end }) diff --git a/awesome/awesome-wm-widgets/todo-widget/README.md b/awesome/awesome-wm-widgets/todo-widget/README.md new file mode 100644 index 0000000..c97d845 --- /dev/null +++ b/awesome/awesome-wm-widgets/todo-widget/README.md @@ -0,0 +1,28 @@ +# ToDo Widget + +This widget displays a list of todo items and allows marking item as done/undone, delete an item and create new ones: + +![screenshot](./todo.gif) + +# Installation + +Widget persists todo items as a JSON, so in order to simplify JSON serialisation/deserialisation download a **json.lua** from this repository: https://github.com/rxi/json.lua under `~/.config/awesone` folder. And don't forget to star a repo :) + +Then clone this repository under **~/.config/awesome/** and add the widget in **rc.lua**: + +```lua +local todo_widget = require("awesome-wm-widgets.todo-widget.todo") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + -- default + todo_widget(), + ... +``` +Also note that widget uses [Arc Icons](https://github.com/horst3180/arc-icon-theme) and expects them to be installed under `/usr/share/icons/Arc/`. + +# Theming + +Widget uses your theme's colors. In case you want to have different colors, without changing your theme, please create an issue for it. I'll extract them as widget parameters. diff --git a/awesome/awesome-wm-widgets/todo-widget/checkbox-checked-symbolic.svg b/awesome/awesome-wm-widgets/todo-widget/checkbox-checked-symbolic.svg new file mode 100644 index 0000000..afeca62 --- /dev/null +++ b/awesome/awesome-wm-widgets/todo-widget/checkbox-checked-symbolic.svg @@ -0,0 +1,148 @@ + + + + + + + + image/svg+xml + + Gnome Symbolic Icon Theme + + + + + + + Gnome Symbolic Icon Theme + + + + + + + + + + + + + + diff --git a/awesome/awesome-wm-widgets/todo-widget/chevron-down.svg b/awesome/awesome-wm-widgets/todo-widget/chevron-down.svg new file mode 100644 index 0000000..dceeb0f --- /dev/null +++ b/awesome/awesome-wm-widgets/todo-widget/chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/todo-widget/chevron-up.svg b/awesome/awesome-wm-widgets/todo-widget/chevron-up.svg new file mode 100644 index 0000000..88474ce --- /dev/null +++ b/awesome/awesome-wm-widgets/todo-widget/chevron-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/todo-widget/list-add-symbolic.svg b/awesome/awesome-wm-widgets/todo-widget/list-add-symbolic.svg new file mode 100644 index 0000000..9cc2d3a --- /dev/null +++ b/awesome/awesome-wm-widgets/todo-widget/list-add-symbolic.svg @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + diff --git a/awesome/awesome-wm-widgets/todo-widget/todo.gif b/awesome/awesome-wm-widgets/todo-widget/todo.gif new file mode 100644 index 0000000..7160e21 Binary files /dev/null and b/awesome/awesome-wm-widgets/todo-widget/todo.gif differ diff --git a/awesome/awesome-wm-widgets/todo-widget/todo.lua b/awesome/awesome-wm-widgets/todo-widget/todo.lua new file mode 100644 index 0000000..78ca262 --- /dev/null +++ b/awesome/awesome-wm-widgets/todo-widget/todo.lua @@ -0,0 +1,340 @@ +------------------------------------------------- +-- ToDo Widget for Awesome Window Manager +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/todo-widget + +-- @author Pavel Makhov +-- @copyright 2020 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local wibox = require("wibox") +local json = require("json") +local spawn = require("awful.spawn") +local gears = require("gears") +local beautiful = require("beautiful") +local gfs = require("gears.filesystem") + +local HOME_DIR = os.getenv("HOME") +local WIDGET_DIR = HOME_DIR .. '/.config/awesome/awesome-wm-widgets/todo-widget' +local STORAGE = HOME_DIR .. '/.cache/awmw/todo-widget/todos.json' + +local GET_TODO_ITEMS = 'bash -c "cat ' .. STORAGE .. '"' + +local rows = { layout = wibox.layout.fixed.vertical } +local todo_widget = {} +local update_widget +todo_widget.widget = wibox.widget { + { + { + { + { + id = "icon", + forced_height = 16, + forced_width = 16, + widget = wibox.widget.imagebox + }, + valign = 'center', + layout = wibox.container.place + }, + { + id = "txt", + widget = wibox.widget.textbox + }, + spacing = 4, + layout = wibox.layout.fixed.horizontal, + }, + margins = 4, + layout = wibox.container.margin + }, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end, + widget = wibox.container.background, + set_text = function(self, new_value) + self:get_children_by_id("txt")[1].text = new_value + end, + set_icon = function(self, new_value) + self:get_children_by_id("icon")[1].image = new_value + end +} + +function todo_widget:update_counter(todos) + local todo_count = 0 + for _,p in ipairs(todos) do + if not p.status then + todo_count = todo_count + 1 + end + end + + todo_widget.widget:set_text(todo_count) +end + +local popup = awful.popup{ + bg = beautiful.bg_normal, + ontop = true, + visible = false, + shape = gears.shape.rounded_rect, + border_width = 1, + border_color = beautiful.bg_focus, + maximum_width = 400, + offset = { y = 5 }, + widget = {} +} + +local add_button = wibox.widget { + { + { + image = WIDGET_DIR .. '/list-add-symbolic.svg', + resize = false, + widget = wibox.widget.imagebox + }, + top = 11, + left = 8, + right = 8, + layout = wibox.container.margin + }, + shape = function(cr, width, height) + gears.shape.circle(cr, width, height, 12) + end, + widget = wibox.container.background +} + +add_button:connect_signal("button::press", function() + local pr = awful.widget.prompt() + + table.insert(rows, wibox.widget { + { + { + pr.widget, + spacing = 8, + layout = wibox.layout.align.horizontal + }, + margins = 8, + layout = wibox.container.margin + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + }) + awful.prompt.run{ + prompt = "New item: ", + bg = beautiful.bg_normal, + bg_cursor = beautiful.fg_urgent, + textbox = pr.widget, + exe_callback = function(input_text) + if not input_text or #input_text == 0 then return end + spawn.easy_async(GET_TODO_ITEMS, function(stdout) + local res = json.decode(stdout) + table.insert(res.todo_items, {todo_item = input_text, status = false}) + spawn.easy_async_with_shell("echo '" .. json.encode(res) .. "' > " .. STORAGE, function() + spawn.easy_async(GET_TODO_ITEMS, function(items) update_widget(items) end) + end) + end) + end + } + popup:setup(rows) +end) +add_button:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end) +add_button:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end) + +local function worker(user_args) + + local args = user_args or {} + + local icon = args.icon or WIDGET_DIR .. '/checkbox-checked-symbolic.svg' + + todo_widget.widget:set_icon(icon) + + function update_widget(stdout) + local result = json.decode(stdout) + if result == nil or result == '' then result = {} end + todo_widget:update_counter(result.todo_items) + + for i = 0, #rows do rows[i]=nil end + + local first_row = wibox.widget { + { + {widget = wibox.widget.textbox}, + { + markup = 'ToDo', + align = 'center', + forced_width = 350, -- for horizontal alignment + forced_height = 40, + widget = wibox.widget.textbox + }, + add_button, + spacing = 8, + layout = wibox.layout.fixed.horizontal + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + } + + table.insert(rows, first_row) + + for i, todo_item in ipairs(result.todo_items) do + + local checkbox = wibox.widget { + checked = todo_item.status, + color = beautiful.bg_normal, + paddings = 2, + shape = gears.shape.circle, + forced_width = 20, + forced_height = 20, + check_color = beautiful.fg_urgent, + widget = wibox.widget.checkbox + } + + checkbox:connect_signal("button::press", function(c) + c:set_checked(not c.checked) + todo_item.status = not todo_item.status + result.todo_items[i] = todo_item + spawn.easy_async_with_shell("echo '" .. json.encode(result) .. "' > " .. STORAGE, function () + todo_widget:update_counter(result.todo_items) + end) + end) + + + local trash_button = wibox.widget { + { + { image = WIDGET_DIR .. '/window-close-symbolic.svg', + resize = false, + widget = wibox.widget.imagebox + }, + margins = 5, + layout = wibox.container.margin + }, + border_width = 1, + shape = function(cr, width, height) + gears.shape.circle(cr, width, height, 10) + end, + widget = wibox.container.background + } + + trash_button:connect_signal("button::press", function() + table.remove(result.todo_items, i) + spawn.easy_async_with_shell("printf '" .. json.encode(result) .. "' > " .. STORAGE, function () + spawn.easy_async(GET_TODO_ITEMS, function(items) update_widget(items) end) + end) + end) + + + local move_up = wibox.widget { + image = WIDGET_DIR .. '/chevron-up.svg', + resize = false, + widget = wibox.widget.imagebox + } + + move_up:connect_signal("button::press", function() + local temp = result.todo_items[i] + result.todo_items[i] = result.todo_items[i-1] + result.todo_items[i-1] = temp + spawn.easy_async_with_shell("printf '" .. json.encode(result) .. "' > " .. STORAGE, function () + spawn.easy_async(GET_TODO_ITEMS, function(items) update_widget(items) end) + end) + end) + + local move_down = wibox.widget { + image = WIDGET_DIR .. '/chevron-down.svg', + resize = false, + widget = wibox.widget.imagebox + } + + move_down:connect_signal("button::press", function() + local temp = result.todo_items[i] + result.todo_items[i] = result.todo_items[i+1] + result.todo_items[i+1] = temp + spawn.easy_async_with_shell("printf '" .. json.encode(result) .. "' > " .. STORAGE, function () + spawn.easy_async(GET_TODO_ITEMS, function(items) update_widget(items) end) + end) + end) + + + local move_buttons = { + layout = wibox.layout.fixed.vertical + } + + if i == 1 and #result.todo_items > 1 then + table.insert(move_buttons, move_down) + elseif i == #result.todo_items and #result.todo_items > 1 then + table.insert(move_buttons, move_up) + elseif #result.todo_items > 1 then + table.insert(move_buttons, move_up) + table.insert(move_buttons, move_down) + end + + local row = wibox.widget { + { + { + { + checkbox, + valign = 'center', + layout = wibox.container.place, + }, + { + { + text = todo_item.todo_item, + align = 'left', + widget = wibox.widget.textbox + }, + left = 10, + layout = wibox.container.margin + }, + { + { + move_buttons, + valign = 'center', + layout = wibox.container.place, + }, + { + trash_button, + valign = 'center', + layout = wibox.container.place, + }, + spacing = 8, + layout = wibox.layout.align.horizontal + }, + spacing = 8, + layout = wibox.layout.align.horizontal + }, + margins = 8, + layout = wibox.container.margin + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + } + + row:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end) + row:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end) + + table.insert(rows, row) + end + + popup:setup(rows) + end + + todo_widget.widget:buttons( + gears.table.join( + awful.button({}, 1, function() + if popup.visible then + todo_widget.widget:set_bg('#00000000') + popup.visible = not popup.visible + else + todo_widget.widget:set_bg(beautiful.bg_focus) + popup:move_next_to(mouse.current_widget_geometry) + end + end) + ) + ) + + spawn.easy_async(GET_TODO_ITEMS, function(stdout) update_widget(stdout) end) + + return todo_widget.widget +end + +if not gfs.file_readable(STORAGE) then + spawn.easy_async(string.format([[bash -c "dirname %s | xargs mkdir -p && echo '{\"todo_items\":{}}' > %s"]], + STORAGE, STORAGE)) +end + +return setmetatable(todo_widget, { __call = function(_, ...) return worker(...) end }) diff --git a/awesome/awesome-wm-widgets/todo-widget/window-close-symbolic.svg b/awesome/awesome-wm-widgets/todo-widget/window-close-symbolic.svg new file mode 100644 index 0000000..46ff888 --- /dev/null +++ b/awesome/awesome-wm-widgets/todo-widget/window-close-symbolic.svg @@ -0,0 +1,95 @@ + + + + + + + + Gnome Symbolic Icon Theme + + + + image/svg+xml + + Gnome Symbolic Icon Theme + + + + + + + + + + + + + + + + + + diff --git a/awesome/awesome-wm-widgets/volume-widget/README.md b/awesome/awesome-wm-widgets/volume-widget/README.md new file mode 100644 index 0000000..4fc7f55 --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/README.md @@ -0,0 +1,119 @@ +# Volume widget + +Volume widget based on [amixer](https://linux.die.net/man/1/amixer) (is used for controlling the audio volume) and [pacmd](https://linux.die.net/man/1/pacmd) (is used for selecting a sink/source). Also, the widget provides an easy way to customize how it looks, following types are supported out-of-the-box: + +![types](screenshots/variations.png) + +From left to right: `horizontal_bar`, `vertical_bar`, `icon`, `icon_and_text`, `arc` + +A right-click on the widget opens a popup where you can choose a sink/source: +![sink-sources](screenshots/volume-sink-sources.png) + +Left click toggles mute and middle click opens a mixer ([pavucontrol](https://freedesktop.org/software/pulseaudio/pavucontrol/) by default). + +### Features + + - switch between sinks/sources by right click on the widget; + - more responsive than previous versions of volume widget, which were refreshed once a second; + - 5 predefined customizable looks; + +## Installation + +Clone the repo under **~/.config/awesome/** and add widget in **rc.lua**: + +```lua +local volume_widget = require('awesome-wm-widgets.volume-widget.volume') +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + -- default + volume_widget(), + -- customized + volume_widget{ + widget_type = 'arc' + }, +``` + +Note that widget uses following command the get the current volume: `amixer -D pulse sget Master`, so please make sure that it works for you, otherwise you need to set parameter `device = 'default'`. + +### Shortcuts + +To improve responsiveness of the widget when volume level is changed by a shortcut use corresponding methods of the widget: + +```lua +awful.key({ modkey }, "]", function() volume_widget:inc(5) end), +awful.key({ modkey }, "[", function() volume_widget:dec(5) end), +awful.key({ modkey }, "\\", function() volume_widget:toggle() end), +``` + +## Customization + +It is possible to customize the widget by providing a table with all or some of the following config parameters: + +### Generic parameter + +| Name | Default | Description | +|---|---|---| +| `mixer_cmd` | `pavucontrol` | command to run on middle click (e.g. a mixer program) | +| `step` | `5` | How much the volume is raised or lowered at once (in %) | +| `widget_type`| `icon_and_text`| Widget type, one of `horizontal_bar`, `vertical_bar`, `icon`, `icon_and_text`, `arc` | +| `device` | `pulse` | Select the device name to control | + +Depends on the chosen widget type add parameters from the corresponding section below: + +#### `icon` parameters + +| Name | Default | Description | +|---|---|---| +| `icon_dir`| `./icons`| Path to the folder with icons | + +_Note:_ if you are changing icons, the folder should contain following .svg images: + - audio-volume-high-symbolic + - audio-volume-medium-symbolic + - audio-volume-low-symbolic + - audio-volume-muted-symbolic + +#### `icon_and_text` parameters + +| Name | Default | Description | +|---|---|---| +| `icon_dir`| `./icons`| Path to the folder with icons | +| `font` | `beautiful.font` | Font name and size, like `Play 12` | + +#### `arc` parameters + +| Name | Default | Description | +|---|---|---| +| `thickness` | 2 | Thickness of the arc | +| `main_color` | `beautiful.fg_color` | Color of the arc | +| `bg_color` | `#ffffff11` | Color of the arc's background | +| `mute_color` | `beautiful.fg_urgent` | Color of the arc when mute | +| `size` | 18 | Size of the widget | + +#### `horizontal_bar` parameters + +| Name | Default | Description | +|---|---|---| +| `main_color` | `beautiful.fg_normal` | Color of the bar | +| `mute_color` | `beautiful.fg_urgent` | Color of the bar when mute | +| `bg_color` | `'#ffffff11'` | Color of the bar's background | +| `width` | `50` | The bar width | +| `margins` | `10` | Top and bottom margins (if your wibar is 22 px high, bar will be 2 px = 22 - 2*10) | +| `shape` | `'bar'` | [gears.shape](https://awesomewm.org/doc/api/libraries/gears.shape.html), could be `octogon`, `hexagon`, `powerline`, etc | +| `with_icon` | `true` | Show volume icon| + +_Note:_ I didn't figure out how does the `forced_height` property of progressbar widget work (maybe it doesn't work at all), thus there is a workaround with margins. + +#### `vertical_bar` parameters + +| Name | Default | Description | +|---|---|---| +| `main_color` | `beautiful.fg_normal` | Color of the bar | +| `mute_color` | `beautiful.fg_urgent` | Color of the bar when mute | +| `bg_color` | `'#ffffff11'` | Color of the bar's background | +| `width` | `10` | The bar width | +| `margins` | `20` | Top and bottom margins (if your wibar is 22 px high, bar will be 2 px = 22 - 2*10) | +| `shape` | `'bar'` | [gears.shape](https://awesomewm.org/doc/api/libraries/gears.shape.html), could be `octogon`, `hexagon`, `powerline`, etc | +| `with_icon` | `true` | Show volume icon| diff --git a/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-high-symbolic.svg b/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-high-symbolic.svg new file mode 100644 index 0000000..985c107 --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-high-symbolic.svg @@ -0,0 +1,88 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-low-symbolic.svg b/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-low-symbolic.svg new file mode 100644 index 0000000..7eb4531 --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-low-symbolic.svg @@ -0,0 +1,88 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-medium-symbolic.svg b/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-medium-symbolic.svg new file mode 100644 index 0000000..11e44fe --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-medium-symbolic.svg @@ -0,0 +1,88 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-muted-symbolic.svg b/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-muted-symbolic.svg new file mode 100644 index 0000000..e577d05 --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/icons/audio-volume-muted-symbolic.svg @@ -0,0 +1,88 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/awesome/awesome-wm-widgets/volume-widget/screenshots/variations.png b/awesome/awesome-wm-widgets/volume-widget/screenshots/variations.png new file mode 100644 index 0000000..21d7ead Binary files /dev/null and b/awesome/awesome-wm-widgets/volume-widget/screenshots/variations.png differ diff --git a/awesome/awesome-wm-widgets/volume-widget/screenshots/volume-sink-sources.png b/awesome/awesome-wm-widgets/volume-widget/screenshots/volume-sink-sources.png new file mode 100644 index 0000000..7d010bc Binary files /dev/null and b/awesome/awesome-wm-widgets/volume-widget/screenshots/volume-sink-sources.png differ diff --git a/awesome/awesome-wm-widgets/volume-widget/utils.lua b/awesome/awesome-wm-widgets/volume-widget/utils.lua new file mode 100644 index 0000000..417a666 --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/utils.lua @@ -0,0 +1,105 @@ + + +local utils = {} + +local function split(string_to_split, separator) + if separator == nil then separator = "%s" end + local t = {} + + for str in string.gmatch(string_to_split, "([^".. separator .."]+)") do + table.insert(t, str) + end + + return t +end + +function utils.extract_sinks_and_sources(pacmd_output) + local sinks = {} + local sources = {} + local device + local properties + local ports + local in_sink = false + local in_source = false + local in_device = false + local in_properties = false + local in_ports = false + for line in pacmd_output:gmatch("[^\r\n]+") do + if string.match(line, 'source%(s%) available.') then + in_sink = false + in_source = true + end + if string.match(line, 'sink%(s%) available.') then + in_sink = true + in_source = false + end + + if string.match(line, 'index:') then + in_device = true + in_properties = false + device = { + id = line:match(': (%d+)'), + is_default = string.match(line, '*') ~= nil + } + if in_sink then + table.insert(sinks, device) + elseif in_source then + table.insert(sources, device) + end + end + + if string.match(line, '^\tproperties:') then + in_device = false + in_properties = true + properties = {} + device['properties'] = properties + end + + if string.match(line, 'ports:') then + in_device = false + in_properties = false + in_ports = true + ports = {} + device['ports'] = ports + end + + if string.match(line, 'active port:') then + in_device = false + in_properties = false + in_ports = false + device['active_port'] = line:match(': (.+)'):gsub('<',''):gsub('>','') + end + + if in_device then + local t = split(line, ': ') + local key = t[1]:gsub('\t+', ''):lower() + local value = t[2]:gsub('^<', ''):gsub('>$', '') + device[key] = value + end + + if in_properties then + local t = split(line, '=') + local key = t[1]:gsub('\t+', ''):gsub('%.', '_'):gsub('-', '_'):gsub(':', ''):gsub("%s+$", "") + local value + if t[2] == nil then + value = t[2] + else + value = t[2]:gsub('"', ''):gsub("^%s+", ""):gsub(' Analog Stereo', '') + end + properties[key] = value + end + + if in_ports then + local t = split(line, ': ') + local key = t[1] + if key ~= nil then + key = key:gsub('\t+', '') + end + ports[key] = t[2] + end + end + + return sinks, sources +end + +return utils \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/volume-widget/volume-2.svg b/awesome/awesome-wm-widgets/volume-widget/volume-2.svg new file mode 100644 index 0000000..10f1c67 --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/volume-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/volume-widget/volume.lua b/awesome/awesome-wm-widgets/volume-widget/volume.lua new file mode 100644 index 0000000..4c44042 --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/volume.lua @@ -0,0 +1,228 @@ +------------------------------------------------- +-- The Ultimate Volume Widget for Awesome Window Manager +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/volume-widget + +-- @author Pavel Makhov +-- @copyright 2020 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local wibox = require("wibox") +local spawn = require("awful.spawn") +local gears = require("gears") +local beautiful = require("beautiful") +local watch = require("awful.widget.watch") +local utils = require("awesome-wm-widgets.volume-widget.utils") + + +local LIST_DEVICES_CMD = [[sh -c "pacmd list-sinks; pacmd list-sources"]] +local function GET_VOLUME_CMD(device) return 'amixer -D ' .. device .. ' sget Master' end +local function INC_VOLUME_CMD(device, step) return 'amixer -D ' .. device .. ' sset Master ' .. step .. '%+' end +local function DEC_VOLUME_CMD(device, step) return 'amixer -D ' .. device .. ' sset Master ' .. step .. '%-' end +local function TOG_VOLUME_CMD(device) return 'amixer -D ' .. device .. ' sset Master toggle' end + + +local widget_types = { + icon_and_text = require("awesome-wm-widgets.volume-widget.widgets.icon-and-text-widget"), + icon = require("awesome-wm-widgets.volume-widget.widgets.icon-widget"), + arc = require("awesome-wm-widgets.volume-widget.widgets.arc-widget"), + horizontal_bar = require("awesome-wm-widgets.volume-widget.widgets.horizontal-bar-widget"), + vertical_bar = require("awesome-wm-widgets.volume-widget.widgets.vertical-bar-widget") +} +local volume = {} + +local rows = { layout = wibox.layout.fixed.vertical } + +local popup = awful.popup{ + bg = beautiful.bg_normal, + ontop = true, + visible = false, + shape = gears.shape.rounded_rect, + border_width = 1, + border_color = beautiful.bg_focus, + maximum_width = 400, + offset = { y = 5 }, + widget = {} +} + +local function build_main_line(device) + if device.active_port ~= nil and device.ports[device.active_port] ~= nil then + return device.properties.device_description .. ' · ' .. device.ports[device.active_port] + else + return device.properties.device_description + end +end + +local function build_rows(devices, on_checkbox_click, device_type) + local device_rows = { layout = wibox.layout.fixed.vertical } + for _, device in pairs(devices) do + + local checkbox = wibox.widget { + checked = device.is_default, + color = beautiful.bg_normal, + paddings = 2, + shape = gears.shape.circle, + forced_width = 20, + forced_height = 20, + check_color = beautiful.fg_urgent, + widget = wibox.widget.checkbox + } + + checkbox:connect_signal("button::press", function() + spawn.easy_async(string.format([[sh -c 'pacmd set-default-%s "%s"']], device_type, device.name), function() + on_checkbox_click() + end) + end) + + local row = wibox.widget { + { + { + { + checkbox, + valign = 'center', + layout = wibox.container.place, + }, + { + { + text = build_main_line(device), + align = 'left', + widget = wibox.widget.textbox + }, + left = 10, + layout = wibox.container.margin + }, + spacing = 8, + layout = wibox.layout.align.horizontal + }, + margins = 4, + layout = wibox.container.margin + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + } + + row:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end) + row:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end) + + local old_cursor, old_wibox + row:connect_signal("mouse::enter", function() + local wb = mouse.current_wibox + old_cursor, old_wibox = wb.cursor, wb + wb.cursor = "hand1" + end) + row:connect_signal("mouse::leave", function() + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end) + + row:connect_signal("button::press", function() + spawn.easy_async(string.format([[sh -c 'pacmd set-default-%s "%s"']], device_type, device.name), function() + on_checkbox_click() + end) + end) + + table.insert(device_rows, row) + end + + return device_rows +end + +local function build_header_row(text) + return wibox.widget{ + { + markup = "" .. text .. "", + align = 'center', + widget = wibox.widget.textbox + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + } +end + +local function rebuild_popup() + spawn.easy_async(LIST_DEVICES_CMD, function(stdout) + + local sinks, sources = utils.extract_sinks_and_sources(stdout) + + for i = 0, #rows do rows[i]=nil end + + table.insert(rows, build_header_row("SINKS")) + table.insert(rows, build_rows(sinks, function() rebuild_popup() end, "sink")) + table.insert(rows, build_header_row("SOURCES")) + table.insert(rows, build_rows(sources, function() rebuild_popup() end, "source")) + + popup:setup(rows) + end) +end + + +local function worker(user_args) + + local args = user_args or {} + + local mixer_cmd = args.mixer_cmd or 'pavucontrol' + local widget_type = args.widget_type + local refresh_rate = args.refresh_rate or 1 + local step = args.step or 5 + local device = args.device or 'pulse' + + if widget_types[widget_type] == nil then + volume.widget = widget_types['icon_and_text'].get_widget(args.icon_and_text_args) + else + volume.widget = widget_types[widget_type].get_widget(args) + end + + local function update_graphic(widget, stdout) + local mute = string.match(stdout, "%[(o%D%D?)%]") -- \[(o\D\D?)\] - [on] or [off] + if mute == 'off' then widget:mute() + elseif mute == 'on' then widget:unmute() + end + local volume_level = string.match(stdout, "(%d?%d?%d)%%") -- (\d?\d?\d)\%) + volume_level = string.format("% 3d", volume_level) + widget:set_volume_level(volume_level) + end + + function volume:inc(s) + spawn.easy_async(INC_VOLUME_CMD(device, s or step), function(stdout) update_graphic(volume.widget, stdout) end) + end + + function volume:dec(s) + spawn.easy_async(DEC_VOLUME_CMD(device, s or step), function(stdout) update_graphic(volume.widget, stdout) end) + end + + function volume:toggle() + spawn.easy_async(TOG_VOLUME_CMD(device), function(stdout) update_graphic(volume.widget, stdout) end) + end + + function volume:mixer() + if mixer_cmd then + spawn.easy_async(mixer_cmd) + end + end + + volume.widget:buttons( + awful.util.table.join( + awful.button({}, 3, function() + if popup.visible then + popup.visible = not popup.visible + else + rebuild_popup() + popup:move_next_to(mouse.current_widget_geometry) + end + end), + awful.button({}, 4, function() volume:inc() end), + awful.button({}, 5, function() volume:dec() end), + awful.button({}, 2, function() volume:mixer() end), + awful.button({}, 1, function() volume:toggle() end) + ) + ) + + watch(GET_VOLUME_CMD(device), refresh_rate, update_graphic, volume.widget) + + return volume.widget +end + +return setmetatable(volume, { __call = function(_, ...) return worker(...) end }) diff --git a/awesome/awesome-wm-widgets/volume-widget/widgets/arc-widget.lua b/awesome/awesome-wm-widgets/volume-widget/widgets/arc-widget.lua new file mode 100644 index 0000000..b512f12 --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/widgets/arc-widget.lua @@ -0,0 +1,46 @@ +local wibox = require("wibox") +local beautiful = require('beautiful') + +local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/volume-widget/icons/' + +local widget = {} + +function widget.get_widget(widgets_args) + local args = widgets_args or {} + + local thickness = args.thickness or 2 + local main_color = args.main_color or beautiful.fg_color + local bg_color = args.bg_color or '#ffffff11' + local mute_color = args.mute_color or beautiful.fg_urgent + local size = args.size or 18 + + return wibox.widget { + { + id = "icon", + image = ICON_DIR .. 'audio-volume-high-symbolic.svg', + resize = true, + widget = wibox.widget.imagebox, + }, + max_value = 100, + thickness = thickness, + start_angle = 4.71238898, -- 2pi*3/4 + forced_height = size, + forced_width = size, + bg = bg_color, + paddings = 2, + widget = wibox.container.arcchart, + set_volume_level = function(self, new_value) + self.value = new_value + end, + mute = function(self) + self.colors = { mute_color } + end, + unmute = function(self) + self.colors = { main_color } + end + } + +end + + +return widget \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/volume-widget/widgets/horizontal-bar-widget.lua b/awesome/awesome-wm-widgets/volume-widget/widgets/horizontal-bar-widget.lua new file mode 100644 index 0000000..be1f38d --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/widgets/horizontal-bar-widget.lua @@ -0,0 +1,58 @@ +local wibox = require("wibox") +local beautiful = require('beautiful') +local gears = require("gears") + +local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/volume-widget/icons/' + +local widget = {} + +function widget.get_widget(widgets_args) + local args = widgets_args or {} + + local main_color = args.main_color or beautiful.fg_normal + local mute_color = args.mute_color or beautiful.fg_urgent + local bg_color = args.bg_color or '#ffffff11' + local width = args.width or 50 + local margins = args.margins or 10 + local shape = args.shape or 'bar' + local with_icon = args.with_icon == true and true or false + + local bar = wibox.widget { + { + { + id = "icon", + image = ICON_DIR .. 'audio-volume-high-symbolic.svg', + resize = false, + widget = wibox.widget.imagebox, + }, + valign = 'center', + visible = with_icon, + layout = wibox.container.place, + }, + { + id = 'bar', + max_value = 100, + forced_width = width, + color = main_color, + margins = { top = margins, bottom = margins }, + background_color = bg_color, + shape = gears.shape[shape], + widget = wibox.widget.progressbar, + }, + spacing = 4, + layout = wibox.layout.fixed.horizontal, + set_volume_level = function(self, new_value) + self:get_children_by_id('bar')[1]:set_value(tonumber(new_value)) + end, + mute = function(self) + self:get_children_by_id('bar')[1]:set_color(mute_color) + end, + unmute = function(self) + self:get_children_by_id('bar')[1]:set_color(main_color) + end + } + + return bar +end + +return widget diff --git a/awesome/awesome-wm-widgets/volume-widget/widgets/icon-and-text-widget.lua b/awesome/awesome-wm-widgets/volume-widget/widgets/icon-and-text-widget.lua new file mode 100644 index 0000000..b1a2793 --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/widgets/icon-and-text-widget.lua @@ -0,0 +1,59 @@ +local wibox = require("wibox") +local beautiful = require('beautiful') + +local widget = {} + +local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/volume-widget/icons/' + +function widget.get_widget(widgets_args) + local args = widgets_args or {} + + local font = args.font or beautiful.font + local icon_dir = args.icon_dir or ICON_DIR + + return wibox.widget { + { + { + id = "icon", + resize = false, + widget = wibox.widget.imagebox, + }, + valign = 'center', + layout = wibox.container.place + }, + { + id = 'txt', + font = font, + widget = wibox.widget.textbox + }, + layout = wibox.layout.fixed.horizontal, + set_volume_level = function(self, new_value) + self:get_children_by_id('txt')[1]:set_text(new_value) + local volume_icon_name + if self.is_muted then + volume_icon_name = 'audio-volume-muted-symbolic' + else + local new_value_num = tonumber(new_value) + if (new_value_num >= 0 and new_value_num < 33) then + volume_icon_name="audio-volume-low-symbolic" + elseif (new_value_num < 66) then + volume_icon_name="audio-volume-medium-symbolic" + else + volume_icon_name="audio-volume-high-symbolic" + end + end + self:get_children_by_id('icon')[1]:set_image(icon_dir .. volume_icon_name .. '.svg') + end, + mute = function(self) + self.is_muted = true + self:get_children_by_id('icon')[1]:set_image(icon_dir .. 'audio-volume-muted-symbolic.svg') + end, + unmute = function(self) + self.is_muted = false + end + } + +end + + +return widget \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/volume-widget/widgets/icon-widget.lua b/awesome/awesome-wm-widgets/volume-widget/widgets/icon-widget.lua new file mode 100644 index 0000000..cc39a3d --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/widgets/icon-widget.lua @@ -0,0 +1,46 @@ +local wibox = require("wibox") + +local widget = {} + +local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/volume-widget/icons/' + +function widget.get_widget(widgets_args) + local args = widgets_args or {} + + local icon_dir = args.icon_dir or ICON_DIR + + return wibox.widget { + { + id = "icon", + resize = false, + widget = wibox.widget.imagebox, + }, + valign = 'center', + layout = wibox.container.place, + set_volume_level = function(self, new_value) + local volume_icon_name + if self.is_muted then + volume_icon_name = 'audio-volume-muted-symbolic' + else + local new_value_num = tonumber(new_value) + if (new_value_num >= 0 and new_value_num < 33) then + volume_icon_name="audio-volume-low-symbolic" + elseif (new_value_num < 66) then + volume_icon_name="audio-volume-medium-symbolic" + else + volume_icon_name="audio-volume-high-symbolic" + end + end + self:get_children_by_id('icon')[1]:set_image(icon_dir .. volume_icon_name .. '.svg') + end, + mute = function(self) + self.is_muted = true + self:get_children_by_id('icon')[1]:set_image(icon_dir .. 'audio-volume-muted-symbolic.svg') + end, + unmute = function(self) + self.is_muted = false + end + } +end + +return widget \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/volume-widget/widgets/vertical-bar-widget.lua b/awesome/awesome-wm-widgets/volume-widget/widgets/vertical-bar-widget.lua new file mode 100644 index 0000000..6f32b50 --- /dev/null +++ b/awesome/awesome-wm-widgets/volume-widget/widgets/vertical-bar-widget.lua @@ -0,0 +1,64 @@ +local wibox = require("wibox") +local beautiful = require('beautiful') +local gears = require("gears") + +local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/volume-widget/icons/' + +local widget = {} + +function widget.get_widget(widgets_args) + local args = widgets_args or {} + + local main_color = args.main_color or beautiful.fg_normal + local mute_color = args.mute_color or beautiful.fg_urgent + local bg_color = args.bg_color or '#ffffff11' + local width = args.width or 10 + local margins = args.height or 2 + local shape = args.shape or 'bar' + local with_icon = args.with_icon == true and true or false + + local bar = wibox.widget { + { + { + id = "icon", + image = ICON_DIR .. 'audio-volume-high-symbolic.svg', + resize = false, + widget = wibox.widget.imagebox, + }, + valign = 'center', + visible = with_icon, + layout = wibox.container.place, + }, + { + { + id = 'bar', + max_value = 100, + forced_width = width, + forced_height = 5, + margins = { top = margins, bottom = margins }, + color = main_color, + background_color = bg_color, + shape = gears.shape[shape], + widget = wibox.widget.progressbar, + }, + forced_width = width, + direction = 'east', + layout = wibox.container.rotate, + }, + spacing = 4, + layout = wibox.layout.fixed.horizontal, + set_volume_level = function(self, new_value) + self:get_children_by_id('bar')[1]:set_value(tonumber(new_value)) + end, + mute = function(self) + self:get_children_by_id('bar')[1]:set_color(mute_color) + end, + unmute = function(self) + self:get_children_by_id('bar')[1]:set_color(main_color) + end + } + + return bar +end + +return widget diff --git a/awesome/awesome-wm-widgets/weather-widget/README.md b/awesome/awesome-wm-widgets/weather-widget/README.md new file mode 100644 index 0000000..3bf6228 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/README.md @@ -0,0 +1,144 @@ +# Weather widget + +

+ GitHub issues by-label + + + Twitter URL + +

+ +The widget showing current, hourly and daily weather forecast: + +

+ screenshot +

+ +The widget consists of three sections: + - current weather, including humidity, wind speed, UV index + - hourly forecast for the next 24 hours + - daily forecast for the next five days + +## Customization + +It is possible to customize widget by providing a table with all or some of the following config parameters: + +| Name | Default | Description | +|---|---|---| +| coordinates | Required | Table with two elements: latitude and longitude, e.g. `{46.204400, 6.143200}` | +| api_key | Required | Get it [here](https://openweathermap.org/appid) | +| font_name | `beautiful.font:gsub("%s%d+$", "")` | **Name** of the font to use e.g. 'Play' | +| both_units_widget | false | Show temperature in both units - '28°C (83°F) | +| units | metric | `metric` for celsius, `imperial` for fahrenheit | +| show_hourly_forecast | false | Show hourly forecase section | +| time_format_12h |false | 12 or 24 hour format (13:00 - default or 1pm) | +| show_daily_forecast | false | Show daily forecast section | +| icon_pack_name | weather-underground-icons | Name of the icon pack, could be `weather-underground-icon` or `VitalyGorbachev` or create your own, more details below | +| icons_extension | `.png` | File extension of icons in the pack | +| timeout | 120 | How often in seconds the widget refreshes | + +### Icons: + +The widget comes with two predefined icon packs: + + - weather-underground-icons taken from [here](https://github.com/manifestinteractive/weather-underground-icons) + - VitalyGorbachev taken from [here](https://www.flaticon.com/authors/vitaly-gorbachev) + +To add your custom icons, create a folder with the pack name under `/icons` and use the folder name in widget's config. There should be 18 icons, preferably 128x128 minimum. Icons should also respect the naming convention, please check widget's source. + +### Examples: + +#### Custom font, icons + +![example1](./example1.png) + +```lua +weather_curl_widget({ + api_key='', + coordinates = {45.5017, -73.5673}, + time_format_12h = true, + units = 'imperial', + both_units_widget = true, + font_name = 'Carter One', + icons = 'VitalyGorbachev', + icons_extension = '.svg', + show_hourly_forecast = true, + show_daily_forecast = true, +}), +``` + +#### Only current weather + +![example2](./example2.png) + +```lua +weather_curl_widget({ + api_key='', + coordinates = {45.5017, -73.5673}, +}), +``` + +## Installation + +1. Download json parser for lua from [github.com/rxi/json.lua](https://github.com/rxi/json.lua) and place it under **~/.config/awesome/** (don't forget to star a repo ): + + ```bash + wget -P ~/.config/awesome/ https://raw.githubusercontent.com/rxi/json.lua/master/json.lua + ``` + +1. Clone this repo under **~/.config/awesome/**: + + ```bash + git clone https://github.com/streetturtle/awesome-wm-widgets.git ~/.config/awesome/ + ``` + +1. Get Open Weather Map app id here: [openweathermap.org/appid](https://openweathermap.org/appid). + +1. Require weather widget at the beginning of **rc.lua**: + + ```lua + local weather_widget = require("awesome-wm-widgets.weather-widget.weather") + ``` + +1. Add widget to the tasklist: + + ```lua + s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + --default + weather_widget({ + api_key='', + coordinates = {45.5017, -73.5673}, + }), + , + --customized + weather_curl_widget({ + api_key='', + coordinates = {45.5017, -73.5673}, + time_format_12h = true, + units = 'imperial', + both_units_widget = true, + font_name = 'Carter One', + icons = 'VitalyGorbachev', + icons_extension = '.svg', + show_hourly_forecast = true, + show_daily_forecast = true, + }), + ... + ``` + +## More screenshots + +Only negative temperature: + +![negative](./negative.png) + +Both positive and negative tempertature: + +![both](./both.png) + +## How it works + +TBW diff --git a/awesome/awesome-wm-widgets/weather-widget/both.png b/awesome/awesome-wm-widgets/weather-widget/both.png new file mode 100644 index 0000000..0947a37 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/both.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/example1.png b/awesome/awesome-wm-widgets/weather-widget/example1.png new file mode 100644 index 0000000..7074faa Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/example1.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/example2.png b/awesome/awesome-wm-widgets/weather-widget/example2.png new file mode 100644 index 0000000..857274b Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/example2.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/example_response.json b/awesome/awesome-wm-widgets/weather-widget/example_response.json new file mode 100644 index 0000000..2b90a6e --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/example_response.json @@ -0,0 +1,1419 @@ +{ + "lat": 45.5, + "lon": -73.57, + "timezone": "America/Toronto", + "timezone_offset": -14400, + "current": { + "dt": 1603155313, + "sunrise": 1603106181, + "sunset": 1603144896, + "temp": 8.91, + "feels_like": 7.97, + "pressure": 1025, + "humidity": 100, + "dew_point": 8.91, + "uvi": 2.37, + "clouds": 90, + "visibility": 4828, + "wind_speed": 1, + "wind_deg": 40, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + }, + { + "id": 701, + "main": "Mist", + "description": "mist", + "icon": "50n" + } + ], + "rain": { + "1h": 0.65 + } + }, + "hourly": [ + { + "dt": 1603152000, + "temp": -8.91, + "feels_like": 7.95, + "pressure": 1025, + "humidity": 100, + "dew_point": 8.91, + "clouds": 90, + "visibility": 10000, + "wind_speed": 1.03, + "wind_deg": 32, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + } + ], + "pop": 1, + "rain": { + "1h": 0.4 + } + }, + { + "dt": 1603155600, + "temp": -9.16, + "feels_like": 7.7, + "pressure": 1025, + "humidity": 91, + "dew_point": 7.77, + "clouds": 95, + "visibility": 10000, + "wind_speed": 1.34, + "wind_deg": 67, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + } + ], + "pop": 0.29, + "rain": { + "1h": 0.87 + } + }, + { + "dt": 1603159200, + "temp": -9.24, + "feels_like": 7.7, + "pressure": 1024, + "humidity": 88, + "dew_point": 7.36, + "clouds": 98, + "visibility": 10000, + "wind_speed": 1.32, + "wind_deg": 48, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + } + ], + "pop": 0.59, + "rain": { + "1h": 0.42 + } + }, + { + "dt": 1603162800, + "temp": -9.18, + "feels_like": 6.91, + "pressure": 1023, + "humidity": 86, + "dew_point": 6.96, + "clouds": 99, + "visibility": 10000, + "wind_speed": 2.23, + "wind_deg": 42, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0.86 + }, + { + "dt": 1603166400, + "temp": -9.09, + "feels_like": 6.46, + "pressure": 1023, + "humidity": 88, + "dew_point": 7.21, + "clouds": 100, + "visibility": 10000, + "wind_speed": 2.83, + "wind_deg": 46, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + } + ], + "pop": 0.94, + "rain": { + "1h": 0.6 + } + }, + { + "dt": 1603170000, + "temp": -8.96, + "feels_like": 6.43, + "pressure": 1022, + "humidity": 91, + "dew_point": 7.62, + "clouds": 100, + "visibility": 5405, + "wind_speed": 2.81, + "wind_deg": 18, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + } + ], + "pop": 1, + "rain": { + "1h": 1.89 + } + }, + { + "dt": 1603173600, + "temp": -8.84, + "feels_like": 6.29, + "pressure": 1021, + "humidity": 91, + "dew_point": 7.6, + "clouds": 100, + "visibility": 7599, + "wind_speed": 2.8, + "wind_deg": 35, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + } + ], + "pop": 1, + "rain": { + "1h": 2.07 + } + }, + { + "dt": 1603177200, + "temp": -8.92, + "feels_like": 6.34, + "pressure": 1021, + "humidity": 92, + "dew_point": 7.78, + "clouds": 100, + "visibility": 8594, + "wind_speed": 2.91, + "wind_deg": 44, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + } + ], + "pop": 1, + "rain": { + "1h": 1.19 + } + }, + { + "dt": 1603180800, + "temp": -9.08, + "feels_like": 7.18, + "pressure": 1020, + "humidity": 93, + "dew_point": 8.06, + "clouds": 100, + "visibility": 9347, + "wind_speed": 2.06, + "wind_deg": 37, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + } + ], + "pop": 1, + "rain": { + "1h": 1.02 + } + }, + { + "dt": 1603184400, + "temp": -8.98, + "feels_like": 6.28, + "pressure": 1019, + "humidity": 93, + "dew_point": 8, + "clouds": 100, + "visibility": 6164, + "wind_speed": 3.16, + "wind_deg": 354, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + } + ], + "pop": 1, + "rain": { + "1h": 1.89 + } + }, + { + "dt": 1603188000, + "temp": -8.69, + "feels_like": 5.78, + "pressure": 1019, + "humidity": 92, + "dew_point": 7.58, + "clouds": 100, + "visibility": 5143, + "wind_speed": 3.31, + "wind_deg": 29, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + } + ], + "pop": 1, + "rain": { + "1h": 2.6 + } + }, + { + "dt": 1603191600, + "temp": -8.6, + "feels_like": 6.08, + "pressure": 1019, + "humidity": 92, + "dew_point": 7.42, + "clouds": 100, + "visibility": 6072, + "wind_speed": 2.73, + "wind_deg": 29, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10n" + } + ], + "pop": 1, + "rain": { + "1h": 2.3 + } + }, + { + "dt": 1603195200, + "temp": -8.56, + "feels_like": 6.68, + "pressure": 1019, + "humidity": 92, + "dew_point": 7.45, + "clouds": 100, + "visibility": 6697, + "wind_speed": 1.8, + "wind_deg": 16, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 2.58 + } + }, + { + "dt": 1603198800, + "temp": -8.74, + "feels_like": 6.88, + "pressure": 1020, + "humidity": 91, + "dew_point": 7.38, + "clouds": 100, + "visibility": 10000, + "wind_speed": 1.77, + "wind_deg": 319, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 1.06 + } + }, + { + "dt": 1603202400, + "temp": -8.93, + "feels_like": 7.32, + "pressure": 1020, + "humidity": 90, + "dew_point": 7.48, + "clouds": 100, + "visibility": 10000, + "wind_speed": 1.42, + "wind_deg": 291, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 0.95 + } + }, + { + "dt": 1603206000, + "temp": -9.07, + "feels_like": 6.75, + "pressure": 1021, + "humidity": 89, + "dew_point": 7.43, + "clouds": 100, + "visibility": 10000, + "wind_speed": 2.43, + "wind_deg": 276, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 0.31 + } + }, + { + "dt": 1603209600, + "temp": -9.31, + "feels_like": 6.58, + "pressure": 1022, + "humidity": 86, + "dew_point": 7.17, + "clouds": 100, + "visibility": 10000, + "wind_speed": 2.93, + "wind_deg": 262, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ], + "pop": 0.8 + }, + { + "dt": 1603213200, + "temp": -10.07, + "feels_like": 6.68, + "pressure": 1023, + "humidity": 80, + "dew_point": 6.78, + "clouds": 100, + "visibility": 10000, + "wind_speed": 3.77, + "wind_deg": 269, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ], + "pop": 0.8 + }, + { + "dt": 1603216800, + "temp": -11.87, + "feels_like": 7.99, + "pressure": 1023, + "humidity": 67, + "dew_point": 6.15, + "clouds": 99, + "visibility": 10000, + "wind_speed": 4.21, + "wind_deg": 265, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ], + "pop": 0.8 + }, + { + "dt": 1603220400, + "temp": -12.05, + "feels_like": 7.95, + "pressure": 1024, + "humidity": 64, + "dew_point": 5.63, + "clouds": 100, + "visibility": 10000, + "wind_speed": 4.38, + "wind_deg": 270, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ], + "pop": 0 + }, + { + "dt": 1603224000, + "temp": -11.74, + "feels_like": 7.54, + "pressure": 1025, + "humidity": 63, + "dew_point": 5.08, + "clouds": 100, + "visibility": 10000, + "wind_speed": 4.38, + "wind_deg": 276, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ], + "pop": 0 + }, + { + "dt": 1603227600, + "temp": -11.09, + "feels_like": 7.13, + "pressure": 1026, + "humidity": 62, + "dew_point": 4.24, + "clouds": 100, + "visibility": 10000, + "wind_speed": 3.79, + "wind_deg": 293, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04d" + } + ], + "pop": 0 + }, + { + "dt": 1603231200, + "temp": -10.13, + "feels_like": 6.51, + "pressure": 1027, + "humidity": 63, + "dew_point": 3.43, + "clouds": 100, + "visibility": 10000, + "wind_speed": 3.13, + "wind_deg": 318, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603234800, + "temp": -9.53, + "feels_like": 7.02, + "pressure": 1028, + "humidity": 63, + "dew_point": 3.02, + "clouds": 100, + "visibility": 10000, + "wind_speed": 1.4, + "wind_deg": 329, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603238400, + "temp": -9.2, + "feels_like": 7.3, + "pressure": 1028, + "humidity": 65, + "dew_point": 3.03, + "clouds": 100, + "visibility": 10000, + "wind_speed": 0.56, + "wind_deg": 52, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603242000, + "temp": -8.73, + "feels_like": 6.57, + "pressure": 1029, + "humidity": 68, + "dew_point": 3.28, + "clouds": 100, + "visibility": 10000, + "wind_speed": 0.98, + "wind_deg": 75, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603245600, + "temp": -8.12, + "feels_like": 5.55, + "pressure": 1029, + "humidity": 71, + "dew_point": 3.27, + "clouds": 89, + "visibility": 10000, + "wind_speed": 1.57, + "wind_deg": 68, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603249200, + "temp": -7.83, + "feels_like": 4.86, + "pressure": 1029, + "humidity": 71, + "dew_point": 3.05, + "clouds": 93, + "visibility": 10000, + "wind_speed": 2.07, + "wind_deg": 68, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603252800, + "temp": -7.49, + "feels_like": 4.21, + "pressure": 1029, + "humidity": 72, + "dew_point": 2.8, + "clouds": 94, + "visibility": 10000, + "wind_speed": 2.48, + "wind_deg": 66, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603256400, + "temp": -6.92, + "feels_like": 3.31, + "pressure": 1029, + "humidity": 73, + "dew_point": 2.47, + "clouds": 96, + "visibility": 10000, + "wind_speed": 2.87, + "wind_deg": 81, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603260000, + "temp": -6.49, + "feels_like": 2.48, + "pressure": 1029, + "humidity": 74, + "dew_point": 2.22, + "clouds": 96, + "visibility": 10000, + "wind_speed": 3.38, + "wind_deg": 78, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603263600, + "temp": -6.3, + "feels_like": 1.81, + "pressure": 1028, + "humidity": 71, + "dew_point": 1.55, + "clouds": 100, + "visibility": 10000, + "wind_speed": 3.89, + "wind_deg": 84, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603267200, + "temp": -6.22, + "feels_like": 1.39, + "pressure": 1027, + "humidity": 69, + "dew_point": 0.99, + "clouds": 98, + "visibility": 10000, + "wind_speed": 4.27, + "wind_deg": 74, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0 + }, + { + "dt": 1603270800, + "temp": -6.69, + "feels_like": 1.66, + "pressure": 1026, + "humidity": 65, + "dew_point": 0.79, + "clouds": 96, + "visibility": 10000, + "wind_speed": 4.47, + "wind_deg": 69, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0.05 + }, + { + "dt": 1603274400, + "temp": -6.53, + "feels_like": 1.74, + "pressure": 1024, + "humidity": 68, + "dew_point": 1.07, + "clouds": 97, + "visibility": 10000, + "wind_speed": 4.23, + "wind_deg": 65, + "weather": [ + { + "id": 804, + "main": "Clouds", + "description": "overcast clouds", + "icon": "04n" + } + ], + "pop": 0.28 + }, + { + "dt": 1603278000, + "temp": -6.41, + "feels_like": 1.87, + "pressure": 1023, + "humidity": 73, + "dew_point": 1.96, + "clouds": 97, + "visibility": 10000, + "wind_speed": 4.08, + "wind_deg": 73, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + } + ], + "pop": 0.35, + "rain": { + "1h": 0.17 + } + }, + { + "dt": 1603281600, + "temp": -6.42, + "feels_like": 2.71, + "pressure": 1022, + "humidity": 79, + "dew_point": 3.21, + "clouds": 98, + "visibility": 9620, + "wind_speed": 3.16, + "wind_deg": 71, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "pop": 0.62, + "rain": { + "1h": 0.37 + } + }, + { + "dt": 1603285200, + "temp": -6.67, + "feels_like": 3.38, + "pressure": 1021, + "humidity": 86, + "dew_point": 4.59, + "clouds": 100, + "visibility": 10000, + "wind_speed": 2.95, + "wind_deg": 84, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10d" + } + ], + "pop": 0.9, + "rain": { + "1h": 1.08 + } + }, + { + "dt": 1603288800, + "temp": -8.55, + "feels_like": 5.61, + "pressure": 1019, + "humidity": 87, + "dew_point": 6.64, + "clouds": 100, + "visibility": 10000, + "wind_speed": 3.05, + "wind_deg": 135, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 0.23 + } + }, + { + "dt": 1603292400, + "temp": -10.85, + "feels_like": 8.09, + "pressure": 1018, + "humidity": 95, + "dew_point": 10.13, + "clouds": 100, + "visibility": 10000, + "wind_speed": 4.04, + "wind_deg": 150, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 0.31 + } + }, + { + "dt": 1603296000, + "temp": -13.37, + "feels_like": 10.29, + "pressure": 1017, + "humidity": 90, + "dew_point": 11.93, + "clouds": 100, + "visibility": 10000, + "wind_speed": 5.19, + "wind_deg": 170, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 0.32 + } + }, + { + "dt": 1603299600, + "temp": -13.92, + "feels_like": 11.34, + "pressure": 1015, + "humidity": 94, + "dew_point": 13.07, + "clouds": 100, + "visibility": 6450, + "wind_speed": 5.01, + "wind_deg": 177, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 3.08 + } + }, + { + "dt": 1603303200, + "temp": -14.85, + "feels_like": 12.78, + "pressure": 1014, + "humidity": 95, + "dew_point": 14.1, + "clouds": 100, + "visibility": 10000, + "wind_speed": 4.79, + "wind_deg": 183, + "weather": [ + { + "id": 502, + "main": "Rain", + "description": "heavy intensity rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 4.94 + } + }, + { + "dt": 1603306800, + "temp": -15.94, + "feels_like": 13.56, + "pressure": 1014, + "humidity": 93, + "dew_point": 14.96, + "clouds": 100, + "visibility": 7138, + "wind_speed": 5.61, + "wind_deg": 207, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 2.71 + } + }, + { + "dt": 1603310400, + "temp": -16.72, + "feels_like": 14.6, + "pressure": 1014, + "humidity": 93, + "dew_point": 15.66, + "clouds": 100, + "visibility": 10000, + "wind_speed": 5.64, + "wind_deg": 208, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 1.33 + } + }, + { + "dt": 1603314000, + "temp": -16.74, + "feels_like": 14.61, + "pressure": 1014, + "humidity": 94, + "dew_point": 15.81, + "clouds": 100, + "visibility": 10000, + "wind_speed": 5.75, + "wind_deg": 216, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "pop": 1, + "rain": { + "1h": 0.89 + } + }, + { + "dt": 1603317600, + "temp": -17.05, + "feels_like": 14.53, + "pressure": 1015, + "humidity": 92, + "dew_point": 15.83, + "clouds": 100, + "visibility": 10000, + "wind_speed": 6.3, + "wind_deg": 234, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + } + ], + "pop": 1, + "rain": { + "1h": 0.51 + } + }, + { + "dt": 1603321200, + "temp": -16.74, + "feels_like": 14.18, + "pressure": 1016, + "humidity": 87, + "dew_point": 14.65, + "clouds": 100, + "visibility": 10000, + "wind_speed": 5.74, + "wind_deg": 257, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10n" + } + ], + "pop": 1, + "rain": { + "1h": 0.22 + } + } + ], + "daily": [ + { + "dt": 1603123200, + "sunrise": 1603106181, + "sunset": 1603144896, + "temp": { + "day": 12, + "min": 8.91, + "max": 12.73, + "night": 9.05, + "eve": 9.72, + "morn": 12.73 + }, + "feels_like": { + "day": 9.92, + "night": 7.02, + "eve": 7.88, + "morn": 8.02 + }, + "pressure": 1025, + "humidity": 78, + "dew_point": 8.34, + "wind_speed": 2.41, + "wind_deg": 242, + "weather": [ + { + "id": 501, + "main": "Rain", + "description": "moderate rain", + "icon": "10d" + } + ], + "clouds": 100, + "pop": 1, + "rain": 8.77, + "uvi": 2.37 + }, + { + "dt": 1603209600, + "sunrise": 1603192663, + "sunset": 1603231195, + "temp": { + "day": 9.07, + "min": 7.83, + "max": 11.87, + "night": 7.83, + "eve": 11.09, + "morn": 8.98 + }, + "feels_like": { + "day": 6.75, + "night": 4.86, + "eve": 7.13, + "morn": 6.28 + }, + "pressure": 1021, + "humidity": 89, + "dew_point": 7.43, + "wind_speed": 2.43, + "wind_deg": 276, + "weather": [ + { + "id": 502, + "main": "Rain", + "description": "heavy intensity rain", + "icon": "10d" + } + ], + "clouds": 100, + "pop": 1, + "rain": 18.46, + "uvi": 2.3 + }, + { + "dt": 1603296000, + "sunrise": 1603279145, + "sunset": 1603317495, + "temp": { + "day": 10.85, + "min": 6.42, + "max": 16.74, + "night": 12.25, + "eve": 16.74, + "morn": 6.69 + }, + "feels_like": { + "day": 8.09, + "night": 8.59, + "eve": 14.61, + "morn": 1.66 + }, + "pressure": 1018, + "humidity": 95, + "dew_point": 10.13, + "wind_speed": 4.04, + "wind_deg": 150, + "weather": [ + { + "id": 502, + "main": "Rain", + "description": "heavy intensity rain", + "icon": "10d" + } + ], + "clouds": 100, + "pop": 1, + "rain": 16.19, + "uvi": 2.32 + }, + { + "dt": 1603382400, + "sunrise": 1603365627, + "sunset": 1603403795, + "temp": { + "day": 9.95, + "min": 7.29, + "max": 11.27, + "night": 7.29, + "eve": 11.01, + "morn": 9.44 + }, + "feels_like": { + "day": 5.45, + "night": 2.63, + "eve": 8.07, + "morn": 5.65 + }, + "pressure": 1027, + "humidity": 57, + "dew_point": 2.03, + "wind_speed": 4, + "wind_deg": 283, + "weather": [ + { + "id": 802, + "main": "Clouds", + "description": "scattered clouds", + "icon": "03d" + } + ], + "clouds": 27, + "pop": 0, + "uvi": 2.36 + }, + { + "dt": 1603468800, + "sunrise": 1603452109, + "sunset": 1603490097, + "temp": { + "day": 12.02, + "min": 6.62, + "max": 17.04, + "night": 15.91, + "eve": 17.04, + "morn": 7.09 + }, + "feels_like": { + "day": 8.48, + "night": 11.82, + "eve": 12.58, + "morn": 3.07 + }, + "pressure": 1022, + "humidity": 72, + "dew_point": 7.29, + "wind_speed": 4.1, + "wind_deg": 147, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "clouds": 99, + "pop": 0.29, + "rain": 0.22, + "uvi": 2.2 + }, + { + "dt": 1603555200, + "sunrise": 1603538592, + "sunset": 1603576400, + "temp": { + "day": 8.39, + "min": 6.83, + "max": 15.86, + "night": 6.83, + "eve": 9.56, + "morn": 12.99 + }, + "feels_like": { + "day": 3.79, + "night": 3.04, + "eve": 6.58, + "morn": 10.39 + }, + "pressure": 1022, + "humidity": 58, + "dew_point": 0.71, + "wind_speed": 3.87, + "wind_deg": 10, + "weather": [ + { + "id": 500, + "main": "Rain", + "description": "light rain", + "icon": "10d" + } + ], + "clouds": 72, + "pop": 0.9, + "rain": 2.54, + "uvi": 2.07 + }, + { + "dt": 1603641600, + "sunrise": 1603625075, + "sunset": 1603662705, + "temp": { + "day": 5.33, + "min": 3.23, + "max": 7.24, + "night": 4.97, + "eve": 6.59, + "morn": 3.97 + }, + "feels_like": { + "day": 1.26, + "night": 0.02, + "eve": 2.58, + "morn": -0.34 + }, + "pressure": 1025, + "humidity": 61, + "dew_point": -5.56, + "wind_speed": 2.67, + "wind_deg": 37, + "weather": [ + { + "id": 803, + "main": "Clouds", + "description": "broken clouds", + "icon": "04d" + } + ], + "clouds": 74, + "pop": 0.08, + "uvi": 2.25 + }, + { + "dt": 1603728000, + "sunrise": 1603711558, + "sunset": 1603749010, + "temp": { + "day": 3.7, + "min": 2.09, + "max": 3.88, + "night": 3.54, + "eve": 3.54, + "morn": 2.09 + }, + "feels_like": { + "day": -0.28, + "night": -0.76, + "eve": -0.86, + "morn": -2.81 + }, + "pressure": 1021, + "humidity": 90, + "dew_point": 2.33, + "wind_speed": 3.35, + "wind_deg": 32, + "weather": [ + { + "id": 502, + "main": "Rain", + "description": "heavy intensity rain", + "icon": "10d" + } + ], + "clouds": 100, + "pop": 1, + "rain": 12.43 + } + ] +} \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/broken-clouds-night.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/broken-clouds-night.svg new file mode 100644 index 0000000..8b7fc48 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/broken-clouds-night.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/broken-clouds.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/broken-clouds.svg new file mode 100644 index 0000000..d42ea59 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/broken-clouds.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/clear-sky-night.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/clear-sky-night.svg new file mode 100644 index 0000000..44f096c --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/clear-sky-night.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/clear-sky.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/clear-sky.svg new file mode 100644 index 0000000..dc82163 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/clear-sky.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/few-clouds-night.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/few-clouds-night.svg new file mode 100644 index 0000000..8b7fc48 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/few-clouds-night.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/few-clouds.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/few-clouds.svg new file mode 100644 index 0000000..d42ea59 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/few-clouds.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/mist-night.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/mist-night.svg new file mode 100644 index 0000000..960b07d --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/mist-night.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/mist.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/mist.svg new file mode 100644 index 0000000..770f8d7 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/mist.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/rain-night.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/rain-night.svg new file mode 100644 index 0000000..11ecf00 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/rain-night.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/rain.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/rain.svg new file mode 100644 index 0000000..11ecf00 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/scattered-clouds-night.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/scattered-clouds-night.svg new file mode 100644 index 0000000..8b7fc48 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/scattered-clouds-night.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/scattered-clouds.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/scattered-clouds.svg new file mode 100644 index 0000000..d42ea59 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/scattered-clouds.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/shower-rain-night.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/shower-rain-night.svg new file mode 100644 index 0000000..4d1897c --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/shower-rain-night.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/shower-rain.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/shower-rain.svg new file mode 100644 index 0000000..4d1897c --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/shower-rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/snow-night.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/snow-night.svg new file mode 100644 index 0000000..bee891e --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/snow-night.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/snow.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/snow.svg new file mode 100644 index 0000000..e2ea140 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/snow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/thunderstorm-night.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/thunderstorm-night.svg new file mode 100644 index 0000000..1813197 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/thunderstorm-night.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/thunderstorm.svg b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/thunderstorm.svg new file mode 100644 index 0000000..44a733c --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/icons/VitalyGorbachev/thunderstorm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/broken-clouds-night.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/broken-clouds-night.png new file mode 100644 index 0000000..061d1cd Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/broken-clouds-night.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/broken-clouds.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/broken-clouds.png new file mode 100755 index 0000000..5967d92 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/broken-clouds.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/clear-sky-night.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/clear-sky-night.png new file mode 100644 index 0000000..cc40d0f Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/clear-sky-night.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/clear-sky.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/clear-sky.png new file mode 100755 index 0000000..acf8e5c Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/clear-sky.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/few-clouds-night.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/few-clouds-night.png new file mode 100644 index 0000000..9c34fab Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/few-clouds-night.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/few-clouds.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/few-clouds.png new file mode 100755 index 0000000..7580fc5 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/few-clouds.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/mist-night.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/mist-night.png new file mode 100755 index 0000000..102142a Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/mist-night.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/mist.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/mist.png new file mode 100755 index 0000000..102142a Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/mist.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/rain-night.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/rain-night.png new file mode 100755 index 0000000..49f0903 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/rain-night.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/rain.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/rain.png new file mode 100755 index 0000000..49f0903 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/rain.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/scattered-clouds-night.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/scattered-clouds-night.png new file mode 100755 index 0000000..63cb1b2 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/scattered-clouds-night.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/scattered-clouds.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/scattered-clouds.png new file mode 100755 index 0000000..63cb1b2 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/scattered-clouds.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/shower-rain-night.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/shower-rain-night.png new file mode 100755 index 0000000..49f0903 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/shower-rain-night.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/shower-rain.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/shower-rain.png new file mode 100755 index 0000000..49f0903 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/shower-rain.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/snow-night.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/snow-night.png new file mode 100755 index 0000000..0a7f006 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/snow-night.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/snow.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/snow.png new file mode 100755 index 0000000..0a7f006 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/snow.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/thunderstorm-night.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/thunderstorm-night.png new file mode 100755 index 0000000..2102104 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/thunderstorm-night.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/thunderstorm.png b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/thunderstorm.png new file mode 100755 index 0000000..2102104 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/icons/weather-underground-icons/thunderstorm.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/locale/de.lua b/awesome/awesome-wm-widgets/weather-widget/locale/de.lua new file mode 100644 index 0000000..2a9236a --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/locale/de.lua @@ -0,0 +1,13 @@ +local de = { + warning_title = "Wetter Widget", + parameter_warning = "Folgende benötigte Parameter fehlen: ", + directions = { + "N", "NNO", "NO", "ONO", "O", "OSO", "SO", "SSO", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW", "N" + }, + feels_like = "Gefühlt: ", + wind = "Wind: ", + humidity = "Luftfeuchtigkeit: ", + uv = "UV-Index: " +} + +return de diff --git a/awesome/awesome-wm-widgets/weather-widget/locale/en.lua b/awesome/awesome-wm-widgets/weather-widget/locale/en.lua new file mode 100644 index 0000000..377dc6f --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/locale/en.lua @@ -0,0 +1,14 @@ +local en = { + warning_title = "Weather Widget", + parameter_warning = "Required parameters are not set: ", + directions = { + "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", + "WSW", "W", "WNW", "NW", "NNW", "N" + }, + feels_like = "Feels like ", + wind = "Wind: ", + humidity = "Humidity: ", + uv = "UV: " +} + +return en diff --git a/awesome/awesome-wm-widgets/weather-widget/locale/fr.lua b/awesome/awesome-wm-widgets/weather-widget/locale/fr.lua new file mode 100644 index 0000000..de50814 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/locale/fr.lua @@ -0,0 +1,14 @@ +local fr = { + warning_title = "Widget Météo", + parameter_warning = "Les paramètres suivants sont obligatoires : ", + directions = { + "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSO", "SO", + "OSO", "O", "ONO", "NO", "NNO", "N" + }, + feels_like = "ressentie à ", + wind = "Vent : ", + humidity = "Humidité : ", + uv = "Indice UV : " +} + +return fr diff --git a/awesome/awesome-wm-widgets/weather-widget/locale/pt.lua b/awesome/awesome-wm-widgets/weather-widget/locale/pt.lua new file mode 100644 index 0000000..e7f4012 --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/locale/pt.lua @@ -0,0 +1,14 @@ +local pt = { + warning_title = "Widget do tempo", + parameter_warning = "Parâmetros necessários não definidos: ", + directions = { + "N", "NNE", "NE", "ENE", "L", "ESE", "SE", "SSE", "S", "SSO", "SO", + "OSO", "O", "ONO", "NO", "NNO", "N" + }, + feels_like = "Sensação de ", + wind = "Vento: ", + humidity = "Umidade: ", + uv = "UV: " +} + +return pt diff --git a/awesome/awesome-wm-widgets/weather-widget/negative.png b/awesome/awesome-wm-widgets/weather-widget/negative.png new file mode 100644 index 0000000..afcf567 Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/negative.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/weather-widget.png b/awesome/awesome-wm-widgets/weather-widget/weather-widget.png new file mode 100644 index 0000000..c7fc37e Binary files /dev/null and b/awesome/awesome-wm-widgets/weather-widget/weather-widget.png differ diff --git a/awesome/awesome-wm-widgets/weather-widget/weather.lua b/awesome/awesome-wm-widgets/weather-widget/weather.lua new file mode 100644 index 0000000..3ec1c3f --- /dev/null +++ b/awesome/awesome-wm-widgets/weather-widget/weather.lua @@ -0,0 +1,575 @@ +------------------------------------------------- +-- Weather Widget based on the OpenWeatherMap +-- https://openweathermap.org/ +-- +-- @author Pavel Makhov +-- @copyright 2020 Pavel Makhov +------------------------------------------------- +local awful = require("awful") +local watch = require("awful.widget.watch") +local json = require("json") +local naughty = require("naughty") +local wibox = require("wibox") +local gears = require("gears") +local beautiful = require("beautiful") + +local HOME_DIR = os.getenv("HOME") +local WIDGET_DIR = HOME_DIR .. '/.config/awesome/awesome-wm-widgets/weather-widget' +local GET_FORECAST_CMD = [[bash -c "curl -s --show-error -X GET '%s'"]] + +local SYS_LANG = os.getenv("LANG"):sub(1, 2) +if SYS_LANG == "C" or SYS_LANG == "C." then + -- C-locale is a common fallback for simple English + SYS_LANG = "en" +end +-- default language is ENglish +local LANG = gears.filesystem.file_readable(WIDGET_DIR .. "/" .. "locale/" .. + SYS_LANG .. ".lua") and SYS_LANG or "en" +local LCLE = require("awesome-wm-widgets.weather-widget.locale." .. LANG) + + +local function show_warning(message) + naughty.notify { + preset = naughty.config.presets.critical, + title = LCLE.warning_title, + text = message + } +end + +if SYS_LANG ~= LANG then + show_warning("Your language is not supported yet. Language set to English") +end + +local weather_widget = {} +local warning_shown = false +local tooltip = awful.tooltip { + mode = 'outside', + preferred_positions = {'bottom'} +} + +local weather_popup = awful.popup { + ontop = true, + visible = false, + shape = gears.shape.rounded_rect, + border_width = 1, + border_color = beautiful.bg_focus, + maximum_width = 400, + offset = {y = 5}, + hide_on_right_click = true, + widget = {} +} + +--- Maps openWeatherMap icon name to file name w/o extension +local icon_map = { + ["01d"] = "clear-sky", + ["02d"] = "few-clouds", + ["03d"] = "scattered-clouds", + ["04d"] = "broken-clouds", + ["09d"] = "shower-rain", + ["10d"] = "rain", + ["11d"] = "thunderstorm", + ["13d"] = "snow", + ["50d"] = "mist", + ["01n"] = "clear-sky-night", + ["02n"] = "few-clouds-night", + ["03n"] = "scattered-clouds-night", + ["04n"] = "broken-clouds-night", + ["09n"] = "shower-rain-night", + ["10n"] = "rain-night", + ["11n"] = "thunderstorm-night", + ["13n"] = "snow-night", + ["50n"] = "mist-night" +} + +--- Return wind direction as a string +local function to_direction(degrees) + -- Ref: https://www.campbellsci.eu/blog/convert-wind-directions + if degrees == nil then return "Unknown dir" end + local directions = LCLE.directions + return directions[math.floor((degrees % 360) / 22.5) + 1] +end + +--- Convert degrees Celsius to Fahrenheit +local function celsius_to_fahrenheit(c) return c * 9 / 5 + 32 end + +-- Convert degrees Fahrenheit to Celsius +local function fahrenheit_to_celsius(f) return (f - 32) * 5 / 9 end + +local function gen_temperature_str(temp, fmt_str, show_other_units, units) + local temp_str = string.format(fmt_str, temp) + local s = temp_str .. '°' .. (units == 'metric' and 'C' or 'F') + + if (show_other_units) then + local temp_conv, units_conv + if (units == 'metric') then + temp_conv = celsius_to_fahrenheit(temp) + units_conv = 'F' + else + temp_conv = fahrenheit_to_celsius(temp) + units_conv = 'C' + end + + local temp_conv_str = string.format(fmt_str, temp_conv) + s = s .. ' ' .. '(' .. temp_conv_str .. '°' .. units_conv .. ')' + end + return s +end + +local function uvi_index_color(uvi) + local color + if uvi >= 0 and uvi < 3 then color = '#A3BE8C' + elseif uvi >= 3 and uvi < 6 then color = '#EBCB8B' + elseif uvi >= 6 and uvi < 8 then color = '#D08770' + elseif uvi >= 8 and uvi < 11 then color = '#BF616A' + elseif uvi >= 11 then color = '#B48EAD' + end + + return '' .. uvi .. '' +end + +local function worker(user_args) + + local args = user_args or {} + + --- Validate required parameters + if args.coordinates == nil or args.api_key == nil then + show_warning(LCLE.parameter_warning .. + (args.coordinates == nil and 'coordinates' or '') .. + (args.api_key == nil and ', api_key ' or '')) + return + end + + local coordinates = args.coordinates + local api_key = args.api_key + local font_name = args.font_name or beautiful.font:gsub("%s%d+$", "") + local units = args.units or 'metric' + local time_format_12h = args.time_format_12h + local both_units_widget = args.both_units_widget or false + local show_hourly_forecast = args.show_hourly_forecast + local show_daily_forecast = args.show_daily_forecast + local icon_pack_name = args.icons or 'weather-underground-icons' + local icons_extension = args.icons_extension or '.png' + local timeout = args.timeout or 120 + + local ICONS_DIR = WIDGET_DIR .. '/icons/' .. icon_pack_name .. '/' + local owm_one_cal_api = + ('https://api.openweathermap.org/data/2.5/onecall' .. + '?lat=' .. coordinates[1] .. '&lon=' .. coordinates[2] .. '&appid=' .. api_key .. + '&units=' .. units .. '&exclude=minutely' .. + (show_hourly_forecast == false and ',hourly' or '') .. + (show_daily_forecast == false and ',daily' or '') .. + '&lang=' .. LANG) + + weather_widget = wibox.widget { + { + { + { + { + id = 'icon', + resize = true, + widget = wibox.widget.imagebox + }, + valign = 'center', + widget = wibox.container.place, + }, + { + id = 'txt', + widget = wibox.widget.textbox + }, + layout = wibox.layout.fixed.horizontal, + }, + left = 4, + right = 4, + layout = wibox.container.margin + }, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end, + widget = wibox.container.background, + set_image = function(self, path) + self:get_children_by_id('icon')[1].image = path + end, + set_text = function(self, text) + self:get_children_by_id('txt')[1].text = text + end, + is_ok = function(self, is_ok) + if is_ok then + self:get_children_by_id('icon')[1]:set_opacity(1) + self:get_children_by_id('icon')[1]:emit_signal('widget:redraw_needed') + else + self:get_children_by_id('icon')[1]:set_opacity(0.2) + self:get_children_by_id('icon')[1]:emit_signal('widget:redraw_needed') + end + end + } + + local current_weather_widget = wibox.widget { + { + { + { + id = 'icon', + resize = true, + forced_width = 128, + forced_height = 128, + widget = wibox.widget.imagebox + }, + align = 'center', + widget = wibox.container.place + }, + { + id = 'description', + font = font_name .. ' 10', + align = 'center', + widget = wibox.widget.textbox + }, + forced_width = 128, + layout = wibox.layout.align.vertical + }, + { + { + { + id = 'temp', + font = font_name .. ' 36', + widget = wibox.widget.textbox + }, + { + id = 'feels_like_temp', + align = 'center', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + layout = wibox.layout.fixed.vertical + }, + { + { + id = 'wind', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + { + id = 'humidity', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + { + id = 'uv', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + expand = 'inside', + layout = wibox.layout.align.vertical + }, + spacing = 16, + forced_width = 150, + layout = wibox.layout.fixed.vertical + }, + forced_width = 300, + layout = wibox.layout.flex.horizontal, + update = function(self, weather) + self:get_children_by_id('icon')[1]:set_image( + ICONS_DIR .. icon_map[weather.weather[1].icon] .. icons_extension) + self:get_children_by_id('temp')[1]:set_text(gen_temperature_str(weather.temp, '%.0f', false, units)) + self:get_children_by_id('feels_like_temp')[1]:set_text( + LCLE.feels_like .. gen_temperature_str(weather.feels_like, '%.0f', false, units)) + self:get_children_by_id('description')[1]:set_text(weather.weather[1].description) + self:get_children_by_id('wind')[1]:set_markup( + LCLE.wind .. '' .. weather.wind_speed .. 'm/s (' .. to_direction(weather.wind_deg) .. ')') + self:get_children_by_id('humidity')[1]:set_markup(LCLE.humidity .. '' .. weather.humidity .. '%') + self:get_children_by_id('uv')[1]:set_markup(LCLE.uv .. uvi_index_color(weather.uvi)) + end + } + + + local daily_forecast_widget = { + forced_width = 300, + layout = wibox.layout.flex.horizontal, + update = function(self, forecast, timezone_offset) + local count = #self + for i = 0, count do self[i]=nil end + for i, day in ipairs(forecast) do + if i > 5 then break end + local day_forecast = wibox.widget { + { + text = os.date('%a', tonumber(day.dt) + tonumber(timezone_offset)), + align = 'center', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + { + { + { + image = ICONS_DIR .. icon_map[day.weather[1].icon] .. icons_extension, + resize = true, + forced_width = 48, + forced_height = 48, + widget = wibox.widget.imagebox + }, + align = 'center', + layout = wibox.container.place + }, + { + text = day.weather[1].description, + font = font_name .. ' 8', + align = 'center', + forced_height = 50, + widget = wibox.widget.textbox + }, + layout = wibox.layout.fixed.vertical + }, + { + { + text = gen_temperature_str(day.temp.day, '%.0f', false, units), + align = 'center', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + { + text = gen_temperature_str(day.temp.night, '%.0f', false, units), + align = 'center', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + layout = wibox.layout.fixed.vertical + }, + spacing = 8, + layout = wibox.layout.fixed.vertical + } + table.insert(self, day_forecast) + end + end + } + + local hourly_forecast_graph = wibox.widget { + step_width = 12, + color = '#EBCB8B', + background_color = beautiful.bg_normal, + forced_height = 100, + forced_width = 300, + widget = wibox.widget.graph, + set_max_value = function(self, new_max_value) + self.max_value = new_max_value + end, + set_min_value = function(self, new_min_value) + self.min_value = new_min_value + end + } + local hourly_forecast_negative_graph = wibox.widget { + step_width = 12, + color = '#5E81AC', + background_color = beautiful.bg_normal, + forced_height = 100, + forced_width = 300, + widget = wibox.widget.graph, + set_max_value = function(self, new_max_value) + self.max_value = new_max_value + end, + set_min_value = function(self, new_min_value) + self.min_value = new_min_value + end + } + + local hourly_forecast_widget = { + layout = wibox.layout.fixed.vertical, + update = function(self, hourly) + local hours_below = { + id = 'hours', + forced_width = 300, + layout = wibox.layout.flex.horizontal + } + local temp_below = { + id = 'temp', + forced_width = 300, + layout = wibox.layout.flex.horizontal + } + + local max_temp = -1000 + local min_temp = 1000 + local values = {} + for i, hour in ipairs(hourly) do + if i > 25 then break end + values[i] = hour.temp + if max_temp < hour.temp then max_temp = hour.temp end + if min_temp > hour.temp then min_temp = hour.temp end + if (i - 1) % 5 == 0 then + table.insert(hours_below, wibox.widget { + text = os.date(time_format_12h and '%I%p' or '%H:00', tonumber(hour.dt)), + align = 'center', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }) + table.insert(temp_below, wibox.widget { + markup = '' + .. string.format('%.0f', hour.temp) .. '°' .. '', + align = 'center', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }) + end + end + + hourly_forecast_graph:set_max_value(math.max(max_temp, math.abs(min_temp))) + hourly_forecast_graph:set_min_value(min_temp > 0 and min_temp * 0.7 or 0) -- move graph a bit up + + hourly_forecast_negative_graph:set_max_value(math.abs(min_temp)) + hourly_forecast_negative_graph:set_min_value(max_temp < 0 and math.abs(max_temp) * 0.7 or 0) + + for _, value in ipairs(values) do + if value >= 0 then + hourly_forecast_graph:add_value(value) + hourly_forecast_negative_graph:add_value(0) + else + hourly_forecast_graph:add_value(0) + hourly_forecast_negative_graph:add_value(math.abs(value)) + end + end + + local count = #self + for i = 0, count do self[i]=nil end + + -- all temperatures are positive + if min_temp > 0 then + table.insert(self, wibox.widget{ + { + hourly_forecast_graph, + reflection = {horizontal = true}, + widget = wibox.container.mirror + }, + { + temp_below, + valign = 'bottom', + widget = wibox.container.place + }, + id = 'graph', + layout = wibox.layout.stack + }) + table.insert(self, hours_below) + + -- all temperatures are negative + elseif max_temp < 0 then + table.insert(self, hours_below) + table.insert(self, wibox.widget{ + { + hourly_forecast_negative_graph, + reflection = {horizontal = true, vertical = true}, + widget = wibox.container.mirror + }, + { + temp_below, + valign = 'top', + widget = wibox.container.place + }, + id = 'graph', + layout = wibox.layout.stack + }) + + -- there are both negative and positive temperatures + else + table.insert(self, wibox.widget{ + { + hourly_forecast_graph, + reflection = {horizontal = true}, + widget = wibox.container.mirror + }, + { + temp_below, + valign = 'bottom', + widget = wibox.container.place + }, + id = 'graph', + layout = wibox.layout.stack + }) + table.insert(self, wibox.widget{ + { + hourly_forecast_negative_graph, + reflection = {horizontal = true, vertical = true}, + widget = wibox.container.mirror + }, + { + hours_below, + valign = 'top', + widget = wibox.container.place + }, + id = 'graph', + layout = wibox.layout.stack + }) + end + end + } + + local function update_widget(widget, stdout, stderr) + if stderr ~= '' then + if not warning_shown then + if (stderr ~= 'curl: (52) Empty reply from server' + and stderr ~= 'curl: (28) Failed to connect to api.openweathermap.org port 443: Connection timed out' + and stderr:find('^curl: %(18%) transfer closed with %d+ bytes remaining to read$') ~= nil + ) then + show_warning(stderr) + end + warning_shown = true + widget:is_ok(false) + tooltip:add_to_object(widget) + + widget:connect_signal('mouse::enter', function() tooltip.text = stderr end) + end + return + end + + warning_shown = false + tooltip:remove_from_object(widget) + widget:is_ok(true) + + local result = json.decode(stdout) + + widget:set_image(ICONS_DIR .. icon_map[result.current.weather[1].icon] .. icons_extension) + widget:set_text(gen_temperature_str(result.current.temp, '%.0f', both_units_widget, units)) + + current_weather_widget:update(result.current) + + local final_widget = { + current_weather_widget, + spacing = 16, + layout = wibox.layout.fixed.vertical + } + + if show_hourly_forecast then + hourly_forecast_widget:update(result.hourly) + table.insert(final_widget, hourly_forecast_widget) + end + + if show_daily_forecast then + daily_forecast_widget:update(result.daily, result.timezone_offset) + table.insert(final_widget, daily_forecast_widget) + end + + weather_popup:setup({ + { + final_widget, + margins = 10, + widget = wibox.container.margin + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + }) + end + + weather_widget:buttons(gears.table.join(awful.button({}, 1, function() + if weather_popup.visible then + weather_widget:set_bg('#00000000') + weather_popup.visible = not weather_popup.visible + else + weather_widget:set_bg(beautiful.bg_focus) + weather_popup:move_next_to(mouse.current_widget_geometry) + end + end))) + + watch( + string.format(GET_FORECAST_CMD, owm_one_cal_api), + timeout, -- API limit is 1k req/day; day has 1440 min; every 2 min is good + update_widget, weather_widget + ) + + return weather_widget +end + +return setmetatable(weather_widget, {__call = function(_, ...) return worker(...) end}) diff --git a/awesome/binding/bindtotags.lua b/awesome/binding/bindtotags.lua new file mode 100644 index 0000000..a7f9851 --- /dev/null +++ b/awesome/binding/bindtotags.lua @@ -0,0 +1,79 @@ +-- Standard awesome library +local gears = require("gears") +local awful = require("awful") + +local _M = {} +local modkey = RC.vars.modkey + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +-- {{{ Key bindings + +function _M.get(globalkeys) + -- Bind all key numbers to tags. + -- Be careful: we use keycodes to make it work on any keyboard layout. + -- This should map on the top row of your keyboard, usually 1 to 9. + for i = 1, 9 do + globalkeys = gears.table.join(globalkeys, + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- View tag only. + awful.key({ modkey }, "#" .. i + 9, + function () + local screen = awful.screen.focused() + local tag = screen.tags[i] + if tag then + tag:view_only() + end + end, + {description = "view tag #"..i, group = "tag"}), + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- Toggle tag display. + awful.key({ modkey, "Control" }, "#" .. i + 9, + function () + local screen = awful.screen.focused() + local tag = screen.tags[i] + if tag then + awful.tag.viewtoggle(tag) + end + end, + {description = "toggle tag #" .. i, group = "tag"}), + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- Move client to tag. + awful.key({ modkey, "Shift" }, "#" .. i + 9, + function () + if client.focus then + local tag = client.focus.screen.tags[i] + if tag then + client.focus:move_to_tag(tag) + end + end + end, + {description = "move focused client to tag #"..i, group = "tag"}), + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- Toggle tag on focused client. + awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9, + function () + if client.focus then + local tag = client.focus.screen.tags[i] + if tag then + client.focus:toggle_tag(tag) + end + end + end, + {description = "toggle focused client on tag #" .. i, group = "tag"}) + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + ) + end + + return globalkeys +end +-- }}} + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/binding/clientbuttons.lua b/awesome/binding/clientbuttons.lua new file mode 100644 index 0000000..811a6e3 --- /dev/null +++ b/awesome/binding/clientbuttons.lua @@ -0,0 +1,30 @@ +-- Standard awesome library +local gears = require("gears") +local awful = require("awful") + +local _M = {} +local modkey = RC.vars.modkey + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function _M.get() + local clientbuttons = gears.table.join( + awful.button({ }, 1, function (c) + c:emit_signal("request::activate", "mouse_click", {raise = true}) + end), + awful.button({ modkey }, 1, function (c) + c:emit_signal("request::activate", "mouse_click", {raise = true}) + awful.mouse.client.move(c) + end), + awful.button({ modkey }, 3, function (c) + c:emit_signal("request::activate", "mouse_click", {raise = true}) + awful.mouse.client.resize(c) + end) + ) + + return clientbuttons +end + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/binding/clientkeys.lua b/awesome/binding/clientkeys.lua new file mode 100644 index 0000000..f15a14f --- /dev/null +++ b/awesome/binding/clientkeys.lua @@ -0,0 +1,62 @@ +-- Standard Awesome library +local gears = require("gears") +local awful = require("awful") +-- Custom Local Library +-- local titlebar = require("anybox.titlebar") + +local _M = {} +local modkey = RC.vars.modkey + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function _M.get() + local clientkeys = gears.table.join( + awful.key({ modkey, }, "f", + function (c) + c.fullscreen = not c.fullscreen + c:raise() + end, + {description = "toggle fullscreen", group = "client"}), + awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end, + {description = "close", group = "client"}), + awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle , + {description = "toggle floating", group = "client"}), + awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end, + {description = "move to master", group = "client"}), + awful.key({ modkey, }, "o", function (c) c:move_to_screen() end, + {description = "move to screen", group = "client"}), + awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end, + {description = "toggle keep on top", group = "client"}), + awful.key({ modkey, }, "n", + function (c) + -- The client currently has the input focus, so it cannot be + -- minimized, since minimized clients can't have the focus. + c.minimized = true + end , + {description = "minimize", group = "client"}), + awful.key({ modkey, }, "m", + function (c) + c.maximized = not c.maximized + c:raise() + end , + {description = "(un)maximize", group = "client"}), + awful.key({ modkey, "Control" }, "m", + function (c) + c.maximized_vertical = not c.maximized_vertical + c:raise() + end , + {description = "(un)maximize vertically", group = "client"}), + awful.key({ modkey, "Shift" }, "m", + function (c) + c.maximized_horizontal = not c.maximized_horizontal + c:raise() + end , + {description = "(un)maximize horizontally", group = "client"}) + ) + + return clientkeys +end + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/binding/globalbuttons.lua b/awesome/binding/globalbuttons.lua new file mode 100644 index 0000000..72425e1 --- /dev/null +++ b/awesome/binding/globalbuttons.lua @@ -0,0 +1,21 @@ +-- Standard awesome library +local gears = require("gears") +local awful = require("awful") + +local _M = {} + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function _M.get() + local globalbuttons = gears.table.join( + awful.button({ }, 3, function () RC.mainmenu:toggle() end), + awful.button({ }, 4, awful.tag.viewnext), + awful.button({ }, 5, awful.tag.viewprev) + ) + + return globalbuttons +end + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/binding/globalkeys.lua b/awesome/binding/globalkeys.lua new file mode 100644 index 0000000..3df49dc --- /dev/null +++ b/awesome/binding/globalkeys.lua @@ -0,0 +1,161 @@ +-- Standard awesome library +local gears = require("gears") +local awful = require("awful") +-- local hotkeys_popup = require("awful.hotkeys_popup").widget +local hotkeys_popup = require("awful.hotkeys_popup") +-- Menubar library +local menubar = require("menubar") + +-- Resource Configuration +local modkey = RC.vars.modkey +local terminal = RC.vars.terminal + +local _M = {} + +-- reading +-- https://awesomewm.org/wiki/Global_Keybindings + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function _M.get() + local globalkeys = gears.table.join( + awful.key({ modkey, }, "s", hotkeys_popup.show_help, + {description="show help", group="awesome"}), + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- Tag browsing + awful.key({ modkey, }, "Left", awful.tag.viewprev, + {description = "view previous", group = "tag"}), + awful.key({ modkey, }, "Right", awful.tag.viewnext, + {description = "view next", group = "tag"}), + awful.key({ modkey, }, "Escape", awful.tag.history.restore, + {description = "go back", group = "tag"}), + + awful.key({ modkey, }, "j", + function () + awful.client.focus.byidx( 1) + end, + {description = "focus next by index", group = "client"} + ), + awful.key({ modkey, }, "k", + function () + awful.client.focus.byidx(-1) + end, + {description = "focus previous by index", group = "client"} + ), + awful.key({ modkey, }, "w", function () RC.mainmenu:show() end, + {description = "show main menu", group = "awesome"}), + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- Layout manipulation + awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end, + {description = "swap with next client by index", group = "client"}), + awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end, + {description = "swap with previous client by index", group = "client"}), + awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end, + {description = "focus the next screen", group = "screen"}), + awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end, + {description = "focus the previous screen", group = "screen"}), + awful.key({ modkey, }, "u", awful.client.urgent.jumpto, + {description = "jump to urgent client", group = "client"}), + awful.key({ modkey, }, "Tab", + function () + awful.client.focus.history.previous() + if client.focus then + client.focus:raise() + end + end, + {description = "go back", group = "client"}), + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- Standard program + awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end, + {description = "open a terminal", group = "launcher"}), + awful.key({ modkey, "Control" }, "r", awesome.restart, + {description = "reload awesome", group = "awesome"}), + awful.key({ modkey, "Shift" }, "q", awesome.quit, + {description = "quit awesome", group = "awesome"}), + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- Layout manipulation + awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end, + {description = "increase master width factor", group = "layout"}), + awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end, + {description = "decrease master width factor", group = "layout"}), + awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end, + {description = "increase the number of master clients", group = "layout"}), + awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end, + {description = "decrease the number of master clients", group = "layout"}), + awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end, + {description = "increase the number of columns", group = "layout"}), + awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end, + {description = "decrease the number of columns", group = "layout"}), + awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end, + {description = "select next", group = "layout"}), + awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end, + {description = "select previous", group = "layout"}), + + awful.key({ modkey, "Control" }, "n", + function () + local c = awful.client.restore() + -- Focus restored client + if c then + c:emit_signal( + "request::activate", "key.unminimize", {raise = true} + ) + end + end, + {description = "restore minimized", group = "client"}), + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- Prompt + awful.key({ modkey }, "r", function () awful.screen.focused().mypromptbox:run() end, + {description = "run prompt", group = "launcher"}), + + awful.key({ modkey }, "x", + function () + awful.prompt.run { + prompt = "Run Lua code: ", + textbox = awful.screen.focused().mypromptbox.widget, + exe_callback = awful.util.eval, + history_path = awful.util.get_cache_dir() .. "/history_eval" + } + end, + {description = "lua execute prompt", group = "awesome"}), + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- Resize + --awful.key({ modkey, "Control" }, "Left", function () awful.client.moveresize( 20, 20, -40, -40) end), + --awful.key({ modkey, "Control" }, "Right", function () awful.client.moveresize(-20, -20, 40, 40) end), + awful.key({ modkey, "Control" }, "Down", + function () awful.client.moveresize( 0, 0, 0, -20) end), + awful.key({ modkey, "Control" }, "Up", + function () awful.client.moveresize( 0, 0, 0, 20) end), + awful.key({ modkey, "Control" }, "Left", + function () awful.client.moveresize( 0, 0, -20, 0) end), + awful.key({ modkey, "Control" }, "Right", + function () awful.client.moveresize( 0, 0, 20, 0) end), + + -- Move + awful.key({ modkey, "Shift" }, "Down", + function () awful.client.moveresize( 0, 20, 0, 0) end), + awful.key({ modkey, "Shift" }, "Up", + function () awful.client.moveresize( 0, -20, 0, 0) end), + awful.key({ modkey, "Shift" }, "Left", + function () awful.client.moveresize(-20, 0, 0, 0) end), + awful.key({ modkey, "Shift" }, "Right", + function () awful.client.moveresize( 20, 0, 0, 0) end), + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + -- Menubar + awful.key({ modkey }, "p", function() menubar.show() end, + {description = "show the menubar", group = "launcher"}) + + ) + + return globalkeys +end + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/deco/borders.lua b/awesome/deco/borders.lua new file mode 100644 index 0000000..e1267a9 --- /dev/null +++ b/awesome/deco/borders.lua @@ -0,0 +1,5 @@ +local beautiful = require("beautiful") + +-- Gaps between windows +beautiful.useless_gap = 3 +beautiful.gap_single_client = true \ No newline at end of file diff --git a/awesome/deco/statusbar.lua b/awesome/deco/statusbar.lua new file mode 100644 index 0000000..59a80b4 --- /dev/null +++ b/awesome/deco/statusbar.lua @@ -0,0 +1,87 @@ +-- Standard awesome library +local gears = require("gears") +local awful = require("awful") + +-- Wibox handling library +local wibox = require("wibox") + +-- Custom Local Library: Common Functional Decoration +local deco = { + wallpaper = require("deco.wallpaper"), + taglist = require("deco.taglist"), + tasklist = require("deco.tasklist"), + borders = require("deco.borders") +} + +local taglist_buttons = deco.taglist() +local tasklist_buttons = deco.tasklist() + +local _M = {} + +-- Custom Local Library: widgets +local volume_widget = require('awesome-wm-widgets.pactl-widget.volume') + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +-- {{{ Wibar +-- Create a textclock widget +mytextclock = wibox.widget.textclock('%l:%M %p ⁂ %a. %B %e, %Y ') + +awful.screen.connect_for_each_screen(function(s) + -- Wallpaper + set_wallpaper(s) + + -- Create a promptbox for each screen + s.mypromptbox = awful.widget.prompt() + + -- Create an imagebox widget which will contain an icon indicating which layout we're using. + -- We need one layoutbox per screen. + s.mylayoutbox = awful.widget.layoutbox(s) + s.mylayoutbox:buttons(gears.table.join( + awful.button({ }, 1, function () awful.layout.inc( 1) end), + awful.button({ }, 3, function () awful.layout.inc(-1) end), + awful.button({ }, 4, function () awful.layout.inc( 1) end), + awful.button({ }, 5, function () awful.layout.inc(-1) end) + )) + + -- Create a taglist widget + s.mytaglist = awful.widget.taglist { + screen = s, + filter = awful.widget.taglist.filter.all, + buttons = taglist_buttons + } + + -- Create a tasklist widget + s.mytasklist = awful.widget.tasklist { + screen = s, + filter = awful.widget.tasklist.filter.currenttags, + buttons = tasklist_buttons + } + + -- Create the wibox + s.mywibox = awful.wibar({ position = "top", screen = s, height = 24 }) + + -- Add widgets to the wibox + s.mywibox:setup { + layout = wibox.layout.align.horizontal, + { -- Left widgets + layout = wibox.layout.fixed.horizontal, +-- RC.launcher, + s.mytaglist, + s.mypromptbox, + }, + s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, +-- mykeyboardlayout, +-- wibox.widget.systray(), + volume_widget{ + widget_type = 'arc', + tooltip = 'true' + }, + mytextclock, + s.mylayoutbox + }, + } +end) +-- }}} diff --git a/awesome/deco/taglist.lua b/awesome/deco/taglist.lua new file mode 100644 index 0000000..bb2cb67 --- /dev/null +++ b/awesome/deco/taglist.lua @@ -0,0 +1,34 @@ +-- {{{ Required libraries +local gears = require("gears") +local awful = require("awful") +-- }}} + +local _M = {} + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function _M.get() + -- Create a wibox for each screen and add it + local taglist_buttons = gears.table.join( + awful.button({ }, 1, function(t) t:view_only() end), + awful.button({ modkey }, 1, function(t) + if client.focus then + client.focus:move_to_tag(t) + end + end), + awful.button({ }, 3, awful.tag.viewtoggle), + awful.button({ modkey }, 3, function(t) + if client.focus then + client.focus:toggle_tag(t) + end + end), + awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end), + awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end) + ) + + return taglist_buttons +end + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/deco/tasklist.lua b/awesome/deco/tasklist.lua new file mode 100644 index 0000000..a5802bf --- /dev/null +++ b/awesome/deco/tasklist.lua @@ -0,0 +1,39 @@ +-- {{{ Required libraries +local gears = require("gears") +local awful = require("awful") +-- }}} + +local _M = {} + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function _M.get() + local tasklist_buttons = gears.table.join( + awful.button({ }, 1, function (c) + if c == client.focus then + c.minimized = true + else + c:emit_signal( + "request::activate", + "tasklist", + {raise = true} + ) + end + end), + awful.button({ }, 3, function() + awful.menu.client_list({ theme = { width = 250 } }) + end), + awful.button({ }, 4, function () + awful.client.focus.byidx(1) + end), + awful.button({ }, 5, function () + awful.client.focus.byidx(-1) + end) + ) + + return tasklist_buttons +end + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/deco/titlebar.lua b/awesome/deco/titlebar.lua new file mode 100644 index 0000000..dd582f6 --- /dev/null +++ b/awesome/deco/titlebar.lua @@ -0,0 +1,47 @@ +-- module("anybox.titlebar", package.seeall) + +-- Standard awesome library +local gears = require("gears") +local awful = require("awful") + +-- Widget and layout library +local wibox = require("wibox") + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +-- Add a titlebar if titlebars_enabled is set to true in the rules. +client.connect_signal("request::titlebars", function(c) + -- buttons for the titlebar + local buttons = gears.table.join( + awful.button({ }, 1, function() + c:emit_signal("request::activate", "titlebar", {raise = true}) + awful.mouse.client.move(c) + end), + awful.button({ }, 3, function() + c:emit_signal("request::activate", "titlebar", {raise = true}) + awful.mouse.client.resize(c) + end) + ) + + awful.titlebar(c) : setup { + { -- Left + awful.titlebar.widget.iconwidget(c), + buttons = buttons, + layout = wibox.layout.fixed.horizontal + }, + { -- Middle + { -- Title + align = "left", + widget = awful.titlebar.widget.titlewidget(c) + }, + buttons = buttons, + layout = wibox.layout.flex.horizontal + }, + { -- Right + awful.titlebar.widget.floatingbutton (c), + awful.titlebar.widget.maximizedbutton(c), + layout = wibox.layout.fixed.horizontal() + }, + layout = wibox.layout.align.horizontal + } +end) diff --git a/awesome/deco/wallpaper.lua b/awesome/deco/wallpaper.lua new file mode 100644 index 0000000..2199e95 --- /dev/null +++ b/awesome/deco/wallpaper.lua @@ -0,0 +1,20 @@ +-- Standard awesome library +local gears = require("gears") +local beautiful = require("beautiful") + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function set_wallpaper(s) + -- Wallpaper + if beautiful.wallpaper then + local wallpaper = beautiful.wallpaper + -- If wallpaper is a function, call it with the screen + if type(wallpaper) == "function" then + wallpaper = wallpaper(s) + end + gears.wallpaper.maximized(wallpaper, s, false) + end +end + +-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution) +screen.connect_signal("property::geometry", set_wallpaper) diff --git a/awesome/main/error-handling.lua b/awesome/main/error-handling.lua new file mode 100644 index 0000000..ebf0bf1 --- /dev/null +++ b/awesome/main/error-handling.lua @@ -0,0 +1,31 @@ +-- Notification library +local naughty = require("naughty") + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +-- Check if awesome encountered an error during startup and fell back to +-- another config (This code will only ever execute for the fallback config) +if awesome.startup_errors then + naughty.notify({ + preset = naughty.config.presets.critical, + title = "Oops, there were errors during startup!", + text = awesome.startup_errors + }) +end + +-- Handle runtime errors after startup +do + local in_error = false + awesome.connect_signal("debug::error", function (err) + -- Make sure we don't go into an endless error loop + if in_error then return end + in_error = true + + naughty.notify({ + preset = naughty.config.presets.critical, + title = "Oops, an error happened!", + text = tostring(err) + }) + in_error = false + end) +end diff --git a/awesome/main/layouts.lua b/awesome/main/layouts.lua new file mode 100644 index 0000000..bcc4688 --- /dev/null +++ b/awesome/main/layouts.lua @@ -0,0 +1,39 @@ +-- Standard awesome library +local awful = require("awful") + +local _M = {} + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function _M.get () + -- Table of layouts to cover with awful.layout.inc, order matters. + local layouts = { + awful.layout.suit.floating, -- 1: + + awful.layout.suit.tile, -- 2: + awful.layout.suit.tile.left, -- 3: + awful.layout.suit.tile.bottom, -- 4: + awful.layout.suit.tile.top, -- 5: + + awful.layout.suit.fair, -- 6: + awful.layout.suit.fair.horizontal, -- 7: + +-- awful.layout.suit.spiral, +-- awful.layout.suit.spiral.dwindle, + +-- awful.layout.suit.max, +-- awful.layout.suit.max.fullscreen, +-- awful.layout.suit.magnifier, + +-- awful.layout.suit.corner.nw +-- awful.layout.suit.corner.ne, +-- awful.layout.suit.corner.sw, +-- awful.layout.suit.corner.se, + } + + return layouts +end + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/main/menu.lua b/awesome/main/menu.lua new file mode 100644 index 0000000..b53a0e1 --- /dev/null +++ b/awesome/main/menu.lua @@ -0,0 +1,98 @@ +-- Standard awesome library +local awful = require("awful") +local hotkeys_popup = require("awful.hotkeys_popup").widget +-- Theme handling library +local beautiful = require("beautiful") -- for awesome.icon + +local M = {} -- menu +local _M = {} -- module + +-- reading +-- https://awesomewm.org/apidoc/popups%20and%20bars/awful.menu.html + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +-- This is used later as the default terminal and editor to run. +-- local terminal = "xfce4-terminal" +local terminal = RC.vars.terminal + +-- Variable definitions +-- This is used later as the default terminal and editor to run. +local editor = os.getenv("EDITOR") or "nano" +local editor_cmd = terminal .. " -e " .. editor + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +M.awesome = { + { "hotkeys", function() + hotkeys_popup.show_help(nil, awful.screen.focused()) + end }, + { "manual", terminal .. " -e man awesome" }, + { "edit config", editor_cmd .. " " .. awesome.conffile }, + { "terminal", terminal }, + { "restart", awesome.restart }, + { "quit", function() awesome.quit() end } +} + +M.network = { + { "firefox", "firefox" }, + { "discord", "flatpak run com.discordapp.Discord" }, + { "thunderbird", "thunderbird" }, + { "steam", "flatpak run com.valvesoftware.Steam" }, + { "qbittorrent", "qbittorrent" }, + { "keepassxc", "keepassxc" }, +} + +M.develop = { + { "vs code", "flatpak run com.visualstudio.code" }, + { "bless", "bless" }, + { "beekeeper studio", "flatpak run io.beekeeperstudio.Studio" }, + { "sqlite browser", "sqlitebrowser" } +} + +M.emulators = { + { "citra", "flatpak run org.citra_emu.citra" }, + { "dolphin", "flatpak run org.DolphinEmu.dolphin-emu" }, + { "yuzu", "flatpak run org.yuzu_emu.yuzu"} +} + +M.games = { + { "emulators", M.emulators }, + { "vintage story", "flatpak run at.vintagestory.VintageStory" }, + { "osu!", "flatpak run sh.ppy.osu" } +} + +M.utils = { + { "catfish", "catfish" }, + { "text pieces", "flatpak run com.github.liferooter.textpieces" }, + { "flatseal", "flatpak run com.github.tchx84.Flatseal" }, + { "piper", "piper" } +} + +M.media = { + { "youtube", "/usr/lib64/chromium-browser/chromium-browser.sh --profile-directory=Default --app-id=agimnkijcaahngcdmfeangaknmldooml"}, + { "spotify", "flatpak run com.spotify.Client" } +} +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function _M.get() + + -- Main Menu + local menu_items = { + { "awesome", M.awesome, beautiful.awesome_subicon }, + { "terminal", terminal }, + { "thunar", "Thunar" }, + { "www", M.network }, + { "media", M.media }, + { "dev", M.develop }, + { "games", M.games }, + { "utils", M.utils }, +-- { "maim (select)", "maim -s $(HOME)$(date +%s)" }, + } + + return menu_items +end + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/main/rules.lua b/awesome/main/rules.lua new file mode 100644 index 0000000..9a039a4 --- /dev/null +++ b/awesome/main/rules.lua @@ -0,0 +1,85 @@ +-- Standard awesome library +local awful = require("awful") +-- Theme handling library +local beautiful = require("beautiful") + +local _M = {} + +-- reading +-- https://awesomewm.org/apidoc/libraries/awful.rules.html + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function _M.get(clientkeys, clientbuttons) + local rules = { + + -- All clients will match this rule. + { rule = { }, + properties = { + border_width = beautiful.border_width, + border_color = beautiful.border_normal, + focus = awful.client.focus.filter, + raise = true, + keys = clientkeys, + buttons = clientbuttons, + screen = awful.screen.preferred, + placement = awful.placement.no_overlap+awful.placement.no_offscreen + } + }, + + -- Floating clients. + { rule_any = { + instance = { + "DTA", -- Firefox addon DownThemAll. + "copyq", -- Includes session name in class. + "pinentry", + }, + class = { + "Arandr", + "Blueman-manager", + "Gpick", + "Kruler", + "MessageWin", -- kalarm. + "Sxiv", + "Tor Browser", -- Needs a fixed window size to avoid fingerprinting by screen size. + "Wpa_gui", + "veromix", + "xtightvncviewer"}, + + -- Note that the name property shown in xprop might be set slightly after creation of the client + -- and the name shown there might not match defined rules here. + name = { + "Event Tester", -- xev. + }, + role = { + "AlarmWindow", -- Thunderbird's calendar. + "ConfigManager", -- Thunderbird's about:config. + "pop-up", -- e.g. Google Chrome's (detached) Developer Tools. + } + }, + properties = { + floating = true + } + }, + + -- Add titlebars to normal clients and dialogs + { rule_any = { + type = { "normal", "dialog" } + }, + properties = { + titlebars_enabled = false + } + }, + + -- Set Firefox to always map on the tag named "2" on screen 1. + -- { rule = { class = "Firefox" }, + -- properties = { screen = 1, tag = "2" } }, + + } + + return rules +end + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/main/signals.lua b/awesome/main/signals.lua new file mode 100644 index 0000000..a38f882 --- /dev/null +++ b/awesome/main/signals.lua @@ -0,0 +1,41 @@ +-- Standard awesome library +local gears = require("gears") +local awful = require("awful") + +-- Widget and layout library +local wibox = require("wibox") + +-- Theme handling library +local beautiful = require("beautiful") + +-- Custom Local Library: Common Functional Decoration +require("deco.titlebar") + +-- reading +-- https://awesomewm.org/apidoc/classes/signals.html + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +-- {{{ Signals +-- Signal function to execute when a new client appears. +client.connect_signal("manage", function (c) + -- Set the windows at the slave, + -- i.e. put it at the end of others instead of setting it master. + -- if not awesome.startup then awful.client.setslave(c) end + + if awesome.startup + and not c.size_hints.user_position + and not c.size_hints.program_position then + -- Prevent clients from being unreachable after screen count changes. + awful.placement.no_offscreen(c) + end +end) + +-- Enable sloppy focus, so that focus follows mouse. +client.connect_signal("mouse::enter", function(c) + c:emit_signal("request::activate", "mouse_enter", {raise = false}) +end) + +client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end) +client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end) +-- }}} diff --git a/awesome/main/startup.lua b/awesome/main/startup.lua new file mode 100644 index 0000000..a6f328c --- /dev/null +++ b/awesome/main/startup.lua @@ -0,0 +1,5 @@ +local awful = require("awful") +local os = require("os") + +awful.spawn.single_instance("picom --config /home/nu/.config/picom/picom.conf") +-- awful.spawn.once("redshift -O 3800") diff --git a/awesome/main/tags.lua b/awesome/main/tags.lua new file mode 100644 index 0000000..e082244 --- /dev/null +++ b/awesome/main/tags.lua @@ -0,0 +1,31 @@ +-- Standard awesome library +local awful = require("awful") + +local _M = {} + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +function _M.get () + local tags = {} + + awful.tag.add("➊ home", + { + layout = awful.layout.suit.floating, + }) + + awful.tag.add("➋ code", + { + layout = awful.layout.suit.tile, + }) + + awful.tag.add("➌ art", + { + layout = awful.layout.suit.floating, + }) + + return tags +end + +-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + +return setmetatable({}, { __call = function(_, ...) return _M.get(...) end }) diff --git a/awesome/main/user-variables.lua b/awesome/main/user-variables.lua new file mode 100644 index 0000000..c2d0cbf --- /dev/null +++ b/awesome/main/user-variables.lua @@ -0,0 +1,25 @@ +-- {{{ Global Variable Definitions +-- moved here in module as local variable +-- }}} + +local home = os.getenv("HOME") + +local _M = { + -- This is used later as the default terminal and editor to run. + -- terminal = "xterm", + terminal = "alacritty", + + -- Default modkey. + -- Usually, Mod4 is the key with a logo between Control and Alt. + -- If you do not like this or do not have such a key, + -- I suggest you to remap Mod4 to another key using xmodmap or other tools. + -- However, you can use another modifier like Mod1, but it may interact with others. + modkey = "Mod4", + + -- user defined wallpaper + wallpaper = "/usr/share/backgrounds/custom/space_station.jpg", + --wallpaper = home .. "/Pictures/your-wallpaper-here.jpg", +} + +return _M + diff --git a/awesome/rc.lua b/awesome/rc.lua new file mode 100644 index 0000000..7637e53 --- /dev/null +++ b/awesome/rc.lua @@ -0,0 +1,104 @@ +-- If LuaRocks is installed, make sure that packages installed through it are +-- found (e.g. lgi). If LuaRocks is not installed, do nothing. +pcall(require, "luarocks.loader") + +-- Standard awesome library +local gears = require("gears") +local awful = require("awful") + +-- Theme handling library +local beautiful = require("beautiful") + +-- Miscellanous awesome library +local menubar = require("menubar") + +RC = {} -- global namespace, on top before require any modules +RC.vars = require("main.user-variables") + +-- {{{ Error handling -- }}} +require("main.error-handling") + +-- {{{ Variable definitions +-- Themes define colours, icons, font and wallpapers. +beautiful.init("~/.config/awesome/themes/spacestation/theme.lua") +beautiful.wallpaper = RC.vars.wallpaper +-- }}} + +modkey = RC.vars.modkey + +-- Custom Local Library +local main = { + layouts = require("main.layouts"), + tags = require("main.tags"), + menu = require("main.menu"), + rules = require("main.rules"), +} + +-- Custom Local Library: Keys and Mouse Binding +local binding = { + globalbuttons = require("binding.globalbuttons"), + clientbuttons = require("binding.clientbuttons"), + globalkeys = require("binding.globalkeys"), + bindtotags = require("binding.bindtotags"), + clientkeys = require("binding.clientkeys") +} + +-- {{{ Layouts +-- Table of layouts to cover with awful.layout.inc, order matters. +-- a variable needed in main.tags, and statusbar +-- awful.layout.layouts = { ... } +RC.layouts = main.layouts() +-- }}} + +-- {{{ Tags +-- Define a tag table which hold all screen tags. +-- a variable needed in rules, tasklist, and globalkeys +RC.tags = main.tags() +-- }}} + +-- {{{ Menu +-- Create a laucher widget and a main menu +RC.mainmenu = awful.menu({ items = main.menu() }) -- in globalkeys + +-- a variable needed in statusbar (helper) +RC.launcher = awful.widget.launcher( + { image = beautiful.awesome_icon, menu = RC.mainmenu } +) + +-- Menubar configuration +-- Set the terminal for applications that require it +menubar.utils.terminal = RC.vars.terminal + +-- }}} + +-- {{{ Mouse and Key bindings +RC.globalkeys = binding.globalkeys() +RC.globalkeys = binding.bindtotags(RC.globalkeys) + +-- Set root +root.buttons(binding.globalbuttons()) +root.keys(RC.globalkeys) +-- }}} + +-- Keyboard map indicator and switcher +mykeyboardlayout = awful.widget.keyboardlayout() + +-- {{{ Statusbar: Wibar +require("deco.statusbar") +-- }}} + +-- {{{ Rules +-- Rules to apply to new clients (through the "manage" signal). +awful.rules.rules = main.rules( + binding.clientkeys(), + binding.clientbuttons() +) +-- }}} + +-- {{{ Signals +require("main.signals") +-- }}} + +-- {{{ Startup applications +require("main.startup") +-- }}} \ No newline at end of file diff --git a/awesome/themes/spacestation/layouts/cornerne.png b/awesome/themes/spacestation/layouts/cornerne.png new file mode 100644 index 0000000..c85bd56 Binary files /dev/null and b/awesome/themes/spacestation/layouts/cornerne.png differ diff --git a/awesome/themes/spacestation/layouts/cornernew.png b/awesome/themes/spacestation/layouts/cornernew.png new file mode 100644 index 0000000..c3fd986 Binary files /dev/null and b/awesome/themes/spacestation/layouts/cornernew.png differ diff --git a/awesome/themes/spacestation/layouts/cornernw.png b/awesome/themes/spacestation/layouts/cornernw.png new file mode 100644 index 0000000..dfe78b3 Binary files /dev/null and b/awesome/themes/spacestation/layouts/cornernw.png differ diff --git a/awesome/themes/spacestation/layouts/cornernww.png b/awesome/themes/spacestation/layouts/cornernww.png new file mode 100644 index 0000000..f489010 Binary files /dev/null and b/awesome/themes/spacestation/layouts/cornernww.png differ diff --git a/awesome/themes/spacestation/layouts/cornerse.png b/awesome/themes/spacestation/layouts/cornerse.png new file mode 100644 index 0000000..023ae79 Binary files /dev/null and b/awesome/themes/spacestation/layouts/cornerse.png differ diff --git a/awesome/themes/spacestation/layouts/cornersew.png b/awesome/themes/spacestation/layouts/cornersew.png new file mode 100644 index 0000000..f7cfa1c Binary files /dev/null and b/awesome/themes/spacestation/layouts/cornersew.png differ diff --git a/awesome/themes/spacestation/layouts/cornersw.png b/awesome/themes/spacestation/layouts/cornersw.png new file mode 100644 index 0000000..c1453c9 Binary files /dev/null and b/awesome/themes/spacestation/layouts/cornersw.png differ diff --git a/awesome/themes/spacestation/layouts/cornersww.png b/awesome/themes/spacestation/layouts/cornersww.png new file mode 100644 index 0000000..a65a043 Binary files /dev/null and b/awesome/themes/spacestation/layouts/cornersww.png differ diff --git a/awesome/themes/spacestation/layouts/dwindle.png b/awesome/themes/spacestation/layouts/dwindle.png new file mode 100644 index 0000000..9902d22 Binary files /dev/null and b/awesome/themes/spacestation/layouts/dwindle.png differ diff --git a/awesome/themes/spacestation/layouts/dwindlew.png b/awesome/themes/spacestation/layouts/dwindlew.png new file mode 100644 index 0000000..9199049 Binary files /dev/null and b/awesome/themes/spacestation/layouts/dwindlew.png differ diff --git a/awesome/themes/spacestation/layouts/fairh.png b/awesome/themes/spacestation/layouts/fairh.png new file mode 100644 index 0000000..d41deea Binary files /dev/null and b/awesome/themes/spacestation/layouts/fairh.png differ diff --git a/awesome/themes/spacestation/layouts/fairhw.png b/awesome/themes/spacestation/layouts/fairhw.png new file mode 100644 index 0000000..bb50e3a Binary files /dev/null and b/awesome/themes/spacestation/layouts/fairhw.png differ diff --git a/awesome/themes/spacestation/layouts/fairv.png b/awesome/themes/spacestation/layouts/fairv.png new file mode 100644 index 0000000..f5f0288 Binary files /dev/null and b/awesome/themes/spacestation/layouts/fairv.png differ diff --git a/awesome/themes/spacestation/layouts/fairvw.png b/awesome/themes/spacestation/layouts/fairvw.png new file mode 100644 index 0000000..4f4ed52 Binary files /dev/null and b/awesome/themes/spacestation/layouts/fairvw.png differ diff --git a/awesome/themes/spacestation/layouts/floating.png b/awesome/themes/spacestation/layouts/floating.png new file mode 100644 index 0000000..b8061a0 Binary files /dev/null and b/awesome/themes/spacestation/layouts/floating.png differ diff --git a/awesome/themes/spacestation/layouts/floatingw.png b/awesome/themes/spacestation/layouts/floatingw.png new file mode 100644 index 0000000..4815894 Binary files /dev/null and b/awesome/themes/spacestation/layouts/floatingw.png differ diff --git a/awesome/themes/spacestation/layouts/fullscreen.png b/awesome/themes/spacestation/layouts/fullscreen.png new file mode 100644 index 0000000..d02f6fc Binary files /dev/null and b/awesome/themes/spacestation/layouts/fullscreen.png differ diff --git a/awesome/themes/spacestation/layouts/fullscreenw.png b/awesome/themes/spacestation/layouts/fullscreenw.png new file mode 100644 index 0000000..5c35bfa Binary files /dev/null and b/awesome/themes/spacestation/layouts/fullscreenw.png differ diff --git a/awesome/themes/spacestation/layouts/magnifier.png b/awesome/themes/spacestation/layouts/magnifier.png new file mode 100644 index 0000000..2925414 Binary files /dev/null and b/awesome/themes/spacestation/layouts/magnifier.png differ diff --git a/awesome/themes/spacestation/layouts/magnifierw.png b/awesome/themes/spacestation/layouts/magnifierw.png new file mode 100644 index 0000000..6209556 Binary files /dev/null and b/awesome/themes/spacestation/layouts/magnifierw.png differ diff --git a/awesome/themes/spacestation/layouts/max.png b/awesome/themes/spacestation/layouts/max.png new file mode 100644 index 0000000..8d20844 Binary files /dev/null and b/awesome/themes/spacestation/layouts/max.png differ diff --git a/awesome/themes/spacestation/layouts/maxw.png b/awesome/themes/spacestation/layouts/maxw.png new file mode 100644 index 0000000..85f5ce3 Binary files /dev/null and b/awesome/themes/spacestation/layouts/maxw.png differ diff --git a/awesome/themes/spacestation/layouts/spiral.png b/awesome/themes/spacestation/layouts/spiral.png new file mode 100644 index 0000000..d9434be Binary files /dev/null and b/awesome/themes/spacestation/layouts/spiral.png differ diff --git a/awesome/themes/spacestation/layouts/spiralw.png b/awesome/themes/spacestation/layouts/spiralw.png new file mode 100644 index 0000000..b78dd86 Binary files /dev/null and b/awesome/themes/spacestation/layouts/spiralw.png differ diff --git a/awesome/themes/spacestation/layouts/tile.png b/awesome/themes/spacestation/layouts/tile.png new file mode 100644 index 0000000..3ede21e Binary files /dev/null and b/awesome/themes/spacestation/layouts/tile.png differ diff --git a/awesome/themes/spacestation/layouts/tilebottom.png b/awesome/themes/spacestation/layouts/tilebottom.png new file mode 100644 index 0000000..6f8c257 Binary files /dev/null and b/awesome/themes/spacestation/layouts/tilebottom.png differ diff --git a/awesome/themes/spacestation/layouts/tilebottomw.png b/awesome/themes/spacestation/layouts/tilebottomw.png new file mode 100644 index 0000000..a1de7b2 Binary files /dev/null and b/awesome/themes/spacestation/layouts/tilebottomw.png differ diff --git a/awesome/themes/spacestation/layouts/tileleft.png b/awesome/themes/spacestation/layouts/tileleft.png new file mode 100644 index 0000000..31d6870 Binary files /dev/null and b/awesome/themes/spacestation/layouts/tileleft.png differ diff --git a/awesome/themes/spacestation/layouts/tileleftw.png b/awesome/themes/spacestation/layouts/tileleftw.png new file mode 100644 index 0000000..cf14c25 Binary files /dev/null and b/awesome/themes/spacestation/layouts/tileleftw.png differ diff --git a/awesome/themes/spacestation/layouts/tiletop.png b/awesome/themes/spacestation/layouts/tiletop.png new file mode 100644 index 0000000..98cade2 Binary files /dev/null and b/awesome/themes/spacestation/layouts/tiletop.png differ diff --git a/awesome/themes/spacestation/layouts/tiletopw.png b/awesome/themes/spacestation/layouts/tiletopw.png new file mode 100644 index 0000000..d1d0872 Binary files /dev/null and b/awesome/themes/spacestation/layouts/tiletopw.png differ diff --git a/awesome/themes/spacestation/layouts/tilew.png b/awesome/themes/spacestation/layouts/tilew.png new file mode 100644 index 0000000..fde2ca4 Binary files /dev/null and b/awesome/themes/spacestation/layouts/tilew.png differ diff --git a/awesome/themes/spacestation/submenu.png b/awesome/themes/spacestation/submenu.png new file mode 100644 index 0000000..b2778e2 Binary files /dev/null and b/awesome/themes/spacestation/submenu.png differ diff --git a/awesome/themes/spacestation/taglist/squarefw.png b/awesome/themes/spacestation/taglist/squarefw.png new file mode 100644 index 0000000..2a86430 Binary files /dev/null and b/awesome/themes/spacestation/taglist/squarefw.png differ diff --git a/awesome/themes/spacestation/taglist/squarew.png b/awesome/themes/spacestation/taglist/squarew.png new file mode 100644 index 0000000..913f2ca Binary files /dev/null and b/awesome/themes/spacestation/taglist/squarew.png differ diff --git a/awesome/themes/spacestation/theme.lua b/awesome/themes/spacestation/theme.lua new file mode 100644 index 0000000..00cebf3 --- /dev/null +++ b/awesome/themes/spacestation/theme.lua @@ -0,0 +1,143 @@ +--------------------------- +-- Default awesome theme -- +--------------------------- + +local theme_assets = require("beautiful.theme_assets") +local xresources = require("beautiful.xresources") +local dpi = xresources.apply_dpi + +local gfs = require("gears.filesystem") +local themes_path = gfs.get_themes_dir() + +local theme = {} + +theme.font = "Fira Code 9" + +theme.bg_normal = "#ffffff4f" +theme.bg_focus = "#e1b661" +theme.bg_urgent = "#233871" +theme.bg_minimize = "#ffffff00" +theme.bg_systray = "#ffffff00" + +theme.fg_normal = "#233871" +theme.fg_focus = "#233871" +theme.fg_urgent = "#e1b661" +theme.fg_minimize = "#23387180" + +theme.border_width = 0 +theme.border_normal = "#f0eef1" +theme.border_focus = "#e1b661" +theme.border_marked = "#ff8e9d" + +theme.taglist_bg_focus = "#e1b661" + +theme.notification_bg = "#ffffff4f" +theme.notification_fg = "#233871" +theme.notification_border_color = "#233871" + +theme.tooltip_fg_color = "#233871" +theme.tooltip_bg_color = "#ffffff4f" +theme.tooltip_border_color = "#233871" + +theme.prompt_bg = "#ffffff4f" + +-- There are other variable sets +-- overriding the default one when +-- defined, the sets are: +-- taglist_[bg|fg]_[focus|urgent|occupied|empty|volatile] +-- tasklist_[bg|fg]_[focus|urgent] +-- titlebar_[bg|fg]_[normal|focus] +-- tooltip_[font|opacity|fg_color|bg_color|border_width|border_color] +-- mouse_finder_[color|timeout|animate_timeout|radius|factor] +-- prompt_[fg|bg|fg_cursor|bg_cursor|font] +-- hotkeys_[bg|fg|border_width|border_color|shape|opacity|modifiers_fg|label_bg|label_fg|group_margin|font|description_font] +-- Example: +--theme.taglist_bg_focus = "#ff0000" + +-- Generate taglist squares: +local taglist_square_size = dpi(4) +theme.taglist_squares_sel = theme_assets.taglist_squares_sel( + taglist_square_size, theme.fg_normal +) +theme.taglist_squares_unsel = theme_assets.taglist_squares_unsel( + taglist_square_size, theme.fg_normal +) + +-- Variables set for theming notifications: +-- notification_font +-- notification_[bg|fg] +-- notification_[width|height|margin] +-- notification_[border_color|border_width|shape|opacity] + +-- Variables set for theming the menu: +-- menu_[bg|fg]_[normal|focus] +-- menu_[border_color|border_width] +theme.menu_submenu_icon = themes_path.."default/submenu.png" +theme.menu_height = dpi(15) +theme.menu_width = dpi(100) +theme.menu_bg_normal = "#ffffff4f" +theme.menu_bg_focus = "#e1b661" +theme.menu_border_color = "#233871" + +-- You can add as many variables as +-- you wish and access them by using +-- beautiful.variable in your rc.lua +--theme.bg_widget = "#cc0000" + +-- Define the image to load +theme.titlebar_close_button_normal = themes_path.."default/titlebar/close_normal.png" +theme.titlebar_close_button_focus = themes_path.."default/titlebar/close_focus.png" + +theme.titlebar_minimize_button_normal = themes_path.."default/titlebar/minimize_normal.png" +theme.titlebar_minimize_button_focus = themes_path.."default/titlebar/minimize_focus.png" + +theme.titlebar_ontop_button_normal_inactive = themes_path.."default/titlebar/ontop_normal_inactive.png" +theme.titlebar_ontop_button_focus_inactive = themes_path.."default/titlebar/ontop_focus_inactive.png" +theme.titlebar_ontop_button_normal_active = themes_path.."default/titlebar/ontop_normal_active.png" +theme.titlebar_ontop_button_focus_active = themes_path.."default/titlebar/ontop_focus_active.png" + +theme.titlebar_sticky_button_normal_inactive = themes_path.."default/titlebar/sticky_normal_inactive.png" +theme.titlebar_sticky_button_focus_inactive = themes_path.."default/titlebar/sticky_focus_inactive.png" +theme.titlebar_sticky_button_normal_active = themes_path.."default/titlebar/sticky_normal_active.png" +theme.titlebar_sticky_button_focus_active = themes_path.."default/titlebar/sticky_focus_active.png" + +theme.titlebar_floating_button_normal_inactive = themes_path.."default/titlebar/floating_normal_inactive.png" +theme.titlebar_floating_button_focus_inactive = themes_path.."default/titlebar/floating_focus_inactive.png" +theme.titlebar_floating_button_normal_active = themes_path.."default/titlebar/floating_normal_active.png" +theme.titlebar_floating_button_focus_active = themes_path.."default/titlebar/floating_focus_active.png" + +theme.titlebar_maximized_button_normal_inactive = themes_path.."default/titlebar/maximized_normal_inactive.png" +theme.titlebar_maximized_button_focus_inactive = themes_path.."default/titlebar/maximized_focus_inactive.png" +theme.titlebar_maximized_button_normal_active = themes_path.."default/titlebar/maximized_normal_active.png" +theme.titlebar_maximized_button_focus_active = themes_path.."default/titlebar/maximized_focus_active.png" + +-- You can use your own layout icons like this: +theme.layout_fairh = themes_path.."default/layouts/fairhw.png" +theme.layout_fairv = themes_path.."default/layouts/fairvw.png" +theme.layout_floating = themes_path.."default/layouts/floatingw.png" +theme.layout_magnifier = themes_path.."default/layouts/magnifierw.png" +theme.layout_max = themes_path.."default/layouts/maxw.png" +theme.layout_fullscreen = themes_path.."default/layouts/fullscreenw.png" +theme.layout_tilebottom = themes_path.."default/layouts/tilebottomw.png" +theme.layout_tileleft = themes_path.."default/layouts/tileleftw.png" +theme.layout_tile = themes_path.."default/layouts/tilew.png" +theme.layout_tiletop = themes_path.."default/layouts/tiletopw.png" +theme.layout_spiral = themes_path.."default/layouts/spiralw.png" +theme.layout_dwindle = themes_path.."default/layouts/dwindlew.png" +theme.layout_cornernw = themes_path.."default/layouts/cornernww.png" +theme.layout_cornerne = themes_path.."default/layouts/cornernew.png" +theme.layout_cornersw = themes_path.."default/layouts/cornersww.png" +theme.layout_cornerse = themes_path.."default/layouts/cornersew.png" + +-- Generate Awesome icon: +theme.awesome_icon = theme_assets.awesome_icon( + theme.menu_height, theme.bg_focus, theme.fg_focus +) + +-- Define the icon theme for application icons. If not set then the icons +-- from /usr/share/icons and /usr/share/icons/hicolor will be used. +theme.icon_theme = nil + +return theme + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/awesome/themes/spacestation/titlebar/close_focus.png b/awesome/themes/spacestation/titlebar/close_focus.png new file mode 100644 index 0000000..01ef825 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/close_focus.png differ diff --git a/awesome/themes/spacestation/titlebar/close_normal.png b/awesome/themes/spacestation/titlebar/close_normal.png new file mode 100644 index 0000000..5448ed8 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/close_normal.png differ diff --git a/awesome/themes/spacestation/titlebar/floating_focus_active.png b/awesome/themes/spacestation/titlebar/floating_focus_active.png new file mode 100644 index 0000000..82dcc7c Binary files /dev/null and b/awesome/themes/spacestation/titlebar/floating_focus_active.png differ diff --git a/awesome/themes/spacestation/titlebar/floating_focus_inactive.png b/awesome/themes/spacestation/titlebar/floating_focus_inactive.png new file mode 100644 index 0000000..c19ba80 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/floating_focus_inactive.png differ diff --git a/awesome/themes/spacestation/titlebar/floating_normal_active.png b/awesome/themes/spacestation/titlebar/floating_normal_active.png new file mode 100644 index 0000000..62342d1 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/floating_normal_active.png differ diff --git a/awesome/themes/spacestation/titlebar/floating_normal_inactive.png b/awesome/themes/spacestation/titlebar/floating_normal_inactive.png new file mode 100644 index 0000000..e2bbdfa Binary files /dev/null and b/awesome/themes/spacestation/titlebar/floating_normal_inactive.png differ diff --git a/awesome/themes/spacestation/titlebar/maximized_focus_active.png b/awesome/themes/spacestation/titlebar/maximized_focus_active.png new file mode 100644 index 0000000..d7dffd7 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/maximized_focus_active.png differ diff --git a/awesome/themes/spacestation/titlebar/maximized_focus_inactive.png b/awesome/themes/spacestation/titlebar/maximized_focus_inactive.png new file mode 100644 index 0000000..844389f Binary files /dev/null and b/awesome/themes/spacestation/titlebar/maximized_focus_inactive.png differ diff --git a/awesome/themes/spacestation/titlebar/maximized_normal_active.png b/awesome/themes/spacestation/titlebar/maximized_normal_active.png new file mode 100644 index 0000000..a705f81 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/maximized_normal_active.png differ diff --git a/awesome/themes/spacestation/titlebar/maximized_normal_inactive.png b/awesome/themes/spacestation/titlebar/maximized_normal_inactive.png new file mode 100644 index 0000000..4c1ab1f Binary files /dev/null and b/awesome/themes/spacestation/titlebar/maximized_normal_inactive.png differ diff --git a/awesome/themes/spacestation/titlebar/minimize_focus.png b/awesome/themes/spacestation/titlebar/minimize_focus.png new file mode 100644 index 0000000..caaceb2 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/minimize_focus.png differ diff --git a/awesome/themes/spacestation/titlebar/minimize_normal.png b/awesome/themes/spacestation/titlebar/minimize_normal.png new file mode 100644 index 0000000..36621d0 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/minimize_normal.png differ diff --git a/awesome/themes/spacestation/titlebar/ontop_focus_active.png b/awesome/themes/spacestation/titlebar/ontop_focus_active.png new file mode 100644 index 0000000..312c00b Binary files /dev/null and b/awesome/themes/spacestation/titlebar/ontop_focus_active.png differ diff --git a/awesome/themes/spacestation/titlebar/ontop_focus_inactive.png b/awesome/themes/spacestation/titlebar/ontop_focus_inactive.png new file mode 100644 index 0000000..a48e1c5 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/ontop_focus_inactive.png differ diff --git a/awesome/themes/spacestation/titlebar/ontop_normal_active.png b/awesome/themes/spacestation/titlebar/ontop_normal_active.png new file mode 100644 index 0000000..117a203 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/ontop_normal_active.png differ diff --git a/awesome/themes/spacestation/titlebar/ontop_normal_inactive.png b/awesome/themes/spacestation/titlebar/ontop_normal_inactive.png new file mode 100644 index 0000000..d3a10c8 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/ontop_normal_inactive.png differ diff --git a/awesome/themes/spacestation/titlebar/sticky_focus_active.png b/awesome/themes/spacestation/titlebar/sticky_focus_active.png new file mode 100644 index 0000000..814499b Binary files /dev/null and b/awesome/themes/spacestation/titlebar/sticky_focus_active.png differ diff --git a/awesome/themes/spacestation/titlebar/sticky_focus_inactive.png b/awesome/themes/spacestation/titlebar/sticky_focus_inactive.png new file mode 100644 index 0000000..21b000d Binary files /dev/null and b/awesome/themes/spacestation/titlebar/sticky_focus_inactive.png differ diff --git a/awesome/themes/spacestation/titlebar/sticky_normal_active.png b/awesome/themes/spacestation/titlebar/sticky_normal_active.png new file mode 100644 index 0000000..bdb5595 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/sticky_normal_active.png differ diff --git a/awesome/themes/spacestation/titlebar/sticky_normal_inactive.png b/awesome/themes/spacestation/titlebar/sticky_normal_inactive.png new file mode 100644 index 0000000..a96b9b1 Binary files /dev/null and b/awesome/themes/spacestation/titlebar/sticky_normal_inactive.png differ diff --git a/picom/picom.conf b/picom/picom.conf new file mode 100644 index 0000000..1a8af60 --- /dev/null +++ b/picom/picom.conf @@ -0,0 +1,406 @@ +################################# +# Shadows # +################################# + + +# Enabled client-side shadows on windows. Note desktop windows +# (windows with '_NET_WM_WINDOW_TYPE_DESKTOP') never get shadow, +# unless explicitly requested using the wintypes option. +shadow = true; + +# The blur radius for shadows, in pixels. (defaults to 12) +shadow-radius = 12; + +# The opacity of shadows. (0.0 - 1.0, defaults to 0.75) +shadow-opacity = .70 + +# The left offset for shadows, in pixels. (defaults to -15) +shadow-offset-x = -12; + +# The top offset for shadows, in pixels. (defaults to -15) +shadow-offset-y = -12; + +# Red color value of shadow (0.0 - 1.0, defaults to 0). +# shadow-red = 0 + +# Green color value of shadow (0.0 - 1.0, defaults to 0). +# shadow-green = 0 + +# Blue color value of shadow (0.0 - 1.0, defaults to 0). +# shadow-blue = 0 + +# Hex string color value of shadow (#000000 - #FFFFFF, defaults to #000000). This option will override options set shadow-(red/green/blue) +# shadow-color = "#000000" + +# Specify a list of conditions of windows that should have no shadow. +shadow-exclude = [ + "name = 'Notification'", + "class_g = 'Conky'", + "class_g = 'Cairo-clock'", + "class_g ~= 'slop'", "class_g ~= 'maim'", + "class_i ~= 'slop'", "class_i ~= 'maim'", + "name ~= 'slop'", "name ~= 'maim'", + "_GTK_FRAME_EXTENTS@:c" +]; + +# Specify a list of conditions of windows that should have no shadow painted over, such as a dock window. +# clip-shadow-above = [] + +# Specify a X geometry that describes the region in which shadow should not +# be painted in, such as a dock window region. Use +# shadow-exclude-reg = "x10+0+0" +# for example, if the 10 pixels on the bottom of the screen should not have shadows painted on. +# +# shadow-exclude-reg = "" + +# Crop shadow of a window fully on a particular Xinerama screen to the screen. +# xinerama-shadow-crop = false + + +################################# +# Fading # +################################# + + +# Fade windows in/out when opening/closing and when opacity changes, +# unless no-fading-openclose is used. +fading = true; + +# Opacity change between steps while fading in. (0.01 - 1.0, defaults to 0.028) +fade-in-step = 0.12; + +# Opacity change between steps while fading out. (0.01 - 1.0, defaults to 0.03) +fade-out-step = 0.12; + +# The time between steps in fade step, in milliseconds. (> 0, defaults to 10) +# fade-delta = 10 + +# Specify a list of conditions of windows that should not be faded. +# fade-exclude = [] + +# Do not fade on window open/close. +# no-fading-openclose = false + +# Do not fade destroyed ARGB windows with WM frame. Workaround of bugs in Openbox, Fluxbox, etc. +# no-fading-destroyed-argb = false + + +################################# +# Transparency / Opacity # +################################# + + +# Opacity of inactive windows. (0.1 - 1.0, defaults to 1.0) +inactive-opacity = 1; + +# Opacity of window titlebars and borders. (0.1 - 1.0, disabled by default) +frame-opacity = 1; + +# Let inactive opacity set by -i override the '_NET_WM_WINDOW_OPACITY' values of windows. +# inactive-opacity-override = false; + +# Default opacity for active windows. (0.0 - 1.0, defaults to 1.0) +# active-opacity = 1.0 + +# Dim inactive windows. (0.0 - 1.0, defaults to 0.0) +# inactive-dim = 0.12; + +# Specify a list of conditions of windows that should never be considered focused. +# focus-exclude = [] +focus-exclude = [ "class_g = 'Cairo-clock'" ]; + +# Use fixed inactive dim value, instead of adjusting according to window opacity. +# inactive-dim-fixed = 1.0 + +# Specify a list of opacity rules, in the format `PERCENT:PATTERN`, +# like `50:name *= "Firefox"`. picom-trans is recommended over this. +# Note we don't make any guarantee about possible conflicts with other +# programs that set '_NET_WM_WINDOW_OPACITY' on frame or client windows. +# example: +# opacity-rule = [ "80:class_g = 'URxvt'" ]; +# +# opacity-rule = [] + + +################################# +# Corners # +################################# + +# Sets the radius of rounded window corners. When > 0, the compositor will +# round the corners of windows. Does not interact well with +# `transparent-clipping`. +corner-radius = 0; + +# Exclude conditions for rounded corners. +rounded-corners-exclude = [ + "window_type = 'dock'", + "window_type = 'desktop'" +]; + + +################################# +# Background-Blurring # +################################# + + +# Parameters for background blurring, see the *BLUR* section for more information. +blur-method = "dual_kawase"; +blur-size = 4; + +blur-deviation = 4; + +blur-strength = 2; + +# Blur background of semi-transparent / ARGB windows. +# Bad in performance, with driver-dependent behavior. +# The name of the switch may change without prior notifications. +# +blur-background = true; + +# Blur background of windows when the window frame is not opaque. +# Implies: +# blur-background +# Bad in performance, with driver-dependent behavior. The name may change. +blur-background-frame = true; + + +# Use fixed blur strength rather than adjusting according to window opacity. +blur-background-fixed = false; + + +# Specify the blur convolution kernel, with the following format: +# example: +# blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; + + +# Exclude conditions for background blur. +# blur-background-exclude = [] +blur-background-exclude = [ + "window_type = 'desktop'", + "class_g ~= 'slop'", "class_g ~= 'maim'", + "class_i ~= 'slop'", "class_i ~= 'maim'", + "name ~= 'slop'", "name ~= 'maim'", + "_GTK_FRAME_EXTENTS@:c" +]; + +################################# +# General Settings # +################################# + +# Enable remote control via D-Bus. See the man page for more details. +# dbus = true + +# Daemonize process. Fork to background after initialization. Causes issues with certain (badly-written) drivers. +daemon = true; + +# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`. +# `xrender` is the default one. +backend = "glx"; + +# Enable/disable VSync. +vsync = true; + +# Enable remote control via D-Bus. See the *D-BUS API* section below for more details. +# dbus = false + +# Try to detect WM windows (a non-override-redirect window with no +# child that has 'WM_STATE') and mark them as active. +# +# mark-wmwin-focused = false +mark-wmwin-focused = true; + +# Mark override-redirect windows that doesn't have a child window with 'WM_STATE' focused. +# mark-ovredir-focused = false +mark-ovredir-focused = true; + +# Try to detect windows with rounded corners and don't consider them +# shaped windows. The accuracy is not very high, unfortunately. +# +# detect-rounded-corners = false +detect-rounded-corners = true; + +# Detect '_NET_WM_WINDOW_OPACITY' on client windows, useful for window managers +# not passing '_NET_WM_WINDOW_OPACITY' of client windows to frame windows. +# +# detect-client-opacity = false +detect-client-opacity = true; + +# Use EWMH '_NET_ACTIVE_WINDOW' to determine currently focused window, +# rather than listening to 'FocusIn'/'FocusOut' event. Might have more accuracy, +# provided that the WM supports it. +# +# use-ewmh-active-win = false + +# Unredirect all windows if a full-screen opaque window is detected, +# to maximize performance for full-screen windows. Known to cause flickering +# when redirecting/unredirecting windows. +# +# unredir-if-possible = false + +# Delay before unredirecting the window, in milliseconds. Defaults to 0. +# unredir-if-possible-delay = 0 + +# Conditions of windows that shouldn't be considered full-screen for unredirecting screen. +# unredir-if-possible-exclude = [] + +# Use 'WM_TRANSIENT_FOR' to group windows, and consider windows +# in the same group focused at the same time. +# +# detect-transient = false +detect-transient = true; + +# Use 'WM_CLIENT_LEADER' to group windows, and consider windows in the same +# group focused at the same time. This usually means windows from the same application +# will be considered focused or unfocused at the same time. +# 'WM_TRANSIENT_FOR' has higher priority if detect-transient is enabled, too. +detect-client-leader = true; + +# Resize damaged region by a specific number of pixels. +# A positive value enlarges it while a negative one shrinks it. +# If the value is positive, those additional pixels will not be actually painted +# to screen, only used in blur calculation, and such. (Due to technical limitations, +# with use-damage, those pixels will still be incorrectly painted to screen.) +# Primarily used to fix the line corruption issues of blur, +# in which case you should use the blur radius value here +# (e.g. with a 3x3 kernel, you should use `--resize-damage 1`, +# with a 5x5 one you use `--resize-damage 2`, and so on). +# May or may not work with *--glx-no-stencil*. Shrinking doesn't function correctly. +# +# resize-damage = 1 + +# Specify a list of conditions of windows that should be painted with inverted color. +# Resource-hogging, and is not well tested. +# +# invert-color-include = [] + +# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer. +# Might cause incorrect opacity when rendering transparent content (but never +# practically happened) and may not work with blur-background. +# My tests show a 15% performance boost. Recommended. +# +# glx-no-stencil = false + +# GLX backend: Avoid rebinding pixmap on window damage. +# Probably could improve performance on rapid window content changes, +# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.). +# Recommended if it works. +# +# glx-no-rebind-pixmap = false + +# Disable the use of damage information. +# This cause the whole screen to be redrawn every time, instead of the part of the screen +# has actually changed. Potentially degrades the performance, but might fix some artifacts. +# The opposing option is use-damage +use-damage = true; + +# Use X Sync fence to sync clients' draw calls, to make sure all draw +# calls are finished before picom starts drawing. Needed on nvidia-drivers +# with GLX backend for some users. +# +# xrender-sync-fence = false + +# GLX backend: Use specified GLSL fragment shader for rendering window +# contents. Read the man page for a detailed explanation of the interface. +# +# window-shader-fg = "default" + +# Use rules to set per-window shaders. Syntax is SHADER_PATH:PATTERN, similar +# to opacity-rule. SHADER_PATH can be "default". This overrides window-shader-fg. +# +# window-shader-fg-rule = [ +# "my_shader.frag:window_type != 'dock'" +# ] + +# Force all windows to be painted with blending. Useful if you +# have a glx-fshader-win that could turn opaque pixels transparent. +# +# force-win-blend = false + +# Do not use EWMH to detect fullscreen windows. +# Reverts to checking if a window is fullscreen based only on its size and coordinates. +# +# no-ewmh-fullscreen = false + +# Dimming bright windows so their brightness doesn't exceed this set value. +# Brightness of a window is estimated by averaging all pixels in the window, +# so this could comes with a performance hit. +# Setting this to 1.0 disables this behaviour. Requires --use-damage to be disabled. (default: 1.0) +# +max-brightness = 1.0; + +# Make transparent windows clip other windows like non-transparent windows do, +# instead of blending on top of them. +# +transparent-clipping = false; + +# Specify a list of conditions of windows that should never have transparent +# clipping applied. Useful for screenshot tools, where you need to be able to +# see through transparent parts of the window. +# +# transparent-clipping-exclude = [] + +# Set the log level. Possible values are: +# "trace", "debug", "info", "warn", "error" +# in increasing level of importance. Case doesn't matter. +# If using the "TRACE" log level, it's better to log into a file +# using *--log-file*, since it can generate a huge stream of logs. +# +# log-level = "debug" +log-level = "warn"; + +# Set the log file. +# If *--log-file* is never specified, logs will be written to stderr. +# Otherwise, logs will to written to the given file, though some of the early +# logs might still be written to the stderr. +# When setting this option from the config file, it is recommended to use an absolute path. +# +# log-file = "/path/to/your/log/file" + +# Show all X errors (for debugging) +# show-all-xerrors = false + +# Write process ID to a file. +# write-pid-path = "/path/to/your/log/file" + +# Window type settings +# +# 'WINDOW_TYPE' is one of the 15 window types defined in EWMH standard: +# "unknown", "desktop", "dock", "toolbar", "menu", "utility", +# "splash", "dialog", "normal", "dropdown_menu", "popup_menu", +# "tooltip", "notification", "combo", and "dnd". +# +# Following per window-type options are available: :: +# +# fade, shadow::: +# Controls window-type-specific shadow and fade settings. +# +# opacity::: +# Controls default opacity of the window type. +# +# focus::: +# Controls whether the window of this type is to be always considered focused. +# (By default, all window types except "normal" and "dialog" has this on.) +# +# full-shadow::: +# Controls whether shadow is drawn under the parts of the window that you +# normally won't be able to see. Useful when the window has parts of it +# transparent, and you want shadows in those areas. +# +# clip-shadow-above::: +# Controls whether shadows that would have been drawn above the window should +# be clipped. Useful for dock windows that should have no shadow painted on top. +# +# redir-ignore::: +# Controls whether this type of windows should cause screen to become +# redirected again after been unredirected. If you have unredir-if-possible +# set, and doesn't want certain window to cause unnecessary screen redirection, +# you can set this to `true`. +# +wintypes: +{ + tooltip = { fade = true; shadow = true; opacity = 0.75; focus = true; full-shadow = false; }; + dock = { shadow = false; clip-shadow-above = true; } + dnd = { shadow = false; } + popup_menu = { opacity = 0.8; } + dropdown_menu = { opacity = 0.8; } +};