Add menu patch

This commit is contained in:
Sravan Balaji
2024-10-06 15:12:55 -04:00
parent 65ef994e4c
commit 07c8cc46d3
6 changed files with 457 additions and 5 deletions

164
dwl.c
View File

@@ -296,6 +296,14 @@ typedef struct {
struct wl_listener destroy;
} SessionLock;
#if MENU_PATCH
typedef struct {
const char *cmd; /* command to run a menu */
void (*feed)(FILE *f); /* feed input to menu */
void (*action)(char *line); /* do action based on menu output */
} Menu;
#endif // MENU_PATCH
/* function declarations */
static void applybounds(Client *c, struct wlr_box *bbox);
static void applyrules(Client *c);
@@ -391,6 +399,14 @@ static void killclient(const Arg *arg);
static void locksession(struct wl_listener *listener, void *data);
static void mapnotify(struct wl_listener *listener, void *data);
static void maximizenotify(struct wl_listener *listener, void *data);
#if MENU_PATCH
static void menu(const Arg *arg);
static int menuloop(void *data);
static void menuwinfeed(FILE *f);
static void menuwinaction(char *line);
static void menulayoutfeed(FILE *f);
static void menulayoutaction(char *line);
#endif // MENU_PATCH
static void monocle(Monitor *m);
#if MOVESTACK_PATCH
static void movestack(const Arg *arg);
@@ -547,6 +563,13 @@ static struct wlr_box sgeom;
static struct wl_list mons;
static Monitor *selmon;
#if MENU_PATCH
static struct wl_event_source *menu_source;
static pid_t menu_pid;
static int menu_fd;
static const Menu *menu_current;
#endif // MENU_PATCH
#if IPC_PATCH
static struct zdwl_ipc_manager_v2_interface dwl_manager_implementation = {.release = dwl_ipc_manager_release, .get_output = dwl_ipc_manager_get_output};
static struct zdwl_ipc_output_v2_interface dwl_output_implementation = {.release = dwl_ipc_output_release, .set_tags = dwl_ipc_output_set_tags, .set_layout = dwl_ipc_output_set_layout, .set_client_tags = dwl_ipc_output_set_client_tags};
@@ -891,6 +914,9 @@ cleanup(void)
wlr_xwayland_destroy(xwayland);
xwayland = NULL;
#endif // XWAYLAND
#if MENU_PATCH
wl_event_source_remove(menu_source);
#endif // MENU_PATCH
wl_display_destroy_clients(dpy);
#if AUTOSTART_PATCH
@@ -2558,6 +2584,138 @@ maximizenotify(struct wl_listener *listener, void *data)
wlr_xdg_surface_schedule_configure(c->surface.xdg);
}
#if MENU_PATCH
void
menu(const Arg *arg)
{
FILE *f;
pid_t pid;
int fd_right[2], fd_left[2];
if (!selmon || menu_pid != 0)
return;
menu_current = arg->v;
if (pipe(fd_right) == -1 || pipe(fd_left) == -1)
return;
if ((pid = fork()) == -1)
return;
if (pid == 0) {
close(fd_right[1]);
close(fd_left[0]);
dup2(fd_right[0], STDIN_FILENO);
close(fd_right[0]);
dup2(fd_left[1], STDOUT_FILENO);
close(fd_left[1]);
execl("/bin/sh", "/bin/sh", "-c", menu_current->cmd, NULL);
die("dwl: execl %s failed:", "/bin/sh");
}
close(fd_right[0]);
close(fd_left[1]);
if (!(f = fdopen(fd_right[1], "w")))
return;
menu_current->feed(f);
fclose(f);
menu_pid = pid;
menu_fd = fd_left[0];
wl_event_source_timer_update(menu_source, 10);
}
int
menuloop(void *data)
{
FILE *f;
pid_t pid;
char line[256], *s;
/* If process is still running, wait for another 50 ms */
if ((pid = waitpid(menu_pid, NULL, WNOHANG)) == 0) {
wl_event_source_timer_update(menu_source, 10);
return 0;
}
menu_pid = 0;
if (!(f = fdopen(menu_fd, "r")))
return 0;
if (fgets(line, sizeof(line), f)) {
if ((s = strchr(line, '\n')))
*s = '\0';
menu_current->action(line);
}
fclose(f);
return 0;
}
void
menuwinfeed(FILE *f)
{
Client *c;
const char *title;
wl_list_for_each(c, &fstack, flink) {
if (!(title = client_get_title(c)))
continue;
fprintf(f, "%s\n", title);
}
}
void
menuwinaction(char *line)
{
Client *c;
Monitor *prevm = selmon;
const char *title;
if (!selmon)
return;
wl_list_for_each(c, &fstack, flink) {
if (!(title = client_get_title(c)))
continue;
if (strcmp(line, title) == 0)
goto found;
}
return;
found:
focusclient(c, 1);
wlr_cursor_move(cursor, NULL, selmon->m.x - prevm->m.x , 0);
selmon->seltags ^= 1; /* toggle sel tagset */
selmon->tagset[selmon->seltags] = c->tags;
arrange(selmon);
printstatus();
}
void
menulayoutfeed(FILE *f)
{
unsigned int i;
for (i = 0; i < LENGTH(layouts); i++)
fprintf(f, "%s\n", layouts[i].symbol);
}
void
menulayoutaction(char *line)
{
unsigned int i;
Arg a;
for (i = 0; i < LENGTH(layouts); i++)
if (strcmp(line, layouts[i].symbol) == 0)
goto found;
return;
found:
a.v = &layouts[i];
setlayout(&a);
}
#endif // MENU_PATCH
void
monocle(Monitor *m)
{
@@ -3582,6 +3740,12 @@ setup(void)
* e.g when running in the x11 backend or the wayland backend and the
* compositor has Xwayland support */
unsetenv("DISPLAY");
#if MENU_PATCH
menu_source = wl_event_loop_add_timer(
wl_display_get_event_loop(dpy), menuloop, NULL);
#endif // MENU_PATCH
#ifdef XWAYLAND
/*
* Initialise the XWayland X server.