コード例 #1
0
ファイル: dmenu.c プロジェクト: domidimi/rofi
int dmenu_switcher_dialog ( void )
{
    mode_init ( &dmenu_mode );
    MenuFlags            menu_flags      = MENU_NORMAL;
    DmenuModePrivateData *pd             = (DmenuModePrivateData *) dmenu_mode.private_data;
    char                 *input          = NULL;
    unsigned int         cmd_list_length = pd->cmd_list_length;
    char                 **cmd_list      = pd->cmd_list;

    pd->only_selected = FALSE;
    if ( find_arg ( "-markup-rows" ) >= 0 ) {
        pd->do_markup = TRUE;
    }
    if ( find_arg ( "-only-match" ) >= 0 || find_arg ( "-no-custom" ) >= 0 ) {
        pd->only_selected = TRUE;
        if ( cmd_list_length == 0 ) {
            return TRUE;
        }
    }
    if ( config.auto_select && cmd_list_length == 1 ) {
        dmenu_output_formatted_line ( pd->format, cmd_list[0], 0, config.filter );
        return TRUE;
    }
    if ( find_arg ( "-password" ) >= 0 ) {
        menu_flags |= MENU_PASSWORD;
    }
    /* copy filter string */
    input = g_strdup ( config.filter );

    char *select = NULL;
    find_arg_str ( "-select", &select );
    if ( select != NULL ) {
        char         **tokens = tokenize ( select, config.case_sensitive );
        unsigned int i        = 0;
        for ( i = 0; i < cmd_list_length; i++ ) {
            if ( token_match ( tokens, cmd_list[i], !g_str_is_ascii ( cmd_list[i] ), config.case_sensitive ) ) {
                pd->selected_line = i;
                break;
            }
        }
        g_strfreev ( tokens );
    }
    if ( find_arg ( "-dump" ) >= 0 ) {
        char         **tokens = tokenize ( config.filter ? config.filter : "", config.case_sensitive );
        unsigned int i        = 0;
        for ( i = 0; i < cmd_list_length; i++ ) {
            if ( token_match ( tokens, cmd_list[i], !g_str_is_ascii ( cmd_list[i] ), config.case_sensitive ) ) {
                dmenu_output_formatted_line ( pd->format, cmd_list[i], i, config.filter );
            }
        }
        g_strfreev ( tokens );
        return TRUE;
    }
    // TODO remove
    RofiViewState *state = rofi_view_create ( &dmenu_mode, input, pd->prompt, pd->message, menu_flags, dmenu_finalize );
    rofi_view_set_selected_line ( state, pd->selected_line );
    rofi_view_set_active ( state );

    return FALSE;
}
コード例 #2
0
ファイル: xrmoptions.c プロジェクト: benizi/rofi
/**
 * Parse an option from the commandline vector.
 */
