Add unified Xresources theme engine, Default.xth export, and xthemes manager plugin
This commit is contained in:
@@ -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]`).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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.
@@ -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
|
||||
|
||||
Symlink
+1
@@ -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.
Executable
BIN
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
@@ -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.
BIN
Binary file not shown.
Binary file not shown.
@@ -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/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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("");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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("");
|
||||
|
||||
@@ -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]) {
|
||||
|
||||
@@ -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("");
|
||||
|
||||
@@ -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(÷r, "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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user