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
|
||||
{
|
||||
pixel32 *bg = sf.pixelData();
|
||||
int x, y, c, sfw, sfh;
|
||||
int c, sfw, sfh;
|
||||
unsigned int i, e, bgi;
|
||||
sfw = sf.size().width();
|
||||
sfh = sf.size().height();
|
||||
x = (sfw - w) / 2;
|
||||
y = (sfh - h) / 2;
|
||||
|
||||
if (x < 0) x = 0;
|
||||
if (y < 0) y = 0;
|
||||
|
||||
// Reduce the image size if its too big to make it fit on the surface
|
||||
int oldw = w, oldh = h;
|
||||
if (w && h) {
|
||||
// scale it
|
||||
unsigned long *olddata = data;
|
||||
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;
|
||||
unsigned long newdata[sfw*sfh];
|
||||
double dx = w / (double)sfw;
|
||||
double dy = h / (double)sfh;
|
||||
double px = 0.0;
|
||||
double py = 0.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];
|
||||
if (++c >= w) {
|
||||
if (++c >= sfw) {
|
||||
c = 0;
|
||||
px = 0;
|
||||
py += dy;
|
||||
iy = (int)py * oldw;
|
||||
iy = (int)py * w;
|
||||
} else
|
||||
px += dx;
|
||||
}
|
||||
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 r = data[i] >> 16;
|
||||
unsigned char g = data[i] >> 8;
|
||||
unsigned char b = data[i];
|
||||
|
||||
// background color
|
||||
unsigned char bgr = bg[bgi] >> default_red_shift;
|
||||
unsigned char bgg = bg[bgi] >> default_green_shift;
|
||||
unsigned char bgb = bg[bgi] >> default_blue_shift;
|
||||
unsigned char bgr = bg[i] >> default_red_shift;
|
||||
unsigned char bgg = bg[i] >> default_green_shift;
|
||||
unsigned char bgb = bg[i] >> default_blue_shift;
|
||||
|
||||
r = bgr + (((r - bgr) * alpha) >> 8);
|
||||
g = bgg + (((g - bgg) * 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);
|
||||
|
||||
if (++c >= w) {
|
||||
c = 0;
|
||||
bgi += sfw - w;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,4 +496,68 @@ void RenderControl::drawImage(Surface &sf, int w, int h,
|
|||
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,
|
||||
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
|
||||
virtual void drawString(Surface &sf, const Font &font, int x, int y,
|
||||
const RenderColor &color,
|
||||
|
|
|
@ -576,6 +576,17 @@ void Client::updateWMHints(bool initstate)
|
|||
} else // no group!
|
||||
_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);
|
||||
}
|
||||
|
||||
|
@ -758,15 +769,15 @@ void Client::updateIcons()
|
|||
|
||||
void Client::updateKwmIcon()
|
||||
{
|
||||
_kwm_icon = _kwm_icon_mask = None;
|
||||
_pixmap_icon = _pixmap_icon_mask = None;
|
||||
|
||||
unsigned long num = 2;
|
||||
Pixmap *data;
|
||||
if (otk::Property::get(_window, otk::Property::atoms.kwm_win_icon,
|
||||
otk::Property::atoms.kwm_win_icon, &num, &data)) {
|
||||
if (num >= 2) {
|
||||
_kwm_icon = data[0];
|
||||
_kwm_icon_mask = data[1];
|
||||
_pixmap_icon = data[0];
|
||||
_pixmap_icon_mask = data[1];
|
||||
}
|
||||
delete [] data;
|
||||
}
|
||||
|
|
|
@ -348,8 +348,8 @@ private:
|
|||
//! The number of icons in _icons
|
||||
int _nicons;
|
||||
|
||||
Pixmap _kwm_icon;
|
||||
Pixmap _kwm_icon_mask;
|
||||
Pixmap _pixmap_icon;
|
||||
Pixmap _pixmap_icon_mask;
|
||||
|
||||
//! Retrieves the window's initial gravity
|
||||
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;
|
||||
|
||||
//! 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.
|
||||
*/
|
||||
Pixmap kwmIcon() const { return _kwm_icon; }
|
||||
//! Returns the mask for the KWM_WIN_ICON specified on the window (or None)
|
||||
Pixmap pixmapIcon() const { return _pixmap_icon; }
|
||||
//! 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.
|
||||
*/
|
||||
Pixmap kwmIconMask() const { return _kwm_icon_mask; }
|
||||
Pixmap pixmapIconMask() const { return _pixmap_icon_mask; }
|
||||
|
||||
//! 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,
|
||||
geom.button_size));
|
||||
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());
|
||||
XClearWindow(**otk::display, _icon);
|
||||
|
|
Loading…
Reference in a new issue