static void config_parse_cmd_option ( XrmOption *option )
{
    // Prepend a - to the option name.
    char *key = g_strdup_printf ( "-%s", option->name );
    switch ( option->type )
    {
    case xrm_Number:
        if ( find_arg_uint ( key, option->value.num ) == TRUE ) {
            option->source = CONFIG_CMDLINE;
        }
        break;
    case xrm_SNumber:
        if ( find_arg_int (  key, option->value.snum ) == TRUE ) {
            option->source = CONFIG_CMDLINE;
        }
        break;
    case xrm_String:
        if ( find_arg_str (  key, option->value.str ) == TRUE ) {
            if ( option->mem != NULL ) {
                g_free ( option->mem );
                option->mem = NULL;
            }
            option->source = CONFIG_CMDLINE;
        }
        break;
    case xrm_Boolean:
        if ( find_arg (  key ) >= 0 ) {
            *( option->value.num ) = TRUE;
            option->source         = CONFIG_CMDLINE;
        }
        else {
            g_free ( key );
            key = g_strdup_printf ( "-no-%s", option->name );
            if ( find_arg (  key ) >= 0 ) {
                *( option->value.num ) = FALSE;
                option->source         = CONFIG_CMDLINE;
            }
        }
        break;
    case xrm_Char:
        if ( find_arg_char (  key, option->value.charc ) == TRUE ) {
            option->source = CONFIG_CMDLINE;
        }
        break;
    default:
        break;
    }
    g_free ( key );
}
コード例 #3
0
ファイル: rofi.c プロジェクト: blackhole89/rofi
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;
}
コード例 #4
0
ファイル: rofi.c プロジェクト: blackhole89/rofi
static gboolean startup ( G_GNUC_UNUSED gpointer data )
{
    TICK_N ( "Startup" );
    // flags to run immediately and exit
    char *sname = NULL;
    char *msg   = NULL;
    //
    // Sanity check
    if ( config_sanity_check ( ) ) {
        return G_SOURCE_REMOVE;
    }
    TICK_N ( "Config sanity check" );
    // Parse the keybindings.
    if ( !parse_keys_abe () ) {
        // Error dialog
        return G_SOURCE_REMOVE;
    }
    TICK_N ( "Parse ABE" );
    // Dmenu mode.
    if ( dmenu_mode == TRUE ) {
        // force off sidebar mode:
        config.sidebar_mode = FALSE;
        int retv = run_dmenu ();
        if ( retv ) {
            rofi_set_return_code ( EXIT_SUCCESS );
            // Directly exit.
            g_main_loop_quit ( main_loop );
        }
    }
    else if ( find_arg_str (  "-e", &( msg ) ) ) {
        int markup = FALSE;
        if ( find_arg ( "-markup" ) >= 0 ) {
            markup = TRUE;
        }
        if (  !show_error_message ( msg, markup ) ) {
            g_main_loop_quit ( main_loop );
        }
    }
    else if ( find_arg_str ( "-show", &sname ) == TRUE ) {
        int index = switcher_get ( sname );
        if ( index < 0 ) {
            // Add it to the list
            index = add_mode ( sname );
            // Complain
            if ( index >= 0 ) {
                fprintf ( stdout, "Mode %s not enabled. Please add it to the list of enabled modi: %s\n",
                          sname, config.modi );
                fprintf ( stdout, "Adding mode: %s\n", sname );
            }
            // Run it anyway if found.
        }
        if ( index >= 0 ) {
            run_switcher ( index );
        }
        else {
            fprintf ( stderr, "The %s switcher has not been enabled\n", sname );
            return G_SOURCE_REMOVE;
        }
    }
    else{
        // Daemon mode
        fprintf ( stderr, "Rofi daemon mode is now removed.\n" );
        fprintf ( stderr, "Please use your window manager binding functionality or xbindkeys to replace it.\n" );
        g_main_loop_quit ( main_loop );
    }

    return G_SOURCE_REMOVE;
}
コード例 #5
0
ファイル: dmenu.c プロジェクト: Tarrasch/rofi
int dmenu_switcher_dialog ( char **input )
{
    char          *dmenu_prompt = "dmenu ";
    int           selected_line = -1;
    int           retv          = FALSE;
    int           length        = 0;
    char          **list        = get_dmenu ( &length );
    int           restart       = FALSE;
    char          *message      = NULL;
    menu_match_cb filter        = token_match;

    find_arg_str ( "-mesg", &message );

    // By default we print the unescaped line back.
    char *format = "s";
    // This is here for compatibility reason.
    // Use -format 'i' instead.
    if ( find_arg (  "-i" ) >= 0 ) {
        format = "i";
    }
    // Allow user to override the output format.
    find_arg_str ( "-format", &format );
    // Check prompt
    find_arg_str (  "-p", &dmenu_prompt );
    find_arg_int (  "-l", &selected_line );
    // Urgent.
    char *str = NULL;
    find_arg_str (  "-u", &str );
    if ( str != NULL ) {
        parse_ranges ( str, &urgent_list, &num_urgent_list );
    }
    // Active
    str = NULL;
    find_arg_str (  "-a", &str );
    if ( str != NULL ) {
        parse_ranges ( str, &active_list, &num_active_list );
    }

    int only_selected = FALSE;
    if ( find_arg ( "-only-match" ) >= 0 || find_arg ( "-no-custom" ) >= 0 ) {
        only_selected = TRUE;
        if ( length == 0 ) {
            return TRUE;
        }
    }
    find_arg_str_alloc ( "-filter", input );

    if ( find_arg ( "-z" ) >= 0 ) {
        filter = fuzzy_token_match;
    }

    char *select = NULL;
    find_arg_str ( "-select", &select );
    if ( select != NULL ) {
        char **tokens = tokenize ( select, config.case_sensitive );
        int  i        = 0;
        for ( i = 0; i < length; i++ ) {
            if ( token_match ( tokens, list[i], config.case_sensitive, 0, NULL ) ) {
                selected_line = i;
                break;
            }
        }
        g_strfreev ( tokens );
    }

    do {
        int next_pos = selected_line;
        int mretv    = menu ( list, length, input, dmenu_prompt,
                              filter, NULL, &selected_line, config.levenshtein_sort, get_display_data, list, &next_pos, message );
        // Special behavior.
        if ( only_selected ) {
            /**
             * Select item mode.
             */
            restart = ( find_arg ( "-only-match" ) >= 0 );
            if ( ( mretv & ( MENU_OK | MENU_QUICK_SWITCH ) ) && list[selected_line] != NULL ) {
                dmenu_output_formatted_line ( format, list[selected_line], selected_line, *input );
                retv = TRUE;
                if ( ( mretv & MENU_QUICK_SWITCH ) ) {
                    retv = 10 + ( mretv & MENU_LOWER_MASK );
                }
                return retv;
            }
            selected_line = next_pos - 1;
            continue;
        }
        // We normally do not want to restart the loop.
        restart = FALSE;
        // Normal mode
        if ( ( mretv & MENU_OK  ) && list[selected_line] != NULL ) {
            dmenu_output_formatted_line ( format, list[selected_line], selected_line, *input );
            if ( ( mretv & MENU_SHIFT ) ) {
                restart = TRUE;
                // Move to next line.
                selected_line = MIN ( next_pos, length - 1 );
            }
            retv = TRUE;
        }
        // Custom input
        else if ( ( mretv & ( MENU_CUSTOM_INPUT ) ) ) {
            dmenu_output_formatted_line ( format, *input, -1, *input );
            if ( ( mretv & MENU_SHIFT ) ) {
                restart = TRUE;
                // Move to next line.
                selected_line = MIN ( next_pos, length - 1 );
            }

            retv = TRUE;
        }
        // Quick switch with entry selected.
        else if ( ( mretv & MENU_QUICK_SWITCH ) && selected_line >= 0 ) {
            dmenu_output_formatted_line ( format, list[selected_line], selected_line, *input );

            restart = FALSE;
            retv    = 10 + ( mretv & MENU_LOWER_MASK );
        }
        // Quick switch without entry selected.
        else if ( ( mretv & MENU_QUICK_SWITCH ) && selected_line == -1 ) {
            dmenu_output_formatted_line ( format, *input, -1, *input );

            restart = FALSE;
            retv    = 10 + ( mretv & MENU_LOWER_MASK );
        }
    } while ( restart );

    g_strfreev ( list );
    g_free ( urgent_list );
    g_free ( active_list );

    return retv;
}
コード例 #6
0
ファイル: dmenu.c プロジェクト: domidimi/rofi
static int dmenu_mode_init ( Mode *sw )
{
    if ( mode_get_private_data ( sw ) != NULL ) {
        return TRUE;
    }
    mode_set_private_data ( sw, g_malloc0 ( sizeof ( DmenuModePrivateData ) ) );
    DmenuModePrivateData *pd = (DmenuModePrivateData *) mode_get_private_data ( sw );

    pd->prompt        = "dmenu ";
    pd->separator     = '\n';
    pd->selected_line = UINT32_MAX;

    find_arg_str ( "-mesg", &( pd->message ) );

    // Input data separator.
    find_arg_char ( "-sep", &( pd->separator ) );

    // Check prompt
    find_arg_str (  "-p", &( pd->prompt ) );
    find_arg_uint (  "-selected-row", &( pd->selected_line ) );
    // By default we print the unescaped line back.
    pd->format = "s";

    // Allow user to override the output format.
    find_arg_str ( "-format", &( pd->format ) );
    // Urgent.
    char *str = NULL;
    find_arg_str (  "-u", &str );
    if ( str != NULL ) {
        parse_ranges ( str, &( pd->urgent_list ), &( pd->num_urgent_list ) );
    }
    // Active
    str = NULL;
    find_arg_str (  "-a", &str );
    if ( str != NULL ) {
        parse_ranges ( str, &( pd->active_list ), &( pd->num_active_list ) );
    }

    // DMENU COMPATIBILITY
    find_arg_uint (  "-l", &( config.menu_lines ) );

    /**
     * Dmenu compatibility.
     * `-b` put on bottom.
     */
    if ( find_arg ( "-b" ) >= 0 ) {
        config.location = 6;
    }
    /* -i case insensitive */
    config.case_sensitive = TRUE;
    if ( find_arg ( "-i" ) >= 0 ) {
        config.case_sensitive = FALSE;
    }
    FILE *fd = NULL;
    str = NULL;
    if ( find_arg_str ( "-input", &str ) ) {
        char *estr = rofi_expand_path ( str );
        fd = fopen ( str, "r" );
        if ( fd == NULL ) {
            char *msg = g_markup_printf_escaped ( "Failed to open file: <b>%s</b>:\n\t<i>%s</i>", estr, strerror ( errno ) );
            rofi_view_error_dialog ( msg, TRUE );
            g_free ( msg );
            g_free ( estr );
            return TRUE;
        }
        g_free ( estr );
    }
    pd->cmd_list = get_dmenu ( pd, fd == NULL ? stdin : fd, &( pd->cmd_list_length ) );
    if ( fd != NULL ) {
        fclose ( fd );
    }
    return TRUE;
}
コード例 #7
0
int main ( int argc, char **argv )
{
    g_type_init();
    Display *display;

    // catch help request
    if ( find_arg( argc, argv, "-help" ) >= 0
         || find_arg( argc, argv, "--help" ) >= 0
         || find_arg( argc, argv, "-h" ) >= 0 ) {
        help();
        return EXIT_SUCCESS;
    }

    // Get DISPLAY
    const char *display_str= getenv( "DISPLAY" );

    if ( !( display = XOpenDisplay( display_str ) ) ) {
        fprintf( stderr, "cannot open display!\n" );
        return EXIT_FAILURE;
    }

    // Setup error handler.
    XSync( display, False );
    xerror = XSetErrorHandler( X11_oops );
    XSync( display, False );

    // Initialize renderer
    renderer_init( display );

    // Get monitor layout. (xinerama aware)
    MMB_Screen *mmb_screen = mmb_screen_create( display );


    // Check input file.
    char *image_file = NULL;
    find_arg_str( argc, argv, "-input", &image_file );

    if ( image_file ) {
        int clip = ( find_arg( argc, argv, "-clip" ) >= 0 );
        GdkPixbuf *pb = renderer_create_empty_background( mmb_screen );


        if ( renderer_overlay_wallpaper( pb, image_file, mmb_screen,clip ) ) {
            char *output_file = NULL;
            find_arg_str( argc, argv, "-output", &output_file );

            if ( output_file ) {
                renderer_store_image( pb, output_file );
            } else {
                renderer_update_X11_background( display, pb );
            }
        }

        g_object_unref( pb );
    }

    // Print layout
    if ( find_arg( argc, argv, "-print" ) >= 0 ) {
        mmb_screen_print( mmb_screen );
    }

    // Cleanup
    mmb_screen_free( &mmb_screen );
    XCloseDisplay( display );
}