support for pixmap icons, kwm_win_icon and the icon in wmhints

This commit is contained in:
Dana Jansens 2003-02-16 21:57:21 +00:00
parent 0c2f0e0b5e
commit 136c9c078d
5 changed files with 117 additions and 46 deletions

View file

@ -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
// Reduce the image size if its too big to make it fit on the surface
int oldw = w, oldh = h;
unsigned long *olddata = data; unsigned long *olddata = data;
if (w > sfw) w = sfw; unsigned long newdata[sfw*sfh];
if (h > sfh) h = sfh; double dx = w / (double)sfw;
unsigned long newdata[w*h]; double dy = h / (double)sfh;
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
for (i = 0, c = 0, e = sfw*sfh; i < e; ++i, ++bgi) {
unsigned char alpha = data[i] >> 24; unsigned char alpha = data[i] >> 24;
unsigned char r = data[i] >> 16; unsigned char r = data[i] >> 16;
unsigned char g = data[i] >> 8; unsigned char g = data[i] >> 8;
unsigned char b = data[i]; 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);
}
} }

View file

@ -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,

View file

@ -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;
} }

View file

@ -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.
/*! /*!

View file

@ -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);