openbox/grab.h \
openbox/group.c \
openbox/group.h \
- openbox/imageload.c \
- openbox/imageload.h \
openbox/keyboard.c \
openbox/keyboard.h \
openbox/keytree.c \
<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>
#include "image.h"
#include "color.h"
#include "imagecache.h"
+#ifdef USE_IMLIB2
+#include <Imlib2.h>
+#endif
#include <glib.h>
#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;
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);
}
}
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);
/* 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
#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]);
}
pic = g_new(RrImagePic, 1);
- RrImagePicInit(pic, dstW, dstH, dststart);
+ RrImagePicInit(pic, NULL, dstW, dstH, dststart);
return pic;
}
}
/*! 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)
#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)
}
}
-/*! 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;
/* 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.
*/
#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,
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;
}
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))
*/
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
/* 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
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
/*! 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
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 =
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;
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;
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"))) {
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);
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 */
+++ /dev/null
-/* -*- 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
+++ /dev/null
-#ifndef __imageload_h
-#define __imageload_h
-
-#include "obrender/render.h"
-RrImage* RrImageFetchFromFile(RrImageCache *cache, const gchar *name);
-
-#endif
#include "gettext.h"
#include "obt/xml.h"
#include "obt/paths.h"
-#include "imageload.h"
typedef struct _ObMenuParseState ObMenuParseState;
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);