/* 
 	really sucking codes.. sorry..
	from psi ,  modified and cleand by fasthyun@magicn.com
	trayicon_x11.cpp - X11 trayicon (for use with KDE and GNOME)
	Copyright (C) 2003  Justin Karneges
	GNOME2 Notification Area support: Tomasz Sterna

 */

#include	<QApplication>	// *****should be First!!!
#include 	"global.h"		// Qps *qps;
#include 	"trayicon.h" 

#include	<QMouseEvent>
#include	<QDesktopWidget>
#include	<QPainter>
#include	<QToolTip>

#include	<QX11Info> 

#include	<X11/Xlib.h>
#include	<X11/Xutil.h>
#include	<X11/Xatom.h>

extern bool flag_session_start;
//----------------------------------------------------------------------------
// common stuff
//----------------------------------------------------------------------------
// for Gnome2 Notification Area
static XErrorHandler old_handler = 0;
static int dock_xerror = 0;
extern "C" int dock_xerrhandler(Display* dpy, XErrorEvent* err)
{
	dock_xerror = err->error_code;
	return old_handler(dpy, err);
}

static void trap_errors()
{
	dock_xerror = 0;
	old_handler = XSetErrorHandler(dock_xerrhandler);
}

static bool untrap_errors()
{
	XSetErrorHandler(old_handler);
	return (dock_xerror == 0);
        
}
unsigned char *windowName(Display *d, Window w)
{
	Atom ATOM_NET_WM_NAME =XInternAtom(d, "_NET_WM_NAME", True);
	Atom ATOM_WM_NAME =XInternAtom(d, "WM_NAME", False);
	Atom ATOM_UTF8_STRING = XInternAtom(d, "UTF8_STRING", True);
	Atom ATOM_STRING = XInternAtom(d, "STRING", True);

	{
		int ret_format;
		Atom ret_type;
		unsigned long ret_nitems, ret_bafter;
		
		if(ATOM_NET_WM_NAME != None && ATOM_UTF8_STRING != None)
		{
			printf("windowName() xxx\n");
			unsigned char *uwname=0;
			int status = XGetWindowProperty(d, w, ATOM_NET_WM_NAME, 0, 2048, False,
				ATOM_UTF8_STRING, &ret_type, &ret_format, &ret_nitems, &ret_bafter,
				&uwname);
			//if(status == Success && uwname)
			if(status == Success)
			{
				printf("_NET_WM_NAME(ATOM_UTF8_STRING)=\"%s\"\n",uwname);
				return uwname;
			}
		}
//		if(ATOM_WM_NAME != None && ATOM_STRING != None)
		if(ATOM_WM_NAME != None)
		{
			printf("windowName() xxx1\n");
			unsigned char *uwname=0;
			int status = XGetWindowProperty(d, w, ATOM_WM_NAME, 0, 2048, False,
				ATOM_STRING, &ret_type, &ret_format, &ret_nitems, &ret_bafter,
				&uwname);
			if(status == Success && uwname)
			{
				printf("WM_NAME(STRING)=\"%s\"\n",uwname);
				return uwname;
			}
		}
	}
	{
		char *wname=0;

		XFetchName(d,w,(char**)&wname);
		if(wname)
		{
			printf("wname=\"%s\"\n",wname);
		//	return(wname);
		}
	}
	return(NULL);
}


char *get_wm_name(Display *display, Window win/*sender winid*/) 
{
	char *wm_name = NULL;
	Atom  atom;

	/* Extract WM Name */	
	if((atom = XInternAtom(display, "_NET_WM_NAME", True)) != None) {
		unsigned char   *prop_return = NULL;
		unsigned long    nitems_return;
		unsigned long    bytes_after_return;
		Atom             type_return, type_utf8;
		int              format_return;

		if((XGetWindowProperty(display, win, atom, 0, 128, False, XA_STRING,
						&type_return, &format_return, &nitems_return,
						&bytes_after_return, &prop_return)) == Success) {
	
			//	printf (" 0000= %s\n",prop_return);
			if(type_return != None) {
				if(type_return == XA_STRING) 
				{
					wm_name = strdup((char *)prop_return);
				}
				else		
				{
					type_utf8 = XInternAtom(display, "UTF8_STRING", True);
					if(type_utf8 != None) {
						if(type_return == type_utf8) {
							if(prop_return)
								XFree(prop_return);
							prop_return = NULL;

							if((XGetWindowProperty(display, win, atom, 0, 128, False, type_utf8,
											&type_return, &format_return, &nitems_return,
											&bytes_after_return, &prop_return)) == Success) {

								if(format_return == 8)
									wm_name = strdup((char *)prop_return);

							}
						}
						else if(format_return == 8)
							wm_name = strdup((char *)prop_return);

					}
				}

			}

			if(prop_return)
				XFree(prop_return);
		}
	}

	return wm_name;
}

