#include "baghira.h"
#include <cmath>
#include <qapplication.h>
#include <qbrush.h>
#include <qcolor.h>
#include <qevent.h> 
#include <qimage.h>
#include <qobject.h>
#include <qpainter.h>
#include <qpalette.h>
#include <qpopupmenu.h>
#include <qrect.h>
#include <qsettings.h>
#include <qsize.h>
#include <qstring.h>
#include <kpixmapeffect.h>
#include <kimageeffect.h>
#include <X11/X.h>
#include <X11/Xlib.h>

#define _SCALE_    65536
#define _NORMALIZE_ >>16

/*
  Internal class to get access to protected QWidget-members
*/

class QAccessPopupMenu : public QPopupMenu
{
    friend class OptionHandler;
public:
    QAccessPopupMenu( QWidget* parent=0, const char* name=0)
	: QPopupMenu( parent, name ) {}
};

//using namespace BaghiraStyle;
static int *top_right_corner;
static int *top_left_corner;
static int *bottom_right_corner;
static int *bottom_left_corner;
static int *shadow_strip;

OptionHandler::OptionHandler( QObject *parent ) : QObject( parent ) {
	QIntDict<KPixmap>popupDict(499);
	fillPixmap = NULL;
	directFollower = true;
	menusProcessed = false;
	scrollerActive = false;
//	menuItemActive = false;
	menuLevelCounter = 0;
	groupShadowButton = false;
//	lastPopupRect;// = new QRect;
	popupDict.setAutoDelete(true);
	dropShadowsInited = false;
	indicatedMenuItemPix = NULL;
	lastIndicatedMenuItemPix = NULL;
	indicatedMenuItemRect = new QRect(0,0,0,0);
	lastIndicatedMenuItemRect = new QRect(0,0,0,0);
	daddyWasAPopup = false;
        mouseOverMenu = false;
	unblocked = true;
	currentMenu = NULL;
	reloadSettings();
	}

	
const QColor& OptionHandler::textColor() {
	return ( useCustomMenuColor ? fgColor : qApp->palette().active().text() );
	}

const QColor& OptionHandler::bgColor() {
	LiquidStyle * style = ( LiquidStyle* ) parent();
	if ( !menuColorButton )
		return ( style->isKicker ? style->origPanelBrush.color() : qApp->palette().active().background() );
	else{
//		qWarning("we have button color");
		return ( qApp->palette().active().button() );
		}
	return (color);

	}

const QColor& OptionHandler::buttonColor() {
	LiquidStyle * style = ( LiquidStyle* ) parent();
	if ( !menuColorButton )
		return ( style->isKicker ? style->origPanelBrush.color() : qApp->palette().active().button() );
	else{
//		qWarning("we have button color");
		return ( qApp->palette().active().background() );
		}
	return (color);

	}

void OptionHandler::reloadSettings() {
	popupDict.setAutoDelete(true);
	popupDict.clear();
	currentPopupWinID = 0;
	currentPopup = NULL;
	lastPopupID = 0;
	lastIndicatedMenuItemID = 0;
	// gather options...
	QSettings *settings = new QSettings;
	
	//we need that first to make sure we use some proper settings ;)
	customButtonColor = QColor(settings->readNumEntry("/qt/Baghira/buttonColor",(int)qApp->palette().active().button().rgb()));
	forceRectButton = settings->readBoolEntry( "/qt/Baghira/forceRectButtons", false);
        brushMe = settings->readBoolEntry( "/qt/Baghira/brushMe", false );
	if (brushMe){
		tintBrush = settings->readBoolEntry( "/qt/Baghira/tintBrush", false );
		if (tintBrush)
			brushTint.setRgb( settings->readNumEntry( "/qt/Baghira/brushTint", ( int ) bgColor().rgb()));
		else
			brushedMetalColor = QColor(200, 200, 200);
		
	}
	// menu stuff
	stippleMenu = settings->readBoolEntry( "/qt/Baghira/stippleMenu", true);
	menuTranslucency =  settings->readNumEntry( "/qt/Baghira/menuTranslucency", DefaultTrans);
	if (menuTranslucency >= CustomTrans)
		opacity = settings->readNumEntry( "/qt/Baghira/customMenuOpacity", 9);
	menuColorButton = settings->readBoolEntry( "/qt/Baghira/menuColorButton", false);
	shadowText = settings->readBoolEntry( "/qt/Baghira/shadowedText", false);
	menuDropShadows = settings->readBoolEntry( "/qt/Baghira/menuDropShadows", true);
	shadowOffset = menuDropShadows ? settings->readNumEntry( "/qt/Baghira/shadowOffset", 8) : 0;
	dropShadowDarkness = menuDropShadows ? settings->readNumEntry( "/qt/Baghira/dropShadowDarkness", 2) : 0;

	// color stuff
	// widgets
	customWidgetColor  =  settings->readBoolEntry( "/qt/Baghira/useCustomWidgetColor", false);
	if ( customWidgetColor ) {
		customColors[ CustomRadioOn ].setRgb( settings->readNumEntry( "/qt/Baghira/customRadioOnColor", ( int ) buttonColor().rgb() ) );
		customColors[ CustomRadioOff ].setRgb( settings->readNumEntry( "/qt/Baghira/customRadioOffColor", ( int ) bgColor().rgb() ) );
		customColors[ CustomCBOn ].setRgb( settings->readNumEntry( "/qt/Baghira/customCheckOnColor", ( int ) buttonColor().rgb() ) );
		customColors[ CustomCBOff ].setRgb( settings->readNumEntry( "/qt/Baghira/customCheckOffColor", ( int ) bgColor().rgb() ) );
		customColors[ CustomTabOn ].setRgb( settings->readNumEntry( "/qt/Baghira/customActiveTabColor", ( int ) buttonColor().rgb() ) );
		customColors[ CustomTabOff ].setRgb( settings->readNumEntry( "/qt/Baghira/customInactiveTabColor", ( int ) bgColor().rgb() ) );
		customColors[ CustomSBSlider ].setRgb( settings->readNumEntry( "/qt/Baghira/customSliderColor", ( int ) bgColor().rgb() ) );
		customColors[ CustomSBSliderHover ].setRgb( settings->readNumEntry( "/qt/Baghira/customHoveredSliderColor", ( int ) buttonColor().rgb() ) );
		customColors[ CustomSBSliderPressed ].setRgb( settings->readNumEntry( "/qt/Baghira/customPressedSliderColor", ( int ) buttonColor().dark(110).rgb() ) );
		customColors[ CustomSBGroove ].setRgb( settings->readNumEntry( "/qt/Baghira/customSliderGrooveColor", ( int ) bgColor().rgb() ) );
	}
	// menu
	useCustomMenuColor = settings->readBoolEntry( "/qt/Baghira/useCustomMenuStyle", false);
	if (useCustomMenuColor){
		color = QColor( settings->readNumEntry( "/qt/Baghira/customMenuColor", 0 ) );
		fgColor = QColor( settings->readNumEntry( "/qt/Baghira/customMenuTextColor", 0 ) );
	}
	menuAnimation = (Effects::DirFlags) settings->readNumEntry( "/qt/Baghira/menuAnimation", 1);
	menuAnimationSpeed = settings->readNumEntry( "/qt/Baghira/menuAnimationSpeed", 20)*10;
	// Panel
	panelCustom = settings->readBoolEntry( "/qt/Baghira/useCustomPanelColor", false );
	if (panelCustom)
		customPanelColor = QColor( settings->readNumEntry( "/qt/Baghira/customPanelColor", ( int ) bgColor().rgb() ) );
	// inactive Button
	inactiveButtonColor = settings->readNumEntry( "/qt/Baghira/inactiveButtonColor", Background);
	if (inactiveButtonColor == Custom)
		customInactiveButtonColor = QColor( settings->readNumEntry( "/qt/Baghira/customInactiveButtonColor", (int) bgColor().rgb()));

	//design stuff
	//stipple
	bgStipple = brushMe ? true : settings->readBoolEntry( "/qt/Baghira/stippleBackground", true );
	panelStipple = brushMe ? true : settings->readBoolEntry( "/qt/Baghira/stipplePanel", true );
	contrast = settings->readNumEntry( "/qt/Baghira/stippleContrast", 3);
        bevelHighlights_ = settings->readBoolEntry( "/qt/Baghira/bevelHighlights", true);
	//shadows
	groupboxshadow = brushMe ? false : settings->readBoolEntry( "/qt/Baghira/useGroupShadows", true );
	shadowDarkness = settings->readNumEntry( "/qt/Baghira/shadowDarkness", 3);
	//ListViews
	expanderStyle = settings->readNumEntry( "/qt/Baghira/expanderStyle", Apple);
	useCustomExpanderColor = settings->readBoolEntry( "/qt/Baghira/useCustomExpanderColor", false);
	if (useCustomExpanderColor)
		expanderColor = QColor( settings->readNumEntry( "/qt/Baghira/expanderColor", (int) qApp->palette().active().text().rgb()));
	drawDotlines = settings->readBoolEntry( "/qt/Baghira/drawDotlines", true);
	if (drawDotlines){
		dotlineStyle = settings->readNumEntry( "/qt/Baghira/dotlineStyle", Line);
		dotlineColor = QColor( settings->readNumEntry( "/qt/Baghira/dotlineColor", (int) qApp->palette().active().mid().rgb()));
	}
	//slider
	squeezesbslider = settings->readBoolEntry( "/qt/Baghira/squeezeSbSlider", false );
	shadowsbslider = settings->readBoolEntry( "/qt/Baghira/shadowSbSlider", false );
	animateSlider = settings->readBoolEntry( "/qt/Baghira/animateSlider", true );
	// toolbar
	tbFrame = settings->readBoolEntry( "/qt/Baghira/drawToolbarButtonFrames", false );

	// tweaks
//	alignStipples = settings->readBoolEntry( "/qt/Baghira/alignStipples", false);
	centerTabs = settings->readBoolEntry( "/qt/Baghira/centerTabs", true);
//	engageFB = settings->readBoolEntry( "/qt/Baghira/engageFB", false);
	smoothListViewHeaders = settings->readBoolEntry( "/qt/Baghira/smoothListViewHeaders", true);
	smootherLVH = settings->readBoolEntry( "/qt/Baghira/smootherLVH", false);
	icyButtons = settings->readBoolEntry( "/qt/Baghira/icyButtons", true);
//	saturation = settings->readNumEntry( "/qt/Baghira/saturation", 6);
	progressBar = settings->readNumEntry( "/qt/Baghira/progressBar", baghira);
	removeKickerBevel = settings->readBoolEntry( "/qt/Baghira/removeKickerBevel", false);
	smoothToolbuttons = settings->readBoolEntry( "/qt/Baghira/smoothToolbuttons", true);
	drawProgressLabel = settings->readBoolEntry( "/qt/Baghira/drawProgressLabel", false);
	tabStyle_ = (tabStyle) settings->readNumEntry( "/qt/Baghira/TabStyle", Clever);
        
        settings->writeEntry("/qt/BAB/styleQueried", true);
        delete settings;

	// Option gathered
	}


void OptionHandler::rightShadow(QImage& dst, int swh)
{
	int swh2;
	if (dst.depth() != 32)
		dst = dst.convertDepth(32);
		
	if (dst.height() < 2*swh){
		swh = dst.height()/2;
		swh2 = dst.height() - swh;
	}
	else
		swh2 = swh;

	// blend top-right corner.
	int pixels = dst.width() * dst.height();
#ifdef WORDS_BIGENDIAN
	register unsigned char* data = dst.bits() + 1;	// Skip alpha
#else
	register unsigned char* data = dst.bits();		// Skip alpha
#endif
	for(register int i = 0; i < dst.width()*swh; i++) {
		*data++ = (unsigned char)(((*data)*top_right_corner[i])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*top_right_corner[i])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*top_right_corner[i])_NORMALIZE_);
		data++;	// skip alpha
	}

	pixels -= (dst.width()*swh + dst.width()*swh2);	// tint right strip without rounded edges.
	register int c = 0;
	for(register int i = 0; i < pixels; i++) {
		*data++ = (unsigned char)(((*data)*shadow_strip[c])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*shadow_strip[c])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*shadow_strip[c])_NORMALIZE_);
		data++; // skip alpha
		c = ++c % dst.width();
	}

	// tint bottom edge
	for(register int i = 0; i < dst.width()*swh2; i++) {
		*data++ = (unsigned char)(((*data)*bottom_right_corner[i])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*bottom_right_corner[i])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*bottom_right_corner[i])_NORMALIZE_);
		data++;	// skip alpha
	}
}

void OptionHandler::leftShadow(QImage& dst, int swh)
{
	int swh2;
	if (dst.depth() != 32)
		dst = dst.convertDepth(32);
		
	if (dst.height() < 2*swh){
		swh = dst.height()/2;
		swh2 = dst.height() - swh;
	}
	else
		swh2 = swh;

	// blend top-right corner.
	int pixels = dst.width() * dst.height();
#ifdef WORDS_BIGENDIAN
	register unsigned char* data = dst.bits() + 1;	// Skip alpha
#else
	register unsigned char* data = dst.bits();		// Skip alpha
#endif
	for(register int i = 0; i < dst.width()*swh; i++) {
		*data++ = (unsigned char)(((*data)*top_left_corner[i])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*top_left_corner[i])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*top_left_corner[i])_NORMALIZE_);
		data++;	// skip alpha
	}

	pixels -= (dst.width()*swh + dst.width()*swh2);	// tint right strip without rounded edges.
	register int c = 0;
	for(register int i = 0; i < pixels; i++) {
		*data++ = (unsigned char)(((*data)*shadow_strip[swh-1-c])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*shadow_strip[swh-1-c])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*shadow_strip[swh-1-c])_NORMALIZE_);
		data++; // skip alpha
		c = ++c % dst.width();
	}

	// tint bottom edge
	for(register int i = 0; i < dst.width()*swh2; i++) {
		*data++ = (unsigned char)(((*data)*bottom_left_corner[i])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*bottom_left_corner[i])_NORMALIZE_);
		*data++ = (unsigned char)(((*data)*bottom_left_corner[i])_NORMALIZE_);
		data++;	// skip alpha
	}
}

void OptionHandler::bottomShadow(QImage& dst, int swh)
{
	if (dst.depth() != 32)
		dst = dst.convertDepth(32);
	
	if (dst.width() < swh)
		swh = dst.width();

	int line = 0;
	int width = dst.width()/* - swh*/;
	int strip_data = shadow_strip[0];
//	double* corner = const_cast<double*>(bottom_left_corner);

#ifdef WORDS_BIGENDIAN
	register unsigned char* data = dst.bits() + 1;	// Skip alpha
#else
	register unsigned char* data = dst.bits();	// Skip alpha
#endif
	for(int y = 0; y < dst.height(); y++)
	{
		// Bottom-left Corner
/*		for(register int x = 0; x < swh; x++) {
			*data++ = (unsigned char)((*data)*(*corner));
			*data++ = (unsigned char)((*data)*(*corner));
			*data++ = (unsigned char)((*data)*(*corner));
			data++; // skip alpha
			corner++;
		}*/

		// Scanline
		for(register int x = 0; x < width; x++) {
			*data++ = (unsigned char)(((*data)*strip_data)_NORMALIZE_);
			*data++ = (unsigned char)(((*data)*strip_data)_NORMALIZE_);
			*data++ = (unsigned char)(((*data)*strip_data)_NORMALIZE_);
			data++;
		}

		strip_data = shadow_strip[++line];
	}
}

void OptionHandler::saveBitBlt(QPixmap* to, int x_to, int y_to, QPixmap* from, int x_from, int y_from, int width, int height, QString error){
	if (x_to < 0)
		qWarning("Error (x_to < 0): %s", error.ascii());
	else if (y_to < 0)
		qWarning("Error (y_to < 0): %s", error.ascii());
	else if (x_from < 0)
		qWarning("Error (x_from < 0): %s", error.ascii());
	else if (y_from < 0)
		qWarning("Error (y_from < 0): %s", error.ascii());
	else if (from->width() - x_from < width)
		qWarning("Error (from too narrow): %s", error.ascii());
	else if (from->height() - y_from < height)
		qWarning("Error (from to short): %s", error.ascii());
	else if (to->width() - x_to < width)
		qWarning("Error (to too narrow): %s", error.ascii());
	else if (to->height() - y_to < height)
		qWarning("Error (x_from < 0): %s", error.ascii());
	else
		bitBlt(to, x_to, y_to, from, x_from, y_from, width, height);
}

// Create a shadow of variable thickness
void OptionHandler::createShadowWindows(const QPopupMenu* p, PopupStuff *popupStuff/*QPixmap *cleanPix*/, int swh/*, int leftOffset*/)
{
// first, we should check, if we allready rendered the dropshadows for this popup...
	if (popupStuff->hasShadows){
		ShadowElements *se = popupStuff->shadow;
		// Show the 'shadow' just before showing the popup menu window
		// Don't use QWidget::show() so we don't confuse QEffects, thus causing broken focus.
		if (se->w1) XMapWindow(qt_xdisplay(), se->w1->winId());
		if (se->w3) XMapWindow(qt_xdisplay(), se->w3->winId());
		if (se->w2) XMapWindow(qt_xdisplay(), se->w2->winId());
	}
	else{ // this is a new shadow, so we have to render it from scratch
		ShadowElements *se = new ShadowElements;
		int leftOffset = 0;
		KPixmap *cleanPix = NULL;
		if (popupStuff) {leftOffset = popupStuff->leftOffset; cleanPix = popupStuff->cleanPix;}
		bool haveCleanPix = cleanPix && !cleanPix->isNull();
                QImage img;
		if (p->height() >= swh){ // right shadows
			QRect *tmpRect;
			QRect shadow1;
			int x2 = p->x()+p->width();
			int x3 = p->x()-leftOffset;
			if (haveCleanPix){
				// hier scheitert's manchmal - ich weiß aber net, warum...
				//if (cleanPix->isNull()) qWarning("Null Pixmap received?!");
				shadow1 = QRect(x2, p->y(), cleanPix->width() - p->width() - leftOffset, cleanPix->height());
			}
			else{
				shadow1 = QRect(x2, p->y() + swh, swh, p->height());
			}
			if (shadow1.width() > 0){
				se->w1 = new QWidget(0, 0, WStyle_Customize | WType_Popup | WX11BypassWM );
				se->w1->setGeometry(shadow1);
				// Create a fake drop-down shadow effect via blended Xwindows
				XSelectInput(qt_xdisplay(), se->w1->winId(), StructureNotifyMask );
				// Some hocus-pocus here to create the drop-shadow.
				QPixmap pix_shadow1;
				if (haveCleanPix){  // we have a proper pixmap to take background information from...
					pix_shadow1.resize(shadow1.width(), shadow1.height());
					// as the shadows may conflict with the menuindicator, we "reclean" the the clean pix by patching the menuindicator in ;-)
					// if you think of removing this for the right side shadows: remember someone could use kicker on the right side... :}
					if (daddyWasAPopup){
						// obviously, this is also for the left shadows, but we do it a bit before to avoid using unhandled cleanpix!
						QRect tmpRect2 = QRect(x3,p->y(),cleanPix->width(),cleanPix->height());
						if ((tmpRect = sharedRect(lastIndicatedMenuItemRect,&tmpRect2))){
							//saveBitBlt(cleanPix,tmpRect->x() - x3, tmpRect->y() - p->y(), lastIndicatedMenuItemPix, tmpRect->x() - lastIndicatedMenuItemRect->x(), tmpRect->y() - lastIndicatedMenuItemRect->y(), tmpRect->width(), tmpRect->height(), "1");
							bitBlt(cleanPix,tmpRect->x() - x3, tmpRect->y() - p->y(), lastIndicatedMenuItemPix, tmpRect->x() - lastIndicatedMenuItemRect->x(), tmpRect->y() - lastIndicatedMenuItemRect->y(), tmpRect->width(), tmpRect->height());
						}
					}
					// can't create shadow pixmap before, as cleanpix was just handled
					//saveBitBlt( &pix_shadow1, 0, 0, cleanPix, p->width() + leftOffset, 0, cleanPix->width() - p->width() - leftOffset, cleanPix->height(), "2");
					bitBlt( &pix_shadow1, 0, 0, cleanPix, p->width()+leftOffset, 0, pix_shadow1.width(), pix_shadow1.height());
					if (daddyWasAPopup){
						if ((tmpRect = sharedRect(indicatedMenuItemRect,&shadow1))){
							//saveBitBlt(&pix_shadow1,shadow1.width()-tmpRect->width(),tmpRect->y()-shadow1.y(),indicatedMenuItemPix,/*this will pretty much allways be zero*/tmpRect->x()-indicatedMenuItemRect->x(),/*this will pretty much allways be zero*/ tmpRect->y()-indicatedMenuItemRect->y(),tmpRect->width(),tmpRect->height(),"3");
							bitBlt(&pix_shadow1,shadow1.width()-tmpRect->width(),tmpRect->y() - shadow1.y(),indicatedMenuItemPix,/*this will pretty much allways be zero*/tmpRect->x()-indicatedMenuItemRect->x(),/*this will pretty much allways be zero*/ tmpRect->y() - indicatedMenuItemRect->y(),tmpRect->width(),tmpRect->height());
						}
					}
				}
				else{  // ... otherwise we have to take a new (probably ugly) screenshot.
					qWarning("NULL pixmap received for shadows");
					pix_shadow1 = QPixmap::grabWindow(qt_xrootwin(), shadow1.x(), shadow1.y(), shadow1.width(), shadow1.height());
				}
				
				img = pix_shadow1.convertToImage();
				rightShadow(img, swh);
				KImageEffect::addNoise(img);
				pix_shadow1.convertFromImage(img);
				// Set the background pixmaps
				se->w1->setErasePixmap(pix_shadow1);
				// Show the 'shadow' just before showing the popup menu window
				// Don't use QWidget::show() so we don't confuse QEffects, thus causing broken focus.	
				XMapWindow(qt_xdisplay(), se->w1->winId());
			}
			// and left shadows...
			QRect shadow3;
			if (haveCleanPix){
				shadow3 = QRect(x3, p->y(), leftOffset, cleanPix->height());
			}
			else{
				shadow3 = QRect(p->x()-swh, p->y() + swh, swh, p->height());
			}
			if (shadow3.width() > 0){
				se->w3 = new QWidget(0, 0, WStyle_Customize | WType_Popup | WX11BypassWM );
				se->w3->setGeometry(shadow3);
				// Create a fake drop-down shadow effect via blended Xwindows
				XSelectInput(qt_xdisplay(), se->w3->winId(), StructureNotifyMask );
				// Some hocus-pocus here to create the drop-shadow.
				QPixmap pix_shadow3;
				if (haveCleanPix){  // we have a proper pixmap to take background information from...
					pix_shadow3.resize(leftOffset, cleanPix->height());
					bitBlt( &pix_shadow3, 0, 0, cleanPix, 0, 0, pix_shadow3.width(), pix_shadow3.height());
					//saveBitBlt( &pix_shadow3, 0, 0, cleanPix, 0, 0, pix_shadow3.width(), pix_shadow3.height(),"4");
					// as the shadows may conflict with the menuindicator, we "reclean" the the clean pix by patching the menuindicator in ;-)
					if (daddyWasAPopup && (tmpRect = sharedRect(indicatedMenuItemRect,&shadow3))){
						//saveBitBlt(&pix_shadow3,shadow3.width()-tmpRect->width(),tmpRect->y()-shadow3.y(),indicatedMenuItemPix,/*this will pretty much allways be zero*/tmpRect->x()-indicatedMenuItemRect->x(),/*this will pretty much allways be zero*/ tmpRect->y()-indicatedMenuItemRect->y(),tmpRect->width(),tmpRect->height(),"5");
						bitBlt(&pix_shadow3,shadow3.width()-tmpRect->width(),tmpRect->y()-shadow3.y(),indicatedMenuItemPix,/*this will pretty much allways be zero*/tmpRect->x()-indicatedMenuItemRect->x(),/*this will pretty much allways be zero*/ tmpRect->y()-indicatedMenuItemRect->y(),tmpRect->width(),tmpRect->height());
					}
				}
				else{  // ... otherwise we have to take a new (probably ugly) screenshot.
					qWarning("NULL pixmap received for shadows");
					pix_shadow3 = QPixmap::grabWindow(qt_xrootwin(), shadow3.x(), shadow3.y(), shadow3.width(), shadow3.height());
				}
			
				img = pix_shadow3.convertToImage();
				leftShadow(img, swh);
				KImageEffect::addNoise(img);
				pix_shadow3.convertFromImage(img);
				// Set the background pixmaps
				se->w3->setErasePixmap(pix_shadow3);
				// Show the 'shadow' just before showing the popup menu window
				// Don't use QWidget::show() so we don't confuse QEffects, thus causing broken focus.
				XMapWindow(qt_xdisplay(), se->w3->winId());
			}
		}
		if (p->width() >= swh){ // bottom shadows
			QRect shadow2;
			int y2 = p->y()+p->height();
			if (haveCleanPix){
				shadow2 = QRect(p->x(), y2, p->width(), cleanPix->height()-p->height());
			}
			else{			
				shadow2 = QRect(p->x() + swh, y2, p->width() - swh, swh);
			}
			if (shadow2.height() > 0){
				se->w2 = new QWidget(0, 0, WStyle_Customize | WType_Popup | WX11BypassWM );
				se->w2->setGeometry(shadow2);
				// Create a fake drop-down shadow effect via blended Xwindows
				XSelectInput(qt_xdisplay(), se->w2->winId(), StructureNotifyMask );
				// Some hocus-pocus here to create the drop-shadow.
				QPixmap pix_shadow2;
				if (haveCleanPix){  // we have a proper pixmap to take background information from...
					pix_shadow2.resize(p->width(), shadow2.height());
					//saveBitBlt( &pix_shadow2, 0, 0, cleanPix, leftOffset, p->height(), pix_shadow2.width(), pix_shadow2.height()/*p->width(), cleanPix->height()-p->height()*/,"6");
					bitBlt( &pix_shadow2, 0, 0, cleanPix, leftOffset, p->height(), pix_shadow2.width(), pix_shadow2.height());
				}
				else{  // ... otherwise we have to take a new (probably ugly) screenshot.
					qWarning("NULL pixmap received for shadows");
					pix_shadow2 = QPixmap::grabWindow(qt_xrootwin(), shadow2.x(), shadow2.y(), shadow2.width(), shadow2.height());
				}
				
				img = pix_shadow2.convertToImage();
				bottomShadow(img, swh);
				KImageEffect::addNoise(img);
				pix_shadow2.convertFromImage(img);
				// Set the background pixmaps
				se->w2->setErasePixmap(pix_shadow2);
				// Show the 'shadow' just before showing the popup menu window
				// Don't use QWidget::show() so we don't confuse QEffects, thus causing broken focus.
				XMapWindow(qt_xdisplay(), se->w2->winId());
			}
		}
		// Insert a new ShadowMap entry
		popupStuff->shadow = se;
		popupStuff->hasShadows = true;
	}
	daddyWasAPopup = false;
}

void OptionHandler::removeShadowWindows(const QPopupMenu* p)
{
	PopupStuff *popupStuff = popupDict.find(p->winId());
	if (popupStuff && popupStuff->shadow)
	{
	ShadowElements *se = popupStuff->shadow;
	if (se->w1)
		XUnmapWindow(qt_xdisplay(), se->w1->winId());	// hide
	if (se->w2)
		XUnmapWindow(qt_xdisplay(), se->w2->winId());
	if (se->w3)
		XUnmapWindow(qt_xdisplay(), se->w3->winId());
	XFlush(qt_xdisplay());							// try to hide faster
	}
}

void OptionHandler::prepareMenus() {
	if ( menusProcessed )
		return ;

	if ( fillPixmap )
		delete fillPixmap;
	fillPixmap = NULL;
	if ( stippleMenu ) {
		QColor c( bgColor() );
		fillPixmap = new QPixmap( 32, 32 );
		fillPixmap->fill( c.rgb() );
		int i;
		QPainter painter;
		painter.begin( fillPixmap );
		painter.setPen( c.dark( 103 ) );
		for ( i = 0; i < 32; i += 4 ) {
			painter.drawLine( 0, i, 32, i );
			//            painter.drawLine(0, i+1, 32, i+1);
			}
		painter.end();
		}
	menusProcessed = true;
	}

void OptionHandler::stripePixmap( KPixmap &pix, const QColor &color ) {
	QImage img( pix.convertToImage() );
	if ( img.depth() < 32 )
		img = img.convertDepth( 32 );
	KImageEffect::fade( img, 0.9, color );
	int x, y;
	int r, g, b;
	for ( y = 0; y < img.height(); y += 3 ) {
		unsigned int * data = ( unsigned int * ) img.scanLine( y );
		for ( x = 0; x < img.width(); ++x ) {
			r = qRed( data[ x ] );
			g = qGreen( data[ x ] );
			b = qBlue( data[ x ] );
			r = r - 10 >= 0 ? r - 10 : 0;
			g = g - 10 >= 0 ? g - 10 : 0;
			b = b - 10 >= 0 ? b - 10 : 0;
			data[ x ] = qRgb( r, g, b );
			}
		}
	pix.convertFromImage( img );
	}

void OptionHandler::stripePixmap( KPixmap &pix, const QColor &color, int density )    // density in percent, therefore use 0..100
	{
	density > 100 ? density = 100 : density < 0 ? density = 0 : density = density;
	QImage img( pix.convertToImage() );
	if ( img.depth() < 32 )
		img = img.convertDepth( 32 );
	KImageEffect::fade( img, (float) density / 100, color );
	int x, y;
	int r, g, b;
	for ( y = 0; y < img.height(); y += 3 ) {
		unsigned int * data = ( unsigned int * ) img.scanLine( y );
		for ( x = 0; x < img.width(); ++x ) {
			r = qRed( data[ x ] );
			g = qGreen( data[ x ] );
			b = qBlue( data[ x ] );
			r = r - 10 >= 0 ? r - 10 : 0;
			g = g - 10 >= 0 ? g - 10 : 0;
			b = b - 10 >= 0 ? b - 10 : 0;
			data[ x ] = qRgb( r, g, b );
			}
		}
	pix.convertFromImage( img );
	}

void OptionHandler::renderMenuBlendPixmap( KPixmap *blendPix, QColor c, QPopupMenu *p, int leftOffset ){
	QImage gr = KImageEffect::gradient(QSize(p->width(),4), c.dark(150), c.light(170), KImageEffect::HorizontalGradient );
	QPixmap grT(gr);
	QPainter p2(blendPix);
	p2.drawTiledPixmap(leftOffset,0, p->width(), p->height(), grT);
	p2.end();
}

void OptionHandler::initDropShadows(int swh){
	top_right_corner = new int[swh*swh];
	top_left_corner = new int[swh*swh];
	bottom_right_corner = new int[swh*swh];
	bottom_left_corner = new int[swh*swh];
	shadow_strip = new int[swh];
	double slow = (double)swh / 2.5;
	int dark = dropShadowDarkness;
	for (int i = 0; i < swh; i++){ // top 2 bottom ....
		for (int j = 0; j < swh; j++){ // left 2 right ...
			top_right_corner[swh*i+j] =// pow(-exp(-(((swh-i)+j)/slow)-1)+1,dark); // x = 0 -> inf (swh)
			top_left_corner[swh*i+(swh-1-j)] =  int(pow(-exp(-(((swh-i)+j)/slow)-1)+1,dark) * _SCALE_);
			bottom_right_corner[swh*i+j] =// pow(-exp(-((i+j)/slow)-1)+1,dark);
//			bottom_left_corner[swh*i+j] = pow(-exp(-((i+(swh-j))/slow)-1)+1,dark);
			bottom_left_corner[swh*i+(swh-1-j)] = int(pow(-exp(-((i+j)/slow)-1)+1,dark) * _SCALE_);
		}
		shadow_strip[i] = int(pow(-exp(-(i/slow)-1)+1,dark) * _SCALE_);
	}
	dropShadowsInited = true;
}

