/*
 *  WindowMaker window manager
 * 
 *  Copyright (c) 1997 Alfredo K. Kojima
 * 
 *  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 WMWINDOW_H_
#define WMWINDOW_H_

#include "wconfig.h"
#include "GNUstep.h"
#include "texture.h"
#include "button.h"
#include "menu.h"
#include "application.h"

/* not defined in my X11 headers */
#ifndef UrgencyHint
#define UrgencyHint (1L << 8)
#endif


#define BORDER_TOP	1
#define BORDER_BOTTOM	2
#define BORDER_LEFT	4
#define BORDER_RIGHT	8
#define BORDER_ALL	(1|2|4|8)


#define CLIENT_EVENTS (StructureNotifyMask | PropertyChangeMask\
	| EnterWindowMask | LeaveWindowMask | ColormapChangeMask \
	| FocusChangeMask)

typedef enum {
    WFM_PASSIVE, WFM_NO_INPUT, WFM_LOCALLY_ACTIVE, WFM_GLOBALLY_ACTIVE
} FocusMode;


/*
 * window attribute flags.
 */
typedef struct {
    /* OpenStep */
    unsigned int titlebar:1;	       /* draw titlebar? */
    unsigned int resizable:1;	       /* draw the bottom handle? */
    unsigned int closable:1;	       /* draw a close button? */
    unsigned int miniaturizable:1;     /* draw an iconify button? */
    
    unsigned int broken_close:1;       /* is the close button broken? */
    /* GNUstep */
    unsigned int client_resizebar:1;   /* resizebar controled by client */
    unsigned int menu_window:1;	       /* is a menu window */
    unsigned int icon_window:1;	       /* is an icon window */
    /* ours */
    unsigned int shadeable:1;
    unsigned int focusable:1;
    unsigned int omnipresent:1;
    unsigned int skip_window_list:1;
    unsigned int floating:1;	       /* make this a floating window */
    unsigned int ignore_keys:1;	       /* do not intercept wm kbd binds 
					* while window is focused */
    unsigned int ignore_mouse:1;       /* do not intercept mouse events
					* on client area while window
					* is focused */
    unsigned int ignore_hide_others:1;
    unsigned int not_application:1;    /* do not make app icon */
#if 0
    unsigned int start_withdrawn:1;
#endif
    unsigned int reserved:14;
} WWindowAttributes;


/* bit flags for the above window attributes */
#define WA_TITLEBAR  		(1<<0)
#define WA_RESIZABLE  		(1<<1)
#define WA_CLOSABLE  		(1<<2)
#define WA_MINIATURIZABLE  	(1<<3)
#define WA_BROKEN_CLOSE  	(1<<4)
#define WA_SHADEABLE  		(1<<5)
#define WA_FOCUSABLE  		(1<<6)
#define WA_OMNIPRESENT 	 	(1<<7)
#define WA_SKIP_WINDOW_LIST  	(1<<8)
#define WA_FLOATING  		(1<<9)
#define WA_IGNORE_KEYS 		(1<<10)
#define WA_IGNORE_MOUSE  	(1<<11)
#define WA_IGNORE_HIDE_OTHERS	(1<<12)
#define WA_NOT_APPLICATION	(1<<13)
#define WA_START_WITHDRAWN	(1<<14)
/*
 * Window manager protocols that both the client as we understand.
 */
typedef struct {
    unsigned int TAKE_FOCUS:1;
    unsigned int SAVE_YOURSELF:1;
    unsigned int DELETE_WINDOW:1;

    /* GNUstep specific */
    unsigned int MINIATURIZE_WINDOW:1;
#if 0
    unsigned int RESIZE_WINDOW:1;
#endif
} WProtocols;


/*
 * Stores client window information. Each client window has it's
 * structure created when it's being first mapped.
 */