extern bool flag_xcompmgr;
//works
//char *get_atom_prop(Display *display, Window win,Atom atom) 
void check_Opacity(Display *display) 
{
	char *wm_name = NULL;
	Atom atom; 
	
	Window root=XDefaultRootWindow(display);
	//atom = XInternAtom(dsp, "_NET_WM_WINDOW_OPACITY", false);
	atom = XInternAtom(display, "_NET_SUPPORTED", false);
//	if(wid!=None)	printf("_NET_WM_WINDOW_OPACITY\n");

	unsigned char   *prop_return = NULL;
	unsigned long    nitems_return;
	unsigned long    bytes_after_return;
	Atom             type_return;
	Atom			 type_utf8,ATOM;
	int              format_return;
	//	 status = XGetWindowProperty(dpy, target_win, atom, 0, (max_len+3)/4,
	//		False, AnyPropertyType, &actual_type,&actual_format, &nitems, &bytes_after, &prop);
	if((XGetWindowProperty(display, root, atom /***/, 0, 128, False, AnyPropertyType,
					&type_return, &format_return, &nitems_return,
					&bytes_after_return, &prop_return)) == Success) {
		//printf (" 0000= %s\n",prop_return);
		type_utf8 = XInternAtom(display, "UTF8_STRING", True);
		//ATOM = XInternAtom(display, "ATOM", True);

		if(type_return != None) {
			if(type_return == XA_STRING) 
			{
				printf( " XA_STRING !!");
				wm_name = strdup((char *)prop_return);
			}
			else if(type_utf8!=None and type_return == type_utf8) 
			{
				printf( " UTF8 !!");
				/*
				{	if(prop_return)
							XFree(prop_return);
						prop_return = NULL;

						//	if(format_return == 8)
						//		wm_name = strdup((char *)prop_return);

						}
					}
					else if(format_return == 8)
						wm_name = strdup((char *)prop_return);
 
				} */

			}
			else if(type_return ==XA_ATOM)
			{
				//printf("XA_ATOM, n=%d\n",nitems_return);
				Atom	*atoms;
				atoms=(Atom *)prop_return;

				for(int i=0;i<nitems_return;i++)
				{
					char *r=XGetAtomName(display,atoms[i]);
					//if(r) printf("[%d] atom name=%s\n",i,r);
					if(strcmp(r,"_NET_WM_WINDOW_OPACITY")==0)
					{
						printf("found _NET_WM_WINDOW_OPACITY ! maybe COMPIZ.\n");
						flag_xcompmgr=true;
					}
				}
			}
			else{ 
			//	printf( " else type !! \n");
				char *r=XGetAtomName(display,type_return);
				if(r) 	printf("else type name=%s\n",r);
			}

		}

		if(prop_return)
			XFree(prop_return);
	}

//	return wm_name;
}

//works
void test_getPorp(Display *dpy,Window w)
{
		
   // ListProperties
	  Status state;
      int num_prop;
      Atom *list = XListProperties(dpy, w, &num_prop);
	  for(int i=0;i<num_prop;i++)
	  {
		char * name = XGetAtomName(dpy,list[i]);
		//printf("Atom:%s\n", name);
		XTextProperty text_prop;
		if(strstr(name,"WM_LOCALE")!=0) continue;
		if(strstr(name,"RESOURCE")!=0) continue;
		//Atom property;
		state=XGetTextProperty(dpy, w, &text_prop, list[i]);
		if(state!=0 and text_prop.nitems>0 )
		{
			int count;
			//char ***list_return;
			char **slist;
			state=XTextPropertyToStringList(&text_prop, &slist, &count);
			//printf("default=%s\t",XDefaultString());	
			if(state) 
			{

				printf("Atom:%s = ", name);
				for(int j=0;j<count;j++)
				{
						printf("%s	",slist[j]);
				}
				printf("\n");
				XFreeStringList (slist); // ***
			}
		}
	//	char *XDefaultString()
	  }

	  XFree(list);
}

