//-*-c++-*-
// -------------------------------------------
// RCS data:
// $Date: 2003/07/04 16:43:44 $
// $Revision: 1.4 $
// $Source: /cvsroot/miwm/miwm/miwm/miwm.h,v $
// $Id: miwm.h,v 1.4 2003/07/04 16:43:44 sgbeal Exp $
// $RCSfile: miwm.h,v $
// -------------------------------------------
// Copyright by Ben Paul Wise.
// -------------------------------------------
// 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
// (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA.
// -------------------------------------------

#ifndef MIWM_BASIC_H
#define MIWM_BASIC_H

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


#include        <iostream>
#include        <stdio.h>
#include        <stdlib.h>
#include        <signal.h>
#include        <errno.h>
#include        <assert.h>

#include        <unistd.h>
#include        <sys/types.h>
#include        <sys/wait.h>
#include       <sys/time.h> // try to get timeval struct and select function



#include	<X11/X.h>
#include	<X11/Xos.h>
#include	<X11/Xlib.h>
#include	<X11/Xutil.h>
#include <X11/xpm.h>

// dogdog
// experimental
#include "mlchckr.h"

#include "alpha.h"
#include "rng.h"
#include "nodes.h"

#include "miconfig.h"

#include "struct.h"
#include "client.h"



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

// classes
class WorkSpace;
class WindowManager;
extern WindowManager *theWM;


//  This should really have been in X.h --- if you select both ButtonPress
//  and ButtonRelease events, the server makes an automatic grab on the
//  pressed button for you. This is almost always exactly what you want.

#define ButtonMask (ButtonPressMask | ButtonReleaseMask)

// ----------------------------------------------
// these are the reference declarations of the variables,
// which should be available to all who include this header.
// ----------------------------------------------
//	miwm.c	
// extern Mode mode;
extern int start_x;
extern int start_y;
extern Display	*dpy;            // the display
extern int display_width;
extern int display_height;
extern Window	root;            // the root window
extern Window	popup;   // this is the one popup that gets resized for various things
extern GC gc;                       // root gc
extern GC gc_thin;              // like root gc, but thinner lines
extern GC menu_gc;
extern GC size_gc;
extern XFontStruct *font;
extern XFontStruct *popup_font;
extern Atom wm_state;
extern Atom wm_change_state;
extern Atom wm_protocols;
extern Atom wm_delete;
extern Atom wm_take_focus;
extern Atom wm_colormaps;

extern Bool shape;
extern int shape_event;
extern char *argv0;
extern void shell(int, int, int);
extern void sendConfigureNotify(Client *);
extern int titleHeight(void);


void menuButtonRelease(XEvent *ev);



extern Edge interacting_edge;
extern Client *getClient(Window);
extern Client *addClient(Window);
extern void adjustClientBorder(Client *, Edge, int *, int *, int *, int *);
extern void drawClientBorder(Client *, int);
extern void setactive(Client *, int, long);
extern void Client_SizeFeedback(void);
extern void size_expose(void);
extern void reshapeClientEdge(Client *, Edge);
extern void moveClient(Client*);
extern void setClientState(Client *, int);
extern void closeClient(Client *);
extern void removeClient(Client *);
extern void Client_FreeAll(void);
extern void Client_ColorMap(XEvent*);
extern int hidden(Client *);
extern int withdrawn(Client *);
extern int normal(Client *);
extern Client *current;
extern Client *clients;


extern Cursor root_cursor;
extern Cursor frame_cursor;
extern Cursor menu_cursor;
extern Cursor edgecursor(Edge edge);
extern void initCursor(void);


extern void dispatch(XEvent *);

extern int ignore_badwindow;
extern int ErrorHandler(Display *, XErrorEvent *);
extern void miAbort(char*);


extern void getWindowName(Client *);
extern void getNormalHints(Client *);
extern void withdraw(Client *);
extern void cmapfocus(Client *);
extern void getColormaps(Client *);
extern void getTransientFor(Client *);
extern void Terminate(int);

// WM operations
void toggleRaiseOnFocus();
void toggleTopLeft();
void toggleClientPreview();
void toggleTiling(); // switch auto-tiling on/off
void togglePixmaps(); // switch use of pixmaps on/off
void restartWM(); // kill the current WM process and launch a new one
void terminateWM(); //  just kill the current WM
void stepWSup();// cycle up through work spaces
void stepWS(int step);// cycle up or down through work spaces
void contractWS();// contract all clients into WS 0, unhiding all
void retileWS();  // try to neatly re-tile the current WS
void rotateClients(); // successively raise clients of the current workspace

// WM operations on the current Client
void toggleSticky(); // toggle Sticky on the current Client
void idCurrent(); // show some ID
void terminateCurrent(); // toggle Sticky on the current Client



