Root pixmap is set when wallpaper is choosed (pseudo transparency).

When icons are moved, correct shape is applied on that window.
...maybe something forgot to add...
This commit is contained in:
Sanel Zukan 2007-06-20 10:58:07 +00:00
parent 84339d9232
commit c153f4f114
7 changed files with 339 additions and 9 deletions

View File

@ -34,8 +34,10 @@
// 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_Button(is->x, is->y, ICONSIZE, ICONSIZE) {
Fl_Widget(is->x, is->y, ICONSIZE, ICONSIZE) {
EASSERT(gs != NULL);
@ -214,7 +216,29 @@ void DesktopIcon::draw(void) {
}
int DesktopIcon::handle(int event) {
return Fl_Button::handle(event);
switch(event) {
case FL_FOCUS:
case FL_UNFOCUS:
case FL_ENTER:
case FL_LEAVE:
return 1;
/*
* We have to handle FL_MOVE too, if want to get only once
* FL_ENTER when entered or FL_LEAVE when leaved.
*/
case FL_MOVE:
return 1;
case FL_PUSH:
return 1;
case FL_RELEASE:
if(Fl::event_clicks() > 0)
EDEBUG(ESTRLOC ": EXECUTE: %s\n", settings->cmd.c_str());
return 1;
default:
break;
}
return 1;
}
MovableIcon::MovableIcon(DesktopIcon* ic) : Fl_Window(ic->x(), ic->y(), ic->w(), ic->h()), icon(ic) {
@ -224,7 +248,16 @@ MovableIcon::MovableIcon(DesktopIcon* ic) : Fl_Window(ic->x(), ic->y(), ic->w(),
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());
#else
icon_box = new Fl_Box(0, 0, w(), h());
#endif
icon_box->image(ic->icon_image());
end();
}
@ -235,8 +268,9 @@ MovableIcon::~MovableIcon() {
void MovableIcon::show(void) {
if(!shown())
Fl_X::make_xid(this);
#if 0
Pixmap mask = create_mask((Fl_RGB_Image*)icon->icon_image());
#ifdef SHAPE
Pixmap mask = create_mask(icon->icon_image());
XShapeCombineMask(fl_display, fl_xid(this), ShapeBounding, 0, 0, mask, ShapeSet);
#endif
}

View File

@ -23,7 +23,7 @@ class GlobalIconSettings;
class IconSettings;
class MovableIcon;
class DesktopIcon : public Fl_Button {
class DesktopIcon : public Fl_Widget {
private:
IconSettings* settings;
const GlobalIconSettings* globals;

View File

@ -23,6 +23,7 @@ Atom _XA_NET_WM_WINDOW_TYPE_DESKTOP = 0;
Atom _XA_NET_NUMBER_OF_DESKTOPS = 0;
Atom _XA_NET_CURRENT_DESKTOP = 0;
Atom _XA_NET_DESKTOP_NAMES = 0;
Atom _XA_XROOTPMAP_ID = 0;
Atom _XA_EDE_DESKTOP_NOTIFY = 0;
Atom _XA_EDE_DESKTOP_NOTIFY_COLOR = 0;
@ -43,6 +44,7 @@ void init_atoms(void) {
_XA_NET_NUMBER_OF_DESKTOPS = XInternAtom(fl_display, "_NET_NUMBER_OF_DESKTOPS", False);
_XA_NET_CURRENT_DESKTOP = XInternAtom(fl_display, "_NET_CURRENT_DESKTOP", False);
_XA_NET_DESKTOP_NAMES = XInternAtom(fl_display, "_NET_DESKTOP_NAMES", False);
_XA_XROOTPMAP_ID = XInternAtom(fl_display, "_XROOTPMAP_ID", False);
_XA_EDE_DESKTOP_NOTIFY = XInternAtom(fl_display, "_EDE_DESKTOP_NOTIFY", False);
_XA_EDE_DESKTOP_NOTIFY_COLOR = XInternAtom(fl_display, "_EDE_DESKTOP_NOTIFY_COLOR", False);
@ -288,6 +290,64 @@ void set_xoverlay_drawable(Fl_Window* win) {
overlay_drawable = win;
}
Pixmap create_mask(Fl_Image* img) {
if(!img)
return 0;
// no alpha
if(img->d() != 4)
return 0;
int iw = img->w();
int ih = img->h();
unsigned char* xim_data = new unsigned char[((iw >> 3) + 8) * ih];
XImage* xim = XCreateImage(fl_display, fl_visual->visual, 1, ZPixmap, 0, (char*)xim_data, iw, ih, 8, 0);
if(!xim) {
delete [] xim_data;
return 0;
}
const char* src = img->data()[0];
unsigned char r,g,b,a;
for(int y = 0; y < ih; y++) {
for(int x = 0; x < iw; x++) {
r = *src++;
g = *src++;
b = *src++;
a = *src++;
//EDEBUG("x: %i y: %i\n", x, y);
if(a < 128)
XPutPixel(xim, x, y, 0);
else
XPutPixel(xim, x, y, 1);
}
}
Window drawable = XCreateSimpleWindow(fl_display, RootWindow(fl_display, fl_screen), 0, 0, iw,
ih, 0, 0, BlackPixel(fl_display, fl_screen));
Pixmap pix = XCreatePixmap(fl_display, drawable, iw, ih, 1);
XGCValues gcv;
gcv.graphics_exposures = False;
GC dgc = XCreateGC(fl_display, pix, GCGraphicsExposures, &gcv);
XPutImage(fl_display, pix, dgc, xim, 0, 0, 0, 0, iw, ih);
XDestroyWindow(fl_display, drawable);
XFreeGC(fl_display, dgc);
delete [] xim->data;
xim->data = 0;
XDestroyImage(xim);
return pix;
}
char* get_basename(const char* path) {
char* p = strrchr(path, '/');
if(p)

View File

@ -24,6 +24,7 @@ extern Atom _XA_NET_WM_WINDOW_TYPE_DESKTOP;
extern Atom _XA_NET_NUMBER_OF_DESKTOPS;
extern Atom _XA_NET_CURRENT_DESKTOP;
extern Atom _XA_NET_DESKTOP_NAMES;
extern Atom _XA_XROOTPMAP_ID;
// via XGetTextProperty/XSetTextProperty
extern Atom _XA_EDE_DESKTOP_NOTIFY;
@ -45,7 +46,7 @@ void draw_xoverlay(int x, int y, int w, int h);
void clear_xoverlay(void);
void set_xoverlay_drawable(Fl_Window* win);
Pixmap create_mask(Fl_RGB_Image* img);
Pixmap create_mask(Fl_Image* img);
char* get_basename(const char* path);

View File

@ -11,15 +11,174 @@
*/
#include "Wallpaper.h"
#include "Utils.h"
#include <edelib/Debug.h>
#include <FL/Fl_Shared_Image.h>
#include <FL/fl_draw.h>
#include <FL/x.h>
Wallpaper::Wallpaper(int X, int Y, int W, int H) : Fl_Box(X, Y, W, H, 0), img(NULL), tiled(false) {
Pixmap create_xpixmap(Fl_Image* img, XImage* xim, Pixmap pix) {
if(!img)
return 0;
if(xim) {
if(xim->data)
delete [] xim->data;
XDestroyImage(xim);
}
if(pix)
XFreePixmap(fl_display, pix);
unsigned long rmask = fl_visual->visual->red_mask;
unsigned long gmask = fl_visual->visual->green_mask;
unsigned long bmask = fl_visual->visual->blue_mask;
unsigned long start_mask;
int start_shift;
int rshift = 0;
int gshift = 0;
int bshift = 0;
if(fl_visual->depth == 24 || fl_visual->depth == 16) {
unsigned long n;
if(fl_visual->depth == 24) {
start_shift = 24;
start_mask = 0x80000000;
} else {
start_shift = 8;
start_mask = 0x8000;
}
rshift = start_shift;
n = start_mask;
while(!(n & rmask)) {
n >>= 1;
rshift--;
}
gshift = start_shift;
n = start_mask;
while(!(n & gmask)) {
n >>= 1;
gshift--;
}
bshift = start_shift;
n = start_mask;
while(!(n & bmask)) {
n >>= 1;
bshift--;
}
}
// assume display == 16 depth
xim = XCreateImage(fl_display, fl_visual->visual, 16, ZPixmap, 0, 0, img->w(), img->h(), 16, 0);
if(xim->bits_per_pixel != 16) {
EWARNING("Visual %i not implemented yet\n", xim->bits_per_pixel);
XDestroyImage(xim);
return 0;
}
if(img->d() < 3) {
EWARNING("Only RGB(A) images is supported for now\n");
XDestroyImage(xim);
return 0;
}
int iw = img->w();
int ih = img->h();
int id = img->d();
bool msb = false;
if(ImageByteOrder(fl_display) == MSBFirst)
msb = true;
else
msb = false;
unsigned int r, g, b, tmp;
unsigned char* dest = new unsigned char[iw * ih * id];
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(id == 4)
src++;
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);
if(msb) {
// big endian
*destptr++ = (tmp >> 8) & 0xff;
*destptr++ = (tmp & 0xff);
} else {
// little endian
*destptr++ = (tmp & 0xff);
*destptr++ = (tmp >> 8) & 0xff;
}
}
}
xim->data = (char*)dest;
/*
* Creating another window as drawable is needed since fl_window (as drawable) can't be
* used here (valid only in draw()).
*/
Window drawable = XCreateSimpleWindow(fl_display, RootWindow(fl_display, fl_screen), 0, 0, iw,
ih, 0, 0, BlackPixel(fl_display, fl_screen));
pix = XCreatePixmap(fl_display, drawable, iw, ih, fl_visual->depth);
/*
* The same applies as above;
* fl_gc can't be used here.
*/
XGCValues gcv;
gcv.graphics_exposures = False;
GC dgc = XCreateGC(fl_display, pix, GCGraphicsExposures, &gcv);
XPutImage(fl_display, pix, dgc, xim, 0, 0, 0, 0, iw, ih);
XDestroyWindow(fl_display, drawable);
XFreeGC(fl_display, dgc);
return pix;
}
Wallpaper::Wallpaper(int X, int Y, int W, int H) :
Fl_Box(X, Y, W, H, 0), rootpmap_image(NULL), rootpmap_pixmap(0), img(NULL), tiled(false) {
}
Wallpaper::~Wallpaper() {
if(rootpmap_image) {
if(rootpmap_image->data)
delete [] rootpmap_image->data;
XDestroyImage(rootpmap_image);
}
if(rootpmap_pixmap)
XFreePixmap(fl_display, rootpmap_pixmap);
}
bool Wallpaper::set(const char* path) {
@ -33,6 +192,8 @@ bool Wallpaper::set(const char* path) {
img = i;
image(img);
set_rootpmap();
return true;
}
@ -43,6 +204,46 @@ bool Wallpaper::set_tiled(const char* path) {
return ret;
}
void Wallpaper::set_rootpmap(void) {
if(!image())
return;
rootpmap_pixmap = create_xpixmap(image(), rootpmap_image, rootpmap_pixmap);
if(!rootpmap_pixmap)
return;
XChangeProperty(fl_display, RootWindow(fl_display, fl_screen),
_XA_XROOTPMAP_ID, XA_PIXMAP, 32, PropModeReplace, (unsigned char *)&rootpmap_pixmap, 1);
#if 0
XGCValues gcv;
gcv.graphics_exposures = False;
GC dgc = XCreateGC(fl_display, pix, GCGraphicsExposures, &gcv);
XImage img;
img.byte_order = LSBFirst; // TODO: check
img.format = ZPixmap;
img.depth = fl_visual->depth; // depth of screen or depth of image() ?
// find out bits_per_pixel field
int num_pfv;
XPixmapFormatValues* pfv = 0;
XPixmapFormatValues* pfvlst = 0;
pfvlst = XListPixmapFormats(fl_display, &num_pfv);
for(pfv = pfvlst; pfv < pfvlst + num_pfv; pfv++) {
if(pfv->depth == fl_visual->depth)
break;
}
img.bits_per_pixel = pfv->bits_per_pixel;
if(img.bits_per_pixel & 7) {
EWARNING("Can't work with %i bpp !!!\n", img.bits_per_pixel);
return;
}
#endif
}
void Wallpaper::draw(void) {
if(!image())
return;
@ -84,4 +285,25 @@ void Wallpaper::draw(void) {
}
im->draw(ix, iy);
/*
* For debugging purposes :)
* Uncommenting this (and removing GC/Window creation in create_xpixmap
* will draw _XA_XROOTPMAP_ID Pixmap directly in Wallpaper widget.
* It is used to check Fl_Image->Image conversion.
*/
#if 0
if(global_xim) {
Pixmap pix = fl_create_offscreen(image()->w(), image()->h());
fl_begin_offscreen(pix);
XPutImage(fl_display, pix, fl_gc, global_xim, 0, 0, 0, 0, image()->w(), image()->h());
fl_end_offscreen();
fl_copy_offscreen(ix, iy, image()->w(), image()->h(), pix, 0, 0);
XChangeProperty(fl_display, RootWindow(fl_display, fl_screen),
_XA_XROOTPMAP_ID, XA_PIXMAP, 32, PropModeReplace, (unsigned char *)&pix, 1);
}
#endif
}

View File

@ -16,14 +16,19 @@
#include <FL/Fl_Box.h>
#include <FL/Fl_Image.h>
#include <X11/Xlib.h> // XImage, Pixmap
/*
* Class responsible for displaying images at background
* their scaling (TODO), caching(TODO) and making coffee at spear time.
*/
class Wallpaper : public Fl_Box {
private:
XImage* rootpmap_image;
Pixmap rootpmap_pixmap;
Fl_Image* img;
bool tiled;
void set_rootpmap(void);
public:
Wallpaper(int X, int Y, int W, int H);

View File

@ -87,10 +87,16 @@ int desktop_xmessage_handler(int event) {
return 1;
}
if(fl_xevent->xclient.message_type == _XA_EDE_DESKTOP_NOTIFY_COLOR) {
//if(fl_xevent->xclient.message_type == _XA_EDE_DESKTOP_NOTIFY_COLOR) {
if(fl_xevent->xproperty.atom == _XA_EDE_DESKTOP_NOTIFY_COLOR) {
Desktop::instance()->notify_box_color(ede_get_desktop_notify_color());
return 1;
}
if(fl_xevent->xproperty.atom == _XA_NET_WORKAREA) {
Desktop::instance()->update_workarea();
return 1;
}
}
return 0;
@ -114,7 +120,9 @@ 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/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();
end();