support for pixmap icons, kwm_win_icon and the icon in wmhints
This commit is contained in:
parent
0c2f0e0b5e
commit
136c9c078d
5 changed files with 117 additions and 46 deletions
|
@ -438,62 +438,50 @@ void RenderControl::drawImage(Surface &sf, int w, int h,
|
||||||
unsigned long *data) const
|
unsigned long *data) const
|
||||||
{
|
{
|
||||||
pixel32 *bg = sf.pixelData();
|
pixel32 *bg = sf.pixelData();
|
||||||
int x, y, c, sfw, sfh;
|
int c, sfw, sfh;
|
||||||
unsigned int i, e, bgi;
|
unsigned int i, e, bgi;
|
||||||
sfw = sf.size().width();
|
sfw = sf.size().width();
|
||||||
sfh = sf.size().height();
|
sfh = sf.size().height();
|
||||||
x = (sfw - w) / 2;
|
|
||||||
y = (sfh - h) / 2;
|
|
||||||
|
|
||||||
if (x < 0) x = 0;
|
if (w && h) {
|
||||||
if (y < 0) y = 0;
|
// scale it
|
||||||
|
unsigned long *olddata = data;
|
||||||
// Reduce the image size if its too big to make it fit on the surface
|
unsigned long newdata[sfw*sfh];
|
||||||
int oldw = w, oldh = h;
|
double dx = w / (double)sfw;
|
||||||
unsigned long *olddata = data;
|
double dy = h / (double)sfh;
|
||||||
if (w > sfw) w = sfw;
|
|
||||||
if (h > sfh) h = sfh;
|
|
||||||
unsigned long newdata[w*h];
|
|
||||||
if (w < oldw || h < oldh) {
|
|
||||||
double dx = oldw / (double)w;
|
|
||||||
double dy = oldh / (double)h;
|
|
||||||
double px = 0.0;
|
double px = 0.0;
|
||||||
double py = 0.0;
|
double py = 0.0;
|
||||||
int iy = 0;
|
int iy = 0;
|
||||||
for (i = 0, c = 0, e = w*h; i < e; ++i) {
|
for (i = 0, c = 0, e = sfw*sfh; i < e; ++i) {
|
||||||
newdata[i] = olddata[(int)px + iy];
|
newdata[i] = olddata[(int)px + iy];
|
||||||
if (++c >= w) {
|
if (++c >= sfw) {
|
||||||
c = 0;
|
c = 0;
|
||||||
px = 0;
|
px = 0;
|
||||||
py += dy;
|
py += dy;
|
||||||
iy = (int)py * oldw;
|
iy = (int)py * w;
|
||||||
} else
|
} else
|
||||||
px += dx;
|
px += dx;
|
||||||
}
|
}
|
||||||
data = newdata;
|
data = newdata;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0, c = 0, bgi = y * sfw + x, e = w*h; i < e; ++i, ++bgi) {
|
// apply the alpha channel
|
||||||
unsigned char alpha = data[i] >> 24;
|
for (i = 0, c = 0, e = sfw*sfh; i < e; ++i, ++bgi) {
|
||||||
unsigned char r = data[i] >> 16;
|
unsigned char alpha = data[i] >> 24;
|
||||||
unsigned char g = data[i] >> 8;
|
unsigned char r = data[i] >> 16;
|
||||||
unsigned char b = data[i];
|
unsigned char g = data[i] >> 8;
|
||||||
|
unsigned char b = data[i];
|
||||||
|
|
||||||
// background color
|
// background color
|
||||||
unsigned char bgr = bg[bgi] >> default_red_shift;
|
unsigned char bgr = bg[i] >> default_red_shift;
|
||||||
unsigned char bgg = bg[bgi] >> default_green_shift;
|
unsigned char bgg = bg[i] >> default_green_shift;
|
||||||
unsigned char bgb = bg[bgi] >> default_blue_shift;
|
unsigned char bgb = bg[i] >> default_blue_shift;
|
||||||
|
|
||||||
r = bgr + (((r - bgr) * alpha) >> 8);
|
r = bgr + (((r - bgr) * alpha) >> 8);
|
||||||
g = bgg + (((g - bgg) * alpha) >> 8);
|
g = bgg + (((g - bgg) * alpha) >> 8);
|
||||||
b = bgb + (((b - bgb) * alpha) >> 8);
|
b = bgb + (((b - bgb) * alpha) >> 8);
|
||||||
|
|
||||||
bg[bgi] = (r << default_red_shift) | (g << default_green_shift) |
|
bg[i] = (r << default_red_shift) | (g << default_green_shift) |
|
||||||
(b << default_blue_shift);
|
(b << default_blue_shift);
|
||||||
|
|
||||||
if (++c >= w) {
|
|
||||||
c = 0;
|
|
||||||
bgi += sfw - w;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,4 +496,68 @@ void RenderControl::drawImage(Surface &sf, int w, int h,
|
||||||
XDestroyImage(im);
|
XDestroyImage(im);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderControl::drawImage(Surface &sf, Pixmap pixmap, Pixmap mask) const
|
||||||
|
{
|
||||||
|
int junk, sfw, sfh, w, h, depth, mw, mh, mdepth;
|
||||||
|
Window wjunk;
|
||||||
|
const ScreenInfo *info = display->screenInfo(_screen);
|
||||||
|
GC mgc = 0;
|
||||||
|
|
||||||
|
assert(pixmap != None);
|
||||||
|
|
||||||
|
sfw = sf.size().width();
|
||||||
|
sfh = sf.size().height();
|
||||||
|
|
||||||
|
XGetGeometry(**display, pixmap, &wjunk, &junk, &junk,
|
||||||
|
(unsigned int*)&w, (unsigned int*)&h,
|
||||||
|
(unsigned int*)&junk, (unsigned int*)&depth);
|
||||||
|
if (mask != None) {
|
||||||
|
XGetGeometry(**display, mask, &wjunk, &junk, &junk,
|
||||||
|
(unsigned int*)&mw, (unsigned int*)&mh,
|
||||||
|
(unsigned int*)&junk, (unsigned int*)&mdepth);
|
||||||
|
if (mw != w || mh != h || mdepth != 1)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pixmap p = XCreatePixmap(**display, info->rootWindow(), sfw, sfh,
|
||||||
|
info->depth());
|
||||||
|
Pixmap m;
|
||||||
|
if (mask == None)
|
||||||
|
m = None;
|
||||||
|
else {
|
||||||
|
m = XCreatePixmap(**display, info->rootWindow(), sfw, sfh, 1);
|
||||||
|
XGCValues gcv;
|
||||||
|
gcv.subwindow_mode = IncludeInferiors;
|
||||||
|
gcv.graphics_exposures = false;
|
||||||
|
mgc = XCreateGC(**display, m, GCGraphicsExposures |
|
||||||
|
GCSubwindowMode, &gcv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// scale it
|
||||||
|
for (int y = sfh - 1; y >= 0; --y) {
|
||||||
|
int yy = y * h / sfh;
|
||||||
|
for (int x = sfw - 1; x >= 0; --x) {
|
||||||
|
int xx = x * w / sfw;
|
||||||
|
if (depth != info->depth()) {
|
||||||
|
XCopyPlane(**display, pixmap, p, DefaultGC(**display, _screen),
|
||||||
|
xx, yy, 1, 1, x, y, 1);
|
||||||
|
} else {
|
||||||
|
XCopyArea(**display, pixmap, p, DefaultGC(**display, _screen),
|
||||||
|
xx, yy, 1, 1, x, y);
|
||||||
|
}
|
||||||
|
if (mask != None)
|
||||||
|
XCopyArea(**display, mask, m, mgc, xx, yy, 1, 1, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XSetClipMask(**display, DefaultGC(**display, _screen), m);
|
||||||
|
XSetClipOrigin(**display, DefaultGC(**display, _screen), 0, 0);
|
||||||
|
XCopyArea(**display, p, sf.pixmap(), DefaultGC(**display, _screen), 0, 0,
|
||||||
|
sfw, sfh, 0, 0);
|
||||||
|
XSetClipMask(**display, DefaultGC(**display, _screen), None);
|
||||||
|
|
||||||
|
XFreePixmap(**display, p);
|
||||||
|
if (m != None) XFreePixmap(**display, m);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,9 @@ public:
|
||||||
virtual void drawImage(Surface &sf, int w, int h,
|
virtual void drawImage(Surface &sf, int w, int h,
|
||||||
unsigned long *data) const;
|
unsigned long *data) const;
|
||||||
|
|
||||||
|
//! Draws an image onto the surface
|
||||||
|
virtual void drawImage(Surface &sf, Pixmap pixmap, Pixmap mask) const;
|
||||||
|
|
||||||
//! Draws a string onto a Surface
|
//! Draws a string onto a Surface
|
||||||
virtual void drawString(Surface &sf, const Font &font, int x, int y,
|
virtual void drawString(Surface &sf, const Font &font, int x, int y,
|
||||||
const RenderColor &color,
|
const RenderColor &color,
|
||||||
|
|
|
@ -576,6 +576,17 @@ void Client::updateWMHints(bool initstate)
|
||||||
} else // no group!
|
} else // no group!
|
||||||
_group = None;
|
_group = None;
|
||||||
|
|
||||||
|
if (hints->flags & IconPixmapHint) {
|
||||||
|
updateKwmIcon(); // try get the kwm icon first, this is a fallback only
|
||||||
|
if (_pixmap_icon == None) {
|
||||||
|
_pixmap_icon = hints->icon_pixmap;
|
||||||
|
if (hints->flags & IconMaskHint)
|
||||||
|
_pixmap_icon_mask = hints->icon_mask;
|
||||||
|
else
|
||||||
|
_pixmap_icon_mask = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
XFree(hints);
|
XFree(hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,15 +769,15 @@ void Client::updateIcons()
|
||||||
|
|
||||||
void Client::updateKwmIcon()
|
void Client::updateKwmIcon()
|
||||||
{
|
{
|
||||||
_kwm_icon = _kwm_icon_mask = None;
|
_pixmap_icon = _pixmap_icon_mask = None;
|
||||||
|
|
||||||
unsigned long num = 2;
|
unsigned long num = 2;
|
||||||
Pixmap *data;
|
Pixmap *data;
|
||||||
if (otk::Property::get(_window, otk::Property::atoms.kwm_win_icon,
|
if (otk::Property::get(_window, otk::Property::atoms.kwm_win_icon,
|
||||||
otk::Property::atoms.kwm_win_icon, &num, &data)) {
|
otk::Property::atoms.kwm_win_icon, &num, &data)) {
|
||||||
if (num >= 2) {
|
if (num >= 2) {
|
||||||
_kwm_icon = data[0];
|
_pixmap_icon = data[0];
|
||||||
_kwm_icon_mask = data[1];
|
_pixmap_icon_mask = data[1];
|
||||||
}
|
}
|
||||||
delete [] data;
|
delete [] data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,8 +348,8 @@ private:
|
||||||
//! The number of icons in _icons
|
//! The number of icons in _icons
|
||||||
int _nicons;
|
int _nicons;
|
||||||
|
|
||||||
Pixmap _kwm_icon;
|
Pixmap _pixmap_icon;
|
||||||
Pixmap _kwm_icon_mask;
|
Pixmap _pixmap_icon_mask;
|
||||||
|
|
||||||
//! Retrieves the window's initial gravity
|
//! Retrieves the window's initial gravity
|
||||||
void getGravity();
|
void getGravity();
|
||||||
|
@ -665,16 +665,16 @@ BB @param window The window id that the Client class should handle
|
||||||
*/
|
*/
|
||||||
const Icon *icon(const otk::Size &s) const;
|
const Icon *icon(const otk::Size &s) const;
|
||||||
|
|
||||||
//! Returns the pixmap for the KWM_WIN_ICON specified on the window (or None)
|
//! Returns the pixmap for the pixmap icon specified on the window (or None)
|
||||||
/*!
|
/*!
|
||||||
The icon given by Client::icon should take precedence over this icon/mask.
|
The icon given by Client::icon should take precedence over this icon/mask.
|
||||||
*/
|
*/
|
||||||
Pixmap kwmIcon() const { return _kwm_icon; }
|
Pixmap pixmapIcon() const { return _pixmap_icon; }
|
||||||
//! Returns the mask for the KWM_WIN_ICON specified on the window (or None)
|
//! Returns the mask for the pixmap icon specified on the window (or None)
|
||||||
/*!
|
/*!
|
||||||
The icon given by Client::icon should take precedence over this icon/mask.
|
The icon given by Client::icon should take precedence over this icon/mask.
|
||||||
*/
|
*/
|
||||||
Pixmap kwmIconMask() const { return _kwm_icon_mask; }
|
Pixmap pixmapIconMask() const { return _pixmap_icon_mask; }
|
||||||
|
|
||||||
//! Move the window (actually, its frame) to a position.
|
//! Move the window (actually, its frame) to a position.
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -557,6 +557,11 @@ void Frame::renderIcon()
|
||||||
const Icon *icon = _client->icon(otk::Size(geom.button_size,
|
const Icon *icon = _client->icon(otk::Size(geom.button_size,
|
||||||
geom.button_size));
|
geom.button_size));
|
||||||
control->drawImage(*s, icon->w, icon->h, icon->data);
|
control->drawImage(*s, icon->w, icon->h, icon->data);
|
||||||
|
if (!icon->data) {
|
||||||
|
Pixmap p = _client->pixmapIcon(), m = _client->pixmapIconMask();
|
||||||
|
if (p != None)
|
||||||
|
control->drawImage(*s, p, m);
|
||||||
|
}
|
||||||
|
|
||||||
XSetWindowBackgroundPixmap(**otk::display, _icon, s->pixmap());
|
XSetWindowBackgroundPixmap(**otk::display, _icon, s->pixmap());
|
||||||
XClearWindow(**otk::display, _icon);
|
XClearWindow(**otk::display, _icon);
|
||||||
|
|
Loading…
Reference in a new issue