summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md10
-rw-r--r--glitch.h1
-rw-r--r--launcher.c53
3 files changed, 61 insertions, 3 deletions
diff --git a/README.md b/README.md
index 3840598..873f1d9 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@ Glitch is a minimal X11 window manager controlled by keyboard shortcuts.
- **Window Centering**: Center windows on screen
- **Audio Control**: Toggle microphone mute with on-screen status
- **Tiling Layout**: Toggle between floating and tiling layouts per desktop
+- **Application Launcher**: Integrated .desktop-aware launcher with usage-based sorting
- **On-screen Indicators**: Live status for desktop, layout, mic, and clock
- **Live Reload**: Reload configuration without restart
@@ -26,6 +27,8 @@ Glitch is a minimal X11 window manager controlled by keyboard shortcuts.
- Built on X11/Xlib for low-level window management
- Uses EWMH (Extended Window Manager Hints) for fullscreen and state functionality
- Integrated PulseAudio support for real-time microphone status tracking
+- Uses GIO/GLib for standard-compliant .desktop file parsing and application discovery
+- Persistent usage tracking for applications to provide "most used" sorting
- Xft-based on-screen widgets for system status (Clock, Mic, Layout, Desktop)
- Maintains state for maximized windows to enable toggle behavior
- Implements proper X11 event handling and window attribute management
@@ -38,13 +41,14 @@ Glitch is a minimal X11 window manager controlled by keyboard shortcuts.
- X11 and Freetype development libraries
- libXft development library
- PulseAudio development library
+- GLib/GIO development libraries
### Installing Dependencies
**Void Linux:**
```sh
-sudo xbps-install libX11-devel freetype-devel libXft-devel pulseaudio-devel pkg-config
+sudo xbps-install libX11-devel freetype-devel libXft-devel pulseaudio-devel glib-devel pkg-config
```
## Compilation
@@ -182,6 +186,7 @@ Modifier key: `Mod4` (Super/Windows key)
{ MODKEY, XK_f, toggle_fullscreen, { 0 } },
{ MODKEY, XK_q, close_window, { 0 } },
{ MODKEY, XK_m, toggle_mic_mute, { 0 } },
+{ MODKEY, XK_p, toggle_launcher, { 0 } },
{ MODKEY, XK_space, toggle_layout, { 0 } },
{ MODKEY | ShiftMask, XK_q, quit, { 0 } },
{ MODKEY | ShiftMask, XK_r, reload, { 0 } },
@@ -211,7 +216,7 @@ Modifier key: `Mod4` (Super/Windows key)
Defined in `shortcuts[]` array:
- `Mod+Return`: Terminal (st)
-- `Mod+p`: Application launcher (rofi)
+- `Mod+p`: Internal application launcher
- `Mod+w`: Browser (brave)
- `Mod+e`: File Manager (thunar)
- `Mod+s`: Screen magnifier (xmagnify)
@@ -243,5 +248,6 @@ Defined in `shortcuts[]` array:
| `window_hmaximize` | Maximize | None | Toggle horizontal maximize |
| `window_vmaximize` | Maximize | None | Toggle vertical maximize |
| `toggle_mic_mute` | Audio | None | Toggle microphone mute state |
+| `toggle_launcher` | Control | None | Toggle integrated app launcher |
| `toggle_layout` | Layout | None | Toggle between floating/tiling |
| `reload` | System | None | Reload configuration/restart WM |
diff --git a/glitch.h b/glitch.h
index c7bcf3f..69cfe0f 100644
--- a/glitch.h
+++ b/glitch.h
@@ -58,6 +58,7 @@ typedef struct Client {
typedef struct {
char *name;
char *exec;
+ int usage;
} LauncherItem;
typedef struct {
diff --git a/launcher.c b/launcher.c
index b82577c..0346403 100644
--- a/launcher.c
+++ b/launcher.c
@@ -10,6 +10,7 @@
#include <X11/Xutil.h>
#include <X11/keysym.h>
+#include <sys/stat.h>
#include <gio/gio.h>
#include "glitch.h"
@@ -19,6 +20,47 @@ extern WindowManager wm;
static void launcher_filter(void);
+static int compare_launcher_items(const void *a, const void *b) {
+ const LauncherItem *ia = (const LauncherItem *)a;
+ const LauncherItem *ib = (const LauncherItem *)b;
+ if (ib->usage != ia->usage)
+ return ib->usage - ia->usage;
+ return strcasecmp(ia->name, ib->name);
+}
+
+static void load_usage(void) {
+ char path[1024];
+ char *home = getenv("HOME");
+ if (!home) return;
+ snprintf(path, sizeof(path), "%s/.cache/glitch/usage.db", home);
+
+ GKeyFile *kf = g_key_file_new();
+ if (g_key_file_load_from_file(kf, path, G_KEY_FILE_NONE, NULL)) {
+ for (int i = 0; i < wm.launcher_items_count; i++) {
+ wm.launcher_items[i].usage = g_key_file_get_integer(kf, "Usage", wm.launcher_items[i].exec, NULL);
+ }
+ }
+ g_key_file_free(kf);
+}
+
+static void record_usage(const char *exec) {
+ char path[1024];
+ char *home = getenv("HOME");
+ if (!home) return;
+ snprintf(path, sizeof(path), "%s/.cache/glitch", home);
+ mkdir(path, 0755);
+ snprintf(path, sizeof(path), "%s/.cache/glitch/usage.db", home);
+
+ GKeyFile *kf = g_key_file_new();
+ g_key_file_load_from_file(kf, path, G_KEY_FILE_NONE, NULL);
+
+ int count = g_key_file_get_integer(kf, "Usage", exec, NULL);
+ g_key_file_set_integer(kf, "Usage", exec, count + 1);
+
+ g_key_file_save_to_file(kf, path, NULL);
+ g_key_file_free(kf);
+}
+
static void load_applications(void) {
if (wm.launcher_items) {
for (int i = 0; i < wm.launcher_items_count; i++) {
@@ -47,8 +89,10 @@ static void load_applications(void) {
if (name && exec) {
wm.launcher_items[wm.launcher_items_count].name = strdup(name);
+ wm.launcher_items[wm.launcher_items_count].usage = 0;
char *e = strdup(exec);
+
char *percent = strchr(e, '%');
if (percent) *percent = '\0';
@@ -66,6 +110,9 @@ static void load_applications(void) {
g_object_unref(app);
}
g_list_free(apps);
+
+ load_usage();
+ qsort(wm.launcher_items, wm.launcher_items_count, sizeof(LauncherItem), compare_launcher_items);
}
void toggle_launcher(const Arg *arg) {
@@ -77,7 +124,10 @@ void toggle_launcher(const Arg *arg) {
return;
}
- if (!wm.launcher_items) {
+ if (wm.launcher_items) {
+ load_usage();
+ qsort(wm.launcher_items, wm.launcher_items_count, sizeof(LauncherItem), compare_launcher_items);
+ } else {
load_applications();
}
@@ -143,6 +193,7 @@ void launcher_handle_key(void) {
}
} else if (keysym == XK_Return) {
if (wm.launcher_filtered_count > 0 && wm.launcher_selected < wm.launcher_filtered_count) {
+ record_usage(wm.launcher_filtered[wm.launcher_selected]->exec);
execute_shortcut(wm.launcher_filtered[wm.launcher_selected]->exec);
toggle_launcher(NULL);
return;