views:

816

answers:

3

How would I change the wallpaper on a Linux desktop (using GNOME) within a C/C++ program? Is there a system API to do it?

+1  A: 

If nothing else, you could probably use system() to invoke one of the command lines suggested here:

http://www.linuxquestions.org/questions/linux-general-1/change-background-via-command-line-350936/

Amber
OP asked about GNOME, not KDE.
Kirill V. Lyadvinsky
Who cares? The linked thread doesn't answer either question.
innaM
If you go to post #5 in the thread, a gconftool-2 command is mentioned that sets the background picture in GNOME.
Amber
OK. Finally found it. Would have been more helpful if you pasted that line in your post (along with the link), though.
innaM
+12  A: 

You could use gconf library to do it. The following sample is a complete program to change background:

// bkgmanage.c
#include <glib.h>
#include <gconf/gconf-client.h>
#include <stdio.h>

typedef enum {
    WALLPAPER_ALIGN_TILED     = 0,
    WALLPAPER_ALIGN_CENTERED  = 1,
    WALLPAPER_ALIGN_STRETCHED = 2,
    WALLPAPER_ALIGN_SCALED    = 3,
    WALLPAPER_NONE            = 4
} WallpaperAlign;

gboolean set_as_wallpaper( const gchar *image_path, WallpaperAlign align )
{
    GConfClient *client;
    char        *options = "none";

    client = gconf_client_get_default();

    // TODO: check that image_path is a file
    if ( image_path == NULL ) options = "none";
    else {
        gconf_client_set_string( client, 
            "/desktop/gnome/background/picture_filename",
            image_path,
            NULL );
        switch ( align ) {
            case WALLPAPER_ALIGN_TILED: options = "wallpaper"; break;
            case WALLPAPER_ALIGN_CENTERED: options = "centered"; break;
            case WALLPAPER_ALIGN_STRETCHED: options = "stretched"; break;
            case WALLPAPER_ALIGN_SCALED: options = "scaled"; break;
            case WALLPAPER_NONE: options = "none"; break;
        }
    }
    gboolean result = gconf_client_set_string( client, 
        "/desktop/gnome/background/picture_options", 
        options,
        NULL);
    g_object_unref( G_OBJECT(client) );

    return result;
}

int main(int argc, const char* argv[])
{
  if ( argc > 1 ) {
    printf( "Setting %s as wallpaper... ", argv[1] );
    if ( set_as_wallpaper( argv[1], WALLPAPER_ALIGN_STRETCHED ) ) printf( "Ok\n" );
    else printf( "Failed\n" );
  } else printf( "Usage: ./bkgmanage <filename>\n" );

  return 0;
}

The source above is based on gthumb project. It could be compiled with the following string:

gcc -Wall -g `pkg-config --libs --cflags glib-2.0 gconf-2.0` bkgmanage.c -o bkgmanage
Kirill V. Lyadvinsky
+6  A: 

Though the question was gnome-specific, there's also a way to deal with the wallpaper that is not depepndant on the higher layer toolkits. You should be able to deal with the root window (which the wallpaper is, in fact) by studying the source of xsetroot.c, the most interesting part of which I copypaste here:

static void
SetBackgroundToBitmap(Pixmap bitmap, unsigned int width, unsigned int height)
{
    Pixmap pix;
    GC gc;
    XGCValues gc_init;

    gc_init.foreground = NameToPixel(fore_color, BlackPixel(dpy, screen));
    gc_init.background = NameToPixel(back_color, WhitePixel(dpy, screen));
    if (reverse) {
        unsigned long temp=gc_init.foreground;
        gc_init.foreground=gc_init.background;
        gc_init.background=temp;
    }
    gc = XCreateGC(dpy, root, GCForeground|GCBackground, &gc_init);
    pix = XCreatePixmap(dpy, root, width, height,
                        (unsigned int)DefaultDepth(dpy, screen));
    XCopyPlane(dpy, bitmap, pix, gc, 0, 0, width, height, 0, 0, (unsigned long)1);
    XSetWindowBackgroundPixmap(dpy, root, pix);
    XFreeGC(dpy, gc);
    XFreePixmap(dpy, bitmap);
    if (save_colors)
        save_pixmap = pix;
    else
        XFreePixmap(dpy, pix);
    XClearWindow(dpy, root);
    unsave_past = 1;
}
Andrew Y
Thanks. That works perfectly.
computergeek6