Add unified Xresources theme engine, Default.xth export, and xthemes manager plugin

This commit is contained in:
Luxferre
2026-10-21 20:36:27 +03:00
parent f615c6ddbe
commit a31595070c
60 changed files with 3692 additions and 419 deletions
+9 -3
View File
@@ -29,7 +29,7 @@ This manual covers flashing, operating, and customizing **Bananarchy Linux** (`v
- **Patched `sxmo-st` (`st`) with HarfBuzz ligatures & XIM**: patched with `libharfbuzz` (`hb.c`/`hb.h`) shaping (`liga`, `calt`, `clig`, `dlig`) so multi-character programming operators (`->`, `=>`, `!=`, `<=`, `>=`, `===`, `::`, `//`, `/*`) render as continuous ligatures at `pixelsize=18`, alongside full `XIM` (`fcitx5-t9`) input support.
- **Patched `sxmo-dmenu` plugin (`dmenu.so` / `dmenu` / `xdmenu`) (`< 2 ms` popup/close)**: preloaded resident DWM plugin rendering a full-screen `240x296` 10-line vertical menu (positioned flush at `Y = 24..320` right below the 24px `dwm` bar, with a `26px` search bar and ten `27px` item rows) with a `#383838` top search bar, `#005577` prompt badge, `#1c1c1c` item list, `XIM` (`XSetLocaleModifiers("")`, `XSetICFocus`, `Xutf8LookupString`) for live `fcitx5-t9` search filtering and `#` mode switching, C-level focus preservation (`prevfocuswin`), built-in `< 0.5 ms` in-place Sxmo menu transitions (`Sys`, `Apps`, `Scripts`, `Modem`, `Config`, `Power`, `St`, `Nano`), and a `/tmp/dwm_plugin_dmenu.sock` IPC server for all `/usr/bin/dmenu` and `sxmo_dmenu.sh` calls.
- **Patched `sxmo-dwm` (`dwm`) (`< 2 ms` display wake/unlock & native plugin system)**: configured for `240x320` (`bh = 24`, `#323232` top bar, `#005577` active tag/border, vertical `bstack` layout default, overflow-protected Pango status bar rendering keeping the right-aligned clock always visible, and a transparent-backgrounded bottom desktop softkey bar displaying `"Menu"` and `"Names"` over the wallpaper). Directly polls `/dev/input/by-path/platform-gpio-keys-event` (`SW_LID`) and intercepts locked-state wake keys (`XF86PowerOff`, `XF86PickupPhone`, `XF86KbdLcdMenu1`, `XF86KbdLcdMenu2`) in C to toggle `/sys/class/backlight/backlight/brightness` and `/sys/class/leds/white:kbd_backlight/brightness` in `< 2 ms` before running Sxmo state hooks asynchronously.
- **Preloaded DWM plugins (`src/sxmo-dmenu/`, `src/dwm-plugins/` & `src/xdrawer/`, `< 2 ms` FIFO/socket wakeup)**: `dwm` dynamically loads `.so` plugins from `/usr/lib/dwm/plugins/` and `~/.local/lib/dwm/plugins/` (`dmenu.so`, `xdrawer.so`, `dialer.so`, `calllog.so`, `contacts.so`, `sms.so`, `files.so`, `camera.so`) and preloads them as resident background daemons (`dwm-plugin <name> --preload`) at startup. Each daemon keeps its X11 window, offscreen `Pixmap`, Xft/Pango layouts, and `stat()`-cached Sxmo TSV state initialized in memory while sleeping at 0% CPU on `/tmp/dwm_plugin_<name>.fifo`.
- **Preloaded DWM plugins (`src/sxmo-dmenu/`, `src/dwm-plugins/` & `src/xdrawer/`, `< 2 ms` FIFO/socket wakeup & unified `.Xresources` theming)**: `dwm` dynamically loads `.so` plugins from `/usr/lib/dwm/plugins/` and `~/.local/lib/dwm/plugins/` (`dmenu.so`, `xdrawer.so`, `dialer.so`, `calllog.so`, `contacts.so`, `sms.so`, `files.so`, `camera.so`, `themes.so`) and preloads them as resident background daemons (`dwm-plugin <name> --preload`) at startup. Each daemon keeps its X11 window, offscreen `Pixmap`, Xft/Pango layouts, and `stat()`-cached Sxmo TSV state initialized in memory while sleeping at 0% CPU on `/tmp/dwm_plugin_<name>.fifo`. Every UI element across `dwm`, `dmenu`, `st`, and all C++ plugins obeys a single unified color and font scheme configured via `~/.Xresources` (`theme.*`, `dwm.*`, `dmenu.*`, `st.*`), with proportional font sizing derived from `theme.baseFontSize` (`12px` / `15px` / `16px` / `18px` at default `15`) and instant live reload via `xthemes`.
2. **Multi-mode `fcitx5-t9` keypad engine (`src/fcitx5-t9/`)**:
- Supports 6 input modes cycled with `#` (`XF86NumericPound`): `abc`, `Abc`, `ABC`, `Sym`, `Ctl`, and `123`, updating the live top-bar status indicator (`[abc]`, `[Abc]`, `[ABC]`, `[Sym]`, `[Ctl]`, `[123]`) in real time.
- Locks the candidate popup bar to the bottom of the screen (`X = 1, Y = 290, W = 238, H = 30`) with fixed-width 28-character monospace formatting (`Fira Code 9.5`), so neither the popup window nor individual letters ever jump when cycling through candidates.
@@ -141,8 +141,8 @@ You can switch between **vertical stack (`TTT`, `bstack`)**, **horizontal tile (
- `Mod4+1`..`4`: switch to workspace tag `1`..`4`
- `Mod4+Shift+q`: close focused window
#### 3.1.2 Preloaded DWM plugins (`DMenu`, `XDrawer`, `Dialer`, `Call Log`, `Contacts`, `SMS`, `Files`, `Camera`)
All eight core phone overlays are compiled as shared-object plugins (`/usr/lib/dwm/plugins/*.so`), preloaded at `dwm` startup (`dwm-plugin <name> --preload` with an exclusive `/tmp/dwm_plugin_<name>.lock` single-instance guard), and awakened over `/tmp/dwm_plugin_<name>.fifo` in `< 2 ms`:
#### 3.1.2 Preloaded DWM plugins (`DMenu`, `XDrawer`, `Dialer`, `Call Log`, `Contacts`, `SMS`, `Files`, `Camera`, `Themes`)
All nine core phone overlays are compiled as shared-object plugins (`/usr/lib/dwm/plugins/*.so`), preloaded at `dwm` startup (`dwm-plugin <name> --preload` with an exclusive `/tmp/dwm_plugin_<name>.lock` single-instance guard), and awakened over `/tmp/dwm_plugin_<name>.fifo` in `< 2 ms`:
1. **`DMenu` (`dmenu.so` / `dmenu` / `xdmenu`) — Zero-Lag System & Context Menus**:
- **Open / Close**: Press **Left softkey (`Menu`)** for the **System menu** (`sys`) or **Right softkey (`Back`)** inside an application for its **Context menu** (`ctx`); press the same softkey or `Escape` to close.
@@ -184,6 +184,12 @@ All eight core phone overlays are compiled as shared-object plugins (`/usr/lib/d
- **Live Viewfinder**: Streams `800x600` `RGB24` frames directly from `/dev/video0` (`msm8905-cam` / `GC2395`) into a `240x180` 4:3 viewfinder with a center reticle and a 1-second V4L2 `poll()` frame watchdog. Press **Center `OK` (`Return`)**, **`5`**, or **Call (green)** to snap a JPEG photo to `~/Pictures/photo-YYYYMMDD-HHMMSS.jpg`; `*` or `1` toggles **Auto-Flash**; `0` or `2` toggles continuous **Torch** (`white:torch`); `Up`/`Down` adjusts **Digital Zoom** (`1.0x` / `2.0x` / `4.0x`); `#` or `3` toggles the **3-second Self-Timer**; **Left softkey (`Gallery`)** opens the built-in photo gallery.
- **Built-in Photo Gallery**: Browse captured photos with `Left`/`Right` or `Up`/`Down`, press `Return` to open full-screen in `feh`, or press **Left softkey (`Delete`)** to delete a photo.
9. **`Theme Manager` (`themes.so` / `xthemes`) — Unified `.Xresources` Theme Browser & Customizer (`~/.xthemes/*.xth`)**:
- **Open**: Select **Themes** from the Sxmo **System menu**, **Apps** menu, or **Config** menu, or run `xthemes`.
- **Theme Files (`~/.xthemes/*.xth`)**: Every `.xth` file in `~/.xthemes/` is a standard `Xresources` file defining `theme.name`, `theme.fontFace`, `theme.iconFontFace`, `theme.baseFontSize` (from which `sizeSmall`, `sizeMain`, `sizeIcon`, and `sizeLarge` are proportionally derived across all UI elements), core and surface colors (`theme.bgMain`, `theme.bgBar`, `theme.bgHeader`, `theme.selBg`, `theme.selFg`, `theme.accent`, `theme.fgMain`, `theme.fgMuted`, etc.), and synchronized `dwm.*`, `dmenu.*`, `st.*`, and `svkbd.*` resources. Pre-installed themes include **`Default.xth`**, **`BananaGold.xth`**, **`MatrixGreen.xth`**, **`NordFrost.xth`**, and **`SolarizedLight.xth`**.
- **Controls & Live Switching**: `Up`/`Down` browses installed themes with live color swatches and typography details; **Center `OK` (`Return`)**, **Call (green)**, or keys **`1`–`9`** immediately writes `~/.Xresources`, runs `xrdb -load ~/.Xresources`, and broadcasts `RELOAD_THEME` to `dwm`, `dmenu`, `st`, and all resident DWM plugins for zero-restart live theme switching.
- **Built-in Theme Customizer & Options (`Left softkey` or `*`/`#`)**: Supports **Customize Theme Colors/Font** (`*` shortcut — adjust `Font Face`, `Base Size`, `Main BG`, `Bar BG`, `Header BG`, `Selected BG`, `Selected FG`, `Accent`, `Font Color`, and `Muted Color` with `Left`/`Right` presets or press `Return` to enter any 6-digit `#RRGGBB` hex code via the keypad), **Save Current as New Theme** (`#` shortcut), **Duplicate Theme**, **Edit `.xth` in Nano**, **Reset Default Theme**, and **Delete Theme**, plus CLI `xthemes --apply <ThemeName>` and `xthemes --export-default`.
### 3.2 Multi-mode `fcitx5-t9` keypad reference
- **Short-press `#`** *(when no character is in preedit)*: cycles through the 6 input modes (`abc` -> `Abc` -> `ABC` -> `Sym` -> `Ctl` -> `123` -> `abc`), displaying a `1500ms` preedit status banner (`[Mode: abc]`, `[Mode: Abc]`, `[Mode: ABC]`, `[Mode: Sym]`, `[Mode: Ctl]`, `[Mode: 123]`).
+5 -4
View File
@@ -10,7 +10,7 @@ Bananarchy targets an ultra-lightweight **Sxmo X11 (`sxmo-de-dwm`)** environment
- **Cross-compiled Xlibre (`X11Libre/xserver` 25.2.0) display server**: `modesetting` KMS + `ShadowFB` Damage partial-rectangle SPI transfers, software cursor fallback, and rootless `elogind` integration.
- **Patched `sxmo-dwm` with native C/C++ plugin architecture**: `240x320` vertical `bstack` layout, 24px Pango status bar with an overflow-protected right-aligned clock, transparent-backgrounded `"Menu"` and `"Names"` desktop softkey labels, direct C `SW_LID` slider and locked-key wake handling in `< 2 ms`, and a dynamic `.so` plugin API (`dwm_plugin.h`) with preloaded resident daemons (`--preload`) and non-blocking FIFO IPC (`< 10 ms` wakeup latency).
- **Preloaded `240x320` keypad-driven DWM plugins (`dmenu`, `xdrawer`, `dialer`, `calllog`, `contacts`, `sms`, `files`, `camera`)**:
- **Preloaded `240x320` keypad-driven DWM plugins (`dmenu`, `xdrawer`, `dialer`, `calllog`, `contacts`, `sms`, `files`, `camera`, `themes`)**:
- **`DMenu` (`dmenu.so` / `dmenu` / `xdmenu`)**: zero-lag (`< 2 ms` popup/close) resident `240x320` full-screen 10-line vertical menu (`240x296` flush below the 24px top bar) with a `#383838` search bar, `#005577` prompt badge, `XIM` `fcitx5-t9` text input, in-place `< 0.5 ms` native Sxmo submenu transitions (`Sys`, `Apps`, `Scripts`, `Modem`, `Config`, `Power`, `St`, `Nano`), and a `/tmp/dwm_plugin_dmenu.sock` client interface serving all `/usr/bin/dmenu` and `sxmo_dmenu.sh` pipes instantaneously.
- **`XDrawer` (`xdrawer.so` / `xdrawer`)**: global phone controls overlay invoked from anywhere by pressing **both softkeys simultaneously**, providing instant sliders and toggles for speaker volume, earpiece volume, flashlight, sound mute, microphone mute, screen brightness, and keypad backlight.
- **`Dialer` (`dialer.so` / `xdialer`)**: opens automatically from the idle desktop when pressing any **`0`–`9`, `*`, or `#` key** (inserting that character immediately), with live T9/number contact filtering, hold-`0` for `+`, and single-press **Call** dialing.
@@ -19,6 +19,7 @@ Bananarchy targets an ultra-lightweight **Sxmo X11 (`sxmo-de-dwm`)** environment
- **`SMS Manager` (`sms.so` / `xsms`)**: conversation thread manager, bubble message history reader, and multi-tap keypad SMS composer/draft editor (with dynamic `Send` / `Draft` center softkey action) integrated with `$SXMO_LOGDIR/<number>/sms.txt`, `draft.txt`, `modemlog.tsv`, and `sxmo_modemsendsms.sh`.
- **`File Manager` (`files.so` / `xfiles`)**: graphical directory browser with live T9/number filtering, dotfiles toggle (`*`), sort mode cycle (`#`), file operations (new folder/file, rename, copy, cut/move, paste, delete, properties, edit in `nano`, open terminal here), built-in text viewer, and built-in `libjpeg`/`libpng` image previewer.
- **`Camera` (`camera.so` / `xcamera`)**: live V4L2 `/dev/video0` (`800x600` `RGB24` -> `240x180` 4:3) viewfinder with 1-second frame watchdog, auto-flash (`*`/`1`), continuous torch (`0`/`2`), digital zoom (`1x`/`2x`/`4x` via `Up`/`Down`), 3-second self-timer (`#`/`3`), direct `libjpeg` photo capture to `~/Pictures/photo-YYYYMMDD-HHMMSS.jpg`, and built-in photo gallery.
- **`Theme Manager` (`themes.so` / `xthemes`)**: unified `.Xresources` theme browser and live customizer managing `~/.xthemes/*.xth` (where every `.xth` file is a valid `Xresources` file controlling `theme.*`, `dwm.*`, `dmenu.*`, `st.*`, and `svkbd.*` colors, font face, and `baseFontSize` with proportional derived font sizes, pre-populated with `Default.xth`, `BananaGold.xth`, `MatrixGreen.xth`, `NordFrost.xth`, and `SolarizedLight.xth`). Applying or editing a theme reloads `dwm`, `dmenu`, `st`, and all resident DWM plugins live without restarting X11.
- **Patched `sxmo-st` terminal (`pixelsize=18`)**: **HarfBuzz (`libharfbuzz`) OpenType ligature shaping** (`liga`, `calt`, `clig`, `dlig`) and `XIM` support.
- **Typography**: non-Nerd **`Fira Code` (`font-fira-code`) with ligatures** as the primary system and terminal font (with `DejaVu SansM Nerd Font` used strictly as an icon fallback).
- **Custom 6-mode `fcitx5-t9` input engine**: fixed bottom candidate bar (`X=1, Y=290, W=238, H=30`) with a constant 28-character monospace preedit layout supporting lowercase, one-shot Shift, Caps Lock, all 32 ASCII punctuation symbols, terminal control codes (`^A`-`^Z`, `Esc`, `Tab`, `F1`-`F12`), and direct numeric entry with live top-bar mode indication (`[abc]`, `[Abc]`, `[ABC]`, `[Sym]`, `[Ctl]`, `[123]`).
@@ -93,7 +94,7 @@ bananarchy/
│ └── 0001-bananarchy-multimode-t9-and-fcitx5-5.1.19.patch
├── src/
│ ├── sxmo-dwm/ # Patched sxmo-dwm (240x320 bstack, Pango bar, desktop softkey bar & plugin API)
│ ├── dwm-plugins/ # DWM plugins (dialer, calllog, contacts, sms, files, camera), shared phone/media lib & runner
│ ├── dwm-plugins/ # DWM plugins (dialer, calllog, contacts, sms, files, camera, themes), theme.h & runner
│ ├── xdrawer/ # XDrawer global phone controls DWM plugin (xdrawer.so / xdrawer)
│ ├── sxmo-dmenu/ # Patched sxmo-dmenu zero-lag DWM plugin (dmenu.so) & client/fallback (dmenu / xdmenu)
│ ├── sxmo-st/ # Patched sxmo-st terminal with HarfBuzz Fira Code ligature shaping & XIM
@@ -103,10 +104,10 @@ bananarchy/
│ ├── leds-msm8905-torch/ # Kernel driver for SY7807 rear torch LED, WCD codec init & PM8909 PON shutdown
│ └── msm8905-cam/ # Kernel V4L2 driver for GC2395 2MP rear camera & MSM8909 CAMSS (/dev/video0)
├── overlay/
│ └── rootfs/ # Complete Bananarchy rootfs overlay (OS branding, Sxmo X11, audio, camera, T9)
│ └── rootfs/ # Complete Bananarchy rootfs overlay (OS branding, Sxmo X11, audio, camera, T9, .xthemes)
├── prebuilt/
│ ├── xlibre/ # Prebuilt armv7 Xlibre Xorg binary and modesetting/libinput/fbdev DDX modules
│ ├── sxmo-x11/ # Prebuilt armv7 patched dwm, dmenu.so/dmenu, 7 C++ DWM plugins, and st (HarfBuzz ligatures)
│ ├── sxmo-x11/ # Prebuilt armv7 patched dwm, dmenu.so/dmenu, 8 C++ DWM plugins, and st (HarfBuzz ligatures)
│ ├── kernel-6.12.1-msm8916/ # Prebuilt QDSP6/Q6Voice .ko, torch .ko, camera .ko, and 5 device DTBs
│ ├── fcitx5-t9/ # Prebuilt armv7 libt9.so and fcitx5 addon/inputmethod configs
│ └── bantam/ # Prebuilt armv7 bantam AI agent binary
+51 -3
View File
@@ -1,13 +1,61 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: Default
theme.name: Default
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #222222
theme.bgBar: #323232
theme.bgHeader: #1c1c1c
theme.bgFooter: #181818
theme.bgOverlay: #161616
theme.bgAltEven: #282828
theme.bgAltOdd: #2e2e2e
theme.bgInput: #1a1a1a
theme.bgInputFocus: #1b3b4b
theme.bgButton: #2a2a2a
theme.bgSearch: #383838
theme.bgBubbleIn: #262d32
theme.bgBubbleOut: #1f2d38
theme.bgToast: #102535
theme.fgMain: #dddddd
theme.fgBright: #ffffff
theme.fgMuted: #999999
theme.selBg: #005577
theme.selFg: #ffffff
theme.accent: #f4d03f
theme.accentAlt: #0088bb
theme.highlight: #ffc978
theme.border: #444444
theme.divider: #666666
theme.success: #2ecc71
theme.info: #5dade2
theme.warning: #e67e22
theme.danger: #e74c3c
theme.dangerBg: #922b21
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #1c1c1c
dmenu.foreground: #e0e0e0
dmenu.foreground: #ffffff
dmenu.selbackground: #005577
dmenu.selforeground: #ffffff
dmenu.outbackground: #383838
dmenu.outforeground: #ffffff
dmenu.highlight: #ffc978
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #323232
dwm.foreground: #dddddd
dwm.border: #444444
dwm.selbackground: #005577
dwm.selforeground: #ffffff
dwm.selborder: #005577
dwm.normbgcolor: #323232
dwm.normbordercolor: #444444
dwm.normfgcolor: #dddddd
@@ -18,7 +66,7 @@ dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #1c1c1c
st.foreground: #e5e5e5
st.cursorColor: #cccccc
st.foreground: #dddddd
st.cursorColor: #f4d03f
svkbd.font: Fira Code:pixelsize=12
@@ -0,0 +1,72 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: BananaGold
theme.name: BananaGold
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #1d1a10
theme.bgBar: #2b2616
theme.bgHeader: #16130b
theme.bgFooter: #121009
theme.bgOverlay: #100e08
theme.bgAltEven: #242014
theme.bgAltOdd: #2c2718
theme.bgInput: #14120b
theme.bgInputFocus: #4d3b0b
theme.bgButton: #282315
theme.bgSearch: #38311e
theme.bgBubbleIn: #262b18
theme.bgBubbleOut: #382e12
theme.bgToast: #33270a
theme.fgMain: #f5ebc6
theme.fgBright: #ffffff
theme.fgMuted: #a89f7d
theme.selBg: #b58900
theme.selFg: #ffffff
theme.accent: #ffd700
theme.accentAlt: #e6b800
theme.highlight: #ffe666
theme.border: #4a4128
theme.divider: #6b5e3a
theme.success: #2ecc71
theme.info: #5dade2
theme.warning: #f39c12
theme.danger: #e74c3c
theme.dangerBg: #922b21
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #16130b
dmenu.foreground: #ffffff
dmenu.selbackground: #b58900
dmenu.selforeground: #ffffff
dmenu.outbackground: #38311e
dmenu.outforeground: #ffffff
dmenu.highlight: #ffe666
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #2b2616
dwm.foreground: #f5ebc6
dwm.border: #4a4128
dwm.selbackground: #b58900
dwm.selforeground: #ffffff
dwm.selborder: #b58900
dwm.normbgcolor: #2b2616
dwm.normbordercolor: #4a4128
dwm.normfgcolor: #f5ebc6
dwm.selbgcolor: #b58900
dwm.selbordercolor: #b58900
dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #16130b
st.foreground: #f5ebc6
st.cursorColor: #ffd700
svkbd.font: Fira Code:pixelsize=12
@@ -0,0 +1,72 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: Default
theme.name: Default
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #222222
theme.bgBar: #323232
theme.bgHeader: #1c1c1c
theme.bgFooter: #181818
theme.bgOverlay: #161616
theme.bgAltEven: #282828
theme.bgAltOdd: #2e2e2e
theme.bgInput: #1a1a1a
theme.bgInputFocus: #1b3b4b
theme.bgButton: #2a2a2a
theme.bgSearch: #383838
theme.bgBubbleIn: #262d32
theme.bgBubbleOut: #1f2d38
theme.bgToast: #102535
theme.fgMain: #dddddd
theme.fgBright: #ffffff
theme.fgMuted: #999999
theme.selBg: #005577
theme.selFg: #ffffff
theme.accent: #f4d03f
theme.accentAlt: #0088bb
theme.highlight: #ffc978
theme.border: #444444
theme.divider: #666666
theme.success: #2ecc71
theme.info: #5dade2
theme.warning: #e67e22
theme.danger: #e74c3c
theme.dangerBg: #922b21
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #1c1c1c
dmenu.foreground: #ffffff
dmenu.selbackground: #005577
dmenu.selforeground: #ffffff
dmenu.outbackground: #383838
dmenu.outforeground: #ffffff
dmenu.highlight: #ffc978
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #323232
dwm.foreground: #dddddd
dwm.border: #444444
dwm.selbackground: #005577
dwm.selforeground: #ffffff
dwm.selborder: #005577
dwm.normbgcolor: #323232
dwm.normbordercolor: #444444
dwm.normfgcolor: #dddddd
dwm.selbgcolor: #005577
dwm.selbordercolor: #005577
dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #1c1c1c
st.foreground: #dddddd
st.cursorColor: #f4d03f
svkbd.font: Fira Code:pixelsize=12
@@ -0,0 +1,72 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: MatrixGreen
theme.name: MatrixGreen
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #0a140c
theme.bgBar: #112214
theme.bgHeader: #070e08
theme.bgFooter: #050b06
theme.bgOverlay: #040905
theme.bgAltEven: #0e1c11
theme.bgAltOdd: #132416
theme.bgInput: #071009
theme.bgInputFocus: #143d1f
theme.bgButton: #102013
theme.bgSearch: #18301c
theme.bgBubbleIn: #112b16
theme.bgBubbleOut: #16381d
theme.bgToast: #0f3018
theme.fgMain: #a8ffb2
theme.fgBright: #e0ffe4
theme.fgMuted: #52995b
theme.selBg: #196627
theme.selFg: #ffffff
theme.accent: #00ff41
theme.accentAlt: #2ecc71
theme.highlight: #80ff9d
theme.border: #1e4224
theme.divider: #2d6336
theme.success: #00ff41
theme.info: #5dade2
theme.warning: #f1c40f
theme.danger: #e74c3c
theme.dangerBg: #922b21
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #070e08
dmenu.foreground: #e0ffe4
dmenu.selbackground: #196627
dmenu.selforeground: #ffffff
dmenu.outbackground: #18301c
dmenu.outforeground: #e0ffe4
dmenu.highlight: #80ff9d
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #112214
dwm.foreground: #a8ffb2
dwm.border: #1e4224
dwm.selbackground: #196627
dwm.selforeground: #ffffff
dwm.selborder: #196627
dwm.normbgcolor: #112214
dwm.normbordercolor: #1e4224
dwm.normfgcolor: #a8ffb2
dwm.selbgcolor: #196627
dwm.selbordercolor: #196627
dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #070e08
st.foreground: #a8ffb2
st.cursorColor: #00ff41
svkbd.font: Fira Code:pixelsize=12
@@ -0,0 +1,72 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: NordFrost
theme.name: NordFrost
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #2e3440
theme.bgBar: #3b4252
theme.bgHeader: #242933
theme.bgFooter: #1f242d
theme.bgOverlay: #1d212a
theme.bgAltEven: #333a47
theme.bgAltOdd: #39404f
theme.bgInput: #262b36
theme.bgInputFocus: #394b68
theme.bgButton: #363d4c
theme.bgSearch: #434c5e
theme.bgBubbleIn: #354249
theme.bgBubbleOut: #344459
theme.bgToast: #2b3c54
theme.fgMain: #e5e9f0
theme.fgBright: #eceff4
theme.fgMuted: #9099ab
theme.selBg: #5e81ac
theme.selFg: #eceff4
theme.accent: #88c0d0
theme.accentAlt: #81a1c1
theme.highlight: #ebcb8b
theme.border: #4c566a
theme.divider: #616e88
theme.success: #a3be8c
theme.info: #88c0d0
theme.warning: #d08770
theme.danger: #bf616a
theme.dangerBg: #7a373e
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #242933
dmenu.foreground: #eceff4
dmenu.selbackground: #5e81ac
dmenu.selforeground: #eceff4
dmenu.outbackground: #434c5e
dmenu.outforeground: #eceff4
dmenu.highlight: #ebcb8b
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #3b4252
dwm.foreground: #e5e9f0
dwm.border: #4c566a
dwm.selbackground: #5e81ac
dwm.selforeground: #eceff4
dwm.selborder: #5e81ac
dwm.normbgcolor: #3b4252
dwm.normbordercolor: #4c566a
dwm.normfgcolor: #e5e9f0
dwm.selbgcolor: #5e81ac
dwm.selbordercolor: #5e81ac
dwm.selfgcolor: #eceff4
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #242933
st.foreground: #e5e9f0
st.cursorColor: #88c0d0
svkbd.font: Fira Code:pixelsize=12
@@ -0,0 +1,72 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: SolarizedLight
theme.name: SolarizedLight
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #fdf6e3
theme.bgBar: #eee8d5
theme.bgHeader: #e6dfca
theme.bgFooter: #e0d9c3
theme.bgOverlay: #ddd6c1
theme.bgAltEven: #f7f0dd
theme.bgAltOdd: #efe8d5
theme.bgInput: #ffffff
theme.bgInputFocus: #d5e5f2
theme.bgButton: #e8e1cc
theme.bgSearch: #d9d2bd
theme.bgBubbleIn: #e3f0d8
theme.bgBubbleOut: #d5e6f5
theme.bgToast: #1b4f72
theme.fgMain: #283739
theme.fgBright: #073642
theme.fgMuted: #657b83
theme.selBg: #268bd2
theme.selFg: #ffffff
theme.accent: #b58900
theme.accentAlt: #2aa198
theme.highlight: #cb4b16
theme.border: #93a1a1
theme.divider: #839496
theme.success: #2aa198
theme.info: #268bd2
theme.warning: #cb4b16
theme.danger: #dc322f
theme.dangerBg: #a93226
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #e6dfca
dmenu.foreground: #073642
dmenu.selbackground: #268bd2
dmenu.selforeground: #ffffff
dmenu.outbackground: #d9d2bd
dmenu.outforeground: #073642
dmenu.highlight: #cb4b16
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #eee8d5
dwm.foreground: #283739
dwm.border: #93a1a1
dwm.selbackground: #268bd2
dwm.selforeground: #ffffff
dwm.selborder: #268bd2
dwm.normbgcolor: #eee8d5
dwm.normbordercolor: #93a1a1
dwm.normfgcolor: #283739
dwm.selbgcolor: #268bd2
dwm.selbordercolor: #268bd2
dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #fdf6e3
st.foreground: #283739
st.cursorColor: #b58900
svkbd.font: Fira Code:pixelsize=12
+51 -3
View File
@@ -1,13 +1,61 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: Default
theme.name: Default
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #222222
theme.bgBar: #323232
theme.bgHeader: #1c1c1c
theme.bgFooter: #181818
theme.bgOverlay: #161616
theme.bgAltEven: #282828
theme.bgAltOdd: #2e2e2e
theme.bgInput: #1a1a1a
theme.bgInputFocus: #1b3b4b
theme.bgButton: #2a2a2a
theme.bgSearch: #383838
theme.bgBubbleIn: #262d32
theme.bgBubbleOut: #1f2d38
theme.bgToast: #102535
theme.fgMain: #dddddd
theme.fgBright: #ffffff
theme.fgMuted: #999999
theme.selBg: #005577
theme.selFg: #ffffff
theme.accent: #f4d03f
theme.accentAlt: #0088bb
theme.highlight: #ffc978
theme.border: #444444
theme.divider: #666666
theme.success: #2ecc71
theme.info: #5dade2
theme.warning: #e67e22
theme.danger: #e74c3c
theme.dangerBg: #922b21
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #1c1c1c
dmenu.foreground: #e0e0e0
dmenu.foreground: #ffffff
dmenu.selbackground: #005577
dmenu.selforeground: #ffffff
dmenu.outbackground: #383838
dmenu.outforeground: #ffffff
dmenu.highlight: #ffc978
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #323232
dwm.foreground: #dddddd
dwm.border: #444444
dwm.selbackground: #005577
dwm.selforeground: #ffffff
dwm.selborder: #005577
dwm.normbgcolor: #323232
dwm.normbordercolor: #444444
dwm.normfgcolor: #dddddd
@@ -18,7 +66,7 @@ dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #1c1c1c
st.foreground: #e5e5e5
st.cursorColor: #cccccc
st.foreground: #dddddd
st.cursorColor: #f4d03f
svkbd.font: Fira Code:pixelsize=12
@@ -0,0 +1,72 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: BananaGold
theme.name: BananaGold
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #1d1a10
theme.bgBar: #2b2616
theme.bgHeader: #16130b
theme.bgFooter: #121009
theme.bgOverlay: #100e08
theme.bgAltEven: #242014
theme.bgAltOdd: #2c2718
theme.bgInput: #14120b
theme.bgInputFocus: #4d3b0b
theme.bgButton: #282315
theme.bgSearch: #38311e
theme.bgBubbleIn: #262b18
theme.bgBubbleOut: #382e12
theme.bgToast: #33270a
theme.fgMain: #f5ebc6
theme.fgBright: #ffffff
theme.fgMuted: #a89f7d
theme.selBg: #b58900
theme.selFg: #ffffff
theme.accent: #ffd700
theme.accentAlt: #e6b800
theme.highlight: #ffe666
theme.border: #4a4128
theme.divider: #6b5e3a
theme.success: #2ecc71
theme.info: #5dade2
theme.warning: #f39c12
theme.danger: #e74c3c
theme.dangerBg: #922b21
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #16130b
dmenu.foreground: #ffffff
dmenu.selbackground: #b58900
dmenu.selforeground: #ffffff
dmenu.outbackground: #38311e
dmenu.outforeground: #ffffff
dmenu.highlight: #ffe666
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #2b2616
dwm.foreground: #f5ebc6
dwm.border: #4a4128
dwm.selbackground: #b58900
dwm.selforeground: #ffffff
dwm.selborder: #b58900
dwm.normbgcolor: #2b2616
dwm.normbordercolor: #4a4128
dwm.normfgcolor: #f5ebc6
dwm.selbgcolor: #b58900
dwm.selbordercolor: #b58900
dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #16130b
st.foreground: #f5ebc6
st.cursorColor: #ffd700
svkbd.font: Fira Code:pixelsize=12
@@ -0,0 +1,72 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: Default
theme.name: Default
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #222222
theme.bgBar: #323232
theme.bgHeader: #1c1c1c
theme.bgFooter: #181818
theme.bgOverlay: #161616
theme.bgAltEven: #282828
theme.bgAltOdd: #2e2e2e
theme.bgInput: #1a1a1a
theme.bgInputFocus: #1b3b4b
theme.bgButton: #2a2a2a
theme.bgSearch: #383838
theme.bgBubbleIn: #262d32
theme.bgBubbleOut: #1f2d38
theme.bgToast: #102535
theme.fgMain: #dddddd
theme.fgBright: #ffffff
theme.fgMuted: #999999
theme.selBg: #005577
theme.selFg: #ffffff
theme.accent: #f4d03f
theme.accentAlt: #0088bb
theme.highlight: #ffc978
theme.border: #444444
theme.divider: #666666
theme.success: #2ecc71
theme.info: #5dade2
theme.warning: #e67e22
theme.danger: #e74c3c
theme.dangerBg: #922b21
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #1c1c1c
dmenu.foreground: #ffffff
dmenu.selbackground: #005577
dmenu.selforeground: #ffffff
dmenu.outbackground: #383838
dmenu.outforeground: #ffffff
dmenu.highlight: #ffc978
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #323232
dwm.foreground: #dddddd
dwm.border: #444444
dwm.selbackground: #005577
dwm.selforeground: #ffffff
dwm.selborder: #005577
dwm.normbgcolor: #323232
dwm.normbordercolor: #444444
dwm.normfgcolor: #dddddd
dwm.selbgcolor: #005577
dwm.selbordercolor: #005577
dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #1c1c1c
st.foreground: #dddddd
st.cursorColor: #f4d03f
svkbd.font: Fira Code:pixelsize=12
@@ -0,0 +1,72 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: MatrixGreen
theme.name: MatrixGreen
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #0a140c
theme.bgBar: #112214
theme.bgHeader: #070e08
theme.bgFooter: #050b06
theme.bgOverlay: #040905
theme.bgAltEven: #0e1c11
theme.bgAltOdd: #132416
theme.bgInput: #071009
theme.bgInputFocus: #143d1f
theme.bgButton: #102013
theme.bgSearch: #18301c
theme.bgBubbleIn: #112b16
theme.bgBubbleOut: #16381d
theme.bgToast: #0f3018
theme.fgMain: #a8ffb2
theme.fgBright: #e0ffe4
theme.fgMuted: #52995b
theme.selBg: #196627
theme.selFg: #ffffff
theme.accent: #00ff41
theme.accentAlt: #2ecc71
theme.highlight: #80ff9d
theme.border: #1e4224
theme.divider: #2d6336
theme.success: #00ff41
theme.info: #5dade2
theme.warning: #f1c40f
theme.danger: #e74c3c
theme.dangerBg: #922b21
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #070e08
dmenu.foreground: #e0ffe4
dmenu.selbackground: #196627
dmenu.selforeground: #ffffff
dmenu.outbackground: #18301c
dmenu.outforeground: #e0ffe4
dmenu.highlight: #80ff9d
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #112214
dwm.foreground: #a8ffb2
dwm.border: #1e4224
dwm.selbackground: #196627
dwm.selforeground: #ffffff
dwm.selborder: #196627
dwm.normbgcolor: #112214
dwm.normbordercolor: #1e4224
dwm.normfgcolor: #a8ffb2
dwm.selbgcolor: #196627
dwm.selbordercolor: #196627
dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #070e08
st.foreground: #a8ffb2
st.cursorColor: #00ff41
svkbd.font: Fira Code:pixelsize=12
@@ -0,0 +1,72 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: NordFrost
theme.name: NordFrost
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #2e3440
theme.bgBar: #3b4252
theme.bgHeader: #242933
theme.bgFooter: #1f242d
theme.bgOverlay: #1d212a
theme.bgAltEven: #333a47
theme.bgAltOdd: #39404f
theme.bgInput: #262b36
theme.bgInputFocus: #394b68
theme.bgButton: #363d4c
theme.bgSearch: #434c5e
theme.bgBubbleIn: #354249
theme.bgBubbleOut: #344459
theme.bgToast: #2b3c54
theme.fgMain: #e5e9f0
theme.fgBright: #eceff4
theme.fgMuted: #9099ab
theme.selBg: #5e81ac
theme.selFg: #eceff4
theme.accent: #88c0d0
theme.accentAlt: #81a1c1
theme.highlight: #ebcb8b
theme.border: #4c566a
theme.divider: #616e88
theme.success: #a3be8c
theme.info: #88c0d0
theme.warning: #d08770
theme.danger: #bf616a
theme.dangerBg: #7a373e
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #242933
dmenu.foreground: #eceff4
dmenu.selbackground: #5e81ac
dmenu.selforeground: #eceff4
dmenu.outbackground: #434c5e
dmenu.outforeground: #eceff4
dmenu.highlight: #ebcb8b
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #3b4252
dwm.foreground: #e5e9f0
dwm.border: #4c566a
dwm.selbackground: #5e81ac
dwm.selforeground: #eceff4
dwm.selborder: #5e81ac
dwm.normbgcolor: #3b4252
dwm.normbordercolor: #4c566a
dwm.normfgcolor: #e5e9f0
dwm.selbgcolor: #5e81ac
dwm.selbordercolor: #5e81ac
dwm.selfgcolor: #eceff4
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #242933
st.foreground: #e5e9f0
st.cursorColor: #88c0d0
svkbd.font: Fira Code:pixelsize=12
@@ -0,0 +1,72 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: SolarizedLight
theme.name: SolarizedLight
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #fdf6e3
theme.bgBar: #eee8d5
theme.bgHeader: #e6dfca
theme.bgFooter: #e0d9c3
theme.bgOverlay: #ddd6c1
theme.bgAltEven: #f7f0dd
theme.bgAltOdd: #efe8d5
theme.bgInput: #ffffff
theme.bgInputFocus: #d5e5f2
theme.bgButton: #e8e1cc
theme.bgSearch: #d9d2bd
theme.bgBubbleIn: #e3f0d8
theme.bgBubbleOut: #d5e6f5
theme.bgToast: #1b4f72
theme.fgMain: #283739
theme.fgBright: #073642
theme.fgMuted: #657b83
theme.selBg: #268bd2
theme.selFg: #ffffff
theme.accent: #b58900
theme.accentAlt: #2aa198
theme.highlight: #cb4b16
theme.border: #93a1a1
theme.divider: #839496
theme.success: #2aa198
theme.info: #268bd2
theme.warning: #cb4b16
theme.danger: #dc322f
theme.dangerBg: #a93226
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #e6dfca
dmenu.foreground: #073642
dmenu.selbackground: #268bd2
dmenu.selforeground: #ffffff
dmenu.outbackground: #d9d2bd
dmenu.outforeground: #073642
dmenu.highlight: #cb4b16
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #eee8d5
dwm.foreground: #283739
dwm.border: #93a1a1
dwm.selbackground: #268bd2
dwm.selforeground: #ffffff
dwm.selborder: #268bd2
dwm.normbgcolor: #eee8d5
dwm.normbordercolor: #93a1a1
dwm.normfgcolor: #283739
dwm.selbgcolor: #268bd2
dwm.selbordercolor: #268bd2
dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #fdf6e3
st.foreground: #283739
st.cursorColor: #b58900
svkbd.font: Fira Code:pixelsize=12
Binary file not shown.
Binary file not shown.
Binary file not shown.
+3 -1
View File
@@ -173,6 +173,7 @@ ${_flash_line}$icon_net Networks^0^sxmo_networks.sh
$icon_mus Audio^0^sxmo_audio.sh
$icon_phn Modem^0^sxmo_appmenu.sh modem
$icon_win Windows^0^sxmo_wmmenu.sh
$icon_cfg Themes^0^xthemes
$icon_cfg Config^0^sxmo_appmenu.sh config
$icon_pwr Power^0^sxmo_appmenu.sh power"
}
@@ -220,7 +221,8 @@ $icon_phl Modem Log^0^sxmo_modemlog.sh"
[ -e "${XDG_CACHE_HOME:-$HOME/.cache}/sxmo/sxmo.nosuspend" ] && _susp_icon="$icon_tof"
_idle_icon="$icon_ton"
[ -e "${XDG_CACHE_HOME:-$HOME/.cache}/sxmo/sxmo.noidle" ] && _idle_icon="$icon_tof"
CHOICES="$icon_aru Brightness^1^sxmo_brightness.sh up
CHOICES="$icon_cfg Themes^0^xthemes
$icon_aru Brightness^1^sxmo_brightness.sh up
$icon_ard Brightness^1^sxmo_brightness.sh down
$icon_cfg Toggle Bar^0^sxmo_wm.sh togglebar
$icon_bth Bluetooth $_bt_icon^1^doas sxmo_bluetoothtoggle.sh && sxmo_hook_statusbar.sh bluetooth
+1
View File
@@ -0,0 +1 @@
dwm-plugin
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,13 +1,61 @@
! Space to setup configversion
! configversion: 7bff124b2de16292fe6e7a7e5d3322ae
! Bananarchy Unified Theme: Default
theme.name: Default
theme.fontFace: Fira Code
theme.iconFontFace: DejaVuSansM Nerd Font
theme.baseFontSize: 15
theme.bgMain: #222222
theme.bgBar: #323232
theme.bgHeader: #1c1c1c
theme.bgFooter: #181818
theme.bgOverlay: #161616
theme.bgAltEven: #282828
theme.bgAltOdd: #2e2e2e
theme.bgInput: #1a1a1a
theme.bgInputFocus: #1b3b4b
theme.bgButton: #2a2a2a
theme.bgSearch: #383838
theme.bgBubbleIn: #262d32
theme.bgBubbleOut: #1f2d38
theme.bgToast: #102535
theme.fgMain: #dddddd
theme.fgBright: #ffffff
theme.fgMuted: #999999
theme.selBg: #005577
theme.selFg: #ffffff
theme.accent: #f4d03f
theme.accentAlt: #0088bb
theme.highlight: #ffc978
theme.border: #444444
theme.divider: #666666
theme.success: #2ecc71
theme.info: #5dade2
theme.warning: #e67e22
theme.danger: #e74c3c
theme.dangerBg: #922b21
dmenu.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
dmenu.background: #1c1c1c
dmenu.foreground: #e0e0e0
dmenu.foreground: #ffffff
dmenu.selbackground: #005577
dmenu.selforeground: #ffffff
dmenu.outbackground: #383838
dmenu.outforeground: #ffffff
dmenu.highlight: #ffc978
dwm.font: Fira Code, DejaVuSansM Nerd Font 15px
dwm.background: #323232
dwm.foreground: #dddddd
dwm.border: #444444
dwm.selbackground: #005577
dwm.selforeground: #ffffff
dwm.selborder: #005577
dwm.normbgcolor: #323232
dwm.normbordercolor: #444444
dwm.normfgcolor: #dddddd
@@ -18,7 +66,7 @@ dwm.selfgcolor: #ffffff
st.font: Fira Code:pixelsize=18:style=Regular:antialias=true:autohint=true
st.termname: xterm-256color
st.background: #1c1c1c
st.foreground: #e5e5e5
st.cursorColor: #cccccc
st.foreground: #dddddd
st.cursorColor: #f4d03f
svkbd.font: Fira Code:pixelsize=12
@@ -215,6 +215,7 @@ write_line_app termite "$icon_trm Termite" "termite -e $SHELL"
write_line_app thunar "$icon_dir Thunar" "sxmo_terminal.sh thunar"
write_line_app thunderbird "$icon_thu Thunderbird" "thunderbird"
write_line_app tilix "$icon_trm Tilix" "tilix"
write_line_app xthemes "$icon_cfg Themes" "xthemes"
write_line_app com.github.bleakgrey.tootle "$icon_msg Tootle" "com.github.bleakgrey.tootle"
write_line_app re.sonny.Tangram "$icon_glb Tangram" "re.sonny.Tangram"
write_line_app totem "$icon_mvi Totem" "totem"
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
dwm-plugin
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+8 -2
View File
@@ -100,7 +100,7 @@ EOF
dwm.c drw.c util.c $DWM_LIBS -o /bananarchy/prebuilt/sxmo-x11/usr/bin/dwm
$STRIP --strip-unneeded /bananarchy/prebuilt/sxmo-x11/usr/bin/dwm
echo "[6/6] Compiling DWM Plugins (xdrawer, dialer, calllog, contacts, sms, files, camera) and dwm-plugin runner..."
echo "[6/6] Compiling DWM Plugins (xdrawer, dialer, calllog, contacts, sms, files, camera, themes) and dwm-plugin runner..."
mkdir -p /bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins
PLUG_INCS="$(pkgconf --cflags x11 xft fontconfig freetype2 pango pangoxft alsa libjpeg libpng)"
PLUG_LIBS="$(pkgconf --libs x11 xft fontconfig freetype2 pango pangoxft alsa)"
@@ -134,6 +134,10 @@ EOF
/bananarchy/src/dwm-plugins/camera_plugin.cpp $PLUG_LIBS $MEDIA_LIBS -lpthread \
-o /bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/camera.so
$CXX $OPT_CFLAGS -fPIC -shared -std=c++17 -Wall -Wextra $PLUG_INCS \
/bananarchy/src/dwm-plugins/themes_plugin.cpp $PLUG_LIBS \
-o /bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/themes.so
$STRIP --strip-unneeded \
/bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/xdrawer.so \
/bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/dialer.so \
@@ -141,7 +145,8 @@ EOF
/bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/contacts.so \
/bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/sms.so \
/bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/files.so \
/bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/camera.so
/bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/camera.so \
/bananarchy/prebuilt/sxmo-x11/usr/lib/dwm/plugins/themes.so
$CC $OPT_CFLAGS -std=c99 -D_DEFAULT_SOURCE -Wall -Wextra \
/bananarchy/src/dwm-plugins/dwm_plugin_runner.c -ldl \
@@ -158,6 +163,7 @@ EOF
ln -sf dwm-plugin /bananarchy/prebuilt/sxmo-x11/usr/bin/xsms
ln -sf dwm-plugin /bananarchy/prebuilt/sxmo-x11/usr/bin/xfiles
ln -sf dwm-plugin /bananarchy/prebuilt/sxmo-x11/usr/bin/xcamera
ln -sf dwm-plugin /bananarchy/prebuilt/sxmo-x11/usr/bin/xthemes
mkdir -p /bananarchy/overlay/rootfs/usr/bin /bananarchy/overlay/rootfs/usr/lib/dwm/plugins
cp -a /bananarchy/prebuilt/sxmo-x11/usr/bin/. /bananarchy/overlay/rootfs/usr/bin/
+32 -40
View File
@@ -101,33 +101,19 @@ int calllog_run_main(int argc, char** argv) {
PangoContext* pangoCtx = pango_font_map_create_context(fontMap);
PangoLayout* layoutMain = pango_layout_new(pangoCtx);
PangoFontDescription* descMain =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 15px");
pango_layout_set_font_description(layoutMain, descMain);
PangoLayout* layoutSmall = pango_layout_new(pangoCtx);
PangoFontDescription* descSmall =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 12px");
pango_layout_set_font_description(layoutSmall, descSmall);
PangoLayout* layoutIcon = pango_layout_new(pangoCtx);
PangoFontDescription* descIcon =
pango_font_description_from_string("DejaVuSansM Nerd Font, Fira Code 16px");
pango_layout_set_font_description(layoutIcon, descIcon);
auto allocColor = [&](const char* hex) {
XftColor col{};
XftColorAllocName(dpy, visual, cmap, hex, &col);
return col;
};
XftColor colWhite = allocColor("#ffffff");
XftColor colLight = allocColor("#dddddd");
XftColor colMuted = allocColor("#999999");
XftColor colYellow = allocColor("#f4d03f");
XftColor colGreen = allocColor("#2ecc71");
XftColor colBlue = allocColor("#5dade2");
XftColor colRed = allocColor("#e74c3c");
PluginTheme theme;
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
nullptr, win);
XftColor& colWhite = theme.colWhite;
XftColor& colLight = theme.colLight;
XftColor& colMuted = theme.colMuted;
XftColor& colYellow = theme.colYellow;
XftColor& colGreen = theme.colGreen;
XftColor& colBlue = theme.colBlue;
XftColor& colRed = theme.colRed;
ContactBook book;
std::vector<CallLogItem> allLogs;
@@ -208,10 +194,10 @@ int calllog_run_main(int argc, char** argv) {
const char* kTabLabels[4] = {"All", "Missed", "In", "Out"};
auto render = [&]() {
XSetForeground(dpy, gc, 0x222222);
XSetForeground(dpy, gc, theme.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
XSetForeground(dpy, gc, 0x1c1c1c);
XSetForeground(dpy, gc, theme.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kHeaderH);
for (int t = 0; t < 4; ++t) {
@@ -219,9 +205,9 @@ int calllog_run_main(int argc, char** argv) {
int tw = ((t + 1) * kWinWidth) / 4 - tx;
bool active = (t == filterTab);
if (active) {
XSetForeground(dpy, gc, 0x005577);
XSetForeground(dpy, gc, theme.spec.selBg);
XFillRectangle(dpy, pix, gc, tx, 0, tw, kHeaderH - 2);
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, tx, kHeaderH - 3, tw, 3);
}
std::string lbl(kTabLabels[t]);
@@ -230,7 +216,7 @@ int calllog_run_main(int argc, char** argv) {
tx + (tw - lw) / 2, 0, kHeaderH - 2, lbl);
}
XSetForeground(dpy, gc, 0x444444);
XSetForeground(dpy, gc, theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, kHeaderH - 1, kWinWidth, 1);
if (filtered.empty()) {
@@ -259,11 +245,11 @@ int calllog_run_main(int argc, char** argv) {
bool isSel = (idx == selected);
XSetForeground(dpy, gc,
isSel ? 0x005577 : ((i % 2 == 0) ? 0x282828 : 0x2e2e2e));
isSel ? theme.spec.selBg : ((i % 2 == 0) ? theme.spec.bgAltEven : theme.spec.bgAltOdd));
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH);
if (isSel) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 0, ry, 4, rowH);
}
@@ -313,15 +299,15 @@ int calllog_run_main(int argc, char** argv) {
int sbH = std::max(16, (kListH * kVisibleRows) / total);
int sbY = kListY +
((kListH - sbH) * scrollOffset) / (total - kVisibleRows);
XSetForeground(dpy, gc, 0x666666);
XSetForeground(dpy, gc, theme.spec.divider);
XFillRectangle(dpy, pix, gc, kWinWidth - 3, sbY, 3, sbH);
}
}
int sbY = kWinHeight - kSoftbarH;
XSetForeground(dpy, gc, 0x181818);
XSetForeground(dpy, gc, theme.spec.bgFooter);
XFillRectangle(dpy, pix, gc, 0, sbY, kWinWidth, kSoftbarH);
XSetForeground(dpy, gc, 0x444444);
XSetForeground(dpy, gc, theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, sbY, kWinWidth, 1);
drawPango(layoutMain, &colLight, 6, sbY + 1, kSoftbarH - 1, "Dialer");
@@ -348,6 +334,9 @@ int calllog_run_main(int argc, char** argv) {
auto showWindow = [&]() {
closeOtherPlugins("calllog");
bool themeChanged = theme.checkAndReload(
dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
nullptr, win);
if (!visible) {
openStartMs = nowMs();
startupIgnoreUntilMs = openStartMs + 90;
@@ -356,7 +345,9 @@ int calllog_run_main(int argc, char** argv) {
softkeyDeadlineMs = 0;
visible = true;
XMapRaised(dpy, win);
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
if (!themeChanged) {
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
}
for (int i = 0; i < 20; ++i) {
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime) ==
GrabSuccess) {
@@ -364,7 +355,7 @@ int calllog_run_main(int argc, char** argv) {
}
usleep(2000);
}
if (reloadLogsIfNeeded() || filterTab != 0 || selected != 0) {
if (reloadLogsIfNeeded() || themeChanged || filterTab != 0 || selected != 0) {
filterTab = 0;
selected = 0;
applyFilter();
@@ -373,7 +364,7 @@ int calllog_run_main(int argc, char** argv) {
XFlush(dpy);
writeIntFile(activePidPath, static_cast<int>(::getpid()));
} else {
if (reloadLogsIfNeeded()) {
if (reloadLogsIfNeeded() || themeChanged) {
render();
}
}
@@ -428,6 +419,10 @@ int calllog_run_main(int argc, char** argv) {
hideWindow(false);
} else if (cmd.rfind("OPEN", 0) == 0) {
showWindow();
} else if (cmd == "RELOAD_THEME") {
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall,
layoutIcon, nullptr, win);
render();
}
}
@@ -614,9 +609,6 @@ int calllog_run_main(int argc, char** argv) {
::unlink(getPluginFifoPath("calllog").c_str());
::unlink(daemonPidPath.c_str());
pango_font_description_free(descIcon);
pango_font_description_free(descSmall);
pango_font_description_free(descMain);
g_object_unref(layoutIcon);
g_object_unref(layoutSmall);
g_object_unref(layoutMain);
+48 -53
View File
@@ -198,10 +198,12 @@ int runCameraApp(int argc, char** argv) {
Visual* visual = DefaultVisual(dpy, screen);
Colormap cmap = DefaultColormap(dpy, screen);
ThemeSpec initSpec = loadThemeSpec(dpy, screen);
XSetWindowAttributes swa {};
swa.override_redirect = True;
swa.background_pixel = 0x181818;
swa.border_pixel = 0x005577;
swa.background_pixel = initSpec.bgMain;
swa.border_pixel = initSpec.selBg;
swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
VisibilityChangeMask | StructureNotifyMask;
@@ -223,37 +225,18 @@ int runCameraApp(int argc, char** argv) {
GC gc = XCreateGC(dpy, pix, 0, nullptr);
XftDraw* xftDraw = XftDrawCreate(dpy, pix, visual, cmap);
PangoFontMap* fontMap = pango_xft_get_font_map(dpy, screen);
PangoContext* pangoCtx = pango_font_map_create_context(fontMap);
PangoLayout* layoutMain = pango_layout_new(pangoCtx);
PangoFontDescription* descMain =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 15px");
pango_layout_set_font_description(layoutMain, descMain);
PangoLayout* layoutSmall = pango_layout_new(pangoCtx);
PangoFontDescription* descSmall =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 12px");
pango_layout_set_font_description(layoutSmall, descSmall);
PangoLayout* layoutIcon = pango_layout_new(pangoCtx);
PangoFontDescription* descIcon =
pango_font_description_from_string("DejaVuSansM Nerd Font, Fira Code 16px");
pango_layout_set_font_description(layoutIcon, descIcon);
auto allocColor = [&](const char* hex) {
XftColor col {};
XftColorAllocName(dpy, visual, cmap, hex, &col);
return col;
};
XftColor colWhite = allocColor("#ffffff");
XftColor colLight = allocColor("#dddddd");
XftColor colMuted = allocColor("#999999");
XftColor colYellow = allocColor("#f4d03f");
XftColor colGreen = allocColor("#2ecc71");
XftColor colBlue = allocColor("#5dade2");
XftColor colRed = allocColor("#e74c3c");
PluginTheme pt;
pt.init(dpy, screen, visual, cmap, win);
auto& layoutMain = pt.layoutMain;
auto& layoutSmall = pt.layoutSmall;
auto& layoutIcon = pt.layoutIcon;
auto& colWhite = pt.colWhite;
auto& colLight = pt.colLight;
auto& colMuted = pt.colMuted;
auto& colYellow = pt.colYellow;
auto& colGreen = pt.colGreen;
auto& colBlue = pt.colBlue;
auto& colRed = pt.colRed;
std::vector<uint32_t> vfFront(kVfW * kVfH, 0x101010);
std::vector<uint32_t> vfBack(kVfW * kVfH, 0x101010);
@@ -524,9 +507,9 @@ int runCameraApp(int argc, char** argv) {
const std::string& centerLabel,
const std::string& rightLabel) {
const int barY = kWinHeight - 26;
XSetForeground(dpy, gc, 0x141414);
XSetForeground(dpy, gc, pt.spec.bgFooter);
XFillRectangle(dpy, pix, gc, 0, barY, kWinWidth, 26);
XSetForeground(dpy, gc, 0x2d2d2d);
XSetForeground(dpy, gc, pt.spec.divider);
XDrawLine(dpy, pix, gc, 0, barY, kWinWidth, barY);
drawPango(layoutMain, &colBlue, 6, barY, 26, leftLabel);
@@ -549,14 +532,15 @@ int runCameraApp(int argc, char** argv) {
auto drawUI = [&]() {
if (!visible) return;
pt.checkAndReload();
int64_t tNow = nowMs();
XSetForeground(dpy, gc, 0x181818);
XSetForeground(dpy, gc, pt.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
if (mode == ViewMode::Viewfinder) {
// Top status bar (28px)
XSetForeground(dpy, gc, 0x141414);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 28);
drawPango(layoutIcon, &colGreen, 6, 0, 28, kIconCamera);
drawPango(layoutMain, &colWhite, 28, 0, 28, "800x600", 85);
@@ -590,7 +574,7 @@ int runCameraApp(int argc, char** argv) {
drawPango(layoutSmall, &colLight, 16, vfY + 78, 24, errMsg, 208);
} else {
// Subtle framing reticle in center of viewfinder
XSetForeground(dpy, gc, 0x0088bb);
XSetForeground(dpy, gc, pt.spec.accentAlt);
int cx = kWinWidth / 2;
int cy = vfY + kVfH / 2;
XDrawLine(dpy, pix, gc, cx - 10, cy, cx - 3, cy);
@@ -600,14 +584,14 @@ int runCameraApp(int argc, char** argv) {
}
if (tNow < shutterFlashUntilMs) {
XSetForeground(dpy, gc, 0xffffff);
XSetForeground(dpy, gc, pt.spec.fgBright);
XDrawRectangle(dpy, pix, gc, 0, vfY, kVfW - 1, kVfH - 1);
XDrawRectangle(dpy, pix, gc, 1, vfY + 1, kVfW - 3, kVfH - 3);
}
if (countdownActive) {
int remSec = std::max(1, static_cast<int>((countdownTargetMs - tNow + 999) / 1000));
XSetForeground(dpy, gc, 0x005577);
XSetForeground(dpy, gc, pt.spec.selBg);
XFillRectangle(dpy, pix, gc, 78, vfY + 66, 84, 44);
drawPango(layoutMain, &colWhite, 92, vfY + 66, 44,
"Timer: " + std::to_string(remSec));
@@ -615,31 +599,34 @@ int runCameraApp(int argc, char** argv) {
// Camera control strip (y = 208..270, 62px)
const int ctlY = 208;
XSetForeground(dpy, gc, 0x1e1e1e);
XSetForeground(dpy, gc, pt.spec.bgAltOdd);
XFillRectangle(dpy, pix, gc, 0, ctlY, kWinWidth, 62);
XSetForeground(dpy, gc, 0x333333);
XSetForeground(dpy, gc, pt.spec.border);
XDrawLine(dpy, pix, gc, 0, ctlY, kWinWidth, ctlY);
// Pill 1: Flash (* or 1)
XSetForeground(dpy, gc, fl ? 0x004466 : 0x282828);
XSetForeground(dpy, gc, fl ? pt.spec.bgInputFocus : pt.spec.bgButton);
XFillRectangle(dpy, pix, gc, 6, ctlY + 5, 110, 24);
drawPango(layoutSmall, fl ? &colYellow : &colLight, 10, ctlY + 5, 24,
std::string("[*] Flash:") + (fl ? "ON" : "OFF"), 102);
// Pill 2: Torch (0 or 2)
XSetForeground(dpy, gc, torchOn ? 0x004466 : 0x282828);
XSetForeground(dpy, gc,
torchOn ? pt.spec.bgInputFocus : pt.spec.bgButton);
XFillRectangle(dpy, pix, gc, 124, ctlY + 5, 110, 24);
drawPango(layoutSmall, torchOn ? &colYellow : &colLight, 128, ctlY + 5,
24, std::string("[0] Torch:") + (torchOn ? "ON" : "OFF"), 102);
// Pill 3: Zoom (Up/Dn)
XSetForeground(dpy, gc, zf > 1 ? 0x004466 : 0x282828);
XSetForeground(dpy, gc,
zf > 1 ? pt.spec.bgInputFocus : pt.spec.bgButton);
XFillRectangle(dpy, pix, gc, 6, ctlY + 33, 110, 24);
drawPango(layoutSmall, &colBlue, 10, ctlY + 33, 24,
"[U/D] Zoom:" + std::to_string(zf) + "x", 102);
// Pill 4: Timer (# or 3)
XSetForeground(dpy, gc, timerEnabled ? 0x004466 : 0x282828);
XSetForeground(dpy, gc,
timerEnabled ? pt.spec.bgInputFocus : pt.spec.bgButton);
XFillRectangle(dpy, pix, gc, 124, ctlY + 33, 110, 24);
drawPango(layoutSmall, timerEnabled ? &colYellow : &colLight, 128,
ctlY + 33, 24,
@@ -648,7 +635,7 @@ int runCameraApp(int argc, char** argv) {
drawSoftkeyBar("Gallery", "SNAP", "Close");
} else if (mode == ViewMode::Gallery) {
XSetForeground(dpy, gc, 0x141414);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 28);
drawPango(layoutIcon, &colBlue, 6, 0, 28, kIconImage);
drawPango(layoutMain, &colWhite, 28, 0, 28, "Gallery", 110);
@@ -684,7 +671,7 @@ int runCameraApp(int argc, char** argv) {
} else if (mode == ViewMode::ConfirmDelete && !photos.empty()) {
const auto& pe = photos[selectedPhoto];
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 36);
drawPango(layoutIcon, &colRed, 8, 0, 36, kIconTrash);
drawPango(layoutMain, &colWhite, 30, 0, 36, "Delete Photo?", 200);
@@ -696,8 +683,10 @@ int runCameraApp(int argc, char** argv) {
for (int i = 0; i < 2; ++i) {
int ry = 156 + i * 40;
bool isSel = (confirmSelected == i);
XSetForeground(dpy, gc,
isSel ? (i == 1 ? 0x922b21 : 0x005577) : 0x2a2a2a);
XSetForeground(
dpy, gc,
isSel ? (i == 1 ? pt.spec.dangerBg : pt.spec.selBg)
: pt.spec.bgButton);
XFillRectangle(dpy, pix, gc, 16, ry, kWinWidth - 32, 34);
drawPango(layoutMain, &colWhite, 28, ry, 34,
i == 0 ? "No, Keep Photo" : "Yes, Delete Photo", 184);
@@ -708,9 +697,9 @@ int runCameraApp(int argc, char** argv) {
{
std::lock_guard<std::mutex> lk(frameMutex);
if (!statusBanner.empty() && tNow < statusBannerUntilMs) {
XSetForeground(dpy, gc, 0x102535);
XSetForeground(dpy, gc, pt.spec.bgToast);
XFillRectangle(dpy, pix, gc, 8, 174, kWinWidth - 16, 28);
XSetForeground(dpy, gc, 0x2ecc71);
XSetForeground(dpy, gc, pt.spec.success);
XDrawRectangle(dpy, pix, gc, 8, 174, kWinWidth - 17, 27);
drawPango(layoutSmall, &colWhite, 14, 174, 28, statusBanner,
kWinWidth - 28);
@@ -814,6 +803,9 @@ int runCameraApp(int argc, char** argv) {
for (const auto& cmd : readFifoLines(fifoFd)) {
if (cmd == "NOP") {
continue;
} else if (cmd == "RELOAD_THEME") {
pt.reload();
if (visible) drawUI();
} else if (cmd == "CLOSE") {
hideWindow();
} else if (cmd == "OPEN") {
@@ -993,7 +985,10 @@ int runCameraApp(int argc, char** argv) {
if (pr > 0) {
if (fifoIdx >= 0 && (pfds[fifoIdx].revents & POLLIN)) {
for (const auto& cmd : readFifoLines(fifoFd)) {
if (cmd == "CLOSE") {
if (cmd == "RELOAD_THEME") {
pt.reload();
if (visible) drawUI();
} else if (cmd == "CLOSE") {
hideWindow();
} else if (cmd == "OPEN") {
showWindow("");
+50 -60
View File
@@ -130,33 +130,19 @@ int runContactsApp(int argc, char** argv) {
PangoContext* pangoCtx = pango_font_map_create_context(fontMap);
PangoLayout* layoutMain = pango_layout_new(pangoCtx);
PangoFontDescription* descMain =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 15px");
pango_layout_set_font_description(layoutMain, descMain);
PangoLayout* layoutSmall = pango_layout_new(pangoCtx);
PangoFontDescription* descSmall =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 12px");
pango_layout_set_font_description(layoutSmall, descSmall);
PangoLayout* layoutIcon = pango_layout_new(pangoCtx);
PangoFontDescription* descIcon =
pango_font_description_from_string("DejaVuSansM Nerd Font, Fira Code 16px");
pango_layout_set_font_description(layoutIcon, descIcon);
auto allocColor = [&](const char* hex) {
XftColor col{};
XftColorAllocName(dpy, visual, cmap, hex, &col);
return col;
};
XftColor colWhite = allocColor("#ffffff");
XftColor colLight = allocColor("#dddddd");
XftColor colMuted = allocColor("#999999");
XftColor colYellow = allocColor("#f4d03f");
XftColor colGreen = allocColor("#2ecc71");
XftColor colBlue = allocColor("#5dade2");
XftColor colRed = allocColor("#e74c3c");
PluginTheme theme;
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
nullptr, win);
XftColor& colWhite = theme.colWhite;
XftColor& colLight = theme.colLight;
XftColor& colMuted = theme.colMuted;
XftColor& colYellow = theme.colYellow;
XftColor& colGreen = theme.colGreen;
XftColor& colBlue = theme.colBlue;
XftColor& colRed = theme.colRed;
ContactBook book;
std::vector<ContactEntry> filtered;
@@ -277,9 +263,9 @@ int runContactsApp(int argc, char** argv) {
const std::string& rightLabel,
XftColor* centerCol = nullptr) {
int sbY = kWinHeight - kSoftbarH;
XSetForeground(dpy, gc, 0x181818);
XSetForeground(dpy, gc, theme.spec.bgFooter);
XFillRectangle(dpy, pix, gc, 0, sbY, kWinWidth, kSoftbarH);
XSetForeground(dpy, gc, 0x444444);
XSetForeground(dpy, gc, theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, sbY, kWinWidth, 1);
if (!leftLabel.empty()) {
@@ -298,14 +284,14 @@ int runContactsApp(int argc, char** argv) {
};
auto render = [&]() {
XSetForeground(dpy, gc, 0x222222);
XSetForeground(dpy, gc, theme.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
if (mode == ViewMode::List || mode == ViewMode::Options) {
// Header bar with live search / count
XSetForeground(dpy, gc, 0x1c1c1c);
XSetForeground(dpy, gc, theme.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kHeaderH);
XSetForeground(dpy, gc, 0x444444);
XSetForeground(dpy, gc, theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, kHeaderH - 1, kWinWidth, 1);
if (searchQuery.empty()) {
@@ -347,10 +333,10 @@ int runContactsApp(int argc, char** argv) {
bool isSel = (idx == selected);
XSetForeground(dpy, gc,
isSel ? 0x005577 : ((i % 2 == 0) ? 0x282828 : 0x2e2e2e));
isSel ? theme.spec.selBg : ((i % 2 == 0) ? theme.spec.bgAltEven : theme.spec.bgAltOdd));
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH);
if (isSel) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 0, ry, 4, rowH);
}
@@ -367,7 +353,7 @@ int runContactsApp(int argc, char** argv) {
int sbH = std::max(16, (kListH * kVisibleRows) / total);
int sbY = kListY +
((kListH - sbH) * scrollOffset) / (total - kVisibleRows);
XSetForeground(dpy, gc, 0x666666);
XSetForeground(dpy, gc, theme.spec.divider);
XFillRectangle(dpy, pix, gc, kWinWidth - 3, sbY, 3, sbH);
}
}
@@ -394,18 +380,18 @@ int runContactsApp(int argc, char** argv) {
int menuRowH = 34;
int menuH = optCount * menuRowH + 4;
int menuY = kWinHeight - kSoftbarH - menuH;
XSetForeground(dpy, gc, 0x181818);
XSetForeground(dpy, gc, theme.spec.bgFooter);
XFillRectangle(dpy, pix, gc, 8, menuY, kWinWidth - 16, menuH);
XSetForeground(dpy, gc, 0x005577);
XSetForeground(dpy, gc, theme.spec.selBg);
XDrawRectangle(dpy, pix, gc, 8, menuY, kWinWidth - 17, menuH - 1);
for (int i = 0; i < optCount; ++i) {
int ry = menuY + 2 + i * menuRowH;
bool isSel = (i == optionSelected);
if (isSel) {
XSetForeground(dpy, gc, 0x005577);
XSetForeground(dpy, gc, theme.spec.selBg);
XFillRectangle(dpy, pix, gc, 10, ry, kWinWidth - 20, menuRowH);
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 10, ry, 4, menuRowH);
}
XftColor* icCol = (i == 5) ? &colRed : (isSel ? &colYellow : &colGreen);
@@ -424,11 +410,11 @@ int runContactsApp(int argc, char** argv) {
c = filtered[selected];
}
constexpr int kCardH = 56;
XSetForeground(dpy, gc, 0x1b3b4b);
XSetForeground(dpy, gc, theme.spec.bgInputFocus);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kCardH);
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 0, 0, 4, kCardH);
XSetForeground(dpy, gc, 0x005577);
XSetForeground(dpy, gc, theme.spec.selBg);
XFillRectangle(dpy, pix, gc, 0, kCardH - 2, kWinWidth, 2);
drawPango(layoutIcon, &colYellow, 10, 6, 24, kIconUser);
@@ -469,10 +455,10 @@ int runContactsApp(int argc, char** argv) {
bool isSel = (idx == detailSelected);
XSetForeground(dpy, gc,
isSel ? 0x005577 : ((i % 2 == 0) ? 0x282828 : 0x2e2e2e));
isSel ? theme.spec.selBg : ((i % 2 == 0) ? theme.spec.bgAltEven : theme.spec.bgAltOdd));
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH);
if (isSel) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 0, ry, 4, rowH);
}
XftColor* icCol =
@@ -485,9 +471,9 @@ int runContactsApp(int argc, char** argv) {
drawSoftbar("Edit", "Select", "Back", &colGreen);
} else if (mode == ViewMode::Edit) {
XSetForeground(dpy, gc, 0x1c1c1c);
XSetForeground(dpy, gc, theme.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kHeaderH);
XSetForeground(dpy, gc, 0x444444);
XSetForeground(dpy, gc, theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, kHeaderH - 1, kWinWidth, 1);
drawPango(layoutIcon, &colGreen, 8, 0, kHeaderH,
@@ -505,9 +491,9 @@ int runContactsApp(int argc, char** argv) {
// Field 0: Name box (y = 44..108)
auto drawFieldBox = [&](int y, int h, bool active, const char* label,
const std::string& val, const char* placeholder) {
XSetForeground(dpy, gc, active ? 0x1b3b4b : 0x2a2a2a);
XSetForeground(dpy, gc, active ? theme.spec.bgInputFocus : theme.spec.bgButton);
XFillRectangle(dpy, pix, gc, 6, y, kWinWidth - 12, h);
XSetForeground(dpy, gc, active ? 0xf4d03f : 0x444444);
XSetForeground(dpy, gc, active ? theme.spec.accent : theme.spec.border);
XDrawRectangle(dpy, pix, gc, 6, y, kWinWidth - 13, h - 1);
drawPango(layoutSmall, active ? &colYellow : &colMuted, 12, y + 3, 18,
label);
@@ -533,10 +519,10 @@ int runContactsApp(int argc, char** argv) {
// Button Row 2: Pick from Recent Numbers (y = 168..208)
auto drawBtnRow = [&](int y, int h, bool active, const char* icon,
const char* label, XftColor* icCol) {
XSetForeground(dpy, gc, active ? 0x005577 : 0x2c2c2c);
XSetForeground(dpy, gc, active ? theme.spec.selBg : theme.spec.bgButton);
XFillRectangle(dpy, pix, gc, 6, y, kWinWidth - 12, h);
if (active) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 6, y, 4, h);
}
drawPango(layoutIcon, active ? &colYellow : icCol, 14, y, h, icon);
@@ -555,9 +541,9 @@ int runContactsApp(int argc, char** argv) {
drawSoftbar("Save", (editField >= 2) ? "Select" : "Next",
canClearChar ? "Clear" : "Cancel", &colGreen);
} else if (mode == ViewMode::PickRecent) {
XSetForeground(dpy, gc, 0x1c1c1c);
XSetForeground(dpy, gc, theme.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kHeaderH);
XSetForeground(dpy, gc, 0x444444);
XSetForeground(dpy, gc, theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, kHeaderH - 1, kWinWidth, 1);
drawPango(layoutIcon, &colBlue, 8, 0, kHeaderH, kIconClock);
drawPango(layoutMain, &colWhite, 32, 0, kHeaderH, "Recent Numbers", 200);
@@ -579,10 +565,10 @@ int runContactsApp(int argc, char** argv) {
int rowH = nextRy - ry;
bool isSel = (idx == recentSelected);
XSetForeground(dpy, gc,
isSel ? 0x005577 : ((i % 2 == 0) ? 0x282828 : 0x2e2e2e));
isSel ? theme.spec.selBg : ((i % 2 == 0) ? theme.spec.bgAltEven : theme.spec.bgAltOdd));
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH);
if (isSel) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 0, ry, 4, rowH);
}
drawPango(layoutIcon, isSel ? &colYellow : &colGreen, 10, ry, rowH,
@@ -593,7 +579,7 @@ int runContactsApp(int argc, char** argv) {
}
drawSoftbar("Use", "Select", "Back", &colGreen);
} else if (mode == ViewMode::ConfirmDelete) {
XSetForeground(dpy, gc, 0x1c1c1c);
XSetForeground(dpy, gc, theme.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kHeaderH);
drawPango(layoutIcon, &colRed, 8, 0, kHeaderH, kIconTrash);
drawPango(layoutMain, &colWhite, 32, 0, kHeaderH, "Delete Contact?", 200);
@@ -609,10 +595,10 @@ int runContactsApp(int argc, char** argv) {
for (int i = 0; i < 2; ++i) {
int ry = 130 + i * 50;
bool isSel = (i == confirmSelected);
XSetForeground(dpy, gc, isSel ? 0x005577 : 0x2c2c2c);
XSetForeground(dpy, gc, isSel ? theme.spec.selBg : theme.spec.bgButton);
XFillRectangle(dpy, pix, gc, 8, ry, kWinWidth - 16, 44);
if (isSel) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 8, ry, 4, 44);
}
drawPango(layoutIcon, (i == 1) ? &colRed : &colGreen, 16, ry, 44,
@@ -691,6 +677,9 @@ int runContactsApp(int argc, char** argv) {
auto showWindow = [&](const std::string& arg) {
closeOtherPlugins("contacts");
bool themeChanged = theme.checkAndReload(
dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
nullptr, win);
bool openNewMode = (arg.rfind("new:", 0) == 0);
std::string prefill = openNewMode ? arg.substr(4) : "";
@@ -703,7 +692,7 @@ int runContactsApp(int argc, char** argv) {
zeroHeld = false;
visible = true;
XMapRaised(dpy, win);
if (!openNewMode) {
if (!openNewMode && !themeChanged) {
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
}
for (int i = 0; i < 20; ++i) {
@@ -717,8 +706,8 @@ int runContactsApp(int argc, char** argv) {
if (openNewMode) {
beginNewContact(prefill);
render();
} else if (reloaded || mode != ViewMode::List || !searchQuery.empty() ||
selected != 0) {
} else if (reloaded || themeChanged || mode != ViewMode::List ||
!searchQuery.empty() || selected != 0) {
mode = ViewMode::List;
searchQuery.clear();
selected = 0;
@@ -918,6 +907,10 @@ int runContactsApp(int argc, char** argv) {
} else {
showWindow("");
}
} else if (cmd == "RELOAD_THEME") {
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall,
layoutIcon, nullptr, win);
render();
} else if (cmd == "OPEN") {
showWindow("");
} else if (cmd.rfind("OPEN ", 0) == 0) {
@@ -1443,9 +1436,6 @@ int runContactsApp(int argc, char** argv) {
::unlink(getPluginFifoPath("contacts").c_str());
::unlink(daemonPidPath.c_str());
pango_font_description_free(descIcon);
pango_font_description_free(descSmall);
pango_font_description_free(descMain);
g_object_unref(layoutIcon);
g_object_unref(layoutSmall);
g_object_unref(layoutMain);
+27 -42
View File
@@ -106,37 +106,19 @@ int dialer_run_main(int argc, char** argv) {
PangoContext* pangoCtx = pango_font_map_create_context(fontMap);
PangoLayout* layoutNum = pango_layout_new(pangoCtx);
PangoFontDescription* descNum =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font Bold 18px");
pango_layout_set_font_description(layoutNum, descNum);
PangoLayout* layoutMain = pango_layout_new(pangoCtx);
PangoFontDescription* descMain =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 15px");
pango_layout_set_font_description(layoutMain, descMain);
PangoLayout* layoutSmall = pango_layout_new(pangoCtx);
PangoFontDescription* descSmall =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 12px");
pango_layout_set_font_description(layoutSmall, descSmall);
PangoLayout* layoutIcon = pango_layout_new(pangoCtx);
PangoFontDescription* descIcon =
pango_font_description_from_string("DejaVuSansM Nerd Font, Fira Code 16px");
pango_layout_set_font_description(layoutIcon, descIcon);
auto allocColor = [&](const char* hex) {
XftColor col{};
XftColorAllocName(dpy, visual, cmap, hex, &col);
return col;
};
XftColor colWhite = allocColor("#ffffff");
XftColor colLight = allocColor("#dddddd");
XftColor colMuted = allocColor("#999999");
XftColor colYellow = allocColor("#f4d03f");
XftColor colGreen = allocColor("#2ecc71");
XftColor colBlue = allocColor("#5dade2");
PluginTheme theme;
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
layoutNum, win);
XftColor& colWhite = theme.colWhite;
XftColor& colLight = theme.colLight;
XftColor& colMuted = theme.colMuted;
XftColor& colYellow = theme.colYellow;
XftColor& colGreen = theme.colGreen;
XftColor& colBlue = theme.colBlue;
ContactBook book;
std::vector<ContactEntry> allContacts;
@@ -241,17 +223,17 @@ int dialer_run_main(int argc, char** argv) {
constexpr int kVisibleRows = 5;
auto render = [&]() {
XSetForeground(dpy, gc, 0x222222);
XSetForeground(dpy, gc, theme.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
bool topSel = (selected < 0);
XSetForeground(dpy, gc, topSel ? 0x1b3b4b : 0x1c1c1c);
XSetForeground(dpy, gc, topSel ? theme.spec.bgInputFocus : theme.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kHeaderH);
if (topSel) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 0, 0, 4, kHeaderH);
}
XSetForeground(dpy, gc, topSel ? 0x005577 : 0x444444);
XSetForeground(dpy, gc, topSel ? theme.spec.selBg : theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, kHeaderH - 2, kWinWidth, 2);
drawPango(layoutIcon, &colGreen, 10, 4, 30, kIconPhone);
@@ -315,11 +297,11 @@ int dialer_run_main(int argc, char** argv) {
bool isSel = (idx == selected);
XSetForeground(dpy, gc,
isSel ? 0x005577 : ((i % 2 == 0) ? 0x282828 : 0x2e2e2e));
isSel ? theme.spec.selBg : ((i % 2 == 0) ? theme.spec.bgAltEven : theme.spec.bgAltOdd));
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH);
if (isSel) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 0, ry, 4, rowH);
}
@@ -345,15 +327,15 @@ int dialer_run_main(int argc, char** argv) {
int sbH = std::max(16, (kListH * kVisibleRows) / total);
int sbY = kListY +
((kListH - sbH) * scrollOffset) / (total - kVisibleRows);
XSetForeground(dpy, gc, 0x666666);
XSetForeground(dpy, gc, theme.spec.divider);
XFillRectangle(dpy, pix, gc, kWinWidth - 3, sbY, 3, sbH);
}
}
int sbY = kWinHeight - kSoftbarH;
XSetForeground(dpy, gc, 0x181818);
XSetForeground(dpy, gc, theme.spec.bgFooter);
XFillRectangle(dpy, pix, gc, 0, sbY, kWinWidth, kSoftbarH);
XSetForeground(dpy, gc, 0x444444);
XSetForeground(dpy, gc, theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, sbY, kWinWidth, 1);
std::string leftLabel = number.empty() ? "Call Log" : "+Sign";
@@ -387,6 +369,9 @@ int dialer_run_main(int argc, char** argv) {
auto showWindow = [&](const std::string& arg) {
closeOtherPlugins("dialer");
bool themeChanged = theme.checkAndReload(
dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
layoutNum, win);
std::string cleanArg = normalizePhone(arg);
if (!visible) {
openStartMs = nowMs();
@@ -398,7 +383,7 @@ int dialer_run_main(int argc, char** argv) {
zeroPressMs = zeroHeld ? openStartMs : 0;
visible = true;
XMapRaised(dpy, win);
if (cleanArg.empty()) {
if (cleanArg.empty() && !themeChanged) {
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
}
for (int i = 0; i < 20; ++i) {
@@ -409,7 +394,7 @@ int dialer_run_main(int argc, char** argv) {
usleep(2000);
}
bool reloaded = reloadContactsIfNeeded();
if (!cleanArg.empty() || reloaded || number != cleanArg) {
if (!cleanArg.empty() || reloaded || themeChanged || number != cleanArg) {
number = cleanArg;
selected = number.empty() ? (allContacts.empty() ? -1 : 0) : -1;
updateFilter();
@@ -494,6 +479,10 @@ int dialer_run_main(int argc, char** argv) {
showWindow("");
} else if (cmd.rfind("OPEN ", 0) == 0) {
showWindow(cmd.substr(5));
} else if (cmd == "RELOAD_THEME") {
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall,
layoutIcon, layoutNum, win);
render();
}
}
@@ -723,10 +712,6 @@ int dialer_run_main(int argc, char** argv) {
::unlink(getPluginFifoPath("dialer").c_str());
::unlink(daemonPidPath.c_str());
pango_font_description_free(descIcon);
pango_font_description_free(descSmall);
pango_font_description_free(descMain);
pango_font_description_free(descNum);
g_object_unref(layoutIcon);
g_object_unref(layoutSmall);
g_object_unref(layoutMain);
+7 -1
View File
@@ -127,7 +127,10 @@ static int try_dmenu_socket_client(int sub_argc, char **sub_argv, int *exit_code
}
static int try_send_plugin_fifo(const char *plugin_name, int sub_argc, char **sub_argv) {
if (sub_argc >= 2 && sub_argv[1] && strcmp(sub_argv[1], "--preload") == 0) {
if (sub_argc >= 2 && sub_argv[1] &&
(strcmp(sub_argv[1], "--preload") == 0 ||
strcmp(sub_argv[1], "--apply") == 0 ||
strcmp(sub_argv[1], "--export-default") == 0)) {
return 0;
}
char pid_path[128];
@@ -212,6 +215,9 @@ static const char *resolve_plugin_name_from_argv0(const char *argv0) {
if (strcasecmp(base, "xcamera") == 0 || strcasecmp(base, "camera") == 0) {
return "camera";
}
if (strcasecmp(base, "xthemes") == 0 || strcasecmp(base, "themes") == 0) {
return "themes";
}
return NULL;
}
+49 -56
View File
@@ -236,10 +236,12 @@ int runFilesApp(int argc, char** argv) {
Visual* visual = DefaultVisual(dpy, screen);
Colormap cmap = DefaultColormap(dpy, screen);
ThemeSpec initSpec = loadThemeSpec(dpy, screen);
XSetWindowAttributes swa {};
swa.override_redirect = True;
swa.background_pixel = 0x222222;
swa.border_pixel = 0x005577;
swa.background_pixel = initSpec.bgMain;
swa.border_pixel = initSpec.selBg;
swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
VisibilityChangeMask | StructureNotifyMask;
@@ -261,38 +263,19 @@ int runFilesApp(int argc, char** argv) {
GC gc = XCreateGC(dpy, pix, 0, nullptr);
XftDraw* xftDraw = XftDrawCreate(dpy, pix, visual, cmap);
PangoFontMap* fontMap = pango_xft_get_font_map(dpy, screen);
PangoContext* pangoCtx = pango_font_map_create_context(fontMap);
PangoLayout* layoutMain = pango_layout_new(pangoCtx);
PangoFontDescription* descMain =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 15px");
pango_layout_set_font_description(layoutMain, descMain);
PangoLayout* layoutSmall = pango_layout_new(pangoCtx);
PangoFontDescription* descSmall =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 12px");
pango_layout_set_font_description(layoutSmall, descSmall);
PangoLayout* layoutIcon = pango_layout_new(pangoCtx);
PangoFontDescription* descIcon =
pango_font_description_from_string("DejaVuSansM Nerd Font, Fira Code 16px");
pango_layout_set_font_description(layoutIcon, descIcon);
auto allocColor = [&](const char* hex) {
XftColor col {};
XftColorAllocName(dpy, visual, cmap, hex, &col);
return col;
};
XftColor colWhite = allocColor("#ffffff");
XftColor colLight = allocColor("#dddddd");
XftColor colMuted = allocColor("#999999");
XftColor colYellow = allocColor("#f4d03f");
XftColor colGreen = allocColor("#2ecc71");
XftColor colBlue = allocColor("#5dade2");
XftColor colOrange = allocColor("#e67e22");
XftColor colRed = allocColor("#e74c3c");
PluginTheme pt;
pt.init(dpy, screen, visual, cmap, win);
auto& layoutMain = pt.layoutMain;
auto& layoutSmall = pt.layoutSmall;
auto& layoutIcon = pt.layoutIcon;
auto& colWhite = pt.colWhite;
auto& colLight = pt.colLight;
auto& colMuted = pt.colMuted;
auto& colYellow = pt.colYellow;
auto& colGreen = pt.colGreen;
auto& colBlue = pt.colBlue;
auto& colOrange = pt.colOrange;
auto& colRed = pt.colRed;
const char* homeEnv = std::getenv("HOME");
std::string homeDir = (homeEnv && homeEnv[0]) ? homeEnv : "/home/user";
@@ -599,9 +582,9 @@ int runFilesApp(int argc, char** argv) {
const std::string& centerLabel,
const std::string& rightLabel) {
const int barY = kWinHeight - 26;
XSetForeground(dpy, gc, 0x141414);
XSetForeground(dpy, gc, pt.spec.bgFooter);
XFillRectangle(dpy, pix, gc, 0, barY, kWinWidth, 26);
XSetForeground(dpy, gc, 0x2d2d2d);
XSetForeground(dpy, gc, pt.spec.divider);
XDrawLine(dpy, pix, gc, 0, barY, kWinWidth, barY);
drawPango(layoutMain, &colBlue, 6, barY, 26, leftLabel);
@@ -624,14 +607,15 @@ int runFilesApp(int argc, char** argv) {
auto drawUI = [&]() {
if (!visible) return;
pt.checkAndReload();
XSetForeground(dpy, gc, 0x222222);
XSetForeground(dpy, gc, pt.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
if (mode == ViewMode::Browser) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 38);
XSetForeground(dpy, gc, 0x333333);
XSetForeground(dpy, gc, pt.spec.border);
XDrawLine(dpy, pix, gc, 0, 37, kWinWidth, 37);
if (searchQuery.empty()) {
@@ -681,12 +665,13 @@ int runFilesApp(int argc, char** argv) {
bool isSel = (idx == selected);
if (isSel) {
XSetForeground(dpy, gc, 0x005577);
XSetForeground(dpy, gc, pt.spec.selBg);
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH - 1);
XSetForeground(dpy, gc, 0x0088bb);
XSetForeground(dpy, gc, pt.spec.accentAlt);
XDrawLine(dpy, pix, gc, 0, ry, kWinWidth, ry);
} else {
XSetForeground(dpy, gc, (i % 2 == 0) ? 0x222222 : 0x1d1d1d);
XSetForeground(dpy, gc,
(i % 2 == 0) ? pt.spec.bgAltEven : pt.spec.bgAltOdd);
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH - 1);
}
@@ -738,7 +723,7 @@ int runFilesApp(int argc, char** argv) {
searchQuery.empty() ? "Close" : "Clear");
} else if (mode == ViewMode::Actions) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 34);
drawPango(layoutIcon, &colBlue, 6, 0, 34, kIconList);
drawPango(layoutMain, &colWhite, 28, 0, 34, "File Actions", 200);
@@ -755,7 +740,7 @@ int runFilesApp(int argc, char** argv) {
if (idx >= static_cast<int>(actionsList.size())) break;
int ry = listY + i * rowH;
bool isSel = (idx == actionSelected);
XSetForeground(dpy, gc, isSel ? 0x005577 : 0x222222);
XSetForeground(dpy, gc, isSel ? pt.spec.selBg : pt.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH - 1);
drawPango(layoutIcon, isSel ? &colYellow : &colBlue, 8, ry, rowH,
actionsList[idx].icon);
@@ -765,7 +750,7 @@ int runFilesApp(int argc, char** argv) {
drawSoftkeyBar("Select", "Select", "Back");
} else if (mode == ViewMode::TextView) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 32);
drawPango(layoutIcon, &colBlue, 6, 0, 32, kIconFileText);
drawPango(layoutMain, &colWhite, 28, 0, 32, viewingFileName, 150);
@@ -791,7 +776,7 @@ int runFilesApp(int argc, char** argv) {
drawSoftkeyBar("Edit", "Down", "Back");
} else if (mode == ViewMode::ImageView) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 36);
drawPango(layoutIcon, &colGreen, 6, 1, 18, kIconImage);
drawPango(layoutMain, &colWhite, 28, 0, 20, viewingFileName, 145);
@@ -807,7 +792,7 @@ int runFilesApp(int argc, char** argv) {
} else if (mode == ViewMode::PropsView && !filteredItems.empty()) {
const auto& it = filteredItems[selected];
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 34);
drawPango(layoutIcon, &colBlue, 6, 0, 34, kIconInfo);
drawPango(layoutMain, &colWhite, 28, 0, 34, "Properties", 200);
@@ -838,7 +823,7 @@ int runFilesApp(int argc, char** argv) {
drawSoftkeyBar("Back", "Back", "Back");
} else if (mode == ViewMode::InputModal) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 36);
drawPango(layoutIcon, &colBlue, 6, 0, 36, kIconEdit);
drawPango(layoutMain, &colWhite, 28, 0, 36, inputTitle, 145);
@@ -849,9 +834,9 @@ int runFilesApp(int argc, char** argv) {
else if (caseMode == TextCaseMode::Num) mBadge = "[123]";
drawPango(layoutSmall, &colYellow, kWinWidth - 46, 0, 36, mBadge);
XSetForeground(dpy, gc, 0x182630);
XSetForeground(dpy, gc, pt.spec.bgInputFocus);
XFillRectangle(dpy, pix, gc, 10, 74, kWinWidth - 20, 38);
XSetForeground(dpy, gc, 0x0088bb);
XSetForeground(dpy, gc, pt.spec.accentAlt);
XDrawRectangle(dpy, pix, gc, 10, 74, kWinWidth - 21, 37);
drawPango(layoutMain, &colWhite, 16, 74, 38, inputValue + "|",
kWinWidth - 32);
@@ -863,7 +848,7 @@ int runFilesApp(int argc, char** argv) {
} else if (mode == ViewMode::ConfirmDelete && !filteredItems.empty()) {
const auto& it = filteredItems[selected];
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 36);
drawPango(layoutIcon, &colRed, 8, 0, 36, kIconTrash);
drawPango(layoutMain, &colWhite, 30, 0, 36, "Delete Item?", 200);
@@ -878,8 +863,10 @@ int runFilesApp(int argc, char** argv) {
for (int i = 0; i < 2; ++i) {
int ry = 164 + i * 40;
bool isSel = (confirmSelected == i);
XSetForeground(dpy, gc,
isSel ? (i == 1 ? 0x922b21 : 0x005577) : 0x2a2a2a);
XSetForeground(
dpy, gc,
isSel ? (i == 1 ? pt.spec.dangerBg : pt.spec.selBg)
: pt.spec.bgButton);
XFillRectangle(dpy, pix, gc, 16, ry, kWinWidth - 32, 34);
drawPango(layoutMain, &colWhite, 28, ry, 34,
i == 0 ? "No, Keep Item" : "Yes, Delete", 184);
@@ -889,9 +876,9 @@ int runFilesApp(int argc, char** argv) {
int64_t tNow = nowMs();
if (!statusBanner.empty() && tNow < statusBannerUntilMs) {
XSetForeground(dpy, gc, 0x102535);
XSetForeground(dpy, gc, pt.spec.bgToast);
XFillRectangle(dpy, pix, gc, 8, kWinHeight - 58, kWinWidth - 16, 28);
XSetForeground(dpy, gc, 0x5dade2);
XSetForeground(dpy, gc, pt.spec.info);
XDrawRectangle(dpy, pix, gc, 8, kWinHeight - 58, kWinWidth - 17, 27);
drawPango(layoutSmall, &colWhite, 14, kWinHeight - 58, 28, statusBanner,
kWinWidth - 28);
@@ -1151,6 +1138,9 @@ int runFilesApp(int argc, char** argv) {
for (const auto& cmd : readFifoLines(fifoFd)) {
if (cmd == "NOP") {
continue;
} else if (cmd == "RELOAD_THEME") {
pt.reload();
if (visible) drawUI();
} else if (cmd == "CLOSE") {
hideWindow();
} else if (cmd == "OPEN") {
@@ -1384,7 +1374,10 @@ int runFilesApp(int argc, char** argv) {
int pr = ::poll(pfds, nfds, timeoutMs);
if (pr > 0 && fifoIdx >= 0 && (pfds[fifoIdx].revents & POLLIN)) {
for (const auto& cmd : readFifoLines(fifoFd)) {
if (cmd == "CLOSE") {
if (cmd == "RELOAD_THEME") {
pt.reload();
if (visible) drawUI();
} else if (cmd == "CLOSE") {
hideWindow();
} else if (cmd == "OPEN") {
showWindow("");
+30
View File
@@ -8,6 +8,8 @@
#define _EVDEVK(_v) (0x10081000 + (_v))
#endif
#include "theme.h"
#include <algorithm>
#include <cctype>
#include <csignal>
@@ -69,6 +71,7 @@ constexpr const char* kIconInfo = "\xef\x81\x9a"; // U+F05A info-circle
constexpr const char* kIconRefresh = "\xef\x80\xa1"; // U+F021 refresh
constexpr const char* kIconSort = "\xef\x83\x9c"; // U+F0DC sort
constexpr const char* kIconEye = "\xef\x81\xae"; // U+F06E eye/view
constexpr const char* kIconPalette = "\xef\x87\xbc"; // U+F1FC paint-brush / theme
inline int64_t nowMs() {
struct timespec ts {};
@@ -962,6 +965,7 @@ inline void closeOtherPlugins(const char* selfPluginName) {
{"xsms.pid", "sms"},
{"xfiles.pid", "files"},
{"xcamera.pid", "camera"},
{"xthemes.pid", "themes"},
};
for (const auto& p : kAllPlugins) {
if (selfPluginName && std::strcmp(p.name, selfPluginName) == 0) {
@@ -976,6 +980,32 @@ inline void closeOtherPlugins(const char* selfPluginName) {
}
}
inline void broadcastThemeReload(const char* selfPluginName = nullptr) {
static const char* kPlugins[] = {
"dmenu",
"xdrawer",
"dialer",
"calllog",
"contacts",
"sms",
"files",
"camera",
"themes",
};
for (const char* name : kPlugins) {
if (selfPluginName && std::strcmp(name, selfPluginName) == 0) {
continue;
}
std::string fifoPath = getPluginFifoPath(name);
int fd = ::open(fifoPath.c_str(), O_WRONLY | O_NONBLOCK | O_CLOEXEC);
if (fd >= 0) {
(void)::write(fd, "RELOAD_THEME\n", 13);
::close(fd);
}
}
runAsyncCmd("pkill -USR1 -x st >/dev/null 2>&1");
}
inline std::string getModemLogDirPath() {
const char* env = std::getenv("SXMO_LOGDIR");
if (env && env[0]) {
+64 -66
View File
@@ -130,10 +130,12 @@ int runSmsApp(int argc, char** argv) {
Visual* visual = DefaultVisual(dpy, screen);
Colormap cmap = DefaultColormap(dpy, screen);
ThemeSpec initSpec = loadThemeSpec(dpy, screen);
XSetWindowAttributes swa {};
swa.override_redirect = True;
swa.background_pixel = 0x222222;
swa.border_pixel = 0x005577;
swa.background_pixel = initSpec.bgMain;
swa.border_pixel = initSpec.selBg;
swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
VisibilityChangeMask | StructureNotifyMask;
@@ -155,37 +157,18 @@ int runSmsApp(int argc, char** argv) {
GC gc = XCreateGC(dpy, pix, 0, nullptr);
XftDraw* xftDraw = XftDrawCreate(dpy, pix, visual, cmap);
PangoFontMap* fontMap = pango_xft_get_font_map(dpy, screen);
PangoContext* pangoCtx = pango_font_map_create_context(fontMap);
PangoLayout* layoutMain = pango_layout_new(pangoCtx);
PangoFontDescription* descMain =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 15px");
pango_layout_set_font_description(layoutMain, descMain);
PangoLayout* layoutSmall = pango_layout_new(pangoCtx);
PangoFontDescription* descSmall =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 12px");
pango_layout_set_font_description(layoutSmall, descSmall);
PangoLayout* layoutIcon = pango_layout_new(pangoCtx);
PangoFontDescription* descIcon =
pango_font_description_from_string("DejaVuSansM Nerd Font, Fira Code 16px");
pango_layout_set_font_description(layoutIcon, descIcon);
auto allocColor = [&](const char* hex) {
XftColor col {};
XftColorAllocName(dpy, visual, cmap, hex, &col);
return col;
};
XftColor colWhite = allocColor("#ffffff");
XftColor colLight = allocColor("#dddddd");
XftColor colMuted = allocColor("#999999");
XftColor colYellow = allocColor("#f4d03f");
XftColor colGreen = allocColor("#2ecc71");
XftColor colBlue = allocColor("#5dade2");
XftColor colRed = allocColor("#e74c3c");
PluginTheme pt;
pt.init(dpy, screen, visual, cmap, win);
auto& layoutMain = pt.layoutMain;
auto& layoutSmall = pt.layoutSmall;
auto& layoutIcon = pt.layoutIcon;
auto& colWhite = pt.colWhite;
auto& colLight = pt.colLight;
auto& colMuted = pt.colMuted;
auto& colYellow = pt.colYellow;
auto& colGreen = pt.colGreen;
auto& colBlue = pt.colBlue;
auto& colRed = pt.colRed;
ContactBook book;
std::vector<SmsThread> allThreads;
@@ -442,9 +425,9 @@ int runSmsApp(int argc, char** argv) {
const std::string& centerLabel,
const std::string& rightLabel) {
const int barY = kWinHeight - 26;
XSetForeground(dpy, gc, 0x141414);
XSetForeground(dpy, gc, pt.spec.bgFooter);
XFillRectangle(dpy, pix, gc, 0, barY, kWinWidth, 26);
XSetForeground(dpy, gc, 0x2d2d2d);
XSetForeground(dpy, gc, pt.spec.divider);
XDrawLine(dpy, pix, gc, 0, barY, kWinWidth, barY);
drawPango(layoutMain, &colBlue, 6, barY, 26, leftLabel);
@@ -467,14 +450,15 @@ int runSmsApp(int argc, char** argv) {
auto drawUI = [&]() {
if (!visible) return;
pt.checkAndReload();
XSetForeground(dpy, gc, 0x222222);
XSetForeground(dpy, gc, pt.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
if (mode == ViewMode::Threads) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 38);
XSetForeground(dpy, gc, 0x333333);
XSetForeground(dpy, gc, pt.spec.border);
XDrawLine(dpy, pix, gc, 0, 37, kWinWidth, 37);
if (searchQuery.empty()) {
@@ -521,12 +505,13 @@ int runSmsApp(int argc, char** argv) {
bool isSel = (idx == selectedThread);
if (isSel) {
XSetForeground(dpy, gc, 0x005577);
XSetForeground(dpy, gc, pt.spec.selBg);
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH - 1);
XSetForeground(dpy, gc, 0x0088bb);
XSetForeground(dpy, gc, pt.spec.accentAlt);
XDrawLine(dpy, pix, gc, 0, ry, kWinWidth, ry);
} else {
XSetForeground(dpy, gc, (i % 2 == 0) ? 0x222222 : 0x1d1d1d);
XSetForeground(dpy, gc,
(i % 2 == 0) ? pt.spec.bgAltEven : pt.spec.bgAltOdd);
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH - 1);
}
@@ -562,9 +547,9 @@ int runSmsApp(int argc, char** argv) {
searchQuery.empty() ? "Close" : "Clear");
} else if (mode == ViewMode::ThreadView) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 36);
XSetForeground(dpy, gc, 0x333333);
XSetForeground(dpy, gc, pt.spec.border);
XDrawLine(dpy, pix, gc, 0, 35, kWinWidth, 35);
std::string cname = book.resolveName(activeNumber);
@@ -640,13 +625,15 @@ int runSmsApp(int argc, char** argv) {
int cardH = std::min(cg.h, areaH - 4);
unsigned long bg = isSel
? 0x004466
: (cg.incoming ? 0x262d32 : 0x1f2d38);
? pt.spec.bgInputFocus
: (cg.incoming ? pt.spec.bgBubbleIn
: pt.spec.bgBubbleOut);
XSetForeground(dpy, gc, bg);
XFillRectangle(dpy, pix, gc, cardX, curY, cardW, cardH);
unsigned long accent = cg.incoming ? 0x2ecc71 : 0x5dade2;
XSetForeground(dpy, gc, isSel ? 0xf4d03f : accent);
unsigned long accent =
cg.incoming ? pt.spec.success : pt.spec.info;
XSetForeground(dpy, gc, isSel ? pt.spec.accent : accent);
if (cg.incoming) {
XFillRectangle(dpy, pix, gc, cardX, curY, 3, cardH);
} else {
@@ -672,9 +659,9 @@ int runSmsApp(int argc, char** argv) {
drawSoftkeyBar("Options", "Reply", "Back");
} else if (mode == ViewMode::Compose) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 32);
XSetForeground(dpy, gc, 0x333333);
XSetForeground(dpy, gc, pt.spec.border);
XDrawLine(dpy, pix, gc, 0, 31, kWinWidth, 31);
drawPango(layoutIcon, &colBlue, 6, 0, 30, kIconSend);
@@ -703,9 +690,10 @@ int runSmsApp(int argc, char** argv) {
// Field 0: Recipient
bool toSel = (composeField == 0);
XSetForeground(dpy, gc, toSel ? 0x004466 : 0x1a1a1a);
XSetForeground(dpy, gc,
toSel ? pt.spec.bgInputFocus : pt.spec.bgInput);
XFillRectangle(dpy, pix, gc, 6, 36, kWinWidth - 12, 32);
XSetForeground(dpy, gc, toSel ? 0x0088bb : 0x383838);
XSetForeground(dpy, gc, toSel ? pt.spec.accentAlt : pt.spec.border);
XDrawRectangle(dpy, pix, gc, 6, 36, kWinWidth - 13, 31);
std::string cname = book.resolveName(composeRecipient);
@@ -719,9 +707,10 @@ int runSmsApp(int argc, char** argv) {
// Field 1: Message Body
bool msgSel = (composeField == 1);
XSetForeground(dpy, gc, msgSel ? 0x182630 : 0x181818);
XSetForeground(dpy, gc,
msgSel ? pt.spec.bgInputFocus : pt.spec.bgInput);
XFillRectangle(dpy, pix, gc, 6, 72, kWinWidth - 12, 156);
XSetForeground(dpy, gc, msgSel ? 0x0088bb : 0x383838);
XSetForeground(dpy, gc, msgSel ? pt.spec.accentAlt : pt.spec.border);
XDrawRectangle(dpy, pix, gc, 6, 72, kWinWidth - 13, 155);
std::string bodyDisp = composeText;
@@ -752,15 +741,15 @@ int runSmsApp(int argc, char** argv) {
// Field 2 & 3: Send & Save Draft buttons
bool sendSel = (composeField == 2);
bool draftSel = (composeField == 3);
XSetForeground(dpy, gc, sendSel ? 0x005577 : 0x262626);
XSetForeground(dpy, gc, sendSel ? pt.spec.selBg : pt.spec.bgButton);
XFillRectangle(dpy, pix, gc, 6, 234, 118, 30);
XSetForeground(dpy, gc, sendSel ? 0x0088bb : 0x444444);
XSetForeground(dpy, gc, sendSel ? pt.spec.accentAlt : pt.spec.border);
XDrawRectangle(dpy, pix, gc, 6, 234, 117, 29);
drawPango(layoutMain, &colGreen, 18, 234, 30, "Send SMS", 100);
XSetForeground(dpy, gc, draftSel ? 0x005577 : 0x262626);
XSetForeground(dpy, gc, draftSel ? pt.spec.selBg : pt.spec.bgButton);
XFillRectangle(dpy, pix, gc, 130, 234, 104, 30);
XSetForeground(dpy, gc, draftSel ? 0x0088bb : 0x444444);
XSetForeground(dpy, gc, draftSel ? pt.spec.accentAlt : pt.spec.border);
XDrawRectangle(dpy, pix, gc, 130, 234, 103, 29);
drawPango(layoutMain, &colYellow, 146, 234, 30, "Draft", 84);
@@ -778,7 +767,7 @@ int runSmsApp(int argc, char** argv) {
}
} else if (mode == ViewMode::PickContact) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 34);
drawPango(layoutIcon, &colBlue, 8, 0, 34, kIconBook);
drawPango(layoutMain, &colWhite, 30, 0, 34, "Select Recipient", 200);
@@ -799,7 +788,7 @@ int runSmsApp(int argc, char** argv) {
const auto& c = pickerContacts[idx];
int ry = listY + i * rowH;
bool isSel = (idx == selectedPicker);
XSetForeground(dpy, gc, isSel ? 0x005577 : 0x222222);
XSetForeground(dpy, gc, isSel ? pt.spec.selBg : pt.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH - 1);
drawPango(layoutIcon, c.isRecent ? &colYellow : &colBlue, 6, ry + 1,
20, c.isRecent ? kIconClock : kIconUser);
@@ -811,7 +800,7 @@ int runSmsApp(int argc, char** argv) {
drawSoftkeyBar("Select", "Select", "Back");
} else if (mode == ViewMode::Options) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 34);
drawPango(layoutIcon, &colBlue, 8, 0, 34, kIconList);
drawPango(layoutMain, &colWhite, 30, 0, 34, "Message Options", 200);
@@ -821,7 +810,7 @@ int runSmsApp(int argc, char** argv) {
for (size_t i = 0; i < optionsList.size(); ++i) {
int ry = listY + static_cast<int>(i) * rowH;
bool isSel = (static_cast<int>(i) == selectedOption);
XSetForeground(dpy, gc, isSel ? 0x005577 : 0x222222);
XSetForeground(dpy, gc, isSel ? pt.spec.selBg : pt.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH - 1);
drawPango(layoutIcon, isSel ? &colYellow : &colBlue, 10, ry, rowH,
optionsList[i].icon);
@@ -831,7 +820,7 @@ int runSmsApp(int argc, char** argv) {
drawSoftkeyBar("Select", "Select", "Back");
} else if (mode == ViewMode::ConfirmDelete) {
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, pt.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 36);
drawPango(layoutIcon, &colRed, 8, 0, 36, kIconTrash);
drawPango(layoutMain, &colWhite, 30, 0, 36, "Delete Thread?", 200);
@@ -844,7 +833,10 @@ int runSmsApp(int argc, char** argv) {
for (int i = 0; i < 2; ++i) {
int ry = 164 + i * 40;
bool isSel = (confirmSelected == i);
XSetForeground(dpy, gc, isSel ? (i == 1 ? 0x922b21 : 0x005577) : 0x2a2a2a);
XSetForeground(
dpy, gc,
isSel ? (i == 1 ? pt.spec.dangerBg : pt.spec.selBg)
: pt.spec.bgButton);
XFillRectangle(dpy, pix, gc, 16, ry, kWinWidth - 32, 34);
drawPango(layoutMain, &colWhite, 28, ry, 34,
i == 0 ? "No, Keep Thread" : "Yes, Delete Thread", 184);
@@ -856,9 +848,9 @@ int runSmsApp(int argc, char** argv) {
{
std::lock_guard<std::mutex> lk(sendMutex);
if (!statusBanner.empty() && tNow < statusBannerUntilMs) {
XSetForeground(dpy, gc, 0x102535);
XSetForeground(dpy, gc, pt.spec.bgToast);
XFillRectangle(dpy, pix, gc, 8, kWinHeight - 58, kWinWidth - 16, 28);
XSetForeground(dpy, gc, 0x5dade2);
XSetForeground(dpy, gc, pt.spec.info);
XDrawRectangle(dpy, pix, gc, 8, kWinHeight - 58, kWinWidth - 17, 27);
drawPango(layoutSmall, &colWhite, 14, kWinHeight - 58, 28, statusBanner,
kWinWidth - 28);
@@ -1106,6 +1098,9 @@ int runSmsApp(int argc, char** argv) {
for (const auto& cmd : readFifoLines(fifoFd)) {
if (cmd == "NOP") {
continue;
} else if (cmd == "RELOAD_THEME") {
pt.reload();
if (visible) drawUI();
} else if (cmd == "CLOSE") {
hideWindow();
} else if (cmd == "OPEN") {
@@ -1416,7 +1411,10 @@ int runSmsApp(int argc, char** argv) {
if (pr > 0) {
if (fifoIdx >= 0 && (pfds[fifoIdx].revents & POLLIN)) {
for (const auto& cmd : readFifoLines(fifoFd)) {
if (cmd == "CLOSE") {
if (cmd == "RELOAD_THEME") {
pt.reload();
if (visible) drawUI();
} else if (cmd == "CLOSE") {
hideWindow();
} else if (cmd == "OPEN") {
showWindow("");
+636
View File
@@ -0,0 +1,636 @@
#ifndef DWM_PLUGINS_THEME_H
#define DWM_PLUGINS_THEME_H
#include <X11/Xatom.h>
#include <X11/Xft/Xft.h>
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#include <pango/pango.h>
#include <pango/pangoxft.h>
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <sstream>
#include <string>
#include <sys/stat.h>
#include <unistd.h>
#include <unordered_map>
namespace bananarchy {
inline std::string themeTrim(const std::string& s) {
size_t b = 0;
while (b < s.size() && std::isspace(static_cast<unsigned char>(s[b]))) {
++b;
}
size_t e = s.size();
while (e > b && std::isspace(static_cast<unsigned char>(s[e - 1]))) {
--e;
}
if (e >= b + 2 &&
((s[b] == '"' && s[e - 1] == '"') || (s[b] == '\'' && s[e - 1] == '\''))) {
return s.substr(b + 1, e - b - 2);
}
return s.substr(b, e - b);
}
inline int themeHexNibble(char c) {
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
return -1;
}
inline bool parseHexRgb(const std::string& raw, uint32_t* outRgb) {
std::string s = themeTrim(raw);
if (s.rfind("0x", 0) == 0 || s.rfind("0X", 0) == 0) {
s = "#" + s.substr(2);
}
if (s.size() == 7 && s[0] == '#') {
uint32_t v = 0;
for (int i = 1; i < 7; ++i) {
int n = themeHexNibble(s[i]);
if (n < 0) return false;
v = (v << 4) | static_cast<uint32_t>(n);
}
*outRgb = v;
return true;
}
if (s.size() == 4 && s[0] == '#') {
int r = themeHexNibble(s[1]);
int g = themeHexNibble(s[2]);
int b = themeHexNibble(s[3]);
if (r < 0 || g < 0 || b < 0) return false;
*outRgb = static_cast<uint32_t>(((r * 17) << 16) | ((g * 17) << 8) | (b * 17));
return true;
}
return false;
}
inline std::string formatHexRgb(uint32_t rgb) {
char buf[16];
std::snprintf(buf, sizeof(buf), "#%06x", static_cast<unsigned int>(rgb & 0xffffffu));
return buf;
}
inline uint32_t adjustRgb(uint32_t rgb, int delta) {
int r = std::clamp(static_cast<int>((rgb >> 16) & 0xff) + delta, 0, 255);
int g = std::clamp(static_cast<int>((rgb >> 8) & 0xff) + delta, 0, 255);
int b = std::clamp(static_cast<int>(rgb & 0xff) + delta, 0, 255);
return static_cast<uint32_t>((r << 16) | (g << 8) | b);
}
inline uint32_t blendRgb(uint32_t c1, uint32_t c2, int weight2Pct) {
int w2 = std::clamp(weight2Pct, 0, 100);
int w1 = 100 - w2;
int r = (((c1 >> 16) & 0xff) * w1 + ((c2 >> 16) & 0xff) * w2) / 100;
int g = (((c1 >> 8) & 0xff) * w1 + ((c2 >> 8) & 0xff) * w2) / 100;
int b = ((c1 & 0xff) * w1 + (c2 & 0xff) * w2) / 100;
return static_cast<uint32_t>((std::clamp(r, 0, 255) << 16) |
(std::clamp(g, 0, 255) << 8) |
std::clamp(b, 0, 255));
}
inline std::string getHomeDirPath() {
const char* h = std::getenv("HOME");
return (h && h[0]) ? h : "/home/user";
}
inline std::string getXresourcesPath() {
return getHomeDirPath() + "/.Xresources";
}
inline std::string getThemesDirPath() {
return getHomeDirPath() + "/.xthemes";
}
struct ThemeSpec {
std::string name = "Default";
std::string fontFace = "Fira Code";
std::string iconFontFace = "DejaVuSansM Nerd Font";
int baseFontSize = 15;
// Core colors (24-bit RGB)
uint32_t bgMain = 0x222222;
uint32_t bgBar = 0x323232;
uint32_t bgHeader = 0x1c1c1c;
uint32_t bgFooter = 0x181818;
uint32_t bgOverlay = 0x161616;
uint32_t bgAltEven = 0x282828;
uint32_t bgAltOdd = 0x2e2e2e;
uint32_t bgInput = 0x1a1a1a;
uint32_t bgInputFocus = 0x1b3b4b;
uint32_t bgButton = 0x2a2a2a;
uint32_t bgSearch = 0x383838;
uint32_t bgBubbleIn = 0x262d32;
uint32_t bgBubbleOut = 0x1f2d38;
uint32_t bgToast = 0x102535;
uint32_t fgMain = 0xdddddd;
uint32_t fgBright = 0xffffff;
uint32_t fgMuted = 0x999999;
uint32_t selBg = 0x005577;
uint32_t selFg = 0xffffff;
uint32_t accent = 0xf4d03f;
uint32_t accentAlt = 0x0088bb;
uint32_t highlight = 0xffc978;
uint32_t border = 0x444444;
uint32_t divider = 0x666666;
uint32_t success = 0x2ecc71;
uint32_t info = 0x5dade2;
uint32_t warning = 0xe67e22;
uint32_t danger = 0xe74c3c;
uint32_t dangerBg = 0x922b21;
int sizeSmall() const {
return std::max(8, static_cast<int>(std::lround(baseFontSize * 12.0 / 15.0)));
}
int sizeMain() const {
return std::clamp(baseFontSize, 10, 24);
}
int sizeIcon() const {
return std::max(10, static_cast<int>(std::lround(baseFontSize * 16.0 / 15.0)));
}
int sizeLarge() const {
return std::max(11, static_cast<int>(std::lround(baseFontSize * 18.0 / 15.0)));
}
std::string pangoMainFontStr() const {
return fontFace + ", " + iconFontFace + " " + std::to_string(sizeMain()) + "px";
}
std::string pangoSmallFontStr() const {
return fontFace + ", " + iconFontFace + " " + std::to_string(sizeSmall()) + "px";
}
std::string pangoIconFontStr() const {
return iconFontFace + ", " + fontFace + " " + std::to_string(sizeIcon()) + "px";
}
std::string pangoLargeBoldFontStr() const {
return fontFace + ", " + iconFontFace + " Bold " + std::to_string(sizeLarge()) + "px";
}
std::string xftFontStr(int pxSize) const {
return fontFace + ":pixelsize=" + std::to_string(pxSize) +
":style=Regular:antialias=true:autohint=true";
}
std::string xftIconFontStr(int pxSize) const {
return iconFontFace + ":pixelsize=" + std::to_string(pxSize) +
":style=Regular:antialias=true:autohint=true";
}
void recomputeDerivedFromCore() {
int luma = (((bgMain >> 16) & 0xff) * 299 +
((bgMain >> 8) & 0xff) * 587 +
(bgMain & 0xff) * 114) / 1000;
int dir = (luma > 140) ? -1 : 1;
bgBar = adjustRgb(bgMain, dir * 16);
bgHeader = adjustRgb(bgMain, -dir * 6);
bgFooter = adjustRgb(bgMain, -dir * 10);
bgOverlay = adjustRgb(bgMain, -dir * 12);
bgAltEven = adjustRgb(bgMain, dir * 6);
bgAltOdd = adjustRgb(bgMain, dir * 12);
bgInput = adjustRgb(bgMain, -dir * 8);
bgInputFocus = blendRgb(bgMain, selBg, 40);
bgButton = adjustRgb(bgMain, dir * 8);
bgSearch = adjustRgb(bgMain, dir * 22);
bgBubbleIn = blendRgb(bgMain, success, 14);
bgBubbleOut = blendRgb(bgMain, selBg, 26);
bgToast = blendRgb(bgOverlay, selBg, 35);
int fgLuma = (((fgMain >> 16) & 0xff) * 299 +
((fgMain >> 8) & 0xff) * 587 +
(fgMain & 0xff) * 114) / 1000;
fgBright = (fgLuma > 128) ? 0xffffff : 0x000000;
fgMuted = blendRgb(fgMain, bgMain, 45);
accentAlt = adjustRgb(selBg, 48);
highlight = blendRgb(accent, 0xffffff, 30);
border = adjustRgb(bgMain, dir * 34);
divider = adjustRgb(bgMain, dir * 68);
}
void parseFromMap(const std::unordered_map<std::string, std::string>& kv) {
auto getStr = [&](const char* k1, const char* k2 = nullptr,
const char* k3 = nullptr) -> std::string {
auto it = kv.find(k1);
if (it != kv.end() && !it->second.empty()) return it->second;
if (k2) {
it = kv.find(k2);
if (it != kv.end() && !it->second.empty()) return it->second;
}
if (k3) {
it = kv.find(k3);
if (it != kv.end() && !it->second.empty()) return it->second;
}
return "";
};
std::string nm = getStr("theme.name", "*themeName");
if (!nm.empty()) name = nm;
std::string ff = getStr("theme.fontFace", "*fontFace");
if (!ff.empty()) {
fontFace = ff;
} else {
std::string dwmFont = getStr("dwm.font");
if (!dwmFont.empty()) {
size_t comma = dwmFont.find(',');
if (comma != std::string::npos) {
fontFace = themeTrim(dwmFont.substr(0, comma));
}
}
}
std::string iff = getStr("theme.iconFontFace", "*iconFontFace");
if (!iff.empty()) iconFontFace = iff;
std::string bfs = getStr("theme.baseFontSize", "*baseFontSize");
if (!bfs.empty()) {
int sz = std::atoi(bfs.c_str());
if (sz >= 10 && sz <= 24) baseFontSize = sz;
} else {
std::string dwmFont = getStr("dwm.font");
size_t pxPos = dwmFont.rfind("px");
if (pxPos != std::string::npos && pxPos > 0) {
size_t sp = pxPos;
while (sp > 0 && std::isdigit(static_cast<unsigned char>(dwmFont[sp - 1]))) {
--sp;
}
if (sp < pxPos) {
int sz = std::atoi(dwmFont.substr(sp, pxPos - sp).c_str());
if (sz >= 10 && sz <= 24) baseFontSize = sz;
}
}
}
auto getCol = [&](uint32_t* dst, const char* k1, const char* k2 = nullptr,
const char* k3 = nullptr) -> bool {
std::string s = getStr(k1, k2, k3);
if (s.empty()) return false;
uint32_t v = 0;
if (parseHexRgb(s, &v)) {
*dst = v;
return true;
}
return false;
};
bool hasCoreBg = getCol(&bgMain, "theme.bgMain", "*background", "dmenu.background");
bool hasCoreFg = getCol(&fgMain, "theme.fgMain", "*foreground", "dwm.normfgcolor");
bool hasSelBg = getCol(&selBg, "theme.selBg", "dmenu.selbackground", "dwm.selbgcolor");
bool hasSelFg = getCol(&selFg, "theme.selFg", "dmenu.selforeground", "dwm.selfgcolor");
bool hasAccent = getCol(&accent, "theme.accent", "*accentColor", "st.cursorColor");
(void)hasCoreBg;
(void)hasCoreFg;
(void)hasSelBg;
(void)hasSelFg;
(void)hasAccent;
// Derive defaults from core colors first, then override with any explicit tokens
recomputeDerivedFromCore();
getCol(&bgBar, "theme.bgBar", "dwm.background", "dwm.normbgcolor");
getCol(&bgHeader, "theme.bgHeader", "dmenu.background", "st.background");
getCol(&bgFooter, "theme.bgFooter");
getCol(&bgOverlay, "theme.bgOverlay");
getCol(&bgAltEven, "theme.bgAltEven");
getCol(&bgAltOdd, "theme.bgAltOdd");
getCol(&bgInput, "theme.bgInput");
getCol(&bgInputFocus, "theme.bgInputFocus");
getCol(&bgButton, "theme.bgButton");
getCol(&bgSearch, "theme.bgSearch", "dmenu.outbackground");
getCol(&bgBubbleIn, "theme.bgBubbleIn");
getCol(&bgBubbleOut, "theme.bgBubbleOut");
getCol(&bgToast, "theme.bgToast");
getCol(&fgBright, "theme.fgBright", "dmenu.selforeground");
getCol(&fgMuted, "theme.fgMuted");
getCol(&accentAlt, "theme.accentAlt");
getCol(&highlight, "theme.highlight", "dmenu.highlight");
getCol(&border, "theme.border", "dwm.border", "dwm.normbordercolor");
getCol(&divider, "theme.divider");
getCol(&success, "theme.success");
getCol(&info, "theme.info");
getCol(&warning, "theme.warning");
getCol(&danger, "theme.danger");
getCol(&dangerBg, "theme.dangerBg");
}
static void parseLinesIntoMap(const std::string& content,
std::unordered_map<std::string, std::string>& kv) {
std::istringstream ss(content);
std::string line;
while (std::getline(ss, line)) {
std::string t = themeTrim(line);
if (t.empty() || t[0] == '!' || t[0] == '#') continue;
size_t colon = t.find(':');
if (colon == std::string::npos) continue;
std::string key = themeTrim(t.substr(0, colon));
std::string val = themeTrim(t.substr(colon + 1));
if (!key.empty() && !val.empty()) {
kv[key] = val;
}
}
}
bool loadFromFile(const std::string& path) {
std::ifstream in(path);
if (!in.is_open()) return false;
std::ostringstream ss;
ss << in.rdbuf();
std::unordered_map<std::string, std::string> kv;
parseLinesIntoMap(ss.str(), kv);
parseFromMap(kv);
return true;
}
void loadActive(Display* dpy, int screen) {
std::unordered_map<std::string, std::string> kv;
if (dpy) {
Atom actualType = None;
int actualFormat = 0;
unsigned long nitems = 0, bytesAfter = 0;
unsigned char* prop = nullptr;
if (XGetWindowProperty(dpy, RootWindow(dpy, screen), XA_RESOURCE_MANAGER,
0L, 65536L, False, XA_STRING, &actualType,
&actualFormat, &nitems, &bytesAfter,
&prop) == Success &&
prop) {
if (actualType == XA_STRING && actualFormat == 8 && nitems > 0) {
std::string resStr(reinterpret_cast<char*>(prop), nitems);
parseLinesIntoMap(resStr, kv);
}
XFree(prop);
}
}
// Also read ~/.Xresources so direct file edits always take effect
std::ifstream in(getXresourcesPath());
if (in.is_open()) {
std::ostringstream ss;
ss << in.rdbuf();
parseLinesIntoMap(ss.str(), kv);
}
if (!kv.empty()) {
parseFromMap(kv);
}
}
std::string serializeXresources() const {
std::ostringstream out;
out << "! Space to setup configversion\n";
out << "! configversion: 7bff124b2de16292fe6e7a7e5d3322ae\n";
out << "! Bananarchy Unified Theme: " << name << "\n\n";
out << "theme.name: " << name << "\n";
out << "theme.fontFace: " << fontFace << "\n";
out << "theme.iconFontFace: " << iconFontFace << "\n";
out << "theme.baseFontSize: " << sizeMain() << "\n\n";
out << "theme.bgMain: " << formatHexRgb(bgMain) << "\n";
out << "theme.bgBar: " << formatHexRgb(bgBar) << "\n";
out << "theme.bgHeader: " << formatHexRgb(bgHeader) << "\n";
out << "theme.bgFooter: " << formatHexRgb(bgFooter) << "\n";
out << "theme.bgOverlay: " << formatHexRgb(bgOverlay) << "\n";
out << "theme.bgAltEven: " << formatHexRgb(bgAltEven) << "\n";
out << "theme.bgAltOdd: " << formatHexRgb(bgAltOdd) << "\n";
out << "theme.bgInput: " << formatHexRgb(bgInput) << "\n";
out << "theme.bgInputFocus: " << formatHexRgb(bgInputFocus) << "\n";
out << "theme.bgButton: " << formatHexRgb(bgButton) << "\n";
out << "theme.bgSearch: " << formatHexRgb(bgSearch) << "\n";
out << "theme.bgBubbleIn: " << formatHexRgb(bgBubbleIn) << "\n";
out << "theme.bgBubbleOut: " << formatHexRgb(bgBubbleOut) << "\n";
out << "theme.bgToast: " << formatHexRgb(bgToast) << "\n\n";
out << "theme.fgMain: " << formatHexRgb(fgMain) << "\n";
out << "theme.fgBright: " << formatHexRgb(fgBright) << "\n";
out << "theme.fgMuted: " << formatHexRgb(fgMuted) << "\n\n";
out << "theme.selBg: " << formatHexRgb(selBg) << "\n";
out << "theme.selFg: " << formatHexRgb(selFg) << "\n";
out << "theme.accent: " << formatHexRgb(accent) << "\n";
out << "theme.accentAlt: " << formatHexRgb(accentAlt) << "\n";
out << "theme.highlight: " << formatHexRgb(highlight) << "\n";
out << "theme.border: " << formatHexRgb(border) << "\n";
out << "theme.divider: " << formatHexRgb(divider) << "\n\n";
out << "theme.success: " << formatHexRgb(success) << "\n";
out << "theme.info: " << formatHexRgb(info) << "\n";
out << "theme.warning: " << formatHexRgb(warning) << "\n";
out << "theme.danger: " << formatHexRgb(danger) << "\n";
out << "theme.dangerBg: " << formatHexRgb(dangerBg) << "\n\n";
out << "dmenu.font: " << xftFontStr(sizeLarge()) << "\n";
out << "dmenu.background: " << formatHexRgb(bgHeader) << "\n";
out << "dmenu.foreground: " << formatHexRgb(fgBright) << "\n";
out << "dmenu.selbackground: " << formatHexRgb(selBg) << "\n";
out << "dmenu.selforeground: " << formatHexRgb(selFg) << "\n";
out << "dmenu.outbackground: " << formatHexRgb(bgSearch) << "\n";
out << "dmenu.outforeground: " << formatHexRgb(fgBright) << "\n";
out << "dmenu.highlight: " << formatHexRgb(highlight) << "\n\n";
out << "dwm.font: " << pangoMainFontStr() << "\n";
out << "dwm.background: " << formatHexRgb(bgBar) << "\n";
out << "dwm.foreground: " << formatHexRgb(fgMain) << "\n";
out << "dwm.border: " << formatHexRgb(border) << "\n";
out << "dwm.selbackground: " << formatHexRgb(selBg) << "\n";
out << "dwm.selforeground: " << formatHexRgb(selFg) << "\n";
out << "dwm.selborder: " << formatHexRgb(selBg) << "\n";
out << "dwm.normbgcolor: " << formatHexRgb(bgBar) << "\n";
out << "dwm.normbordercolor: " << formatHexRgb(border) << "\n";
out << "dwm.normfgcolor: " << formatHexRgb(fgMain) << "\n";
out << "dwm.selbgcolor: " << formatHexRgb(selBg) << "\n";
out << "dwm.selbordercolor: " << formatHexRgb(selBg) << "\n";
out << "dwm.selfgcolor: " << formatHexRgb(selFg) << "\n\n";
out << "st.font: " << xftFontStr(sizeLarge()) << "\n";
out << "st.termname: xterm-256color\n";
out << "st.background: " << formatHexRgb(bgHeader) << "\n";
out << "st.foreground: " << formatHexRgb(fgMain) << "\n";
out << "st.cursorColor: " << formatHexRgb(accent) << "\n\n";
out << "svkbd.font: " << fontFace << ":pixelsize=" << sizeSmall() << "\n";
return out.str();
}
bool saveToFile(const std::string& path) const {
std::ofstream out(path, std::ios::trunc);
if (!out.is_open()) return false;
out << serializeXresources();
return true;
}
};
inline ThemeSpec loadThemeSpec(Display* dpy = nullptr, int screen = 0) {
ThemeSpec spec;
spec.loadActive(dpy, screen);
return spec;
}
struct PluginTheme {
ThemeSpec spec;
time_t lastXresMtime = -1;
off_t lastXresSize = -1;
bool colorsAllocated = false;
Display* dpy_ = nullptr;
int screen_ = 0;
Visual* visual_ = nullptr;
Colormap cmap_ = 0;
Window win_ = None;
PangoContext* pangoCtx = nullptr;
PangoLayout* layoutMain = nullptr;
PangoLayout* layoutSmall = nullptr;
PangoLayout* layoutIcon = nullptr;
PangoLayout* layoutNum = nullptr;
XftColor colWhite{};
XftColor colLight{};
XftColor colMuted{};
XftColor colYellow{};
XftColor colGreen{};
XftColor colBlue{};
XftColor colOrange{};
XftColor colRed{};
void allocXft(Display* dpy, Visual* visual, Colormap cmap, uint32_t rgb,
XftColor* dst) {
std::string hex = formatHexRgb(rgb);
XftColorAllocName(dpy, visual, cmap, hex.c_str(), dst);
}
void init(Display* dpy, int screen, Visual* visual, Colormap cmap,
Window win = None) {
dpy_ = dpy;
screen_ = screen;
visual_ = visual;
cmap_ = cmap;
win_ = win;
if (!pangoCtx && dpy) {
PangoFontMap* fontMap = pango_xft_get_font_map(dpy, screen);
pangoCtx = pango_font_map_create_context(fontMap);
layoutMain = pango_layout_new(pangoCtx);
layoutSmall = pango_layout_new(pangoCtx);
layoutIcon = pango_layout_new(pangoCtx);
layoutNum = pango_layout_new(pangoCtx);
}
reload();
}
void reload() {
if (dpy_ && visual_) {
load(dpy_, screen_, visual_, cmap_, layoutMain, layoutSmall, layoutIcon,
layoutNum, win_);
}
}
void load(Display* dpy, int screen, Visual* visual, Colormap cmap,
PangoLayout* lMain = nullptr,
PangoLayout* lSmall = nullptr,
PangoLayout* lIcon = nullptr,
PangoLayout* lNum = nullptr,
Window win = None) {
dpy_ = dpy;
screen_ = screen;
visual_ = visual;
cmap_ = cmap;
if (win != None) win_ = win;
if (lMain) layoutMain = lMain;
if (lSmall) layoutSmall = lSmall;
if (lIcon) layoutIcon = lIcon;
if (lNum) layoutNum = lNum;
struct stat st {};
if (::stat(getXresourcesPath().c_str(), &st) == 0) {
lastXresMtime = st.st_mtim.tv_sec;
lastXresSize = st.st_size;
}
spec = ThemeSpec{};
spec.loadActive(dpy, screen);
if (colorsAllocated) {
XftColorFree(dpy, visual, cmap, &colWhite);
XftColorFree(dpy, visual, cmap, &colLight);
XftColorFree(dpy, visual, cmap, &colMuted);
XftColorFree(dpy, visual, cmap, &colYellow);
XftColorFree(dpy, visual, cmap, &colGreen);
XftColorFree(dpy, visual, cmap, &colBlue);
XftColorFree(dpy, visual, cmap, &colOrange);
XftColorFree(dpy, visual, cmap, &colRed);
}
allocXft(dpy, visual, cmap, spec.fgBright, &colWhite);
allocXft(dpy, visual, cmap, spec.fgMain, &colLight);
allocXft(dpy, visual, cmap, spec.fgMuted, &colMuted);
allocXft(dpy, visual, cmap, spec.accent, &colYellow);
allocXft(dpy, visual, cmap, spec.success, &colGreen);
allocXft(dpy, visual, cmap, spec.info, &colBlue);
allocXft(dpy, visual, cmap, spec.warning, &colOrange);
allocXft(dpy, visual, cmap, spec.danger, &colRed);
colorsAllocated = true;
if (layoutMain) {
PangoFontDescription* d =
pango_font_description_from_string(spec.pangoMainFontStr().c_str());
pango_layout_set_font_description(layoutMain, d);
pango_font_description_free(d);
}
if (layoutSmall) {
PangoFontDescription* d =
pango_font_description_from_string(spec.pangoSmallFontStr().c_str());
pango_layout_set_font_description(layoutSmall, d);
pango_font_description_free(d);
}
if (layoutIcon) {
PangoFontDescription* d =
pango_font_description_from_string(spec.pangoIconFontStr().c_str());
pango_layout_set_font_description(layoutIcon, d);
pango_font_description_free(d);
}
if (layoutNum) {
PangoFontDescription* d = pango_font_description_from_string(
spec.pangoLargeBoldFontStr().c_str());
pango_layout_set_font_description(layoutNum, d);
pango_font_description_free(d);
}
if (win_ != None) {
XSetWindowBackground(dpy, win_, spec.bgMain);
XSetWindowBorder(dpy, win_, spec.selBg);
}
}
bool checkAndReload() {
if (!dpy_ || !visual_) return false;
return checkAndReload(dpy_, screen_, visual_, cmap_, layoutMain,
layoutSmall, layoutIcon, layoutNum, win_);
}
bool checkAndReload(Display* dpy, int screen, Visual* visual, Colormap cmap,
PangoLayout* lMain = nullptr,
PangoLayout* lSmall = nullptr,
PangoLayout* lIcon = nullptr,
PangoLayout* lNum = nullptr,
Window win = None) {
struct stat st {};
if (::stat(getXresourcesPath().c_str(), &st) == 0) {
if (st.st_mtim.tv_sec != lastXresMtime || st.st_size != lastXresSize) {
load(dpy, screen, visual, cmap, lMain, lSmall, lIcon, lNum, win);
return true;
}
}
return false;
}
};
} // namespace bananarchy
#endif // DWM_PLUGINS_THEME_H
File diff suppressed because it is too large Load Diff
+194
View File
@@ -107,6 +107,10 @@ static Clr *scheme[SchemeLast];
static char *colors[SchemeLast][2];
static const char *fonts[3] = { NULL, NULL, NULL };
static char xres_font_main[256] = "";
static char xres_font_icon[256] = "";
static time_t last_xres_mtime = 0;
static long last_xres_nsec = 0;
#include "config.h"
@@ -151,11 +155,14 @@ static const char *ICON_ZMI = "\xf3\xb0\x9b\xad";
static const char *ICON_ZMO = "\xf3\xb0\x9b\xac";
static const char *ICON_A2X = "\xe2\x87\x84";
static const char *ICON_KBD = "\xef\x84\x9c";
static const char *ICON_THM = "\xf3\xb0\x8f\x98";
static void drawmenu(void);
static void show_menu(void);
static void hide_menu(void);
static void open_builtin_menu(const char *menu_name, int keep_idx);
static void load_dmenu_xresources(void);
static void reload_dmenu_theme(void);
static char *
cistrstr(const char *s, const char *sub)
@@ -1711,6 +1718,9 @@ open_builtin_menu(const char *menu_name, int keep_idx)
snprintf(label, sizeof(label), "%s Camera", ICON_CAM);
add_menu_item(label, "@plugin:camera", 0);
snprintf(label, sizeof(label), "%s Themes", ICON_THM);
add_menu_item(label, "@plugin:themes", 0);
char bl_buf[32] = "";
if (read_first_line("/sys/class/leds/white:torch/brightness", bl_buf, sizeof(bl_buf)) ||
read_first_line("/sys/class/leds/white:flash/brightness", bl_buf, sizeof(bl_buf))) {
@@ -1742,6 +1752,8 @@ open_builtin_menu(const char *menu_name, int keep_idx)
} else if (strcmp(menu_name, "applications") == 0) {
reset_session_defaults(1, "Apps");
append_active_call_entries();
snprintf(label, sizeof(label), "%s Themes", ICON_THM);
add_menu_item(label, "@plugin:themes", 0);
load_cache_or_hook("sxmo_apps.cache", "sxmo_hook_apps.sh");
snprintf(label, sizeof(label), "%s System Menu", ICON_MNU);
add_menu_item(label, "@menu:sys", 1);
@@ -1776,6 +1788,8 @@ open_builtin_menu(const char *menu_name, int keep_idx)
home = "/home/user";
char pbuf[256];
snprintf(label, sizeof(label), "%s Themes", ICON_THM);
add_menu_item(label, "@plugin:themes", 0);
snprintf(label, sizeof(label), "%s Brightness", ICON_ARU);
add_menu_item(label, "@toggle:bright_up", 1);
snprintf(label, sizeof(label), "%s Brightness", ICON_ARD);
@@ -1942,6 +1956,7 @@ close_other_active_plugins(void)
{ "xsms.pid", "/tmp/dwm_plugin_sms.fifo" },
{ "xfiles.pid", "/tmp/dwm_plugin_files.fifo" },
{ "xcamera.pid", "/tmp/dwm_plugin_camera.fifo" },
{ "xthemes.pid", "/tmp/dwm_plugin_themes.fifo" },
};
const char *rdir = getenv("XDG_RUNTIME_DIR");
const char *base = (rdir && rdir[0]) ? rdir : "/run/user/10000";
@@ -1960,12 +1975,185 @@ close_other_active_plugins(void)
}
}
static const char *
dmenu_xrm_lookup(XrmDatabase xdb, const char *k1, const char *k2, const char *k3)
{
char *type = NULL;
XrmValue xval;
if (k1 && XrmGetResource(xdb, k1, "*", &type, &xval) && xval.addr && xval.addr[0])
return xval.addr;
if (k2 && XrmGetResource(xdb, k2, "*", &type, &xval) && xval.addr && xval.addr[0])
return xval.addr;
if (k3 && XrmGetResource(xdb, k3, "*", &type, &xval) && xval.addr && xval.addr[0])
return xval.addr;
return NULL;
}
static void
dmenu_set_color(int scm, int col, const char *val)
{
if (!val || !val[0])
return;
free(colors[scm][col]);
colors[scm][col] = strdup(val);
}
static void
load_dmenu_xresources(void)
{
XrmInitialize();
const char *home = getenv("HOME");
char path[512];
snprintf(path, sizeof(path), "%s/.Xresources", (home && home[0]) ? home : "/home/user");
struct stat st;
if (stat(path, &st) == 0) {
last_xres_mtime = st.st_mtim.tv_sec;
last_xres_nsec = st.st_mtim.tv_nsec;
}
XrmDatabase xdb = XrmGetFileDatabase(path);
Atom actual_type = None;
int actual_format = 0;
unsigned long nitems = 0, bytes_after = 0;
unsigned char *prop = NULL;
if (!xdb && XGetWindowProperty(dpy, root, XA_RESOURCE_MANAGER, 0L, 65536L, False,
XA_STRING, &actual_type, &actual_format,
&nitems, &bytes_after, &prop) == Success && prop) {
if (actual_type == XA_STRING && actual_format == 8 && nitems > 0)
xdb = XrmGetStringDatabase((const char *)prop);
XFree(prop);
}
if (!xdb) {
char *xrm = XResourceManagerString(dpy);
if (xrm)
xdb = XrmGetStringDatabase(xrm);
}
if (xdb) {
const char *ff = dmenu_xrm_lookup(xdb, "theme.fontFace", NULL, NULL);
const char *icf = dmenu_xrm_lookup(xdb, "theme.iconFontFace", NULL, NULL);
const char *bsz = dmenu_xrm_lookup(xdb, "theme.baseFontSize", NULL, NULL);
const char *dmf = dmenu_xrm_lookup(xdb, "dmenu.font", NULL, NULL);
if (ff || bsz) {
int base_sz = bsz ? atoi(bsz) : 15;
if (base_sz < 8 || base_sz > 32)
base_sz = 15;
int large_sz = (base_sz * 18 + 7) / 15;
snprintf(xres_font_main, sizeof(xres_font_main),
"%s:pixelsize=%d:style=Regular:antialias=true:autohint=true",
ff ? ff : "Fira Code", large_sz);
snprintf(xres_font_icon, sizeof(xres_font_icon),
"%s:pixelsize=%d:style=Regular:antialias=true:autohint=true",
icf ? icf : "DejaVuSansM Nerd Font", large_sz);
fonts[0] = xres_font_main;
fonts[1] = xres_font_icon;
} else if (dmf) {
snprintf(xres_font_main, sizeof(xres_font_main), "%s", dmf);
fonts[0] = xres_font_main;
fonts[1] = defaultfonts[1];
}
dmenu_set_color(SchemeNorm, ColBg,
dmenu_xrm_lookup(xdb, "theme.bgHeader", "theme.bgMain", "dmenu.background"));
dmenu_set_color(SchemeNorm, ColFg,
dmenu_xrm_lookup(xdb, "theme.fgBright", "theme.fgMain", "dmenu.foreground"));
dmenu_set_color(SchemeSel, ColBg,
dmenu_xrm_lookup(xdb, "theme.selBg", "dmenu.selbackground", NULL));
dmenu_set_color(SchemeSel, ColFg,
dmenu_xrm_lookup(xdb, "theme.selFg", "dmenu.selforeground", NULL));
dmenu_set_color(SchemeOut, ColBg,
dmenu_xrm_lookup(xdb, "theme.bgSearch", "dmenu.outbackground", "theme.bgInputFocus"));
dmenu_set_color(SchemeOut, ColFg,
dmenu_xrm_lookup(xdb, "theme.fgBright", "dmenu.outforeground", "theme.fgMain"));
dmenu_set_color(SchemeNormHighlight, ColBg,
dmenu_xrm_lookup(xdb, "theme.bgHeader", "theme.bgMain", "dmenu.background"));
dmenu_set_color(SchemeNormHighlight, ColFg,
dmenu_xrm_lookup(xdb, "theme.highlight", "theme.accent", "dmenu.normhlforeground"));
dmenu_set_color(SchemeSelHighlight, ColBg,
dmenu_xrm_lookup(xdb, "theme.selBg", "dmenu.selbackground", NULL));
dmenu_set_color(SchemeSelHighlight, ColFg,
dmenu_xrm_lookup(xdb, "theme.highlight", "theme.accent", "dmenu.selhlforeground"));
XrmDestroyDatabase(xdb);
}
}
static void
reload_dmenu_theme(void)
{
int i;
load_dmenu_xresources();
for (i = 0; i < SchemeLast; ++i) {
if (!colors[i][ColBg])
colors[i][ColBg] = strdup(defaultcolors[i][ColBg]);
if (!colors[i][ColFg])
colors[i][ColFg] = strdup(defaultcolors[i][ColFg]);
}
if (drw->fonts) {
drw_fontset_free(drw->fonts);
drw->fonts = NULL;
}
if (!fonts[0]) {
fonts[0] = defaultfonts[0];
fonts[1] = defaultfonts[1];
}
if (!drw_fontset_create(drw, fonts, 2))
drw_fontset_create(drw, defaultfonts, 2);
lrpad = drw->fonts->h / 2;
bh = drw->fonts->h + 2;
bh = MAX(bh, (int)lineheight);
default_lines = MAX(1, (avail_h_cached / (int)bh) - 1);
for (i = 0; i < SchemeLast; i++) {
free(scheme[i]);
scheme[i] = drw_scm_create(drw, (const char **)colors[i], 2);
}
for (i = 0; i < SchemeLast; ++i) {
free(colors[i][ColFg]);
free(colors[i][ColBg]);
colors[i][ColFg] = NULL;
colors[i][ColBg] = NULL;
}
if (win) {
XSetWindowBackground(dpy, win, scheme[SchemeNorm][ColBg].pixel);
XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel);
}
if (menu_active)
drawmenu();
}
static void
check_dmenu_xres_changed(void)
{
const char *home = getenv("HOME");
char path[512];
snprintf(path, sizeof(path), "%s/.Xresources", (home && home[0]) ? home : "/home/user");
struct stat st;
if (stat(path, &st) == 0) {
if (st.st_mtim.tv_sec != last_xres_mtime || st.st_mtim.tv_nsec != last_xres_nsec)
reload_dmenu_theme();
}
}
static void
show_menu(void)
{
const int bar_h = 24;
int target_y;
check_dmenu_xres_changed();
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
if (lines > 0) {
lines = default_lines;
@@ -2242,6 +2430,8 @@ handle_fifo_commands(int fifo_fd)
if (strcmp(line, "CLOSE") == 0) {
if (menu_active)
cancel_session();
} else if (strcmp(line, "RELOAD_THEME") == 0) {
reload_dmenu_theme();
} else if (strcmp(line, "OPEN") == 0) {
if (active_client_fd >= 0)
finish_client_session(1, NULL);
@@ -2469,6 +2659,8 @@ setup(int map_immediately)
for (j = 0; j < SchemeLast; ++j) {
free(colors[j][ColFg]);
free(colors[j][ColBg]);
colors[j][ColFg] = NULL;
colors[j][ColBg] = NULL;
}
clip = XInternAtom(dpy, "CLIPBOARD", False);
@@ -2789,6 +2981,8 @@ dmenu_run_main(int argc, char *argv[])
die("could not get embedding window attributes: 0x%lx", parentwin);
drw = drw_create(dpy, screen, root, wa.width, wa.height);
load_dmenu_xresources();
if (!fonts[0]) {
fonts[0] = defaultfonts[0];
fonts[1] = defaultfonts[1];
+153 -35
View File
@@ -272,7 +272,8 @@ static void clienttagpush(const Arg *arg);
static void shiftview(const Arg *arg);
static void pushup(const Arg *arg);
static void pushdown(const Arg *arg);
static void readxresources();
static void readxresources(void);
static void reload_dwm_theme(void);
static void load_plugins(void);
static void unload_plugins(void);
@@ -320,6 +321,7 @@ static Window root, wmcheckwin;
/* Empty arrays to be filled from command line, Xresources, and defaults, in decreasing order of precedence */
static char *colors[4][3]; /* 4 schemes, 3 colors each */
static char active_font[256];
static xcb_connection_t *xcon;
@@ -2258,6 +2260,8 @@ propertynotify(XEvent *e)
if (ev->window == root) {
if (ev->atom == XA_WM_NAME)
updatestatus();
else if (ev->atom == XA_RESOURCE_MANAGER)
reload_dwm_theme();
else
drawbars();
} else if (ev->state == PropertyDelete)
@@ -2657,6 +2661,7 @@ setup(void)
root = RootWindow(dpy, screen);
drw = drw_create(dpy, screen, root, sw, sh);
snprintf(active_font, sizeof(active_font), "%s", font);
readxresources();
/* Apply defaults to font and colors*/
for (i = 0; i <= SchemeTabInactive; ++i){
@@ -2666,7 +2671,7 @@ setup(void)
}
}
if (!drw_font_create(drw, font))
if (!drw_font_create(drw, active_font))
die("no fonts could be loaded.");
lrpad = 6;
bh = MAX(drw->font->h + 4, 24);
@@ -2697,6 +2702,10 @@ setup(void)
for (j = 0; j <= SchemeTabInactive; ++j) {
free(colors[j][ColFg]);
free(colors[j][ColBg]);
free(colors[j][ColBorder]);
colors[j][ColFg] = NULL;
colors[j][ColBg] = NULL;
colors[j][ColBorder] = NULL;
}
/* init bars */
updatebars();
@@ -3429,46 +3438,155 @@ zoom(const Arg *arg)
}
static void
set_color_slot(int scm, int col, const char *val)
{
if (!val || !val[0])
return;
free(colors[scm][col]);
colors[scm][col] = strdup(val);
}
static const char *
xrm_lookup_any(XrmDatabase xdb, const char *k1, const char *k2, const char *k3)
{
char *type = NULL;
XrmValue xval;
if (k1 && XrmGetResource(xdb, k1, "*", &type, &xval) && xval.addr && xval.addr[0])
return xval.addr;
if (k2 && XrmGetResource(xdb, k2, "*", &type, &xval) && xval.addr && xval.addr[0])
return xval.addr;
if (k3 && XrmGetResource(xdb, k3, "*", &type, &xval) && xval.addr && xval.addr[0])
return xval.addr;
return NULL;
}
void
readxresources() {
XrmInitialize();
readxresources(void)
{
XrmInitialize();
char* xrm;
if ((xrm = XResourceManagerString(drw->dpy))) {
char *type;
XrmDatabase xdb = XrmGetStringDatabase(xrm);
XrmValue xval;
XrmDatabase xdb = NULL;
Atom actual_type = None;
int actual_format = 0;
unsigned long nitems = 0, bytes_after = 0;
unsigned char *prop = NULL;
if (XrmGetResource(xdb, "dwm.background", "*", &type, &xval) && !colors[SchemeNorm][ColBg] )
colors[SchemeNorm][ColBg] = strdup(xval.addr);
if (XrmGetResource(xdb, "dwm.foreground", "*", &type, &xval) && !colors[SchemeNorm][ColFg] )
colors[SchemeNorm][ColFg] = strdup(xval.addr);
if (XrmGetResource(xdb, "dwm.border", "*", &type, &xval) && !colors[SchemeNorm][ColBorder] )
colors[SchemeNorm][ColBorder] = strdup(xval.addr);
const char *home = getenv("HOME");
char path[512];
snprintf(path, sizeof(path), "%s/.Xresources", (home && home[0]) ? home : "/home/user");
xdb = XrmGetFileDatabase(path);
if (XrmGetResource(xdb, "dwm.selbackground", "*", &type, &xval) && !colors[SchemeSel][ColBg] )
colors[SchemeSel][ColBg] = strdup(xval.addr);
if (XrmGetResource(xdb, "dwm.selforeground", "*", &type, &xval) && !colors[SchemeSel][ColFg] )
colors[SchemeSel][ColFg] = strdup(xval.addr);
if (XrmGetResource(xdb, "dwm.selborder", "*", &type, &xval) && !colors[SchemeSel][ColBorder] )
colors[SchemeSel][ColBorder] = strdup(xval.addr);
if (!xdb && XGetWindowProperty(dpy, root, XA_RESOURCE_MANAGER, 0L, 65536L, False,
XA_STRING, &actual_type, &actual_format,
&nitems, &bytes_after, &prop) == Success && prop) {
if (actual_type == XA_STRING && actual_format == 8 && nitems > 0)
xdb = XrmGetStringDatabase((const char *)prop);
XFree(prop);
}
if (!xdb) {
char *xrm = XResourceManagerString(drw->dpy);
if (xrm)
xdb = XrmGetStringDatabase(xrm);
}
if (XrmGetResource(xdb, "dwm.tabactivebackground", "*", &type, &xval) && !colors[SchemeTabActive][ColBg] )
colors[SchemeTabActive][ColBg] = strdup(xval.addr);
if (XrmGetResource(xdb, "dwm.tabactiveforeground", "*", &type, &xval) && !colors[SchemeTabActive][ColFg] )
colors[SchemeTabActive][ColFg] = strdup(xval.addr);
if (XrmGetResource(xdb, "dwm.tabactiveborder", "*", &type, &xval) && !colors[SchemeTabActive][ColBorder] )
colors[SchemeTabActive][ColBorder] = strdup(xval.addr);
if (xdb) {
const char *ff = xrm_lookup_any(xdb, "theme.fontFace", NULL, NULL);
const char *icf = xrm_lookup_any(xdb, "theme.iconFontFace", NULL, NULL);
const char *bsz = xrm_lookup_any(xdb, "theme.baseFontSize", NULL, NULL);
const char *dwmf = xrm_lookup_any(xdb, "dwm.font", NULL, NULL);
if (XrmGetResource(xdb, "dwm.tabinactivebackground", "*", &type, &xval) && !colors[SchemeTabInactive][ColBg] )
colors[SchemeTabInactive][ColBg] = strdup(xval.addr);
if (XrmGetResource(xdb, "dwm.tabinactiveforeground", "*", &type, &xval) && !colors[SchemeTabInactive][ColFg] )
colors[SchemeTabInactive][ColFg] = strdup(xval.addr);
if (XrmGetResource(xdb, "dwm.tabinactiveborder", "*", &type, &xval) && !colors[SchemeTabInactive][ColBorder] )
colors[SchemeTabInactive][ColBorder] = strdup(xval.addr);
if (ff || bsz) {
int sz = bsz ? atoi(bsz) : 15;
if (sz < 8 || sz > 32)
sz = 15;
snprintf(active_font, sizeof(active_font), "%s, %s %dpx",
ff ? ff : "Fira Code",
icf ? icf : "DejaVuSansM Nerd Font",
sz);
} else if (dwmf) {
snprintf(active_font, sizeof(active_font), "%s", dwmf);
} else {
snprintf(active_font, sizeof(active_font), "%s", font);
}
XrmDestroyDatabase(xdb);
}
set_color_slot(SchemeNorm, ColBg,
xrm_lookup_any(xdb, "theme.bgBar", "dwm.background", "dwm.normbgcolor"));
set_color_slot(SchemeNorm, ColFg,
xrm_lookup_any(xdb, "theme.fgMain", "dwm.foreground", "dwm.normfgcolor"));
set_color_slot(SchemeNorm, ColBorder,
xrm_lookup_any(xdb, "theme.border", "dwm.border", "dwm.normbordercolor"));
set_color_slot(SchemeSel, ColBg,
xrm_lookup_any(xdb, "theme.selBg", "dwm.selbackground", "dwm.selbgcolor"));
set_color_slot(SchemeSel, ColFg,
xrm_lookup_any(xdb, "theme.selFg", "dwm.selforeground", "dwm.selfgcolor"));
set_color_slot(SchemeSel, ColBorder,
xrm_lookup_any(xdb, "theme.accent", "dwm.selborder", "dwm.selbordercolor"));
set_color_slot(SchemeTabActive, ColBg,
xrm_lookup_any(xdb, "theme.selBg", "dwm.tabactivebackground", "dwm.selbgcolor"));
set_color_slot(SchemeTabActive, ColFg,
xrm_lookup_any(xdb, "theme.selFg", "dwm.tabactiveforeground", "dwm.selfgcolor"));
set_color_slot(SchemeTabActive, ColBorder,
xrm_lookup_any(xdb, "theme.accent", "dwm.tabactiveborder", "dwm.selbordercolor"));
set_color_slot(SchemeTabInactive, ColBg,
xrm_lookup_any(xdb, "theme.bgBar", "dwm.tabinactivebackground", "dwm.normbgcolor"));
set_color_slot(SchemeTabInactive, ColFg,
xrm_lookup_any(xdb, "theme.fgMain", "dwm.tabinactiveforeground", "dwm.normfgcolor"));
set_color_slot(SchemeTabInactive, ColBorder,
xrm_lookup_any(xdb, "theme.border", "dwm.tabinactiveborder", "dwm.normbordercolor"));
XrmDestroyDatabase(xdb);
}
}
static void
reload_dwm_theme(void)
{
int i, j;
Monitor *m;
Client *c;
readxresources();
for (i = 0; i <= SchemeTabInactive; ++i) {
for (j = 0; j <= ColBorder; ++j) {
if (!colors[i][j])
colors[i][j] = strdup(defaultcolors[i][j]);
}
}
if (drw->font) {
drw_font_free(drw->font);
drw->font = NULL;
}
if (!drw_font_create(drw, active_font))
drw_font_create(drw, font);
for (i = 0; i < LENGTH(colors); i++) {
free(scheme[i]);
scheme[i] = drw_scm_create(drw, (const char **)colors[i], 3);
}
for (j = 0; j <= SchemeTabInactive; ++j) {
free(colors[j][ColFg]);
free(colors[j][ColBg]);
free(colors[j][ColBorder]);
colors[j][ColFg] = NULL;
colors[j][ColBg] = NULL;
colors[j][ColBorder] = NULL;
}
for (m = mons; m; m = m->next) {
for (c = m->clients; c; c = c->next) {
if (c == m->sel)
XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
else
XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
}
}
drawbars();
}
int
+7 -5
View File
@@ -118,7 +118,9 @@ static const char *colorname[] = {
[255] = 0,
/* more colors can be added after 255 to use with DefaultXX */
"#cccccc",
"#161616",
"#dddddd",
"#f4d03f",
"#555555",
};
@@ -127,10 +129,10 @@ static const char *colorname[] = {
* Default colors (colorname index)
* foreground, background, cursor, reverse cursor
*/
unsigned int defaultfg = 7;
unsigned int defaultbg = 0;
static unsigned int defaultcs = 256;
static unsigned int defaultrcs = 257;
unsigned int defaultfg = 257;
unsigned int defaultbg = 256;
static unsigned int defaultcs = 258;
static unsigned int defaultrcs = 259;
/*
* Default shape of cursor
+7 -5
View File
@@ -118,7 +118,9 @@ static const char *colorname[] = {
[255] = 0,
/* more colors can be added after 255 to use with DefaultXX */
"#cccccc",
"#161616",
"#dddddd",
"#f4d03f",
"#555555",
};
@@ -127,10 +129,10 @@ static const char *colorname[] = {
* Default colors (colorname index)
* foreground, background, cursor, reverse cursor
*/
unsigned int defaultfg = 7;
unsigned int defaultbg = 0;
static unsigned int defaultcs = 256;
static unsigned int defaultrcs = 257;
unsigned int defaultfg = 257;
unsigned int defaultbg = 256;
static unsigned int defaultcs = 258;
static unsigned int defaultrcs = 259;
/*
* Default shape of cursor
+84 -5
View File
@@ -1942,6 +1942,21 @@ resize(XEvent *e)
cresize(e->xconfigure.width, e->xconfigure.height);
}
static volatile sig_atomic_t st_reload_requested = 0;
static char st_theme_font[256] = "";
static char st_theme_bg[32] = "";
static char st_theme_fg[32] = "";
static char st_theme_cs[32] = "";
static void
st_sigusr1(int unused)
{
(void)unused;
st_reload_requested = 1;
}
void config_init(void);
void
run(void)
{
@@ -1970,8 +1985,19 @@ run(void)
ttyfd = ttynew(opt_line, shell, opt_io, opt_cmd);
cresize(w, h);
signal(SIGUSR1, st_sigusr1);
for (timeout = -1, drawing = 0, lastblink = (struct timespec){0};;) {
if (st_reload_requested) {
st_reload_requested = 0;
config_init();
xloadcols();
xunloadfonts();
xloadfonts(opt_font ? opt_font : font, 0);
cresize(win.w, win.h);
redraw();
XFlush(xw.dpy);
}
FD_ZERO(&rfd);
FD_SET(ttyfd, &rfd);
FD_SET(xfd, &rfd);
@@ -2084,18 +2110,71 @@ resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
void
config_init(void)
{
char *resm;
XrmDatabase db;
XrmDatabase db = NULL;
ResourcePref *p;
Atom actual_type = None;
int actual_format = 0;
unsigned long nitems = 0, bytes_after = 0;
unsigned char *prop = NULL;
char *type = NULL;
XrmValue ret;
XrmInitialize();
resm = XResourceManagerString(xw.dpy);
if (!resm)
{
const char *home = getenv("HOME");
char path[512];
snprintf(path, sizeof(path), "%s/.Xresources", (home && home[0]) ? home : "/home/user");
db = XrmGetFileDatabase(path);
}
if (!db && XGetWindowProperty(xw.dpy, DefaultRootWindow(xw.dpy), XA_RESOURCE_MANAGER,
0L, 65536L, False, XA_STRING, &actual_type,
&actual_format, &nitems, &bytes_after, &prop) == Success && prop) {
if (actual_type == XA_STRING && actual_format == 8 && nitems > 0)
db = XrmGetStringDatabase((const char *)prop);
XFree(prop);
}
if (!db) {
char *resm = XResourceManagerString(xw.dpy);
if (resm)
db = XrmGetStringDatabase(resm);
}
if (!db)
return;
db = XrmGetStringDatabase(resm);
for (p = resources; p < resources + LEN(resources); p++)
resource_load(db, p->name, p->type, p->dst);
/* Also honor unified theme.* keys */
const char *ff = NULL, *bsz = NULL;
if (XrmGetResource(db, "theme.fontFace", "*", &type, &ret) && ret.addr && ret.addr[0])
ff = ret.addr;
if (XrmGetResource(db, "theme.baseFontSize", "*", &type, &ret) && ret.addr && ret.addr[0])
bsz = ret.addr;
if (ff || bsz) {
int base_sz = bsz ? atoi(bsz) : 15;
if (base_sz < 8 || base_sz > 32)
base_sz = 15;
int large_sz = (base_sz * 18 + 7) / 15;
snprintf(st_theme_font, sizeof(st_theme_font),
"%s:pixelsize=%d:style=Regular:antialias=true:autohint=true",
ff ? ff : "Fira Code", large_sz);
font = st_theme_font;
}
if (XrmGetResource(db, "theme.bgHeader", "*", &type, &ret) && ret.addr && ret.addr[0]) {
snprintf(st_theme_bg, sizeof(st_theme_bg), "%s", ret.addr);
colorname[256] = st_theme_bg;
} else if (XrmGetResource(db, "theme.bgMain", "*", &type, &ret) && ret.addr && ret.addr[0]) {
snprintf(st_theme_bg, sizeof(st_theme_bg), "%s", ret.addr);
colorname[256] = st_theme_bg;
}
if (XrmGetResource(db, "theme.fgMain", "*", &type, &ret) && ret.addr && ret.addr[0]) {
snprintf(st_theme_fg, sizeof(st_theme_fg), "%s", ret.addr);
colorname[257] = st_theme_fg;
}
if (XrmGetResource(db, "theme.accent", "*", &type, &ret) && ret.addr && ret.addr[0]) {
snprintf(st_theme_cs, sizeof(st_theme_cs), "%s", ret.addr);
colorname[258] = st_theme_cs;
}
}
void
+23 -32
View File
@@ -15,6 +15,7 @@
#include <pango/pangoxft.h>
#include "../sxmo-dwm/dwm_plugin.h"
#include "../dwm-plugins/theme.h"
#include <algorithm>
#include <cmath>
@@ -532,31 +533,17 @@ static int xdrawer_run_main(int argc, char** argv) {
PangoFontMap* fontMap = pango_xft_get_font_map(dpy, screen);
PangoContext* pangoCtx = pango_font_map_create_context(fontMap);
PangoLayout* layoutMain = pango_layout_new(pangoCtx);
PangoFontDescription* descMain =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 15px");
pango_layout_set_font_description(layoutMain, descMain);
PangoLayout* layoutIcon = pango_layout_new(pangoCtx);
PangoFontDescription* descIcon =
pango_font_description_from_string("DejaVuSansM Nerd Font, Fira Code 16px");
pango_layout_set_font_description(layoutIcon, descIcon);
PangoLayout* layoutSmall = pango_layout_new(pangoCtx);
PangoFontDescription* descSmall =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 12px");
pango_layout_set_font_description(layoutSmall, descSmall);
auto allocColor = [&](const char* hex) {
XftColor col{};
XftColorAllocName(dpy, visual, cmap, hex, &col);
return col;
};
XftColor colWhite = allocColor("#ffffff");
XftColor colLight = allocColor("#dddddd");
XftColor colMuted = allocColor("#aaaaaa");
XftColor colYellow = allocColor("#f4d03f");
XftColor colGreen = allocColor("#2ecc71");
bananarchy::PluginTheme theme;
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
nullptr, win);
XftColor& colWhite = theme.colWhite;
XftColor& colLight = theme.colLight;
XftColor& colMuted = theme.colMuted;
XftColor& colYellow = theme.colYellow;
XftColor& colGreen = theme.colGreen;
PhoneController controller;
size_t selected = 0;
@@ -591,7 +578,7 @@ static int xdrawer_run_main(int argc, char** argv) {
};
auto render = [&]() {
XSetForeground(dpy, gc, 0x222222);
XSetForeground(dpy, gc, theme.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
const auto& items = controller.items();
@@ -601,11 +588,11 @@ static int xdrawer_run_main(int argc, char** argv) {
int rowH = nextRy - ry;
bool isSel = (i == selected);
XSetForeground(dpy, gc, isSel ? 0x005577 : ((i % 2 == 0) ? 0x282828 : 0x2e2e2e));
XSetForeground(dpy, gc, isSel ? theme.spec.selBg : ((i % 2 == 0) ? theme.spec.bgAltEven : theme.spec.bgAltOdd));
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH);
if (isSel) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 0, ry, 4, rowH);
}
@@ -635,19 +622,19 @@ static int xdrawer_run_main(int argc, char** argv) {
int barH = 12;
int barY = ry + (rowH - barH) / 2;
XSetForeground(dpy, gc, 0x161616);
XSetForeground(dpy, gc, theme.spec.bgOverlay);
XFillRectangle(dpy, pix, gc, barX, barY, barW, barH);
XSetForeground(dpy, gc, isSel ? 0xdddddd : 0x555555);
XSetForeground(dpy, gc, isSel ? theme.spec.fgMain : theme.spec.border);
XDrawRectangle(dpy, pix, gc, barX, barY, barW - 1, barH - 1);
int fillW = ((barW - 2) * pct) / 100;
if (fillW > 0) {
XSetForeground(dpy, gc, isSel ? 0xf4d03f : 0x3498db);
XSetForeground(dpy, gc, isSel ? theme.spec.accent : theme.spec.info);
XFillRectangle(dpy, pix, gc, barX + 1, barY + 1, fillW, barH - 2);
}
int knobX = barX + std::clamp(fillW - 2, 0, barW - 5);
XSetForeground(dpy, gc, 0xffffff);
XSetForeground(dpy, gc, theme.spec.fgBright);
XFillRectangle(dpy, pix, gc, knobX, barY - 2, 5, barH + 4);
char pctBuf[16];
@@ -727,6 +714,9 @@ static int xdrawer_run_main(int argc, char** argv) {
closeOtherPlugin("xsms.pid", "/tmp/dwm_plugin_sms.fifo");
closeOtherPlugin("xfiles.pid", "/tmp/dwm_plugin_files.fifo");
closeOtherPlugin("xcamera.pid", "/tmp/dwm_plugin_camera.fifo");
closeOtherPlugin("xthemes.pid", "/tmp/dwm_plugin_themes.fifo");
theme.checkAndReload(dpy, screen, visual, cmap, layoutMain, layoutSmall,
layoutIcon, nullptr, win);
openStartMs = nowMs();
startupIgnoreUntilMs = openStartMs + 180;
initialKeysReleased = (querySoftkeysDown(dpy) == 0);
@@ -802,6 +792,10 @@ static int xdrawer_run_main(int argc, char** argv) {
showWindow();
} else if (cmd == "CLOSE") {
hideWindow(false);
} else if (cmd == "RELOAD_THEME") {
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall,
layoutIcon, nullptr, win);
render();
}
}
}
@@ -928,9 +922,6 @@ static int xdrawer_run_main(int argc, char** argv) {
::unlink(fifoPath.c_str());
::unlink(daemonPidPath.c_str());
pango_font_description_free(descSmall);
pango_font_description_free(descIcon);
pango_font_description_free(descMain);
g_object_unref(layoutSmall);
g_object_unref(layoutIcon);
g_object_unref(layoutMain);