Browse Source

native OSX support

David Rose 17 years ago
parent
commit
6c81c213c1

+ 4 - 0
panda/src/tinydisplay/Sources.pp

@@ -1,6 +1,7 @@
 #define BUILD_DIRECTORY $[HAVE_TINYDISPLAY]
 #define BUILDING_DLL BUILDING_TINYDISPLAY
 
+#define OSX_SYS_FRAMEWORKS ApplicationServices Carbon CoreServices Cocoa  
 #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
                    dtoolutil:c dtoolbase:c dtool:m prc:c 
 
@@ -24,6 +25,9 @@
     tinyWinGraphicsWindow.h tinyWinGraphicsWindow.I tinyWinGraphicsWindow.cxx \
     tinyXGraphicsPipe.I tinyXGraphicsPipe.cxx tinyXGraphicsPipe.h \
     tinyXGraphicsWindow.h tinyXGraphicsWindow.I tinyXGraphicsWindow.cxx \
+    tinyOsxGraphicsPipe.I tinyOsxGraphicsPipe.cxx tinyOsxGraphicsPipe.h \
+    tinyOsxGraphicsWindow.h tinyOsxGraphicsWindow.I \
+    $[if $[IS_OSX],tinyOsxGraphicsWindow.mm,] \
     clip.cxx error.cxx \
     image_util.cxx init.cxx light.cxx \
     memory.cxx msghandling.cxx msghandling.h \

+ 30 - 0
panda/src/tinydisplay/config_tinydisplay.cxx

@@ -21,6 +21,8 @@
 #include "tinyXGraphicsWindow.h"
 #include "tinyWinGraphicsPipe.h"
 #include "tinyWinGraphicsWindow.h"
+#include "tinyOsxGraphicsPipe.h"
+#include "tinyOsxGraphicsWindow.h"
 #include "tinySDLGraphicsPipe.h"
 #include "tinySDLGraphicsWindow.h"
 #include "tinyGraphicsStateGuardian.h"
@@ -60,6 +62,26 @@ ConfigVariableInt x_wheel_down_button
           "mouse button number does the system report when the mouse wheel "
           "is rolled one notch down?"));
 
