]> git.sur5r.net Git - i3/i3/blob - i3-config-wizard/xcb.c
move strndup to libi3
[i3/i3] / i3-config-wizard / xcb.c
1 /*
2  * vim:ts=8:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  *
6  * © 2009 Michael Stapelberg and contributors
7  *
8  * See file LICENSE for license information.
9  *
10  */
11 #include <stdint.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <err.h>
16
17 #include <xcb/xcb.h>
18 #include <xcb/xcb_keysyms.h>
19
20 #include <X11/keysym.h>
21
22 #include "xcb.h"
23
24 extern xcb_window_t root;
25 unsigned int xcb_numlock_mask;
26
27 /*
28  * Returns the mask for Mode_switch (to be used for looking up keysymbols by
29  * keycode).
30  *
31  */
32 uint32_t get_mod_mask(xcb_connection_t *conn, uint32_t keycode) {
33         xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(conn);
34
35         xcb_get_modifier_mapping_reply_t *modmap_r;
36         xcb_keycode_t *modmap, kc;
37         xcb_keycode_t *modeswitchcodes = xcb_key_symbols_get_keycode(symbols, keycode);
38         if (modeswitchcodes == NULL)
39                 return 0;
40
41         modmap_r = xcb_get_modifier_mapping_reply(conn, xcb_get_modifier_mapping(conn), NULL);
42         modmap = xcb_get_modifier_mapping_keycodes(modmap_r);
43
44         for (int i = 0; i < 8; i++)
45                 for (int j = 0; j < modmap_r->keycodes_per_modifier; j++) {
46                         kc = modmap[i * modmap_r->keycodes_per_modifier + j];
47                         for (xcb_keycode_t *ktest = modeswitchcodes; *ktest; ktest++) {
48                                 if (*ktest != kc)
49                                         continue;
50
51                                 free(modeswitchcodes);
52                                 free(modmap_r);
53                                 return (1 << i);
54                         }
55                 }
56
57         return 0;
58 }
59
60 /*
61  * Opens the window we use for input/output and maps it
62  *
63  */
64 xcb_window_t open_input_window(xcb_connection_t *conn, uint32_t width, uint32_t height) {
65         xcb_window_t win = xcb_generate_id(conn);
66         //xcb_cursor_t cursor_id = xcb_generate_id(conn);
67
68 #if 0
69         /* Use the default cursor (left pointer) */
70         if (cursor > -1) {
71                 i3Font *cursor_font = load_font(conn, "cursor");
72                 xcb_create_glyph_cursor(conn, cursor_id, cursor_font->id, cursor_font->id,
73                                 XCB_CURSOR_LEFT_PTR, XCB_CURSOR_LEFT_PTR + 1,
74                                 0, 0, 0, 65535, 65535, 65535);
75         }
76 #endif
77
78         uint32_t mask = 0;
79         uint32_t values[3];
80
81         mask |= XCB_CW_BACK_PIXEL;
82         values[0] = 0;
83
84         mask |= XCB_CW_EVENT_MASK;
85         values[1] = XCB_EVENT_MASK_EXPOSURE |
86                     XCB_EVENT_MASK_BUTTON_PRESS;
87
88         xcb_create_window(conn,
89                           XCB_COPY_FROM_PARENT,
90                           win, /* the window id */
91                           root, /* parent == root */
92                           490, 297, width, height, /* dimensions */
93                           0, /* border = 0, we draw our own */
94                           XCB_WINDOW_CLASS_INPUT_OUTPUT,
95                           XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */
96                           mask,
97                           values);
98
99 #if 0
100         if (cursor > -1)
101                 xcb_change_window_attributes(conn, result, XCB_CW_CURSOR, &cursor_id);
102 #endif
103
104         /* Map the window (= make it visible) */
105         xcb_map_window(conn, win);
106
107         return win;
108 }
109
110 /*
111  * Returns the ID of the font matching the given pattern and stores the height
112  * of the font (in pixels) in *font_height. die()s if no font matches.
113  *
114  */
115 int get_font_id(xcb_connection_t *conn, char *pattern, int *font_height) {
116         xcb_void_cookie_t font_cookie;
117         xcb_list_fonts_with_info_cookie_t info_cookie;
118
119         /* Send all our requests first */
120         int result;
121         result = xcb_generate_id(conn);
122         font_cookie = xcb_open_font_checked(conn, result, strlen(pattern), pattern);
123         info_cookie = xcb_list_fonts_with_info(conn, 1, strlen(pattern), pattern);
124
125         xcb_generic_error_t *error = xcb_request_check(conn, font_cookie);
126         if (error != NULL) {
127                 fprintf(stderr, "ERROR: Could not open font: %d\n", error->error_code);
128                 exit(1);
129         }
130
131         /* Get information (height/name) for this font */
132         xcb_list_fonts_with_info_reply_t *reply = xcb_list_fonts_with_info_reply(conn, info_cookie, NULL);
133         if (reply == NULL)
134                 errx(1, "Could not load font \"%s\"\n", pattern);
135
136         *font_height = reply->font_ascent + reply->font_descent;
137
138         return result;
139 }
140
141 /*
142  * Finds out which modifier mask is the one for numlock, as the user may change this.
143  *
144  */
145 void xcb_get_numlock_mask(xcb_connection_t *conn) {
146     xcb_key_symbols_t *keysyms;
147     xcb_get_modifier_mapping_cookie_t cookie;
148     xcb_get_modifier_mapping_reply_t *reply;
149     xcb_keycode_t *modmap;
150     int mask, i;
151     const int masks[8] = { XCB_MOD_MASK_SHIFT,
152                            XCB_MOD_MASK_LOCK,
153                            XCB_MOD_MASK_CONTROL,
154                            XCB_MOD_MASK_1,
155                            XCB_MOD_MASK_2,
156                            XCB_MOD_MASK_3,
157                            XCB_MOD_MASK_4,
158                            XCB_MOD_MASK_5 };
159
160     /* Request the modifier map */
161     cookie = xcb_get_modifier_mapping_unchecked(conn);
162
163     /* Get the keysymbols */
164     keysyms = xcb_key_symbols_alloc(conn);
165
166     if ((reply = xcb_get_modifier_mapping_reply(conn, cookie, NULL)) == NULL) {
167         xcb_key_symbols_free(keysyms);
168         return;
169     }
170
171     modmap = xcb_get_modifier_mapping_keycodes(reply);
172
173     /* Get the keycode for numlock */
174 #ifdef OLD_XCB_KEYSYMS_API
175     xcb_keycode_t numlock = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK);
176 #else
177     /* For now, we only use the first keysymbol. */
178     xcb_keycode_t *numlock_syms = xcb_key_symbols_get_keycode(keysyms, XCB_NUM_LOCK);
179     if (numlock_syms == NULL)
180         return;
181     xcb_keycode_t numlock = *numlock_syms;
182     free(numlock_syms);
183 #endif
184
185     /* Check all modifiers (Mod1-Mod5, Shift, Control, Lock) */
186     for (mask = 0; mask < 8; mask++)
187         for (i = 0; i < reply->keycodes_per_modifier; i++)
188             if (modmap[(mask * reply->keycodes_per_modifier) + i] == numlock)
189                 xcb_numlock_mask = masks[mask];
190
191     xcb_key_symbols_free(keysyms);
192     free(reply);
193 }
194