static xcb_window_t make_window(xcb_connection_t *c, xcb_screen_t *s, uint32_t bg, uint32_t fg, uint32_t width, uint32_t height) { uint32_t mask = 0; xcb_params_cw_t cwa; xcb_window_t w; xcb_void_cookie_t check_cookie; xcb_generic_error_t *error; xcb_visualtype_t *v = xcb_aux_find_visual_by_id(s, s->root_visual); assert(v); XCB_AUX_ADD_PARAM(&mask, &cwa, back_pixel, bg); XCB_AUX_ADD_PARAM(&mask, &cwa, border_pixel, fg); XCB_AUX_ADD_PARAM(&mask, &cwa, override_redirect, 1); XCB_AUX_ADD_PARAM(&mask, &cwa, event_mask, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE); w = xcb_generate_id(c); check_cookie = xcb_aux_create_window_checked(c, s->root_depth, w, s->root, 0, 0, width, height, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, v->visual_id, mask, &cwa); error = xcb_request_check(c, check_cookie); assert(!error); check_cookie = xcb_map_window_checked(c, w); error = xcb_request_check(c, check_cookie); assert(!error); return w; }
static int init_bar() { uint32_t vals[4]; xcb_void_cookie_t cookie; xcb_generic_error_t *err; /* create status bar window at the bottom */ bar_.w = nil_.scr->width_in_pixels; bar_.h = nil_.font.ascent + nil_.font.descent + 2; bar_.x = 0; bar_.y = nil_.scr->height_in_pixels - bar_.h; bar_.win = xcb_generate_id(nil_.con); vals[0] = XCB_BACK_PIXMAP_PARENT_RELATIVE; vals[1] = 1; /* override_redirect */ vals[2] = XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE; vals[3] = nil_.cursor[CURSOR_NORMAL]; cookie = xcb_create_window_checked(nil_.con, nil_.scr->root_depth, bar_.win, nil_.scr->root, bar_.x, bar_.y, bar_.w, bar_.h, 0, XCB_COPY_FROM_PARENT, nil_.scr->root_visual, XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_CURSOR, vals); err = xcb_request_check(nil_.con, cookie); if (err) { NIL_ERR("create window %d", err->error_code); return -1; } vals[0] = XCB_STACK_MODE_ABOVE; xcb_configure_window(nil_.con, bar_.win, XCB_CONFIG_WINDOW_STACK_MODE, &vals[0]); cookie = xcb_map_window_checked(nil_.con, bar_.win); err = xcb_request_check(nil_.con, cookie); if (err) { NIL_ERR("map window %d", err->error_code); return -1; } /* graphic context */ bar_.gc = xcb_generate_id(nil_.con); vals[0] = nil_.color.bar_fg; vals[1] = nil_.color.bar_bg; vals[2] = nil_.font.id; cookie = xcb_create_gc_checked(nil_.con, bar_.gc, bar_.win, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT, vals); err = xcb_request_check(nil_.con, cookie); if (err) { NIL_ERR("map window %d", err->error_code); return -1; } return 0; }
void XCBWindow::map() { // Prepare notification for window destruction xcb_intern_atom_cookie_t protocols_cookie = xcb_intern_atom(m_connection, 1, 12, "WM_PROTOCOLS"); xcb_intern_atom_reply_t* protocols_reply = xcb_intern_atom_reply(m_connection, protocols_cookie, 0); xcb_intern_atom_cookie_t delete_cookie = xcb_intern_atom(m_connection, 0, 16, "WM_DELETE_WINDOW"); m_deleteWindowReply = xcb_intern_atom_reply(m_connection, delete_cookie, 0); xcb_change_property( m_connection, XCB_PROP_MODE_REPLACE, m_handle, (*protocols_reply).atom, 4, 32, 1, &(*m_deleteWindowReply).atom); xcb_void_cookie_t cookie = xcb_map_window_checked(m_connection, m_handle); xcb_generic_error_t* error = nullptr; if ((error = xcb_request_check(m_connection, cookie))) { fprintf(stderr, "Could not reparent the window\n"); free(error); } Assert(xcb_connection_has_error(m_connection) == 0); xcb_flush(m_connection); }
struct rtb_window * window_impl_open(struct rutabaga *rtb, int w, int h, const char *title, intptr_t parent) { struct xcb_rutabaga *xrtb = (void *) rtb; struct xrtb_window *self; Display *dpy; xcb_connection_t *xcb_conn; int default_screen; GLXFBConfig *fb_configs, fb_config; XVisualInfo *visual; int nfb_configs; uint32_t event_mask = XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEYMAP_STATE; uint32_t value_mask = XCB_CW_BORDER_PIXEL | XCB_CW_BACK_PIXMAP | XCB_CW_BIT_GRAVITY | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP; uint32_t value_list[6]; xcb_colormap_t colormap; xcb_void_cookie_t ck_window, ck_map; xcb_generic_error_t *err; assert(rtb); assert(h > 0); assert(w > 0); if (!(self = calloc(1, sizeof(*self)))) goto err_malloc; self->xrtb = xrtb; dpy = xrtb->dpy; xcb_conn = xrtb->xcb_conn; default_screen = DefaultScreen(dpy); self->screen = find_xcb_screen(xcb_conn, default_screen); if (!self->screen) { ERR("couldn't find XCB screen\n"); goto err_screen; } /** * gl configuration */ fb_configs = glXGetFBConfigs(dpy, default_screen, &nfb_configs); if (!fb_configs || !nfb_configs) { ERR("no GL configurations, bailing out\n"); goto err_gl_config; } fb_config = find_reasonable_fb_config(dpy, xcb_conn, fb_configs, nfb_configs, 0); if (!fb_config) { ERR("no reasonable GL configurations, bailing out\n"); goto err_gl_config; } visual = glXGetVisualFromFBConfig(dpy, fb_config); self->gl_ctx = new_gl_context(dpy, fb_config); if (!self->gl_ctx) { ERR("couldn't create GLX context\n"); goto err_gl_ctx; } /** * window setup */ colormap = xcb_generate_id(xcb_conn); self->xcb_win = xcb_generate_id(xcb_conn); xcb_create_colormap( xcb_conn, XCB_COLORMAP_ALLOC_NONE, colormap, self->screen->root, visual->visualid); value_list[0] = 0; value_list[1] = 0; value_list[2] = XCB_GRAVITY_STATIC; value_list[3] = event_mask; value_list[4] = colormap; value_list[5] = 0; ck_window = xcb_create_window_checked( xcb_conn, visual->depth, self->xcb_win, parent ? (xcb_window_t) parent : self->screen->root, 0, 0, w, h, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visual->visualid, value_mask, value_list); free(visual); if ((err = xcb_request_check(xcb_conn, ck_window))) { ERR("can't create XCB window: %d\n", err->error_code); goto err_xcb_win; } get_dpi(dpy, default_screen, &self->dpi.x, &self->dpi.y); self->gl_win = glXCreateWindow(dpy, fb_config, self->xcb_win, 0); if (!self->gl_win) { ERR("couldn't create GL window\n"); goto err_gl_win; } if (set_xprop(xcb_conn, self->xcb_win, XCB_ATOM_WM_NAME, title)) set_xprop(xcb_conn, self->xcb_win, XCB_ATOM_WM_NAME, "oh no"); self->gl_draw = self->gl_win; if (!glXMakeContextCurrent( dpy, self->gl_draw, self->gl_draw, self->gl_ctx)) { ERR("couldn't activate GLX context\n"); goto err_gl_make_current; } ck_map = xcb_map_window_checked(xcb_conn, self->xcb_win); if ((err = xcb_request_check(xcb_conn, ck_map))) { ERR("can't map XCB window: %d\n", err->error_code); goto err_win_map; } if (parent) raise_window(xcb_conn, self->xcb_win); else xcb_icccm_set_wm_protocols(xcb_conn, self->xcb_win, xrtb->atoms.wm_protocols, 1, &xrtb->atoms.wm_delete_window); free(fb_configs); uv_mutex_init(&self->lock); return RTB_WINDOW(self); err_win_map: err_gl_make_current: err_gl_win: xcb_destroy_window(xcb_conn, self->xcb_win); err_xcb_win: glXDestroyContext(dpy, self->gl_ctx); err_gl_ctx: err_gl_config: free(fb_configs); err_screen: free(self); err_malloc: return NULL; }
int main() { //get the connection int screenNum; xcb_connection_t *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); } xcb_screen_t *screen = iter.data; if(!screen){ fprintf(stderr, "ERROR: can't get the current screen\n"); xcb_disconnect(connection); return -1; } // create the window xcb_window_t 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"); setCursor(connection, screen, window, 68); xcb_flush(connection); // Event loop uint8_t isHand = 0; while (1) { xcb_generic_event_t *event = xcb_poll_for_event(connection); if(event){ switch (event->response_type & ~0x80) { case XCB_EXPOSE: { char *text = "click here to change cursor"; drawButton(connection, screen, window, (WIDTH - 7 * strlen(text)) / 2, (WIDTH -16) / 2, text); text = "Press ESC key to exit..."; drawText(connection, screen, window, 10, HEIGHT -10, text); break; } case XCB_BUTTON_PRESS: { xcb_button_press_event_t *press = (xcb_button_press_event_t *)event; int length = strlen("click here to change cursor"); if ((press->event_x >= (WIDTH -7 * length) / 2) && (press->event_x <= ((WIDTH -7 * length) /2 + 7 * length + 6)) && (press->event_y >= (HEIGHT -16) / 2 - 19) && (press->event_y <= ((HEIGHT -16) / 2))) { isHand = 1 - isHand; } if (isHand){ setCursor(connection, screen, window, 58); } else{ setCursor(connection, screen, window, 68); } } case XCB_KEY_RELEASE: { xcb_key_release_event_t *kr = (xcb_key_release_event_t *)event; switch (kr->detail) { // ESC case 9: free(event); xcb_disconnect(connection); return 0; } } } free(event); } } return 0; }
int main () { xcb_screen_iterator_t screen_iter; xcb_connection_t *c; const xcb_setup_t *setup; xcb_screen_t *screen; xcb_generic_event_t *e; xcb_generic_error_t *error; xcb_void_cookie_t cookie_window; xcb_void_cookie_t cookie_map; xcb_window_t window; uint32_t mask; uint32_t values[2]; int screen_number; uint8_t is_hand = 0; /* getting the connection */ c = xcb_connect (NULL, &screen_number); if (!c) { fprintf (stderr, "ERROR: can't connect to an X server\n"); return -1; } /* getting the current screen */ setup = xcb_get_setup (c); screen = NULL; screen_iter = xcb_setup_roots_iterator (setup); for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter)) if (screen_number == 0) { screen = screen_iter.data; break; } if (!screen) { fprintf (stderr, "ERROR: can't get the current screen\n"); xcb_disconnect (c); return -1; } /* creating the window */ window = xcb_generate_id (c); mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; 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; cookie_window = xcb_create_window_checked (c, screen->root_depth, window, screen->root, 20, 200, WIDTH, HEIGHT, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, values); cookie_map = xcb_map_window_checked (c, window); /* error managing */ error = xcb_request_check (c, cookie_window); if (error) { fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code); xcb_disconnect (c); return -1; } error = xcb_request_check (c, cookie_map); if (error) { fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code); xcb_disconnect (c); return -1; } cursor_set (c, screen, window, 68); xcb_flush(c); while (1) { e = xcb_poll_for_event(c); if (e) { switch (e->response_type & ~0x80) { case XCB_EXPOSE: { char *text; text = "click here to change cursor"; button_draw (c, screen, window, (WIDTH - 7 * strlen(text)) / 2, (HEIGHT - 16) / 2, text); text = "Press ESC key to exit..."; text_draw (c, screen, window, 10, HEIGHT - 10, text); break; } case XCB_BUTTON_PRESS: { xcb_button_press_event_t *ev; int length; ev = (xcb_button_press_event_t *)e; length = strlen ("click here to change cursor"); if ((ev->event_x >= (WIDTH - 7 * length) / 2) && (ev->event_x <= ((WIDTH - 7 * length) / 2 + 7 * length + 6)) && (ev->event_y >= (HEIGHT - 16) / 2 - 19) && (ev->event_y <= ((HEIGHT - 16) / 2))) is_hand = 1 - is_hand; is_hand ? cursor_set (c, screen, window, 58) : cursor_set (c, screen, window, 68); } case XCB_KEY_RELEASE: { xcb_key_release_event_t *ev; ev = (xcb_key_release_event_t *)e; switch (ev->detail) { /* ESC */ case 9: free (e); xcb_disconnect (c); return 0; } } } free (e); } } return 0; }