summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/dmenu/dmenu.c128
-rwxr-xr-xtools/power-menu.sh17
-rwxr-xr-xtools/steam-dmenu.sh9
-rwxr-xr-xtools/universal_launcher.sh17
-rw-r--r--tools/universal_launcher.txt5
5 files changed, 120 insertions, 56 deletions
diff --git a/core/dmenu/dmenu.c b/core/dmenu/dmenu.c
index 54a14e2..28a0658 100644
--- a/core/dmenu/dmenu.c
+++ b/core/dmenu/dmenu.c
@@ -60,7 +60,9 @@ static Clr *scheme[SchemeLast];
#include "../accent.h"
static ColorShm *accentshm;
static char accentcol[8] = "#005577";
+static Clr accent[2];
static const double opacity = 0.85;
+static const unsigned int border_width = 3;
static void initaccent(void);
static void updateaccent(void);
@@ -128,8 +130,13 @@ cleanup(void)
static void
updateaccent(void)
{
- if (readaccent(&accentshm, accentcol))
+ if (readaccent(&accentshm, accentcol)) {
drw_clr_create(drw, &scheme[SchemeSel][ColBg], accentcol);
+ drw_clr_create(drw, &accent[ColFg], accentcol);
+ drw_clr_create(drw, &accent[ColBg], accentcol);
+ if (win)
+ XSetWindowBorder(dpy, win, accent[ColFg].pixel);
+ }
}
static void
@@ -193,11 +200,15 @@ drawmenu(void)
drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
}
- if (lines > 0) {
- /* draw vertical list */
- for (item = curr; item != next; item = item->right)
- drawitem(item, x, y += bh, mw - x);
- } else if (matches) {
+ if (lines > 0) {
+ /* draw vertical list */
+ for (item = curr; item != next; item = item->right) {
+ y += bh;
+ drawitem(item, x, y, mw - x);
+ drw_setscheme(drw, accent);
+ drw_rect(drw, x, y + bh - 1, mw - x, 1, 1, 1);
+ }
+ } else if (matches) {
/* draw horizontal list */
x += inputw;
w = TEXTW("<");
@@ -675,67 +686,72 @@ setup(void)
int a, di, n, area = 0;
#endif
/* init appearance */
- for (j = 0; j < SchemeLast; j++)
- scheme[j] = drw_scm_create(drw, colors[j], 2);
+ for (j = 0; j < SchemeLast; j++)
+ scheme[j] = drw_scm_create(drw, colors[j], 2);
+ drw_clr_create(drw, &accent[ColFg], accentcol);
+ drw_clr_create(drw, &accent[ColBg], accentcol);
clip = XInternAtom(dpy, "CLIPBOARD", False);
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
- /* calculate menu geometry */
- bh = drw->fonts->h + 2;
- lines = MAX(lines, 0);
- mh = (lines + 1) * bh;
+ /* calculate menu geometry */
+ bh = drw->fonts->h + 2;
+ lines = MAX(lines, 0);
#ifdef XINERAMA
- i = 0;
- if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
- XGetInputFocus(dpy, &w, &di);
- if (mon >= 0 && mon < n)
- i = mon;
- else if (w != root && w != PointerRoot && w != None) {
- /* find top-level window containing current input focus */
- do {
- if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
- XFree(dws);
- } while (w != root && w != pw);
- /* find xinerama screen with which the window intersects most */
- if (XGetWindowAttributes(dpy, pw, &wa))
- for (j = 0; j < n; j++)
- if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
- area = a;
- i = j;
- }
- }
- /* no focused window is on screen, so use pointer location instead */
- if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
- for (i = 0; i < n; i++)
- if (INTERSECT(x, y, 1, 1, info[i]) != 0)
- break;
-
- x = info[i].x_org;
- y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
- mw = info[i].width;
- XFree(info);
- } else
+ i = 0;
+ if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
+ XGetInputFocus(dpy, &w, &di);
+ if (mon >= 0 && mon < n)
+ i = mon;
+ else if (w != root && w != PointerRoot && w != None) {
+ do {
+ if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
+ XFree(dws);
+ } while (w != root && w != pw);
+ if (XGetWindowAttributes(dpy, pw, &wa))
+ for (j = 0; j < n; j++)
+ if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
+ area = a;
+ i = j;
+ }
+ }
+ if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
+ for (i = 0; i < n; i++)
+ if (INTERSECT(x, y, 1, 1, info[i]) != 0)
+ break;
+
+ mw = info[i].width / 2;
+ if (lines > info[i].height / bh - 1)
+ lines = info[i].height / bh - 1;
+ mh = (lines + 1) * bh;
+ x = info[i].x_org + (info[i].width - mw) / 2;
+ y = info[i].y_org + (info[i].height - mh) / 2;
+ XFree(info);
+ } else
#endif
- {
- if (!XGetWindowAttributes(dpy, parentwin, &wa))
- die("could not get embedding window attributes: 0x%lx",
- parentwin);
- x = 0;
- y = topbar ? 0 : wa.height - mh;
- mw = wa.width;
- }
- promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
- inputw = mw / 3; /* input width: ~33% of monitor width */
- match();
+ {
+ if (!XGetWindowAttributes(dpy, parentwin, &wa))
+ die("could not get embedding window attributes: 0x%lx",
+ parentwin);
+ mw = wa.width / 2;
+ if (lines > wa.height / bh - 1)
+ lines = wa.height / bh - 1;
+ mh = (lines + 1) * bh;
+ x = (wa.width - mw) / 2;
+ y = (wa.height - mh) / 2;
+ }
+ promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
+ inputw = mw - promptw;
+ match();
/* create menu window */
swa.override_redirect = True;
swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
- win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
- CopyFromParent, CopyFromParent, CopyFromParent,
- CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
+ swa.border_pixel = accent[ColFg].pixel;
+ win = XCreateWindow(dpy, root, x, y, mw, mh, border_width,
+ CopyFromParent, CopyFromParent, CopyFromParent,
+ CWOverrideRedirect | CWBackPixel | CWEventMask | CWBorderPixel, &swa);
XSetClassHint(dpy, win, &ch);
/* input methods */
diff --git a/tools/power-menu.sh b/tools/power-menu.sh
new file mode 100755
index 0000000..e3b5c63
--- /dev/null
+++ b/tools/power-menu.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+# simple power menu using dmenu
+choice=$(printf '%s\n' lock reboot shutdown | dmenu -i -l 5)
+case "$choice" in
+ lock)
+ slock &
+ ;;
+ reboot)
+ loginctl reboot
+ ;;
+ shutdown)
+ loginctl poweroff
+ ;;
+ *)
+ exit 0
+ ;;
+esac
diff --git a/tools/steam-dmenu.sh b/tools/steam-dmenu.sh
new file mode 100755
index 0000000..286d312
--- /dev/null
+++ b/tools/steam-dmenu.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+# steam game launcher using dmenu
+appdir="$HOME/.local/share/Steam/steamapps"
+[ -d "$appdir" ] || exit 1
+list=$(find "$appdir" -name '*.acf' -print0 | \
+ xargs -0 -I{} awk -F '"' '/"name"/{name=$4}/"appid"/{printf "%s:%s\n",name,$4}' {} )
+choice=$(printf '%s' "$list" | sort | dmenu -i -l 20)
+appid=$(printf '%s' "$choice" | cut -d: -f2)
+[ -n "$appid" ] && steam -applaunch "$appid" >/dev/null 2>&1 &
diff --git a/tools/universal_launcher.sh b/tools/universal_launcher.sh
new file mode 100755
index 0000000..2cedc59
--- /dev/null
+++ b/tools/universal_launcher.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+# universal dmenu launcher
+choice=$(printf '%s\n' Run Steam Power | dmenu -i -l 10)
+case "$choice" in
+ Run)
+ dmenu_run &
+ ;;
+ Steam)
+ "$(dirname "$0")/steam-dmenu.sh"
+ ;;
+ Power)
+ "$(dirname "$0")/power-menu.sh"
+ ;;
+ *)
+ exit 0
+ ;;
+ esac
diff --git a/tools/universal_launcher.txt b/tools/universal_launcher.txt
new file mode 100644
index 0000000..ef46ae0
--- /dev/null
+++ b/tools/universal_launcher.txt
@@ -0,0 +1,5 @@
+Universal launcher notes:
+- Added `universal_launcher.sh` script providing Run, Steam, and Power menus via dmenu.
+- Added `steam-dmenu.sh` to list installed Steam games and launch them.
+- Added `power-menu.sh` for locking, rebooting, and shutting down.
+- Patched dmenu to center on screen, size dynamically, draw a 3px accent-colored border and separators, and update colors from accent.h.