ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
0
|
// Copyright (C) 2024, Jakob Wakeling |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
1
|
// All rights reserved. |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
2
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
3
|
#include "../draw.h" |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
4
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
5
|
#include <xcb/xcb.h> |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
6
|
#include <xcb/xcb_keysyms.h> |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
7
|
#include <xcb/xproto.h> |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
8
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
9
|
#include <stdint.h> |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
10
|
#include <stdio.h> |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
11
|
#include <stdlib.h> |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
12
|
#include <string.h> |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
13
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
14
|
enum : xcb_atom_t { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
15
|
ATOM_REPAINT = 0x0f00, |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
16
|
}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
17
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
18
|
struct keymap { xcb_keysym_t keysym; draw_key_k key; }; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
19
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
20
|
struct draw_window_s { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
21
|
xcb_connection_t *connection; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
22
|
xcb_screen_t *screen; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
23
|
xcb_window_t window; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
24
|
xcb_key_symbols_t *symbols; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
25
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
26
|
uint32_t x, y, w, h; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
27
|
}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
28
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
29
|
extern const struct keymap keymap[]; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
30
|
extern const size_t keymap_size; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
31
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
32
|
static inline draw_mod_k mod(uint16_t state); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
33
|
static inline draw_key_k keymap_find(draw_window *window, xcb_keycode_t keycode); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
34
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
35
|
int draw_window_init(draw_window **window, int32_t w, int32_t h, const char *title, uint32_t flags) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
36
|
(*window) = calloc(1, sizeof(draw_window)); if ((*window) == NULL) { return -1; } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
37
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
38
|
(*window)->connection = xcb_connect(NULL, NULL); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
39
|
if (xcb_connection_has_error((*window)->connection)) { return -1; } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
40
|
|
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
41
|
xcb_void_cookie_t cookie; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
42
|
xcb_generic_error_t *error = NULL; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
43
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
44
|
(*window)->screen = xcb_setup_roots_iterator(xcb_get_setup((*window)->connection)).data; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
45
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
46
|
(*window)->window = xcb_generate_id((*window)->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
47
|
if ((*window)->window == -1) { xcb_disconnect((*window)->connection); return -1; } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
48
|
|
62f7b77 |
Jakob Wakeling |
2024-03-16 18:12:38 |
49
|
uint32_t mask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
50
|
uint32_t values[4] = { |
62f7b77 |
Jakob Wakeling |
2024-03-16 18:12:38 |
51
|
0, 0, |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
52
|
XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | |
62f7b77 |
Jakob Wakeling |
2024-03-16 18:12:38 |
53
|
XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_EXPOSURE | |
62f7b77 |
Jakob Wakeling |
2024-03-16 18:12:38 |
54
|
XCB_EVENT_MASK_STRUCTURE_NOTIFY, XCB_VISUAL_CLASS_TRUE_COLOR |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
55
|
}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
56
|
|
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
57
|
/**/ |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
58
|
xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator((*window)->screen); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
59
|
xcb_visualtype_t *visual = NULL; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
60
|
|
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
61
|
for (; depth_iter.rem; xcb_depth_next(&depth_iter)) { |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
62
|
if (depth_iter.data->depth != 32) continue; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
63
|
xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth_iter.data); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
64
|
for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) { |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
65
|
visual = visual_iter.data; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
66
|
break; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
67
|
} |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
68
|
if (visual != NULL) break; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
69
|
} |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
70
|
|
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
71
|
if (visual == NULL) { xcb_disconnect((*window)->connection); return -1; } |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
72
|
|
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
73
|
xcb_colormap_t colormap = xcb_generate_id((*window)->connection); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
74
|
cookie = xcb_create_colormap( |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
75
|
(*window)->connection, XCB_COLORMAP_ALLOC_NONE, colormap, (*window)->screen->root, visual->visual_id |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
76
|
); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
77
|
error = xcb_request_check((*window)->connection, cookie); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
78
|
if (error != NULL) { |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
79
|
printf("Error %d while creating colormap\n", error->error_code); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
80
|
free(error); xcb_disconnect((*window)->connection); return -1; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
81
|
} |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
82
|
|
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
83
|
values[3] = colormap; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
84
|
|
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
85
|
cookie = xcb_create_window_checked( |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
86
|
(*window)->connection, 32, (*window)->window, (*window)->screen->root, 0, 0, w, h, 0, |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
87
|
XCB_WINDOW_CLASS_INPUT_OUTPUT, visual->visual_id, mask, values |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
88
|
); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
89
|
error = xcb_request_check((*window)->connection, cookie); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
90
|
if (error != NULL) { |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
91
|
printf("Error %d while creating window\n", error->error_code); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
92
|
free(error); xcb_disconnect((*window)->connection); return -1; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
93
|
} |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
94
|
|
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
95
|
xcb_change_property( |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
96
|
(*window)->connection, XCB_PROP_MODE_REPLACE, (*window)->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
97
|
strlen(title), title |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
98
|
); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
99
|
|
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
100
|
xcb_change_property( |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
101
|
(*window)->connection, XCB_PROP_MODE_REPLACE, (*window)->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
102
|
strlen(title), title |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
103
|
); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
104
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
105
|
(*window)->symbols = xcb_key_symbols_alloc((*window)->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
106
|
(*window)->w = w; (*window)->h = h; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
107
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
108
|
xcb_map_window((*window)->connection, (*window)->window); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
109
|
xcb_flush((*window)->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
110
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
111
|
return 0; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
112
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
113
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
114
|
void draw_window_free(draw_window **window) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
115
|
if (*window == NULL) { return; } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
116
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
117
|
xcb_key_symbols_free((*window)->symbols); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
118
|
xcb_destroy_window((*window)->connection, (*window)->window); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
119
|
xcb_disconnect((*window)->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
120
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
121
|
free(*window); *window = NULL; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
122
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
123
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
124
|
draw_event draw_window_event(draw_window *window) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
125
|
xcb_generic_event_t *_e = xcb_wait_for_event(window->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
126
|
if (_e == NULL) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
127
|
if (draw_debug) { printf("xcb_wait_for_event returned NULL\n"); } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
128
|
return (draw_event){ .kind = DRAW_EVENT_EXIT }; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
129
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
130
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
131
|
draw_event event = {}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
132
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
133
|
/* TODO handle modifiers */ |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
134
|
switch (_e->response_type & ~0x80) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
135
|
case XCB_KEY_PRESS: { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
136
|
xcb_key_press_event_t *e = (xcb_key_press_event_t *)_e; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
137
|
if (draw_debug_verbose) { printf("KeyPress (%d, %d, %d)\n", e->detail, e->event_x, e->event_y); } |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
138
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
139
|
event = (draw_event){ .kind = DRAW_EVENT_KEY, .key = { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
140
|
.code = keymap_find(window, e->detail), .modifiers = mod(e->state), .direction = DRAW_PRESS, |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
141
|
}}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
142
|
} break; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
143
|
case XCB_KEY_RELEASE: { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
144
|
xcb_key_release_event_t *e = (xcb_key_release_event_t *)_e; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
145
|
if (draw_debug_verbose) { printf("KeyRelease (%d, %d, %d)\n", e->detail, e->event_x, e->event_y); } |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
146
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
147
|
event = (draw_event){ .kind = DRAW_EVENT_KEY, .key = { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
148
|
.code = keymap_find(window, e->detail), .modifiers = mod(e->state), .direction = DRAW_RELEASE, |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
149
|
}}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
150
|
} break; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
151
|
case XCB_BUTTON_PRESS: { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
152
|
xcb_button_press_event_t *e = (xcb_button_press_event_t *)_e; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
153
|
if (draw_debug_verbose) { printf("ButtonPress (%d, %d, %d)\n", e->detail, e->event_x, e->event_y); } |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
154
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
155
|
event = (draw_event){ .kind = DRAW_EVENT_MOUSE, .mouse = { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
156
|
.x = e->event_x, .y = e->event_y, .button = e->detail, .modifiers = mod(e->state), |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
157
|
.direction = DRAW_PRESS, |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
158
|
}}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
159
|
} break; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
160
|
case XCB_BUTTON_RELEASE: { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
161
|
xcb_button_release_event_t *e = (xcb_button_release_event_t *)_e; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
162
|
if (draw_debug_verbose) { printf("ButtonRelease (%d, %d, %d)\n", e->detail, e->event_x, e->event_y); } |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
163
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
164
|
event = (draw_event){ .kind = DRAW_EVENT_MOUSE, .mouse = { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
165
|
.x = e->event_x, .y = e->event_y, .button = e->detail, .modifiers = mod(e->state), |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
166
|
.direction = DRAW_RELEASE, |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
167
|
}}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
168
|
} break; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
169
|
case XCB_MOTION_NOTIFY: { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
170
|
xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *)_e; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
171
|
if (draw_debug_verbose) { printf("MotionNotify (%d, %d)\n", e->event_x, e->event_y); } |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
172
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
173
|
event = (draw_event){ .kind = DRAW_EVENT_MOUSE, .mouse = { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
174
|
.x = e->event_x, .y = e->event_y, .button = e->detail, .modifiers = mod(e->state), |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
175
|
.direction = DRAW_REPEAT, |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
176
|
}}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
177
|
} break; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
178
|
case XCB_EXPOSE: { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
179
|
xcb_expose_event_t *e = (xcb_expose_event_t *)_e; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
180
|
if (draw_debug) { printf("Expose (%d, %d, %d, %d)\n", e->x, e->y, e->width, e->height); } |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
181
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
182
|
event = (draw_event){ .kind = DRAW_EVENT_PAINT, .paint = { e->x, e->y, e->width, e->height }}; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
183
|
} break; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
184
|
case XCB_UNMAP_NOTIFY: { |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
185
|
xcb_unmap_notify_event_t *e = (xcb_unmap_notify_event_t *)_e; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
186
|
if (draw_debug) { printf("UnmapNotify\n"); } |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
187
|
event = (draw_event){ .kind = DRAW_EVENT_HIDE }; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
188
|
} break; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
189
|
case XCB_MAP_NOTIFY: { |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
190
|
xcb_map_notify_event_t *e = (xcb_map_notify_event_t *)_e; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
191
|
if (draw_debug) { printf("MapNotify\n"); } |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
192
|
event = (draw_event){ .kind = DRAW_EVENT_SHOW }; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
193
|
} break; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
194
|
case XCB_CONFIGURE_NOTIFY: { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
195
|
xcb_configure_notify_event_t *e = (xcb_configure_notify_event_t *)_e; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
196
|
if (draw_debug) { printf("ConfigureNotify (%d, %d, %d, %d)\n", e->x, e->y, e->width, e->height); } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
197
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
198
|
if (e->width != window->w || e->height != window->h) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
199
|
window->w = e->width; window->h = e->height; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
200
|
event = (draw_event){ .kind = DRAW_EVENT_RESIZE, .resize = { e->width, e->height }}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
201
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
202
|
} break; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
203
|
case XCB_CLIENT_MESSAGE: { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
204
|
xcb_client_message_event_t *e = (xcb_client_message_event_t *)_e; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
205
|
switch (e->type) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
206
|
case ATOM_REPAINT: { |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
207
|
if (draw_debug) { printf("ClientMessage (REPAINT)\n"); } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
208
|
event = (draw_event){ .kind = DRAW_EVENT_PAINT, .paint = { 0, 0, window->w, window->h }}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
209
|
} break; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
210
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
211
|
} break; |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
212
|
default: { if (draw_debug) { |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
213
|
printf("Unhandled X11 event: %d ", _e->response_type & ~0x80); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
214
|
printf("Sequence: %u ", _e->sequence); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
215
|
printf("Full sequence: %u ", _e->full_sequence); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
216
|
printf("Pad0: %u ", _e->pad0); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
217
|
printf("Pad: %u\n", *_e->pad); |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
218
|
}} break; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
219
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
220
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
221
|
free(_e); return event; |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
222
|
} |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
223
|
|
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
224
|
void draw_window_set_title(draw_window *window, const char *title) { |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
225
|
xcb_change_property( |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
226
|
window->connection, XCB_PROP_MODE_REPLACE, window->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen(title), |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
227
|
title |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
228
|
); |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
229
|
xcb_flush(window->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
230
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
231
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
232
|
void draw_window_repaint(draw_window *window) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
233
|
xcb_client_message_event_t e = { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
234
|
.response_type = XCB_CLIENT_MESSAGE, .format = 32, .window = window->window, .type = ATOM_REPAINT, |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
235
|
.data.data32 = {} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
236
|
}; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
237
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
238
|
xcb_send_event(window->connection, 0, window->window, XCB_EVENT_MASK_NO_EVENT, (const char *)&e); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
239
|
xcb_flush(window->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
240
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
241
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
242
|
int draw_window_draw(draw_window *w, point dp, draw_buffer *buf, rect br) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
243
|
if (w == NULL) { return 1; } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
244
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
245
|
xcb_gcontext_t gc = xcb_generate_id(w->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
246
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
247
|
xcb_create_gc(w->connection, gc, w->window, 0, NULL); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
248
|
xcb_put_image( |
0db5818 |
Jakob Wakeling |
2024-03-10 23:32:36 |
249
|
w->connection, XCB_IMAGE_FORMAT_Z_PIXMAP, w->window, gc, br.w, br.h, dp.x, dp.y, 0, 32, |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
250
|
(buf->bounds.w * buf->bounds.h) * sizeof (*buf->buf), (uint8_t *)buf->buf |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
251
|
); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
252
|
xcb_free_gc(w->connection, gc); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
253
|
xcb_flush(w->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
254
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
255
|
return 0; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
256
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
257
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
258
|
void draw_window_clear(draw_window *w, uint32_t colour) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
259
|
if (w == NULL) { return; } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
260
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
261
|
xcb_gcontext_t gc = xcb_generate_id(w->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
262
|
xcb_create_gc(w->connection, gc, w->window, 0, NULL); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
263
|
xcb_change_gc(w->connection, gc, XCB_GC_FOREGROUND, (uint32_t[]){colour}); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
264
|
xcb_poly_fill_rectangle(w->connection, w->window, gc, 1, (xcb_rectangle_t[]){{ |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
265
|
.x = 0, .y = 0, .width = w->w, .height = w->h, |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
266
|
}}); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
267
|
xcb_free_gc(w->connection, gc); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
268
|
xcb_flush(w->connection); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
269
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
270
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
271
|
static inline draw_mod_k mod(uint16_t state) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
272
|
draw_mod_k mod = 0; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
273
|
mod |= ((state & XCB_MOD_MASK_SHIFT) != 0) * DRAW_MOD_SHIFT; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
274
|
mod |= ((state & XCB_MOD_MASK_CONTROL) != 0) * DRAW_MOD_CONTROL; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
275
|
mod |= ((state & XCB_MOD_MASK_1) != 0) * DRAW_MOD_ALT; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
276
|
mod |= ((state & XCB_MOD_MASK_4) != 0) * DRAW_MOD_SUPER; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
277
|
mod |= ((state & XCB_MOD_MASK_LOCK) != 0) * DRAW_MOD_CAPS_LOCK; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
278
|
mod |= ((state & XCB_MOD_MASK_2) != 0) * DRAW_MOD_NUM_LOCK; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
279
|
return mod; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
280
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
281
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
282
|
static inline draw_key_k keymap_find(draw_window *window, xcb_keycode_t keycode) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
283
|
xcb_keysym_t keysym = xcb_key_symbols_get_keysym(window->symbols, keycode, 0); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
284
|
for (size_t i = 0; i < keymap_size; i += 1) { if (keymap[i].keysym == keysym) { return keymap[i].key; }} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
285
|
return DRAW_KEY_UNKNOWN; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
286
|
} |
|
|
|
287
|
|