diff options
| -rw-r--r-- | Makefile.am | 2 | ||||
| -rw-r--r-- | data/rc.xsd | 2 | ||||
| -rw-r--r-- | obrender/image.c | 89 | ||||
| -rw-r--r-- | obrender/image.h | 3 | ||||
| -rw-r--r-- | obrender/imagecache.c | 25 | ||||
| -rw-r--r-- | obrender/imagecache.h | 13 | ||||
| -rw-r--r-- | obrender/render.h | 18 | ||||
| -rw-r--r-- | openbox/client_list_combined_menu.c | 2 | ||||
| -rw-r--r-- | openbox/client_list_menu.c | 2 | ||||
| -rw-r--r-- | openbox/config.c | 19 | ||||
| -rw-r--r-- | openbox/config.h | 4 | ||||
| -rw-r--r-- | openbox/imageload.c | 143 | ||||
| -rw-r--r-- | openbox/imageload.h | 7 | ||||
| -rw-r--r-- | openbox/menu.c | 35 |
14 files changed, 150 insertions, 214 deletions
diff --git a/Makefile.am b/Makefile.am index 16472467..91b23033 100644 --- a/Makefile.am +++ b/Makefile.am @@ -244,8 +244,6 @@ openbox_openbox_SOURCES = \ openbox/grab.h \ openbox/group.c \ openbox/group.h \ - openbox/imageload.c \ - openbox/imageload.h \ openbox/keyboard.c \ openbox/keyboard.h \ openbox/keytree.c \ diff --git a/data/rc.xsd b/data/rc.xsd index 06286426..6d2ed1dd 100644 --- a/data/rc.xsd +++ b/data/rc.xsd @@ -219,7 +219,7 @@ <xsd:element minOccurs="0" name="hideDelay" type="xsd:integer"/> <xsd:element minOccurs="0" name="middle" type="ob:bool"/> <xsd:element minOccurs="0" name="submenuShowDelay" type="xsd:integer"/> - <xsd:element minOccurs="0" name="applicationIcons" type="ob:bool"/> + <xsd:element minOccurs="0" name="showIcons" type="ob:bool"/> <xsd:element minOccurs="0" name="manageDesktops" type="ob:bool"/> </xsd:sequence> </xsd:complexType> diff --git a/obrender/image.c b/obrender/image.c index c65cd2a5..671b7aee 100644 --- a/obrender/image.c +++ b/obrender/image.c @@ -21,6 +21,9 @@ #include "image.h" #include "color.h" #include "imagecache.h" +#ifdef USE_IMLIB2 +#include <Imlib2.h> +#endif #include <glib.h> @@ -28,7 +31,8 @@ #define FLOOR(i) ((i) & (~0UL << FRACTION)) #define AVERAGE(a, b) (((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b))) -void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data) +void RrImagePicInit(RrImagePic *pic, const gchar *name, + gint w, gint h, RrPixel32 *data) { gint i; @@ -38,12 +42,14 @@ void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data) pic->sum = 0; for (i = w*h; i > 0; --i) pic->sum += *(data++); + pic->name = g_strdup(name); } static void RrImagePicFree(RrImagePic *pic) { if (pic) { g_free(pic->data); + g_free(pic->name); g_free(pic); } } @@ -58,7 +64,10 @@ static void AddPicture(RrImage *self, RrImagePic ***list, gint *len, g_assert(pic->width > 0 && pic->height > 0); - g_assert(g_hash_table_lookup(self->cache->table, pic) == NULL); + if (pic->name) + g_assert(!g_hash_table_lookup(self->cache->name_table, pic->name)); + else + g_assert(!g_hash_table_lookup(self->cache->pic_table, pic)); /* grow the list */ *list = g_renew(RrImagePic*, *list, ++*len); @@ -70,8 +79,12 @@ static void AddPicture(RrImage *self, RrImagePic ***list, gint *len, /* set the new picture up at the front of the list */ (*list)[0] = pic; - /* add the picture as a key to point to this image in the cache */ - g_hash_table_insert(self->cache->table, (*list)[0], self); + /* add the name or the picture as a key to point to this image in the + cache */ + if (pic->name) + g_hash_table_insert(self->cache->name_table, pic->name, self); + else + g_hash_table_insert(self->cache->pic_table, (*list)[0], self); /* #ifdef DEBUG @@ -100,8 +113,11 @@ static void RemovePicture(RrImage *self, RrImagePic ***list, #endif */ - /* remove the picture as a key in the cache */ - g_hash_table_remove(self->cache->table, (*list)[i]); + /* remove the name or picture as a key in the cache */ + if ((*list)[i]->name) + g_hash_table_remove(self->cache->name_table, (*list)[i]->name); + else + g_hash_table_remove(self->cache->pic_table, (*list)[i]); /* free the picture */ RrImagePicFree((*list)[i]); @@ -220,7 +236,7 @@ static RrImagePic* ResizeImage(RrPixel32 *src, } pic = g_new(RrImagePic, 1); - RrImagePicInit(pic, dstW, dstH, dststart); + RrImagePicInit(pic, NULL, dstW, dstH, dststart); return pic; } @@ -326,9 +342,11 @@ RrImage* RrImageNew(RrImageCache *cache) } /*! Set function that will be called just before RrImage is destroyed. */ -void RrImageSetDestroyFunc(RrImage *image, RrImageDestroyFunc func) +void RrImageSetDestroyFunc(RrImage *image, RrImageDestroyFunc func, + gpointer data) { image->destroy_func = func; + image->destroy_data = data; } void RrImageRef(RrImage *self) @@ -346,7 +364,7 @@ void RrImageUnref(RrImage *self) #endif */ if (self->destroy_func) - self->destroy_func(self); + self->destroy_func(self, self->destroy_data); while (self->n_original > 0) RemovePicture(self, &self->original, 0, &self->n_original); while (self->n_resized > 0) @@ -355,10 +373,8 @@ void RrImageUnref(RrImage *self) } } -/*! Add a new picture with the given RGBA pixel data and dimensions into the - RrImage. This adds an "original" picture to the image. -*/ -void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h) +static void AddPictureFromData(RrImage *self, const char *name, + const RrPixel32 *data, gint w, gint h) { gint i; RrImagePic *pic; @@ -384,10 +400,55 @@ void RrImageAddPicture(RrImage *self, RrPixel32 *data, gint w, gint h) /* add the new picture */ pic = g_new(RrImagePic, 1); - RrImagePicInit(pic, w, h, g_memdup(data, w*h*sizeof(RrPixel32))); + RrImagePicInit(pic, name, w, h, g_memdup(data, w*h*sizeof(RrPixel32))); AddPicture(self, &self->original, &self->n_original, pic); } +gboolean RrImageAddPictureName(RrImage *self, const gchar *name) +{ +#ifdef USE_IMLIB2 + Imlib_Image img; + gint w, h; + RrPixel32 *data; + gchar *path; + + /* XXX find the path via freedesktop icon spec (use obt) ! */ + path = g_strdup(name); + + if (!(img = imlib_load_image(path))) + g_message("Cannot load image \"%s\" from file \"%s\"", name, path); + g_free(path); + + if (!img) + return FALSE; /* failed to load it */ + + /* Get data and dimensions of the image. + + WARNING: This stuff is NOT threadsafe !! + */ + imlib_context_set_image(img); + data = imlib_image_get_data_for_reading_only(); + w = imlib_image_get_width(); + h = imlib_image_get_height(); + + /* add it to the RrImage, and set its name */ + AddPictureFromData(self, name, data, w, h); + + imlib_free_image(); + return TRUE; +#else + return FALSE; +#endif +} + +/*! Add a new picture with the given RGBA pixel data and dimensions into the + RrImage. This adds an "original" picture to the image. +*/ +void RrImageAddPicture(RrImage *self, const RrPixel32 *data, gint w, gint h) +{ + AddPictureFromData(self, NULL, data, w, h); +} + /*! Remove the picture from the RrImage which has the given dimensions. This removes an "original" picture from the image. */ diff --git a/obrender/image.h b/obrender/image.h index b478daf9..6e4a50e0 100644 --- a/obrender/image.h +++ b/obrender/image.h @@ -23,7 +23,8 @@ #include "geom.h" /*! Initialize an RrImagePicture to the specified dimensions and pixel data */ -void RrImagePicInit(RrImagePic *pic, gint w, gint h, RrPixel32 *data); +void RrImagePicInit(RrImagePic *pic, const gchar *path, + gint w, gint h, RrPixel32 *data); void RrImageDrawImage(RrPixel32 *target, RrTextureImage *img, gint target_w, gint target_h, diff --git a/obrender/imagecache.c b/obrender/imagecache.c index fde1e7a0..036ac121 100644 --- a/obrender/imagecache.c +++ b/obrender/imagecache.c @@ -32,9 +32,9 @@ RrImageCache* RrImageCacheNew(gint max_resized_saved) self = g_new(RrImageCache, 1); self->ref = 1; self->max_resized_saved = max_resized_saved; - self->table = g_hash_table_new((GHashFunc)RrImagePicHash, - (GEqualFunc)RrImagePicEqual); - self->file_name_table = NULL; + self->pic_table = g_hash_table_new((GHashFunc)RrImagePicHash, + (GEqualFunc)RrImagePicEqual); + self->name_table = g_hash_table_new(g_str_hash, g_str_equal); return self; } @@ -46,22 +46,31 @@ void RrImageCacheRef(RrImageCache *self) void RrImageCacheUnref(RrImageCache *self) { if (self && --self->ref == 0) { - g_assert(g_hash_table_size(self->table) == 0); - g_assert(self->file_name_table == NULL); - g_hash_table_unref(self->table); + g_assert(g_hash_table_size(self->pic_table) == 0); + g_hash_table_unref(self->pic_table); + self->pic_table = NULL; + + g_assert(g_hash_table_size(self->name_table) == 0); + g_hash_table_destroy(self->name_table); + self->name_table = NULL; g_free(self); } } +RrImage* RrImageCacheFindName(RrImageCache *self, const gchar *name) +{ + return g_hash_table_lookup(self->name_table, name); +} + /*! Finds an image in the cache, if it is already in there */ RrImage* RrImageCacheFind(RrImageCache *self, RrPixel32 *data, gint w, gint h) { RrImagePic pic; - RrImagePicInit(&pic, w, h, data); - return g_hash_table_lookup(self->table, &pic); + RrImagePicInit(&pic, NULL, w, h, data); + return g_hash_table_lookup(self->pic_table, &pic); } #define hashsize(n) ((RrPixel32)1<<(n)) diff --git a/obrender/imagecache.h b/obrender/imagecache.h index a61fae67..9baf34bb 100644 --- a/obrender/imagecache.h +++ b/obrender/imagecache.h @@ -45,11 +45,14 @@ struct _RrImageCache { */ gint max_resized_saved; - GHashTable *table; - - /* Used to find out if an image file has already been loaded. - Quick file_name -> RrImage lookup. */ - GHashTable *file_name_table; + /*! A hash table of images in the cache that don't have a file name + attached to them, with their key being a hash of the contents of the + image. */ + GHashTable *pic_table; + + /*! Used to find out if an image file has already been loaded. + Provides a quick file_name -> RrImage lookup. */ + GHashTable *name_table; }; #endif diff --git a/obrender/render.h b/obrender/render.h index 7aa9d698..64c2f6a1 100644 --- a/obrender/render.h +++ b/obrender/render.h @@ -230,9 +230,13 @@ struct _RrImagePic { /* The sum of all the pixels. This is used to compare pictures if their hashes match. */ gint sum; + /* The name of the image. This is used to determine + if the named image already is loaded. May be NULL if the image + was not loaded from disk. */ + gchar *name; }; -typedef void (*RrImageDestroyFunc)(RrImage *image); +typedef void (*RrImageDestroyFunc)(RrImage *image, gpointer data); /*! An RrImage is a sort of meta-image. It can contain multiple versions of an image at different sizes, which may or may not be completely different @@ -252,10 +256,11 @@ struct _RrImage { RrImage. */ RrImagePic **resized; gint n_resized; - + /* This function (if not NULL) will be called just before destroying RrImage. */ RrImageDestroyFunc destroy_func; + gpointer destroy_data; }; /* these are the same on all endian machines because it seems to be dependant @@ -343,12 +348,19 @@ void RrImageCacheUnref(RrImageCache *self); /*! Finds an image in the cache, if it is already in there */ RrImage* RrImageCacheFind(RrImageCache *self, RrPixel32 *data, gint w, gint h); +/*! Finds an image in the cache, by searching for the name of the image */ +RrImage* RrImageCacheFindName(RrImageCache *self, + const gchar *name); RrImage* RrImageNew(RrImageCache *cache); void RrImageRef(RrImage *im); void RrImageUnref(RrImage *im); -void RrImageAddPicture(RrImage *im, RrPixel32 *data, gint w, gint h); +void RrImageAddPicture(RrImage *im, const RrPixel32 *data, gint w, gint h); +/*! Adds a picture by name, from a file on disk. + @name Can be a full path to an image, or it can be a name as per the + freedesktop.org icon spec. */ +gboolean RrImageAddPictureName(RrImage *im, const gchar *name); void RrImageRemovePicture(RrImage *im, gint w, gint h); G_END_DECLS diff --git a/openbox/client_list_combined_menu.c b/openbox/client_list_combined_menu.c index 22840ad6..f4aae884 100644 --- a/openbox/client_list_combined_menu.c +++ b/openbox/client_list_combined_menu.c @@ -67,7 +67,7 @@ static gboolean self_update(ObMenuFrame *frame, gpointer data) e = menu_add_normal(menu, desktop, c->title, NULL, FALSE); } - if (config_menu_client_list_icons) { + if (config_menu_show_icons) { e->data.normal.icon = client_icon(c); RrImageRef(e->data.normal.icon); e->data.normal.icon_alpha = diff --git a/openbox/client_list_menu.c b/openbox/client_list_menu.c index 3f79f621..2d62c3e9 100644 --- a/openbox/client_list_menu.c +++ b/openbox/client_list_menu.c @@ -69,7 +69,7 @@ static gboolean desk_menu_update(ObMenuFrame *frame, gpointer data) e = menu_add_normal(menu, d->desktop, c->title, NULL, FALSE); } - if (config_menu_client_list_icons) { + if (config_menu_show_icons) { e->data.normal.icon = client_icon(c); RrImageRef(e->data.normal.icon); e->data.normal.icon_alpha = c->iconic ? OB_ICONIC_ALPHA : 0xff; diff --git a/openbox/config.c b/openbox/config.c index 304079c9..6963559d 100644 --- a/openbox/config.c +++ b/openbox/config.c @@ -94,9 +94,8 @@ guint config_menu_hide_delay; gboolean config_menu_middle; guint config_submenu_show_delay; guint config_submenu_hide_delay; -gboolean config_menu_client_list_icons; gboolean config_menu_manage_desktops; -gboolean config_menu_user_show_icons; +gboolean config_menu_show_icons; GSList *config_menu_files; @@ -817,17 +816,14 @@ static void parse_menu(xmlNodePtr node, gpointer d) config_submenu_show_delay = obt_xml_node_int(n); if ((n = obt_xml_find_node(node, "submenuHideDelay"))) config_submenu_hide_delay = obt_xml_node_int(n); - if ((n = obt_xml_find_node(node, "applicationIcons"))) - config_menu_client_list_icons = obt_xml_node_bool(n); if ((n = obt_xml_find_node(node, "manageDesktops"))) config_menu_manage_desktops = obt_xml_node_bool(n); if ((n = obt_xml_find_node(node, "showIcons"))) { - config_menu_user_show_icons = obt_xml_node_bool(n); - #ifndef USE_IMLIB2 - if (config_menu_user_show_icons) - g_message(_("Openbox was compiled without Imlib2." - " Icons in user-defined menus will NOT be loaded.")); - #endif + config_menu_show_icons = obt_xml_node_bool(n); +#ifndef USE_IMLIB2 + if (config_menu_show_icons) + g_message(_("Openbox was compiled without Imlib2 image loading support. Icons in menus will not be loaded.")); +#endif } while ((node = obt_xml_find_node(node, "file"))) { @@ -1031,10 +1027,9 @@ void config_startup(ObtXmlInst *i) config_menu_middle = FALSE; config_submenu_show_delay = 200; config_submenu_hide_delay = 400; - config_menu_client_list_icons = TRUE; config_menu_manage_desktops = TRUE; config_menu_files = NULL; - config_menu_user_show_icons = TRUE; + config_menu_show_icons = TRUE; obt_xml_register(i, "menu", parse_menu, NULL); diff --git a/openbox/config.h b/openbox/config.h index 1825f477..0e4ccb5c 100644 --- a/openbox/config.h +++ b/openbox/config.h @@ -193,12 +193,10 @@ extern gboolean config_menu_middle; extern guint config_submenu_show_delay; /*! Delay before closing a submenu in milliseconds */ extern guint config_submenu_hide_delay; -/*! Show icons in client_list_menu */ -extern gboolean config_menu_client_list_icons; /*! Show manage desktops in client_list_menu */ extern gboolean config_menu_manage_desktops; /*! Load & show icons in user-defined menus */ -extern gboolean config_menu_user_show_icons; +extern gboolean config_menu_show_icons; /*! User-specified menu files */ extern GSList *config_menu_files; /*! Per app settings */ diff --git a/openbox/imageload.c b/openbox/imageload.c deleted file mode 100644 index e7c1ddf7..00000000 --- a/openbox/imageload.c +++ /dev/null @@ -1,143 +0,0 @@ -/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- - imageload.c for the Openbox window manager - by Libor Kadlcik (aka KadlSoft) -*/ - -/* - All loaded images are cached. There's no separate cache for the images, - instead they are simply stored in image cache (RrImageCache) as RrImages, - ready to be used. - Every RrImage loaded from file is associated with name of the file. This is - done by file name table (RrImageCache.file_name_table), which is a simple - hash table, where file names are keys to pointers to RrImage. - If you request to load file that is already in image cache, nothing will be - loaded and you just got the RrImage from cache. - When RrImage is destroyed (see RrImageDestroyNotify), the file name - pointer - to RrImage pair is removed from the file name table. -*/ - -#include "debug.h" -#include "menu.h" -#include "openbox.h" -#include "gettext.h" -#include "obrender/render.h" -#include "obrender/image.h" -#include "obrender/imagecache.h" -#include "imageload.h" -#include <Imlib2.h> - -#ifndef USE_IMLIB2 -RrImage* RrImageFetchFromFile(RrImageCache *cache, const gchar *name) -{ - return NULL; -} -#else - -static void CreateFileNameTable(RrImageCache *self) -{ - g_assert(self->file_name_table == NULL); - self->file_name_table = g_hash_table_new(&g_str_hash, &g_str_equal); -} - -static void DestroyFileNameTable(RrImageCache *self) -{ - g_assert(g_hash_table_size(self->file_name_table) == 0); - g_hash_table_destroy(self->file_name_table); - self->file_name_table = NULL; -} - -/*! Return file name from which this image has been loaded. */ -static gchar* GetFileName(RrImage *image) -{ - GHashTableIter iter; - void *key, *value; - - g_hash_table_iter_init(&iter, image->cache->file_name_table); - while (g_hash_table_iter_next(&iter, &key, &value)) { - if (value == image) - return key; - } - return NULL; -} - -/* RrImage is about to be deleted. So remove it from file name table. */ -static void RrImageDestroyNotify(RrImage *image) -{ - gchar *file_name = GetFileName(image); - g_assert(file_name != NULL); - ob_debug("Image \"%s\" no longer needed", file_name); - g_hash_table_remove(image->cache->file_name_table, file_name); - g_free(file_name); - - if (g_hash_table_size(image->cache->file_name_table) == 0) { - ob_debug("No RrImage in file_name_table, destroying"); - DestroyFileNameTable(image->cache); - } -} - -#if (RrDefaultAlphaOffset != 24 || RrDefaultRedOffset != 16 \ - || RrDefaultGreenOffset != 8 || RrDefaultBlueOffset != 0) -#error RrImageFetchFromFile cannot handle current bit layout of RrPixel32. -#endif - -/*! Load image from specified file and create RrImage for it (RrImage will be - linked into specified image cache). Reference count of the RrImage will - be set to 1. - If that image has already been loaded into the image cache, RrImage - from the cache will be returned and its reference count will be incremented. -*/ -RrImage* RrImageFetchFromFile(RrImageCache *cache, const gchar *name) -{ - RrImage *rr_image, *found_rr_image; - gint w, h; - DATA32 *ro_data; - - imlib_set_color_usage(128); - - if (cache->file_name_table == NULL) - CreateFileNameTable(cache); - - /* Find out if that image has already been loaded to this cache. */ - rr_image = g_hash_table_lookup(cache->file_name_table, name); - if (rr_image && rr_image->cache == cache) { - ob_debug("\"%s\" already loaded in this image cache.", name); - RrImageRef(rr_image); - return rr_image; - } - - Imlib_Image imlib_image = imlib_load_image(name); - if (imlib_image == NULL) { - g_message(_("Cannot load image from file \"%s\""), name); - return NULL; - } - - /* Get data and dimensions of the image. */ - imlib_context_set_image(imlib_image); - g_message("Alpha = %d\n", imlib_image_has_alpha()); - ro_data = imlib_image_get_data_for_reading_only(); - w = imlib_image_get_width(); - h = imlib_image_get_height(); - ob_debug("Loaded \"%s\", dimensions %dx%d", name, w, h); - - /* There must not be any duplicated pictures in RrImageCache. */ - found_rr_image = RrImageCacheFind(cache, ro_data, w, h); - if (found_rr_image) { - rr_image = found_rr_image; - RrImageRef(rr_image); - ob_debug("Image \"%s\" is duplicate", name); - } - else { - /* Create RrImage from the image and add it to file name table. */ - rr_image = RrImageNew(cache); - RrImageSetDestroyFunc(rr_image, &RrImageDestroyNotify); - /* XXX: Is Imlib2's format of DATA32 always identical to RrPixel32? */ - RrImageAddPicture(rr_image, ro_data, w, h); - g_hash_table_insert(cache->file_name_table, g_strdup(name), rr_image); - } - - imlib_free_image(); - - return rr_image; -} - -#endif diff --git a/openbox/imageload.h b/openbox/imageload.h deleted file mode 100644 index 21e7c9b0..00000000 --- a/openbox/imageload.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __imageload_h -#define __imageload_h - -#include "obrender/render.h" -RrImage* RrImageFetchFromFile(RrImageCache *cache, const gchar *name); - -#endif diff --git a/openbox/menu.c b/openbox/menu.c index 77d9548c..524220c0 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -36,7 +36,6 @@ #include "gettext.h" #include "obt/xml.h" #include "obt/paths.h" -#include "imageload.h" typedef struct _ObMenuParseState ObMenuParseState; @@ -275,29 +274,39 @@ static void parse_menu_item(xmlNodePtr node, gpointer data) if (state->parent) { /* Don't try to extract "icon" attribute if icons in user-defined - menus are not enabled. */ - if (!(config_menu_user_show_icons && - obt_xml_attr_string(node, "icon", &icon))) - { - icon = NULL; - } + menus are not enabled. */ if (obt_xml_attr_string(node, "label", &label)) { + xmlNodePtr c; GSList *acts = NULL; - node = obt_xml_find_node(node->children, "action"); - while (node) { - ObActionsAct *action = actions_parse(node); + c = obt_xml_find_node(node->children, "action"); + while (c) { + ObActionsAct *action = actions_parse(c); if (action) acts = g_slist_append(acts, action); - node = obt_xml_find_node(node->next, "action"); + c = obt_xml_find_node(node->next, "action"); } e = menu_add_normal(state->parent, -1, label, acts, TRUE); - if (icon) { /* Icon will be used. */ - e->data.normal.icon = RrImageFetchFromFile(ob_rr_icons, icon); + if (config_menu_show_icons && + obt_xml_attr_string(node, "icon", &icon)) + { + RrImage *ic; + + ic = RrImageCacheFindName(ob_rr_icons, icon); + if (ic) + RrImageRef(ic); + else { + ic = RrImageNew(ob_rr_icons); + if (!RrImageAddPictureName(ic, icon)) + RrImageUnref(ic); /* no need to keep it around */ + } + e->data.normal.icon = ic; + if (e->data.normal.icon) e->data.normal.icon_alpha = 0xff; + g_free(icon); } g_free(label); |