void Show_All_Props (Display *dpy,Window target_win)
{
	Atom *atoms, atom;
	const char *name;
	int count, i;
	if (target_win != -1) {
		atoms = XListProperties(dpy, target_win, &count);
		for (i = 0; i < count; i++) {
			 name=XGetAtomName(dpy, atoms[i]);
			 if(name)
			 {
				if(strcmp(name,"ATOMs Name")==0)
				{
				//	printf("name =%s \n",name);
				//	get_atom_prop(dpy,target_win,atoms[i]);
				}
				if(strstr(name,"WINDOWMAKER")!=0)
				{
					printf("name =%s \n",name);
				}
				//printf("name =%s \n",name);
			 }
		}
	} 
}


//:WM_CLASS = groupLeader	WindowMaker	
int isWindowMaker()
{
	Window	target_win= QApplication::desktop()->winId(); // **** window_manager X_ID?
	Display	*dpy = QX11Info::display (); // get the display(X server)

	Atom *atoms, atom;
	const char *name;
	int count, i;
	if (target_win != -1) {
		atoms = XListProperties(dpy, target_win, &count);
		//state=XTextPropertyToStringList(&text_prop, &slist, &count);

		for (i = 0; i < count; i++) {
			 name=XGetAtomName(dpy, atoms[i]);
			 if(name)
			 {
				///printf("Atom name=%s \n",name);
				if(strstr(name,"WINDOWMAKER")!=0)
				{
					printf("Qps: Windowmaker Found !\n",name);
					return 1;
				}
			 }
		}
	} 
	return 0;
}


// 
static bool send_message(
	Display* dpy,	/* display */
	Window w,	/* sender (tray icon window) */
	long message,	/* message opcode */
	long data1,	/* message data 1 */
	long data2,	/* message data 2 */
	long data3	/* message data 3 */
//	long data3	/* message type*/
) {
	XEvent ev;

	memset(&ev, 0, sizeof(ev));
	ev.xclient.type = ClientMessage;
	ev.xclient.window = w;
	ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", False );
	ev.xclient.format = 32;
	ev.xclient.data.l[0] = CurrentTime;
	ev.xclient.data.l[1] = message;
	ev.xclient.data.l[2] = data1;
	ev.xclient.data.l[3] = data2;
	ev.xclient.data.l[4] = data3;

	trap_errors();
	XSendEvent(dpy, w /* rootwin ??? */ , False, NoEventMask, &ev);
	XSync(dpy, False);
	return untrap_errors();
}

#define SYSTEM_TRAY_REQUEST_DOCK    0
#define SYSTEM_TRAY_BEGIN_MESSAGE   1
#define SYSTEM_TRAY_CANCEL_MESSAGE  2


TrayIcon::TrayIcon( const QPixmap &icon, const QString &tooltip, 
		QMenu *popup, QWidget *parent, const char *name )
: QWidget(0 /* shoud be NULL!! */ ), pop(popup), pm(icon), tip(tooltip)
{
	systray_window=None;
	flag_show_tip=false;
	flag_systray_ready=false;
	inTray=false;
	isWMDock = false;

	setAttribute(Qt::WA_OpaquePaintEvent);  // no background paint  (why?)
	setMouseTracking(true);
	setMinimumSize(22,22);
	if ( !pm.width() || !pm.height() )
		pm = QPixmap( 45, 45 );

}

/*!
  Removes the icon from the system tray and frees all allocated resources.
*/
TrayIcon::~TrayIcon()
{
    	sysRemove();
}


/*!
  Sets the context menu to \a popup. The context menu will pop up when the
  user clicks the system tray entry with the right mouse button.
*/
void TrayIcon::setPopup( QMenu* popup )
{
		pop = popup;
}

/*!
  Returns the current popup menu.
*/
QMenu* TrayIcon::popup() const
{
    return pop;
}


QPixmap TrayIcon::icon() const
{
    return pm;
}



