From f006fb0d0f1bd4d9b9807bc0d7c10b8d55706adf Mon Sep 17 00:00:00 2001 From: Sanel Zukan Date: Fri, 22 Jun 2007 09:43:15 +0000 Subject: [PATCH] Small fix in case of desktop icon without image. Rootpmap accepts now works for 16/24 bit displays with 16/24/32 bit images. --- eiconman/DesktopIcon.cpp | 64 ++++++++++--- eiconman/DesktopIcon.h | 3 + eiconman/Utils.cpp | 17 ++-- eiconman/Wallpaper.cpp | 201 +++++++++++++++++++++++++++++++-------- eiconman/eiconman.cpp | 4 +- 5 files changed, 225 insertions(+), 64 deletions(-) diff --git a/eiconman/DesktopIcon.cpp b/eiconman/DesktopIcon.cpp index a17619a..7514f0c 100644 --- a/eiconman/DesktopIcon.cpp +++ b/eiconman/DesktopIcon.cpp @@ -22,7 +22,11 @@ #include #include -#include +#define USE_SHAPE 1 + +#ifdef USE_SHAPE + #include +#endif // minimal icon size #define ICONSIZE 48 @@ -34,7 +38,6 @@ // label offset from icon y()+h(), so selection box can be drawn nicely #define LABEL_OFFSET 2 -#define SHAPE 1 DesktopIcon::DesktopIcon(GlobalIconSettings* gs, IconSettings* is, int bg) : Fl_Widget(is->x, is->y, ICONSIZE, ICONSIZE) { @@ -121,15 +124,42 @@ void DesktopIcon::update_label_size(void) { void DesktopIcon::drag(int x, int y, bool apply) { if(!micon) { micon = new MovableIcon(this); +#if USE_SHAPE + /* + * This is used to calculate correct window startup/ending + * position since icon is placed in the middle of the box. + * + * Opposite, window (shaped) will have small but noticeable 'jump off' and + * dropped icon position will not be at the exact place where was dropped. + */ + int ix, iy; + ix = iy = 0; + if(image()) { + ix = (w()/2) - (image()->w()/2); + iy = (h()/2) - (image()->h()/2); + } + + micon->position(micon->x() + ix, micon->y() + iy); +#endif micon->show(); + } else { + EASSERT(micon != NULL); + + micon->position(x, y); } - EASSERT(micon != NULL); - - micon->position(x, y); - if(apply) { +#if USE_SHAPE + int ix, iy; + ix = iy = 0; + if(image()) { + ix = (w()/2) - (image()->w()/2); + iy = (h()/2) - (image()->h()/2); + } + position(micon->x() - ix, micon->y() - iy); +#else position(micon->x(), micon->y()); +#endif delete micon; micon = NULL; } @@ -241,20 +271,23 @@ int DesktopIcon::handle(int event) { return 1; } -MovableIcon::MovableIcon(DesktopIcon* ic) : Fl_Window(ic->x(), ic->y(), ic->w(), ic->h()), icon(ic) { +MovableIcon::MovableIcon(DesktopIcon* ic) : Fl_Window(ic->x(), ic->y(), ic->w(), ic->h()), icon(ic), mask(0) { EASSERT(icon != NULL); set_override(); color(ic->color()); begin(); - Fl_Image* img = ic->icon_image(); /* * Force box be same width/height as icon so it * can fit inside masked window. */ -#ifdef SHAPE - icon_box = new Fl_Box(0, 0, img->w(), img->h()); +#ifdef USE_SHAPE + Fl_Image* img = ic->icon_image(); + if(img) + icon_box = new Fl_Box(0, 0, img->w(), img->h()); + else + icon_box = new Fl_Box(0, 0, w(), h()); #else icon_box = new Fl_Box(0, 0, w(), h()); #endif @@ -263,14 +296,19 @@ MovableIcon::MovableIcon(DesktopIcon* ic) : Fl_Window(ic->x(), ic->y(), ic->w(), } MovableIcon::~MovableIcon() { + if(mask) + XFreePixmap(fl_display, mask); } void MovableIcon::show(void) { if(!shown()) Fl_X::make_xid(this); -#ifdef SHAPE - Pixmap mask = create_mask(icon->icon_image()); - XShapeCombineMask(fl_display, fl_xid(this), ShapeBounding, 0, 0, mask, ShapeSet); +#ifdef USE_SHAPE + if(icon->icon_image()) { + mask = create_mask(icon->icon_image()); + if(mask) + XShapeCombineMask(fl_display, fl_xid(this), ShapeBounding, 0, 0, mask, ShapeSet); + } #endif } diff --git a/eiconman/DesktopIcon.h b/eiconman/DesktopIcon.h index d91eb15..5b83a73 100644 --- a/eiconman/DesktopIcon.h +++ b/eiconman/DesktopIcon.h @@ -19,6 +19,8 @@ #include #include +#include // Pixmap + class GlobalIconSettings; class IconSettings; class MovableIcon; @@ -76,6 +78,7 @@ class MovableIcon : public Fl_Window { private: DesktopIcon* icon; Fl_Box* icon_box; + Pixmap mask; public: MovableIcon(DesktopIcon* i); diff --git a/eiconman/Utils.cpp b/eiconman/Utils.cpp index 9a0e459..608c583 100644 --- a/eiconman/Utils.cpp +++ b/eiconman/Utils.cpp @@ -310,21 +310,22 @@ Pixmap create_mask(Fl_Image* img) { } const char* src = img->data()[0]; - unsigned char r,g,b,a; + unsigned char a; for(int y = 0; y < ih; y++) { for(int x = 0; x < iw; x++) { - r = *src++; - g = *src++; - b = *src++; + // jump rgb and pick alpha + src += 3; a = *src++; - //EDEBUG("x: %i y: %i\n", x, y); - - if(a < 128) + if(a < 128) { + // these are transparent XPutPixel(xim, x, y, 0); - else + } + else { + // these are opaque XPutPixel(xim, x, y, 1); + } } } diff --git a/eiconman/Wallpaper.cpp b/eiconman/Wallpaper.cpp index b0e2205..bb37cbb 100644 --- a/eiconman/Wallpaper.cpp +++ b/eiconman/Wallpaper.cpp @@ -18,14 +18,35 @@ #include #include +#define CALC_PIXEL(tmp, rshift, rmask, gshift, gmask, bshift, bmask) \ + tmp = 0; \ + if(rshift >= 0) \ + tmp |= (((int)r << rshift) & rmask); \ + else \ + tmp |= (((int)r >> (-rshift)) & rmask); \ +\ + if(gshift >= 0) \ + tmp |= (((int)g << gshift) & gmask); \ + else \ + tmp |= (((int)g >> (-gshift)) & gmask); \ +\ + if(bshift >= 0) \ + tmp |= (((int)b << bshift) & bmask); \ + else \ + tmp |= (((int)b >> (-bshift)) & bmask); + + Pixmap create_xpixmap(Fl_Image* img, XImage* xim, Pixmap pix) { if(!img) return 0; if(xim) { - if(xim->data) + if(xim->data) { delete [] xim->data; + xim->data = 0; + } XDestroyImage(xim); + xim = 0; } if(pix) @@ -70,25 +91,26 @@ Pixmap create_xpixmap(Fl_Image* img, XImage* xim, Pixmap pix) { n >>= 1; bshift--; } - } else { - EWARNING("Depth %i not supported, for now\n", fl_visual->depth); - return 0; } - // assume display == 16 depth - xim = XCreateImage(fl_display, fl_visual->visual, 16, ZPixmap, 0, 0, img->w(), img->h(), 16, 0); + /* + * Figure out bitmap_pad and create image coresponding to the current + * display depth except for 8 bpp display + */ + int bitmap_pad = 0; + if(fl_visual->depth > 16) + bitmap_pad = 32; + else if(fl_visual->depth > 8) + bitmap_pad = 16; + else { + EWARNING("Visual %i not supported\n", xim->bits_per_pixel); - if(xim->bits_per_pixel != 16) { - EWARNING("Visual %i not implemented yet\n", xim->bits_per_pixel); XDestroyImage(xim); + xim = 0; return 0; } - if(img->d() < 3) { - EWARNING("Only RGB(A) images is supported for now\n"); - XDestroyImage(xim); - return 0; - } + xim = XCreateImage(fl_display, fl_visual->visual, fl_visual->depth, ZPixmap, 0, 0, img->w(), img->h(), bitmap_pad, 0); int iw = img->w(); int ih = img->h(); @@ -105,39 +127,136 @@ Pixmap create_xpixmap(Fl_Image* img, XImage* xim, Pixmap pix) { unsigned char* destptr = dest; unsigned char* src = (unsigned char*)img->data()[0]; - for(int j = 0; j < ih; j++) { - for(int i = 0; i < iw; i++) { - r = *src++; - g = *src++; - b = *src++; + if(xim->bits_per_pixel == 32) { + if(id == 3 || id == 4) { + for(int j = 0; j < ih; j++) { + for(int i = 0; i < iw; i++) { + r = *src++; + g = *src++; + b = *src++; - if(id == 4) - src++; + if(id == 4) + src++; - tmp = 0; - if(rshift >= 0) - tmp |= (((int)r << rshift) & rmask); - else - tmp |= (((int)r >> (-rshift)) & rmask); + CALC_PIXEL(tmp, rshift, rmask, gshift, gmask, bshift, bmask); - if(gshift >= 0) - tmp |= (((int)g << gshift) & gmask); - else - tmp |= (((int)g >> (-gshift)) & gmask); + if(msb) { + // big endian + *destptr++ = (tmp & 0xff000000) >> 24; + *destptr++ = (tmp & 0xff0000) >> 16; + *destptr++ = (tmp & 0xff00) >> 8; + *destptr++ = (tmp & 0xff); + } else { + // little endian + *destptr++ = (tmp & 0xff); + *destptr++ = (tmp & 0xff00) >> 8; + *destptr++ = (tmp & 0xff0000) >> 16; + *destptr++ = (tmp & 0xff000000) >> 24; + } + } + } + } else { + for(int j = 0; j < ih; j++) { + for(int i = 0; i < iw; i++) { + r = *src++; + g = *src++; + b = *src++; - if(bshift >= 0) - tmp |= (((int)b << bshift) & bmask); - else - tmp |= (((int)b >> (-bshift)) & bmask); + if(msb) { + *destptr++ = 0; + *destptr++ = b; + *destptr++ = g; + *destptr++ = r; + } else { + *destptr++ = r; + *destptr++ = g; + *destptr++ = b; + *destptr++ = 0; + } + } + } + } + } else if(xim->bits_per_pixel == 24) { + if(id == 3 || id == 4) { + for(int j = 0; j < ih; j++) { + for(int i = 0; i < iw; i++) { + r = *src++; + g = *src++; + b = *src++; - if(msb) { - // big endian - *destptr++ = (tmp >> 8) & 0xff; - *destptr++ = (tmp & 0xff); - } else { - // little endian - *destptr++ = (tmp & 0xff); - *destptr++ = (tmp >> 8) & 0xff; + if(id == 4) + src++; + + CALC_PIXEL(tmp, rshift, rmask, gshift, gmask, bshift, bmask); + + if(msb) { + // big endian + *destptr++ = (tmp & 0xff0000) >> 16; + *destptr++ = (tmp & 0xff00) >> 8; + *destptr++ = (tmp & 0xff); + + } else { + // little endian + *destptr++ = (tmp & 0xff); + *destptr++ = (tmp & 0xff00) >> 8; + *destptr++ = (tmp & 0xff0000) >> 16; + } + } + } + } else { + for(int j = 0; j < ih; j++) { + for(int i = 0; i < iw; i++) { + r = *src++; + g = *src++; + b = *src++; + if(msb) { + // big endian + *destptr++ = b; + *destptr++ = g; + *destptr++ = r; + } else { + // little endian + *destptr++ = r; + *destptr++ = g; + *destptr++ = b; + } + } + } + } + } else if(xim->bits_per_pixel == 16) { + if(id == 3 || id == 4) { + for(int j = 0; j < ih; j++) { + for(int i = 0; i < iw; i++) { + r = *src++; + g = *src++; + b = *src++; + + if(id == 4) + src++; + + CALC_PIXEL(tmp, rshift, rmask, gshift, gmask, bshift, bmask); + + if(msb) { + // big endian + *destptr++ = (tmp >> 8) & 0xff; + *destptr++ = (tmp & 0xff); + + } else { + // little endian + *destptr++ = (tmp & 0xff); + *destptr++ = (tmp >> 8) & 0xff; + } + } + } + } else { + for(int j = 0; j < ih; j++) { + for(int i = 0; i < iw; i++) { + r = *src >> 3; src++; + g = *src >> 2; src++; + b = *src >> 3; src++; + + *destptr++ = r << 11 | g << 5 | b; + } } } } diff --git a/eiconman/eiconman.cpp b/eiconman/eiconman.cpp index 34d3979..207ccf6 100644 --- a/eiconman/eiconman.cpp +++ b/eiconman/eiconman.cpp @@ -120,8 +120,8 @@ Desktop::Desktop() : Fl_Window(0, 0, 100, 100, "") { */ begin(); wallpaper = new Wallpaper(0, 0, w(), h()); - //wallpaper->set("/home/sanel/wallpapers/katebig.jpg"); - wallpaper->set("/home/sanelz/walls/nin/1024x768-04.jpg"); + wallpaper->set("/home/sanel/wallpapers/katebig.jpg"); + //wallpaper->set("/home/sanelz/walls/nin/1024x768-04.jpg"); //wallpaper->set("/home/sanelz/walls/nin/1024x768-02.jpg"); notify = new NotifyBox(w(), h()); notify->hide();