+ConfigVariableBool show_resize_box
+("show-resize-box", true,
+ PRC_DESC("When this variable is true, then resizable OSX Panda windows will "
+          "be rendered with a resize control in the lower-right corner.  "
+          "This is specially handled by Panda, since otherwise the 3-d "
+          "window would completely hide any resize control drawn by the "
+          "OS.  Set this variable false to allow this control to be hidden."));
+
+ConfigVariableBool osx_disable_event_loop
+("osx-disable-event-loop", false,
+ PRC_DESC("Set this true to disable the window event loop for the Panda "
+          "windows.  This makes sense only in a publish environment where "
+          "the window event loop is already handled by another part of the "
+          "app."));
+
+ConfigVariableInt osx_mouse_wheel_scale
+("osx-mouse-wheel-scale", 1,
+ PRC_DESC("Specify the number of units to spin the Mac mouse wheel to "
+          "represent a single wheel_up or wheel_down message."));
+
 ConfigVariableInt td_texture_ram
 ("td-texture-ram", -1,
  PRC_DESC("This specifies the maximum amount of RAM to devote to keeping "
@@ -122,6 +144,14 @@ init_libtinydisplay() {
   ps->set_system_tag("TinyGL", "native_window_system", "Win");
 #endif
 
+#ifdef IS_OSX
+  TinyOsxGraphicsPipe::init_type();
+  TinyOsxGraphicsWindow::init_type();
+  selection->add_pipe_type(TinyOsxGraphicsPipe::get_class_type(),
+                           TinyOsxGraphicsPipe::pipe_constructor);
+  ps->set_system_tag("TinyGL", "OSX", "OSX");
+#endif
+
 #ifdef HAVE_SDL
   TinySDLGraphicsPipe::init_type();
   TinySDLGraphicsWindow::init_type();

+ 4 - 0
panda/src/tinydisplay/config_tinydisplay.h

@@ -34,6 +34,10 @@ extern ConfigVariableBool x_error_abort;
 extern ConfigVariableInt x_wheel_up_button;
 extern ConfigVariableInt x_wheel_down_button;
 
+extern ConfigVariableBool show_resize_box;
+extern ConfigVariableBool osx_disable_event_loop;
+extern ConfigVariableInt osx_mouse_wheel_scale;
+
 extern ConfigVariableInt td_texture_ram;
 extern ConfigVariableBool td_ignore_mipmaps;
 extern ConfigVariableBool td_perspective_textures;

+ 5 - 0
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -434,6 +434,11 @@ end_frame(Thread *current_thread) {
 
   // Evict any textures that exceed our texture memory.
   _textures_lru.begin_epoch();
+
+  // Clear these pointers so we don't have floating pointers between
+  // frames.
+  _current_frame_buffer = NULL;
+  _c->zb = NULL;
 }
 
 

+ 18 - 0
panda/src/tinydisplay/tinyOsxGraphicsPipe.I

@@ -0,0 +1,18 @@
+// Filename: tinyOsxGraphicsPipe.I
+// Created by:  drose (12May08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+

+ 247 - 0
panda/src/tinydisplay/tinyOsxGraphicsPipe.cxx

@@ -0,0 +1,247 @@
+// Filename: tinyOsxGraphicsPipe.cxx
+// Created by:  drose (12May08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pandabase.h"
+
+#ifdef IS_OSX
+
+#include "tinyOsxGraphicsPipe.h"
+#include "config_tinydisplay.h"
+#include "tinyOsxGraphicsWindow.h"
+#include "pnmImage.h"
+
+TypeHandle TinyOsxGraphicsPipe::_type_handle;
+  
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsPipe::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+TinyOsxGraphicsPipe::
+TinyOsxGraphicsPipe() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsPipe::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+TinyOsxGraphicsPipe::
+~TinyOsxGraphicsPipe() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsPipe::get_interface_name
+//       Access: Published, Virtual
+//  Description: Returns the name of the rendering interface
+//               associated with this GraphicsPipe.  This is used to
+//               present to the user to allow him/her to choose
+//               between several possible GraphicsPipes available on a
+//               particular platform, so the name should be meaningful
+//               and unique for a given platform.
+////////////////////////////////////////////////////////////////////
+string TinyOsxGraphicsPipe::
+get_interface_name() const {
+  return "TinyGL Windows";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsPipe::pipe_constructor
+//       Access: Public, Static
+//  Description: This function is passed to the GraphicsPipeSelection
+//               object to allow the user to make a default
+//               TinyOsxGraphicsPipe.
+////////////////////////////////////////////////////////////////////
+PT(GraphicsPipe) TinyOsxGraphicsPipe::
+pipe_constructor() {
+  return new TinyOsxGraphicsPipe;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsPipe::create_cg_image
+//       Access: Public, Static
+//  Description: Creates a new Quartz bitmap image with the data in
+//               the indicated PNMImage.  The caller should eventually
+//               free this image via CGImageRelease.
+////////////////////////////////////////////////////////////////////
+CGImageRef TinyOsxGraphicsPipe::
+create_cg_image(const PNMImage &pnm_image) {
+  size_t width = pnm_image.get_x_size();
+  size_t height = pnm_image.get_y_size();
+
+#ifdef PGM_BIGGRAYS
+  size_t bytes_per_component = 2;
+#else
+  size_t bytes_per_component = 1;
+#endif
+  size_t bits_per_component = bytes_per_component * 8;
+  size_t num_components = pnm_image.get_num_channels();
+
+  size_t bits_per_pixel = num_components * bits_per_component;
+  size_t bytes_per_row = num_components * bytes_per_component * width;
+
+  size_t num_bytes = bytes_per_row * height;
+  bool has_alpha;
+  bool is_grayscale;
+
+  CFStringRef color_space_name = NULL;
+  switch (pnm_image.get_color_type()) {
+  case PNMImage::CT_grayscale:
+    color_space_name = kCGColorSpaceGenericGray;
+    has_alpha = false;
+    is_grayscale = true;
+    break;
+
+  case PNMImage::CT_two_channel:
+    color_space_name = kCGColorSpaceGenericGray;
+    has_alpha = true;
+    is_grayscale = true;
+    break;
+
+  case PNMImage::CT_color:
+    color_space_name = kCGColorSpaceGenericRGB;
+    has_alpha = false;
+    is_grayscale = false;
+    break;
+
+  case PNMImage::CT_four_channel:
+    color_space_name = kCGColorSpaceGenericRGB;
+    has_alpha = true;
+    is_grayscale = false;
+    break;
+
+  case PNMImage::CT_invalid:
+    // Shouldn't get here.
+    nassertr(false, NULL);
+    break;
+  }
+  nassertr(color_space_name != NULL, NULL);
+
+  CGColorSpaceRef color_space = CGColorSpaceCreateWithName(color_space_name);
+  nassertr(color_space != NULL, NULL);
+
+  CGBitmapInfo bitmap_info = 0;
+#ifdef PGM_BIGGRAYS
+  bitmap_info |= kCGBitmapByteOrder16Host;
+#endif
+  if (has_alpha) {
+    bitmap_info |= kCGImageAlphaLast;
+  }
+
+  // Now convert the pixel data to a format friendly to
+  // CGImageCreate().
+  char *char_array = (char *)PANDA_MALLOC_ARRAY(num_bytes);
+
+  xelval *dp = (xelval *)char_array;
+  for (size_t yi = 0; yi < height; ++yi) {
+    for (size_t xi = 0; xi < width; ++xi) {
+      if (is_grayscale) {
+        *dp++ = (xelval)(pnm_image.get_gray(xi, yi) * PGM_MAXMAXVAL);
+      } else {
+        *dp++ = (xelval)(pnm_image.get_red(xi, yi) * PGM_MAXMAXVAL);
+        *dp++ = (xelval)(pnm_image.get_green(xi, yi) * PGM_MAXMAXVAL);
+        *dp++ = (xelval)(pnm_image.get_blue(xi, yi) * PGM_MAXMAXVAL);
+      }
+      if (has_alpha) {
+        *dp++ = (xelval)(pnm_image.get_alpha(xi, yi) * PGM_MAXMAXVAL);
+      }
+    }
+  }
+  nassertr((void *)dp == (void *)(char_array + num_bytes), NULL);
+
+  CGDataProviderRef provider = 
+    CGDataProviderCreateWithData(NULL, char_array, num_bytes, release_data);
+  nassertr(provider != NULL, NULL);
+
+  CGImageRef image = CGImageCreate
+    (width, height, bits_per_component, bits_per_pixel, bytes_per_row,
+     color_space, bitmap_info, provider,
+     NULL, false, kCGRenderingIntentDefault);
+  nassertr(image != NULL, NULL);
+
+  CGColorSpaceRelease(color_space);
+  CGDataProviderRelease(provider);
+
+  return image;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsPipe::release_data
+//       Access: Private, Static
+//  Description: This callback is assigned to delete the data array
+//               allocated within create_cg_image().
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsPipe::
+release_data(void *info, const void *data, size_t size) {
+  char *char_array = (char *)data;
+  PANDA_FREE_ARRAY(char_array);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsPipe::make_output
+//       Access: Protected, Virtual
+//  Description: Creates a new window or buffer on the pipe, if possible.
+//               This routine is only called from GraphicsEngine::make_output.
+////////////////////////////////////////////////////////////////////
+PT(GraphicsOutput) TinyOsxGraphicsPipe::
+make_output(const string &name,
+            const FrameBufferProperties &fb_prop,
+            const WindowProperties &win_prop,
+            int flags,
+            GraphicsStateGuardian *gsg,
+            GraphicsOutput *host,
+            int retry,
+            bool &precertify) {
+  
+  if (!_is_valid) {
+    return NULL;
+  }
+
+  TinyGraphicsStateGuardian *tinygsg = 0;
+  if (gsg != 0) {
+    DCAST_INTO_R(tinygsg, gsg, NULL);
+  }
+
+  // First thing to try: a TinyOsxGraphicsWindow
+
+  if (retry == 0) {
+    if (((flags&BF_require_parasite)!=0)||
+        ((flags&BF_refuse_window)!=0)||
+        ((flags&BF_resizeable)!=0)||
+        ((flags&BF_size_track_host)!=0)||
+        ((flags&BF_rtt_cumulative)!=0)||
+        ((flags&BF_can_bind_color)!=0)||
+        ((flags&BF_can_bind_every)!=0)) {
+      return NULL;
+    }
+    if ((flags & BF_fb_props_optional)==0) {
+      if ((fb_prop.get_aux_rgba() > 0)||
+          (fb_prop.get_aux_hrgba() > 0)||
+          (fb_prop.get_aux_float() > 0)) {
+        return NULL;
+      }
+    }
+    return new TinyOsxGraphicsWindow(this, name, fb_prop, win_prop,
+                                     flags, gsg, host);
+  }
+  
+  // Nothing else left to try.
+  return NULL;
+}
+
+#endif  // IS_OSX

+ 85 - 0
panda/src/tinydisplay/tinyOsxGraphicsPipe.h

@@ -0,0 +1,85 @@
+// Filename: tinyOsxGraphicsPipe.h
+// Created by:  drose (12May08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef TINYOSXGRAPHICSPIPE_H
+#define TINYOSXGRAPHICSPIPE_H
+
+#include "pandabase.h"
+
+#ifdef IS_OSX
+
+// We have to include this early, before anyone includes
+// netinet/tcp.h, which will define TCP_NODELAY and other symbols and
+// confuse the Apply system headers.
+#include <Carbon/Carbon.h>
+
+#include "graphicsPipe.h"
+#include "tinyGraphicsStateGuardian.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : TinyOsxGraphicsPipe
+// Description : This graphics pipe represents the interface for
+//               creating TinyGL graphics windows on a Windows-based
+//               client.
+////////////////////////////////////////////////////////////////////
+class EXPCL_TINYDISPLAY TinyOsxGraphicsPipe : public GraphicsPipe {
+public:
+  TinyOsxGraphicsPipe();
+  virtual ~TinyOsxGraphicsPipe();
+
+  virtual string get_interface_name() const;
+  static PT(GraphicsPipe) pipe_constructor();
+
+  static CGImageRef create_cg_image(const PNMImage &pnm_image);
+
+private:
+  static void release_data(void *info, const void *data, size_t size);
+
+protected:
+  virtual PT(GraphicsOutput) make_output(const string &name,
+                                         const FrameBufferProperties &fb_prop,
+                                         const WindowProperties &win_prop,
+                                         int flags,
+                                         GraphicsStateGuardian *gsg,
+                                         GraphicsOutput *host,
+                                         int retry,
+                                         bool &precertify);
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    GraphicsPipe::init_type();
+    register_type(_type_handle, "TinyOsxGraphicsPipe",
+                  GraphicsPipe::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "tinyOsxGraphicsPipe.I"
+
+#endif  // IS_OSX
+
+#endif

+ 27 - 0
panda/src/tinydisplay/tinyOsxGraphicsWindow.I

@@ -0,0 +1,27 @@
+// Filename: tinyOsxGraphicsWindow.I
+// Created by:  drose (12May08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+
+inline void TinyOsxGraphicsWindow::SendKeyEvent( ButtonHandle  key, bool down)
+{
+    if(down)
+		_input_devices[0].button_down(key);
+	else
+		_input_devices[0].button_up(key);
+}

+ 155 - 0
panda/src/tinydisplay/tinyOsxGraphicsWindow.h

@@ -0,0 +1,155 @@
+// Filename: tinyOsxGraphicsWindow.h
+// Created by:  drose (12May08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef TINYOSXGRAPHICSWINDOW_H
+#define TINYOSXGRAPHICSWINDOW_H
+
+#include "pandabase.h"
+
+#ifdef IS_OSX
+
+#include <Carbon/Carbon.h>
+
+#include "graphicsWindow.h"
+#include "buttonHandle.h"
+#include "tinyGraphicsStateGuardian.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : TinyOsxGraphicsWindow
+// Description : Opens a window on OS X to display the TinyGL software
+//               rendering.
+////////////////////////////////////////////////////////////////////
+class TinyOsxGraphicsWindow : public GraphicsWindow {
+public:
+  TinyOsxGraphicsWindow(GraphicsPipe *pipe, 
+                        const string &name,
+                        const FrameBufferProperties &fb_prop,
+                        const WindowProperties &win_prop,
+                        int flags,
+                        GraphicsStateGuardian *gsg,
+                        GraphicsOutput *host);
+  virtual ~TinyOsxGraphicsWindow();
+
+  virtual bool move_pointer(int device, int x, int y);
+
+  virtual bool begin_frame(FrameMode mode, Thread *current_thread);
+  virtual void end_frame(FrameMode mode, Thread *current_thread);
+  virtual void begin_flip();
+  virtual void end_flip();
+  virtual void process_events();
+  
+  virtual bool do_reshape_request(int x_origin, int y_origin, bool has_origin,
+                                  int x_size, int y_size);
+  
+  virtual void mouse_mode_absolute();
+  virtual void mouse_mode_relative();
+
+  virtual void set_properties_now(WindowProperties &properties);
+
+private:
+  void   ReleaseSystemResources();
+  inline void SendKeyEvent( ButtonHandle  key, bool down);
+
+protected:
+  virtual void close_window();
+  virtual bool open_window();
+
+private:
+	
+  bool OSOpenWindow(WindowProperties &properties);
+
+    //
+    // a singleton .. for the events to find the right pipe to push the event into
+    //
+
+
+public: // do not call direct ..
+  OSStatus handleKeyInput (EventHandlerCallRef myHandler, EventRef event, Boolean keyDown);
+  OSStatus handleTextInput (EventHandlerCallRef myHandler, EventRef event);
+  OSStatus handleWindowMouseEvents (EventHandlerCallRef myHandler, EventRef event);
+  ButtonHandle OSX_TranslateKey( UInt32 key,  EventRef event );
+  static TinyOsxGraphicsWindow * GetCurrentOSxWindow (WindowRef hint);
+
+  void     HandleModifireDeleta(UInt32 modifiers);
+  void HandleButtonDelta(UInt32 new_buttons);
+  void     DoResize(void);
+
+  OSStatus event_handler(EventHandlerCallRef myHandler, EventRef event);
+
+  virtual void user_close_request();
+  void SystemCloseWindow();
+  void SystemSetWindowForground(bool forground);	
+  void SystemPointToLocalPoint(Point &qdGlobalPoint);
+  void LocalPointToSystemPoint(Point &qdLocalPoint);
+  bool set_icon_filename(const Filename &icon_filename);
+
+  void set_pointer_in_window(int x, int y);
+  void set_pointer_out_of_window();
+
+private:
+  void create_frame_buffer();
+
+private:
+  ZBuffer *_frame_buffer;
+
+private:
+  UInt32 _last_key_modifiers;
+  UInt32 _last_buttons;
+  WindowRef _osx_window;
+  bool _is_fullscreen;
+
+  CGImageRef _pending_icon;
+  CGImageRef _current_icon;
+  
+  int _ID;
+  static TinyOsxGraphicsWindow  *FullScreenWindow; 
+  
+  CFDictionaryRef _originalMode;
+
+  // True if _properties.get_cursor_hidden() is true.
+  bool _cursor_hidden;
+
+  // True if the cursor is actually hidden right now via system calls.
+  bool _display_hide_cursor;
+
+  SInt32 _wheel_delta;
+	 
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    GraphicsWindow::init_type();
+    register_type(_type_handle, "TinyOsxGraphicsWindow",
+                  GraphicsWindow::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "tinyOsxGraphicsWindow.I"
+
+#endif  // IS_OSX
+
+#endif
+

+ 1791 - 0
panda/src/tinydisplay/tinyOsxGraphicsWindow.mm

@@ -0,0 +1,1791 @@
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+#include <Carbon/Carbon.h>
+#include <Cocoa/Cocoa.h>
+
+#include "tinyOsxGraphicsWindow.h"
+#include "config_tinydisplay.h"
+#include "tinyOsxGraphicsPipe.h"
+#include "pStatTimer.h"
+#include "keyboardButton.h"
+#include "mouseButton.h"
+#include "tinyGraphicsStateGuardian.h"
+#include "throw_event.h"
+#include "pnmImage.h"
+#include "virtualFileSystem.h"
+#include "config_util.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#include "pmutex.h"
+//#include "mutexHolder.h"
+
+////////////////////////////////////
+
+\
+Mutex &  OSXGloablMutex()
+{
+    static   Mutex  m("OSXWIN_Mutex");
+	return m;
+}
+
+
+struct work1
+{
+	volatile bool work_done;
+};
+
+#define PANDA_CREATE_WINDOW  101
+static void Post_Event_Wiait(unsigned short type, unsigned int data1 , unsigned int data2 , int target_window )
+{
+	work1 w;
+	w.work_done = false;
+	NSEvent *ev = [NSEvent otherEventWithType:NSApplicationDefined 
+									 location:NSZeroPoint 
+								modifierFlags:0 
+									timestamp:0.0f 
+								 windowNumber:target_window 
+									  context:nil 
+									  subtype:type
+										data1:data1
+										data2:(int)&w]; 
+	
+	[NSApp postEvent:ev atStart:NO];
+	while(!w.work_done)
+	    usleep(10);
+	
+}
+
+
+
+////////////////////////// Global Objects .....
+
+TypeHandle TinyOsxGraphicsWindow::_type_handle;
+TinyOsxGraphicsWindow  * TinyOsxGraphicsWindow::FullScreenWindow = NULL;
+
+
+#define USER_CONTAINER
+
+#include <set>
+
+#ifdef USER_CONTAINER
+
+std::set< WindowRef >     MyWindows;
+void AddAWindow( WindowRef window)
+{
+     MyWindows.insert(window);
+}
+bool checkmywindow(WindowRef window)
+{
+   return MyWindows.find(window) != MyWindows.end();
+}
+#else
+
+void AddAWindow( WindowRef window)
+{
+}
+
+bool checkmywindow(WindowRef window)
+{
+    return true;
+}
+
+#endif
+
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: GetCurrentOSxWindow
+//       Access: Static,
+//  Description: How to find the active window for events  on osx..
+//
+////////////////////////////////////////////////////////////////////
+TinyOsxGraphicsWindow* TinyOsxGraphicsWindow::GetCurrentOSxWindow(WindowRef window)
+{
+	if(FullScreenWindow != NULL)
+	   return FullScreenWindow;
+
+	if (NULL == window)  // HID use this path
+	{
+		//	Assume first we are a child window. If we cant find a window of that class, then we
+		//	are standalone and can jsut grab the front window.
+		window	=	GetFrontWindowOfClass(kSimpleWindowClass, TRUE);
+		if (NULL == window)
+			window	=	FrontNonFloatingWindow();
+	}
+		
+	if (window  && checkmywindow(window))
+	//if (window )
+	{
+		return (TinyOsxGraphicsWindow *)GetWRefCon (window);
+	}
+	else
+		return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::event_handler
+//       Access: Public
+//  Description: The standard window event handler for non-fullscreen
+//               windows.
+////////////////////////////////////////////////////////////////////
+OSStatus TinyOsxGraphicsWindow::event_handler(EventHandlerCallRef myHandler, EventRef event)
+{
+
+	OSStatus result = eventNotHandledErr;
+	UInt32 the_class = GetEventClass(event);
+	UInt32 kind = GetEventKind(event);
+
+	WindowRef window = NULL;
+	GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window);
+
+	if (tinydisplay_cat.is_spam())
+	{
+		tinydisplay_cat.spam() << ClockObject::get_global_clock()->get_real_time() << " event_handler: " << (void *)this << ", " << window << ", " << the_class << ", " << kind << "\n";
+	}
+
+  switch (the_class)
+  {
+	  case kEventClassMouse:
+		result  = handleWindowMouseEvents (myHandler, event);
+		break;
+		
+	  case kEventClassWindow:	
+		switch (kind) {
+		case kEventWindowCollapsing:
+		  /*
+		  Rect r;
+		  GetWindowPortBounds (window, &r);					
+		  CompositeGLBufferIntoWindow( get_context(), &r, GetWindowPort (window));
+		  UpdateCollapsedWindowDockTile (window);
+		  */
+		  SystemSetWindowForground(false);
+		  break;
+		case kEventWindowActivated: // called on click activation and initially
+		  SystemSetWindowForground(true);
+		  DoResize();
+		  break;
+		case kEventWindowDeactivated:
+		  SystemSetWindowForground(false);
+		  break;
+		case kEventWindowClose: // called when window is being closed (close box)
+		  // This is a message from the window manager indicating that
+		  // the user has requested to close the window.
+		  user_close_request();
+		  result = noErr;
+		  break;
+		case kEventWindowShown: // called on initial show (not on un-minimize)
+		  if (window == FrontNonFloatingWindow ())
+			SetUserFocusWindow (window);
+		  break;
+		case kEventWindowBoundsChanged: // called for resize and moves (drag)
+		  DoResize();
+		  break;
+		case kEventWindowZoomed:
+		  break;
+		case kEventWindowCollapsed:
+		  {
+			WindowProperties properties;
+			properties.set_minimized(true);
+			system_changed_properties(properties);
+		  }
+		  break;
+		case kEventWindowExpanded:
+		  {
+			WindowProperties properties;
+			properties.set_minimized(false);
+			system_changed_properties(properties);
+		  }
+		  break;
+		}
+		break;
+  }
+
+  return result;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::user_close_request
+//       Access: Private
+//  Description: The user has requested to close the window, for
+//               instance with Cmd-W, or by clicking on the close
+//               button.
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::user_close_request()
+{
+  string close_request_event = get_close_request_event();
+  if (!close_request_event.empty())
+  {
+    // In this case, the app has indicated a desire to intercept the request and process it directly.
+    throw_event(close_request_event);
+  }    
+  else
+  {
+    // In this case, the default case, the app does not intend to service the request, so we do by closing the window.
+    close_window();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::SystemCloseWindow
+//       Access: private
+//  Description: The Windows is closed by a OS resource not by a internal request 
+//
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::SystemCloseWindow()
+{	
+	if (tinydisplay_cat.is_debug())	
+		tinydisplay_cat.debug() << "System Closing Window \n";
+	ReleaseSystemResources();	
+};
+
+////////////////////////////////////////////////////////////////////
+//     Function: windowEvtHndlr
+//       Access: file scope static
+//  Description: The C callback for Window Events ..
+//
+//  We only hook this up for non fullscreen window... so we only
+//  handle system window events..
+//        
+////////////////////////////////////////////////////////////////////
+static pascal OSStatus	windowEvtHndlr(EventHandlerCallRef myHandler, EventRef event, void *userData)
+{
+#pragma unused (userData)
+  
+//  volatile().lock();
+ 
+  WindowRef window = NULL;		
+  GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window);
+
+  if (window != NULL)
+  {
+    TinyOsxGraphicsWindow *osx_win = TinyOsxGraphicsWindow::GetCurrentOSxWindow(window);
+    if (osx_win != (TinyOsxGraphicsWindow *)NULL)
+	{
+        //OSXGloablMutex().release();
+      return osx_win->event_handler(myHandler, event);
+	}
+  }
+  
+  //OSXGloablMutex().release();
+  return eventNotHandledErr;
+}
+
+///////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::DoResize
+//       Access: 
+//  Description: The C callback for Window Events ..
+//
+//   We only hook this up for none fullscreen window... so we only handle system window events..
+//        
+////////////////////////////////////////////////////////////////////
+
+void     TinyOsxGraphicsWindow::DoResize(void)
+{
+	tinydisplay_cat.info() << "In Resize....." << _properties << "\n";
+
+    // only in window mode .. not full screen
+    if(_osx_window != NULL && !_is_fullscreen && _properties.has_size())
+    {
+        Rect				rectPort = {0,0,0,0};
+        CGRect 				viewRect = {{0.0f, 0.0f}, {0.0f, 0.0f}};
+
+        GetWindowPortBounds (_osx_window, &rectPort); 
+        viewRect.size.width = (float) (rectPort.right - rectPort.left);
+        viewRect.size.height = (float) (rectPort.bottom - rectPort.top);
+        // tell panda
+        WindowProperties properties;
+        properties.set_size((int)viewRect.size.width,(int)viewRect.size.height);
+        properties.set_origin((int) rectPort.left,(int)rectPort.top);
+        system_changed_properties(properties);
+        ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size());
+		
+		if (tinydisplay_cat.is_debug())	
+			tinydisplay_cat.debug() << " Resizing Window " << viewRect.size.width << " " << viewRect.size.height << "\n";
+
+    }						
+};
+
+///////////////////////////////////////////////////////////////////
+//     Function: appEvtHndlr
+//       Access: 
+//  Description: The C callback for APlication Events..
+//
+//    Hooked  once for application
+//        
+////////////////////////////////////////////////////////////////////
+
+static pascal OSStatus appEvtHndlr (EventHandlerCallRef myHandler, EventRef event, void* userData)
+{
+#pragma unused (myHandler)
+    OSStatus result = eventNotHandledErr;
+	{
+
+    //OSXGloablMutex().lock();
+
+    TinyOsxGraphicsWindow *osx_win = NULL;
+    WindowRef window = NULL;	
+    UInt32 the_class = GetEventClass (event);
+    UInt32 kind = GetEventKind (event);
+
+	GetEventParameter(event, kEventParamWindowRef, typeWindowRef, NULL, sizeof(WindowRef), NULL, (void*) &window);
+    osx_win = TinyOsxGraphicsWindow::GetCurrentOSxWindow(window);
+    if (osx_win == NULL)
+	{
+	    //OSXGloablMutex().release();
+	  return eventNotHandledErr;
+	  }
+
+	switch (the_class)
+	{
+        case kEventClassTextInput:
+			  if(kind == kEventTextInputUnicodeForKeyEvent)
+				osx_win->handleTextInput(myHandler, event);
+			  //result = noErr; 
+				//
+				// can not report handled .. the os will not sent the raw key strokes then 
+				//	if(osx_win->handleTextInput(myHandler, event) == noErr)
+				//	      result = noErr;
+			  break;
+		case kEventClassKeyboard:
+			{
+			switch (kind) {
+                case kEventRawKeyRepeat:
+				case kEventRawKeyDown:
+					result = osx_win->handleKeyInput  (myHandler, event, true);
+					break;
+				case kEventRawKeyUp:
+					result = osx_win->handleKeyInput  (myHandler, event, false);
+					break;
+				case kEventRawKeyModifiersChanged:
+					{
+						UInt32 newModifiers;
+						OSStatus error = GetEventParameter(event, kEventParamKeyModifiers,typeUInt32, NULL,sizeof(UInt32), NULL, &newModifiers);
+						if(error == noErr)			
+						{			   
+							osx_win->HandleModifireDeleta(newModifiers);
+							result = noErr; 	
+						  }
+					}
+					break;
+			   }
+			}
+			break;
+
+		case kEventClassMouse:
+                  // tinydisplay_cat.info() << "Mouse movement handled by Application handler\n";
+			//if(TinyOsxGraphicsWindow::FullScreenWindow != NULL)	
+				result = osx_win->handleWindowMouseEvents (myHandler, event);
+ 		    //result = noErr; 
+			break;
+	}
+	
+    //OSXGloablMutex().release();	
+	}
+		
+    return result;
+}
+
+///////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::handleTextInput
+//       Access: 
+//  Description:  Trap Unicode  Input.
+//
+//        
+////////////////////////////////////////////////////////////////////
+OSStatus TinyOsxGraphicsWindow::handleTextInput (EventHandlerCallRef myHandler, EventRef theTextEvent)
+{
+	UniChar      *text = NULL;
+	UInt32       actualSize = 0; 
+ 
+	OSStatus ret = GetEventParameter (theTextEvent, kEventParamTextInputSendText, typeUnicodeText, NULL, 0, &actualSize, NULL);
+	if(ret != noErr)
+	   return ret;
+ 
+	text = (UniChar*)NewPtr(actualSize);
+	if(text!= NULL)
+	{
+		ret = GetEventParameter (theTextEvent, kEventParamTextInputSendText,typeUnicodeText, NULL, actualSize, NULL, text);
+		if(ret != noErr)
+			return ret;
+
+		for(unsigned int x = 0; x < actualSize/sizeof(UniChar); ++x)
+			_input_devices[0].keystroke(text[x]);	
+		DisposePtr((char *)text);
+	}
+	
+	return ret;
+}
+///////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::ReleaseSystemResources
+//       Access: private..
+//  Description: Clean up the OS level messes..
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::ReleaseSystemResources()
+{
+  if (_is_fullscreen)
+  {
+    _is_fullscreen = false;
+    FullScreenWindow = NULL;
+    
+    if (_originalMode != NULL)
+      CGDisplaySwitchToMode( kCGDirectMainDisplay, _originalMode );
+
+    CGDisplayRelease( kCGDirectMainDisplay );
+    
+    _originalMode = NULL;
+  }
+
+  if(_osx_window != NULL)
+  {
+    SetWRefCon (_osx_window, (long int) NULL);
+    HideWindow (_osx_window);
+    DisposeWindow(_osx_window);
+    _osx_window = NULL;
+  }
+  
+  if (_pending_icon != NULL) {
+    CGImageRelease(_pending_icon);
+    _pending_icon = NULL;
+  }
+  if (_current_icon != NULL) {
+    cerr << "release current icon\n";
+    CGImageRelease(_current_icon);
+    _current_icon = NULL;
+  }
+
+  WindowProperties properties;
+  properties.set_foreground(false);
+  properties.set_open(false);
+  properties.set_cursor_filename(Filename());
+  system_changed_properties(properties);
+				
+  _is_fullscreen = false;	
+  _osx_window = NULL;
+}
+
+
+static int id_seed = 100;
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+TinyOsxGraphicsWindow::TinyOsxGraphicsWindow(GraphicsPipe *pipe, 
+                  						const string &name,
+                  						const FrameBufferProperties &fb_prop,
+                  						const WindowProperties &win_prop,
+                  						int flags,
+                  						GraphicsStateGuardian *gsg,
+                  						GraphicsOutput *host) :
+  GraphicsWindow(pipe, name, fb_prop, win_prop, flags, gsg, host),
+  _osx_window(NULL),
+  _is_fullscreen(false),
+  _pending_icon(NULL),
+  _current_icon(NULL),
+  _originalMode(NULL),
+  _ID(id_seed++)
+{
+  GraphicsWindowInputDevice device =
+    GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard/mouse");
+  _input_devices.push_back(device);
+  _input_devices[0].set_pointer_in_window(0, 0);
+  _last_key_modifiers = 0;
+  _last_buttons = 0;
+
+  _cursor_hidden = false;
+  _display_hide_cursor = false;
+  _wheel_delta = 0;
+  
+  if (tinydisplay_cat.is_debug())	
+    tinydisplay_cat.debug() << "TinyOsxGraphicsWindow::TinyOsxGraphicsWindow() -" <<_ID << "\n";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+TinyOsxGraphicsWindow::~TinyOsxGraphicsWindow()
+{
+  if (tinydisplay_cat.is_debug())	
+    tinydisplay_cat.debug() << "TinyOsxGraphicsWindow::~TinyOsxGraphicsWindow() -" <<_ID << "\n";
+
+  // Make sure the window callback won't come back to this
+  // (destructed) object any more.
+  if (_osx_window) {
+    SetWRefCon (_osx_window, (long) NULL);
+  }
+
+  ReleaseSystemResources();	
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::set_icon_filename
+//       Access: Private
+//  Description: Called internally to load up an icon file that should
+//               be applied to the window.  Returns true on success,
+//               false on failure.
+////////////////////////////////////////////////////////////////////
+bool TinyOsxGraphicsWindow::set_icon_filename(const Filename &icon_filename)
+{
+  VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+
+  Filename icon_pathname = icon_filename;
+  if (!vfs->resolve_filename(icon_pathname, model_path)) {
+    // The filename doesn't exist.
+    tinydisplay_cat.warning()
+      << "Could not find icon filename " << icon_filename << "\n";
+    return false;
+  }
+
+
+  PNMImage pnmimage;
+  if (!pnmimage.read(icon_pathname))
+  {
+    tinydisplay_cat.warning()
+      << "Could not read icon filename " << icon_pathname << "\n";
+    return false;
+  }
+
+  CGImageRef icon_image = TinyOsxGraphicsPipe::create_cg_image(pnmimage);
+  if (icon_image == NULL)
+  {
+    return false;
+  }
+
+  if (_pending_icon != NULL)
+  {
+    CGImageRelease(_pending_icon);
+    _pending_icon = NULL;
+  }
+  _pending_icon = icon_image;
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::set_pointer_in_window
+//       Access: Private
+//  Description: Indicates the mouse pointer is seen within the
+//               window.
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::
+set_pointer_in_window(int x, int y) 
+{
+  _input_devices[0].set_pointer_in_window(x, y);
+
+  if (_cursor_hidden != _display_hide_cursor) {
+    if (_cursor_hidden) {
+      CGDisplayHideCursor(kCGDirectMainDisplay); 
+      _display_hide_cursor = true;
+    } else { 
+      CGDisplayShowCursor(kCGDirectMainDisplay); 
+      _display_hide_cursor = false;
+    } 
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::set_pointer_out_of_window
+//       Access: Private
+//  Description: Indicates the mouse pointer is no longer within the
+//               window.
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::
+set_pointer_out_of_window() {
+  _input_devices[0].set_pointer_out_of_window();
+
+  if (_display_hide_cursor) {
+    CGDisplayShowCursor(kCGDirectMainDisplay); 
+    _display_hide_cursor = false;
+  }
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::begin_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               before beginning rendering for a given frame.  It
+//               should do whatever setup is required, and return true
+//               if the frame should be rendered, or false if it
+//               should be skipped.
+////////////////////////////////////////////////////////////////////
+bool TinyOsxGraphicsWindow::begin_frame(FrameMode mode, Thread *current_thread)
+{
+  PStatTimer timer(_make_current_pcollector);
+  
+  begin_frame_spam(mode);
+  if (_gsg == (GraphicsStateGuardian *)NULL || 
+      (_osx_window == NULL && !_is_fullscreen))
+  {
+    // not powered up .. just abort..
+    return false;
+  }
+ 
+  // Now is a good time to apply the icon change that may have
+  // recently been requested.  By this point, we should be able to get
+  // a handle to the dock context.
+  if (_pending_icon != NULL)
+  {
+    CGContextRef context = BeginCGContextForApplicationDockTile();
+    if (context != NULL)
+    {
+      SetApplicationDockTileImage(_pending_icon);
+      EndCGContextForApplicationDockTile(context); 
+
+      if (_current_icon != NULL)
+      {
+        CGImageRelease(_current_icon);
+        _current_icon = NULL;
+      }
+      _current_icon = _pending_icon;
+      _pending_icon = NULL;
+    }
+  }
+
+  TinyGraphicsStateGuardian *tinygsg;
+  DCAST_INTO_R(tinygsg, _gsg, false);
+
+  tinygsg->_current_frame_buffer = _frame_buffer;
+  tinygsg->reset_if_new();
+  
+  _gsg->set_current_properties(&get_fb_properties());
+  return _gsg->begin_frame(current_thread);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::end_frame
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after rendering is completed for a given frame.  It
+//               should do whatever finalization is required.
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::end_frame(FrameMode mode, Thread *current_thread) 
+{
+  end_frame_spam(mode);
+  
+  if(mode == FM_render )
+  {
+    nassertv(_gsg != (GraphicsStateGuardian *)NULL);
+
+        /*
+    if (!_properties.get_fixed_size() && 
+        !_properties.get_undecorated() && 
+        !_properties.get_fullscreen() &&
+        show_resize_box) {
+      // Draw a kludgey little resize box in the corner of the window,
+      // so the user knows he's supposed to be able to drag the window
+      // if he wants.
+      DisplayRegionPipelineReader dr_reader(_default_display_region, current_thread);
+      _gsg->prepare_display_region(&dr_reader, Lens::SC_mono);
+      DCAST(TinyGraphicsStateGuardian, _gsg)->draw_resize_box();
+    }
+        */
+  }
+
+  _gsg->end_frame(current_thread);
+
+  if (mode == FM_render) {
+    trigger_flip();
+    if (_one_shot) {
+      prepare_for_deletion();
+    }
+    clear_cube_map_selection();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::begin_flip
+//       Access: Public, Virtual
+//  Description: This function will be called within the draw thread
+//               after end_frame() has been called on all windows, to
+//               initiate the exchange of the front and back buffers.
+//
+//               This should instruct the window to prepare for the
+//               flip at the next video sync, but it should not wait.
+//
+//               We have the two separate functions, begin_flip() and
+//               end_flip(), to make it easier to flip all of the
+//               windows at the same time.
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::end_flip()
+{
+  //  cerr << " end_flip [" << _ID << "]\n";
+}
+
+void TinyOsxGraphicsWindow::begin_flip() 
+{
+  if (_osx_window == NULL) {
+    return;
+  }
+
+  QDErr err;
+
+  // blit rendered framebuffer into window backing store
+  long width  = _frame_buffer->xsize;
+  long height  = _frame_buffer->ysize;
+  
+  Rect src_rect = {0, 0, height, width};
+  Rect ddrc_rect = {0, 0, height, width};
+  
+  // create a GWorld containing our image
+  GWorldPtr pGWorld;
+  err = NewGWorldFromPtr(&pGWorld, k32BGRAPixelFormat, &src_rect, 0, 0, 0, 
+                         (char *)_frame_buffer->pbuf, _frame_buffer->linesize);
+  if (err != noErr) {
+    tinydisplay_cat.error()
+      << " error in NewGWorldFromPtr, called from begin_flip()\n";
+    return;
+  }
+
+  GrafPtr out_port = GetWindowPort(_osx_window);
+  GrafPtr portSave = NULL;
+  Boolean portChanged = QDSwapPort(out_port, &portSave);
+
+  {
+    static PStatCollector b2("Wait:Flip:Begin:CopyBits");
+    PStatTimer t2(b2);
+    CopyBits(GetPortBitMapForCopyBits(pGWorld), 
+             GetPortBitMapForCopyBits(out_port), 
+             &src_rect, &ddrc_rect, srcCopy, 0);
+  }
+  
+  if (portChanged) {
+    QDSwapPort(portSave, NULL);
+  }
+  
+  DisposeGWorld(pGWorld);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::close_window
+//       Access: Protected, Virtual
+//  Description: Closes the window right now.  Called from the window
+//               thread.
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::close_window()
+{
+  SystemCloseWindow();
+
+  WindowProperties properties;
+  properties.set_open(false);
+  system_changed_properties(properties);
+
+  ReleaseSystemResources();
+  _gsg.clear();
+  _active = false;
+  GraphicsWindow::close_window();
+}
+
+//////////////////////////////////////////////////////////
+// HACK ALLERT ************ Undocumented OSX calls...
+// I can not find any other way to get the mouse focus to a window in OSX..
+//
+//extern "C" {
+//	struct  CPSProcessSerNum
+//	{
+//		UInt32 lo;
+//		UInt32 hi;
+//	};
+///
+//extern OSErr CPSGetCurrentProcess(CPSProcessSerNum *psn);
+//extern OSErr CPSEnableForegroundOperation( struct CPSProcessSerNum *psn);
+//extern OSErr CPSSetProcessName ( struct CPSProcessSerNum *psn, char *processname);
+//extern OSErr CPSSetFrontProcess( struct CPSProcessSerNum *psn);
+//};
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::open_window
+//       Access: Protected, Virtual
+//  Description: Opens the window right now.  Called from the window
+//               thread.  Returns true if the window is successfully
+//               opened, or false if there was a problem.
+////////////////////////////////////////////////////////////////////
+bool TinyOsxGraphicsWindow::open_window()
+{
+  // GSG Creation/Initialization
+  TinyGraphicsStateGuardian *tinygsg;
+  if (_gsg == 0) {
+    // There is no old gsg.  Create a new one.
+    tinygsg = new TinyGraphicsStateGuardian(_pipe, NULL);
+    _gsg = tinygsg;
+  } else {
+    DCAST_INTO_R(tinygsg, _gsg, false);
+  }
+  
+  create_frame_buffer();
+  if (_frame_buffer == NULL) {
+    tinydisplay_cat.error()
+      << "Could not create frame buffer.\n";
+    return false;
+  }
+
+  tinygsg->_current_frame_buffer = _frame_buffer;
+  
+  tinygsg->reset_if_new();
+  if (!tinygsg->is_valid()) {
+    close_window();
+    return false;
+  }
+  
+  WindowProperties req_properties  = _properties;
+  //OSXGloablMutex().lock();
+  bool answer =  OSOpenWindow(req_properties);
+  //OSXGloablMutex().release();
+  return answer;
+}
+
+
+bool TinyOsxGraphicsWindow::OSOpenWindow(WindowProperties &req_properties)
+{
+	OSErr err = noErr;
+
+	if (_current_icon != NULL && _pending_icon == NULL)
+	{
+		// If we already have an icon specified, we'll need to reapply it
+		// when the window is succesfully created.
+		_pending_icon = _current_icon;
+		_current_icon = NULL;
+	}
+  
+  
+  
+	static bool GlobalInits = false;
+	if (!GlobalInits)
+	{
+		//
+		// one time aplication inits.. to get a window open from a standalone aplication..
+
+		EventHandlerRef	application_event_ref_ref1;
+		EventTypeSpec	list1[] =
+		{ 
+			//{ kEventClassCommand,  kEventProcessCommand },
+			//{ kEventClassCommand,  kEventCommandUpdateStatus },
+			{ kEventClassMouse, kEventMouseDown },// handle trackball functionality globaly because there is only a single user
+			{ kEventClassMouse, kEventMouseUp }, 
+			{ kEventClassMouse, kEventMouseMoved },
+			{ kEventClassMouse, kEventMouseDragged },
+			{ kEventClassMouse, kEventMouseWheelMoved } ,
+			{ kEventClassKeyboard, kEventRawKeyDown },
+			{ kEventClassKeyboard, kEventRawKeyUp } ,
+			{ kEventClassKeyboard, kEventRawKeyRepeat },
+			{ kEventClassKeyboard, kEventRawKeyModifiersChanged }	,
+			{ kEventClassTextInput,	kEventTextInputUnicodeForKeyEvent},				   
+		};
+
+		EventHandlerUPP	gEvtHandler = NewEventHandlerUPP(appEvtHndlr);
+		err = InstallApplicationEventHandler (gEvtHandler, GetEventTypeCount (list1) , list1, this, &application_event_ref_ref1 );
+		GlobalInits = true;
+
+		ProcessSerialNumber psn = { 0, kCurrentProcess };
+		TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+		SetFrontProcess(&psn);
+	}
+
+	if (req_properties.has_fullscreen() && req_properties.get_fullscreen())
+	{
+		tinydisplay_cat.info() << "Creating full screen\n";
+
+		// capture the main display
+		CGDisplayCapture( kCGDirectMainDisplay );
+		// if sized try and switch it..
+		if (req_properties.has_size())
+		{
+			_originalMode = CGDisplayCurrentMode( kCGDirectMainDisplay );	
+			CFDictionaryRef newMode = CGDisplayBestModeForParameters( kCGDirectMainDisplay, 32,  req_properties.get_x_size(), req_properties.get_y_size(), 0 );
+			if (newMode == NULL)
+			{
+				tinydisplay_cat.error()
+					<< "Invalid fullscreen size: " << req_properties.get_x_size()
+					<< ", " << req_properties.get_y_size()
+					<< "\n";
+			}
+			else
+			{
+				CGDisplaySwitchToMode( kCGDirectMainDisplay, newMode);
+
+				// Set our new window size according to the size we actually got.
+
+				SInt32 width, height;
+				CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(newMode, kCGDisplayWidth), kCFNumberSInt32Type, &width);
+				CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(newMode, kCGDisplayHeight), kCFNumberSInt32Type, &height);
+
+				_properties.set_size(width, height);
+			}
+		}
+
+		_properties.set_fullscreen(true);
+		_is_fullscreen	=true;	
+		FullScreenWindow = this;
+		req_properties.clear_fullscreen();
+	}
+	else
+	{
+		Rect r;
+		if (req_properties.has_origin())
+		{	
+			r.top = req_properties.get_y_origin();
+			r.left =req_properties.get_x_origin();
+		}
+		else
+		{
+			r.top = 50;
+			r.left = 10;
+		}
+      
+		if (req_properties.has_size())
+		{
+		  r.right = r.left + req_properties.get_x_size();
+		  r.bottom = r.top + req_properties.get_y_size();
+		}
+		else
+		{			
+		  r.right = r.left + 512;
+		  r.bottom = r.top + 512;
+		}
+    
+		if (req_properties.has_parent_window())
+		{
+			tinydisplay_cat.info() << "Creating child window\n";
+
+			CreateNewWindow(kSimpleWindowClass, kWindowNoAttributes, &r, &_osx_window);
+			AddAWindow(_osx_window);
+						
+			_properties.set_fixed_size(true);
+			tinydisplay_cat.info() << "Child window created\n";
+		}
+		else
+		{
+			if (req_properties.has_undecorated() && req_properties.get_undecorated())
+			{ // create a unmovable .. no edge window..
+				
+				tinydisplay_cat.info() << "Creating undecorated window\n";
+				
+				CreateNewWindow(kDocumentWindowClass, kWindowStandardDocumentAttributes |  kWindowNoTitleBarAttribute, &r, &_osx_window);
+			}
+			else
+			{ // create a window with crome and sizing and sucj
+			  // In this case, we want to constrain the window to the
+			  // available size.
+				
+				Rect bounds;
+				GetAvailableWindowPositioningBounds(GetMainDevice(), &bounds);
+				
+				r.left = max(r.left, bounds.left);
+				r.right = min(r.right, bounds.right);
+				r.top = max(r.top, bounds.top);
+				r.bottom = min(r.bottom, bounds.bottom);
+				
+				tinydisplay_cat.info() << "Creating standard window\n";
+				CreateNewWindow(kDocumentWindowClass, kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute, &r, &_osx_window);
+  			    AddAWindow(_osx_window);
+			}
+		}
+
+    
+		if (_osx_window)
+		{
+		
+			EventHandlerUPP gWinEvtHandler;			// window event handler
+			EventTypeSpec list[] =
+			{ 
+				{ kEventClassWindow, kEventWindowCollapsing },
+				{ kEventClassWindow, kEventWindowShown },
+				{ kEventClassWindow, kEventWindowActivated },
+				{ kEventClassWindow, kEventWindowDeactivated },
+				{ kEventClassWindow, kEventWindowClose },
+				{ kEventClassWindow, kEventWindowBoundsChanged },
+
+				{ kEventClassWindow, kEventWindowCollapsed },
+				{ kEventClassWindow, kEventWindowExpanded },
+				{ kEventClassWindow, kEventWindowZoomed },
+				{ kEventClassWindow, kEventWindowClosed },
+			};
+
+			SetWRefCon (_osx_window, (long) this); // point to the window record in the ref con of the window
+			gWinEvtHandler = NewEventHandlerUPP(windowEvtHndlr); 
+			InstallWindowEventHandler(_osx_window, gWinEvtHandler, GetEventTypeCount(list), list, (void*)this, NULL); // add event handler
+			
+            if(!req_properties.has_parent_window())
+			{
+			    ShowWindow (_osx_window);
+			}
+			else
+			{
+			    
+				NSWindow*	parentWindow		=	(NSWindow *)req_properties.get_parent_window();
+			//	NSView*		aView				=	[[parentWindow contentView] viewWithTag:378];
+			//	NSRect		aRect				=	[aView frame];
+			//	NSPoint		origin				=	[parentWindow convertBaseToScreen:aRect.origin];
+						
+			//	NSWindow*	childWindow			=	[[NSWindow alloc] initWithWindowRef:_osx_window];
+			
+					
+				Post_Event_Wiait(PANDA_CREATE_WINDOW,(unsigned long) _osx_window,1,[parentWindow windowNumber]);			
+			
+			//	[childWindow setFrameOrigin:origin];
+			//	[childWindow setAcceptsMouseMovedEvents:YES];
+			//	[childWindow setBackgroundColor:[NSColor blackColor]];
+				 // this seems to block till the parent accepts the connection ?
+//				[parentWindow addChildWindow:childWindow ordered:NSWindowAbove];
+//				[childWindow orderFront:nil];
+				
+				
+				_properties.set_parent_window(req_properties.get_parent_window());
+				req_properties.clear_parent_window();
+				
+			}	
+
+			if (req_properties.has_fullscreen())
+			{
+			  _properties.set_fullscreen(false);		
+			  req_properties.clear_fullscreen();			
+			}
+
+			if (req_properties.has_undecorated())
+			{
+			  _properties.set_undecorated(req_properties.get_undecorated());
+			  req_properties.clear_undecorated();
+			}
+		}
+
+		// Now measure the size and placement of the window we
+		// actually ended up with.
+		Rect rectPort = {0,0,0,0};
+		GetWindowPortBounds (_osx_window, &rectPort); 	
+		_properties.set_size((int)(rectPort.right - rectPort.left),(int) (rectPort.bottom - rectPort.top));
+		req_properties.clear_size();
+		req_properties.clear_origin();
+  }
+
+	if (req_properties.has_icon_filename())
+		set_icon_filename(req_properties.get_icon_filename());
+
+	_properties.set_foreground(true);
+	_properties.set_minimized(false);
+	_properties.set_open(true);
+
+	if (_properties.has_size())
+		set_size_and_recalc(_properties.get_x_size(), _properties.get_y_size());
+ 
+  
+  return (err == noErr);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::process_events()
+//       Access: virtual, protected
+//  Description: Required Event upcall . Used to dispatch Window and Aplication Events 
+//               back into panda
+//               
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::process_events()
+{
+    GraphicsWindow::process_events();
+
+    if (!osx_disable_event_loop)
+    {
+      EventRef 		 theEvent;
+      EventTargetRef theTarget	=	GetEventDispatcherTarget();
+      
+      if (!_properties.has_parent_window())
+	  {
+          while  (ReceiveNextEvent(0, NULL, kEventDurationNoWait, true, &theEvent)== noErr)
+          {
+            SendEventToEventTarget (theEvent, theTarget);
+            ReleaseEvent(theEvent);
+          }
+	   }
+    }
+};
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::handleKeyInput()
+//       Access: virtual, protected
+//  Description: Required Event upcall . Used to dispatch Window and Aplication Events 
+//               back into panda
+//               
+////////////////////////////////////////////////////////////////////
+// key input handler
+OSStatus TinyOsxGraphicsWindow::handleKeyInput (EventHandlerCallRef myHandler, EventRef event, Boolean keyDown) {
+
+
+ if (tinydisplay_cat.is_debug()) {
+    UInt32 keyCode;
+    GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
+
+    tinydisplay_cat.debug()
+      << ClockObject::get_global_clock()->get_real_time() 
+      << " handleKeyInput: " << (void *)this << ", " << keyCode 
+      << ", " << (int)keyDown << "\n";
+  }
+  
+  //CallNextEventHandler(myHandler, event);
+
+  // We don't check the result of the above function.  In principle,
+  // this should return eventNotHandledErr if the key event is not
+  // handled by the OS, but in practice, testing this just seems to
+  // eat the Escape keypress meaninglessly.  Keypresses like F11 that
+  // are already mapped in the desktop seem to not even come into this
+  // function in the first place.
+  UInt32 newModifiers = 0;
+  OSStatus error = GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &newModifiers);
+  if(error == noErr)						   
+	HandleModifireDeleta(newModifiers);
+    
+  UInt32 keyCode;
+  GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
+  ButtonHandle button = OSX_TranslateKey(keyCode, event);
+
+  if (keyDown)
+  {
+    if ((newModifiers & cmdKey) != 0)
+    {
+      if (button == KeyboardButton::ascii_key("q") || button == KeyboardButton::ascii_key("w"))
+      {
+        // Command-Q or Command-W: quit the application or close the
+        // window, respectively.  For now, we treat them both the
+        // same: close the window.
+        user_close_request();
+      }
+    }
+    SendKeyEvent(button, true);
+  }
+  else
+  {
+    SendKeyEvent(button, false);
+  }
+  return   CallNextEventHandler(myHandler, event);
+//  return noErr;
+}
+
+ ////////////////////////////////////////////////////////////////////
+ //     Function: 
+ //       Access: 
+ //  Description: 
+ ////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::SystemSetWindowForground(bool forground)
+{
+	  WindowProperties properties;
+      properties.set_foreground(forground);
+	  system_changed_properties(properties);
+}		
+ 
+////////////////////////////////////////////////////////////////////
+//     Function: 
+//       Access: 
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::SystemPointToLocalPoint(Point &qdGlobalPoint)
+{
+    if(_osx_window != NULL)
+	{
+		GrafPtr savePort;
+		Boolean	portChanged	=	QDSwapPort(GetWindowPort(_osx_window), &savePort);
+
+		GlobalToLocal(&qdGlobalPoint);
+
+		if (portChanged)
+			QDSwapPort(savePort, NULL);
+	}			
+}
+	
+ ////////////////////////////////////////////////////////////////////
+ //     Function: 
+ //       Access: 
+ //  Description: 
+ ////////////////////////////////////////////////////////////////////
+
+ OSStatus TinyOsxGraphicsWindow::handleWindowMouseEvents (EventHandlerCallRef myHandler, EventRef event)
+ {
+     WindowRef			window = NULL;
+     OSStatus			result = eventNotHandledErr;
+     UInt32 				kind = GetEventKind (event);
+     EventMouseButton	button = 0;
+     Point qdGlobalPoint = {0, 0};
+     UInt32				modifiers = 0;	
+     Rect 				rectPort;
+     SInt32 this_wheel_delta;
+     EventMouseWheelAxis wheelAxis;
+
+//	 cerr <<" Start Mouse Event " << _ID << "\n";
+
+     // Mac OS X v10.1 and later
+     // should this be front window???
+     GetEventParameter(event, kEventParamWindowRef, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window);
+
+     if(!_is_fullscreen && (window == NULL || window != _osx_window )) {
+       if (kind == kEventMouseMoved)
+      {
+         set_pointer_out_of_window();
+       }
+       return eventNotHandledErr;
+     }
+
+
+	 
+     GetWindowPortBounds (window, &rectPort);
+
+    // result = CallNextEventHandler(myHandler, event);	
+    // if (eventNotHandledErr == result) 
+     { // only handle events not already handled (prevents wierd resize interaction)
+         switch (kind) {
+             // Whenever mouse button state changes, generate the
+             // appropriate Panda down/up events to represent the
+             // change.
+
+            case kEventMouseDown:
+            case kEventMouseUp:
+              {
+                GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
+                if (_properties.get_mouse_mode() == WindowProperties::M_relative)
+                {
+                  GetEventParameter(event, kEventParamMouseDelta,typeQDPoint, NULL, sizeof(Point),NULL	, (void*) &qdGlobalPoint);
+                  MouseData currMouse = get_pointer(0);
+                  qdGlobalPoint.h += currMouse.get_x();
+                  qdGlobalPoint.v += currMouse.get_y();
+                }
+                else
+                {
+                  GetEventParameter(event, kEventParamMouseLocation,typeQDPoint, NULL, sizeof(Point),NULL	, (void*) &qdGlobalPoint);                    
+                  SystemPointToLocalPoint(qdGlobalPoint);
+                }
+
+                set_pointer_in_window((int)qdGlobalPoint.h, (int)qdGlobalPoint.v);
+
+                UInt32 new_buttons = GetCurrentEventButtonState();
+                HandleButtonDelta(new_buttons);
+              }
+              result = noErr;
+              break;
+
+            case kEventMouseMoved:	
+            case kEventMouseDragged:
+                if(_properties.get_mouse_mode()==WindowProperties::M_relative)
+                {
+                  GetEventParameter(event, kEventParamMouseDelta,typeQDPoint, NULL, sizeof(Point),NULL	, (void*) &qdGlobalPoint);
+                  
+                  MouseData currMouse=get_pointer(0);
+                  qdGlobalPoint.h+=currMouse.get_x();
+                  qdGlobalPoint.v+=currMouse.get_y();
+                }
+                else
+                { 
+                  GetEventParameter(event, kEventParamMouseLocation,typeQDPoint, NULL, sizeof(Point),NULL	, (void*) &qdGlobalPoint);
+                  SystemPointToLocalPoint(qdGlobalPoint);
+                }
+                if (kind == kEventMouseMoved && 
+                    (qdGlobalPoint.h < 0 || qdGlobalPoint.v < 0)) {
+                  // Moving into the titlebar region.
+                  set_pointer_out_of_window();
+                } else {
+                  // Moving within the window itself (or dragging anywhere).
+                  set_pointer_in_window((int)qdGlobalPoint.h, (int)qdGlobalPoint.v);
+                }
+                result = noErr;
+
+                break;
+				
+            case kEventMouseWheelMoved: 
+                GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(this_wheel_delta), NULL, &this_wheel_delta);
+                GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(wheelAxis), NULL, &wheelAxis );
+                GetEventParameter(event, kEventParamMouseLocation,typeQDPoint, NULL, sizeof(Point),NULL	, (void*) &qdGlobalPoint);
+                SystemPointToLocalPoint(qdGlobalPoint);
+                
+                if (wheelAxis == kEventMouseWheelAxisY)
+                {
+                    set_pointer_in_window((int)qdGlobalPoint.h, (int)qdGlobalPoint.v);
+                    _wheel_delta += this_wheel_delta;
+                    SInt32 wheel_scale = osx_mouse_wheel_scale;
+                    while (_wheel_delta > wheel_scale) {
+                      _input_devices[0].button_down(MouseButton::wheel_up());
+                      _input_devices[0].button_up(MouseButton::wheel_up());
+                      _wheel_delta -= wheel_scale;
+                    }
+                    while (_wheel_delta < -wheel_scale) {
+                      _input_devices[0].button_down(MouseButton::wheel_down());
+                      _input_devices[0].button_up(MouseButton::wheel_down());
+                      _wheel_delta += wheel_scale;
+                    }
+                }
+                result = noErr;
+                break;               
+         }
+//         result = noErr;
+     }	
+	 
+
+     return result;
+ }
+
+ ////////////////////////////////////////////////////////////////////
+ //     Function: TinyOsxGraphicsWindow::OSX_TranslateKey
+ //       Access: Private
+ //  Description: MAC Key Codes to Panda Key Codes
+ ////////////////////////////////////////////////////////////////////
+ ButtonHandle TinyOsxGraphicsWindow::OSX_TranslateKey(UInt32 key, EventRef event)
+ {
+
+
+     ButtonHandle nk = ButtonHandle::none();
+     switch ( key )
+     {
+     case 0:    nk = KeyboardButton::ascii_key('a');       break;
+     case 11:   nk = KeyboardButton::ascii_key('b');       break;
+     case 8:    nk = KeyboardButton::ascii_key('c');       break;
+     case 2:    nk = KeyboardButton::ascii_key('d');       break;
+     case 14:   nk = KeyboardButton::ascii_key('e');       break;
+     case 3:    nk = KeyboardButton::ascii_key('f');       break;
+     case 5:    nk = KeyboardButton::ascii_key('g');       break;
+     case 4:    nk = KeyboardButton::ascii_key('h');       break;
+     case 34:   nk = KeyboardButton::ascii_key('i');       break;
+     case 38:   nk = KeyboardButton::ascii_key('j');       break;
+     case 40:   nk = KeyboardButton::ascii_key('k');       break;
+     case 37:   nk = KeyboardButton::ascii_key('l');       break;
+     case 46:   nk = KeyboardButton::ascii_key('m');       break;
+     case 45:   nk = KeyboardButton::ascii_key('n');       break;
+     case 31:   nk = KeyboardButton::ascii_key('o');       break;
+     case 35:   nk = KeyboardButton::ascii_key('p');       break;
+     case 12:   nk = KeyboardButton::ascii_key('q');       break;
+     case 15:   nk = KeyboardButton::ascii_key('r');       break;
+     case 1:    nk = KeyboardButton::ascii_key('s');       break;
+     case 17:   nk = KeyboardButton::ascii_key('t');       break;
+     case 32:   nk = KeyboardButton::ascii_key('u');       break;
+     case 9:    nk = KeyboardButton::ascii_key('v');       break;
+     case 13:   nk = KeyboardButton::ascii_key('w');       break;
+     case 7:    nk = KeyboardButton::ascii_key('x');       break;
+     case 16:   nk = KeyboardButton::ascii_key('y');       break;
+     case 6:    nk = KeyboardButton::ascii_key('z');       break;
+
+         // top row numbers
+     case 29:   nk = KeyboardButton::ascii_key('0');       break;
+     case 18:   nk = KeyboardButton::ascii_key('1');       break;
+     case 19:   nk = KeyboardButton::ascii_key('2');       break;
+     case 20:   nk = KeyboardButton::ascii_key('3');       break;
+     case 21:   nk = KeyboardButton::ascii_key('4');       break;
+     case 23:   nk = KeyboardButton::ascii_key('5');       break;
+     case 22:   nk = KeyboardButton::ascii_key('6');       break;
+     case 26:   nk = KeyboardButton::ascii_key('7');       break;
+     case 28:   nk = KeyboardButton::ascii_key('8');       break;
+     case 25:   nk = KeyboardButton::ascii_key('9');       break;
+
+         // key pad ... do they really map to the top number in panda ?
+     case 82:   nk = KeyboardButton::ascii_key('0');       break;
+     case 83:   nk = KeyboardButton::ascii_key('1');       break;
+     case 84:   nk = KeyboardButton::ascii_key('2');       break;
+     case 85:   nk = KeyboardButton::ascii_key('3');       break;
+     case 86:   nk = KeyboardButton::ascii_key('4');       break;
+     case 87:   nk = KeyboardButton::ascii_key('5');       break;
+     case 88:   nk = KeyboardButton::ascii_key('6');       break;
+     case 89:   nk = KeyboardButton::ascii_key('7');       break;
+     case 91:   nk = KeyboardButton::ascii_key('8');       break;
+     case 92:   nk = KeyboardButton::ascii_key('9');       break;
+
+
+         //	case 36:   nk = KeyboardButton::ret();			  break;   // no return  in panda ???
+     case 49:   nk = KeyboardButton::space();		 	  break;
+     case 51:   nk = KeyboardButton::backspace();		  break;
+     case 48:   nk = KeyboardButton::tab();				  break;
+     case 53:   nk = KeyboardButton::escape();			  break;
+     case 76:   nk = KeyboardButton::enter();			  break;	
+     case 36:   nk = KeyboardButton::enter();			  break;	
+
+     case 123:  nk = KeyboardButton::left();			  break;
+     case 124:  nk = KeyboardButton::right();			  break;
+     case 125:  nk = KeyboardButton::down();			  break;
+     case 126:  nk = KeyboardButton::up();				  break;
+     case 116:  nk = KeyboardButton::page_up();			  break;
+     case 121:  nk = KeyboardButton::page_down();		  break;
+     case 115:  nk = KeyboardButton::home();			  break;
+     case 119:  nk = KeyboardButton::end();				  break;
+     case 114:  nk = KeyboardButton::help();			  break;			
+     case 117:  nk = KeyboardButton::del();				  break;			
+
+         //	case  71:  nk = KeyboardButton::num_lock()        break; 
+
+     case 122:  nk = KeyboardButton::f1();				  break;
+     case 120:  nk = KeyboardButton::f2();				  break;
+     case  99:  nk = KeyboardButton::f3();				  break;
+     case 118:  nk = KeyboardButton::f4();				  break;
+     case  96:  nk = KeyboardButton::f5();				  break;
+     case  97:  nk = KeyboardButton::f6();				  break;
+     case  98:  nk = KeyboardButton::f7();				  break;
+     case 100:  nk = KeyboardButton::f8();				  break;
+     case 101:  nk = KeyboardButton::f9();				  break;
+     case 109:  nk = KeyboardButton::f10();				  break;
+     case 103:  nk = KeyboardButton::f11();				  break;
+     case 111:  nk = KeyboardButton::f12();				  break;
+
+     case 105:  nk = KeyboardButton::f13();				  break;
+     case 107:  nk = KeyboardButton::f14();				  break;
+     case 113:  nk = KeyboardButton::f15();				  break;
+     case 106:  nk = KeyboardButton::f16();				  break;
+
+         // shiftable chartablet 
+     case  50:  nk = KeyboardButton::ascii_key('`');	  break;
+     case  27:  nk = KeyboardButton::ascii_key('-');	  break;
+     case  24:  nk = KeyboardButton::ascii_key('=');	  break;
+     case  33:  nk = KeyboardButton::ascii_key('[');	  break;
+     case  30:  nk = KeyboardButton::ascii_key(']');	  break;
+     case  42:  nk = KeyboardButton::ascii_key('\\');	  break;
+     case  41:  nk = KeyboardButton::ascii_key(';');	  break;
+     case  39:  nk = KeyboardButton::ascii_key('\'');	  break;
+     case  43:  nk = KeyboardButton::ascii_key(',');	  break;
+     case  47:  nk = KeyboardButton::ascii_key('.');	  break;
+     case  44:  nk = KeyboardButton::ascii_key('/');	  break;
+
+     default:
+       if (tinydisplay_cat.is_debug()) {
+         tinydisplay_cat.debug()
+           << " Untranslated KeyCode: " << key
+           << " (0x" << hex << key << dec << ")\n";
+       }
+
+       // not sure this is right .. but no mapping for keypad and such
+       // this at least does a best gess..
+       
+       char charCode =  0;	
+       if(GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, nil, sizeof( charCode ), nil, &charCode ) == noErr)
+         nk = KeyboardButton::ascii_key(charCode);	
+     }
+     return nk;
+ }
+ ////////////////////////////////////////////////////////////////////
+ //     Function: TinyOsxGraphicsWindow::HandleModifireDeleta
+ //       Access: Private
+ //  Description: Used to emulate key events for the MAC key Modifiers..
+ ////////////////////////////////////////////////////////////////////
+ void     TinyOsxGraphicsWindow::HandleModifireDeleta(UInt32 newModifiers)
+ {
+     UInt32 changed = _last_key_modifiers ^ newModifiers;
+
+     if ((changed & (shiftKey | rightShiftKey)) != 0)
+         SendKeyEvent(KeyboardButton::shift(),(newModifiers & (shiftKey | rightShiftKey)) != 0) ;
+
+     if ((changed & (optionKey | rightOptionKey)) != 0) 
+         SendKeyEvent(KeyboardButton::alt(),(newModifiers & (optionKey | rightOptionKey)) != 0);
+
+
+     if ((changed & (controlKey | rightControlKey)) != 0) 
+		SendKeyEvent(KeyboardButton::control(),(newModifiers & (controlKey | rightControlKey)) != 0);
+
+     if ((changed & cmdKey) != 0) 
+		SendKeyEvent(KeyboardButton::meta(),(newModifiers & cmdKey) != 0);
+	
+    if ((changed & alphaLock) != 0) 
+		SendKeyEvent(KeyboardButton::caps_lock(),(newModifiers & alphaLock) != 0);
+	
+	// save current state
+    _last_key_modifiers = newModifiers;						   
+								
+ };
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::HandleButtonDelta
+//       Access: Private
+//  Description: Used to emulate buttons events/
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::
+HandleButtonDelta(UInt32 new_buttons) {
+  UInt32 changed = _last_buttons ^ new_buttons;
+
+  if (changed & 0x01) {
+    if (new_buttons & 0x01) {
+      _input_devices[0].button_down(MouseButton::one());
+    } else {
+      _input_devices[0].button_up(MouseButton::one());
+    }
+  }
+
+  if (changed & 0x04) {
+    if (new_buttons & 0x04) {
+      _input_devices[0].button_down(MouseButton::two());
+    } else {
+      _input_devices[0].button_up(MouseButton::two());
+    }
+  }
+
+  if (changed & 0x02) {
+    if (new_buttons & 0x02) {
+      _input_devices[0].button_down(MouseButton::three());
+    } else {
+      _input_devices[0].button_up(MouseButton::three());
+    }
+  }
+
+  _last_buttons = new_buttons;
+}
+
+ ////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::move_pointer
+//       Access: Published, Virtual
+//  Description: Forces the pointer to the indicated position within
+//               the window, if possible.  
+//
+//               Returns true if successful, false on failure.  This
+//               may fail if the mouse is not currently within the
+//               window, or if the API doesn't support this operation.
+////////////////////////////////////////////////////////////////////
+bool TinyOsxGraphicsWindow::move_pointer(int device, int x, int y) 
+{ 
+    if(_osx_window == NULL) 
+        return false; 
+    
+if (tinydisplay_cat.is_debug())    
+        tinydisplay_cat.debug() << "move_pointer " << device <<" "<<  x <<" "<< y <<"\n"; 
+    
+    Point pt = {0, 0}; 
+    pt.h = x; 
+    pt.v = y; 
+    set_pointer_in_window(x, y);  
+
+    if(_properties.get_mouse_mode()==WindowProperties::M_absolute)
+    {
+       LocalPointToSystemPoint(pt); 
+       CGPoint newCursorPosition = {0, 0}; 
+       newCursorPosition.x = pt.h; 
+       newCursorPosition.y = pt.v; 
+       mouse_mode_relative();
+       CGWarpMouseCursorPosition(newCursorPosition); 
+       mouse_mode_absolute();
+    }
+    
+    return true; 
+}; 
+
+bool TinyOsxGraphicsWindow::do_reshape_request(int x_origin, int y_origin, bool has_origin,int x_size, int y_size)
+{
+	tinydisplay_cat.info() << "Do Reshape\n";
+
+  if (_properties.get_fullscreen()) {
+    return false;
+  }
+
+  if (_properties.has_parent_window())
+  {
+    if (has_origin)
+    {
+		NSWindow*	parentWindow		=	(NSWindow *)_properties.get_parent_window();
+		NSRect		parentFrame			=	[parentWindow frame];
+		
+		MoveWindow(_osx_window, x_origin+parentFrame.origin.x, y_origin+parentFrame.origin.y, false);
+	 }
+  }
+  else
+  {
+	  // We sometimes get a bogus origin of (0, 0).  As a special hack,
+	  // treat this as a special case, and ignore it.
+	  if (has_origin) {
+		if (x_origin != 0 || y_origin != 0) {
+		  MoveWindow(_osx_window, x_origin, y_origin, false);
+		}
+	  }
+  }
+
+  if (!_properties.get_undecorated())
+  {
+    // Constrain the window to the available desktop size.
+    Rect bounds;
+    GetAvailableWindowPositioningBounds(GetMainDevice(), &bounds);
+    
+    x_size = min(x_size, bounds.right - bounds.left);
+    y_size = min(y_size, bounds.bottom - bounds.top);
+  }
+
+  SizeWindow(_osx_window, x_size, y_size, false);
+
+  system_changed_size(x_size, y_size);
+  ZB_resize(_frame_buffer, NULL, _properties.get_x_size(), _properties.get_y_size());
+  return true;
+}								
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::set_properties_now
+//       Access: Public, Virtual
+//  Description: Applies the requested set of properties to the
+//               window, if possible, for instance to request a change
+//               in size or minimization status.
+//
+//               The window properties are applied immediately, rather
+//               than waiting until the next frame.  This implies that
+//               this method may *only* be called from within the
+//               window thread.
+//
+//               The properties that have been applied are cleared
+//               from the structure by this function; so on return,
+//               whatever remains in the properties structure are
+//               those that were unchanged for some reason (probably
+//               because the underlying interface does not support
+//               changing that property on an open window).
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::set_properties_now(WindowProperties &properties) 
+{
+  if (tinydisplay_cat.is_debug())
+  {
+    tinydisplay_cat.debug()
+      << "------------------------------------------------------\n";
+    tinydisplay_cat.debug()
+      << "set_properties_now " << properties << "\n";
+  }
+  
+  GraphicsWindow::set_properties_now(properties);
+	  
+  if (tinydisplay_cat.is_debug()) {
+    tinydisplay_cat.debug()
+      << "set_properties_now After Base Class" << properties << "\n";
+  }
+ 
+  // for some changes .. a full rebuild is required for the OS layer Window.
+  //    I think it is the crome atribute and full screen behaviour.
+  bool need_full_rebuild = false;
+ 
+  // if we are not full and transitioning to full
+  if (properties.has_fullscreen() && 
+      properties.get_fullscreen() != _properties.get_fullscreen()) {
+    need_full_rebuild = true;
+  }
+
+  // If we are fullscreen and requesting a size change
+  if (_properties.get_fullscreen() &&  
+      (properties.has_size() && 
+       (properties.get_x_size() != _properties.get_x_size() ||
+        properties.get_y_size() != _properties.get_y_size()))) {
+    need_full_rebuild = true;
+  }
+  
+  if (need_full_rebuild) {
+    // Logic here is ..  take a union of the properties .. with the
+    // new allowed to overwrite the old states.  and start a bootstrap
+    // of a new window ..
+    
+    // get a copy of my properties..
+    WindowProperties req_properties(_properties); 
+    ReleaseSystemResources();
+    req_properties.add_properties(properties);	
+    
+    OSOpenWindow(req_properties); 
+    
+    // Now we've handled all of the requested properties.
+    properties.clear();
+  }
+
+  if (properties.has_title()) {
+    _properties.set_title(properties.get_title());
+    if (_osx_window) {
+      SetWindowTitleWithCFString(_osx_window,
+                                 CFStringCreateWithCString(NULL,properties.get_title().c_str(),
+                                                           kCFStringEncodingMacRoman));
+    }
+    properties.clear_title();
+  }
+
+  // An icon filename means to load up the icon and save it.  We can't
+  // necessarily apply it immediately; it will get applied later, in
+  // the window event handler.
+  if (properties.has_icon_filename()) {
+    if (set_icon_filename(properties.get_icon_filename())) {
+      properties.clear_icon_filename();
+    }
+  }
+
+  // decorated .. if this changes it reqires a new window
+  if (properties.has_undecorated()) {
+    _properties.set_undecorated(properties.get_undecorated());
+    properties.clear_undecorated();
+  }
+
+  if (properties.has_cursor_hidden()) { 
+    _properties.set_cursor_hidden(properties.get_cursor_hidden()); 
+    _cursor_hidden = properties.get_cursor_hidden();
+    if (_cursor_hidden && _input_devices[0].has_pointer()) { 
+      if (!_display_hide_cursor) {
+        CGDisplayHideCursor(kCGDirectMainDisplay); 
+        _display_hide_cursor = true;
+      }
+    } else { 
+      if (_display_hide_cursor) {
+        CGDisplayShowCursor(kCGDirectMainDisplay); 
+        _display_hide_cursor = false;
+      }
+    } 
+    properties.clear_cursor_hidden(); 
+  } 
+
+  if (tinydisplay_cat.is_debug()) {
+    tinydisplay_cat.debug()
+      << "set_properties_now  Out....." << _properties << "\n";
+  }
+
+  return;
+}
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+void TinyOsxGraphicsWindow::LocalPointToSystemPoint(Point &qdLocalPoint) 
+{ 
+    if(_osx_window != NULL) 
+    { 
+        GrafPtr savePort;
+        Boolean portChanged = QDSwapPort(GetWindowPort(_osx_window), &savePort);
+ 
+        LocalToGlobal( &qdLocalPoint );
+       
+        if (portChanged)
+            QDSwapPort(savePort, NULL);
+    } 
+} 
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::mouse_mode_relative
+//       Access: Protected, Virtual
+//  Description: detaches mouse. Only mouse delta from now on. 
+//               
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::mouse_mode_relative()
+{
+  CGAssociateMouseAndMouseCursorPosition(false);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::mouse_mode_absolute
+//       Access: Protected, Virtual
+//  Description: reattaches mouse to location
+//               
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::mouse_mode_absolute()
+{
+  CGAssociateMouseAndMouseCursorPosition(true);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TinyOsxGraphicsWindow::create_frame_buffer
+//       Access: Private
+//  Description: Creates a suitable frame buffer for the current
+//               window size.
+////////////////////////////////////////////////////////////////////
+void TinyOsxGraphicsWindow::
+create_frame_buffer() {
+  if (_frame_buffer != NULL) {
+    ZB_close(_frame_buffer);
+    _frame_buffer = NULL;
+  }
+
+  _frame_buffer = ZB_open(_properties.get_x_size(), _properties.get_y_size(), ZB_MODE_RGBA, 0, 0, 0, 0);
+}