int main_loop(Display *display, xcb_connection_t *connection, xcb_screen_t *screen, xcb_window_t window, GLXDrawable drawable) { int running = 1; while (running) { /* Wait for event */ xcb_generic_event_t *event = xcb_wait_for_event(connection); if (!event) { fprintf(stderr, "i/o error in xcb_wait_for_event\n"); return -1; } switch(event->response_type & ~0x80) { case XCB_KEY_PRESS: /* Quit on key press */ running = 0; break; case XCB_EXPOSE: /* Handle expose event, draw and swap buffers */ draw(connection, screen, window); glXSwapBuffers(display, drawable); break; default: break; } free(event); } return 0; }
/// X event loop void *event_loop(void*) { xcb_generic_event_t *event; // wait for X events and process them while((event = xcb_wait_for_event(con))) { switch(event->response_type & ~0x80) { case XCB_EXPOSE: { xcb_expose_event_t *expose_event = reinterpret_cast<xcb_expose_event_t*>(event); // ignore the expose event, if there are more waiting. if(!expose_event->count && window && window->get_window_id() == expose_event->window) window->redraw(); break; } case XCB_CONFIGURE_NOTIFY: { xcb_configure_notify_event_t *configure_notify_event = reinterpret_cast<xcb_configure_notify_event_t*>(event); if(window && window->get_window_id() == configure_notify_event->window) window->resize(configure_notify_event->width, configure_notify_event->height); break; } default: // ignore break; } free(event); } pthread_exit(0); }
void event_handler(xcb_connection_t *c, xcb_drawable_t root) { xcb_generic_event_t *e; for (;;) { e = xcb_wait_for_event (c); switch (e->response_type & ~0x80) { case XCB_CONFIGURE_NOTIFY: printf("XCB_CONFIGURE_NOTIFY\n"); break; case XCB_BUTTON_PRESS: //xcb_button_press_event_t *press = (xcb_button_press_event_t *)e; printf("XCB_BUTTON_PRESS\n"); break; case XCB_KEY_PRESS: printf("XCB_KEY_PRESS\n"); break; default: break; } free (e); } }
int run(config_t* config, key_handler_t key_handler) { int default_screen; xcb_connection_t* c = xcb_connect(NULL, &default_screen); if(xcb_connection_has_error(c)) { fprintf(stderr, "Cannot open display %s\n", getenv("DISPLAY") ? getenv("DISPLAY") : "<NULL>"); return -1; } xcb_screen_t* screen; if(!(screen = xcb_aux_get_screen(c, default_screen))) { fprintf(stderr, "Cannot obtain default screen.\n"); return -1; } context_t context = { config, key_handler }; xcb_event_handlers_t eh; memset(&eh, 0, sizeof(xcb_event_handlers_t)); xcb_event_handlers_init(c, &eh); xcb_event_set_key_press_handler(&eh, handle_keypress, &context); xcb_void_cookie_t* cookies = alloca(sizeof(xcb_void_cookie_t) * config->count); if(!cookies) return -1; int i; for(i = 0; i < config->count; ++i) cookies[i] = xcb_grab_key(c, true, screen->root, config->keys[i].is_alt ? XCB_MOD_MASK_1 : 0, config->keys[i].keysym, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); for(i = 0; i < config->count; ++i) { xcb_generic_error_t* e = xcb_request_check(c, cookies[i]); if(e) { fprintf(stderr, "WARNING: unable to grab key: %d\n", e->error_code); free(e); } } xcb_generic_event_t* e; while((e = xcb_wait_for_event(c))) { xcb_event_handle(&eh, e); free(e); } return 0; }
/** * \brief The main event loop to process window messages. * * \param [in] arg The clipboard context. * * This thread will run indefinitely until the clipboard context's window * is destroyed. It *must* receive a DestroyNotify message to end. */ static void *x11_event_loop(void *arg) { clipboard_c *cb = (clipboard_c *)arg; xcb_generic_event_t *e; while ((e = xcb_wait_for_event(cb->xc))) { if (e->response_type == 0) { /* I think this cast is appropriate... */ xcb_generic_error_t *err = (xcb_generic_error_t *) e; fprintf(stderr, "x11_event_loop: [Warn] Received X11 error: %d\n", err->error_code); free(e); /* XCB: Do not use custom allocators */ continue; } switch (e->response_type & ~0x80) { case XCB_DESTROY_NOTIFY: { xcb_destroy_notify_event_t *evt = (xcb_destroy_notify_event_t *)e; if (evt->window == cb->xw) { free(e); /* XCB: Do not use custom allocators */ return NULL; } } break; case XCB_SELECTION_CLEAR: { x11_clear_selection(cb, (xcb_selection_clear_event_t *)e); } break; case XCB_SELECTION_NOTIFY: { x11_retrieve_selection(cb, (xcb_selection_notify_event_t *)e); } break; case XCB_SELECTION_REQUEST: { xcb_selection_request_event_t *req = (xcb_selection_request_event_t *)e; xcb_selection_notify_event_t notify = {0}; notify.response_type = XCB_SELECTION_NOTIFY; notify.time = XCB_CURRENT_TIME; notify.requestor = req->requestor; notify.selection = req->selection; notify.target = req->target; notify.property = x11_transmit_selection(cb, req) ? req->property : XCB_NONE; xcb_send_event(cb->xc, false, req->requestor, XCB_EVENT_MASK_PROPERTY_CHANGE, (char *)¬ify); xcb_flush(cb->xc); } break; case XCB_PROPERTY_NOTIFY: { } break; default: { /* Ignore unknown messages */ } } free(e); /* XCB: Do not use custom allocators */ } fprintf(stderr, "x11_event_loop: [Warn] xcb_wait_for_event returned NULL\n"); return NULL; }
void xcb_event_wait_for_event_loop(xcb_event_handlers_t *evenths) { xcb_generic_event_t *event; while((event = xcb_wait_for_event(evenths->c))) { xcb_event_handle(evenths, event); free(event); } }
int main(int argc, char *argv[]) { /* TODO: Accept DISPLAY environment or --display arguments */ xcb_connection_t *conn = xcb_connect(NULL, NULL); towel_window_t *win = NULL; for (;;) { if (win == NULL) { win = towel_create_window(conn); towel_window_hide_cursor(win); } sleep(CHECK_PERIOD); towel_window_update_working_time(win, CHECK_PERIOD); if (win->idle_time > REST_TIME) win->working_time = 0; /* TODO: option processing */ if (win->working_time > WORKING_TIME) { time_t prev = time(NULL); towel_window_map(win); xcb_flush(conn); for (;;) { xcb_generic_event_t *event = xcb_wait_for_event(conn); if ((event->response_type & ~0x80) == XCB_EXPOSE) { #if !DEBUG towel_window_grab_input(win); #endif towel_window_render_time(win, REST_TIME); xcb_flush(conn); break; } free(event); } for (;;) { int delta = time(NULL) - prev; towel_window_render_time(win, REST_TIME - delta); xcb_flush(conn); if (delta >= REST_TIME) { towel_window_unmap(win); towel_window_destroy(win); win = NULL; xcb_flush(conn); break; } sleep(1); } } } if (win) towel_window_destroy(win); xcb_disconnect(conn); return EXIT_SUCCESS; }
int main(void) { xcb_connection_t *conn; xcb_screen_t *root; xcb_window_t window; uint32_t mask; uint32_t values[5]; xcb_generic_event_t *event; struct xamine_context *ctx; struct xamine_conversation *conversation; conn = xcb_connect(NULL, NULL); root = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; window = xcb_generate_id(conn); mask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_BACKING_STORE | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; values[0] = root->white_pixel; values[1] = root->black_pixel; values[2] = XCB_BACKING_STORE_ALWAYS; values[3] = 0; values[4] = AllEventsMask; xcb_create_window(conn, 0, window, root->root, 0, 0, 256, 256, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT, root->root_visual, mask, values); xcb_map_window(conn, window); xcb_flush(conn); ctx = xamine_context_new(0); conversation = xamine_conversation_new(ctx, 0); while ((event = xcb_wait_for_event(conn)) != NULL) { struct xamine_item *item = xamine_examine(conversation, XAMINE_RESPONSE, event, 32); free(event); print_tree(item, 0); /* Exit on ESC. */ if (strcmp(item->definition->name, "KeyPress") == 0 && item->child->next->u.unsigned_value == 9) { xamine_item_free(item); break; } xamine_item_free(item); } xamine_conversation_unref(conversation); xamine_context_unref(ctx); xcb_disconnect(conn); xmlCleanupParser(); return 0; }
/* * This function is called from a fork()ed child and will raise the i3lock * window when the window is obscured, even when the main i3lock process is * blocked due to PAM. * */ static void raise_loop(xcb_window_t window) { xcb_connection_t *conn; xcb_generic_event_t *event; int screens; if ((conn = xcb_connect(NULL, &screens)) == NULL || xcb_connection_has_error(conn)) errx(EXIT_FAILURE, "Cannot open display\n"); /* We need to know about the window being obscured or getting destroyed. */ xcb_change_window_attributes(conn, window, XCB_CW_EVENT_MASK, (uint32_t[]){XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY}); xcb_flush(conn); DEBUG("Watching window 0x%08x\n", window); while ((event = xcb_wait_for_event(conn)) != NULL) { if (event->response_type == 0) { xcb_generic_error_t *error = (xcb_generic_error_t *)event; DEBUG("X11 Error received! sequence 0x%x, error_code = %d\n", error->sequence, error->error_code); free(event); continue; } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); DEBUG("Read event of type %d\n", type); switch (type) { case XCB_VISIBILITY_NOTIFY: handle_visibility_notify( conn, (xcb_visibility_notify_event_t *)event); break; case XCB_UNMAP_NOTIFY: DEBUG("UnmapNotify for 0x%08x\n", (((xcb_unmap_notify_event_t *)event)->window)); if (((xcb_unmap_notify_event_t *)event)->window == window) exit(EXIT_SUCCESS); break; case XCB_DESTROY_NOTIFY: DEBUG("DestroyNotify for 0x%08x\n", (((xcb_destroy_notify_event_t *)event)->window)); if (((xcb_destroy_notify_event_t *)event)->window == window) exit(EXIT_SUCCESS); break; default: DEBUG("Unhandled event type %d\n", type); break; } free(event); } }
void ShellXcb::loop_wait() { while (true) { xcb_generic_event_t *ev = xcb_wait_for_event(c_); if (!ev) continue; handle_event(ev); free(ev); if (quit_) break; acquire_back_buffer(); present_back_buffer(); } }
/** Events loop */ void recv_events() { xcb_generic_event_t *e; unsigned int type; while ((e = xcb_wait_for_event(nil_.con))) { type = e->response_type & ~0x80; if (type < NIL_LEN(HANDLERS_) && HANDLERS_[type] != 0) { (*HANDLERS_[type])(e); } else { NIL_LOG("event: unknown type %u", type); } /* Free the Generic Event */ free(e); } }
void NGBMainLoop() { while((event = xcb_wait_for_event(con))) { switch(event->response_type & ~0x80) { case XCB_EXPOSE: //xcb_poly_point(con, XCB_COORD_MODE_ORIGIN, win, foreground, 4, points); DisplayFunc(); xcb_flush(con); break; default: break; } } }
void event_loop(xcb_window_t window, xcb_gcontext_t graphics_context) { xcb_generic_event_t *event; xcb_rectangle_t r = { 20, 20, 60, 60 }; while(event = xcb_wait_for_event(connection)) { switch(event->response_type) { case XCB_EXPOSE: xcb_poly_fill_rectangle(connection, window, graphics_context, 1, &r); xcb_flush(connection); break; case XCB_KEY_PRESS: return; } } }
void EventReader::run() { Qt::MouseButtons buttons; xcb_generic_event_t *event; while (running.load() && (event = xcb_wait_for_event(m_hooks->connection()))) { uint response_type = event->response_type & ~0x80; switch (response_type) { case XCB_BUTTON_PRESS: { xcb_button_press_event_t *press = (xcb_button_press_event_t *)event; QPoint p(press->event_x, press->event_y); buttons = (buttons & ~0x7) | translateMouseButtons(press->state); buttons |= translateMouseButton(press->detail); QWindowSystemInterface::handleMouseEvent(0, press->time, p, p, buttons); break; } case XCB_BUTTON_RELEASE: { xcb_button_release_event_t *release = (xcb_button_release_event_t *)event; QPoint p(release->event_x, release->event_y); buttons = (buttons & ~0x7) | translateMouseButtons(release->state); buttons &= ~translateMouseButton(release->detail); QWindowSystemInterface::handleMouseEvent(0, release->time, p, p, buttons); break; } case XCB_MOTION_NOTIFY: { xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)event; QPoint p(motion->event_x, motion->event_y); QWindowSystemInterface::handleMouseEvent(0, motion->time, p, p, buttons); break; } case XCB_CLIENT_MESSAGE: { xcb_client_message_event_t *client = (xcb_client_message_event_t *) event; const xcb_atom_t *atoms = m_hooks->atoms(); if (client->format == 32 && client->type == atoms[Atoms::WM_PROTOCOLS] && client->data.data32[0] == atoms[Atoms::WM_DELETE_WINDOW]) { QWindow *window = m_hooks->platformWindow() ? m_hooks->platformWindow()->window() : 0; if (window) QWindowSystemInterface::handleCloseEvent(window); } break; } default: break; } } }
void handle_events(void) { int i, wn; xcb_window_t *wc, wid = 0; xcb_generic_event_t *e; xcb_create_notify_event_t *ec; /* * We need to get notifed of window creations, no matter what, because * we need to register the event mask on all newly created windows */ register_events(scr->root, XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY); if (mask & XCB_EVENT_MASK_BUTTON_PRESS) { xcb_grab_button(conn, 0, scr->root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 1, XCB_NONE); } /* register the events on all mapped windows */ wn = get_windows(conn, scr->root, &wc); for (i=0; i<wn; i++) register_events(wc[i], mask); xcb_flush(conn); for(;;) { e = xcb_wait_for_event(conn); switch (e->response_type & ~0x80) { case XCB_CREATE_NOTIFY: ec = (xcb_create_notify_event_t*)e; register_events(ec->window, mask); default: wid = get_window_id(e); } if (wid > 0) { printf("%d:0x%08x\n", e->response_type, wid); fflush(stdout); } } }
int main(void) { xcb_connection_t *dpy = xcb_connect(NULL, NULL); if (dpy == NULL) { fprintf(stderr, "Can't connect to X.\n"); return EXIT_FAILURE; } xcb_atom_t WM_PROTOCOLS, WM_DELETE_WINDOW; if (!get_atom(dpy, "WM_PROTOCOLS", &WM_PROTOCOLS) || !get_atom(dpy, "WM_DELETE_WINDOW", &WM_DELETE_WINDOW)) { fprintf(stderr, "Can't get required atoms.\n"); xcb_disconnect(dpy); return EXIT_FAILURE; } xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data; if (screen == NULL) { fprintf(stderr, "Can't get current screen.\n"); xcb_disconnect(dpy); return EXIT_FAILURE; } xcb_window_t win = xcb_generate_id(dpy); uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; uint32_t values[] = {0xff111111, XCB_EVENT_MASK_EXPOSURE}; xcb_create_window(dpy, XCB_COPY_FROM_PARENT, win, screen->root, 0, 0, 320, 240, 2, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, mask, values); xcb_icccm_set_wm_class(dpy, win, sizeof(TEST_WINDOW_IC), TEST_WINDOW_IC); xcb_map_window(dpy, win); xcb_flush(dpy); xcb_generic_event_t *evt; bool running = true; while (running && (evt = xcb_wait_for_event(dpy)) != NULL) { uint8_t rt = XCB_EVENT_RESPONSE_TYPE(evt); if (rt == XCB_CLIENT_MESSAGE) { xcb_client_message_event_t *cme = (xcb_client_message_event_t *) evt; if (cme->type == WM_PROTOCOLS && cme->data.data32[0] == WM_DELETE_WINDOW) { running = false; } } else if (rt == XCB_EXPOSE) { render_text(dpy, win, 12, 24); } free(evt); } xcb_destroy_window(dpy, win); xcb_disconnect(dpy); return EXIT_SUCCESS; }
int main() { xcb_connection_t *conn = xcb_connect(NULL, NULL); xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; xcb_drawable_t win = screen->root; xcb_gcontext_t fg = xcb_generate_id(conn); uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; uint32_t values[2] = { screen->black_pixel, 0 }; xcb_create_gc(conn, fg, win, mask, values); win = xcb_generate_id(conn); mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; values[0] = screen->white_pixel; values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS; xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, screen->root, x, y, w, h, bw, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, values); xcb_map_window(conn, win); xcb_flush(conn); xcb_generic_event_t *event; // xcb_poll_for_event does not block, so this will only catch the EXPOSE event then die out. // If we used xcb_wait_for_event, we'd block, thus continuing the loop and would actually // have a window to receive a possible XCB_BUTTON_PRESS. while ((event = xcb_wait_for_event(conn))) { switch (event->response_type & ~0x80) { case XCB_EXPOSE: printf("Expose event\n"); xcb_flush(conn); break; case XCB_BUTTON_PRESS: printf("Button press\n"); xcb_flush(conn); break; default: printf("Some otherrr event\n"); break; } free(event); } return 0; }
void event_loop(xcb_window_t window, xcb_gcontext_t graphics_context, xcb_pixmap_t pixmap) { xcb_generic_event_t *event; while(event = xcb_wait_for_event(connection)) { switch(event->response_type) { case XCB_EXPOSE: xcb_copy_area(connection, pixmap, window, graphics_context, 0, 0, 0, 0, neko_width, neko_height); xcb_flush(connection); break; case XCB_KEY_PRESS: return; } } }
void event_loop() { xcb_generic_event_t *e; while ((e = xcb_wait_for_event (c))) { switch (e->response_type & ~0x80) { /* ESC to exit */ case XCB_KEY_PRESS: { xcb_key_press_event_t *ev; ev = (xcb_key_press_event_t *)e; if (ev->detail == 9) return; break; } } free (e); } }
bool X11AppContext::dispatchLoop(LoopControl& control) { X11LoopImpl loopImpl(control, xConnection(), xDummyWindow()); while(loopImpl.run.load()) { while(auto func = loopImpl.popFunction()) func(); xcb_generic_event_t* event = xcb_wait_for_event(xConnection_); if(!event && !checkErrorWarn()) return false; processEvent(static_cast<const x11::GenericEvent&>(*event)); free(event); xcb_flush(&xConnection()); } return true; }
void KbdStateListener::run() { #ifdef USE_XCB conn = xcb_connect(0,0); xcb_void_cookie_t ck = xcb_xkb_select_events(conn, XCB_XKB_ID_USE_CORE_KBD, XCB_EVENT_MASK_KEYMAP_STATE, 0,0,XCB_EVENT_MASK_KEYMAP_STATE,0,0); xcb_request_check(conn,ck); forever{ break; //something is wrong, probably xcb_xkb_select_events is not used properly (any docs somewhere???) xcb_wait_for_event(conn); #else dpy = XOpenDisplay(0); XkbSelectEvents((Display *)dpy, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask); forever{ XEvent xev; XNextEvent((Display *)dpy,&xev); #endif emit eventRecived(); } }
static void _e_alert_run(void) { xcb_generic_event_t *event = NULL; xcb_flush(conn); while ((event = xcb_wait_for_event(conn))) { switch (event->response_type & ~0x80) { case XCB_BUTTON_PRESS: ret = _e_alert_handle_button_press(event); break; case XCB_KEY_PRESS: ret = _e_alert_handle_key_press(event); break; case XCB_EXPOSE: { xcb_expose_event_t *ev; ev = (xcb_expose_event_t *)event; if (ev->window != win) break; _e_alert_draw(); _e_alert_sync(); break; } default: break; } free(event); if (ret > 0) return; } }
static void process_events(xcb_connection_t *c, xcb_gcontext_t g, xcb_window_t w, xcb_pixmap_t p, uint32_t width, uint32_t height) { xcb_generic_event_t *e; xcb_void_cookie_t cookie; while ((e = xcb_wait_for_event(c))) { uint32_t r = XCB_EVENT_RESPONSE_TYPE(e); xcb_generic_error_t *err; fprintf(stderr, "event %d\n", r); switch (r) { case XCB_EXPOSE: case XCB_MAP_NOTIFY: cookie = xcb_copy_area_checked(c, p, w, g, 0, 0, 0, 0, width, height); assert(!xcb_request_check(c, cookie)); break; case XCB_BUTTON_PRESS: exit(0); break; case 0: err = (xcb_generic_error_t *) e; printf("error: %d (sequence %d)\n", err->error_code, (unsigned int) err->full_sequence); exit(1); default: break; } free(e); } }
/* * Creates the config file and tells i3 to reload. * */ static void finish() { printf("creating \"%s\"...\n", config_path); if (!(dpy = XOpenDisplay(NULL))) errx(1, "Could not connect to X11"); FILE *kc_config = fopen(SYSCONFDIR "/i3/config.keycodes", "r"); if (kc_config == NULL) err(1, "Could not open input file \"%s\"", SYSCONFDIR "/i3/config.keycodes"); FILE *ks_config = fopen(config_path, "w"); if (ks_config == NULL) err(1, "Could not open output config file \"%s\"", config_path); free(config_path); char *line = NULL; size_t len = 0; #ifndef USE_FGETLN ssize_t read; #endif bool head_of_file = true; /* write a header about auto-generation to the output file */ fputs("# This file has been auto-generated by i3-config-wizard(1).\n", ks_config); fputs("# It will not be overwritten, so edit it as you like.\n", ks_config); fputs("#\n", ks_config); fputs("# Should you change your keyboard layout somewhen, delete\n", ks_config); fputs("# this file and re-run i3-config-wizard(1).\n", ks_config); fputs("#\n", ks_config); #ifdef USE_FGETLN char *buf = NULL; while ((buf = fgetln(kc_config, &len)) != NULL) { /* fgetln does not return null-terminated strings */ FREE(line); sasprintf(&line, "%.*s", len, buf); #else size_t linecap = 0; while ((read = getline(&line, &linecap, kc_config)) != -1) { len = strlen(line); #endif /* skip the warning block at the beginning of the input file */ if (head_of_file && strncmp("# WARNING", line, strlen("# WARNING")) == 0) continue; head_of_file = false; /* Skip leading whitespace */ char *walk = line; while (isspace(*walk) && walk < (line + len)) { /* Pre-output the skipped whitespaces to keep proper indentation */ fputc(*walk, ks_config); walk++; } /* Set the modifier the user chose */ if (strncmp(walk, "set $mod ", strlen("set $mod ")) == 0) { if (modifier == MOD_Mod1) fputs("set $mod Mod1\n", ks_config); else fputs("set $mod Mod4\n", ks_config); continue; } /* Check for 'bindcode'. If it’s not a bindcode line, we * just copy it to the output file */ if (strncmp(walk, "bindcode", strlen("bindcode")) != 0) { fputs(walk, ks_config); continue; } char *result = rewrite_binding(walk); fputs(result, ks_config); free(result); } /* sync to do our best in order to have the file really stored on disk */ fflush(ks_config); fsync(fileno(ks_config)); #ifndef USE_FGETLN free(line); #endif fclose(kc_config); fclose(ks_config); /* tell i3 to reload the config file */ int sockfd = ipc_connect(socket_path); ipc_send_message(sockfd, strlen("reload"), 0, (uint8_t*)"reload"); close(sockfd); exit(0); } int main(int argc, char *argv[]) { config_path = resolve_tilde("~/.i3/config"); socket_path = getenv("I3SOCK"); char *pattern = "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1"; char *patternbold = "-misc-fixed-bold-r-normal--13-120-75-75-C-70-iso10646-1"; int o, option_index = 0; static struct option long_options[] = { {"socket", required_argument, 0, 's'}, {"version", no_argument, 0, 'v'}, {"limit", required_argument, 0, 'l'}, {"prompt", required_argument, 0, 'P'}, {"prefix", required_argument, 0, 'p'}, {"font", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; char *options_string = "s:vh"; while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) { switch (o) { case 's': FREE(socket_path); socket_path = strdup(optarg); break; case 'v': printf("i3-config-wizard " I3_VERSION "\n"); return 0; case 'h': printf("i3-config-wizard " I3_VERSION "\n"); printf("i3-config-wizard [-s <socket>] [-v]\n"); return 0; } } /* Check if the destination config file does not exist but the path is * writable. If not, exit now, this program is not useful in that case. */ struct stat stbuf; if (stat(config_path, &stbuf) == 0) { printf("The config file \"%s\" already exists. Exiting.\n", config_path); return 0; } /* Create ~/.i3 if it does not yet exist */ char *config_dir = resolve_tilde("~/.i3"); if (stat(config_dir, &stbuf) != 0) if (mkdir(config_dir, 0755) == -1) err(1, "mkdir(%s) failed", config_dir); free(config_dir); int fd; if ((fd = open(config_path, O_CREAT | O_RDWR, 0644)) == -1) { printf("Cannot open file \"%s\" for writing: %s. Exiting.\n", config_path, strerror(errno)); return 0; } close(fd); unlink(config_path); if (socket_path == NULL) socket_path = root_atom_contents("I3_SOCKET_PATH"); if (socket_path == NULL) socket_path = "/tmp/i3-ipc.sock"; int screens; if ((conn = xcb_connect(NULL, &screens)) == NULL || xcb_connection_has_error(conn)) errx(1, "Cannot open display\n"); xcb_get_modifier_mapping_cookie_t modmap_cookie; modmap_cookie = xcb_get_modifier_mapping(conn); symbols = xcb_key_symbols_alloc(conn); /* Place requests for the atoms we need as soon as possible */ #define xmacro(atom) \ xcb_intern_atom_cookie_t atom ## _cookie = xcb_intern_atom(conn, 0, strlen(#atom), #atom); #include "atoms.xmacro" #undef xmacro root_screen = xcb_aux_get_screen(conn, screens); root = root_screen->root; if (!(modmap_reply = xcb_get_modifier_mapping_reply(conn, modmap_cookie, NULL))) errx(EXIT_FAILURE, "Could not get modifier mapping\n"); xcb_numlock_mask = get_mod_mask_for(XCB_NUM_LOCK, symbols, modmap_reply); font = load_font(pattern, true); bold_font = load_font(patternbold, true); /* Open an input window */ win = xcb_generate_id(conn); xcb_create_window( conn, XCB_COPY_FROM_PARENT, win, /* the window id */ root, /* parent == root */ 490, 297, 300, 205, /* dimensions */ 0, /* X11 border = 0, we draw our own */ XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_WINDOW_CLASS_COPY_FROM_PARENT, /* copy visual from parent */ XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, (uint32_t[]){ 0, /* back pixel: black */ XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS }); /* Map the window (make it visible) */ xcb_map_window(conn, win); /* Setup NetWM atoms */ #define xmacro(name) \ do { \ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, name ## _cookie, NULL); \ if (!reply) \ errx(EXIT_FAILURE, "Could not get atom " # name "\n"); \ \ A_ ## name = reply->atom; \ free(reply); \ } while (0); #include "atoms.xmacro" #undef xmacro /* Set dock mode */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, A__NET_WM_WINDOW_TYPE, A_ATOM, 32, 1, (unsigned char*) &A__NET_WM_WINDOW_TYPE_DIALOG); /* Set window title */ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, A__NET_WM_NAME, A_UTF8_STRING, 8, strlen("i3: first configuration"), "i3: first configuration"); /* Create pixmap */ pixmap = xcb_generate_id(conn); pixmap_gc = xcb_generate_id(conn); xcb_create_pixmap(conn, root_screen->root_depth, pixmap, win, 500, 500); xcb_create_gc(conn, pixmap_gc, pixmap, 0, 0); /* Grab the keyboard to get all input */ xcb_flush(conn); /* Try (repeatedly, if necessary) to grab the keyboard. We might not * get the keyboard at the first attempt because of the keybinding * still being active when started via a wm’s keybinding. */ xcb_grab_keyboard_cookie_t cookie; xcb_grab_keyboard_reply_t *reply = NULL; int count = 0; while ((reply == NULL || reply->status != XCB_GRAB_STATUS_SUCCESS) && (count++ < 500)) { cookie = xcb_grab_keyboard(conn, false, win, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); reply = xcb_grab_keyboard_reply(conn, cookie, NULL); usleep(1000); } if (reply->status != XCB_GRAB_STATUS_SUCCESS) { fprintf(stderr, "Could not grab keyboard, status = %d\n", reply->status); exit(-1); } xcb_flush(conn); xcb_generic_event_t *event; while ((event = xcb_wait_for_event(conn)) != NULL) { if (event->response_type == 0) { fprintf(stderr, "X11 Error received! sequence %x\n", event->sequence); continue; } /* Strip off the highest bit (set if the event is generated) */ int type = (event->response_type & 0x7F); switch (type) { case XCB_KEY_PRESS: handle_key_press(NULL, conn, (xcb_key_press_event_t*)event); break; /* TODO: handle mappingnotify */ case XCB_BUTTON_PRESS: handle_button_press((xcb_button_press_event_t*)event); break; case XCB_EXPOSE: handle_expose(); break; } free(event); } return 0; }
int main(void) { xcb_connection_t *c; xcb_screen_t *s; xcb_window_t w; xcb_gcontext_t g; xcb_generic_event_t *e; uint32_t mask; uint32_t values[4]; int done =0 ; signal(SIGSEGV, handler); /* open connection with the server */ c = xcb_connect(NULL,NULL); if (xcb_connection_has_error(c)) { printf("Cannot open display\n"); exit(1); } /* get the first screen */ s = xcb_setup_roots_iterator( xcb_get_setup(c) ).data; xcb_get_geometry_reply_t *geo; /* create sub window */ w= xcb_generate_id(c); mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; values[0] = s->black_pixel; values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; xcb_void_cookie_t cookie; int width =640; int height =480; mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; values[0] = s->white_pixel; values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_VISIBILITY_CHANGE ; values[1] = 0xffff; xcb_create_window(c, s->root_depth, w, s->root, 10, 10, width, height, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, s->root_visual, mask, values); xcb_map_window(c, w); xcb_flush(c); // xcb_reparent_window(c, child, G.s->root,100,100); values[1] |= XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE; xcb_change_window_attributes_checked(c, w, mask, values); xcb_flush(c); G.conn = c; G.s = s; create_dri_drawable(); printf("wait event\n"); while (!done ) { //printf("\re=>(x%x)", e->response_type); fflush(stdout); e = xcb_wait_for_event(c); if(!e) { printf("wait event error\n"); break;} else{ switch (e->response_type & ~0x80) { case XCB_EXPOSE: /* draw or redraw the window */ printf("XCB_EXPOSE\n"); // draw_gc(w); break; case XCB_KEY_PRESS: /* exit on key press */ printf("KEY\n"); struct xcb_key_press_event_t *ep = e; printf("key=%d\n", (char)ep->detail); if(ep->detail == 9) exit(1); draw_gc(w); //gwj done = 1; break; case XCB_MOTION_NOTIFY: { printf("XCB_MOTION\n"); } break; default: printf("default e=%d\n",e->response_type); break; } free(e); } } xcb_unmap_window(c, w); xcb_destroy_window(c, w); return 0; }
void track_pointer(coordinates_t loc, pointer_action_t pac, xcb_point_t pos) { node_t *n = loc.node; resize_handle_t rh = get_handle(loc.node, pos, pac); uint16_t last_motion_x = pos.x, last_motion_y = pos.y; xcb_timestamp_t last_motion_time = 0; xcb_generic_event_t *evt = NULL; grabbing = true; grabbed_node = n; do { free(evt); while ((evt = xcb_wait_for_event(dpy)) == NULL) { xcb_flush(dpy); } uint8_t resp_type = XCB_EVENT_RESPONSE_TYPE(evt); if (resp_type == XCB_MOTION_NOTIFY) { xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t*) evt; uint32_t dtime = e->time - last_motion_time; if (dtime < pointer_motion_interval) { continue; } last_motion_time = e->time; int16_t dx = e->root_x - last_motion_x; int16_t dy = e->root_y - last_motion_y; if (pac == ACTION_MOVE) { move_client(&loc, dx, dy); } else { resize_client(&loc, rh, e->root_x, e->root_y, false); } last_motion_x = e->root_x; last_motion_y = e->root_y; xcb_flush(dpy); } else if (resp_type == XCB_BUTTON_RELEASE) { grabbing = false; } else { handle_event(evt); } } while (grabbing && grabbed_node != NULL); free(evt); xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); if (grabbed_node == NULL) { grabbing = false; return; } if (pac == ACTION_MOVE) { put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X move end\n", loc.monitor->id, loc.desktop->id, n->id); } else if (pac == ACTION_RESIZE_CORNER) { put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_corner end\n", loc.monitor->id, loc.desktop->id, n->id); } else if (pac == ACTION_RESIZE_SIDE) { put_status(SBSC_MASK_POINTER_ACTION, "pointer_action 0x%08X 0x%08X 0x%08X resize_side end\n", loc.monitor->id, loc.desktop->id, n->id); } xcb_rectangle_t r = get_rectangle(NULL, NULL, n); put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc.monitor->id, loc.desktop->id, loc.node->id, r.width, r.height, r.x, r.y); if ((pac == ACTION_MOVE && IS_TILED(n->client)) || ((pac == ACTION_RESIZE_CORNER || pac == ACTION_RESIZE_SIDE) && n->client->state == STATE_TILED)) { for (node_t *f = first_extrema(loc.desktop->root); f != NULL; f = next_leaf(f, loc.desktop->root)) { if (f == n || f->client == NULL || !IS_TILED(f->client)) { continue; } xcb_rectangle_t r = f->client->tiled_rectangle; put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc.monitor->id, loc.desktop->id, f->id, r.width, r.height, r.x, r.y); } } }
xcb_window_t Select_Window(xcb_connection_t *dpy, const xcb_screen_t *screen, int descend) { xcb_cursor_t cursor; xcb_generic_event_t *event; xcb_window_t target_win = XCB_WINDOW_NONE; xcb_window_t root = screen->root; int buttons = 0; xcb_generic_error_t *err; xcb_grab_pointer_cookie_t grab_cookie; xcb_grab_pointer_reply_t *grab_reply; /* Make the target cursor */ cursor = Create_Font_Cursor (dpy, XC_crosshair); /* Grab the pointer using target cursor, letting it room all over */ grab_cookie = xcb_grab_pointer (dpy, False, root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, root, cursor, XCB_TIME_CURRENT_TIME); grab_reply = xcb_grab_pointer_reply (dpy, grab_cookie, &err); if (grab_reply->status != XCB_GRAB_STATUS_SUCCESS) Fatal_Error ("Can't grab the mouse."); /* Let the user select a window... */ while ((target_win == XCB_WINDOW_NONE) || (buttons != 0)) { /* allow one more event */ xcb_allow_events (dpy, XCB_ALLOW_SYNC_POINTER, XCB_TIME_CURRENT_TIME); xcb_flush (dpy); event = xcb_wait_for_event (dpy); switch (event->response_type & 0x7f) { case XCB_BUTTON_PRESS: { xcb_button_press_event_t *bp = (xcb_button_press_event_t *)event; if (target_win == XCB_WINDOW_NONE) { target_win = bp->child; /* window selected */ if (target_win == XCB_WINDOW_NONE) target_win = root; } buttons++; break; } case XCB_BUTTON_RELEASE: if (buttons > 0) /* there may have been some down before we started */ buttons--; break; default: /* just discard all other events */ break; } free (event); } xcb_ungrab_pointer (dpy, XCB_TIME_CURRENT_TIME); /* Done with pointer */ if (!descend || (target_win == root)) return (target_win); target_win = Find_Client (dpy, root, target_win); return (target_win); }
void * run_event_loop(void *thread_arg_struct) { _connection_data *conn_data; xcwm_context_t *context; xcb_connection_t *event_conn; xcb_generic_event_t *evt; xcwm_event_t return_evt; xcwm_event_cb_t callback_ptr; conn_data = thread_arg_struct; context = conn_data->context; event_conn = context->conn; callback_ptr = conn_data->callback; free(thread_arg_struct); _xcwm_windows_adopt(context, callback_ptr); /* Start the event loop, and flush if first */ xcb_flush(event_conn); while ((evt = xcb_wait_for_event(event_conn))) { uint8_t response_type = evt->response_type & ~0x80; if (response_type == context->damage_event_mask) { xcb_damage_notify_event_t *dmgevnt = (xcb_damage_notify_event_t *)evt; /* printf("damage %d,%d @ %d,%d reported against window 0x%08x\n", */ /* dmgevnt->area.width, dmgevnt->area.height, dmgevnt->area.x, dmgevnt->area.y, */ /* dmgevnt->drawable); */ xcwm_window_t *window = _xcwm_get_window_node_by_window_id(dmgevnt->drawable); return_evt.event_type = XCWM_EVENT_WINDOW_DAMAGE; return_evt.window = window; if (!window) { printf("damage reported against unknown window 0x%08x\n", dmgevnt->drawable); continue; } /* Increase the damaged area of window if new damage is * larger than current. */ xcwm_event_get_thread_lock(); /* Initial damage events for override-redirect windows are * reported relative to the root window, subsequent events * are relative to the window itself. We also catch cases * where the damage area is larger than the bounds of the * window. */ if (window->initial_damage == 1 || (dmgevnt->area.width > window->bounds.width) || (dmgevnt->area.height > window->bounds.height) ) { xcb_xfixes_region_t region = xcb_generate_id(window->context->conn); xcb_rectangle_t rect; /* printf("initial damage on window 0x%08x\n", dmgevnt->drawable); */ /* Remove the damage */ xcb_xfixes_create_region(window->context->conn, region, 1, &dmgevnt->area); xcb_damage_subtract(window->context->conn, window->damage, region, XCB_NONE); /* Add new damage area for entire window */ rect.x = 0; rect.y = 0; rect.width = window->bounds.width; rect.height = window->bounds.height; xcb_xfixes_set_region(window->context->conn, region, 1, &rect); xcb_damage_add(window->context->conn, window->window_id, region); window->initial_damage = 0; xcb_xfixes_destroy_region(window->context->conn, region); xcwm_event_release_thread_lock(); continue; } window->dmg_bounds.x = dmgevnt->area.x; window->dmg_bounds.y = dmgevnt->area.y; window->dmg_bounds.width = dmgevnt->area.width; window->dmg_bounds.height = dmgevnt->area.height; xcwm_event_release_thread_lock(); callback_ptr(&return_evt); } else if (response_type == context->shape_event) { xcb_shape_notify_event_t *shapeevnt = (xcb_shape_notify_event_t *)evt; if (shapeevnt->shape_kind == XCB_SHAPE_SK_BOUNDING) { xcwm_window_t *window = _xcwm_get_window_node_by_window_id(shapeevnt->affected_window); _xcwm_window_set_shape(window, shapeevnt->shaped); return_evt.event_type = XCWM_EVENT_WINDOW_SHAPE; return_evt.window = window; callback_ptr(&return_evt); } } else if (response_type == context->fixes_event_base + XCB_XFIXES_CURSOR_NOTIFY) { /* xcb_xfixes_cursor_notify_event_t *cursorevnt = */ /* (xcb_xfixes_cursor_notify_event_t *)evt; */ return_evt.event_type = XCWM_EVENT_CURSOR; return_evt.window = NULL; callback_ptr(&return_evt); } else { switch (response_type) { case 0: { /* Error case. Something very bad has happened. Spit * out some hopefully useful information and then * die. * FIXME: Decide under what circumstances we should * acutally kill the application. */ xcb_generic_error_t *err = (xcb_generic_error_t *)evt; fprintf(stderr, "Error received in event loop.\n" "Error code: %i\n", err->error_code); if ((err->error_code >= XCB_VALUE) && (err->error_code <= XCB_FONT)) { xcb_value_error_t *val_err = (xcb_value_error_t *)evt; fprintf(stderr, "Bad value: %i\n" "Major opcode: %i\n" "Minor opcode: %i\n", val_err->bad_value, val_err->major_opcode, val_err->minor_opcode); } break; } case XCB_EXPOSE: { xcb_expose_event_t *exevnt = (xcb_expose_event_t *)evt; printf( "Window %u exposed. Region to be redrawn at location (%d, %d), ", exevnt->window, exevnt->x, exevnt->y); printf("with dimensions (%d, %d).\n", exevnt->width, exevnt->height); return_evt.event_type = XCWM_EVENT_WINDOW_EXPOSE; callback_ptr(&return_evt); break; } case XCB_CREATE_NOTIFY: { /* We don't actually allow our client to create its * window here, wait until the XCB_MAP_REQUEST */ break; } case XCB_DESTROY_NOTIFY: { // Window destroyed in root window xcb_destroy_notify_event_t *notify = (xcb_destroy_notify_event_t *)evt; xcwm_window_t *window = _xcwm_window_remove(event_conn, notify->window); if (!window) { /* Not a window in the list, don't try and destroy */ break; } return_evt.event_type = XCWM_EVENT_WINDOW_DESTROY; return_evt.window = window; callback_ptr(&return_evt); // Release memory for the window _xcwm_window_release(window); break; } case XCB_MAP_NOTIFY: { xcb_map_notify_event_t *notify = (xcb_map_notify_event_t *)evt; /* notify->event holds parent of the window */ xcwm_window_t *window = _xcwm_get_window_node_by_window_id(notify->window); if (!window) { /* No MAP_REQUEST for override-redirect windows, so need to create the xcwm_window_t for it now */ /* printf("MAP_NOTIFY without MAP_REQUEST\n"); */ window = _xcwm_window_create(context, notify->window, notify->event); if (window) { _xcwm_window_composite_pixmap_update(window); return_evt.window = window; return_evt.event_type = XCWM_EVENT_WINDOW_CREATE; callback_ptr(&return_evt); } } else { _xcwm_window_composite_pixmap_update(window); } break; } case XCB_MAP_REQUEST: { xcb_map_request_event_t *request = (xcb_map_request_event_t *)evt; /* Map the window */ xcb_map_window(context->conn, request->window); xcb_flush(context->conn); return_evt.window = _xcwm_window_create(context, request->window, request->parent); if (!return_evt.window) { break; } return_evt.event_type = XCWM_EVENT_WINDOW_CREATE; callback_ptr(&return_evt); break; } case XCB_UNMAP_NOTIFY: { xcb_unmap_notify_event_t *notify = (xcb_unmap_notify_event_t *)evt; xcwm_window_t *window = _xcwm_window_remove(event_conn, notify->window); if (!window) { /* Not a window in the list, don't try and destroy */ break; } return_evt.event_type = XCWM_EVENT_WINDOW_DESTROY; return_evt.window = window; callback_ptr(&return_evt); _xcwm_window_composite_pixmap_release(window); // Release memory for the window _xcwm_window_release(window); break; } case XCB_CONFIGURE_NOTIFY: { xcb_configure_notify_event_t *request = (xcb_configure_notify_event_t *)evt; printf("CONFIGURE_NOTIFY: XID 0x%08x %dx%d @ %d,%d\n", request->window, request->width, request->height, request->x, request->y); xcwm_window_t *window = _xcwm_get_window_node_by_window_id(request->window); if (window) _xcwm_window_composite_pixmap_update(window); break; } case XCB_CONFIGURE_REQUEST: { xcb_configure_request_event_t *request = (xcb_configure_request_event_t *)evt; printf("CONFIGURE_REQUEST: XID 0x%08x %dx%d @ %d,%d mask 0x%04x\n", request->window, request->width, request->height, request->x, request->y, request->value_mask); /* relying on the server's idea of the current values of values not in value_mask is a bad idea, we might have a configure request of our own on this window in flight */ if (request->value_mask & (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT)) _xcwm_resize_window(event_conn, request->window, request->x, request->y, request->width, request->height); /* Ignore requests to change stacking ? */ break; } case XCB_PROPERTY_NOTIFY: { xcb_property_notify_event_t *notify = (xcb_property_notify_event_t *)evt; xcwm_window_t *window = _xcwm_get_window_node_by_window_id(notify->window); if (!window) { break; } /* If this is WM_PROTOCOLS, do not send event, just * handle internally */ if (notify->atom == window->context->atoms.ewmh_conn.WM_PROTOCOLS) { _xcwm_atoms_set_wm_delete(window); break; } xcwm_event_type_t event; if (_xcwm_atom_change_to_event(notify->atom, window, &event)) { /* Send the appropriate event */ return_evt.event_type = event; return_evt.window = window; callback_ptr(&return_evt); } else { printf("PROPERTY_NOTIFY for ignored property atom %d\n", notify->atom); /* We need a mechanism to forward properties we don't know about to WM, otherwise everything needs to be in libXcwm ...? */ } break; } case XCB_MAPPING_NOTIFY: break; default: { printf("UNKNOWN EVENT: %i\n", (evt->response_type & ~0x80)); break; } } } /* Free the event */ free(evt); } return NULL; }
int dispatcher::execute( void ) { xcb_flush( _connection ); _exit_code = 0; bool done = false; while ( !done ) { auto event = core::wrap_cptr( xcb_wait_for_event( _connection ) ); if ( !event ) break; switch ( event->response_type & ~0x80 ) { case XCB_EXPOSE: { auto *ev = reinterpret_cast<xcb_expose_event_t*>( event.get() ); if ( ev->count == 0 ) _windows[ev->window]->exposed(); xcb_flush( _connection ); break; } case XCB_CONFIGURE_NOTIFY: { auto *ev = reinterpret_cast<xcb_configure_notify_event_t*>( event.get() ); auto w = _windows[ev->window]; if ( w->check_last_position( ev->x, ev->y ) ) w->moved( ev->x, ev->y ); if ( w->check_last_size( ev->width, ev->height ) ) w->resize_canvas( ev->width, ev->height ); break; } case XCB_DESTROY_NOTIFY: { auto *ev = reinterpret_cast<xcb_destroy_notify_event_t*>( event.get() ); auto w = _windows[ev->window]; w->closed(); break; } case XCB_MAP_NOTIFY: { auto *ev = reinterpret_cast<xcb_map_notify_event_t*>( event.get() ); auto w = _windows[ev->window]; w->shown(); w->restored(); break; } case XCB_UNMAP_NOTIFY: { auto *ev = reinterpret_cast<xcb_unmap_notify_event_t*>( event.get() ); auto w = _windows[ev->window]; w->hidden(); w->minimized(); break; } case XCB_ENTER_NOTIFY: { auto *ev = reinterpret_cast<xcb_enter_notify_event_t*>( event.get() ); auto w = _windows[ev->event]; w->entered(); break; } case XCB_LEAVE_NOTIFY: { auto *ev = reinterpret_cast<xcb_leave_notify_event_t*>( event.get() ); auto w = _windows[ev->event]; w->exited(); break; } case XCB_KEY_PRESS: { auto *ev = reinterpret_cast<xcb_key_press_event_t*>( event.get() ); auto w = _windows[ev->event]; platform::scancode sc = _keyboard->get_scancode( ev->detail ); w->key_pressed( _keyboard, sc ); break; } case XCB_KEY_RELEASE: { auto *ev = reinterpret_cast<xcb_key_press_event_t*>( event.get() ); auto w = _windows[ev->event]; platform::scancode sc = _keyboard->get_scancode( ev->detail ); w->key_released( _keyboard, sc ); break; } case XCB_MAPPING_NOTIFY: { auto *ev = reinterpret_cast<xcb_mapping_notify_event_t*>( event.get() ); if ( ev->request == XCB_MAPPING_MODIFIER || ev->request == XCB_MAPPING_KEYBOARD ) _keyboard->update_mapping(); break; } case XCB_BUTTON_PRESS: { auto *ev = reinterpret_cast<xcb_button_press_event_t*>( event.get() ); auto w = _windows[ev->event]; switch ( ev->detail ) { case 1: case 2: case 3: w->mouse_pressed( _mouse, { double(ev->event_x), double(ev->event_y) }, ev->detail ); break; case 4: // Mouse wheel up case 5: // Mouse wheel down break; } break; } case XCB_BUTTON_RELEASE: { auto *ev = reinterpret_cast<xcb_button_press_event_t*>( event.get() ); auto w = _windows[ev->event]; switch ( ev->detail ) { case 1: case 2: case 3: w->mouse_released( _mouse, { double(ev->event_x), double(ev->event_y) }, ev->detail ); break; case 4: // Mouse wheel up case 5: // Mouse wheel down break; } break; } case XCB_MOTION_NOTIFY: { auto *ev = reinterpret_cast<xcb_motion_notify_event_t*>( event.get() ); auto w = _windows[ev->event]; w->mouse_moved( _mouse, { double(ev->event_x), double(ev->event_y) } ); break; } case XCB_VISIBILITY_NOTIFY: case XCB_REPARENT_NOTIFY: break; case XCB_CLIENT_MESSAGE: { auto *ev = reinterpret_cast<xcb_client_message_event_t*>( event.get() ); if ( ev->data.data32[0] == _atom_delete_window ) { auto w = _windows[ev->window]; w->hide(); _windows.erase( w->id() ); done = _windows.empty(); } break; } default: std::cout << "Unknown event: " << uint32_t( event->response_type & ~0x80 ) << ' ' << uint32_t( event->response_type ) << std::endl; } } return _exit_code; }
int main() { xcb_connection_t * conn; xcb_screen_t * scrn; xcb_drawable_t win; xcb_gcontext_t foreground; xcb_generic_event_t * e; uint32_t mask = 0; uint32_t values[2]; xcb_point_t points[] = { { 10, 10 }, { 10, 20 }, { 20, 10 }, { 20, 20 } }; xcb_point_t polyline[] = { { 50, 10 }, { 5, 20 }, { 25,-20 }, { 10, 10 } }; xcb_segment_t segments[] = { { 100, 10, 140, 30 }, { 110, 25, 130, 60 } }; xcb_rectangle_t rectangles[] = { { 10, 50, 40, 30 }, { 80, 50, 10, 40 } }; xcb_arc_t arcs[] = { { 10, 100, 60, 40, 0, 90 << 6 }, { 90, 100, 55, 40, 0, 270 << 6 } }; //initialize the connection to X conn = xcb_connect(NULL, &scrnNum); //get the first screen data scrn = get_setup_roots_iterator(xcb_get_setup(conn)).data; foreground = xcb_generate_id(conn); mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; values[0] = scrn->black_pixel; values[1] = 0; xcb_create_gc(conn, foreground, win, mask, values); //ask for the window's id win = xcb_generate_id(conn); //create the window mask = XCB_CW_BLACK_PIXEL | XCB_GC_GRAPHICS_EXPOSURES values[0] = scrn->white_pixel; values[1] = XCB_EVENT_MASK_EXPOSURE; xcb_create_window(conn, XCB_COPY_FROM_PARENT, win, scrn->root, 0, 0, 150, 150, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT, scrn->root_visual, mask, values); //map the window xcb_map_window(conn, win); xcb_flush(conn); while (( e = xcb_wait_for_event(conn)) { switch (e->response_type & ~0x80) { case XCB_EXPOSE: { //draw things xcb_poly_point(conn, XCB_COORD_MODE_ORIGIN, win, foreground, 4, points); xcb_poly_line(conn, XCB_COORD_MODE_PREVIOUS, win, foreground, 4, polyline); xcb_poly_segment(conn, win, foreground, 2, segments); xcb_poly_rectangle(conn, win, foreground, 2 , rectangles); xcb_poly_arc(conn, win, foreground, 2, arcs); xcb_flush(conn); break; } default: { break; } } free(e); } return 0; }