//----------------------------------------------------------------------------
// TrayIcon
//----------------------------------------------------------------------------
// DRAFT Code (by fasthyun@magicn.com) 
void TrayIcon::init_TrayIconFreeDesktop()
{
	Display *dsp =QX11Info::display (); // get the display(X server?)
	Screen *screen = XDefaultScreenOfDisplay(dsp); // get the screen
	int screen_id = XScreenNumberOfScreen(screen); // and it's number

	// tell X that we want to see ClientMessage and Deleted events, which
	// are picked up by QApplication::x11EventFilter
	Window window_manager = QApplication::desktop()->winId(); // **** Window_manager X_ID ?
	//printf("winId()=%X qps->winId()=%X WM=%X\n",winId(),qps->winId(),window_manager);
	XWindowAttributes attr;

	//--------------------------------


	XGetWindowAttributes(dsp, window_manager, &attr);
	// *** important : to get the event that systray start or window manager changer
	// StructureNotifyMask : reparent ,destroy events
	XSelectInput(dsp, window_manager, attr.your_event_mask | StructureNotifyMask); 

	///Show_All_Props(dsp,root_window);
	///windowName(dsp, winId());
	
	char buf[32];
	snprintf(buf, sizeof(buf), "_NET_SYSTEM_TRAY_S%d", screen_id);
	selection_atom = XInternAtom(dsp, buf, false);
	manager_atom = XInternAtom (dsp,"MANAGER", false); // make a atom for later
//	Atom orientation_atom = XInternAtom (xdisplay,"_NET_SYSTEM_TRAY_ORIENTATION",False);
/*
  	The X server can report PropertyNotify events to clients wanting information about property changes 
  	for a specified window.
	To receive PropertyNotify events, set the PropertyChangeMask bit in the event-mask attribute of 
	the window. The X server can report PropertyNotify events to clients wanting information about property 
	changes for a specified window.
*/
	// X server reply the owner of the "atom", Kicker, Gnome-panel window_id
	systray_window = XGetSelectionOwner(dsp, selection_atom); // return the winid has the _NET_SYSTEM_TRAY_S atom
	if ( systray_window != None )
		// *** important : get  systray's destroy and property events from systray_Window
		XSelectInput(dsp, systray_window, StructureNotifyMask);
		//XSelectInput(dsp, systray_window, StructureNotifyMask|PropertyChangeMask);
	XFlush(dsp); // ?

	if ( systray_window != None )
	{
		if(send_message(dsp, systray_window, SYSTEM_TRAY_REQUEST_DOCK, winId(), 0, 0))
			;//printf("send_message() ok !!\n");//
		else
		{
			printf("***** send_message() Fail !! when does this occurs ?\n");
			setSysTray(false);
			return;
		}

	}
	else
	{
		printf("Qps: NO SYSTEM_TRAY .. ok ! \n");
		setSysTray(false);
		return;
	}
	
	flag_systray_ready=true;
	setSysTray(true);

	// WM_LEADER
	/* DEL
	XWMHints 	*hints;
	hints = XAllocWMHints();
	hints->flags = WindowGroupHint	;//| IconPositionHint | IconWindowHint | StateHint;	
	hints->window_group = qps->winId();		// set the window hint
	hints->initial_state = WithdrawnState;	// initial state
	hints->icon_x = 0;
	hints->icon_y = 0;
	XSetWMHints(dsp, winId(), hints);     // set the window hints for WM to use.
	//XSetWMHints(dsp, qps->winId(), hints);     // set the window hints for WM to use.
	XFree(hints);
	*/

}

QWidget *dummy;
void TrayIcon::init_WindowMakerDock()
{
///	printf("TrayIcon::init_WindowMakerDock()\n");
	Display *dsp =QX11Info::display ();//Qt4 x11Display(); // get the display(X server?)
	Status	    stat;
	XClassHint	*classhint;
	XWMHints 	*hints;
	Window	window = None;
	Window	icon_window = None;

	//window = qps->winId();
	dummy=new QWidget(0); dummy->setGeometry(-100,100,10,10);	
	window = dummy->winId();
	icon_window = winId();
	//printf(" id =%X %X\n",window,icon_window);  // 1000001F 10000021
	
	/*	
	classhint = XAllocClassHint();
	if (classhint == NULL) {
		fprintf(stderr, " can't allocate memory for wm hints!\n");
		exit(1);
    	}
	classhint->res_class = "DockApp";
    classhint->res_name = "qpsdock";
    XSetClassHint(dsp, window, classhint);
    XFree(classhint);
	*/

	hints = XAllocWMHints();
	//hints = XGetWMHints(dsp, window);	
	//hints->flags = WindowGroupHint	| IconPositionHint | IconWindowHint | StateHint;	
	//hints->flags = WindowGroupHint| IconWindowHint | StateHint;	
	hints->flags = IconPositionHint | IconWindowHint | StateHint;	
	hints->window_group = window;		// set the window hint
	hints->initial_state = WithdrawnState;	// initial state
	hints->icon_window = icon_window;	// **** important ****
	hints->icon_x = 0;
	hints->icon_y = 0;
	XSetWMHints(dsp, window, hints);     // set the window hints for WM to use.
	XFree(hints);
//	XFlush(dsp);

//	qps->show();
//	dummy->hide(); // Dock not shown!
	dummy->show();
	isWMDock= true;
}