bool OptionHandler::eventFilter( QObject *obj, QEvent *ev ) {
	prepareMenus();
	QAccessPopupMenu * p = ( QAccessPopupMenu * ) obj;
	const int swh = shadowOffset;
//	if (p->parent() && p->parent()->inherits("KPopupMenu")) qWarning ("dady is a %s", p->parent()->className());
	bool secMenuDropShadows = menuDropShadows && (unblocked = (unblocked && (!p->parent() || !(p->parent()->inherits("KPopupMenu")) || p->parent()->inherits("KPanelMenu"))));// && (p->height() > swh) && (p->width() > swh);
	int leftOffset = swh;

	if ( ev->type() == QEvent::Show ) {
		menuLevelCounter++; // one more menu
		if (secMenuDropShadows && ! dropShadowsInited) initDropShadows(swh);
		KPixmap *cleanPix = NULL;
		PopupStuff *newPopupStuff = NULL;
		if (secMenuDropShadows || (menuTranslucency >= DefaultTrans)){
			newPopupStuff = new PopupStuff;
		}
		QWidget fadeWidget;
		fadeWidget.setGeometry(p->geometry());
		QPixmap fadeBackPix(fadeWidget.width(), fadeWidget.height());
		if ((menuTranslucency >= DefaultTrans) && unblocked ) {
			KPixmap *pix = new KPixmap;
			KPixmap *blendPix = NULL;
//			KPixmap *blendPixFract;
			QImage blendImg;
			QImage backImg;
			//search ONCE for the old and or current popupstuff
			PopupStuff *popupStuff = popupDict.find(p->winId());
			PopupStuff *oldPopupStuff = popupDict.find(lastPopupID);
			//now either we have it, or not!
			if ( p->testWFlags( Qt::WType_Popup ) ) { // switch these lines for permormance...!
				QPixmap fadePix;
				if (MenuAnimation() > None) fadePix = QPixmap(fadeWidget.width(), fadeWidget.height());
				if (popupStuff){
					if (MenuAnimation() > None){
						bitBlt( &fadePix, 0, 0, popupStuff->pix, popupStuff->leftOffset, 0, fadePix.width(), fadePix.height());
						fadeWidget.setErasePixmap(fadePix);
						bitBlt( &fadeBackPix, 0, 0, popupStuff->cleanPix, popupStuff->leftOffset, 0, fadeBackPix.width(), fadeBackPix.height());
						if (MenuAnimation() == Effects::FadeIn){
							secMenuDropShadows ? 
							FadeEffect(&fadeWidget, &fadeBackPix, MenuAnimationSpeed(), this, p, popupStuff, swh ) :
							FadeEffect(&fadeWidget, &fadeBackPix, MenuAnimationSpeed());
						}
						else {
							secMenuDropShadows ? 
							ScrollEffect(&fadeWidget, &fadeBackPix, MenuAnimation(), MenuAnimationSpeed(), this, p, popupStuff, swh ) :
							ScrollEffect(&fadeWidget, &fadeBackPix, MenuAnimation(), MenuAnimationSpeed());
						}
					}
					else if (secMenuDropShadows) createShadowWindows(p, popupStuff, swh);
					directFollower = false;
					return (false); //skip unnessecary following stuff
				}
				else{
					QRect r( p->x()-swh, p->y(), p->width()+2*swh, p->height()+swh );
					QRect *rShare;
					if (directFollower && oldPopupStuff && oldPopupStuff->pix){
						KPixmap *oldPix;
						if ((menuTranslucency == Gradient || secMenuDropShadows || MenuAnimation() == Effects::FadeIn) && oldPopupStuff && oldPopupStuff->cleanPix){
//							qWarning("old clean Pix used");
							oldPix = oldPopupStuff->cleanPix;
						}else
							oldPix = oldPopupStuff->pix;
						rShare = sharedRect(&r, &lastPopupRect );

						QRect deskR = QApplication::desktop() ->rect();
						if ( r.right() > deskR.right() && r.right() - deskR.right() < r.width() ) r.setRight( deskR.right() );
						if ( r.left() < deskR.left() && deskR.left() - r.left() < r.width()){leftOffset = swh - (deskR.left()-r.left()); r.setLeft( deskR.left() );}
						if (r.bottom() > deskR.bottom()  && r.bottom() - deskR.bottom() < r.height()) r.setBottom( deskR.bottom() );

						QApplication::syncX();
						*pix = QPixmap::grabWindow( qt_xrootwin(), r.x(), r.y(), r.width(), r.height());
						if (menuTranslucency == Gradient || secMenuDropShadows || MenuAnimation() == Effects::FadeIn){
							cleanPix = new KPixmap(*pix);
						}
						if (menuTranslucency == Gradient){
							blendPix = (KPixmap *)(new QPixmap(pix->width(), pix->height()));
							renderMenuBlendPixmap( blendPix, useCustomMenuColor ? color : bgColor(), p, leftOffset );
						}

						if (rShare /*&& rShare->width()*rShare->height() > ??? (for speed optimization, it could be useful to precheck if the following work is worth it)*/){
/*
						Now we want to fract the grabbed Pixmap, depending on the shared rect.
						There can be a maximum of 5 fracts (OK, if we were gtkRadiant, there could be severel thousands and thousands :) - Don't take this serious: fracting in gtkRadiant is a bit more complex than this...
						A possible fraction can be like this:
								|---------------------------------------------------------------|
								|			top					|
								|---------------------------------------------------------------|
								|	l	|				|	r	|
								|	e	|	center			|	i	|
								|	f	|	(this is rShare!)	|	g	|
								|	t	|				|	h	|
								|-----------------------------------------------|	t	|
								|		bottom				|		|
								---------------------------------------------------------------
						So all we have to do, is checking if the different sections exist and if so, transform them and copy them to the resulting pixmap
*/
							QPainter icyApainter;
//							QPainter icyAnotherpainter;
							KPixmap *tmpFractPix;
							int topHeight = 0, rightWidth = 0, bottomHeight = 0, leftWidth = 0;
							tmpFractPix = (KPixmap *)(new QPixmap(rShare->width(), rShare->height())); // as there IS a share, we start with this!
							bitBlt( tmpFractPix, 0, 0, oldPix, rShare->x() - lastPopupRect.x(), rShare->y() - lastPopupRect.y(), rShare->width(), rShare->height());
							if (menuTranslucency == Gradient || secMenuDropShadows || MenuAnimation() == Effects::FadeIn){
								// first clean the new Pix
								icyApainter.begin( cleanPix );
								icyApainter.drawPixmap(rShare->x() - (p->x()-leftOffset),rShare->y() - p->y(),*tmpFractPix);
								icyApainter.end();
								// then store our new clean pixmap
								newPopupStuff->cleanPix = cleanPix;
							}
							if (menuTranslucency == Gradient){
								icyApainter.begin( pix );
								icyApainter.drawPixmap(rShare->x() - (p->x()-leftOffset),rShare->y() - p->y(),*tmpFractPix);
								icyApainter.end();
								if (opacity < 10){
									// blend me
									blendImg = blendPix->convertToImage();
									backImg  = pix->convertToImage();
									KImageEffect::blend(blendImg, backImg, (( float ) opacity )  * 0.1);
									pix->convertFromImage(backImg); // tmpFractPix should now be fractpart blended
								}
								else 
									pix = blendPix;
								newPopupStuff->pix = pix;
								newPopupStuff->leftOffset = leftOffset;
								popupDict.insert(p->winId(),newPopupStuff);
								if (MenuAnimation() > None){
									bitBlt( &fadePix, 0, 0, pix, leftOffset, 0, fadePix.width(), fadePix.height());
									fadeWidget.setErasePixmap(fadePix);
									bitBlt( &fadeBackPix, 0, 0, cleanPix, leftOffset, 0, fadeBackPix.width(), fadeBackPix.height());
									if (MenuAnimation() == Effects::FadeIn){
										secMenuDropShadows ? 
										FadeEffect(&fadeWidget, &fadeBackPix, MenuAnimationSpeed(), this, p, newPopupStuff, swh ) :
										FadeEffect(&fadeWidget, &fadeBackPix, MenuAnimationSpeed());
									} 
									else {
										secMenuDropShadows ? 
										ScrollEffect(&fadeWidget, &fadeBackPix, MenuAnimation(), MenuAnimationSpeed(), this, p, newPopupStuff, swh ) :
										ScrollEffect(&fadeWidget, &fadeBackPix, MenuAnimation(), MenuAnimationSpeed());
									}
								}
								else if (secMenuDropShadows) createShadowWindows(p, newPopupStuff, swh);
								// fracting is slow for gradients because of the pixmap-image converter function
								// as fracting also doesn't improve anythig for gradients: out here
								directFollower = false;
								return (false);
							}
							if (menuTranslucency == Gradient || secMenuDropShadows || MenuAnimation() == Effects::FadeIn)
								oldPix = oldPopupStuff->pix;
							bitBlt( tmpFractPix, 0, 0, oldPix, rShare->x() - lastPopupRect.x(), rShare->y() - lastPopupRect.y(), rShare->width(), rShare->height());
							icyApainter.begin( pix );
							icyApainter.drawPixmap(rShare->x() - (p->x()-leftOffset),rShare->y() - p->y(),*tmpFractPix);

							if (rShare->y() > p->y()){ // top fract, as (0,0) is upper left corner
								delete tmpFractPix;
								tmpFractPix = (KPixmap *)(new QPixmap(p->width()+leftOffset+swh, topHeight = rShare->y() - p->y()));
								bitBlt( tmpFractPix, 0, 0, pix, 0, 0, p->width()+leftOffset+swh, topHeight);

								if (stippleMenu){
									if (menuTranslucency == CustomTrans)
										stripePixmap(*tmpFractPix, useCustomMenuColor ? color : bgColor(), opacity * 10);
									else
										stripePixmap( *tmpFractPix, useCustomMenuColor ? color : bgColor() );
								}
								else {
									if (menuTranslucency == CustomTrans)
										KPixmapEffect::fade( *tmpFractPix, (  ( float ) opacity )  * 0.1, useCustomMenuColor ? color : bgColor() );
									else
										KPixmapEffect::fade( *tmpFractPix, 0.9, useCustomMenuColor ? color : bgColor() );
								}
								icyApainter.drawPixmap(0, 0, *tmpFractPix);
							}

							if (p->x() + p->width()+swh > rShare->x() + rShare->width()){ // right fract
								delete tmpFractPix;
								tmpFractPix = (KPixmap *)(new QPixmap(rightWidth = (p->x() + p->width() + swh) - (rShare->x() + rShare->width()), p->height() + swh - topHeight));
								bitBlt( tmpFractPix, 0, 0, pix, p->width() + leftOffset+swh - rightWidth, topHeight, rightWidth, p->height() + swh - topHeight);


								if (stippleMenu){
									if (menuTranslucency == CustomTrans)
										stripePixmap(*tmpFractPix, useCustomMenuColor ? color : bgColor(), opacity * 10);
									else
										stripePixmap( *tmpFractPix, useCustomMenuColor ? color : bgColor() );
								}
								else {
									if (menuTranslucency == CustomTrans)
										KPixmapEffect::fade( *tmpFractPix, (  ( float ) opacity )  * 0.1, useCustomMenuColor ? color : bgColor() );
									else
										KPixmapEffect::fade( *tmpFractPix,  0.9, useCustomMenuColor ? color : bgColor() );
								}
								icyApainter.drawPixmap(p->width() + leftOffset+swh - rightWidth, topHeight, *tmpFractPix);
							}

							if (p->y() + p->height() + swh > rShare->y() + rShare->height()){ // bottom fract
								delete tmpFractPix;
								tmpFractPix = (KPixmap *)(new QPixmap(p->width() + leftOffset+swh - rightWidth, bottomHeight = p->height() + swh - topHeight - rShare->height()));
								bitBlt( tmpFractPix, 0, 0, pix, 0, topHeight + rShare->height(), p->width() + leftOffset+swh - rightWidth, bottomHeight);

								if (stippleMenu){
									if (menuTranslucency == CustomTrans)
										stripePixmap(*tmpFractPix, useCustomMenuColor ? color : bgColor(), opacity * 10);
									else
										stripePixmap( *tmpFractPix, useCustomMenuColor ? color : bgColor() );
								}
								else {
									if (menuTranslucency == CustomTrans)
										KPixmapEffect::fade( *tmpFractPix, (  ( float ) opacity )  * 0.1, useCustomMenuColor ? color : bgColor() );
									else
										KPixmapEffect::fade( *tmpFractPix, 0.9, useCustomMenuColor ? color : bgColor() );
								}
								icyApainter.drawPixmap(0, p->height() + swh - bottomHeight, *tmpFractPix);
							}

							if (rShare->x() > p->x()){ // left fract
								delete tmpFractPix;
								tmpFractPix = (KPixmap *)(new QPixmap(leftWidth = rShare->x() - (p->x()-swh), rShare->height()));
								bitBlt( tmpFractPix, 0, 0, pix, 0, topHeight, leftWidth, rShare->height());

								if (stippleMenu){
									if (menuTranslucency == CustomTrans)
										stripePixmap(*tmpFractPix, useCustomMenuColor ? color : bgColor(), opacity * 10);
									else
										stripePixmap( *tmpFractPix, useCustomMenuColor ? color : bgColor() );
								}
								else {
									if (menuTranslucency == CustomTrans)
										KPixmapEffect::fade( *tmpFractPix, (  ( float ) opacity )  * 0.1, useCustomMenuColor ? color : bgColor() );
									else
										KPixmapEffect::fade( *tmpFractPix, 0.9, useCustomMenuColor ? color : bgColor() );
								}
								icyApainter.drawPixmap(0, topHeight, *tmpFractPix);
							}

							icyApainter.end();
						}
						else{
							if (menuTranslucency == Gradient || secMenuDropShadows || MenuAnimation() == Effects::FadeIn)
								cleanPix = new KPixmap(*pix);
							if (menuTranslucency == Gradient){
								blendImg = blendPix->convertToImage();
								backImg  = pix->convertToImage();
								KImageEffect::blend(blendImg, backImg, (( float ) opacity )  * 0.1);
								pix->convertFromImage(backImg); // pix should now be blended
							}
							else if (stippleMenu){
								if (menuTranslucency == CustomTrans)
									stripePixmap(*pix, useCustomMenuColor ? color : bgColor(), opacity * 10);
								else
									stripePixmap( *pix, useCustomMenuColor ? color : bgColor() );
							}
							else {
								if (menuTranslucency == CustomTrans)
									KPixmapEffect::fade( *pix, (  ( float ) opacity )  * 0.1, useCustomMenuColor ? color : bgColor() );
								else
									KPixmapEffect::fade( *pix, 0.9, useCustomMenuColor ? color : bgColor() );
							}
						}
					}
					else{
						QRect deskR = QApplication::desktop() ->rect();
						if ( r.right() > deskR.right() && r.right() - deskR.right() < r.width()) r.setRight( deskR.right() );
						if ( r.left() < deskR.left() && deskR.left() - r.left() < r.width()){leftOffset = swh - (deskR.left()-r.left()) ;r.setLeft( deskR.left() );}
						if (r.bottom() > deskR.bottom() && r.bottom() - deskR.bottom() < r.height()) r.setBottom( deskR.bottom() );

						QApplication::syncX();
						*pix = QPixmap::grabWindow( qt_xrootwin(), r.x(), r.y(), r.width(), r.height() );
						if (menuTranslucency == Gradient || secMenuDropShadows || MenuAnimation() == Effects::FadeIn)
							cleanPix = new KPixmap(*pix);
						if (menuTranslucency == Gradient){
							blendPix = (KPixmap *)(new QPixmap(pix->width(), pix->height()));
							renderMenuBlendPixmap( blendPix, useCustomMenuColor ? color : bgColor(), p, leftOffset);
							blendImg = blendPix->convertToImage();
							backImg  = pix->convertToImage();
							KImageEffect::blend(blendImg, backImg, (( float ) opacity )  * 0.1);
							pix->convertFromImage(backImg); // pix should now be blended
						}
						else if (stippleMenu){
							if (menuTranslucency == CustomTrans)
								stripePixmap(*pix, useCustomMenuColor ? color : bgColor(), opacity * 10);
							else
								stripePixmap( *pix, useCustomMenuColor ? color : bgColor() );
						}
						else {
							if (menuTranslucency == CustomTrans)
								KPixmapEffect::fade( *pix, (  ( float ) opacity )  * 0.1, useCustomMenuColor ? color : bgColor() );
							else
								KPixmapEffect::fade( *pix, 0.9, useCustomMenuColor ? color : bgColor() );
						}
					}
				}
				if (menuTranslucency == Gradient || secMenuDropShadows || MenuAnimation() == Effects::FadeIn){
					newPopupStuff->cleanPix = cleanPix;
				}
				if (popupDict.count() == 499) {popupDict.setAutoDelete(true);popupDict.clear();currentPopupWinID=0;currentPopup = NULL;lastIndicatedMenuItemID = 0;}
				newPopupStuff->pix = pix;
				newPopupStuff->leftOffset = leftOffset;
				popupDict.insert( p->winId(), newPopupStuff );
				if (MenuAnimation() > None){
					bitBlt( &fadePix, 0, 0, pix, leftOffset, 0, fadePix.width(), fadePix.height());
					fadeWidget.setErasePixmap(fadePix);
					bitBlt( &fadeBackPix, 0, 0, cleanPix, leftOffset, 0, fadeBackPix.width(), fadeBackPix.height());
					if (MenuAnimation() == Effects::FadeIn){
						secMenuDropShadows ? 
						FadeEffect(&fadeWidget, &fadeBackPix, MenuAnimationSpeed(), this, p, newPopupStuff, swh ) :
						FadeEffect(&fadeWidget, &fadeBackPix, MenuAnimationSpeed());
					}
					else {
						secMenuDropShadows ? 
						ScrollEffect(&fadeWidget, &fadeBackPix, MenuAnimation(), MenuAnimationSpeed(), this, p, newPopupStuff, swh ):
						ScrollEffect(&fadeWidget, &fadeBackPix, MenuAnimation(), MenuAnimationSpeed());
					}
				}
				else if (secMenuDropShadows) createShadowWindows(p, newPopupStuff, swh);
			}
			//==============================================================================
			else{ // tear off menu
				pix = (KPixmap *)(new QPixmap(p->width(), p->height()));
				if (menuTranslucency == Gradient){
				renderMenuBlendPixmap( pix, useCustomMenuColor ? color : bgColor(), p, leftOffset);
				}
				else if (stippleMenu){
					pix->fill( Qt::black.rgb() );
					if (menuTranslucency == CustomTrans)
						stripePixmap(*pix, useCustomMenuColor ? color : bgColor(), opacity * 10);
					else
						stripePixmap( *pix, useCustomMenuColor ? color : bgColor() );
				}
				else {
					pix->fill( Qt::black.rgb() );
					if (menuTranslucency == CustomTrans)
						KPixmapEffect::fade( *pix, (  ( float ) opacity )  * 0.1, useCustomMenuColor ? color : bgColor() );
					else
						KPixmapEffect::fade( *pix, 0.9, useCustomMenuColor ? color : bgColor() );
				}
				if (popupDict.count() == 499) {popupDict.setAutoDelete(true);popupDict.clear();currentPopupWinID=0;currentPopup = NULL;lastIndicatedMenuItemID = 0;}
				newPopupStuff->pix = pix;
				newPopupStuff->leftOffset = 0;
				popupDict.insert( p->winId(), newPopupStuff );
			}
			//======================================================================================
		}
		else if (secMenuDropShadows && unblocked){ // solid with dropshadows (need buffering / offscreenbuffercleaning - sorry)
			QRect r( p->x()-swh, p->y(), p->width()+2*swh, p->height()+swh );
			cleanPix = new KPixmap;
			PopupStuff *oldPopupStuff = popupDict.find(lastPopupID);
			QRect deskR = QApplication::desktop() ->rect();
			leftOffset = swh;
			if ( r.right() > deskR.right()) r.setRight( deskR.right() );
			if ( r.left() < deskR.left()){leftOffset = swh - (deskR.left()-r.left()) ;r.setLeft( deskR.left() );}
			if (r.bottom() > deskR.bottom() ) r.setBottom( deskR.bottom() );
			QApplication::syncX();
			*cleanPix = QPixmap::grabWindow( qt_xrootwin(), r.x(), r.y(), r.width(), r.height());
			if (oldPopupStuff && oldPopupStuff->cleanPix){
				KPixmap *oldPix = oldPopupStuff->cleanPix;
				QRect *rShare = sharedRect(&r, &lastPopupRect );
				if (rShare){
					KPixmap *tmpFractPix = (KPixmap *)(new QPixmap(rShare->width(), rShare->height()));
					bitBlt( tmpFractPix, 0, 0, oldPix, rShare->x() - lastPopupRect.x(), rShare->y() - lastPopupRect.y(), rShare->width(), rShare->height());
					// first clean the new Pix
					QPainter icyApainter;
					icyApainter.begin( cleanPix );
					icyApainter.drawPixmap(rShare->x() - (p->x()-leftOffset),rShare->y() - p->y(),*tmpFractPix);
					icyApainter.end();
				}
			}
			// then store our new clean pixmap
			if (popupDict.count() == 499) {popupDict.setAutoDelete(true);popupDict.clear();currentPopup = NULL; lastIndicatedMenuItemID = 0;}
			newPopupStuff->cleanPix = cleanPix;
			newPopupStuff->leftOffset = leftOffset;
// 			if (menuTranslucency == SolidGradient) {
// 				newPopupStuff->pix = (KPixmap *)(new QPixmap(r.width(), r.height()));
// 				renderMenuBlendPixmap( newPopupStuff->pix, useCustomMenuColor ? color : bgColor(), p, leftOffset );
// 			}
			popupDict.insert( p->winId(), newPopupStuff );
			if (MenuAnimation() > None){
				fadeWidget.setEraseColor(UseCustomMenuColor() ? Color() : bgColor());
				bitBlt( &fadeBackPix, 0, 0, cleanPix, leftOffset, 0, fadeBackPix.width(), fadeBackPix.height());
				if (MenuAnimation() == Effects::FadeIn){
					secMenuDropShadows ? 
					FadeEffect(&fadeWidget, &fadeBackPix, MenuAnimationSpeed(), this, p, newPopupStuff, swh ) :
					FadeEffect(&fadeWidget, &fadeBackPix, MenuAnimationSpeed());
				}
				else {
					secMenuDropShadows ? 
					ScrollEffect(&fadeWidget, &fadeBackPix, MenuAnimation(), MenuAnimationSpeed(), this, p, newPopupStuff, swh ):
					ScrollEffect(&fadeWidget, &fadeBackPix, MenuAnimation(), MenuAnimationSpeed());
				}
			}
			else createShadowWindows(p, newPopupStuff, swh);
		}
		else if (MenuAnimation() > None && unblocked){
				QApplication::syncX();
				fadeWidget.setEraseColor(UseCustomMenuColor() ? Color() : bgColor());
				fadeBackPix = QPixmap::grabWindow( qt_xrootwin(), p->x(), p->y(), p->width(), p->height());
				if (MenuAnimation() == Effects::FadeIn){
					secMenuDropShadows ? 
					FadeEffect(&fadeWidget, &fadeBackPix, MenuAnimationSpeed(), this, p, newPopupStuff, swh ) :
					FadeEffect(&fadeWidget, &fadeBackPix, MenuAnimationSpeed());
				}
				else {
					secMenuDropShadows ? 
					ScrollEffect(&fadeWidget, &fadeBackPix, MenuAnimation(), MenuAnimationSpeed(), this, p, newPopupStuff, swh ):
					ScrollEffect(&fadeWidget, &fadeBackPix, MenuAnimation(), MenuAnimationSpeed());
				}
		}
		directFollower = false;
	}
	else if ( ev->type() == QEvent::Hide ) {
		if (!unblocked)
			unblocked = p->parent() && p->parent()->inherits("KPopupMenu") && !p->parent()->inherits("KPanelMenu");
		if ( (menuTranslucency >= DefaultTrans) || secMenuDropShadows) {
			menuLevelCounter--;
			lastPopupID = p->winId();
			QRect deskR = QApplication::desktop() ->rect();
			int tmp = p->x() - deskR.x();
			leftOffset = (tmp  > swh ? swh : tmp);
			lastPopupRect = QRect( p->x()-leftOffset, p->y(), p->width() + leftOffset+swh, p->height() + swh);
   			if (secMenuDropShadows) removeShadowWindows(p);
			if (menuLevelCounter == 0){
                            mouseOverMenu ? QTimer::singleShot( 200, this, SLOT(deletePopupDict()) ) : deletePopupDict();
                        }
		}
		directFollower = true;
	}
	else if ( ev->type() == QEvent::MouseButtonPress ){
		if (!unblocked) unblocked = true;
	}
	else if ( ev->type() == QEvent::ApplicationPaletteChange ) {
		if ( (menuTranslucency >= DefaultTrans)) {
			/*            QBrush brush(bgColor(), *bgPixmap());
			            QPalette pal = p->palette();
			            pal.setBrush(QColorGroup::Background, brush);
			            p->setPalette(pal);*/
			p->hide();
		}
		else if ( stippleMenu && (menuTranslucency == Solid) ) {
			prepareMenus();
			QBrush brush( bgColor(), *bgPixmap() );
			QPalette pal = p->palette();
			pal.setBrush( QColorGroup::Background, brush );
			p->setPalette( pal );
		}
		else if ( (menuTranslucency == Solid) && !stippleMenu ) {
			prepareMenus();
			QBrush brush( bgColor() );
			QPalette pal = p->palette();
			pal.setBrush( QColorGroup::Background, brush );
			p->setPalette( pal );
		}
	}
	return ( false );
}

/*returns congruent area of r1 and r2 - or NULL*/
QRect *OptionHandler::sharedRect(QRect *r1, QRect *r2){
	if (!(r1 && r2)) return NULL;
	QRect *r = new QRect;
	int x2,y2;
	(r1->x() >= r2->x()) ? r->setX(r1->x()) : r->setX(r2->x());
	(r1->y() >= r2->y()) ? r->setY(r1->y()) : r->setY(r2->y());
	(r1->y() + r1->height() <= r2->y() + r2->height()) ? y2 = r1->y() + r1->height() : y2 = r2->y() + r2->height();
	if (y2 <= r->y())
		return NULL;
	else
		r->setHeight(y2 - r->y()); // first cause it'll probably happen more often (kicker!)
	(r1->x() + r1->width() <= r2->x() + r2->width()) ? x2 = r1->x() + r1->width() : x2 = r2->x() + r2->width();
	if (x2 <= r->x())
		return NULL;
	else
		r->setWidth(x2 - r->x());
	return r;
} 
