Changing wallpaper on Linux programmatically
Asked Answered
L

3

7

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?

Laden answered 3/8, 2009 at 5:58 Comment(1)
If you figure out how, please do it, I've wanted to be able to do that for some time.Headwind
C
10

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;
}
Calia answered 3/8, 2009 at 7:29 Comment(0)
P
19

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
Pickings answered 3/8, 2009 at 7:6 Comment(0)
C
10

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;
}
Calia answered 3/8, 2009 at 7:29 Comment(0)
E
2

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/

Emblazon answered 3/8, 2009 at 6:2 Comment(4)
OP asked about GNOME, not KDE.Pickings
If you go to post #5 in the thread, a gconftool-2 command is mentioned that sets the background picture in GNOME.Emblazon
OK. Finally found it. Would have been more helpful if you pasted that line in your post (along with the link), though.Fouquet
the command is gconftool-2 --type string --set /desktop/gnome/background/picture_filename /path/to/image.jpgStrawboard

© 2022 - 2024 — McMap. All rights reserved.