mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 02:42:49 -04:00
1808 lines
60 KiB
Plaintext
1808 lines
60 KiB
Plaintext
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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
|
|
// panda3d-general@lists.sourceforge.net .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
#include <Carbon/Carbon.h>
|
|
#include <Cocoa/Cocoa.h>
|
|
|
|
#include "osxGraphicsWindow.h"
|
|
#include "config_osxdisplay.h"
|
|
#include "osxGraphicsPipe.h"
|
|
#include "pStatTimer.h"
|
|
#include "glgsg.h"
|
|
#include "keyboardButton.h"
|
|
#include "mouseButton.h"
|
|
#include "osxGraphicsStateGuardian.h"
|
|
#include "osxGraphicsPipe.h"
|
|
#include "throw_event.h"
|
|
#include "pnmImage.h"
|
|
#include "virtualFileSystem.h"
|
|
#include "config_util.h"
|
|
|
|
#include <OpenGL/gl.h>
|
|
#include <AGL/agl.h>
|
|
#include <ApplicationServices/ApplicationServices.h>
|
|
|
|
////////////////////////// Global Objects .....
|
|
|
|
TypeHandle osxGraphicsWindow::_type_handle;
|
|
osxGraphicsWindow * osxGraphicsWindow::FullScreenWindow = NULL;
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: GetCurrentOSxWindow
|
|
// Access: Static,
|
|
// Description: How to find the active window for events on osx..
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
osxGraphicsWindow* osxGraphicsWindow::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)
|
|
return (osxGraphicsWindow *)GetWRefCon (window);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: aglReportError
|
|
// Access: public
|
|
// Description: Helper function for AGL error message and Grabing error code if any
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
OSStatus aglReportError(const std::string &comment)
|
|
{
|
|
GLenum err = aglGetError();
|
|
if (err != AGL_NO_ERROR )
|
|
osxdisplay_cat.error()<<"AGL Error " << aglErrorString(err) << "[" <<comment <<"]\n";
|
|
|
|
if (err == AGL_NO_ERROR)
|
|
return noErr;
|
|
else
|
|
return (OSStatus)err;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: InvertGLImage
|
|
// Access: file scopre, static
|
|
// Description: Helper function invertiung a gl image
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
static void InvertGLImage( char *imageData, size_t imageSize, size_t rowBytes )
|
|
{
|
|
size_t i, j;
|
|
char *tBuffer = (char*) malloc (rowBytes);
|
|
if (NULL == tBuffer)
|
|
return;
|
|
|
|
// Copy by rows through temp buffer
|
|
for (i = 0, j = imageSize - rowBytes; i < imageSize >> 1; i += rowBytes, j -= rowBytes)
|
|
{
|
|
memcpy( tBuffer, &imageData[i], rowBytes );
|
|
memcpy( &imageData[i], &imageData[j], rowBytes );
|
|
memcpy( &imageData[j], tBuffer, rowBytes );
|
|
}
|
|
|
|
free(tBuffer);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: CompositeGLBufferIntoWindow
|
|
// Access: file scopre, static
|
|
// Description: Drop a Gl overlay onto a carbon window..
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
static void CompositeGLBufferIntoWindow (AGLContext ctx, Rect *bufferRect, GrafPtr out_port)
|
|
{
|
|
GWorldPtr pGWorld;
|
|
QDErr err;
|
|
|
|
// blit OpenGL content into window backing store
|
|
// allocate buffer to hold pane image
|
|
long width = (bufferRect->right - bufferRect->left);
|
|
long height = (bufferRect->bottom - bufferRect->top);
|
|
|
|
Rect src_rect = {0, 0, height, width};
|
|
Rect ddrc_rect = {0, 0, height, width};
|
|
long rowBytes = width * 4;
|
|
long imageSize = rowBytes * height;
|
|
char *image = (char *) NewPtr (imageSize);
|
|
|
|
if (!image)
|
|
{
|
|
osxdisplay_cat.error() << "Out of memory in CompositeGLBufferIntoWindow()!\n";
|
|
return; // no harm in continuing
|
|
}
|
|
|
|
// pull GL content down to our image buffer
|
|
aglSetCurrentContext( ctx );
|
|
glReadPixels (0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, image);
|
|
|
|
// GL buffers are upside-down relative to QD buffers, so we need to flip it
|
|
InvertGLImage( image, imageSize, rowBytes );
|
|
|
|
// create a GWorld containing our image
|
|
err = NewGWorldFromPtr (&pGWorld, k32ARGBPixelFormat, &src_rect, 0, 0, 0, image, rowBytes);
|
|
if (err != noErr)
|
|
{
|
|
osxdisplay_cat.error() << " error in NewGWorldFromPtr, called from CompositeGLBufferIntoWindow()\n";
|
|
free(image);
|
|
return;
|
|
}
|
|
|
|
GrafPtr portSave = NULL;
|
|
Boolean portChanged = QDSwapPort(out_port, &portSave);
|
|
|
|
CopyBits(GetPortBitMapForCopyBits (pGWorld), GetPortBitMapForCopyBits (out_port), &src_rect, &ddrc_rect, srcCopy, 0);
|
|
|
|
if (portChanged)
|
|
QDSwapPort(portSave, NULL);
|
|
|
|
DisposeGWorld(pGWorld);
|
|
DisposePtr(image);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::event_handler
|
|
// Access: Public
|
|
// Description: The standard window event handler for non-fullscreen
|
|
// windows.
|
|
////////////////////////////////////////////////////////////////////
|
|
OSStatus osxGraphicsWindow::event_handler(EventHandlerCallRef myHandler, EventRef event)
|
|
{
|
|
OSStatus result = eventNotHandledErr;
|
|
UInt32 the_class = GetEventClass(event);
|
|
UInt32 kind = GetEventKind(event);
|
|
|
|
WindowRef window = _osx_window; // NULL;
|
|
// GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window);
|
|
|
|
if (osxdisplay_cat.is_spam())
|
|
{
|
|
osxdisplay_cat.spam() << ClockObject::get_global_clock()->get_real_time() << " event_handler: " << (void *)this << ", " << window << ", " << the_class << ", " << kind << "\n";
|
|
}
|
|
|
|
switch (the_class)
|
|
{
|
|
case kEventClassMouse:
|
|
osxdisplay_cat.info() << "Mouse movement handled by Window handler\n";
|
|
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: osxGraphicsWindow::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 osxGraphicsWindow::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: osxGraphicsWindow::SystemCloseWindow
|
|
// Access: private
|
|
// Description: The Windows is closed by a OS resource not by a internal request
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void osxGraphicsWindow::SystemCloseWindow()
|
|
{
|
|
if (osxdisplay_cat.is_debug())
|
|
osxdisplay_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)
|
|
{
|
|
osxGraphicsWindow* osx_win = (osxGraphicsWindow *)userData;
|
|
if (osx_win != (osxGraphicsWindow *)NULL)
|
|
return osx_win->event_handler(myHandler, event);
|
|
|
|
//#pragma unused (userData)
|
|
|
|
// WindowRef window = NULL;
|
|
// GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window);
|
|
|
|
// if (window != NULL)
|
|
// {
|
|
// osxGraphicsWindow *osx_win = osxGraphicsWindow::GetCurrentOSxWindow(window);
|
|
// if (osx_win != (osxGraphicsWindow *)NULL)
|
|
// return osx_win->event_handler(myHandler, event);
|
|
// }
|
|
|
|
return eventNotHandledErr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::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 osxGraphicsWindow::DoResize(void)
|
|
{
|
|
osxdisplay_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);
|
|
|
|
if (osxdisplay_cat.is_debug())
|
|
osxdisplay_cat.debug() << " Resizing Window " << viewRect.size.width << " " << viewRect.size.height << "\n";
|
|
|
|
// ping gl
|
|
aglUpdateContext (aglGetCurrentContext());
|
|
aglReportError("aglUpdateContext .. This is a Resize..");
|
|
osxdisplay_cat.info() << "Resize Complete.....\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;
|
|
osxGraphicsWindow *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 = osxGraphicsWindow::GetCurrentOSxWindow(window);
|
|
if (osx_win == NULL)
|
|
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:
|
|
osxdisplay_cat.info() << "Mouse movement handled by Application handler\n";
|
|
//if(osxGraphicsWindow::FullScreenWindow != NULL)
|
|
result = osx_win->handleWindowMouseEvents (myHandler, event);
|
|
//result = noErr;
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::handleTextInput
|
|
// Access:
|
|
// Description: Trap Unicode Input.
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
OSStatus osxGraphicsWindow::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: osxGraphicsWindow::ReleaseSystemResources
|
|
// Access: private..
|
|
// Description: Clean up the OS level messes..
|
|
////////////////////////////////////////////////////////////////////
|
|
void osxGraphicsWindow::ReleaseSystemResources()
|
|
{
|
|
if (_is_fullscreen)
|
|
{
|
|
_is_fullscreen = false;
|
|
FullScreenWindow = NULL;
|
|
|
|
if (_originalMode != NULL)
|
|
CGDisplaySwitchToMode( kCGDirectMainDisplay, _originalMode );
|
|
|
|
CGDisplayRelease( kCGDirectMainDisplay );
|
|
aglSetDrawable (get_ggs_context(), NULL);
|
|
|
|
_originalMode = NULL;
|
|
}
|
|
|
|
// if the ggs context is assigned to this window
|
|
// clear it..
|
|
if (_osx_window != NULL && GetWindowPort (_osx_window) == (GrafPtr)aglGetDrawable(get_ggs_context()))
|
|
aglSetDrawable (get_ggs_context(),NULL);
|
|
|
|
// if we are the active gl context clear it..
|
|
if(aglGetCurrentContext() == get_ggs_context())
|
|
aglSetCurrentContext (NULL);
|
|
|
|
if(_osx_window != NULL)
|
|
{
|
|
SetWRefCon (_osx_window, (long int) NULL);
|
|
HideWindow (_osx_window);
|
|
DisposeWindow(_osx_window);
|
|
_osx_window = NULL;
|
|
}
|
|
|
|
if (_holder_aglcontext) {
|
|
aglDestroyContext (_holder_aglcontext);
|
|
_holder_aglcontext = 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: osxGraphicsWindow::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
osxGraphicsWindow::osxGraphicsWindow(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),
|
|
#ifdef HACK_SCREEN_HASH_CONTEXT
|
|
_holder_aglcontext(NULL),
|
|
#endif
|
|
_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;
|
|
|
|
if (osxdisplay_cat.is_debug())
|
|
osxdisplay_cat.debug() << "osxGraphicsWindow::osxGraphicsWindow() -" <<_ID << "\n";
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::Destructor
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
osxGraphicsWindow::~osxGraphicsWindow()
|
|
{
|
|
if (osxdisplay_cat.is_debug())
|
|
osxdisplay_cat.debug() << "osxGraphicsWindow::~osxGraphicsWindow() -" <<_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: osxGraphicsWindow::get_context
|
|
// Access: private..
|
|
// Description: Helper to Decide whitch context to use if any
|
|
////////////////////////////////////////////////////////////////////
|
|
AGLContext osxGraphicsWindow::get_context(void)
|
|
{
|
|
if(_holder_aglcontext != NULL)
|
|
return _holder_aglcontext;
|
|
|
|
return get_ggs_context();
|
|
}
|
|
///////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::get_ggs_context
|
|
// Access: private..
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
AGLContext osxGraphicsWindow::get_ggs_context(void)
|
|
{
|
|
if(_gsg != NULL)
|
|
{
|
|
osxGraphicsStateGuardian *osxgsg = NULL;
|
|
osxgsg = DCAST(osxGraphicsStateGuardian, _gsg);
|
|
return osxgsg->get_context();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::buildGL
|
|
// Access: private..
|
|
// Description: Code of the class.. used to control the GL context Allocation ..
|
|
////////////////////////////////////////////////////////////////////
|
|
OSStatus osxGraphicsWindow::
|
|
buildGL(bool full_screen) {
|
|
// make sure the ggs is up and runnig..
|
|
osxGraphicsStateGuardian *osxgsg = NULL;
|
|
osxgsg = DCAST(osxGraphicsStateGuardian, _gsg);
|
|
OSStatus stat = osxgsg->buildGL(*this, full_screen, _fb_properties);
|
|
|
|
if(stat != noErr) {
|
|
return stat;
|
|
}
|
|
|
|
OSStatus err = noErr;
|
|
|
|
if (osxgsg->getAGlPixelFormat()) {
|
|
_holder_aglcontext = aglCreateContext(osxgsg->getAGlPixelFormat(),NULL);
|
|
|
|
err = aglReportError ("aglCreateContext");
|
|
if(_holder_aglcontext == NULL) {
|
|
osxdisplay_cat.error() << "osxGraphicsWindow::buildG Error aglCreateContext \n";
|
|
if(err ==noErr)
|
|
err = -1;
|
|
} else {
|
|
aglSetInteger (_holder_aglcontext, AGL_BUFFER_NAME, &osxgsg->SharedBuffer);
|
|
err = aglReportError ("aglSetInteger AGL_BUFFER_NAME");
|
|
|
|
}
|
|
} else {
|
|
osxdisplay_cat.error()
|
|
<< "osxGraphicsWindow::buildG Error Getting PixelFormat \n";
|
|
if(err ==noErr) {
|
|
err = -1;
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::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 osxGraphicsWindow::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.
|
|
osxdisplay_cat.warning()
|
|
<< "Could not find icon filename " << icon_filename << "\n";
|
|
return false;
|
|
}
|
|
|
|
|
|
PNMImage pnmimage;
|
|
if (!pnmimage.read(icon_pathname))
|
|
{
|
|
osxdisplay_cat.warning()
|
|
<< "Could not read icon filename " << icon_pathname << "\n";
|
|
return false;
|
|
}
|
|
|
|
CGImageRef icon_image = osxGraphicsPipe::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: osxGraphicsWindow::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 osxGraphicsWindow::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;
|
|
}
|
|
}
|
|
|
|
if (_is_fullscreen)
|
|
{
|
|
aglSetFullScreen(get_ggs_context(),0,0,0,0);
|
|
aglReportError ("aglSetFullScreen");
|
|
|
|
if (!aglSetCurrentContext(get_ggs_context()))
|
|
aglReportError ("aglSetCurrentContext");
|
|
|
|
}else
|
|
{
|
|
if (FullScreenWindow != NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!aglSetDrawable (get_ggs_context(), GetWindowPort (_osx_window)))
|
|
{
|
|
osxdisplay_cat.error() << "Error aglSetDrawable \n";
|
|
aglReportError("aglSetDrawable");
|
|
}
|
|
|
|
if (!aglSetCurrentContext(get_ggs_context()))
|
|
{
|
|
osxdisplay_cat.error() << "Error in aglSetCurrentContext \n";
|
|
aglReportError ("aglSetCurrentContext");
|
|
}
|
|
}
|
|
|
|
_gsg->reset_if_new();
|
|
_gsg->set_current_properties(&get_fb_properties());
|
|
return _gsg->begin_frame(current_thread);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::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 osxGraphicsWindow::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(osxGraphicsStateGuardian, _gsg)->draw_resize_box();
|
|
}
|
|
|
|
aglSwapBuffers (get_ggs_context());
|
|
_gsg->end_frame(current_thread);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::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 osxGraphicsWindow::end_flip()
|
|
{
|
|
// cerr << " end_flip [" << _ID << "]\n";
|
|
}
|
|
|
|
void osxGraphicsWindow::begin_flip()
|
|
{
|
|
// this forces a rip to proper context
|
|
// cerr << " begin_flip [" << _ID << "]\n";
|
|
return;
|
|
|
|
if(_is_fullscreen)
|
|
{
|
|
aglSetFullScreen(get_ggs_context(),0,0,0,0);
|
|
aglReportError ("aglSetFullScreen");
|
|
|
|
if (!aglSetCurrentContext(get_ggs_context()))
|
|
aglReportError ("aglSetCurrentContext");
|
|
|
|
aglSwapBuffers (get_ggs_context());
|
|
}
|
|
else
|
|
{
|
|
if(!aglSetDrawable (get_ggs_context(),GetWindowPort (_osx_window)))
|
|
{
|
|
osxdisplay_cat.error() << "Error aglSetDrawable \n";
|
|
aglReportError("aglSetDrawable");
|
|
}
|
|
|
|
if (!aglSetCurrentContext(get_ggs_context()))
|
|
{
|
|
osxdisplay_cat.error() << "Error in aglSetCurrentContext \n";
|
|
aglReportError ("aglSetCurrentContext");
|
|
}
|
|
|
|
aglSwapBuffers (get_ggs_context());
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::close_window
|
|
// Access: Protected, Virtual
|
|
// Description: Closes the window right now. Called from the window
|
|
// thread.
|
|
////////////////////////////////////////////////////////////////////
|
|
void osxGraphicsWindow::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: osxGraphicsWindow::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 osxGraphicsWindow::open_window()
|
|
{
|
|
WindowProperties req_properties = _properties;
|
|
|
|
if (_gsg == 0)
|
|
{
|
|
_gsg = new osxGraphicsStateGuardian(_pipe, NULL);
|
|
}
|
|
|
|
return OSOpenWindow(req_properties);
|
|
}
|
|
|
|
|
|
bool osxGraphicsWindow::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 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, &ref1 );
|
|
GlobalInits = true;
|
|
|
|
// Replicating the hacky code with more document/support code which should do the same thing
|
|
|
|
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
|
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
|
SetFrontProcess(&psn);
|
|
|
|
// Hacky code
|
|
|
|
// struct CPSProcessSerNum PSN;
|
|
// GetCurrentProcess((ProcessSerialNumber *)&PSN);
|
|
// err = CPSGetCurrentProcess(&PSN);
|
|
|
|
// if (req_properties.has_title())
|
|
// err = CPSSetProcessName(&PSN,(char *)req_properties.get_title().c_str());
|
|
// else
|
|
// err = CPSSetProcessName(&PSN,"");
|
|
|
|
// err = CPSEnableForegroundOperation(&PSN);
|
|
// err = CPSSetFrontProcess(&PSN);
|
|
}
|
|
|
|
if (req_properties.has_fullscreen() && req_properties.get_fullscreen())
|
|
{
|
|
osxdisplay_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)
|
|
{
|
|
osxdisplay_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);
|
|
}
|
|
}
|
|
|
|
if (buildGL(true) != noErr)
|
|
{
|
|
if(_originalMode != NULL)
|
|
CGDisplaySwitchToMode( kCGDirectMainDisplay, _originalMode );
|
|
_originalMode = NULL;
|
|
|
|
CGDisplayRelease( kCGDirectMainDisplay );
|
|
return false;
|
|
}
|
|
|
|
_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())
|
|
{
|
|
NSWindow* parentWindow = (NSWindow *)req_properties.get_parent_window();
|
|
NSView* aView = [[parentWindow contentView] viewWithTag:378];
|
|
NSRect aRect = [aView frame];
|
|
NSPoint origin = [parentWindow convertBaseToScreen:aRect.origin];
|
|
|
|
osxdisplay_cat.info() << "Creating child window\n";
|
|
|
|
CreateNewWindow(kSimpleWindowClass, kWindowNoAttributes, &r, &_osx_window);
|
|
NSWindow* childWindow = [[NSWindow alloc] initWithWindowRef:_osx_window];
|
|
|
|
[childWindow setFrameOrigin:origin];
|
|
[childWindow setAcceptsMouseMovedEvents:YES];
|
|
[childWindow setBackgroundColor:[NSColor blackColor]];
|
|
[parentWindow addChildWindow:childWindow ordered:NSWindowAbove];
|
|
[childWindow orderFront:nil];
|
|
|
|
_properties.set_fixed_size(true);
|
|
}
|
|
else
|
|
{
|
|
if (req_properties.has_undecorated() && req_properties.get_undecorated())
|
|
{ // create a unmovable .. no edge window..
|
|
|
|
osxdisplay_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);
|
|
|
|
osxdisplay_cat.info() << "Creating standard window\n";
|
|
CreateNewWindow(kDocumentWindowClass, kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute, &r, &_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
|
|
ShowWindow (_osx_window);
|
|
|
|
if(buildGL(false) != noErr)
|
|
{
|
|
osxdisplay_cat.error() << " Error In Generate GL \n";
|
|
|
|
HideWindow (_osx_window);
|
|
SetWRefCon (_osx_window, (long int) NULL);
|
|
DisposeWindow(_osx_window);
|
|
_osx_window = NULL;
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// atach the holder context to the window..
|
|
//
|
|
|
|
if (!aglSetDrawable(_holder_aglcontext, GetWindowPort (_osx_window)))
|
|
err = aglReportError ("aglSetDrawable");
|
|
|
|
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: osxGraphicsWindow::process_events()
|
|
// Access: virtual, protected
|
|
// Description: Required Event upcall . Used to dispatch Window and Aplication Events
|
|
// back into panda
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void osxGraphicsWindow::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: osxGraphicsWindow::handleKeyInput()
|
|
// Access: virtual, protected
|
|
// Description: Required Event upcall . Used to dispatch Window and Aplication Events
|
|
// back into panda
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
// key input handler
|
|
OSStatus osxGraphicsWindow::handleKeyInput (EventHandlerCallRef myHandler, EventRef event, Boolean keyDown) {
|
|
if (osxdisplay_cat.is_debug()) {
|
|
UInt32 keyCode;
|
|
GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
|
|
|
|
osxdisplay_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 noErr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function:
|
|
// Access:
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void osxGraphicsWindow::SystemSetWindowForground(bool forground)
|
|
{
|
|
WindowProperties properties;
|
|
properties.set_foreground(forground);
|
|
system_changed_properties(properties);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function:
|
|
// Access:
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
void osxGraphicsWindow::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 osxGraphicsWindow::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 wheelDelta;
|
|
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 ))
|
|
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);
|
|
}
|
|
|
|
_input_devices[0].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);
|
|
}
|
|
_input_devices[0].set_pointer_in_window((int)qdGlobalPoint.h, (int)qdGlobalPoint.v);
|
|
result = noErr;
|
|
|
|
break;
|
|
|
|
case kEventMouseWheelMoved:
|
|
GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(wheelDelta), NULL, &wheelDelta);
|
|
GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(wheelAxis), NULL, &wheelAxis );
|
|
GetEventParameter(event, kEventParamMouseLocation,typeQDPoint, NULL, sizeof(Point),NULL , (void*) &qdGlobalPoint);
|
|
SystemPointToLocalPoint(qdGlobalPoint);
|
|
|
|
if (wheelAxis == kEventMouseWheelAxisY)
|
|
{
|
|
_input_devices[0].set_pointer_in_window((int)qdGlobalPoint.h, (int)qdGlobalPoint.v);
|
|
if (wheelDelta > 0)
|
|
{
|
|
_input_devices[0].button_down(MouseButton::wheel_up());
|
|
result = noErr;
|
|
}
|
|
else if (wheelDelta < 0)
|
|
{
|
|
_input_devices[0].button_down(MouseButton::wheel_down());
|
|
}
|
|
}
|
|
result = noErr;
|
|
break;
|
|
}
|
|
// result = noErr;
|
|
}
|
|
|
|
// cerr <<" End Mouse Event \n";
|
|
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::OSX_TranslateKey
|
|
// Access: Private
|
|
// Description: MAC Key Codes to Panda Key Codes
|
|
////////////////////////////////////////////////////////////////////
|
|
ButtonHandle osxGraphicsWindow::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 (osxdisplay_cat.is_debug()) {
|
|
osxdisplay_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: osxGraphicsWindow::HandleModifireDeleta
|
|
// Access: Private
|
|
// Description: Used to emulate key events for the MAC key Modifiers..
|
|
////////////////////////////////////////////////////////////////////
|
|
void osxGraphicsWindow::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: osxGraphicsWindow::HandleButtonDelta
|
|
// Access: Private
|
|
// Description: Used to emulate buttons events/
|
|
////////////////////////////////////////////////////////////////////
|
|
void osxGraphicsWindow::
|
|
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: osxGraphicsWindow::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 osxGraphicsWindow::move_pointer(int device, int x, int y)
|
|
{
|
|
if(_osx_window == NULL)
|
|
return false;
|
|
|
|
if (osxdisplay_cat.is_debug())
|
|
osxdisplay_cat.debug() << "move_pointer " << device <<" "<< x <<" "<< y <<"\n";
|
|
|
|
Point pt = {0, 0};
|
|
pt.h = x;
|
|
pt.v = y;
|
|
_input_devices[0].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 osxGraphicsWindow::do_reshape_request(int x_origin, int y_origin, bool has_origin,int x_size, int y_size)
|
|
{
|
|
osxdisplay_cat.info() << "Do Reshape\n";
|
|
|
|
if (_properties.get_fullscreen()) {
|
|
return false;
|
|
}
|
|
|
|
// For now, ignore the origin, since we seem to be getting a bogus
|
|
// origin of (0, 0).
|
|
//
|
|
// We need this to be here so that changing window size places the
|
|
// window in the correct position.
|
|
|
|
if (has_origin) {
|
|
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);
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: osxGraphicsWindow::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 osxGraphicsWindow::set_properties_now(WindowProperties &properties)
|
|
{
|
|
if (osxdisplay_cat.is_debug())
|
|
{
|
|
osxdisplay_cat.debug()
|
|
<< "------------------------------------------------------\n";
|
|
osxdisplay_cat.debug()
|
|
<< "set_properties_now " << properties << "\n";
|
|
}
|
|
|
|
GraphicsWindow::set_properties_now(properties);
|
|
|
|
if (osxdisplay_cat.is_debug()) {
|
|
osxdisplay_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());
|
|
if (properties.get_cursor_hidden()) {
|
|
CGDisplayHideCursor(kCGDirectMainDisplay);
|
|
} else {
|
|
CGDisplayShowCursor(kCGDirectMainDisplay);
|
|
}
|
|
properties.clear_cursor_hidden();
|
|
}
|
|
|
|
if (osxdisplay_cat.is_debug()) {
|
|
osxdisplay_cat.debug()
|
|
<< "set_properties_now Out....." << _properties << "\n";
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
void osxGraphicsWindow::LocalPointToSystemPoint(Point &qdLocalPoint)
|
|
{
|
|
if(_osx_window != NULL)
|
|
{
|
|
GrafPtr savePort;
|
|
Boolean portChanged = QDSwapPort(GetWindowPort(_osx_window), &savePort);
|
|
|
|
LocalToGlobal( &qdLocalPoint );
|
|
|
|
if (portChanged)
|
|
QDSwapPort(savePort, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OSXGraphicsWindow::mouse_mode_relative
|
|
// Access: Protected, Virtual
|
|
// Description: detaches mouse. Only mouse delta from now on.
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void osxGraphicsWindow::mouse_mode_relative()
|
|
{
|
|
CGAssociateMouseAndMouseCursorPosition(false);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: OSXGraphicsWindow::mouse_mode_absolute
|
|
// Access: Protected, Virtual
|
|
// Description: reattaches mouse to location
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
void osxGraphicsWindow::mouse_mode_absolute()
|
|
{
|
|
CGAssociateMouseAndMouseCursorPosition(true);
|
|
}
|