void TrayIcon::sysInstall()
{
	setSysTray(false);
	
	//test_xapp();	

	init_TrayIconFreeDesktop(); //check hasSysTray !

	if(hasSysTray()==false and isWindowMaker() )
	{
		setFixedSize(46,46); // setIconSize
		init_WindowMakerDock();
		setSysTray(true);
	}
}



void TrayIcon::sysRemove()
{
	//printf("Qps: sysRemove\n");
	systray_window=None;
	inTray=false;
	boolSysTray=isWMDock=false;
	hide();
}

/*!
  update systray icon  
  called by qps::refresh()
*/
void TrayIcon::setIcon( const QPixmap &pix )
{
	///printf("setIcon()\n");
	if(isVisible()==false) return;
       	// X Error:BadWindow (invalid Window parameter) 3,Major:20,minor:0 occur
	// QWidget::setWindowIcon(pix);  // why X Error ?  dont need!!
    pm = pix;
    update(); 
}

/*!
  \property TrayIcon::toolTip
  \brief the tooltip for the system tray entry

  On some systems, the tooltip's length is limited and will be truncated as necessary.
*/
void TrayIcon::setToolTip( const QString &tooltip )
{
	if(pop->isVisible()) 
		flag_show_tip=false;
	if(flag_show_tip)
		QToolTip::showText(tip_pos,tooltip);
	else
		QToolTip::hideText();
	tip=tooltip;
}

void TrayIcon::leaveEvent ( QEvent * )
{
	flag_show_tip=false;
}

void TrayIcon::mouseMoveEvent( QMouseEvent *e )
{
	//printf("move\n");
	//QToolTip::showText(QPoint(0,0),"" );
	//QToolTip::showText(e->globalPos(),tip );
	tip_pos=e->globalPos();
	flag_show_tip=true;
	QToolTip::showText(tip_pos,tip);
	e->accept();
}


//	Atom *XListProperties(display, w, num_prop_return)
//  status	XInternalConnectionNumbers
//  XQueryTree() return root,parent,child list
//	XGetWindowAttributes
//	XListProperites()
//
void TrayIcon::test_xapp()
{
	Display *dpy =QX11Info::display ();//Qt4 x11Display(); // get the display(X server?)
	WId id=QWidget::winId ();

      Window root,w,tw;
	  w=id;
	 
	// GetGeometry
      int x, y;
      unsigned width, height, border_width, depth;

      XGetGeometry(dpy, w, &root, &x, &y, &width, &height, &border_width, &depth);
	printf("root=%d [%d,%d,%d,%d] boder=%d,depth=%d\n",root,x,y,width,height,border_width,depth); 
      XGetGeometry(dpy, root, &tw, &x, &y, &width, &height, &border_width, &depth);
	printf("root=%d [%d,%d,%d,%d] boder=%d,depth=%d\n",root,x,y,width,height,border_width,depth); 
     
	 //test_getPorp(dpy,w);
	 // QueryTree
      Window parent;
      Window *children;
      unsigned nchildren;
      //Status success = XQueryTree(dpy, w, &root, &parent, &children, &nchildren);
      Status success = XQueryTree(dpy, root, &tw, &parent, &children, &nchildren);
	  for(int i=0;i<nchildren;i++)
	  {
		test_getPorp(dpy,children[i]);
	  }
      XFree(children);
   // GetWindowAttributes
      XWindowAttributes wa;
      success = XGetWindowAttributes(dpy, w, &wa);
}


