xcb_visualtype_t * ephyr_glamor_get_visual(void) { xcb_screen_t *xscreen = xcb_aux_get_screen(XGetXCBConnection(dpy), DefaultScreen(dpy)); int attribs[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, 1, None }; int event_base = 0, error_base = 0, nelements; GLXFBConfig *fbconfigs; if (!glXQueryExtension (dpy, &error_base, &event_base)) FatalError("Couldn't find GLX extension\n"); fbconfigs = glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs, &nelements); if (!nelements) FatalError("Couldn't choose an FBConfig\n"); fb_config = fbconfigs[0]; free(fbconfigs); visual_info = glXGetVisualFromFBConfig(dpy, fb_config); if (visual_info == NULL) FatalError("Couldn't get RGB visual\n"); return xcb_aux_find_visual_by_id(xscreen, visual_info->visualid); }
int main(int argc, char **argv) { uint32_t width = test_width - 2 * INSET_X; uint32_t height = test_height - 2 * INSET_Y; int snum; xcb_void_cookie_t check_cookie; xcb_window_t w; xcb_gcontext_t gc; xcb_pixmap_t pix; xcb_connection_t *c = xcb_connect(0, &snum); xcb_screen_t *s = xcb_aux_get_screen(c, snum); xcb_alloc_named_color_cookie_t bg_cookie = xcb_alloc_named_color(c, s->default_colormap, strlen("white"), "white"); xcb_alloc_named_color_cookie_t fg_cookie = xcb_alloc_named_color(c, s->default_colormap, strlen("black"), "black"); xcb_alloc_named_color_reply_t *bg_reply = xcb_alloc_named_color_reply(c, bg_cookie, 0); xcb_alloc_named_color_reply_t *fg_reply = xcb_alloc_named_color_reply(c, fg_cookie, 0); uint32_t fg, bg; xcb_image_t *image, *native_image, *subimage; uint32_t mask = 0; xcb_params_gc_t gcv; assert(bg_reply && fg_reply); bg = bg_reply->pixel; fg = fg_reply->pixel; free(bg_reply); free(fg_reply); w = make_window(c, s, bg, fg, width, height); gc = xcb_generate_id(c); check_cookie = xcb_create_gc_checked(c, gc, w, 0, 0); assert(!xcb_request_check(c, check_cookie)); image = xcb_image_create_from_bitmap_data((uint8_t *)test_bits, test_width, test_height); native_image = xcb_image_native(c, image, 1); assert(native_image); if (native_image != image) xcb_image_destroy(image); subimage = xcb_image_subimage(native_image, INSET_X, INSET_Y, width, height, 0, 0, 0); assert(subimage); xcb_image_destroy(native_image); subimage->format = XCB_IMAGE_FORMAT_XY_BITMAP; pix = xcb_generate_id(c); xcb_create_pixmap(c, s->root_depth, pix, w, subimage->width, subimage->height); gc = xcb_generate_id(c); XCB_AUX_ADD_PARAM(&mask, &gcv, foreground, fg); XCB_AUX_ADD_PARAM(&mask, &gcv, background, bg); xcb_aux_create_gc(c, gc, pix, mask, &gcv); xcb_image_put(c, pix, gc, subimage, 0, 0, 0); process_events(c, gc, w, pix, width, height); xcb_disconnect(c); return 1; }
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; }
static void setup(void) { int screennr; conn = xcb_connect(NULL, &screennr); if (xcb_connection_has_error(conn)) { fprintf(stderr, "Failed to connect to X11 server.\n"); exit(EXIT_FAILURE); } screen = xcb_aux_get_screen(conn, 0); }
/* * Creates a database similarly to XGetDefault(). For typical applications, * this is the recommended way to construct the resource database. * * The database is created as follows: * - If the RESOURCE_MANAGER property exists on the root window of * screen 0, the database is constructed from it using @ref * xcb_xrm_database_from_resource_manager(). * - Otherwise, if $HOME/.Xresources exists, the database is constructed from * it using @ref xcb_xrm_database_from_file(). * - Otherwise, if $HOME/.Xdefaults exists, the database is constructed from * it using @ref xcb_xrm_database_from_file(). * - If the environment variable XENVIRONMENT is set, the file specified by * it is loaded using @ref xcb_xrm_database_from_file and then combined with * the database using @ref xcb_xrm_database_combine() with override set to * true. * If XENVIRONMENT is not specified, the same is done with * $HOME/.Xdefaults-$HOSTNAME, wherein $HOSTNAME is determined by * gethostname(2). * * This represents the way XGetDefault() creates the database for the most * part, but is not exactly the same. In particular, XGetDefault() does not * consider $HOME/.Xresources. * * @param conn XCB connection. * @returns The constructed database. Can return NULL, e.g., if the screen * cannot be determined. */ xcb_xrm_database_t *xcb_xrm_database_from_default(xcb_connection_t *conn) { xcb_screen_t *screen; xcb_xrm_database_t *database; char *xenvironment; screen = xcb_aux_get_screen(conn, 0); if (screen == NULL) return NULL; /* 1. Try to load the database from RESOURCE_MANAGER. */ database = xcb_xrm_database_from_resource_manager(conn, screen); /* 2. Otherwise, try to load the database from $HOME/.Xresources. */ if (database == NULL) { char *xresources = get_home_dir_file(".Xresources"); database = xcb_xrm_database_from_file(xresources); FREE(xresources); } /* 3. Otherwise, try to load the database from $HOME/.Xdefaults. */ if (database == NULL) { char *xdefaults = get_home_dir_file(".Xdefaults"); database = xcb_xrm_database_from_file(xdefaults); FREE(xdefaults); } /* 4. If XENVIRONMENT is specified, merge the database defined by that file. * Otherwise, use $HOME/.Xdefaults-$HOSTNAME. */ if ((xenvironment = getenv("XENVIRONMENT")) != NULL) { xcb_xrm_database_t *source = xcb_xrm_database_from_file(xenvironment); xcb_xrm_database_combine(source, &database, true); xcb_xrm_database_free(source); } else { char hostname[1024]; hostname[1023] = '\0'; if (gethostname(hostname, 1023) == 0) { char *name; if (asprintf(&name, ".Xdefaults-%s", hostname) >= 0) { xcb_xrm_database_t *source; char *xdefaults = get_home_dir_file(name); FREE(name); source = xcb_xrm_database_from_file(xdefaults); FREE(xdefaults); xcb_xrm_database_combine(source, &database, true); xcb_xrm_database_free(source); } } } return database; }
void scan_windows(void) { const int screens_len = xcb_setup_roots_length(xcb_get_setup(wm_conf.connection)); int screen_idx; xcb_window_t root_wins[screens_len]; xcb_query_tree_cookie_t root_tree_cookies[screens_len]; /* request window trees for the root window of each screen */ for (screen_idx = 0; screen_idx < screens_len; ++screen_idx) { xcb_screen_t *screen = xcb_aux_get_screen(wm_conf.connection, screen_idx); root_wins[screen_idx] = screen->root; root_tree_cookies[screen_idx] = xcb_query_tree_unchecked(wm_conf.connection, root_wins[screen_idx]); } xcb_query_tree_reply_t *root_tree_replies[screens_len]; xcb_window_t *wins; int wins_len; /* collect replies */ for (screen_idx = 0; screen_idx < screens_len; ++screen_idx) { root_tree_replies[screen_idx] = xcb_query_tree_reply(wm_conf.connection, root_tree_cookies[screen_idx], NULL); wins = xcb_query_tree_children(root_tree_replies[screen_idx]); if (!wins) fprintf(stderr, "failed to get child tree for window %u\n", root_wins[screen_idx]); wins_len = xcb_query_tree_children_length(root_tree_replies[screen_idx]); fprintf(stderr, "root window %u has %d children\n", root_wins[screen_idx], wins_len); fprintf(stderr, "examining children\n"); xcb_window_t child_win; int i; for (i = 0; i < wins_len; ++i) { child_win = wins[i]; fprintf(stderr, " child window %u\n", child_win); client_t *client = find_client(child_win); if (!client) { client = client_init(client_alloc()); client->window = child_win; sglib_client_t_add(&client_list, client); } read_client_geometry(client); } } for (screen_idx = 0; screen_idx < screens_len; ++screen_idx) free(root_tree_replies[screen_idx]); }
xcb_visualtype_t * xcb_aux_get_visualtype (xcb_connection_t *c, int scr, xcb_visualid_t vid) { xcb_screen_t *screen; xcb_depth_t *depth; xcb_visualtype_iterator_t iter; int cur; screen = xcb_aux_get_screen (c, scr); if (!screen) return NULL; depth = xcb_screen_allowed_depths_iterator(screen).data; if (!depth) return NULL; iter = xcb_depth_visuals_iterator(depth); for (cur = 0 ; cur < iter.rem ; xcb_visualtype_next(&iter), ++cur) if (vid == iter.data->visual_id) return iter.data; return NULL; }
int main ( int argc, char *argv[] ) { TIMINGS_START (); cmd_set_arguments ( argc, argv ); // Version if ( find_arg ( "-v" ) >= 0 || find_arg ( "-version" ) >= 0 ) { #ifdef GIT_VERSION fprintf ( stdout, "Version: "GIT_VERSION "\n" ); #else fprintf ( stdout, "Version: "VERSION "\n" ); #endif exit ( EXIT_SUCCESS ); } // Detect if we are in dmenu mode. // This has two possible causes. // 1 the user specifies it on the command-line. if ( find_arg ( "-dmenu" ) >= 0 ) { dmenu_mode = TRUE; } // 2 the binary that executed is called dmenu (e.g. symlink to rofi) else{ // Get the base name of the executable called. char *base_name = g_path_get_basename ( argv[0] ); const char * const dmenu_str = "dmenu"; dmenu_mode = ( strcmp ( base_name, dmenu_str ) == 0 ); // Free the basename for dmenu detection. g_free ( base_name ); } TICK (); // Get the path to the cache dir. cache_dir = g_get_user_cache_dir (); // Create pid file path. const char *path = g_get_user_runtime_dir (); if ( path ) { pidfile = g_build_filename ( path, "rofi.pid", NULL ); } config_parser_add_option ( xrm_String, "pid", (void * *) &pidfile, "Pidfile location" ); if ( find_arg ( "-config" ) < 0 ) { const char *cpath = g_get_user_config_dir (); if ( cpath ) { config_path = g_build_filename ( cpath, "rofi", "config", NULL ); } } else { char *c = NULL; find_arg_str ( "-config", &c ); config_path = rofi_expand_path ( c ); } TICK (); // Register cleanup function. atexit ( cleanup ); TICK (); // Get DISPLAY, first env, then argument. char *display_str = getenv ( "DISPLAY" ); find_arg_str ( "-display", &display_str ); if ( setlocale ( LC_ALL, "" ) == NULL ) { fprintf ( stderr, "Failed to set locale.\n" ); return EXIT_FAILURE; } xcb->connection = xcb_connect ( display_str, &xcb->screen_nbr ); if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Failed to open display: %s", display_str ); return EXIT_FAILURE; } TICK_N ( "Open Display" ); xcb->screen = xcb_aux_get_screen ( xcb->connection, xcb->screen_nbr ); xcb_intern_atom_cookie_t *ac = xcb_ewmh_init_atoms ( xcb->connection, &xcb->ewmh ); xcb_generic_error_t *errors = NULL; xcb_ewmh_init_atoms_replies ( &xcb->ewmh, ac, &errors ); if ( errors ) { fprintf ( stderr, "Failed to create EWMH atoms\n" ); free ( errors ); } if ( xkb_x11_setup_xkb_extension ( xcb->connection, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &xkb.first_event, NULL ) < 0 ) { fprintf ( stderr, "cannot setup XKB extension!\n" ); return EXIT_FAILURE; } xkb.context = xkb_context_new ( XKB_CONTEXT_NO_FLAGS ); if ( xkb.context == NULL ) { fprintf ( stderr, "cannot create XKB context!\n" ); return EXIT_FAILURE; } xkb.xcb_connection = xcb->connection; xkb.device_id = xkb_x11_get_core_keyboard_device_id ( xcb->connection ); enum { required_events = ( XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY ), required_nkn_details = ( XCB_XKB_NKN_DETAIL_KEYCODES ), required_map_parts = ( XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP ), required_state_details = ( XCB_XKB_STATE_PART_MODIFIER_BASE | XCB_XKB_STATE_PART_MODIFIER_LATCH | XCB_XKB_STATE_PART_MODIFIER_LOCK | XCB_XKB_STATE_PART_GROUP_BASE | XCB_XKB_STATE_PART_GROUP_LATCH | XCB_XKB_STATE_PART_GROUP_LOCK ), }; static const xcb_xkb_select_events_details_t details = { .affectNewKeyboard = required_nkn_details, .newKeyboardDetails = required_nkn_details, .affectState = required_state_details, .stateDetails = required_state_details, }; xcb_xkb_select_events ( xcb->connection, xkb.device_id, required_events, /* affectWhich */ 0, /* clear */ required_events, /* selectAll */ required_map_parts, /* affectMap */ required_map_parts, /* map */ &details ); xkb.keymap = xkb_x11_keymap_new_from_device ( xkb.context, xcb->connection, xkb.device_id, XKB_KEYMAP_COMPILE_NO_FLAGS ); if ( xkb.keymap == NULL ) { fprintf ( stderr, "Failed to get Keymap for current keyboard device.\n" ); return EXIT_FAILURE; } xkb.state = xkb_x11_state_new_from_device ( xkb.keymap, xcb->connection, xkb.device_id ); if ( xkb.state == NULL ) { fprintf ( stderr, "Failed to get state object for current keyboard device.\n" ); return EXIT_FAILURE; } xkb.compose.table = xkb_compose_table_new_from_locale ( xkb.context, setlocale ( LC_CTYPE, NULL ), 0 ); if ( xkb.compose.table != NULL ) { xkb.compose.state = xkb_compose_state_new ( xkb.compose.table, 0 ); } else { fprintf ( stderr, "Failed to get keyboard compose table. Trying to limp on.\n" ); } if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } x11_setup ( &xkb ); if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } const xcb_query_extension_reply_t *er = xcb_get_extension_data ( xcb->connection, &xcb_xinerama_id ); if ( er ) { if ( er->present ) { xcb_xinerama_is_active_cookie_t is_active_req = xcb_xinerama_is_active ( xcb->connection ); xcb_xinerama_is_active_reply_t *is_active = xcb_xinerama_is_active_reply ( xcb->connection, is_active_req, NULL ); xcb->has_xinerama = is_active->state; free ( is_active ); } } main_loop = g_main_loop_new ( NULL, FALSE ); TICK_N ( "Setup mainloop" ); // startup not. xcb->sndisplay = sn_xcb_display_new ( xcb->connection, error_trap_push, error_trap_pop ); if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } if ( xcb->sndisplay != NULL ) { xcb->sncontext = sn_launchee_context_new_from_environment ( xcb->sndisplay, xcb->screen_nbr ); } if ( xcb_connection_has_error ( xcb->connection ) ) { fprintf ( stderr, "Connection has error\n" ); exit ( EXIT_FAILURE ); } TICK_N ( "Startup Notification" ); // Initialize Xresources subsystem. config_parse_xresource_init (); TICK_N ( "Initialize Xresources system" ); // Setup keybinding setup_abe (); TICK_N ( "Setup abe" ); if ( find_arg ( "-no-config" ) < 0 ) { load_configuration ( ); } if ( !dmenu_mode ) { // setup_modi setup_modi (); } if ( find_arg ( "-no-config" ) < 0 ) { // Reload for dynamic part. load_configuration_dynamic ( ); } // Dump. // catch help request if ( find_arg ( "-h" ) >= 0 || find_arg ( "-help" ) >= 0 || find_arg ( "--help" ) >= 0 ) { help ( argc, argv ); exit ( EXIT_SUCCESS ); } if ( find_arg ( "-dump-xresources" ) >= 0 ) { config_parse_xresource_dump (); exit ( EXIT_SUCCESS ); } if ( find_arg ( "-dump-xresources-theme" ) >= 0 ) { config_parse_xresources_theme_dump (); exit ( EXIT_SUCCESS ); } main_loop_source = g_water_xcb_source_new_for_connection ( NULL, xcb->connection, main_loop_x11_event_handler, NULL, NULL ); TICK_N ( "X11 Setup " ); rofi_view_workers_initialize (); // Setup signal handling sources. // SIGINT g_unix_signal_add ( SIGINT, main_loop_signal_handler_int, NULL ); g_idle_add ( startup, NULL ); // Start mainloop. g_main_loop_run ( main_loop ); return return_code; }
ZLEwlViewWidget::ZLEwlViewWidget(ZLApplication *application, ZLView::Angle initialAngle) : ZLViewWidget(initialAngle) { myApplication = application; w = 600; h = 800; xcb_screen_iterator_t screen_iter; const xcb_setup_t *setup; xcb_generic_event_t *e; xcb_generic_error_t *error; xcb_void_cookie_t cookie_window; xcb_void_cookie_t cookie_map; uint32_t mask; uint32_t values[2]; int screen_number; uint8_t is_hand = 0; xcb_rectangle_t rect_coord = { 0, 0, 600, 800}; /* getting the connection */ connection = xcb_connect (NULL, &screen_number); if (xcb_connection_has_error(connection)) { fprintf (stderr, "ERROR: can't connect to an X server\n"); exit(-1); } screen = xcb_aux_get_screen (connection, screen_number); gc = xcb_generate_id (connection); mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; values[0] = screen->black_pixel; values[1] = 0; /* no graphics exposures */ xcb_create_gc (connection, gc, screen->root, mask, values); bgcolor = xcb_generate_id (connection); mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; values[0] = screen->white_pixel; values[1] = 0; /* no graphics exposures */ xcb_create_gc (connection, bgcolor, screen->root, mask, values); /* creating the window */ window = xcb_generate_id(connection); mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; values[0] = screen->white_pixel; values[1] = XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE; uint8_t depth = xcb_aux_get_depth (connection, screen); xcb_create_window(connection, depth, window, screen->root, 0, 0, 600, 800, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, values); rect = xcb_generate_id (connection); xcb_create_pixmap (connection, depth, rect, window, 600, 800); xcb_map_window(connection, window); xcb_colormap_t colormap; colormap = screen->default_colormap; xcb_alloc_color_reply_t *rep; rep = xcb_alloc_color_reply (connection, xcb_alloc_color (connection, colormap, 0, 0, 0), NULL); pal_[0] = rep->pixel; free(rep); rep = xcb_alloc_color_reply (connection, xcb_alloc_color (connection, colormap, 0x55<<8, 0x55<<8, 0x55<<8), NULL); pal_[1] = rep->pixel; free(rep); rep = xcb_alloc_color_reply (connection, xcb_alloc_color (connection, colormap, 0xaa<<8, 0xaa<<8, 0xaa<<8), NULL); pal_[2] = rep->pixel; free(rep); rep = xcb_alloc_color_reply (connection, xcb_alloc_color (connection, colormap, 0xff<<8, 0xff<<8, 0xff<<8), NULL); pal_[3] = rep->pixel; free(rep); pal = pal_; xcb_shm_query_version_reply_t *rep_shm; rep_shm = xcb_shm_query_version_reply (connection, xcb_shm_query_version (connection), NULL); if(rep_shm) { xcb_image_format_t format; int shmctl_status; if (rep_shm->shared_pixmaps && (rep_shm->major_version > 1 || rep_shm->minor_version > 0)) format = (xcb_image_format_t)rep_shm->pixmap_format; else format = (xcb_image_format_t)0; im = xcb_image_create_native (connection, 600, 800, format, depth, NULL, ~0, NULL); assert(im); shminfo.shmid = shmget (IPC_PRIVATE, im->stride*im->height, IPC_CREAT | 0777); assert(shminfo.shmid != -1); shminfo.shmaddr = (uint8_t*)shmat (shminfo.shmid, 0, 0); assert(shminfo.shmaddr); im->data = shminfo.shmaddr; shminfo.shmseg = xcb_generate_id (connection); xcb_shm_attach (connection, shminfo.shmseg, shminfo.shmid, 0); shmctl_status = shmctl(shminfo.shmid, IPC_RMID, 0); assert(shmctl_status != -1); free (rep_shm); } xcb_flush(connection); }
int main(int argc, char *argv[]) { format = sstrdup("%s"); char *socket_path = NULL; char *pattern = sstrdup("pango:monospace 8"); 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'}, {"format", required_argument, 0, 'F'}, {"font", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; char *options_string = "s:p:P:f:l:F:vh"; while ((o = getopt_long(argc, argv, options_string, long_options, &option_index)) != -1) { switch (o) { case 's': FREE(socket_path); socket_path = sstrdup(optarg); break; case 'v': printf("i3-input " I3_VERSION); return 0; case 'p': /* This option is deprecated, but will still work in i3 v4.1, 4.2 and 4.3 */ fprintf(stderr, "i3-input: WARNING: the -p option is DEPRECATED in favor of the -F (format) option\n"); FREE(format); sasprintf(&format, "%s%%s", optarg); break; case 'l': limit = atoi(optarg); break; case 'P': i3string_free(prompt); prompt = i3string_from_utf8(optarg); break; case 'f': FREE(pattern); pattern = sstrdup(optarg); break; case 'F': FREE(format); format = sstrdup(optarg); break; case 'h': printf("i3-input " I3_VERSION "\n"); printf("i3-input [-s <socket>] [-F <format>] [-l <limit>] [-P <prompt>] [-f <font>] [-v]\n"); printf("\n"); printf("Example:\n"); printf(" i3-input -F 'workspace \"%%s\"' -P 'Switch to workspace: '\n"); return 0; } } printf("using format \"%s\"\n", format); int screen; conn = xcb_connect(NULL, &screen); if (!conn || xcb_connection_has_error(conn)) die("Cannot open display\n"); sockfd = ipc_connect(socket_path); root_screen = xcb_aux_get_screen(conn, screen); root = root_screen->root; symbols = xcb_key_symbols_alloc(conn); init_dpi(); font = load_font(pattern, true); set_font(&font); if (prompt != NULL) prompt_offset = predict_text_width(prompt); const xcb_rectangle_t win_pos = get_window_position(); /* Open an input window */ win = xcb_generate_id(conn); xcb_create_window( conn, XCB_COPY_FROM_PARENT, win, /* the window id */ root, /* parent == root */ win_pos.x, win_pos.y, win_pos.width, win_pos.height, /* 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_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, (uint32_t[]){ 0, /* back pixel: black */ 1, /* override redirect: don’t manage this window */ XCB_EVENT_MASK_EXPOSURE}); /* Map the window (make it visible) */ xcb_map_window(conn, win); /* Initialize the drawable surface */ draw_util_surface_init(conn, &surface, win, get_visualtype(root_screen), win_pos.width, win_pos.height); /* 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; case XCB_KEY_RELEASE: handle_key_release(NULL, conn, (xcb_key_release_event_t *)event); break; case XCB_EXPOSE: if (((xcb_expose_event_t *)event)->count == 0) { handle_expose(NULL, conn, (xcb_expose_event_t *)event); } break; } free(event); } draw_util_surface_free(conn, &surface); return 0; }
static int dri2_connect(Display *display) { xcb_dri2_query_version_cookie_t query_version_cookie; xcb_dri2_query_version_reply_t *query_version_reply; xcb_dri2_connect_cookie_t connect_cookie; xcb_dri2_connect_reply_t *connect_reply; xcb_dri2_authenticate_cookie_t auth_cookie; xcb_dri2_authenticate_reply_t *auth_reply; xcb_screen_t *root; xcb_connection_t *c = XGetXCBConnection(display); drm_magic_t magic; const xcb_query_extension_reply_t *dri2_reply; char *device_name; int len; root = xcb_aux_get_screen(c, DefaultScreen(display)); dri2_reply = xcb_get_extension_data(c, &xcb_dri2_id); if (!dri2_reply) { XVMC_ERR("DRI2 required"); return BadValue; } /* Query the extension and make our first use of it at the same time. */ query_version_cookie = xcb_dri2_query_version(c, 1, 0); connect_cookie = xcb_dri2_connect(c, root->root, DRI2DriverDRI); query_version_reply = xcb_dri2_query_version_reply(c, query_version_cookie, NULL); connect_reply = xcb_dri2_connect_reply(c, connect_cookie, NULL); if (!query_version_reply) { XVMC_ERR("DRI2 required"); return BadValue; } free(query_version_reply); len = xcb_dri2_connect_device_name_length(connect_reply); device_name = malloc(len + 1); if (!device_name) { XVMC_ERR("malloc failure"); return BadAlloc; } strncpy(device_name, xcb_dri2_connect_device_name(connect_reply), len); device_name[len] = 0; xvmc_driver->fd = open(device_name, O_RDWR); free(device_name); free(connect_reply); if (xvmc_driver->fd < 0) { XVMC_ERR("Failed to open drm device: %s\n", strerror(errno)); return BadValue; } if (drmGetMagic(xvmc_driver->fd, &magic)) { XVMC_ERR("Failed to get magic\n"); return BadValue; } auth_cookie = xcb_dri2_authenticate(c, root->root, magic); auth_reply = xcb_dri2_authenticate_reply(c, auth_cookie, NULL); if (!auth_reply) { XVMC_ERR("Failed to authenticate magic %d\n", magic); return BadValue; } free(auth_reply); return Success; }
static gboolean _eventd_nd_xcb_start(EventdNdBackendContext *self, const gchar *target) { gint r; gchar *h; gint d; r = xcb_parse_display(target, &h, &d, NULL); if ( r == 0 ) return FALSE; free(h); const xcb_query_extension_reply_t *extension_query; gint screen; self->source = g_water_xcb_source_new(NULL, target, &screen, _eventd_nd_xcb_events_callback, self, NULL); if ( self->source == NULL ) { g_warning("Couldn't initialize X connection for '%s'", target); return FALSE; } self->xcb_connection = g_water_xcb_source_get_connection(self->source); self->screen_number = screen; self->screen = xcb_aux_get_screen(self->xcb_connection, screen); self->bubbles = g_hash_table_new(NULL, NULL); if ( self->follow_focus != EVENTD_ND_XCB_FOLLOW_FOCUS_NONE ) { guint32 mask[] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; xcb_change_window_attributes(self->xcb_connection, self->screen->root, XCB_CW_EVENT_MASK, mask); } xcb_intern_atom_cookie_t *ac; ac = xcb_ewmh_init_atoms(self->xcb_connection, &self->ewmh); xcb_ewmh_init_atoms_replies(&self->ewmh, ac, NULL); extension_query = xcb_get_extension_data(self->xcb_connection, &xcb_randr_id); if ( ! extension_query->present ) g_warning("No RandR extension"); else { self->randr = TRUE; self->randr_event_base = extension_query->first_event; xcb_randr_select_input(self->xcb_connection, self->screen->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE | XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE | XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE | XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY); } self->custom_map = _eventd_nd_xcb_get_colormap(self); if ( self->custom_map ) { /* We have a 32bit color map, try to support compositing */ xcb_get_selection_owner_cookie_t oc; xcb_window_t owner; oc = xcb_ewmh_get_wm_cm_owner(&self->ewmh, self->screen_number); self->compositing = xcb_ewmh_get_wm_cm_owner_reply(&self->ewmh, oc, &owner, NULL) && ( owner != XCB_WINDOW_NONE ); extension_query = xcb_get_extension_data(self->xcb_connection, &xcb_xfixes_id); if ( ! extension_query->present ) g_warning("No XFixes extension"); else { xcb_xfixes_query_version_cookie_t vc; xcb_xfixes_query_version_reply_t *r; vc = xcb_xfixes_query_version(self->xcb_connection, XCB_XFIXES_MAJOR_VERSION, XCB_XFIXES_MINOR_VERSION); r = xcb_xfixes_query_version_reply(self->xcb_connection, vc, NULL); if ( r == NULL ) g_warning("Cannot get XFixes version"); else { self->xfixes = TRUE; self->xfixes_event_base = extension_query->first_event; xcb_xfixes_select_selection_input_checked(self->xcb_connection, self->screen->root, self->ewmh._NET_WM_CM_Sn[self->screen_number], XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE); } } } extension_query = xcb_get_extension_data(self->xcb_connection, &xcb_shape_id); if ( ! extension_query->present ) g_warning("No Shape extension"); else self->shape = TRUE; xcb_flush(self->xcb_connection); _eventd_nd_xcb_check_geometry(self); return TRUE; }
int main(int argc, char **argv) { memset(&globalconf, 0, sizeof(globalconf)); globalconf.connection = xcb_connect(NULL, &globalconf.screen_nbr); if(xcb_connection_has_error(globalconf.connection)) fatal("Cannot open display"); /* Get the root window */ globalconf.screen = xcb_aux_get_screen(globalconf.connection, globalconf.screen_nbr); /* Set up signal handlers and function called on normal exit */ struct sigaction sa; sigemptyset(&sa.sa_mask); sa.sa_handler = exit_on_signal; sa.sa_flags = 0; sigaction(SIGHUP, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); atexit(exit_cleanup); /** * First round-trip */ /* Send requests for EWMH atoms initialisation */ xcb_intern_atom_cookie_t *ewmh_cookies = atoms_init(); parse_command_line_parameters(argc, argv); /* Prefetch the extensions data */ xcb_prefetch_extension_data(globalconf.connection, &xcb_composite_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_damage_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_xfixes_id); /* Initialise errors handlers */ xcb_event_handlers_init(globalconf.connection, &globalconf.evenths); event_init_start_handlers(); /* Pre-initialisation of the rendering backend */ if(!rendering_load()) { free(ewmh_cookies); fatal("Can't initialise rendering backend"); } /* Get replies for EWMH atoms initialisation */ if(!atoms_init_finalise(ewmh_cookies)) /* No need to free ewmh_cookies in case of error as it's already handles by xcb-ewmh when getting the replies */ fatal("Cannot initialise atoms"); /* First check whether there is already a Compositing Manager (ICCCM) */ xcb_get_selection_owner_cookie_t wm_cm_owner_cookie = xcb_ewmh_get_wm_cm_owner(&globalconf.ewmh, globalconf.screen_nbr); /** * Second round-trip */ /* Initialise extensions based on the cache and perform initialisation of the rendering backend */ display_init_extensions(); if(!(*globalconf.rendering->init)()) return EXIT_FAILURE; /* Check ownership for WM_CM_Sn before actually claiming it (ICCCM) */ xcb_window_t wm_cm_owner_win; if(xcb_ewmh_get_wm_cm_owner_reply(&globalconf.ewmh, wm_cm_owner_cookie, &wm_cm_owner_win, NULL) && wm_cm_owner_win != XCB_NONE) fatal("A compositing manager is already active (window=%jx)", (uintmax_t) wm_cm_owner_win); /* Now send requests to register the CM */ display_register_cm(); /** * Third round-trip */ /* Check extensions version and finish initialisation of the rendering backend */ display_init_extensions_finalise(); if(!(*globalconf.rendering->init_finalise)()) return EXIT_FAILURE; /* All the plugins given in the configuration file */ plugin_load_all(); /* Validate errors and get PropertyNotify needed to acquire _NET_WM_CM_Sn ownership */ xcb_aux_sync(globalconf.connection); xcb_event_poll_for_event_loop(&globalconf.evenths); globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection); xcb_get_modifier_mapping_cookie_t key_mapping_cookie = xcb_get_modifier_mapping_unchecked(globalconf.connection); /* Finish CM X registration */ if(!display_register_cm_finalise()) fatal("Could not acquire _NET_WM_CM_Sn ownership"); /** * Last initialisation round-trip */ /* Grab the server before performing redirection and get the tree of windows to ensure there won't be anything else at the same time */ xcb_grab_server(globalconf.connection); /* Now redirect windows and add existing windows */ display_init_redirect(); /* Validate errors handlers during redirect */ xcb_aux_sync(globalconf.connection); xcb_event_poll_for_event_loop(&globalconf.evenths); /* Manage existing windows */ display_init_redirect_finalise(); xcb_ungrab_server(globalconf.connection); /* Check the plugin requirements which will disable plugins which don't meet the requirements */ plugin_check_requirements(); /* Get the lock masks reply of the request previously sent */ key_lock_mask_get_reply(key_mapping_cookie); /* Initialise normal errors and events handlers */ event_init_handlers(); xcb_generic_event_t *event; /* Flush existing requests before the loop as DamageNotify events may have been received in the meantime */ xcb_flush(globalconf.connection); globalconf.do_repaint = true; /* Main event and error loop */ do { /* Block until an event is received */ event = xcb_wait_for_event(globalconf.connection); /* Check X connection to avoid SIGSEGV */ if(xcb_connection_has_error(globalconf.connection)) fatal("X connection invalid"); xcb_event_handle(&globalconf.evenths, event); free(event); /* Then process all remaining events in the queue because before painting, all the DamageNotify have to be received */ xcb_event_poll_for_event_loop(&globalconf.evenths); /* Now paint the windows */ if(globalconf.do_repaint) { window_t *windows = NULL; for(plugin_t *plugin = globalconf.plugins; plugin; plugin = plugin->next) if(plugin->enable && plugin->vtable->render_windows && (windows = (*plugin->vtable->render_windows)())) break; if(!windows) windows = globalconf.windows; window_paint_all(windows); xcb_aux_sync(globalconf.connection); } globalconf.do_repaint = false; } while(true); return EXIT_SUCCESS; }
/** * sn_xcb_display_new: * @xdisplay: an X window system connection * @push_trap_func: function to push an X error trap * @pop_trap_func: function to pop an X error trap * * Creates a new #SnDisplay object, containing * data that libsn associates with an X connection. * * @push_trap_func should be a function that causes X errors to be * ignored until @pop_trap_func is called as many times as * @push_trap_func has been called. (Nested push/pop pairs must be * supported.) * These functions are used to avoid X errors due to BadWindow and * such. * * Return value: the new #SnDisplay **/ SnDisplay* sn_xcb_display_new (xcb_connection_t *xconnection, SnXcbDisplayErrorTrapPush push_trap_func, SnXcbDisplayErrorTrapPop pop_trap_func) { SnDisplay *display; int i; /* Get all atoms we will need in the future */ xcb_intern_atom_cookie_t atom_utf8_string_c = xcb_intern_atom(xconnection, FALSE, sizeof("UTF8_STRING") - 1, "UTF8_STRING"); xcb_intern_atom_cookie_t atom_net_startup_info_begin_c = xcb_intern_atom(xconnection, FALSE, sizeof("_NET_STARTUP_INFO_BEGIN") - 1, "_NET_STARTUP_INFO_BEGIN"); xcb_intern_atom_cookie_t atom_net_startup_info_c = xcb_intern_atom(xconnection, FALSE, sizeof("_NET_STARTUP_INFO") - 1, "_NET_STARTUP_INFO"); xcb_intern_atom_cookie_t atom_net_startup_id_c = xcb_intern_atom(xconnection, FALSE, sizeof("_NET_STARTUP_ID") - 1, "_NET_STARTUP_ID"); display = sn_new0 (SnDisplay, 1); display->xconnection = xconnection; display->n_screens = xcb_setup_roots_length (xcb_get_setup (xconnection)); display->screens = sn_new (xcb_screen_t*, display->n_screens); display->refcount = 1; display->xcb_push_trap_func = push_trap_func; display->xcb_pop_trap_func = pop_trap_func; for (i = 0; i < display->n_screens; ++i) display->screens[i] = xcb_aux_get_screen(xconnection, i); xcb_intern_atom_reply_t *atom_reply; atom_reply = xcb_intern_atom_reply(display->xconnection, atom_utf8_string_c, NULL); display->UTF8_STRING = atom_reply->atom; free(atom_reply); atom_reply = xcb_intern_atom_reply(display->xconnection, atom_net_startup_info_begin_c, NULL); display->NET_STARTUP_INFO_BEGIN = atom_reply->atom; free(atom_reply); atom_reply = xcb_intern_atom_reply(display->xconnection, atom_net_startup_info_c, NULL); display->NET_STARTUP_INFO = atom_reply->atom; free(atom_reply); atom_reply = xcb_intern_atom_reply(display->xconnection, atom_net_startup_id_c, NULL); display->NET_STARTUP_ID = atom_reply->atom; free(atom_reply); return display; }
/* Main driver */ int main (int argc, char **argv) { xcb_connection_t *conn; int conn_screen; xcb_screen_t *root_screen; xcb_drawable_t root_window; xcb_connection_t *conn_two; int conn_two_screen; xcb_screen_t *root_two_screen; xcb_drawable_t root_two_window; xcb_drawable_t window; uint32_t mask; uint32_t values[1]; xcb_void_cookie_t cookie; xcb_get_geometry_reply_t *geom_reply; xcb_generic_event_t *event; image_data_t img_data; xcb_image_t *image; xcb_pixmap_t pixmap; xcb_gcontext_t gc; /* Check the first argument to see what display to connect to. If empty, then use default display. */ if (argc > 1) { conn = xcb_connect(argv[1], &conn_screen); } else { conn = xcb_connect(NULL, &conn_screen); } root_screen = xcb_aux_get_screen(conn, conn_screen); root_window = root_screen->root; /* Get the geometry of the root window */ geom_reply = GetWindowGeometry(conn, root_window); WriteWindowInfo(conn, root_window); WriteAllChildrenWindowInfo(conn, root_window); img_data = GetWindowImageData(conn, root_window); xcb_flush(conn); /* Get the image of the root window */ image = xcb_image_get(conn, root_window, geom_reply->x, geom_reply->y, geom_reply->width, geom_reply->height, (unsigned int) ~0L, XCB_IMAGE_FORMAT_Z_PIXMAP); /* Set up the events the window will recognize */ mask = XCB_CW_EVENT_MASK; values[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS; /* Create our new window on the default display. Make it half the size */ conn_two = xcb_connect(NULL, &conn_two_screen); root_two_screen = xcb_aux_get_screen(conn_two, conn_two_screen); root_two_window = root_two_screen->root; window = xcb_generate_id(conn_two); cookie = xcb_create_window_checked(conn_two, XCB_COPY_FROM_PARENT, window, root_two_window, geom_reply->x, geom_reply->y, geom_reply->width / 2, geom_reply->height / 2, geom_reply->border_width, XCB_WINDOW_CLASS_INPUT_OUTPUT, root_two_screen->root_visual, mask, values); if (RequestCheck(conn_two, cookie, "Falied to create new window")) { exit(1); } WriteWindowInfo(conn_two, window); /* Map the window and flush the connection so it draws to the screen */ xcb_map_window(conn_two, window); xcb_flush(conn_two); WriteWindowInfo(conn_two, window); /* Create the pixmap and associate it with our new window. */ pixmap = xcb_generate_id(conn_two); cookie = xcb_create_pixmap(conn_two, geom_reply->depth, pixmap, window, geom_reply->width, geom_reply->height); if (RequestCheck(conn_two, cookie, "Failed to create pixmap")) { exit(1); } /* Put the root_window image into the pixmap. Note that a gc is * created, but I believe it is ignored. */ gc = xcb_generate_id(conn_two); xcb_create_gc(conn_two, gc, window, 0, 0); cookie = xcb_image_put(conn_two, pixmap, gc, image, 0, 0, 0); if (RequestCheck(conn_two, cookie, "Failed to put image into pixmap")) { exit(1); } /* Copy the pixmap into the new window */ cookie = xcb_copy_area(conn_two, pixmap, window, gc, 0, 0, 0, 0, geom_reply->width / 2, geom_reply->height / 2); if (RequestCheck(conn_two, cookie, "Failed to put image into pixmap")) { exit(1); } xcb_flush(conn_two); WriteWindowInfo(conn_two, window); /* Enter infinte loop so the window stays open */ while (1) { } /* Never get here, but if we could, would still want to clean up memory */ free(geom_reply); xcb_disconnect(conn); xcb_disconnect(conn_two); return 0; }
/* * 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; }
// ===== startSystemTray() ===== WId LXCB::startSystemTray(int screen){ qDebug() << "Starting System Tray:" << screen; //Setup the freedesktop standards compliance //Get the appropriate atom for this screen QString str = QString("_NET_SYSTEM_TRAY_S%1").arg(QString::number(screen)); //qDebug() << "Default Screen Atom Name:" << str; xcb_intern_atom_reply_t *treply = xcb_intern_atom_reply(QX11Info::connection(), \ xcb_intern_atom(QX11Info::connection(), 0, str.length(), str.toLocal8Bit()), NULL); xcb_intern_atom_reply_t *oreply = xcb_intern_atom_reply(QX11Info::connection(), \ xcb_intern_atom(QX11Info::connection(), 0, 28, "_NET_SYSTEM_TRAY_ORIENTATION"), NULL); xcb_intern_atom_reply_t *vreply = xcb_intern_atom_reply(QX11Info::connection(), \ xcb_intern_atom(QX11Info::connection(), 0, 23, "_NET_SYSTEM_TRAY_VISUAL"), NULL); if(treply==0){ qDebug() << " - ERROR: Could not initialize _NET_SYSTEM_TRAY_S<num> atom"; return 0; } if(oreply==0){ qDebug() << " - ERROR: Could not initialize _NET_SYSTEM_TRAY_ORIENTATION atom"; return 0; } if(vreply==0){ qDebug() << " - ERROR: Could not initialize _NET_SYSTEM_TRAY_VISUAL atom"; return 0; } xcb_atom_t _NET_SYSTEM_TRAY_S = treply->atom; xcb_atom_t _NET_SYSTEM_TRAY_ORIENTATION = oreply->atom; xcb_atom_t _NET_SYSTEM_TRAY_VISUAL = vreply->atom; free(treply); //done with atom generation free(oreply); free(vreply); //Make sure that there is no other system tray running xcb_get_selection_owner_reply_t *ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \ xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL); if(ownreply==0){ qWarning() << " - Could not get owner selection reply"; return 0; } if(ownreply->owner != 0){ free(ownreply); qWarning() << " - An alternate system tray is currently in use"; return 0; } free(ownreply); //Create a simple window to register as the tray (not visible - just off the screen) xcb_screen_t *root_screen = xcb_aux_get_screen(QX11Info::connection(), QX11Info::appScreen()); uint32_t params[] = {1}; WId LuminaSessionTrayID = xcb_generate_id(QX11Info::connection()); //need a new ID xcb_create_window(QX11Info::connection(), root_screen->root_depth, \ LuminaSessionTrayID, root_screen->root, -1, -1, 1, 1, 0, \ XCB_WINDOW_CLASS_INPUT_OUTPUT, root_screen->root_visual, \ XCB_CW_OVERRIDE_REDIRECT, params); //Now register this widget as the system tray xcb_set_selection_owner(QX11Info::connection(), LuminaSessionTrayID, _NET_SYSTEM_TRAY_S, XCB_CURRENT_TIME); //Make sure that it was registered properly ownreply = xcb_get_selection_owner_reply(QX11Info::connection(), \ xcb_get_selection_owner_unchecked(QX11Info::connection(), _NET_SYSTEM_TRAY_S), NULL); if(ownreply==0 || ownreply->owner != LuminaSessionTrayID){ if(ownreply!=0){ free(ownreply); } qWarning() << " - Could not register the system tray"; xcb_destroy_window(QX11Info::connection(), LuminaSessionTrayID); return 0; } free(ownreply); //done with structure //Now register the orientation of the system tray uint32_t orient = _NET_SYSTEM_TRAY_ORIENTATION_HORZ; xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, LuminaSessionTrayID, \ _NET_SYSTEM_TRAY_ORIENTATION, XCB_ATOM_CARDINAL, 32, 1, &orient); //Now set the visual ID for the system tray (same as the root window, but TrueColor) xcb_visualtype_t *type = xcb_aux_find_visual_by_attrs(root_screen, XCB_VISUAL_CLASS_TRUE_COLOR, 32); if(type!=0){ xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, LuminaSessionTrayID, \ _NET_SYSTEM_TRAY_VISUAL, XCB_ATOM_VISUALID, 32, 1, &type->visual_id); }else{ qWarning() << " - Could not set TrueColor visual for system tray"; } //Finally, send out an X event letting others know that the system tray is up and running xcb_client_message_event_t event; event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; event.window = root_screen->root; event.type = EWMH.MANAGER; //MANAGER atom event.data.data32[0] = XCB_TIME_CURRENT_TIME; //CurrentTime; event.data.data32[1] = _NET_SYSTEM_TRAY_S; //_NET_SYSTEM_TRAY_S atom event.data.data32[2] = LuminaSessionTrayID; event.data.data32[3] = 0; event.data.data32[4] = 0; xcb_send_event(QX11Info::connection(), 0, root_screen->root, XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event); //Success return LuminaSessionTrayID; }
/** Hello, this is main. * \param argc Who knows. * \param argv Who knows. * \return EXIT_SUCCESS I hope. */ int main(int argc, char **argv) { char *confpath = NULL; int xfd, i, opt; ssize_t cmdlen = 1; xdgHandle xdg; bool no_argb = false; xcb_generic_event_t *event; xcb_query_tree_cookie_t tree_c; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'v' }, { "config", 1, NULL, 'c' }, { "check", 0, NULL, 'k' }, { "no-argb", 0, NULL, 'a' }, { NULL, 0, NULL, 0 } }; /* event loop watchers */ ev_io xio = { .fd = -1 }; ev_check xcheck; ev_prepare a_refresh; ev_signal sigint; ev_signal sigterm; ev_signal sighup; /* clear the globalconf structure */ p_clear(&globalconf, 1); globalconf.keygrabber = LUA_REFNIL; globalconf.mousegrabber = LUA_REFNIL; buffer_init(&globalconf.startup_errors); /* save argv */ for(i = 0; i < argc; i++) cmdlen += a_strlen(argv[i]) + 1; awesome_argv = p_new(char, cmdlen); a_strcpy(awesome_argv, cmdlen, argv[0]); for(i = 1; i < argc; i++) { a_strcat(awesome_argv, cmdlen, " "); a_strcat(awesome_argv, cmdlen, argv[i]); } /* Text won't be printed correctly otherwise */ setlocale(LC_CTYPE, ""); /* Get XDG basedir data */ xdgInitHandle(&xdg); /* init lua */ luaA_init(&xdg); /* check args */ while((opt = getopt_long(argc, argv, "vhkc:a", long_options, NULL)) != -1) switch(opt) { case 'v': eprint_version(); break; case 'h': exit_help(EXIT_SUCCESS); break; case 'k': if(!luaA_parserc(&xdg, confpath, false)) { fprintf(stderr, "✘ Configuration file syntax error.\n"); return EXIT_FAILURE; } else { fprintf(stderr, "✔ Configuration file syntax OK.\n"); return EXIT_SUCCESS; } case 'c': if(a_strlen(optarg)) confpath = a_strdup(optarg); else fatal("-c option requires a file name"); break; case 'a': no_argb = true; break; } globalconf.loop = ev_default_loop(EVFLAG_NOSIGFD); /* register function for signals */ ev_signal_init(&sigint, exit_on_signal, SIGINT); ev_signal_init(&sigterm, exit_on_signal, SIGTERM); ev_signal_init(&sighup, restart_on_signal, SIGHUP); ev_signal_start(globalconf.loop, &sigint); ev_signal_start(globalconf.loop, &sigterm); ev_signal_start(globalconf.loop, &sighup); ev_unref(globalconf.loop); ev_unref(globalconf.loop); ev_unref(globalconf.loop); struct sigaction sa = { .sa_handler = signal_fatal, .sa_flags = 0 }; sigemptyset(&sa.sa_mask); sigaction(SIGSEGV, &sa, 0); /* X stuff */ globalconf.connection = xcb_connect(NULL, &globalconf.default_screen); if(xcb_connection_has_error(globalconf.connection)) fatal("cannot open display"); globalconf.screen = xcb_aux_get_screen(globalconf.connection, globalconf.default_screen); /* FIXME The following two assignments were swapped on purpose */ if(!no_argb) globalconf.visual = a_default_visual(globalconf.screen); if(!globalconf.visual) globalconf.visual = a_argb_visual(globalconf.screen); globalconf.default_depth = a_visual_depth(globalconf.screen, globalconf.visual->visual_id); globalconf.default_cmap = globalconf.screen->default_colormap; if(globalconf.default_depth != globalconf.screen->root_depth) { // We need our own color map if we aren't using the default depth globalconf.default_cmap = xcb_generate_id(globalconf.connection); xcb_create_colormap(globalconf.connection, XCB_COLORMAP_ALLOC_NONE, globalconf.default_cmap, globalconf.screen->root, globalconf.visual->visual_id); } /* Prefetch all the extensions we might need */ xcb_prefetch_extension_data(globalconf.connection, &xcb_big_requests_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_test_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_randr_id); xcb_prefetch_extension_data(globalconf.connection, &xcb_xinerama_id); /* initialize dbus */ a_dbus_init(); /* Get the file descriptor corresponding to the X connection */ xfd = xcb_get_file_descriptor(globalconf.connection); ev_io_init(&xio, &a_xcb_io_cb, xfd, EV_READ); ev_io_start(globalconf.loop, &xio); ev_check_init(&xcheck, &a_xcb_check_cb); ev_check_start(globalconf.loop, &xcheck); ev_unref(globalconf.loop); ev_prepare_init(&a_refresh, &a_refresh_cb); ev_prepare_start(globalconf.loop, &a_refresh); ev_unref(globalconf.loop); /* Grab server */ xcb_grab_server(globalconf.connection); /* Make sure there are no pending events. Since we didn't really do anything * at all yet, we will just discard all events which we received so far. * The above GrabServer should make sure no new events are generated. */ xcb_aux_sync(globalconf.connection); while ((event = xcb_poll_for_event(globalconf.connection)) != NULL) { /* Make sure errors are printed */ uint8_t response_type = XCB_EVENT_RESPONSE_TYPE(event); if(response_type == 0) event_handle(event); p_delete(&event); } { const uint32_t select_input_val = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; /* This causes an error if some other window manager is running */ xcb_change_window_attributes(globalconf.connection, globalconf.screen->root, XCB_CW_EVENT_MASK, &select_input_val); } /* Need to xcb_flush to validate error handler */ xcb_aux_sync(globalconf.connection); /* Process all errors in the queue if any. There can be no events yet, so if * this function returns something, it must be an error. */ if (xcb_poll_for_event(globalconf.connection) != NULL) fatal("another window manager is already running"); /* Prefetch the maximum request length */ xcb_prefetch_maximum_request_length(globalconf.connection); /* check for xtest extension */ const xcb_query_extension_reply_t *xtest_query; xtest_query = xcb_get_extension_data(globalconf.connection, &xcb_test_id); globalconf.have_xtest = xtest_query->present; /* Allocate the key symbols */ globalconf.keysyms = xcb_key_symbols_alloc(globalconf.connection); xcb_get_modifier_mapping_cookie_t xmapping_cookie = xcb_get_modifier_mapping_unchecked(globalconf.connection); /* init atom cache */ atoms_init(globalconf.connection); /* init screens information */ screen_scan(); xutil_lock_mask_get(globalconf.connection, xmapping_cookie, globalconf.keysyms, &globalconf.numlockmask, &globalconf.shiftlockmask, &globalconf.capslockmask, &globalconf.modeswitchmask); /* do this only for real screen */ ewmh_init(); systray_init(); /* init spawn (sn) */ spawn_init(); /* The default GC is just a newly created associated with a window with * depth globalconf.default_depth */ xcb_window_t tmp_win = xcb_generate_id(globalconf.connection); globalconf.gc = xcb_generate_id(globalconf.connection); xcb_create_window(globalconf.connection, globalconf.default_depth, tmp_win, globalconf.screen->root, -1, -1, 1, 1, 0, XCB_COPY_FROM_PARENT, globalconf.visual->visual_id, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP, (const uint32_t []) { globalconf.screen->black_pixel, globalconf.screen->black_pixel, globalconf.default_cmap }); xcb_create_gc(globalconf.connection, globalconf.gc, tmp_win, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND, (const uint32_t[]) { globalconf.screen->black_pixel, globalconf.screen->white_pixel }); xcb_destroy_window(globalconf.connection, tmp_win); /* Get the window tree associated to this screen */ tree_c = xcb_query_tree_unchecked(globalconf.connection, globalconf.screen->root); xcb_change_window_attributes(globalconf.connection, globalconf.screen->root, XCB_CW_EVENT_MASK, ROOT_WINDOW_EVENT_MASK); /* we will receive events, stop grabbing server */ xcb_ungrab_server(globalconf.connection); /* Parse and run configuration file */ if (!luaA_parserc(&xdg, confpath, true)) fatal("couldn't find any rc file"); p_delete(&confpath); xdgWipeHandle(&xdg); /* scan existing windows */ scan(tree_c); xcb_flush(globalconf.connection); /* main event loop */ ev_loop(globalconf.loop, 0); /* cleanup event loop */ ev_ref(globalconf.loop); ev_check_stop(globalconf.loop, &xcheck); ev_ref(globalconf.loop); ev_prepare_stop(globalconf.loop, &a_refresh); ev_ref(globalconf.loop); ev_io_stop(globalconf.loop, &xio); awesome_atexit(false); return EXIT_SUCCESS; }