Last active
March 20, 2021 09:01
-
-
Save andr1972/c629924b60d117ec5c31 to your computer and use it in GitHub Desktop.
XCB loop and timer event
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CodeBlocks config: | |
Build options->Linker settings: rt xcb | |
Properties->Build targets: GUI application |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//xcb loop: //http://xcb.freedesktop.org/tutorial/fonts/ | |
//timer: https://groups.google.com/forum/#!topic/comp.os.linux.development.apps/p8GKe4frd0k | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <csignal> | |
#include <iostream> | |
#include <inttypes.h> | |
#include <xcb/xcb.h> | |
#include <xcb/xproto.h> | |
//xcb_event.h | |
#define XCB_EVENT_RESPONSE_TYPE_MASK (0x7f) | |
#define XCB_EVENT_RESPONSE_TYPE(e) (e->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) | |
#define XCB_EVENT_SENT(e) (e->response_type & ~XCB_EVENT_RESPONSE_TYPE_MASK) | |
#define WIDTH 300 | |
#define HEIGHT 100 | |
using namespace std; | |
char* text_message = "abcdef"; | |
xcb_connection_t* connection; | |
xcb_screen_t* screen; | |
xcb_window_t window; | |
static xcb_gcontext_t getFontGC(xcb_connection_t* c, | |
xcb_screen_t* screen, | |
xcb_window_t window, | |
const char* font_name); | |
static void testCookie(xcb_void_cookie_t cookie, | |
xcb_connection_t* connection, | |
char* errMessage) | |
{ | |
xcb_generic_error_t* error = xcb_request_check(connection, cookie); | |
if (error) { | |
fprintf(stderr, "ERROR: %s : %" PRIu8 "\n", errMessage, error->error_code); | |
xcb_disconnect(connection); | |
exit(-1); | |
} | |
} | |
static void drawText(xcb_connection_t* connection, | |
xcb_screen_t* screen, | |
xcb_window_t window, | |
int16_t x1, | |
int16_t y1, | |
const char* label) | |
{ | |
/* get graphics context */ | |
xcb_gcontext_t gc = getFontGC(connection, screen, window, "fixed"); | |
/* draw the text */ | |
xcb_void_cookie_t textCookie = xcb_image_text_8_checked(connection, | |
strlen(label), | |
window, | |
gc, | |
x1, y1, | |
label); | |
testCookie(textCookie, connection, "can't paste text"); | |
/* free the gc */ | |
xcb_void_cookie_t gcCookie = xcb_free_gc(connection, gc); | |
testCookie(gcCookie, connection, "can't free gc"); | |
} | |
static xcb_gcontext_t | |
getFontGC(xcb_connection_t* connection, | |
xcb_screen_t* screen, | |
xcb_window_t window, | |
const char* font_name) | |
{ | |
/* get font */ | |
xcb_font_t font = xcb_generate_id(connection); | |
xcb_void_cookie_t fontCookie = xcb_open_font_checked(connection, | |
font, | |
strlen(font_name), | |
font_name); | |
testCookie(fontCookie, connection, "can't open font"); | |
/* create graphics context */ | |
xcb_gcontext_t gc = xcb_generate_id(connection); | |
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT; | |
uint32_t value_list[3] = { screen->black_pixel, | |
screen->white_pixel, | |
font }; | |
xcb_void_cookie_t gcCookie = xcb_create_gc_checked(connection, | |
gc, | |
window, | |
mask, | |
value_list); | |
testCookie(gcCookie, connection, "can't create gc"); | |
/* close font */ | |
fontCookie = xcb_close_font_checked(connection, font); | |
testCookie(fontCookie, connection, "can't close font"); | |
return gc; | |
} | |
void invalidate() | |
{ | |
xcb_expose_event_t invalidate_event; | |
invalidate_event.window = window; | |
invalidate_event.response_type = XCB_EXPOSE; | |
invalidate_event.x = 0; | |
invalidate_event.y = 0; | |
invalidate_event.width = WIDTH; | |
invalidate_event.height = HEIGHT; | |
xcb_send_event(connection, false, window, XCB_EVENT_MASK_EXPOSURE, (char*)&invalidate_event); | |
xcb_flush(connection); | |
} | |
void handler(sigval val) | |
{ | |
text_message = "111111"; | |
invalidate(); | |
} | |
timer_t tid; | |
void set_timer() | |
{ | |
sigevent sig; | |
sig.sigev_notify = SIGEV_THREAD; | |
sig.sigev_notify_function = handler; | |
sig.sigev_notify_attributes = NULL; | |
sig.sigev_value.sival_ptr = &tid; | |
timer_create(CLOCK_REALTIME, &sig, &tid); | |
itimerspec t = { { 1, 0 }, { 1, 0 } }; | |
timer_settime(tid, 0, &t, 0); | |
} | |
void event_loop() | |
{ | |
xcb_generic_event_t* event; | |
int done = 0; | |
while (!done && (event = xcb_wait_for_event(connection))) { | |
switch (event->response_type & XCB_EVENT_RESPONSE_TYPE_MASK) { | |
case XCB_EXPOSE: /* draw or redraw the window */ | |
drawText(connection, | |
screen, | |
window, | |
10, HEIGHT - 10, | |
text_message); | |
xcb_flush(connection); | |
break; | |
case XCB_KEY_RELEASE: /* exit on key release */ | |
done = 1; | |
break; | |
} | |
free(event); | |
} | |
} | |
int main() | |
{ | |
set_timer(); | |
int screenNum; | |
connection = xcb_connect(NULL, &screenNum); | |
if (!connection) { | |
fprintf(stderr, "ERROR: can't connect to an X server\n"); | |
return -1; | |
} | |
/* get the current screen */ | |
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(xcb_get_setup(connection)); | |
// we want the screen at index screenNum of the iterator | |
for (int i = 0; i < screenNum; ++i) { | |
xcb_screen_next(&iter); | |
} | |
screen = iter.data; | |
if (!screen) { | |
fprintf(stderr, "ERROR: can't get the current screen\n"); | |
xcb_disconnect(connection); | |
return -1; | |
} | |
/* create the window */ | |
window = xcb_generate_id(connection); | |
uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; | |
uint32_t values[2]; | |
values[0] = screen->white_pixel; | |
values[1] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION; | |
xcb_void_cookie_t windowCookie = xcb_create_window_checked(connection, | |
screen->root_depth, | |
window, screen->root, | |
20, 200, | |
WIDTH, HEIGHT, | |
0, XCB_WINDOW_CLASS_INPUT_OUTPUT, | |
screen->root_visual, | |
mask, values); | |
testCookie(windowCookie, connection, "can't create window"); | |
xcb_void_cookie_t mapCookie = xcb_map_window_checked(connection, window); | |
testCookie(mapCookie, connection, "can't map window"); | |
xcb_flush(connection); // make sure window is drawn | |
event_loop(); | |
xcb_disconnect(connection); | |
timer_delete(tid); | |
exit(EXIT_SUCCESS); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment