From 136c9c078d33e5784881267be03d8ff1adf41bc5 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sun, 16 Feb 2003 21:57:21 +0000 Subject: [PATCH] support for pixmap icons, kwm_win_icon and the icon in wmhints --- otk/rendercontrol.cc | 130 ++++++++++++++++++++++++++++++------------- otk/rendercontrol.hh | 3 + src/client.cc | 17 +++++- src/client.hh | 12 ++-- src/frame.cc | 5 ++ 5 files changed, 119 insertions(+), 48 deletions(-) diff --git a/otk/rendercontrol.cc b/otk/rendercontrol.cc index 8f932968..bf48d58a 100644 --- a/otk/rendercontrol.cc +++ b/otk/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]; - // 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; + // 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[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); + 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); - - if (++c >= w) { - c = 0; - bgi += sfw - w; + bg[i] = (r << default_red_shift) | (g << default_green_shift) | + (b << default_blue_shift); } } @@ -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); +} + } diff --git a/otk/rendercontrol.hh b/otk/rendercontrol.hh index 5e21da29..ff9d313d 100644 --- a/otk/rendercontrol.hh +++ b/otk/rendercontrol.hh @@ -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, diff --git a/src/client.cc b/src/client.cc index 7bf72645..53a6d768 100644 --- a/src/client.cc +++ b/src/client.cc @@ -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; } diff --git a/src/client.hh b/src/client.hh index 8d97bfcc..932bac16 100644 --- a/src/client.hh +++ b/src/client.hh @@ -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. /*! diff --git a/src/frame.cc b/src/frame.cc index d1c206e7..23742be8 100644 --- a/src/frame.cc +++ b/src/frame.cc @@ -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); -- 2.39.2