{
    This file is part of Chentrah,
    Copyright (C) 2004-2008 Anton Rzheshevski (chebmaster@mail.ru).

    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, see http://www.gnu.org/licenses/

 **********************************************************************

    This file contains the window manager class header.

 **********************************************************************}

{ NOTE: This class far outlived the initial design of the framework structure
    it was intended for, so it could look a bit weird.
  The OnXxx methods do only one thing: they compose Chentrah events by putting
    a series of values into the queue for the module to read.
}


Const
  MaxKey = 255;
  

// too lazy to correct all the old code, use macros instead.
{ $define WinW := MotherState.DisplayWidth }
{ $define WinH := MotherState.DisplayHeight }
{ $define f_IsFullscreen := MotherState.InFullScreenMode }
{ $define _WindowExists := MotherState.WindowExists }
{ $define f_Visible := MotherState.WindowVisible }
{ $define f_textinput := MotherState.TextInput }

type
  TWindowManager = class
  protected
//    _WindowExists: boolean;
    MxFpsCull, MyFpsCull: Longint;
    PreviousFpsCullTsc, PreviousCcToMTsc: qword;

   {$ifdef unix}
    {$ifdef darwin}
      //MacosX support was never finished :(
      context: pointer;
      event: EventRecord;
      //window:
    {$else}
      display: PDisplay;
      screen: integer;
      context: GLXContext;
      WindowHandle: GLXDrawable;
      Visual: PXVisualInfo;
      pnProtocols : array [0..1] of TAtom;
      nWMProtocols : TAtom;
      icon_hwcursor: TCursor;
      Icon: TPixMap;
      TabletManager: TXinputTabletManager;
    {$Endif}
   {$else}
    display: HDC;
    context : HGLRC;
    WindowHandle: HWND;
    icon_hwcursor : HCursor;
    pfd : TPIXELFORMATDESCRIPTOR;
    rect: TRect;
    ShowCursorCount: integer;
   {$endif}
    f_focus: boolean;
    f_cursortexture: glUint;
    CursorCreated,
    GLInitialized: boolean;
    f_HadMessages: boolean;
    f_LoseFocusFramesCount: integer;
    f_KeyState: array[0..MaxKey] of boolean;
    f_MouseX, f_MouseY: integer;
    f_PointerGrabbed,
    f_PointerVisible,
    f_prevUseHwCursor: boolean;
    minW, minH: integer;
    InitialWidth, InitialHeight: integer;
    HasFocus: Boolean;
    PointerBitmap: record
      Bitmap: array[0..31, 0..31, 0..3] of byte;
      Andmask, XorMask: array [0..31] of dword;
    end;
    PointerXHotSpot, PointerYHotSpot: integer;
    CombinedMx, CombinedMy, gcMx, gcMy, gcMxV, gcMyV, gcMxAcc, gcMyAcc : float;
    gcMxPrevi, gcMyPrevi: longint;
    rMxPrev, rMyPrev: longint;
    MouseIsGamepad: boolean;
    procedure CreateWindow;
    procedure InitGL;
    procedure CloseGL;
    procedure CloseWindow;
    function _readKeyState (i: integer): boolean;
    procedure _UploadPointer;
    procedure _CheckCursorMode;
    procedure _CreateGLcursor;
    procedure _DrawGLcursor;
    procedure _UploadGLcursor;
    function IsHotkey(scancode: integer; HK: array of integer): boolean;
    procedure AddRightThumbToMouseMovement(x, y: float);
    procedure EmulateMouseViaGamepad;
  public
    AnyKey: boolean;
    property Handle: {$ifdef unix}GLXDrawable{$else}HWND{$endif} read WindowHandle;
    property Focus: boolean read HasFocus;


 //   property InFullScreenMode: boolean read f_IsFullScreen;

	// set it when if your class expects text input instead.
	// look about the OnType method.
//    property TextInput: boolean read f_textinput write f_textinput;

    property RenderingContext: {$ifdef unix}
                                 {$ifdef darwin}
                                   pointer
                                 {$else}
                                   glXContext
                                 {$endif}
                               {$else}
                                 HGLRC
                               {$endif}
                                       read context;

    // return window client area dimensions
{    property DisplayWidth: integer read WinW;
    property DisplayHeight: integer read WinH;
}
    // tells if the key is held down at the moment.
    // always false for mouse wheel "keys" -4 and -5.
    property Pressed [index: integer]: boolean read _readKeyState;

    //Mouse cursor position, in window client area coordinates
    property MouseX: float read CombinedMx;//f_MouseX;
    property MouseY: float read CombinedMy;//f_MouseY;
    
    // does the window exist now?..
    // Check in OnDestroy to determine if it was destroyed prematurely.
//    property WindowExists: boolean read _WindowExists;
    
    // check to not draw when window is not visible.
//    property WindowVisible: boolean read f_Visible;

    Constructor Create; virtual;
    Destructor Destroy; override;

    // the work executer each frame: processing mesages, updating window size, etc.
    procedure OneCycle;

    // contains the main program cycle
    Procedure MainLoop;
    
    procedure GrabPointer;  //NOT IMPLEMENTED YET!
    procedure UngrabPointer;
    
    //must point to a 32x32 ABGR pixels array.
    //NIL causes to hide the pointer.
    procedure SetPointerImage(p: pointer; xhs, yhs: integer);

    // performs OpenGL's SwapBuffers for the main framebuffer, nothing more.
    procedure SwapBuffers;
    
    // it's called one per every system mouse movement message.
    // use MouseX and MouseY to obtain coordinates.
    procedure OnMouseMove;

    // mouse buttons are considered keys
    // mouse wheel is considered two keys than they receive only OnPress,
    //  and Pressed for them is always false.
    procedure OnPress(scancode: integer);
    procedure OnRelease(scancode: integer);
    
    // if the TextInput property is set to True, and the pressed keys
    // represent a valid character, then OnType will be called instead
    // of OnPress.
    procedure OnType(input: WideChar);

    procedure OnPen(x, y, pressure, reserved1, reserved2, reserved3: single);



    // Main cyclic method. Called repeatedly, unless there is anything else to do
    procedure OnIdle;
    
    procedure UpdateWindowSize;
  end;

  CWindowManager = class of TWindowManager;

var
  WindowManager: TWindowManager;


  

