1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
/* aewm - Copyright 1998-2007 Decklin Foster <decklin@red-bean.com>.
* This program is free software; please see LICENSE for details. */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include "common.h"
#include "parser.h"
#include "atom.h"
#include "menu.h"
void setup_switch_atoms()
{
utf8_string = XInternAtom(dpy, "UTF8_STRING", False);
wm_state = XInternAtom(dpy, "WM_STATE", False);
net_client_list = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
net_cur_desk = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", False);
net_wm_desk = XInternAtom(dpy, "_NET_WM_DESKTOP", False);
net_wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
net_wm_state_skipt = XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False);
net_wm_state_skipp = XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", False);
net_wm_wintype = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
net_wm_type_dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
net_wm_type_desk = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
}
void snprint_wm_name(char *buf, size_t len, Window w)
{
char *n;
if ((n = get_wm_name(w))) {
if (get_wm_state(w) == NormalState) {
if (snprintf(buf, len, "%s", n) > len)
strcpy(buf+len-4, "...");
} else {
if (snprintf(buf, len, "[%s]", n) > len)
strcpy(buf+len-5, "...]");
}
XFree(n);
} else {
snprintf(buf, len, "%#lx", w);
}
}
/* The WM receives the ClientMessage here and sets the property in response,
* so we only do this after the PropertyNotify. */
int is_on_cur_desk(Window w)
{
unsigned long w_desk, cur_desk;
if (get_atoms(root, net_cur_desk, XA_CARDINAL, 0, &cur_desk, 1, NULL) &&
(get_atoms(w, net_wm_desk, XA_CARDINAL, 0, &w_desk, 1, NULL)))
return IS_ON_DESK(w_desk, cur_desk);
else
return 1;
}
int is_skip(Window w)
{
Atom win_type, state;
int i;
unsigned long r;
if (get_atoms(w, net_wm_wintype, XA_ATOM, 0, &win_type, 1, NULL) &&
(win_type == net_wm_type_dock || win_type == net_wm_type_desk))
return 1;
for (i = 0, r = 1; r; i += r)
if ((r = get_atoms(w, net_wm_state, XA_ATOM, i, &state, 1, NULL)) &&
(state == net_wm_state_skipt || state == net_wm_state_skipp))
return 1;
return 0;
}
/* This XSync call is required, as we don't have any sort of integration with
* the real X event loop. */
void raise_win(Window w)
{
XMapRaised(dpy, w);
XSync(dpy, False);
}
/* XXX: We do not free the command, since make_item_cb gives gives the
* toolkit a pointer for use at some point in the future. The label we assume
* is copied right away and thus can be freed as soon as the item is created.
*
* If we want to catch SIGHUP and rebuild the menu, we are going to need to
* find some way to make sure the toolkit actually frees this stuff, or come
* up with some fantastically ugly way of doing it ourselves. */
static void do_launch_menu(FILE *rc, void *menu, make_item_func make_item_cb)
{
char buf[BUF_SIZE], token[BUF_SIZE], *p;
while (get_rc_line(buf, sizeof buf, rc)) {
p = buf;
while (get_token(&p, token)) {
if (strcmp(token, "menu") == 0) {
void *newmenu;
if (get_token(&p, token)) {
newmenu = make_item_cb(menu, token, NULL);
do_launch_menu(rc, newmenu, make_item_cb);
}
}
if (strcmp(token, "cmd") == 0) {
if (get_token(&p, token)) {
char *label = strdup(token);
if (get_token(&p, token))
make_item_cb(menu, label, strdup(token));
free(label);
}
}
if (strcmp(token, "include") == 0) {
if (get_token(&p, token)) {
FILE *f = fopen(token, "r");
if (f) {
do_launch_menu(f, menu, make_item_cb);
fclose(f);
}
}
}
if (strcmp(token, "end") == 0)
return;
}
}
}
void make_launch_menu(char *rcfile, void *menu, make_item_func make_item_cb)
{
FILE *rc;
if ((rc = open_rc(rcfile, "clientsrc"))) {
do_launch_menu(rc, menu, make_item_cb);
fclose(rc);
} else {
fprintf(stderr, "can't find any rc files\n");
exit(1);
}
}
|