typedef struct WWindow {
    struct WWindow *prev;	       /* window focus list */
    struct WWindow *next;

    WScreen *screen_ptr;	       /* pointer to the screen structure */
    WWindowAttributes window_flags;    /* window attribute flags */
    short window_level;
    short workspace;		       /* workspace that the window occupies */

    WCoreWindow *frame;		       /* the frame window */
    int frame_x, frame_y;	       /* position of the frame in root*/
    short top_width, bottom_width;     /* width of the borders */

    struct {
	int x, y;
	unsigned int width, height;    /* original geometry of the window */
    } old_geometry;		       /* (before things like maximize) */

    WCoreWindow *titlebar;	       /* the titlebar */
    WCoreWindow *resizebar;	       /* bottom resizebar */

    /* l_buttons[0] = miniaturize
     * r_buttons[0] = close */
    WButton *l_buttons[MAX_LBUTTONS];  /* array of buttons at left */
    WButton *r_buttons[MAX_RBUTTONS];  /* array of buttons at right */
    short l_button_no;		       /* number of buttons defined */
    short r_button_no;

    WTexData focused_texture_data;     /* private data for focused texture */
    WTexData pfocused_texture_data;    /* private data for pfocused texture */
    WTexData unfocused_texture_data;   /* private data for unfocused texture */
    WTexData resizebar_texture_data;   /* private data for resizebar texture */
    
    short resizebar_corner_width;
    /* client window info */
    short old_border_width;	       /* original border width of client_win*/
    Window client_win;		       /* the window we're managing */
    WObjDescriptor client_descriptor; /* dummy descriptor for client */
    struct {
	int x, y;		       /* position of *client* relative 
					* to root */
	unsigned int width, height;    /* size of the client window */
    } client;

    XSizeHints *normal_hints;	       /* WM_NORMAL_HINTS */
    XWMHints *wm_hints;		       /* WM_HINTS (optional) */
    char *wm_instance;		       /* instance of WM_CLASS */
    char *wm_class;    		       /* class of WM_CLASS */
    GNUstepWMAttributes *wm_gnustep_attr;/* GNUstep window attributes */
    
    char *title;		       /* window name (title) */
 
    int state;			       /* state as in ICCCM */
    
    Window transient_for;	       /* WM_TRANSIENT_FOR */
    Window group_id;		       /* the leader window of the group */
    Window client_leader;	       /* WM_CLIENT_LEADER */

    Window main_window;		       /* main window for the application */
      
    int cmap_window_no;
    Window *cmap_windows;
    
    /* protocols */
    WProtocols protocols;	       /* accepted WM_PROTOCOLS */
    
    FocusMode focus_mode;	       /* type of keyboard input focus */

    struct {
	/* state flags */
	unsigned int mapped:1;	
	unsigned int focused:1;
	unsigned int miniaturized:1;
	unsigned int hidden:1;
	unsigned int shaded:1;
	unsigned int maximized:1;

	unsigned int semi_focused:1;
	/* window type flags */
	unsigned int urgent:1;	       /* if wm_hints says this is urgent */
#ifdef SHAPE
	unsigned int shaped:1;
#endif
	
	/* info flags */
	unsigned int buttons_dont_fit:1;
	unsigned int rebuild_texture:1;/* the window was resized and 
					* gradients should be re-rendered */
	unsigned int needs_full_repaint:1;/* does a full repaint of the 
					   * window next time it's painted */
	unsigned int icon_moved:1;     /* icon for this window was moved
					* by the user */
	unsigned int ignore_next_unmap:1;
	unsigned int selected:1;       /* multiple window selection */
	unsigned int skip_next_animation:1;
	unsigned int internal_window:1;
    } flags;		/* state of the window */

    char *icon_file;		       /* ptr to file name of icon to use
					* NULL == use global default */
    char *icon_text;
    struct WIcon *icon;		       /* icon info for the window */
    int icon_x, icon_y;		       /* position of the icon */
} WWindow;


typedef struct WSavedState {
    int workspace;
    int shaded;
    int hidden;
} WSavedState;


void wWindowDestroy(WWindow *wwin);
WWindow *wWindowCreate();

#ifdef SHAPE
void wWindowSetShape(WWindow *wwin);
#endif

WWindow *wManageWindow(WScreen *scr, Window window);

void wUnmanageWindow(WWindow *wwin, int restore);

void wWindowPaint(WWindow *wwin, int side, int repaint);
void wWindowFocus(WWindow *wwin);
void wWindowUnfocus(WWindow *wwin);
void wWindowConstrainSize(WWindow *wwin, int *nwidth, int *nheight);
void wWindowConfigure(WWindow *wwin, int req_x, int req_y, 
		      int req_width, int req_height);
WWindow *wWindowFor(Window window);

void wWindowInitialize();

void wWindowConfigureBorders(WWindow *wwin);

void wWindowUpdateButtonImages(WWindow *wwin);

void wWindowSaveState(WWindow *wwin);

void wWindowChangeWorkspace(WWindow *wwin, int workspace);

#endif
