4 * this is public domain without any warranties of any kind
7 /* XXX: KEEP AN EYE ON ABBREVIATIONS */
13 #include "app_core_types.h"
15 #include "app_state.c"
17 #define LINUX_KEY_ESC 0x01
18 #define LINUX_KEY_SPACE 0x39
19 /* x11 keycodes do offset linux keycodes by 8 */
20 #define X11_KEYCODE_ESC (LINUX_KEY_ESC + 8)
21 #define X11_KEYCODE_SPACE (LINUX_KEY_SPACE + 8)
31 static struct app_xcb_t app_xcb
;
33 static void app_xcb_win_create(void)
37 xcb_void_cookie_t cookie
;
38 xcb_generic_error_t
*e
;
40 app_xcb
.win_id
= dl_xcb_generate_id(app_xcb
.c
);
41 LOG("0:MAIN:xcb:'%s':connection:%p:screen:%d:root window id:%#x:window id=%#x\n", app_xcb
.disp_env
, app_xcb
.c
, app_xcb
.scr_idx
, app_xcb
.scr
->root
, app_xcb
.win_id
);
43 value_mask
= XCB_CW_BACK_PIXEL
| XCB_CW_EVENT_MASK
;
44 value_list
[0] = app_xcb
.scr
->black_pixel
;
45 value_list
[1] = XCB_EVENT_MASK_KEY_RELEASE
46 | XCB_EVENT_MASK_RESIZE_REDIRECT
;
48 dl_xcb_create_window(app_xcb
.c
, XCB_COPY_FROM_PARENT
, app_xcb
.win_id
,
49 app_xcb
.scr
->root
, 0, 0,
50 APP_WIN_WIDTH
, APP_WIN_HEIGHT
, 0,
51 XCB_WINDOW_CLASS_INPUT_OUTPUT
,
52 app_xcb
.scr
->root_visual
,
53 value_mask
, value_list
);
54 cookie
= dl_xcb_map_window_checked(app_xcb
.c
, app_xcb
.win_id
);
55 LOG("0:MAIN:xcb:'%s':connection:%p:screen:%d:root window id:%#x:window id:%#x:map window request cookie=%#x\n", app_xcb
.disp_env
, app_xcb
.c
, app_xcb
.scr_idx
, app_xcb
.scr
->root
, app_xcb
.win_id
, cookie
);
57 e
= dl_xcb_request_check(app_xcb
.c
, cookie
);
59 LOG("0:MAIN:FATAL:xcb:'%s':connection:%p:screen:%d:root window id:%#x:window id:%#x:unable to map window\n", app_xcb
.disp_env
, app_xcb
.c
, app_xcb
.scr_idx
, app_xcb
.scr
->root
, app_xcb
.win_id
);
62 LOG("0:MAIN:xcb:'%s':connection:%p:screen:%d:root window id:%#x:window id:%#x:window mapped\n", app_xcb
.disp_env
, app_xcb
.c
, app_xcb
.scr_idx
, app_xcb
.scr
->root
, app_xcb
.win_id
);
66 * a disp is n scrs and 1 [set of] keyboard[s] and 1 [set of] mouse[s]
67 * 1 scr could be n monitors
68 * nowdays: usually 1 scr per display
69 * 1 scr has 1 root win
71 static void app_xcb_connect(void)
75 app_xcb
.disp_env
= getenv("DISPLAY");
76 if (app_xcb
.disp_env
== 0 || app_xcb
.disp_env
[0] == 0) {
77 LOG("0:MAIN:no x11 DISPLAY environment variable, exiting\n");
82 app_xcb
.c
= dl_xcb_connect(0, &app_xcb
.scr_idx
); /* should be 0 though */
83 r
= dl_xcb_connection_has_error(app_xcb
.c
);
85 LOG("0:MAIN:FATAL:%d:%s:error while connecting to the x11 server\n", r
, app_xcb
.disp_env
);
88 LOG("0:MAIN:xcb:'%s':connection=%p, default screen index is %d (should be 0)\n", app_xcb
.disp_env
, app_xcb
.c
, app_xcb
.scr_idx
);
91 static void app_xcb_scr_get(void)
93 xcb_screen_iterator_t iter
;
97 app_xcb
.setup
= dl_xcb_get_setup(app_xcb
.c
);
99 scrs_n
= dl_xcb_setup_roots_length(app_xcb
.setup
);
100 LOG("0:MAIN:xcb:'%s':connection:%p:has %d screens (should be 1)\n", app_xcb
.disp_env
, app_xcb
.c
, scrs_n
);
102 iter
= dl_xcb_setup_roots_iterator(app_xcb
.setup
);
107 break; /* no more scr to iterate on */
109 if (i
== app_xcb
.scr_idx
) {
110 app_xcb
.scr
= iter
.data
;
113 dl_xcb_screen_next(&iter
);
115 LOG("0:MAIN:xcb:'%s':connection:%p:screen:%d:root window id:%#x:width=%d pixels\n", app_xcb
.disp_env
, app_xcb
.c
, app_xcb
.scr_idx
, app_xcb
.scr
->root
, app_xcb
.scr
->width_in_pixels
);
116 LOG("0:MAIN:xcb:'%s':connection:%p:screen:%d:root window id:%#x:height=%d pixels\n", app_xcb
.disp_env
, app_xcb
.c
, app_xcb
.scr_idx
, app_xcb
.scr
->root
, app_xcb
.scr
->height_in_pixels
);
117 LOG("0:MAIN:xcb:'%s':connection:%p:screen:%d:root window id:%#x:white pixel=0x%08x\n", app_xcb
.disp_env
, app_xcb
.c
, app_xcb
.scr_idx
, app_xcb
.scr
->root
, app_xcb
.scr
->white_pixel
);
118 LOG("0:MAIN:xcb:'%s':connection:%p:screen:%d:root window id:%#x:black pixel=0x%08x\n", app_xcb
.disp_env
, app_xcb
.c
, app_xcb
.scr_idx
, app_xcb
.scr
->root
, app_xcb
.scr
->black_pixel
);
121 #define MIN_SZ_BIT (1 << 4)
122 #define MAX_SZ_BIT (1 << 5)
124 /* 4 padding dwords */
130 static void app_xcb_wm_hints(void)
134 memset(data
, 0, sizeof(data
));
135 data
[FLAGS
] = MIN_SZ_BIT
| MAX_SZ_BIT
;
136 data
[MIN_WIDTH
] = APP_WIN_WIDTH
;
137 data
[MIN_HEIGHT
] = APP_WIN_HEIGHT
;
138 data
[MAX_WIDTH
] = APP_WIN_WIDTH
;
139 data
[MAX_HEIGHT
] = APP_WIN_HEIGHT
;
141 dl_xcb_change_property(app_xcb
.c
, XCB_PROP_MODE_REPLACE
, app_xcb
.win_id
,
142 XCB_ATOM_WM_NORMAL_HINTS
, XCB_ATOM_WM_SIZE_HINTS
, 32, DWORDS_N
,
154 static void app_xcb_init(void)
158 app_xcb_client_lib_load();
163 app_xcb_win_create();
166 r
= dl_xcb_flush(app_xcb
.c
);
168 LOG("0:MAIN:FATAL:%d:xcb:'%s':connection:%p:screen:%d:root window id:%#x:window id:%#x:unable to flush the connection\n", r
, app_xcb
.disp_env
, app_xcb
.c
, app_xcb
.scr_idx
, app_xcb
.scr
->root
, app_xcb
.win_id
);
171 LOG("0:MAIN:xcb:'%s':connection:%p:connection flushed\n", app_xcb
.disp_env
, app_xcb
.c
);
174 static void app_xcb_evt_key_release(xcb_generic_event_t
*evt
)
176 xcb_key_release_event_t
*key
;
178 key
= (xcb_key_release_event_t
*)evt
;
180 switch (key
->detail
) {
181 case X11_KEYCODE_ESC
:
182 app_state
= app_state_quit
;
184 case X11_KEYCODE_SPACE
:
185 app_do_render
= true;
188 LOG("0:MAIN:xcb:'%s':connection:%p:event:key release:keycode:%#02x\n", app_xcb
.disp_env
, app_xcb
.c
, key
->detail
);
193 static void app_xcb_evt_resz_request(xcb_generic_event_t
*evt
)
195 xcb_resize_request_event_t
*rre
;
198 * the x11 server is not resizing the win, it is asking us to
199 * actually do it (and we won't)
201 rre
= (xcb_resize_request_event_t
*)evt
;
202 LOG("0:MAIN:xcb:'%s':connection:%p:event:resize request:window=%u width=%u,height=%u\n", app_xcb
.disp_env
, app_xcb
.c
, rre
->window
, rre
->width
, rre
->height
);
205 static void app_xcb_evt_handle(xcb_generic_event_t
*evt
)
210 * do not discriminate evts generated by clients using sendevent
211 * requests (note: "client message" evts have always their most
212 * significant bit set)
214 evt_code
= evt
->response_type
& 0x7f;
217 case XCB_KEY_RELEASE
:
218 app_xcb_evt_key_release(evt
);
220 case XCB_RESIZE_REQUEST
:
221 app_xcb_evt_resz_request(evt
);