Redesign launcher: modern dark UI, 4-col grid, pill filters, footer
- 640x490 window, larger cards (132x106), 4 columns - Full-width search bar in header with active-state indicator - Category filters as pill chips with gaps - Cards show surface bg + accent top bar on hover - Footer bar with app count and keyboard hints - Fix menu: pavucontrol -> alsamixer in xterm Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
daf9cb4f96
commit
4854ab85aa
2 files changed
+135
-91
No files matched your search
+134
-90
@@ -11,51 +11,55 @@
|
||||
#include <unistd.h>
|
||||
|
||||
/* ── dimensions ─────────────────────────────────────────────────────── */
|
||||
#define WIN_W 580
|
||||
#define WIN_H 420
|
||||
#define HDR_H 50
|
||||
#define TAB_H 34
|
||||
#define CONTENT_Y (HDR_H + TAB_H)
|
||||
#define PAD 12
|
||||
#define CARD_W 96
|
||||
#define CARD_H 84
|
||||
#define CARD_GAP 8
|
||||
#define COLS 5
|
||||
#define ICON_SZ 38
|
||||
#define WIN_W 640
|
||||
#define WIN_H 490
|
||||
#define HDR_H 58
|
||||
#define PILLS_H 42
|
||||
#define CONTENT_Y (HDR_H + PILLS_H)
|
||||
#define FOOTER_H 28
|
||||
#define CARD_W 132
|
||||
#define CARD_H 106
|
||||
#define CARD_GAP 10
|
||||
#define COLS 4
|
||||
#define ICON_SZ 46
|
||||
#define PILL_GAP 8
|
||||
#define ROWS_VIS 3
|
||||
|
||||
#define GX0 ((WIN_W - (COLS * CARD_W + (COLS-1) * CARD_GAP)) / 2)
|
||||
#define GY0 (CONTENT_Y + PAD)
|
||||
#define ROWS_VIS 3 /* rows visible before scrolling */
|
||||
#define GY0 (CONTENT_Y + 12)
|
||||
#define MAX_APPS 256
|
||||
|
||||
/* ── palette ─────────────────────────────────────────────────────────── */
|
||||
#define C_BG 0x0E1220
|
||||
#define C_HDR 0x090C18
|
||||
#define C_BORDER 0x192236
|
||||
#define C_ACCENT 0x2258B0
|
||||
#define C_TAB_SEL 0x141E30
|
||||
#define C_CARD_HOV 0x131C2E
|
||||
#define C_CARD_BD 0x1E2E48
|
||||
#define C_SEARCH 0x131A28
|
||||
#define C_SEARCH_BD 0x1C2C44
|
||||
#define C_TEXT 0x8AAAC8
|
||||
#define C_TEXT_HOV 0xE8F0FF
|
||||
#define C_TEXT_DIM 0x344A62
|
||||
#define C_TAB_TXT 0x486070
|
||||
#define C_TAB_TSEL 0xA8C4E8
|
||||
#define C_SCROLL_BG 0x0C1020
|
||||
#define C_SCROLL_TH 0x1E3258
|
||||
#define C_BG 0x111318
|
||||
#define C_SURFACE 0x1A1D28
|
||||
#define C_SURFACE_HV 0x1F2335
|
||||
#define C_BORDER 0x252A42
|
||||
#define C_BORDER_HV 0x3A5490
|
||||
#define C_ACCENT 0x4B8FF0
|
||||
#define C_PILL_SEL 0x19305C
|
||||
#define C_PILL_BD 0x2A4480
|
||||
#define C_SRCH_BG 0x161820
|
||||
#define C_SRCH_BD 0x262C48
|
||||
#define C_TEXT 0xC0CFF0
|
||||
#define C_TEXT_HOV 0xEEF2FF
|
||||
#define C_TEXT_DIM 0x3A4068
|
||||
#define C_TEXT_CAT 0x586090
|
||||
#define C_TEXT_CAT_S 0x8AAEE8
|
||||
#define C_FOOTER_BG 0x0C0E14
|
||||
#define C_FOOTER_TXT 0x353C62
|
||||
#define C_SCROLL_BG 0x161820
|
||||
#define C_SCROLL_TH 0x2C3460
|
||||
|
||||
static const unsigned long ICON_BG[] = {
|
||||
0x1A4D88, 0x166C3C, 0x6C3018,
|
||||
0x4A1A80, 0x126070, 0x6C1A38,
|
||||
0x365218, 0x183460,
|
||||
0x1A3A88, 0x0F6040, 0x7A2820, 0x501A80,
|
||||
0x106070, 0x6A1A3A, 0x384C18, 0x1A3060,
|
||||
0x6A4010, 0x103A60,
|
||||
};
|
||||
#define NICON 8
|
||||
#define NICON 10
|
||||
|
||||
#define FONT_UI "Sans:size=9"
|
||||
#define FONT_LOGO "Sans:size=11:weight=bold"
|
||||
#define FONT_ICON "Sans:size=13:weight=bold"
|
||||
#define FONT_ICON "Sans:size=14:weight=bold"
|
||||
#define FONT_HINT "Sans:size=8"
|
||||
#define MAX_FLT 64
|
||||
|
||||
typedef struct { char name[64]; char cmd[256]; char cat[32]; char icon[64]; } App;
|
||||
@@ -171,7 +175,6 @@ static void load_apps(void) {
|
||||
load_desktop_dir(p);
|
||||
}
|
||||
|
||||
/* fallback if no .desktop files (dev environment, macOS, etc.) */
|
||||
if (NAPP == 0) {
|
||||
static const struct { const char *n, *c, *cat; } FB[] = {
|
||||
{ "Terminal", "xterm &", "System" },
|
||||
@@ -196,7 +199,7 @@ typedef struct {
|
||||
Display *dpy; int screen;
|
||||
Window root, win; GC gc;
|
||||
Colormap cmap; Visual *visual;
|
||||
XftFont *font_ui, *font_logo, *font_icon;
|
||||
XftFont *font_ui, *font_icon, *font_hint;
|
||||
int sel_cat, hov, scroll;
|
||||
char filter[MAX_FLT];
|
||||
int filter_len;
|
||||
@@ -257,28 +260,28 @@ static int nvis(L *l, int out[MAX_APPS]) {
|
||||
return n;
|
||||
}
|
||||
|
||||
static void tab_layout(L *l, int widths[NCAT], int *total) {
|
||||
static void pill_layout(L *l, int widths[NCAT], int *total) {
|
||||
*total = 0;
|
||||
for (int i = 0; i < NCAT; i++) {
|
||||
XGlyphInfo e;
|
||||
XftTextExtentsUtf8(l->dpy, l->font_ui, (FcChar8*)CATS[i], strlen(CATS[i]), &e);
|
||||
widths[i] = (int)e.width + 22;
|
||||
widths[i] = (int)e.width + 24;
|
||||
*total += widths[i];
|
||||
}
|
||||
*total += (NCAT - 1) * PILL_GAP;
|
||||
}
|
||||
|
||||
static int tab_at(L *l, int x, int y) {
|
||||
if (y < HDR_H || y >= CONTENT_Y) return -1;
|
||||
int w[NCAT], total; tab_layout(l, w, &total);
|
||||
int w[NCAT], total; pill_layout(l, w, &total);
|
||||
int tx = (WIN_W - total) / 2;
|
||||
for (int i = 0; i < NCAT; i++) {
|
||||
if (x >= tx && x < tx + w[i]) return i;
|
||||
tx += w[i];
|
||||
tx += w[i] + PILL_GAP;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* card index within visible slice (adjusted for scroll) */
|
||||
static int card_at_vis(int x, int y) {
|
||||
if (y < CONTENT_Y) return -1;
|
||||
int lx = x - GX0, ly = y - GY0;
|
||||
@@ -328,60 +331,68 @@ found:;
|
||||
static void draw(L *l) {
|
||||
XftDraw *xd = XftDrawCreate(l->dpy, l->win, l->visual, l->cmap);
|
||||
|
||||
/* background */
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_BG));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, 0, 0, WIN_W, WIN_H);
|
||||
|
||||
/* header */
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_HDR));
|
||||
/* ── header: search bar ─────────────────────────── */
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_SURFACE));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, 0, 0, WIN_W, HDR_H);
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_ACCENT));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, 0, 0, WIN_W, 2);
|
||||
|
||||
ds(l, xd, l->font_logo, C_ACCENT, 14, 13, "OrionOS");
|
||||
|
||||
/* search box */
|
||||
/* search input box */
|
||||
{
|
||||
int sx = 86, sy = 10, sw = WIN_W - 86 - 14, sh = 30;
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_SEARCH));
|
||||
int sx = 16, sy = 11, sw = WIN_W - 32, sh = 36;
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_SRCH_BG));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, sx, sy, sw, sh);
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_SEARCH_BD));
|
||||
XDrawRectangle(l->dpy, l->win, l->gc, sx, sy, sw, sh);
|
||||
XSetForeground(l->dpy, l->gc, mkc(l,
|
||||
l->filter_len > 0 ? C_BORDER_HV : C_SRCH_BD));
|
||||
XDrawRectangle(l->dpy, l->win, l->gc, sx, sy, sw - 1, sh - 1);
|
||||
|
||||
/* accent left bar when active */
|
||||
if (l->filter_len > 0) {
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_ACCENT));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, sx, sy, 2, sh);
|
||||
}
|
||||
|
||||
if (l->filter_len == 0) {
|
||||
ds(l, xd, l->font_ui, C_TEXT_DIM, sx + 8, sy + 7, "Search apps...");
|
||||
ds(l, xd, l->font_ui, C_TEXT_DIM, sx + 12, sy + 10, "Search applications...");
|
||||
} else {
|
||||
char buf[MAX_FLT + 2];
|
||||
snprintf(buf, sizeof(buf), "%s|", l->filter);
|
||||
ds(l, xd, l->font_ui, C_TEXT_HOV, sx + 8, sy + 7, buf);
|
||||
snprintf(buf, sizeof(buf), "%s_", l->filter);
|
||||
ds(l, xd, l->font_ui, C_TEXT_HOV, sx + 12, sy + 10, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* header bottom separator */
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_BORDER));
|
||||
XDrawLine(l->dpy, l->win, l->gc, 0, HDR_H, WIN_W, HDR_H);
|
||||
XDrawLine(l->dpy, l->win, l->gc, 0, HDR_H - 1, WIN_W, HDR_H - 1);
|
||||
|
||||
/* ── pills row ───────────────────────────────────── */
|
||||
int pw[NCAT], ptotal; pill_layout(l, pw, &ptotal);
|
||||
int px = (WIN_W - ptotal) / 2;
|
||||
int py = HDR_H + (PILLS_H - 24) / 2;
|
||||
|
||||
/* category tabs */
|
||||
int tw[NCAT], ttotal; tab_layout(l, tw, &ttotal);
|
||||
int tx = (WIN_W - ttotal) / 2;
|
||||
for (int i = 0; i < NCAT; i++) {
|
||||
if (i == l->sel_cat) {
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_TAB_SEL));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, tx, HDR_H + 1, tw[i], TAB_H - 1);
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_ACCENT));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, tx + 5, HDR_H + TAB_H - 2, tw[i] - 10, 2);
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_PILL_SEL));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, px, py, pw[i], 24);
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_PILL_BD));
|
||||
XDrawRectangle(l->dpy, l->win, l->gc, px, py, pw[i] - 1, 23);
|
||||
ds_ctr(l, xd, l->font_ui, C_TEXT_CAT_S, px, py, pw[i], 24, CATS[i]);
|
||||
} else {
|
||||
ds_ctr(l, xd, l->font_ui, C_TEXT_CAT, px, py, pw[i], 24, CATS[i]);
|
||||
}
|
||||
ds_ctr(l, xd, l->font_ui,
|
||||
(i == l->sel_cat) ? C_TAB_TSEL : C_TAB_TXT,
|
||||
tx, HDR_H, tw[i], TAB_H, CATS[i]);
|
||||
tx += tw[i];
|
||||
px += pw[i] + PILL_GAP;
|
||||
}
|
||||
|
||||
/* pills bottom separator */
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_BORDER));
|
||||
XDrawLine(l->dpy, l->win, l->gc, 0, CONTENT_Y, WIN_W, CONTENT_Y);
|
||||
XDrawLine(l->dpy, l->win, l->gc, 0, CONTENT_Y - 1, WIN_W, CONTENT_Y - 1);
|
||||
|
||||
/* app grid with scroll */
|
||||
/* ── app grid ────────────────────────────────────── */
|
||||
int vis[MAX_APPS];
|
||||
int nv = nvis(l, vis);
|
||||
|
||||
/* clamp scroll */
|
||||
int max_scroll = (nv - ROWS_VIS * COLS + COLS - 1) / COLS;
|
||||
if (max_scroll < 0) max_scroll = 0;
|
||||
if (l->scroll > max_scroll) l->scroll = max_scroll;
|
||||
@@ -391,7 +402,8 @@ static void draw(L *l) {
|
||||
|
||||
if (nv == 0) {
|
||||
ds_ctr(l, xd, l->font_ui, C_TEXT_DIM,
|
||||
0, CONTENT_Y, WIN_W, WIN_H - CONTENT_Y, "No apps found");
|
||||
0, CONTENT_Y, WIN_W, WIN_H - CONTENT_Y - FOOTER_H,
|
||||
"No matching apps");
|
||||
} else {
|
||||
for (int i = 0; i < ROWS_VIS * COLS; i++) {
|
||||
int vi = vis_start + i;
|
||||
@@ -402,18 +414,29 @@ static void draw(L *l) {
|
||||
int cy = GY0 + row * (CARD_H + CARD_GAP);
|
||||
int hover = (i == l->hov);
|
||||
|
||||
/* card background */
|
||||
if (hover) {
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_CARD_HOV));
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_SURFACE_HV));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, cx, cy, CARD_W, CARD_H);
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_CARD_BD));
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_BORDER_HV));
|
||||
XDrawRectangle(l->dpy, l->win, l->gc, cx, cy, CARD_W - 1, CARD_H - 1);
|
||||
/* accent top bar on hover */
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_ACCENT));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, cx + 1, cy, CARD_W - 2, 2);
|
||||
} else {
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_SURFACE));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, cx, cy, CARD_W, CARD_H);
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_BORDER));
|
||||
XDrawRectangle(l->dpy, l->win, l->gc, cx, cy, CARD_W - 1, CARD_H - 1);
|
||||
}
|
||||
|
||||
int app_i = vis[vi];
|
||||
unsigned int h = 0;
|
||||
for (const char *p = APPS[app_i].name; *p; p++) h = h * 31 + (unsigned char)*p;
|
||||
|
||||
/* icon */
|
||||
int ix = cx + (CARD_W - ICON_SZ) / 2;
|
||||
int iy = cy + 10;
|
||||
int iy = cy + 14;
|
||||
int icon_rendered = 0;
|
||||
#ifdef HAVE_IMLIB2
|
||||
icon_rendered = render_icon(l, APPS[app_i].icon, ix, iy, ICON_SZ);
|
||||
@@ -421,34 +444,57 @@ static void draw(L *l) {
|
||||
if (!icon_rendered) {
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, ICON_BG[h % NICON]));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, ix, iy, ICON_SZ, ICON_SZ);
|
||||
/* 1px darker border on icon box */
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, 0x000000));
|
||||
XDrawRectangle(l->dpy, l->win, l->gc, ix, iy, ICON_SZ - 1, ICON_SZ - 1);
|
||||
char letter[2] = { APPS[app_i].name[0], '\0' };
|
||||
if (letter[0] >= 'a' && letter[0] <= 'z') letter[0] -= 32;
|
||||
ds_ctr(l, xd, l->font_icon, 0xEAF0FF, ix, iy, ICON_SZ, ICON_SZ, letter);
|
||||
ds_ctr(l, xd, l->font_icon, 0xF0F4FF,
|
||||
ix, iy, ICON_SZ, ICON_SZ, letter);
|
||||
}
|
||||
|
||||
char lbl[14];
|
||||
snprintf(lbl, sizeof(lbl), "%.12s", APPS[app_i].name);
|
||||
/* label */
|
||||
char lbl[16];
|
||||
snprintf(lbl, sizeof(lbl), "%.14s", APPS[app_i].name);
|
||||
ds_ctr(l, xd, l->font_ui,
|
||||
hover ? C_TEXT_HOV : C_TEXT,
|
||||
cx, iy + ICON_SZ + 4, CARD_W, CARD_H - ICON_SZ - 18, lbl);
|
||||
cx, iy + ICON_SZ + 6, CARD_W, CARD_H - ICON_SZ - 24, lbl);
|
||||
}
|
||||
}
|
||||
|
||||
/* scrollbar */
|
||||
if (max_scroll > 0) {
|
||||
int sb_x = WIN_W - 8, sb_y = CONTENT_Y + 4;
|
||||
int sb_h = WIN_H - CONTENT_Y - 8;
|
||||
int sb_x = WIN_W - 6;
|
||||
int sb_y = CONTENT_Y + 4;
|
||||
int sb_h = WIN_H - CONTENT_Y - FOOTER_H - 8;
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_SCROLL_BG));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, sb_x, sb_y, 6, sb_h);
|
||||
XFillRectangle(l->dpy, l->win, l->gc, sb_x, sb_y, 4, sb_h);
|
||||
int total_rows = (nv + COLS - 1) / COLS;
|
||||
int thumb_h = sb_h * ROWS_VIS / total_rows;
|
||||
if (thumb_h < 12) thumb_h = 12;
|
||||
if (thumb_h < 10) thumb_h = 10;
|
||||
int thumb_y = sb_y + (sb_h - thumb_h) * l->scroll / max_scroll;
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_SCROLL_TH));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, sb_x + 1, thumb_y, 4, thumb_h);
|
||||
XFillRectangle(l->dpy, l->win, l->gc, sb_x, thumb_y, 4, thumb_h);
|
||||
}
|
||||
|
||||
/* outer border */
|
||||
/* ── footer ──────────────────────────────────────── */
|
||||
int fy = WIN_H - FOOTER_H;
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_FOOTER_BG));
|
||||
XFillRectangle(l->dpy, l->win, l->gc, 0, fy, WIN_W, FOOTER_H);
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_BORDER));
|
||||
XDrawLine(l->dpy, l->win, l->gc, 0, fy, WIN_W, fy);
|
||||
|
||||
/* app count left, hints right */
|
||||
{
|
||||
char cnt[32];
|
||||
snprintf(cnt, sizeof(cnt), "%d apps", nv);
|
||||
ds(l, xd, l->font_hint, C_FOOTER_TXT, 14, fy + 7, cnt);
|
||||
ds_ctr(l, xd, l->font_hint, C_FOOTER_TXT,
|
||||
0, fy, WIN_W, FOOTER_H,
|
||||
"Return: launch Esc: close Type: filter");
|
||||
}
|
||||
|
||||
/* outer window border */
|
||||
XSetForeground(l->dpy, l->gc, mkc(l, C_BORDER));
|
||||
XDrawRectangle(l->dpy, l->win, l->gc, 0, 0, WIN_W - 1, WIN_H - 1);
|
||||
|
||||
@@ -478,7 +524,6 @@ static void on_key(L *l, XKeyEvent *e) {
|
||||
l->filter[--l->filter_len] = '\0';
|
||||
l->scroll = 0; l->hov = -1; draw(l); return;
|
||||
}
|
||||
/* page up/down for keyboard scroll */
|
||||
if (sym == XK_Prior) { l->scroll -= ROWS_VIS; if (l->scroll < 0) l->scroll = 0; draw(l); return; }
|
||||
if (sym == XK_Next) { l->scroll += ROWS_VIS; draw(l); return; }
|
||||
|
||||
@@ -506,11 +551,11 @@ int main(void) {
|
||||
l.visual = DefaultVisual(l.dpy, l.screen);
|
||||
|
||||
l.font_ui = XftFontOpenName(l.dpy, l.screen, FONT_UI);
|
||||
l.font_logo = XftFontOpenName(l.dpy, l.screen, FONT_LOGO);
|
||||
l.font_icon = XftFontOpenName(l.dpy, l.screen, FONT_ICON);
|
||||
l.font_hint = XftFontOpenName(l.dpy, l.screen, FONT_HINT);
|
||||
if (!l.font_ui) l.font_ui = XftFontOpenName(l.dpy, l.screen, "fixed:size=9");
|
||||
if (!l.font_logo) l.font_logo = l.font_ui;
|
||||
if (!l.font_icon) l.font_icon = l.font_ui;
|
||||
if (!l.font_hint) l.font_hint = l.font_ui;
|
||||
|
||||
int sw = DisplayWidth(l.dpy, l.screen);
|
||||
int sh = DisplayHeight(l.dpy, l.screen);
|
||||
@@ -540,14 +585,13 @@ int main(void) {
|
||||
if (e.xexpose.count == 0) draw(&l);
|
||||
break;
|
||||
case ButtonPress:
|
||||
{
|
||||
/* scroll wheel */
|
||||
if (e.xbutton.button == Button4) {
|
||||
l.scroll -= 1; if (l.scroll < 0) l.scroll = 0; draw(&l); break;
|
||||
}
|
||||
if (e.xbutton.button == Button5) {
|
||||
l.scroll += 1; draw(&l); break;
|
||||
}
|
||||
{
|
||||
int t = tab_at(&l, e.xbutton.x, e.xbutton.y);
|
||||
if (t >= 0) {
|
||||
l.sel_cat = t; l.scroll = 0; l.hov = -1; draw(&l);
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ static const MenuItem MENU_ITEMS[] = {
|
||||
{ "──────────────────", NULL },
|
||||
{ "Web Browser", "firefox &" },
|
||||
{ "System Monitor", "xterm -T 'System Monitor' -e htop &" },
|
||||
{ "Volume Control", "pavucontrol &" },
|
||||
{ "Volume Control", "xterm -e alsamixer &" },
|
||||
{ "Software Updates", "orionpkg &" },
|
||||
{ "Display Settings", "arandr &" },
|
||||
{ "──────────────────", NULL },
|
||||
|
||||
Reference in new issue
Block a user