//TESTing
void TrayIcon::X11trick()
{

	Display *dpy =QX11Info::display (); // get the display(X server?)
	Window rootwin=XDefaultRootWindow(dpy);

	Atom  type; 
	Atom  atom; 
	int   format;
	int   *data = NULL, result = -1;
	
	Window 			win = None;
	unsigned long 	items_read, items_left;
	unsigned long 	items_n;
	

	/* get _NET_WM_USER_TIME_WINDOW from self-WindowProperty
	 * which points to a window on which you can find the _NET_WM_USER_TIME property */
	atom = XInternAtom (dpy,"_NET_WM_USER_TIME_WINDOW", False );
	if (XGetWindowProperty(dpy, winId(), 
				atom,0L, 2L , False, /* return size, delete */
				XA_WINDOW ,			/* request type */
				&type, &format, 	/* real returned type, format */
				&items_n,		/* return items number  */
				&items_left,	/* left data byte */
				(unsigned char **) &data) != Success) 
	{
		printf("Qps: XGetWindowProperty fail\n"); 
		return;	
	
	}
	if ( items_n and (type == XA_WINDOW) && (format == 32) && (data)) {
			win = *data;
	}
	else 
	{
		// NO NET_WindowManager 
		// printf("No _NET_WM_USER_TIME_WINDOW \n"); 
		return;
	}

	atom = XInternAtom (dpy, "_NET_WM_USER_TIME", False );
//	if( atom==None ) 	printf("None \n"); 

	if (XGetWindowProperty(dpy, win,
				atom,0L, 2L, False /* delete */,
				XA_CARDINAL /* request type */, 
				&type, &format, 	/* real returned type, format */
				&items_n , &items_left,
				(unsigned char **) &data) != Success) 
	{
		// not NET_WindowManager 
		// printf("Not a _NET_WM \n"); 
		return;
	}
				
	if(items_n==0)
	{
		printf("  read 0 \n"); 
		return;
	}


	XEvent ev;
	memset(&ev, 0, sizeof(ev));
	ev.xclient.type = ClientMessage;
	ev.xclient.window = qps->winId();
	//ev.xclient.display =;	// (optional)
	ev.xclient.message_type = XInternAtom (dpy, "_NET_ACTIVE_WINDOW", False );
	ev.xclient.format = 32;
	ev.xclient.data.l[0] = 1; // application. pager is 2
	ev.xclient.data.l[1] = *data ; // tmestamp (required)
	ev.xclient.data.l[2] = winId(); // request id 
	ev.xclient.data.l[3] = 0;
	ev.xclient.data.l[4] = 0;
	XSendEvent(dpy,rootwin /* rootwin? */ , False,SubstructureRedirectMask, &ev);
	
	if(data)
		XFree(data);
}

void TrayIcon::mousePressEvent( QMouseEvent *e )
{
//test_xapp();
	// This is for X11, menus appear on mouse press
	// I'm not sure whether Mac should be here or below.. Somebody check?
	switch ( e->button() ) {
		case Qt::RightButton:
			if ( pop ) {
				pop->popup( e->globalPos() );
				e->accept();
			}
			break;
		case Qt::LeftButton:
		case Qt::MidButton:
			//emit clicked( e->globalPos(), e->button() );
			emit clicked( e->globalPos());
			X11trick();
	default:
			break;
	}
	e->ignore();
}

void TrayIcon::mouseReleaseEvent( QMouseEvent *e )
{
//	printf("mouseReleaseEvent\n"); 
	switch ( e->button() ) {
		case Qt::RightButton:
			if ( pop ) {
				// Necessary to make keyboard focus
				// and menu closing work on Windows.
				//	e->accept();
			}
			break;
		case Qt::LeftButton:
		case Qt::MidButton:
			//emit clicked( e->globalPos(), e->button() );
			//emit clicked( e->globalPos());
			break;
		default:
			break;
	}
	e->ignore();
}

void TrayIcon::mouseDoubleClickEvent( QMouseEvent *e )
{
	if ( e->button() == Qt::LeftButton )
		emit doubleClicked( e->globalPos() );
	e->accept();
}


// this will be called  before shown !!
void TrayIcon::paintEvent(QPaintEvent *)
{
	//printf("paintEvent()\n");
	QPainter p(this);
	int w,h;
	if(isVisible()==false) // ** important to prevent X11 Error !!
	{
	//	printf("paintEvent(): hidden\n");
		return; 
	}	
	w=width()/2 ;
	h=height()/2;
	p.drawPixmap(w - pm.width()/2, h - pm.height()/2, pm);
}

//for session logout ?? never called
void TrayIcon::closeEvent ( QCloseEvent * e )
{
	printf("TrayIcon::closeEvent()\n"); 
	e->accept(); 
}

