void xinerama_test(void) { /* check for xinerama extension */ if (xcb_get_extension_data(wm_conf.connection, &xcb_xinerama_id)->present) { xcb_xinerama_is_active_reply_t *r; r = xcb_xinerama_is_active_reply(wm_conf.connection, xcb_xinerama_is_active(wm_conf.connection), NULL); wm_conf.xinerama_is_active = r->state; free(r); } fprintf(stderr, "xinerama is %sactive\n", (wm_conf.xinerama_is_active ? "" : "NOT ")); if (wm_conf.xinerama_is_active) { xcb_xinerama_query_screens_reply_t *r; xcb_xinerama_screen_info_t *screen_info; int num_screens; r = xcb_xinerama_query_screens_reply(wm_conf.connection, xcb_xinerama_query_screens_unchecked(wm_conf.connection), NULL); screen_info = xcb_xinerama_query_screens_screen_info(r); num_screens = xcb_xinerama_query_screens_screen_info_length(r); fprintf(stderr, "xinerama: num_screens=%d\n", num_screens); int screen; for (screen = 0; screen < num_screens; ++screen) { xcb_xinerama_screen_info_t *info = &screen_info[screen]; fprintf(stderr, "xinerama: screen %d\n", screen); fprintf(stderr, " x_org = %d\n", info->x_org); fprintf(stderr, " y_org = %d\n", info->y_org); fprintf(stderr, " width = %u\n", info->width); fprintf(stderr, " height = %u\n", info->height); } free(r); } }
bool xinerama(void) { bool is_active = false; if (xcb_get_extension_data(cfg.conn, &xcb_xinerama_id)->present) { xcb_xinerama_is_active_reply_t *reply = xcb_xinerama_is_active_reply(cfg.conn, xcb_xinerama_is_active(cfg.conn), (void *)0); if (!reply) return false; is_active = reply->state; free(reply); } if (!is_active) { warn("xinerama is not present\n"); return false; } const xcb_xinerama_query_screens_cookie_t cookie = xcb_xinerama_query_screens_unchecked(cfg.conn); xcb_xinerama_query_screens_reply_t *reply = xcb_xinerama_query_screens_reply(cfg.conn, cookie, (void *)0); if (!reply) return false; const xcb_xinerama_screen_info_t *info = xcb_xinerama_query_screens_screen_info(reply); int screens = xcb_xinerama_query_screens_screen_info_length(reply); PRINTF("xinerama screens: %d\n", screens); for (int screen = 0; screen < screens; screen++) { PRINTF("adding screen: %d\n", screen); monitor_add(info[screen].x_org, info[screen].y_org, info[screen].width, info[screen].height); } free(reply); return true; }
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; }
int main(int argc, char **argv) { int just_first = 0; int print_offset = 1; int i; for (i = 1; i < argc; i++) { int hyphens = 0; for (; *argv[i] == '-'; (argv[i])++) hyphens++; int error = 0; if (!hyphens) { error = 1; } else if (!strcmp(argv[i], "first")) { just_first = 1; } else if (!strcmp(argv[i], "all")) { just_first = 0; } else if (!strcmp(argv[i], "dim")) { print_offset = 0; } else { error = 1; } if (error) { fprintf(stdout, "Usage: %s [ --first | --all ] [ --dim ]\n", argv[0]); return 1; } } int screen_default; xcb_connection_t *conn = xcb_connect(NULL, &screen_default); if (xcb_connection_has_error(conn)) { fprintf(stderr,"NOK\n"); return 1; } xcb_generic_error_t *error; xcb_xinerama_is_active_cookie_t is_active_req = xcb_xinerama_is_active(conn); xcb_xinerama_is_active_reply_t *is_active = xcb_xinerama_is_active_reply(conn, is_active_req, &error); if (error) { fprintf(stderr, "Couldn't query Xinerama\n"); return 1; } if (!is_active->state) { fprintf(stderr, "Xinerama inactive\n"); return 1; } xcb_xinerama_query_screens_cookie_t cookie_screen; cookie_screen = xcb_xinerama_query_screens(conn); xcb_xinerama_query_screens_reply_t *query_screens; query_screens = xcb_xinerama_query_screens_reply(conn, cookie_screen, &error); if (error) { fprintf(stderr, "Error getting screen info\n"); return 1; } /* iterator xcb_xinerama_screen_info_iterator_t screens; screens = xcb_xinerama_query_screens_screen_info_iterator(query_screens); for (; screens.rem; xcb_xinerama_screen_info_next(&screens)) { xcb_xinerama_screen_info_t info = *screens.data; fprintf(stdout, "%ux%u@%d,%d\n", info.width, info.height, info.x_org, info.y_org); } */ int len; xcb_xinerama_screen_info_t *screens = xcb_xinerama_query_screens_screen_info(query_screens); len = xcb_xinerama_query_screens_screen_info_length(query_screens); for (i = 0; i < len; i++) { xcb_xinerama_screen_info_t info = screens[i]; fprintf(stdout, "%ux%u", info.width, info.height); if (print_offset) fprintf(stdout, "+%d+%d", info.x_org, info.y_org); fprintf(stdout, "\n"); if (just_first) break; } xcb_disconnect(conn); return 0; }
/* @brief Attempts to find secondary displays and updates settings.screen_* data * with the dimensions of the found screens. * * Note: failure is somewhat expected and is handled by simply using the default * xcb screen's dimension parameters. * * @param connection A connection to the Xorg server. * @param screen A screen created by xcb's xcb_setup_roots function. * @return 0 on success and 1 on failure. */ static int32_t get_multiscreen_settings(xcb_connection_t *connection, xcb_screen_t *screen) { /* First check randr. */ const xcb_query_extension_reply_t *extension_reply = xcb_get_extension_data(connection, &xcb_randr_id); if (extension_reply && extension_reply->present) { debug("Found randr support, searching for displays.\n"); /* Find x, y and width, height. */ xcb_randr_get_screen_resources_current_reply_t *randr_reply = xcb_randr_get_screen_resources_current_reply(connection, xcb_randr_get_screen_resources_current(connection, screen->root), NULL); if (!randr_reply) { fprintf(stderr, "Failed to get randr set up.\n"); } else { int32_t num_outputs = xcb_randr_get_screen_resources_current_outputs_length(randr_reply); if (num_outputs < settings.screen) { fprintf(stderr, "Screen selected not found.\n"); /* Default back to the first screen. */ settings.screen = 0; } xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_current_outputs(randr_reply); uint32_t output_index = settings.screen; xcb_randr_get_output_info_reply_t *randr_output = NULL; do { if (randr_output) { free(randr_output); } randr_output = xcb_randr_get_output_info_reply(connection, xcb_randr_get_output_info(connection, outputs[output_index], XCB_CURRENT_TIME), NULL); output_index++; } while ((randr_output->connection != XCB_RANDR_CONNECTION_CONNECTED) && (output_index < num_outputs)); if (randr_output) { xcb_randr_get_crtc_info_reply_t *randr_crtc = xcb_randr_get_crtc_info_reply(connection, xcb_randr_get_crtc_info(connection, randr_output->crtc, XCB_CURRENT_TIME), NULL); if (!randr_crtc) { fprintf(stderr, "Unable to connect to randr crtc\n"); free(randr_output); free(randr_reply); goto xinerama; } settings.screen_width = randr_crtc->width; settings.screen_height = randr_crtc->height; settings.screen_x = randr_crtc->x; settings.screen_y = randr_crtc->y; debug("randr screen initialization successful, x: %u y: %u w: %u h: %u.\n", settings.screen_x, settings.screen_y, settings.screen_width, settings.screen_height); free(randr_crtc); free(randr_output); free(randr_reply); return 0; } free(randr_output); free(randr_reply); } } xinerama: debug("Did not find randr support, attempting xinerama\n"); /* Still here? Let's try xinerama! */ extension_reply = xcb_get_extension_data(connection, &xcb_xinerama_id); if (extension_reply && extension_reply->present) { debug("Found xinerama support, searching for displays.\n"); xcb_xinerama_is_active_reply_t *xinerama_is_active_reply = xcb_xinerama_is_active_reply(connection, xcb_xinerama_is_active(connection), NULL); if (xinerama_is_active_reply && xinerama_is_active_reply->state) { free(xinerama_is_active_reply); /* Find x, y and width, height. */ xcb_xinerama_query_screens_reply_t *screen_reply = xcb_xinerama_query_screens_reply(connection, xcb_xinerama_query_screens_unchecked(connection), NULL); xcb_xinerama_screen_info_iterator_t iter = xcb_xinerama_query_screens_screen_info_iterator(screen_reply); free(screen_reply); if (iter.rem < settings.screen) { fprintf(stderr, "Screen selected not found.\n"); /* Default back to the first screen. */ settings.screen = 0; } /* Jump to the appropriate screen. */ int32_t i = 0; while (i < settings.screen) { xcb_xinerama_screen_info_next(&iter); i++; } settings.screen_width = iter.data->width; settings.screen_height = iter.data->height; settings.screen_x = iter.data->x_org; settings.screen_y = iter.data->y_org; debug("xinerama screen initialization successful, x: %u y: %u w: %u h: %u.\n", settings.screen_x, settings.screen_y, settings.screen_width, settings.screen_height); return 0; } } debug("Multiscreen search failed.\n"); return 1; }
void setup(void) { ewmh_init(); screen = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data; if (!screen) err("error: cannot aquire screen\n"); screen_width = screen->width_in_pixels; screen_height = screen->height_in_pixels; root_depth = screen->root_depth; xcb_atom_t net_atoms[] = {ewmh->_NET_SUPPORTED, ewmh->_NET_DESKTOP_NAMES, ewmh->_NET_NUMBER_OF_DESKTOPS, ewmh->_NET_CURRENT_DESKTOP, ewmh->_NET_CLIENT_LIST, ewmh->_NET_ACTIVE_WINDOW, ewmh->_NET_WM_DESKTOP, ewmh->_NET_WM_STATE, ewmh->_NET_WM_STATE_FULLSCREEN, ewmh->_NET_WM_WINDOW_TYPE, ewmh->_NET_WM_WINDOW_TYPE_DOCK, ewmh->_NET_WM_WINDOW_TYPE_NOTIFICATION, ewmh->_NET_WM_WINDOW_TYPE_DIALOG, ewmh->_NET_WM_WINDOW_TYPE_UTILITY, ewmh->_NET_WM_WINDOW_TYPE_TOOLBAR}; xcb_ewmh_set_supported(ewmh, default_screen, LENGTH(net_atoms), net_atoms); monitor_uid = desktop_uid = client_uid = 0; mon = last_mon = mon_head = mon_tail = NULL; bool xinerama_is_active = false; if (xcb_get_extension_data(dpy, &xcb_xinerama_id)->present) { xcb_xinerama_is_active_reply_t *xia = xcb_xinerama_is_active_reply(dpy, xcb_xinerama_is_active(dpy), NULL); if (xia != NULL) { xinerama_is_active = xia->state; free(xia); } } if (xinerama_is_active) { xcb_xinerama_query_screens_reply_t *xsq = xcb_xinerama_query_screens_reply(dpy, xcb_xinerama_query_screens(dpy), NULL); xcb_xinerama_screen_info_t *xsi = xcb_xinerama_query_screens_screen_info(xsq); int n = xcb_xinerama_query_screens_screen_info_length(xsq); PRINTF("number of monitors: %d\n", n); for (int i = 0; i < n; i++) { xcb_xinerama_screen_info_t info = xsi[i]; xcb_rectangle_t rect = (xcb_rectangle_t) {info.x_org, info.y_org, info.width, info.height}; add_monitor(&rect); } free(xsq); } else { warn("Xinerama is inactive"); xcb_rectangle_t rect = (xcb_rectangle_t) {0, 0, screen_width, screen_height}; add_monitor(&rect); } for (monitor_t *m = mon_head; m != NULL; m = m->next) add_desktop(m, NULL); ewmh_update_number_of_desktops(); ewmh_update_desktop_names(); rule_head = make_rule(); frozen_pointer = make_pointer_state(); get_pointer_position(&pointer_position); split_mode = MODE_AUTOMATIC; }