mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-22 05:48:01 +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;
|
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)
|
static RImage *makeRImageFromARGBData(unsigned long *data)
|
||||||
{
|
{
|
||||||
int size, width, height, i;
|
int size, width, height, i;
|
||||||
@@ -452,13 +415,105 @@ static RImage *makeRImageFromARGBData(unsigned long *data)
|
|||||||
return image;
|
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 *get_window_image_from_x11(Window window)
|
||||||
{
|
{
|
||||||
RImage *image;
|
RImage *image;
|
||||||
Atom type;
|
Atom type;
|
||||||
int format;
|
int format;
|
||||||
unsigned long items, rest;
|
unsigned long items, rest;
|
||||||
unsigned long *property, *data;
|
unsigned long *property;
|
||||||
|
|
||||||
/* Get the icon from X11 Window */
|
/* Get the icon from X11 Window */
|
||||||
if (XGetWindowProperty(dpy, window, net_wm_icon, 0L, LONG_MAX,
|
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 */
|
/* Find the best icon */
|
||||||
data = findBestIcon(property, items);
|
image = findBestIcon(property, items);
|
||||||
if (!data) {
|
|
||||||
XFree(property);
|
XFree(property);
|
||||||
|
if (!image)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/* Save the best icon in the X11 icon */
|
|
||||||
image = makeRImageFromARGBData(data);
|
|
||||||
|
|
||||||
XFree(property);
|
|
||||||
|
|
||||||
/* Resize the image to the correct value */
|
/* Resize the image to the correct value */
|
||||||
image = wIconValidateIconSize(image, wPreferences.icon_size);
|
image = wIconValidateIconSize(image, wPreferences.icon_size);
|
||||||
|
|||||||
Reference in New Issue
Block a user