File: menu.c

package info (click to toggle)
aewm 1.3.12-3
  • links: PTS
  • area: main
  • in suites: buster, jessie, jessie-kfreebsd, sid, stretch
  • size: 356 kB
  • sloc: ansic: 2,557; makefile: 77; sh: 20
file content (149 lines) | stat: -rw-r--r-- 4,758 bytes parent folder | download | duplicates (3)
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);
    }
}