extern int current_item;	/* Last known selected menu item. -1 if none. */
extern menuitem * currentMenu;

const char * choose_label(Client *);
extern void getMouse(int * pointerX, int * pointerY);
extern void hide(Client *);
extern void unhidec(Client *, int);
extern void updateMenu(Client *);
extern int whichMenuItem(int, int);
extern void menuhit(XButtonEvent *);      // for the hidden window menu
extern void wsmenuhit(XButtonEvent *);  // for the workspace menu
extern void unhide(int n, int map);
extern void exposeMenu(void);
extern void motionNotifyMenu(XEvent *);
extern void showPreview(int);
extern void stopPreview(int);

extern int shapeevent(XEvent *);
extern int servershapes(void);
extern int isshaped(Window);

extern const char *font_name;
extern const char *popup_font_name;
extern int border;
char * stringCopy(char *);
extern void getResources(void);

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

class WindowManager
{
public:
WindowManager();
~WindowManager();

   menuType whichMenu;
  Mode mode;

  void mainLoop();
  void setupWS();
  void addWorkSpace(const char* wsName);

  void changeWorkSpace(WorkSpace* ws1, WorkSpace* ws2);
  // extern int offWorkSpace;
  void sendClientToWorkSpace(Client* client, WorkSpace* ws2);
  void innerSendClienttoWS(Client* c, int visibleP);

  int followClientToWS;
  void circulateWindowsUp();

  void manageClient(Client *client, bool preexisting = false );
  void autoPlaceCoords(Client *c);
  void diagonalPlaceCoords(Client *c, int *autoX, int *autoY);
  void tilePlaceCoords(Client *c, int *autoX, int *autoY);
  int okPlacement(Client *c1, int x, int y, int w, int h);

  void scanWindowTree();
  void freeAllClients();
  void rotateWSClients();
  
  void focusOn(Client*);
  void unhideClient(Client *c);
  void hideClient(Client *c);
  void spawn(char *command);

  void drawClientBorder(Client* c, int activeP);
  void drawDeadlyBox(Client*);
  void drawTitle(Client*);
  void drawClientOutline(Client* c);
  int titleHeightc(Client* c);

  void backClient(Client*);
  void raiseClient(Client*);

  // deal with menus
  void clearMenu();
  void setHiddenClientMenu();
  void setShellCmdMenu();
  void setWSMenu();
  void setClientOpsMenu();
  void setWMOpsMenu();

  void doFullPreview(Client*);
  void undoFullPreview(Client*);

  GC gc_frame;
  XColor titleColor;
  XColor boxColor;
  XColor parentWindowColor;
  XColor activeBorderColor;
  XColor inactiveBorderColor;
  XColor rootCursorColor;
  XColor frameCursorColor;

   NodeList* allClients; // data of type Client*
   NodeList* hiddenClients; // data of type Client*

  int root_event_mask;
  int menu_event_mask;
  int moving_event_mask;
  int resizing_event_mask;
  RNG *wmRNG;

  struct timeval sleepval;

  Menu* menu;

  void positionFeedbackWindow();
  // moving clients
  void startMovingClient(XEvent *xe, Client* c);
  void motionNotifyMoving();
  void buttonReleaseMoving();
  void positionExpose();

  // resizing clients
  void startResizingClient(XButtonEvent *xbe, Client* c);
  void motionNotifyResizing();
  void buttonReleaseResizing();
  void sizeExpose();

  Edge whichEdge(Client*, int rx, int ry);

  // killing clients
  void startKillingClient(XButtonEvent *xbe, Client* c);
  void motionNotifyKilling();
  void buttonReleaseKilling();

  int mouseInDeadlyBox(Client*);

  WorkSpace* workSpace;     // the one we are using, and will return to when previews end

  WorkSpace **allWorkSpaces;
  int numWorkSpaces;
  int tileP; // should we tile clients?
  int opaqueMoveSize; // anything below this % of screen size is opaque-moved


  int offWorkSpace;
  int auto_x;
  int auto_y;
  int insideClientP(Client* c);
  void warpPointerToBorder(Client* c);


  int usePixmapsP; // 1 to use them, 0 to not.
  Pixmap popupBgd;
  Pixmap activeBgd;
  Pixmap inactiveBgd;

  // keep this. it is only a problem under Solaris
//   struct timeval sleepval;
  int previewCP; // should we preview clients?
  int protectTopLeft;
  int raiseOnFocusP;

protected:
  int previewWSP; // should we preview workspaces?
  WorkSpace* previewedWorkSpace;     // the one we are just previewing

private:

};


// -------------------------------------------
#endif
// -------------------------------------------
// end of miwm.h
// -------------------------------------------

