Esempio n. 1
0
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);
    }
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
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;
}
Esempio n. 6
0
File: bspwm.c Progetto: sunaku/bspwm
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;
}