all repos — openbox @ 136c9c078d33e5784881267be03d8ff1adf41bc5

openbox fork - make it a bit more like ryudo

support for pixmap icons, kwm_win_icon and the icon in wmhints
Dana Jansens danakj@orodu.net
commit

136c9c078d33e5784881267be03d8ff1adf41bc5

parent

0c2f0e0b5e974bace6b7488541fac0fed23c5bc9

5 files changed, 117 insertions(+), 46 deletions(-)

jump to
M otk/rendercontrol.ccotk/rendercontrol.cc

@@ -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; - 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; + if (w && h) { + // scale it + unsigned long *olddata = data; + 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) { - unsigned char alpha = data[i] >> 24; - unsigned char r = data[i] >> 16; - unsigned char g = data[i] >> 8; - unsigned char b = data[i]; + // 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; + // background color + 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) | - (b << default_blue_shift); + r = bgr + (((r - bgr) * alpha) >> 8); + g = bgg + (((g - bgg) * alpha) >> 8); + b = bgb + (((b - bgb) * alpha) >> 8); - if (++c >= w) { - c = 0; - bgi += sfw - w; + bg[i] = (r << default_red_shift) | (g << default_green_shift) | + (b << default_blue_shift); } }

@@ -506,6 +494,70 @@

reduceDepth(sf, im); sf.setPixmap(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); } }
M otk/rendercontrol.hhotk/rendercontrol.hh

@@ -64,6 +64,9 @@ */

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,
M src/client.ccsrc/client.cc

@@ -576,6 +576,17 @@ }

} 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::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; }
M src/client.hhsrc/client.hh

@@ -348,8 +348,8 @@ Icon *_icons;

//! 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 @@ smaller than the specified size will be returned.

*/ 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. /*!
M src/frame.ccsrc/frame.cc

@@ -557,6 +557,11 @@ // draw the icon over it

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