/*
 * windowmanager.hh
 * Copyright (C) 2000 Frank Hale
 * frankhale@yahoo.com
 * http://sapphire.sourceforge.net/
 *
 * Updated: 20 Jan 2002
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#ifndef _WINDOWMANAGER_HH_
#define _WINDOWMANAGER_HH_

#include "aewm.hh"

using namespace std;

class WindowManager
{
private:
	list<Client *> *clientList;
	list<Client *>::iterator it;

	Display *dpy;
	Window 	root;
	int 	screen;
	
	char* window_manager_name;
	
	string command_line;
	
	WindowMenu *windowmenu;
	IconMenu   *iconmenu;
	
	int window_count;
	
	int currentDesktop;
	int maxDesktops;

	int focusModel;

	bool blockFocusChange;

	// The currently focused client
	Client* focusedClient;

	// The number of clients - always on top clients
	int clientCount;
	
	// The screen max resolutions (x,y)
	int xres, yres;
	
	Window gnome_check_win;
	Window gnome_button_proxy_win;
	
	XFontStruct *font;
	GC invert_gc, string_gc, border_gc;
	
	XColor fg, bg, bd, fc;
	Cursor move_curs, resize_curs, arrow_curs;
	
	char 	*opt_display,
		*opt_font, 
		*opt_fc, 
		*opt_fg,
		*opt_fm, 
		*opt_bg, 
		*opt_bd, 
		*opt_tj,
		*opt_wm,
		*opt_es,
		*opt_newkey,
		*opt_new1, 
		*opt_new2;
		
	int	opt_bw;
	int 	opt_text_justify;
	bool 	wire_move;
	bool 	edge_snap;

	#ifdef SHAPE
		int shape, shape_event;
	#endif

	static KeySym AltKeys[];
	
	Window	extended_hints_win;
	
	// Maintains the master struts
	// Apps will add or subtract from
	// the master strut.
	Strut *master_strut;

	list<Strut *> *clientStruts;
	list<Strut *>::iterator struts_it;
	
	// Used to test for ctrl+alt+del and ctrl+alt+backspace
	bool end,control_l,control_r,alt_l,alt_r,del;
public: /* member variables */

	// ICCCM stuff
	Atom 	atom_wm_state, 
		atom_wm_change_state, 
		atom_wm_protos, 
		atom_wm_delete, 
		atom_wm_cmapwins, 
		atom_wm_takefocus;
	
	// Gnome stuff
	Atom 	atom_gnome_win_client_list,
	     	atom_gnome_win_state,
	     	atom_gnome_win_hints,
	     	atom_gnome_win_layer,
	     	atom_gnome_win_supporting_wm_check,
	     	atom_gnome_win_desktop_button_proxy,
	     	atom_gnome_win_workspace,
	     	atom_gnome_win_workspace_count,
	     	atom_gnome_win_protocols;
	
	// Extended WM Hints
	Atom	atom_extended_net_supported,
		atom_extended_net_client_list,
		atom_extended_net_client_list_stacking,
		atom_extended_net_number_of_desktops,
		atom_extended_net_desktop_geometry,
		atom_extended_net_desktop_viewport,
		atom_extended_net_current_desktop,
		//atom_extended_net_desktop_names,
		atom_extended_net_active_window,
		atom_extended_net_workarea,  
		atom_extended_net_supporting_wm_check,
		//atom_extended_net_virtual_roots,
		atom_extended_net_close_window,
		//atom_extended_net_wm_moveresize,
		atom_extended_net_wm_name,
		//atom_extended_net_wm_visible_name,
		//atom_extended_net_wm_icon_name,
		//atom_extended_net_wm_visible_icon_name,
		atom_extended_net_wm_desktop,
		//atom_extended_net_wm_window_type,
		//atom_extended_net_wm_window_type_desktop,
		//atom_extended_net_wm_window_type_dock,
		//atom_extended_net_wm_window_type_toolbar,
		//atom_extended_net_wm_window_type_menu,
		//atom_extended_net_wm_window_type_dialog,
		//atom_extended_net_wm_window_type_normal,
		atom_extended_net_wm_state,
		atom_extended_net_wm_state_modal,
		atom_extended_net_wm_state_sticky,
		atom_extended_net_wm_state_maximized_vert,
		atom_extended_net_wm_state_maximized_horz,
		atom_extended_net_wm_state_shaded,
		atom_extended_net_wm_state_skip_taskbar,
		atom_extended_net_wm_state_skip_pager,
		atom_extended_net_wm_strut;
		//atom_extended_net_wm_icon_geometry,
		//atom_extended_net_wm_icon,
		//atom_extended_net_wm_pid,
		//atom_extended_net_wm_handled_icons,
		//atom_extended_net_wm_ping;
	
	Atom net_wm_states[NET_WM_STATE_MAX_STATES];

	// Atom for motif hints
	Atom 	atom_mwm_hints;