// called after size changed
void TrayIcon::resizeEvent ( QResizeEvent *e ) 
{
	int w,h;
	//printf("TrayIcon::resizeEvent(): w=%d,h=%d\n",width(),height());
	//if(isVisible()==false) return;  // X11 error !!

	w=width();h=height();
	if (isWMDock) 
	{	
		///w=w-14;h=h-14;
	}
	qps->setIconSize(w,h);
}


bool TrayIcon::x11Event(XEvent *xev)
{
	switch(xev->type)
	{
		case ReparentNotify: 
			// printf("--- ReparentNotify\n"); // whos reparent? TrayIcon !
			// Description :
			//	after Notify(systray) new start ,then always reparent called 
			//	should be shown() after ReparentNotify!
			if(isWMDock){
				show();
				dummy->hide();
				//delete dummy; // segfault!
			}
			else
			{
				if(flag_systray_ready)
				{					
					///if(qps->isMinimized())	
					//	qps->hide();
					show();	// show qps's trayicon
				}
			}
			//return false; // event will be passed to Qt 
			return true;
			break;
		case UnmapNotify:   // hide event
			//hide();
			//return true;
			break; // dont hide
		case MapNotify: // show event
			////show();
			//return true;
			break; 
		case ClientMessage:
			// cant' receive any thing !!	
			break;
		case PropertyNotify: // if profperty changed ,, by XSelectInput()
		//	printf("*** PropertyNotify\n");
			break;
		case ResizeRequest:
		//	printf("*** ResizeRequest\n"); // Never recived !
			return false;
	}
	return false; // this event willpass to Qt 
	
	switch(xev->type)
	{
		case MapRequest: 
			printf("*** MapRequest\n");
			return true;
		case Expose:	// ???
			//printf("*** Expose\n");
			return false;
		case VisibilityNotify:
			printf("*** VisibilityNotify\n");
			return true;
		case NoExpose:
			printf("*** NoExposure\n");
			return true;
		case ResizeRequest:
			printf("*** ResizeRequest\n");
			return false;
		case SelectionNotify:
			printf("*** SelectionNotify\n");
			return true;
		case PropertyNotify:
			printf("*** PropertyNotify\n");
			break;
	
		default:
			;
		//	printf("X11=%d\n",(int)xev->type);

	}
	return false;
} 

void QPS_SHOW();

// DRAFT CODE
// from eggtrayicon.c  by fasthyun@magicn.com
// if a tray show up during qps running, then 
bool TrayIcon::checkNewTrayEvent ( XEvent *xev )
{
	static int count=0;
	//printf("checkNewTrayEvent\n");	
	if (xev->type == ClientMessage &&
		xev->xclient.message_type == manager_atom &&
		xev->xclient.data.l[1] == selection_atom)
	{
		sysRemove(); 
		sysInstall(); 
		printf("Qps: Notify(systray) New start \n",count++);
		return true;
	}
	else if (xev->xany.window == systray_window)
	{ 
		if (xev->xany.type == PropertyNotify ) //X property notify event.
		{	
			printf("Qps: systray_window PropertyNotify  \n"); // ????
		}	
		else
		if (xev->xany.type == DestroyNotify)
		{	
			QPS_SHOW();	//qps->showNormal();
			sysRemove();
			flag_systray_ready=false;  // *** important
			printf("Qps: Notify(systray) Destroyed \n");
		}
		//printf("Qps: systray_window events!!  \n"); // ????
		return false;
	}

	//Atom xembed_atom = XInternAtom( qt_xdisplay(), "_XEMBED", FALSE );
	//Atom xembed_atom = XInternAtom( dsp, "_XEMBED", FALSE );
	//Atom atom = XInternAtom (dsp, "_NET_SYSTEM_TRAY_OPCODE", False );

	/*
	// uninitialized ?  xev->xclient.message_type 
	if (xev->xclient.message_type == xembed_atom){
		printf("*** X11 ClientMessage (_XEMBED)\n");
		inTray = true; // false !! sometimes calld ..
	}
	else 
		if (xev->xclient.message_type == atom){
			printf("*** X11 ClientMessage (_NET_SYSTEM_TRAY_OPCODE)\n");
		}
	//else printf("*** X11 ClientMessage else %s\n",XGetAtomName(x11Display(),(Atom)xev->xclient.message_type));
	*/
	
	return false;	
}


