пятница, 28 августа 2009 г.

Changing wallpaper on Linux programmatically

Для тех, кто хочет начать работать с GNOME, но не знает с чего начать, вот задачка — поменять обои рабочего стола. Это я так пытаюсь подойти к проблеме поддержки разных обоев для двух мониторов (точнее, монитора и HD телевизора в моем случае). В KDE с этим проблем нет, но в GNOME такой настройки нет. Оказалось, что сделать это несложно. Проблемой я собирался заняться давно, но преодолеть лень и написать код меня сподвигнул этот вопрос.

Нам понадобятся: Ubuntu, любимый текстовый редактор, пакет build-essentials, libglib-2.0-dev, libgconf2-dev и консоль. Думаю, что ставить пакеты все умеют (кто не умеет — читать тут).

В текстовом редакторе создаем файл следующего содержания:
// 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: проверить, что image_path является файлом и вообще существует
  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;
}
gconf — это библиотека для управлением аналогом реестра в GNOME. С помощью неё и исправляется параметр /desktop/gnome/background/picture_filename для замены картинки, а также /desktop/gnome/background/picture_options для определения параметров отображения этой картинки. Изменения вступают в силу мгновенно.

Сборка указанного выше файла тоже не составляет труда. Достаточно в консоли ввести:
gcc -Wall -g `pkg-config --libs --cflags glib-2.0 gconf-2.0` bkgmanage.c -o bkgmanage
Тут pkg-config возвращает все необходимые пути к include-файлам и библиотеки, необходимые для линковки, что очень удобно. В результате получается исполняемый файл bkgmanage.

Далее, остается сделать GUI для удобного выбора картинок для каждого монитора с последующей склейкой в один файл. Пока не решил какой фреймворк для этого выбрать — основная идея, что хочется писать на С++, но Qt имеет слишком много зависимостей, которые в GNOME по умолчанию отсутствуют...

Комментировать в ВКонтакте