public:

	WindowManager(int argc, char** argv);
	~WindowManager();

	void keyPressEvent(XEvent& ev);
	void buttonPressEvent(XEvent& ev, BaseMenu *mu, Client *c);
	void buttonReleaseEvent(XEvent& ev, BaseMenu *mu, Client *c);
	void configureRequestEvent(XEvent& ev, Client *c);
	void motionNotifyEvent(XEvent& ev, BaseMenu *mu, Client *c);
	void mapNotifyEvent(XEvent& ev, Client *c);
	void mapRequestEvent(XEvent& ev, Client *c);
	void unmapNotifyEvent(XEvent& ev, Client *c);
	void destroyNotifyEvent(XEvent& ev, Client *c);
	void enterNotifyEvent(XEvent& ev, BaseMenu *mu, Client *c);
	void leaveNotifyEvent(XEvent& ev, BaseMenu *mu);
	void focusInEvent(XEvent& ev, Client *c);
	void focusOutEvent(XEvent& ev, Client *c);
	void clientMessageEvent(XEvent& ev, Client *c);
	void colormapNotifyEvent(XEvent& ev, Client *c);
	void propertyNotifyEvent(XEvent& ev, Client *c);
	void exposeEvent(XEvent& ev, BaseMenu *mu, Client *c);
	void defaultEvent(XEvent& ev, Client *c);

	void focusNextWindowInStackingOrder();
	void unfocusAnyStrayClients();

	// Returns a number corresponding to the current focus model.
	int getFocusModel() const { return focusModel; }

	// Accepts a number corresponding to a new focus model.
	void setFocusModel(int new_fm);
	
	// Cleans up and exits the window manager.
	void quitNicely();

	// Restarts the windowmanager
	void restart();

	// Just incase some class may need to do something with the
	// client list.
	list<Client *> *getClientList() const { return clientList; }

	// Returns the window menu object
	WindowMenu* getWindowMenu() 	const { return windowmenu; }
	
	Window	getGnomeCheckWin()	const { return gnome_check_win; }
	
	// Icon menu functions
	IconMenu*   getIconMenu() 	const { return iconmenu; }
	void 	    updateIconMenu();
	void 	    addClientToIconMenu(Client *c);
	void	    removeClientFromIconMenu(Client *c);
	
	Display* getDisplay()  	const { return dpy; 		}
	Window 	 getRootWindow()const { return root; 		}
	int 	 getScreen() 	const { return screen; 		}
	
	XFontStruct* getFont() 	const { return font; 		}

	GC getInvertGC() 	const { return invert_gc; 	}
	GC getStringGC() 	const { return string_gc; 	}
	GC getBorderGC() 	const { return border_gc; 	}
	
	Cursor getMoveCursor() 	const { return move_curs;	}
	Cursor getResizeCursor()const { return resize_curs;	}
	Cursor getArrowCursor() const { return arrow_curs; 	}
	
	XColor getFGColor() 	const { return fg; 		}
	XColor getFCColor() 	const { return fc; 		}
	XColor getBGColor() 	const { return bg; 		}
	XColor getBDColor() 	const { return bd; 		}
	
	int getTextJustify()	const { return opt_text_justify; }
	
	int getXRes() 		const { return xres; }
	int getYRes() 		const { return yres; }
	
	bool getWireMove() 	const { return wire_move; }
	bool getEdgeSnap() 	const { return edge_snap; }
	
	int getCurrentDesktop() const { return currentDesktop; }
	int getMaxDesktops() 	const { return maxDesktops; }
	
	void setCurrentDesktop(int desk);
	void setMaxDesktops(int maxDesks) { maxDesktops=maxDesks; }
	
	#ifdef SHAPE
		int getShape() 		const { return shape; }
		int getShapeEvent() 	const { return shape_event; }
	#endif 
	
	//char* getOptFont() 	const { return opt_font; 	}
	//char* getOptFG() 	const { return opt_fg; 		}
	//char* getOptBG() 	const { return opt_bg; 		}
	//char* getOptNew1() 	const { return opt_new1; 	}
	//char* getOptNew2() 	const { return opt_new2; 	}
	//char* getOptNew3() 	const { return opt_new3; 	}
	int   getOptBW() 	const { return opt_bw; 		}
		
	void getMousePosition(int *x, int *y);

	void goToDesktop(int d);
	void restackOnTopWindows();

	// Gnome hint functions
	void setGnomeHint(Window w, int a, long value);
	int findGnomeDesktopHint(Window win);

	unsigned long getHint(Window w, int a);

	void grabKeys(Window w);
	void ungrabKeys(Window w);
	unsigned int NumLockMask;

	// Uses gnome and if net is defined then it will
	// also use the extended net hints to set the client
	// list.
	void updateClientList();

	// Extended Window Manager hints function prototypes
	void addStrut(Strut *new_strut);
	void removeStrut(Strut *rem_strut);
	Strut* getMasterStrut() const { return master_strut; }
	int sendExtendedHintMessage(Window w, Atom a, long mask, long int data[]);
	void setExtendedWMHint(Window w, int a, long value);
	void setExtendedWMHintString(Window w, int a, char* value);
	void setExtendedNetSupported();
	void setExtendedNetDesktopGeometry();
	void setExtendedNetDesktopViewport();
	void setExtendedNetActiveWindow(Window w);
	void setExtendedNetWorkArea();
	Status getExtendedWMHintString(Window w, int a, char** name);
	NetWMStates* getExtendedNetWMStates(Window win);
	void setExtendedNetWMState(Window win, bool modal, bool sticky, bool max_vert, bool max_horz, bool shaded, bool skip_taskbar, bool skip_pager);
	void *getExtendedNetPropertyData(Window win, Atom prop, Atom type, int *items);					
	int findExtendedDesktopHint(Window win);

	long getDesktopHint(Window win, int a);

	int shouldSkipThisWindow(Window w);

	Client* findClient(Window w);
		
	void focusFocusedClient();
	Client* getFocusedClient() const { return focusedClient; }
	void setFocusedClient(Client *c);
	void setFocusedClientUnderPointer();
	void unsetFocusedClient();

	// If a window unmaps and has transients lets unmap
	// them too!
	// 
	// true = hide | false = unhide
	void findTransientsToMapOrUnmap(Window win, bool hide);

	// If a window lowers and has transients lets lower
	// them too!
	// 
	// true = lower | false = raise
	void findTransientsToRaiseOrLower(Window win, bool low);

	// If a window unsticks and has transients lets unstick
	// them too!
	// 
	// true = stick | false = unstick
	void findTransientsToStickOrUnstick(Window win, bool stick);

private:

	void cleanup();

	void doEventLoop();

	void scanWins();
	void setupDisplay();
};

extern WindowManager *wm;

#endif


syntax highlighted by Code2HTML, v. 0.9.1