mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-21 21:38:00 +01:00
Added feature: automatic scaling of application icons
If the option "Enforce icon margin" is selected, application window icons will be selected or scaled so that they only use 75% of the available icon_size. Even if the feature is not enabled, this change will scale down large application icons to icon_size, so that icons can be used that were rejected by the previous implementation of findBestIcon. (Example: The Qt Creator icon never showed before, because it is only provided in 128x128 resolution. Now it's visible.)
This commit is contained in:
committed by
Carlos R. Mafra
parent
d6c1ac3ecf
commit
2427200c3e
141
src/wmspec.c
141
src/wmspec.c
@@ -388,43 +388,6 @@ int wNETWMGetCurrentDesktopFromHint(WScreen *scr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the best icon to be used by Window Maker for appicon/miniwindows.
|
||||
* Currently the algorithm is to take the image with the size closest
|
||||
* to icon_size x icon_size, but never bigger than that.
|
||||
*
|
||||
* This algorithm is very poorly implemented and needs to be redone (it can
|
||||
* easily select images with very large widths and very small heights over
|
||||
* square images, if the area of the former is closer to the desired one).
|
||||
*
|
||||
* The logic can also be changed to accept bigger images and scale them down.
|
||||
*/
|
||||
static unsigned long *findBestIcon(unsigned long *data, unsigned long items)
|
||||
{
|
||||
int size, wanted, d;
|
||||
unsigned long i, distance;
|
||||
unsigned long *icon;
|
||||
|
||||
/* better use only 75% of icon_size. For 64x64 this means 48x48
|
||||
* This leaves room around the icon for the miniwindow title and
|
||||
* results in better overall aesthetics -Dan */
|
||||
wanted = wPreferences.icon_size * wPreferences.icon_size;
|
||||
|
||||
for (icon = NULL, distance = wanted, i = 0L; i < items - 1;) {
|
||||
size = data[i] * data[i + 1];
|
||||
if (size == 0)
|
||||
break;
|
||||
d = wanted - size;
|
||||
if (d >= 0 && d <= distance && (i + size + 2) <= items) {
|
||||
distance = d;
|
||||
icon = &data[i];
|
||||
}
|
||||
i += size + 2;
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
static RImage *makeRImageFromARGBData(unsigned long *data)
|
||||
{
|
||||
int size, width, height, i;
|
||||
@@ -452,13 +415,105 @@ static RImage *makeRImageFromARGBData(unsigned long *data)
|
||||
return image;
|
||||
}
|
||||
|
||||
/* Find the best icon to be used by Window Maker for appicon/miniwindows. */
|
||||
static RImage *findBestIcon(unsigned long *data, unsigned long items)
|
||||
{
|
||||
int wanted;
|
||||
int dx, dy, d;
|
||||
int sx, sy, size;
|
||||
int best_d, largest;
|
||||
unsigned long i;
|
||||
unsigned long *icon;
|
||||
RImage *src_image, *ret_image;
|
||||
double f;
|
||||
|
||||
if (wPreferences.enforce_icon_margin) {
|
||||
|
||||
/* better use only 75% of icon_size. For 64x64 this means 48x48
|
||||
* This leaves room around the icon for the miniwindow title and
|
||||
* results in better overall aesthetics -Dan */
|
||||
wanted = (int)((double)wPreferences.icon_size * 0.75 + 0.5);
|
||||
|
||||
/* the size should be a multiple of 4 */
|
||||
wanted = (wanted >> 2) << 2;
|
||||
|
||||
} else {
|
||||
|
||||
/* This is the "old" approach, which tries to find the largest
|
||||
* icon that still fits into icon_size. */
|
||||
wanted = wPreferences.icon_size;
|
||||
|
||||
}
|
||||
|
||||
/* try to find an icon which is close to the wanted size, but not larger */
|
||||
icon = NULL;
|
||||
best_d = wanted * wanted * 2;
|
||||
for (i = 0L; i < items - 1;) {
|
||||
|
||||
/* get the current icon's size */
|
||||
sx = (int)data[i];
|
||||
sy = (int)data[i + 1];
|
||||
if ((sx < 1) || (sy < 1))
|
||||
break;
|
||||
size = sx * sy + 2;
|
||||
|
||||
/* check the size difference if it's not too large */
|
||||
if ((sx <= wanted) && (sy <= wanted)) {
|
||||
dx = wanted - sx;
|
||||
dy = wanted - sy;
|
||||
d = (dx * dx) + (dy * dy);
|
||||
if (d < best_d) {
|
||||
icon = &data[i];
|
||||
best_d = d;
|
||||
}
|
||||
}
|
||||
|
||||
i += size;
|
||||
}
|
||||
|
||||
/* if an icon has been found, no transformation is needed */
|
||||
if (icon)
|
||||
return makeRImageFromARGBData(icon);
|
||||
|
||||
/* We need to scale down an icon. Find the largest one, for it usually
|
||||
* looks better to scale down a large image by a large scale than a
|
||||
* small image by a small scale. */
|
||||
largest = 0;
|
||||
for (i = 0L; i < items - 1;) {
|
||||
size = (int)data[i] * (int)data[i + 1];
|
||||
if (size == 0)
|
||||
break;
|
||||
if (size > largest) {
|
||||
icon = &data[i];
|
||||
largest = size;
|
||||
}
|
||||
i += size + 2;
|
||||
}
|
||||
|
||||
/* give up if there's no icon to work with */
|
||||
if (!icon)
|
||||
return NULL;
|
||||
|
||||
/* create a scaled down version of the icon */
|
||||
src_image = makeRImageFromARGBData(icon);
|
||||
if (src_image->width > src_image->height) {
|
||||
f = (double)wanted / (double)src_image->width;
|
||||
ret_image = RScaleImage(src_image, wanted, (int)(f * (double)(src_image->height)));
|
||||
} else {
|
||||
f = (double)wanted / (double)src_image->height;
|
||||
ret_image = RScaleImage(src_image, (int)(f * (double)src_image->width), wanted);
|
||||
}
|
||||
RReleaseImage(src_image);
|
||||
return ret_image;
|
||||
}
|
||||
|
||||
RImage *get_window_image_from_x11(Window window)
|
||||
{
|
||||
RImage *image;
|
||||
Atom type;
|
||||
int format;
|
||||
unsigned long items, rest;
|
||||
unsigned long *property, *data;
|
||||
unsigned long *property;
|
||||
|
||||
/* Get the icon from X11 Window */
|
||||
if (XGetWindowProperty(dpy, window, net_wm_icon, 0L, LONG_MAX,
|
||||
@@ -472,16 +527,10 @@ RImage *get_window_image_from_x11(Window window)
|
||||
}
|
||||
|
||||
/* Find the best icon */
|
||||
data = findBestIcon(property, items);
|
||||
if (!data) {
|
||||
image = findBestIcon(property, items);
|
||||
XFree(property);
|
||||
if (!image)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Save the best icon in the X11 icon */
|
||||
image = makeRImageFromARGBData(data);
|
||||
|
||||
XFree(property);
|
||||
|
||||
/* Resize the image to the correct value */
|
||||
image = wIconValidateIconSize(image, wPreferences.icon_size);
|
||||
|
||||
Reference in New Issue
Block a user