Cocoa port start:
GHOST*Cocoa.mm & .h files creation First Cocoa version of GHOST_SystemCocoa.mm CMake files update to allow optional (WITH_COCOA option) Cocoa version build - disabled by default SCons files are not updated to allow Cocoa build (the ghost .mm files)
This commit is contained in:
@@ -81,6 +81,10 @@ OPTION(WITH_CXX_GUARDEDALLOC "Enable GuardedAlloc for C++ memory allocation" OFF
|
||||
OPTION(WITH_BUILDINFO "Include extra build details" ON)
|
||||
OPTION(WITH_INSTALL "Install accompanying scripts and language files needed to run blender" ON)
|
||||
|
||||
IF (APPLE)
|
||||
OPTION(WITH_COCOA "Use Cocoa framework instead of deprecated Carbon" OFF)
|
||||
ENDIF (APPLE)
|
||||
|
||||
IF(NOT WITH_GAMEENGINE AND WITH_PLAYER)
|
||||
MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE")
|
||||
ENDIF(NOT WITH_GAMEENGINE AND WITH_PLAYER)
|
||||
@@ -402,6 +406,7 @@ IF(APPLE)
|
||||
FIND_PACKAGE(OpenAL)
|
||||
IF(OPENAL_FOUND)
|
||||
SET(WITH_OPENAL ON)
|
||||
SET(OPENAL_INCLUDE_DIR "${OPENAL_INCLUDE_DIR};${LIBDIR}/openal/include")
|
||||
ELSE(OPENAL_FOUND)
|
||||
SET(WITH_OPENAL OFF)
|
||||
ENDIF(OPENAL_FOUND)
|
||||
@@ -485,9 +490,13 @@ IF(APPLE)
|
||||
|
||||
SET(LLIBS stdc++ SystemStubs)
|
||||
|
||||
IF (WITH_COCOA)
|
||||
SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -DGHOST_COCOA")
|
||||
SET(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Cocoa -framework Carbon -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime")
|
||||
ELSE (WITH_COCOA)
|
||||
SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
|
||||
SET(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime")
|
||||
|
||||
ENDIF (WITH_COCOA)
|
||||
IF(WITH_OPENMP)
|
||||
SET(LLIBS "${LLIBS} -lgomp ")
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ")
|
||||
|
||||
@@ -26,9 +26,18 @@
|
||||
|
||||
SET(INC . ../string)
|
||||
|
||||
FILE(GLOB SRC intern/*.cpp)
|
||||
FILE(GLOB SRC intern/*.cpp intern/*.mm)
|
||||
|
||||
IF(APPLE)
|
||||
IF(WITH_COCOA)
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerCarbon.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemCarbon.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowCarbon.cpp")
|
||||
ELSE(WITH_COCOA)
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerCocoa.mm")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemCocoa.mm")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowCocoa.mm")
|
||||
ENDIF(WITH_COCOA)
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerWin32.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemWin32.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowWin32.cpp")
|
||||
@@ -41,6 +50,9 @@ ELSE(APPLE)
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerCarbon.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemCarbon.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowCarbon.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerCocoa.mm")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemCocoa.mm")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowCocoa.mm")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerX11.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemX11.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowX11.cpp")
|
||||
@@ -52,6 +64,9 @@ ELSE(APPLE)
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerCarbon.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemCarbon.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowCarbon.cpp")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_DisplayManagerCocoa.mm")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_SystemCocoa.mm")
|
||||
LIST(REMOVE_ITEM SRC "${CMAKE_CURRENT_SOURCE_DIR}/intern/GHOST_WindowCocoa.mm")
|
||||
ENDIF(WIN32)
|
||||
ENDIF(APPLE)
|
||||
|
||||
|
||||
113
intern/ghost/intern/GHOST_DisplayManagerCocoa.h
Normal file
113
intern/ghost/intern/GHOST_DisplayManagerCocoa.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* $Id: GHOST_DisplayManagerCocoa.h 13161 2008-01-07 19:13:47Z hos $
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
/**
|
||||
* @file GHOST_DisplayManagerCocoa.h
|
||||
* Declaration of GHOST_DisplayManagerCocoa class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_DISPLAY_MANAGER_COCOA_H_
|
||||
#define _GHOST_DISPLAY_MANAGER_COCOA_H_
|
||||
|
||||
#ifndef __APPLE__
|
||||
#error Apple only!
|
||||
#endif // __APPLE__
|
||||
|
||||
#include "GHOST_DisplayManager.h"
|
||||
|
||||
/**
|
||||
* Manages system displays (Mac OSX/Cocoa implementation).
|
||||
* @see GHOST_DisplayManager
|
||||
* @author Maarten Gribnau
|
||||
* @date September 21, 2001
|
||||
*/
|
||||
class GHOST_DisplayManagerCocoa : public GHOST_DisplayManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_DisplayManagerCocoa(void);
|
||||
|
||||
/**
|
||||
* Returns the number of display devices on this system.
|
||||
* @param numDisplays The number of displays on this system.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const;
|
||||
|
||||
/**
|
||||
* Returns the number of display settings for this display device.
|
||||
* @param display The index of the display to query with 0 <= display < getNumDisplays().
|
||||
* @param setting The number of settings of the display device with this index.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const;
|
||||
|
||||
/**
|
||||
* Returns the current setting for this display device.
|
||||
* @param display The index of the display to query with 0 <= display < getNumDisplays().
|
||||
* @param index The setting index to be returned.
|
||||
* @param setting The setting of the display device with this index.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const;
|
||||
|
||||
/**
|
||||
* Returns the current setting for this display device.
|
||||
* @param display The index of the display to query with 0 <= display < getNumDisplays().
|
||||
* @param setting The current setting of the display device with this index.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const;
|
||||
|
||||
/**
|
||||
* Changes the current setting for this display device.
|
||||
* @param display The index of the display to query with 0 <= display < getNumDisplays().
|
||||
* @param setting The current setting of the display device with this index.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Returns a value from a dictionary.
|
||||
* @param values Dictionary to return value from.
|
||||
* @param key Key to return value for.
|
||||
* @return The value for this key.
|
||||
*/
|
||||
long getValue(CFDictionaryRef values, CFStringRef key) const;
|
||||
|
||||
/** Cached number of displays. */
|
||||
CGDisplayCount m_numDisplays;
|
||||
/** Cached display id's for each display. */
|
||||
CGDirectDisplayID* m_displayIDs;
|
||||
};
|
||||
|
||||
|
||||
#endif // _GHOST_DISPLAY_MANAGER_COCOA_H_
|
||||
|
||||
180
intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
Normal file
180
intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* $Id: GHOST_DisplayManagerCocoa.mm 13161 2008-01-07 19:13:47Z hos $
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
* $Id: GHOST_DisplayManagerCocoa.mm 13161 2008-01-07 19:13:47Z hos $
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date September 21, 2001
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include "GHOST_DisplayManagerCocoa.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
// We do not support multiple monitors at the moment
|
||||
|
||||
|
||||
GHOST_DisplayManagerCocoa::GHOST_DisplayManagerCocoa(void)
|
||||
{
|
||||
if (::CGGetActiveDisplayList(0, NULL, &m_numDisplays) != CGDisplayNoErr)
|
||||
{
|
||||
m_numDisplays = 0;
|
||||
m_displayIDs = NULL;
|
||||
}
|
||||
if (m_numDisplays > 0)
|
||||
{
|
||||
m_displayIDs = new CGDirectDisplayID [m_numDisplays];
|
||||
GHOST_ASSERT((m_displayIDs!=NULL), "GHOST_DisplayManagerCocoa::GHOST_DisplayManagerCocoa(): memory allocation failed");
|
||||
::CGGetActiveDisplayList(m_numDisplays, m_displayIDs, &m_numDisplays);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplays(GHOST_TUns8& numDisplays) const
|
||||
{
|
||||
numDisplays = (GHOST_TUns8) m_numDisplays;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getNumDisplaySettings(): only main display is supported");
|
||||
|
||||
CFArrayRef displayModes;
|
||||
displayModes = ::CGDisplayAvailableModes(m_displayIDs[display]);
|
||||
CFIndex numModes = ::CFArrayGetCount(displayModes);
|
||||
numSettings = (GHOST_TInt32)numModes;
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getDisplaySetting(): only main display is supported");
|
||||
|
||||
CFArrayRef displayModes;
|
||||
CGDirectDisplayID d = m_displayIDs[display];
|
||||
displayModes = ::CGDisplayAvailableModes(d);
|
||||
//CFIndex numModes = ::CFArrayGetCount(displayModes);/*unused*/
|
||||
//GHOST_TInt32 numSettings = (GHOST_TInt32)numModes; /*unused*/
|
||||
CFDictionaryRef displayModeValues = (CFDictionaryRef)::CFArrayGetValueAtIndex(displayModes, index);
|
||||
|
||||
setting.xPixels = getValue(displayModeValues, kCGDisplayWidth);
|
||||
setting.yPixels = getValue(displayModeValues, kCGDisplayHeight);
|
||||
setting.bpp = getValue(displayModeValues, kCGDisplayBitsPerPixel);
|
||||
setting.frequency = getValue(displayModeValues, kCGDisplayRefreshRate);
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency);
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(): only main display is supported");
|
||||
|
||||
CFDictionaryRef displayModeValues = ::CGDisplayCurrentMode(m_displayIDs[display]);
|
||||
|
||||
setting.xPixels = getValue(displayModeValues, kCGDisplayWidth);
|
||||
setting.yPixels = getValue(displayModeValues, kCGDisplayHeight);
|
||||
setting.bpp = getValue(displayModeValues, kCGDisplayBitsPerPixel);
|
||||
setting.frequency = getValue(displayModeValues, kCGDisplayRefreshRate);
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
printf("current display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency);
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting)
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(): only main display is supported");
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
printf("GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(): requested settings:\n");
|
||||
printf(" setting.xPixels=%d\n", setting.xPixels);
|
||||
printf(" setting.yPixels=%d\n", setting.yPixels);
|
||||
printf(" setting.bpp=%d\n", setting.bpp);
|
||||
printf(" setting.frequency=%d\n", setting.frequency);
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
CFDictionaryRef displayModeValues = ::CGDisplayBestModeForParametersAndRefreshRate(
|
||||
m_displayIDs[display],
|
||||
(size_t)setting.bpp,
|
||||
(size_t)setting.xPixels,
|
||||
(size_t)setting.yPixels,
|
||||
(CGRefreshRate)setting.frequency,
|
||||
NULL);
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
printf("GHOST_DisplayManagerCocoa::setCurrentDisplaySetting(): switching to:\n");
|
||||
printf(" setting.xPixels=%d\n", getValue(displayModeValues, kCGDisplayWidth));
|
||||
printf(" setting.yPixels=%d\n", getValue(displayModeValues, kCGDisplayHeight));
|
||||
printf(" setting.bpp=%d\n", getValue(displayModeValues, kCGDisplayBitsPerPixel));
|
||||
printf(" setting.frequency=%d\n", getValue(displayModeValues, kCGDisplayRefreshRate));
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues);
|
||||
|
||||
return err == CGDisplayNoErr ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
long GHOST_DisplayManagerCocoa::getValue(CFDictionaryRef values, CFStringRef key) const
|
||||
{
|
||||
CFNumberRef numberValue = (CFNumberRef) CFDictionaryGetValue(values, key);
|
||||
|
||||
if (!numberValue)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
long intValue;
|
||||
|
||||
if (!CFNumberGetValue(numberValue, kCFNumberLongType, &intValue))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return intValue;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,11 @@
|
||||
# include "GHOST_SystemWin32.h"
|
||||
#else
|
||||
# ifdef __APPLE__
|
||||
# include "GHOST_SystemCarbon.h"
|
||||
# ifdef GHOST_COCOA
|
||||
# include "GHOST_SystemCocoa.h"
|
||||
# else
|
||||
# include "GHOST_SystemCarbon.h"
|
||||
# endif
|
||||
# else
|
||||
# include "GHOST_SystemX11.h"
|
||||
# endif
|
||||
@@ -62,7 +66,11 @@ GHOST_TSuccess GHOST_ISystem::createSystem()
|
||||
m_system = new GHOST_SystemWin32 ();
|
||||
#else
|
||||
# ifdef __APPLE__
|
||||
m_system = new GHOST_SystemCarbon ();
|
||||
# ifdef GHOST_COCOA
|
||||
m_system = new GHOST_SystemCocoa ();
|
||||
# else
|
||||
m_system = new GHOST_SystemCarbon ();
|
||||
# endif
|
||||
# else
|
||||
m_system = new GHOST_SystemX11 ();
|
||||
# endif
|
||||
|
||||
274
intern/ghost/intern/GHOST_SystemCocoa.h
Normal file
274
intern/ghost/intern/GHOST_SystemCocoa.h
Normal file
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
* $Id: GHOST_SystemCocoa.h 20741 2009-06-08 20:08:19Z blendix $
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Maarten Gribnau 05/2001
|
||||
* Damien Plisson 09/2009
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
/**
|
||||
* @file GHOST_SystemCocoa.h
|
||||
* Declaration of GHOST_SystemCocoa class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_SYSTEM_COCOA_H_
|
||||
#define _GHOST_SYSTEM_COCOA_H_
|
||||
|
||||
#ifndef __APPLE__
|
||||
#error Apple OSX only!
|
||||
#endif // __APPLE__
|
||||
|
||||
//#define __CARBONSOUND__
|
||||
|
||||
|
||||
#include "GHOST_System.h"
|
||||
|
||||
class GHOST_EventCursor;
|
||||
class GHOST_EventKey;
|
||||
class GHOST_EventWindow;
|
||||
|
||||
|
||||
class GHOST_SystemCocoa : public GHOST_System {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_SystemCocoa();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~GHOST_SystemCocoa();
|
||||
|
||||
/***************************************************************************************
|
||||
** Time(r) functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the system time.
|
||||
* Returns the number of milliseconds since the start of the system process.
|
||||
* Based on ANSI clock() routine.
|
||||
* @return The number of milliseconds.
|
||||
*/
|
||||
virtual GHOST_TUns64 getMilliSeconds() const;
|
||||
|
||||
/***************************************************************************************
|
||||
** Display/window management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the number of displays on this system.
|
||||
* @return The number of displays.
|
||||
*/
|
||||
virtual GHOST_TUns8 getNumDisplays() const;
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the main display on this system.
|
||||
* @return The dimension of the main display.
|
||||
*/
|
||||
virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const;
|
||||
|
||||
/**
|
||||
* Create a new window.
|
||||
* The new window is added to the list of windows managed.
|
||||
* Never explicitly delete the window, use disposeWindow() instead.
|
||||
* @param title The name of the window (displayed in the title bar of the window if the OS supports it).
|
||||
* @param left The coordinate of the left edge of the window.
|
||||
* @param top The coordinate of the top edge of the window.
|
||||
* @param width The width the window.
|
||||
* @param height The height the window.
|
||||
* @param state The state of the window when opened.
|
||||
* @param type The type of drawing context installed in this window.
|
||||
* @param parentWindow Parent (embedder) window
|
||||
* @return The new window (or 0 if creation failed).
|
||||
*/
|
||||
virtual GHOST_IWindow* createWindow(
|
||||
const STR_String& title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_TDrawingContextType type,
|
||||
const bool stereoVisual,
|
||||
const GHOST_TEmbedderWindowID parentWindow = 0
|
||||
);
|
||||
|
||||
virtual GHOST_TSuccess beginFullScreen(
|
||||
const GHOST_DisplaySetting& setting,
|
||||
GHOST_IWindow** window,
|
||||
const bool stereoVisual
|
||||
);
|
||||
|
||||
virtual GHOST_TSuccess endFullScreen( void );
|
||||
|
||||
/***************************************************************************************
|
||||
** Event management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Gets events from the system and stores them in the queue.
|
||||
* @param waitForEvent Flag to wait for an event (or return immediately).
|
||||
* @return Indication of the presence of events.
|
||||
*/
|
||||
virtual bool processEvents(bool waitForEvent);
|
||||
|
||||
/***************************************************************************************
|
||||
** Cursor management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the current location of the cursor (location in screen coordinates)
|
||||
* @param x The x-coordinate of the cursor.
|
||||
* @param y The y-coordinate of the cursor.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const;
|
||||
|
||||
/**
|
||||
* Updates the location of the cursor (location in screen coordinates).
|
||||
* @param x The x-coordinate of the cursor.
|
||||
* @param y The y-coordinate of the cursor.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const;
|
||||
|
||||
/***************************************************************************************
|
||||
** Access to mouse button and keyboard states.
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the state of all modifier keys.
|
||||
* @param keys The state of all modifier keys (true == pressed).
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const;
|
||||
|
||||
/**
|
||||
* Returns the state of the mouse buttons (ouside the message queue).
|
||||
* @param buttons The state of the buttons.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const;
|
||||
|
||||
/**
|
||||
* Returns Clipboard data
|
||||
* @param selection Indicate which buffer to return
|
||||
* @return Returns the selected buffer
|
||||
*/
|
||||
virtual GHOST_TUns8* getClipboard(bool selection) const;
|
||||
|
||||
/**
|
||||
* Puts buffer to system clipboard
|
||||
* @param buffer The buffer to be copied
|
||||
* @param selection Indicates which buffer to copy too, only used on X11
|
||||
*/
|
||||
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initializes the system.
|
||||
* For now, it justs registers the window class (WNDCLASS).
|
||||
* @return A success value.
|
||||
*/
|
||||
virtual GHOST_TSuccess init();
|
||||
|
||||
/**
|
||||
* Closes the system down.
|
||||
* @return A success value.
|
||||
*/
|
||||
virtual GHOST_TSuccess exit();
|
||||
|
||||
|
||||
/**
|
||||
* Handles a tablet event.
|
||||
* @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
int handleTabletEvent(void *eventPtr);
|
||||
/**
|
||||
* Handles a mouse event.
|
||||
* @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
int handleMouseEvent(void *eventPtr);
|
||||
|
||||
/**
|
||||
* Handles a key event.
|
||||
* @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
int handleKeyEvent(void *eventPtr);
|
||||
|
||||
/**
|
||||
* Handles a window event.
|
||||
* @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
int handleWindowEvent(void *eventPtr);
|
||||
|
||||
/**
|
||||
* Handles all basic Mac application stuff for a mouse down event.
|
||||
* @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
// bool handleMouseDown(void *eventPtr);
|
||||
|
||||
/**
|
||||
* Handles a Mac menu command.
|
||||
* @param menuResult A Mac menu/item identifier.
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
// bool handleMenuCommand(GHOST_TInt32 menuResult);
|
||||
|
||||
/* callback for blender generated events */
|
||||
// static OSStatus blendEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData);
|
||||
|
||||
|
||||
/**
|
||||
* Callback for Mac Timer tasks that expire.
|
||||
* @param tmTask Pointer to the timer task that expired.
|
||||
*/
|
||||
//static void s_timerCallback(TMTaskPtr tmTask);
|
||||
|
||||
/** Cocoa autoReleasePool (void*) used for enablign standard C++ compilation */
|
||||
void* autoReleasePool;
|
||||
|
||||
/** Event handler reference. */
|
||||
//EventHandlerRef m_handler;
|
||||
|
||||
/** Start time at initialization. */
|
||||
GHOST_TUns64 m_start_time;
|
||||
|
||||
/** Mouse buttons state */
|
||||
GHOST_TUns32 m_pressedMouseButtons;
|
||||
|
||||
/** State of the modifiers. */
|
||||
GHOST_TUns32 m_modifierMask;
|
||||
|
||||
/** Ignores window size messages (when window is dragged). */
|
||||
bool m_ignoreWindowSizedMessages;
|
||||
};
|
||||
|
||||
#endif // _GHOST_SYSTEM_COCOA_H_
|
||||
|
||||
1282
intern/ghost/intern/GHOST_SystemCocoa.mm
Normal file
1282
intern/ghost/intern/GHOST_SystemCocoa.mm
Normal file
@@ -0,0 +1,1282 @@
|
||||
/**
|
||||
* $Id: GHOST_SystemCocoa.cpp 23296 2009-09-16 22:27:27Z broken $
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Maarten Gribnau 05/2001
|
||||
* Damien Plisson 09/2009
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include "GHOST_SystemCocoa.h"
|
||||
|
||||
#include "GHOST_DisplayManagerCocoa.h"
|
||||
#include "GHOST_EventKey.h"
|
||||
#include "GHOST_EventButton.h"
|
||||
#include "GHOST_EventCursor.h"
|
||||
#include "GHOST_EventWheel.h"
|
||||
#include "GHOST_EventNDOF.h"
|
||||
|
||||
#include "GHOST_TimerManager.h"
|
||||
#include "GHOST_TimerTask.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
#include "GHOST_WindowCocoa.h"
|
||||
#include "GHOST_NDOFManager.h"
|
||||
#include "AssertMacros.h"
|
||||
|
||||
#define GHOST_KEY_SWITCH(mac, ghost) { case (mac): ghostKey = (ghost); break; }
|
||||
|
||||
/* blender class and types events */
|
||||
enum {
|
||||
kEventClassBlender = 'blnd'
|
||||
};
|
||||
|
||||
enum {
|
||||
kEventBlenderNdofAxis = 1,
|
||||
kEventBlenderNdofButtons = 2
|
||||
};
|
||||
|
||||
#pragma mark KeyMap, mouse converters
|
||||
|
||||
const EventTypeSpec kEvents[] =
|
||||
{
|
||||
{ kEventClassAppleEvent, kEventAppleEvent },
|
||||
/*
|
||||
{ kEventClassApplication, kEventAppActivated },
|
||||
{ kEventClassApplication, kEventAppDeactivated },
|
||||
*/
|
||||
{ kEventClassKeyboard, kEventRawKeyDown },
|
||||
{ kEventClassKeyboard, kEventRawKeyRepeat },
|
||||
{ kEventClassKeyboard, kEventRawKeyUp },
|
||||
{ kEventClassKeyboard, kEventRawKeyModifiersChanged },
|
||||
|
||||
{ kEventClassMouse, kEventMouseDown },
|
||||
{ kEventClassMouse, kEventMouseUp },
|
||||
{ kEventClassMouse, kEventMouseMoved },
|
||||
{ kEventClassMouse, kEventMouseDragged },
|
||||
{ kEventClassMouse, kEventMouseWheelMoved },
|
||||
|
||||
{ kEventClassWindow, kEventWindowClickZoomRgn } , /* for new zoom behaviour */
|
||||
{ kEventClassWindow, kEventWindowZoom }, /* for new zoom behaviour */
|
||||
{ kEventClassWindow, kEventWindowExpand } , /* for new zoom behaviour */
|
||||
{ kEventClassWindow, kEventWindowExpandAll }, /* for new zoom behaviour */
|
||||
|
||||
{ kEventClassWindow, kEventWindowClose },
|
||||
{ kEventClassWindow, kEventWindowActivated },
|
||||
{ kEventClassWindow, kEventWindowDeactivated },
|
||||
{ kEventClassWindow, kEventWindowUpdate },
|
||||
{ kEventClassWindow, kEventWindowBoundsChanged },
|
||||
|
||||
{ kEventClassBlender, kEventBlenderNdofAxis },
|
||||
{ kEventClassBlender, kEventBlenderNdofButtons }
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
static GHOST_TButtonMask convertButton(EventMouseButton button)
|
||||
{
|
||||
switch (button) {
|
||||
case 0:
|
||||
return GHOST_kButtonMaskLeft;
|
||||
case 1:
|
||||
return GHOST_kButtonMaskRight;
|
||||
case 2:
|
||||
return GHOST_kButtonMaskMiddle;
|
||||
case 3:
|
||||
return GHOST_kButtonMaskButton4;
|
||||
case 4:
|
||||
return GHOST_kButtonMaskButton5;
|
||||
default:
|
||||
return GHOST_kButtonMaskLeft;
|
||||
}
|
||||
}
|
||||
|
||||
static GHOST_TKey convertKey(int rawCode, unsigned char asciiCharacter)
|
||||
{
|
||||
/* This bit of magic converts the rawCode into a virtual
|
||||
* Mac key based on the current keyboard mapping, but
|
||||
* without regard to the modifiers (so we don't get 'a'
|
||||
* and 'A' for example.
|
||||
*/
|
||||
/* Map numpad based on rawcodes first, otherwise they
|
||||
* look like non-numpad events.
|
||||
* Added too: mapping the number keys, for french keyboards etc (ton)
|
||||
*/
|
||||
// printf("GHOST: vk: %d %c raw: %d\n", asciiCharacter, asciiCharacter, rawCode);
|
||||
//FIXME : check rawcodes
|
||||
switch (rawCode) {
|
||||
case 18: return GHOST_kKey1;
|
||||
case 19: return GHOST_kKey2;
|
||||
case 20: return GHOST_kKey3;
|
||||
case 21: return GHOST_kKey4;
|
||||
case 23: return GHOST_kKey5;
|
||||
case 22: return GHOST_kKey6;
|
||||
case 26: return GHOST_kKey7;
|
||||
case 28: return GHOST_kKey8;
|
||||
case 25: return GHOST_kKey9;
|
||||
case 29: return GHOST_kKey0;
|
||||
|
||||
case 82: return GHOST_kKeyNumpad0;
|
||||
case 83: return GHOST_kKeyNumpad1;
|
||||
case 84: return GHOST_kKeyNumpad2;
|
||||
case 85: return GHOST_kKeyNumpad3;
|
||||
case 86: return GHOST_kKeyNumpad4;
|
||||
case 87: return GHOST_kKeyNumpad5;
|
||||
case 88: return GHOST_kKeyNumpad6;
|
||||
case 89: return GHOST_kKeyNumpad7;
|
||||
case 91: return GHOST_kKeyNumpad8;
|
||||
case 92: return GHOST_kKeyNumpad9;
|
||||
case 65: return GHOST_kKeyNumpadPeriod;
|
||||
case 76: return GHOST_kKeyNumpadEnter;
|
||||
case 69: return GHOST_kKeyNumpadPlus;
|
||||
case 78: return GHOST_kKeyNumpadMinus;
|
||||
case 67: return GHOST_kKeyNumpadAsterisk;
|
||||
case 75: return GHOST_kKeyNumpadSlash;
|
||||
}
|
||||
|
||||
if ((asciiCharacter >= 'a') && (asciiCharacter <= 'z')) {
|
||||
return (GHOST_TKey) (asciiCharacter - 'a' + GHOST_kKeyA);
|
||||
} else if ((asciiCharacter >= '0') && (asciiCharacter <= '9')) {
|
||||
return (GHOST_TKey) (asciiCharacter - '0' + GHOST_kKey0);
|
||||
} else if (asciiCharacter==16) {
|
||||
switch (rawCode) {
|
||||
case 122: return GHOST_kKeyF1;
|
||||
case 120: return GHOST_kKeyF2;
|
||||
case 99: return GHOST_kKeyF3;
|
||||
case 118: return GHOST_kKeyF4;
|
||||
case 96: return GHOST_kKeyF5;
|
||||
case 97: return GHOST_kKeyF6;
|
||||
case 98: return GHOST_kKeyF7;
|
||||
case 100: return GHOST_kKeyF8;
|
||||
case 101: return GHOST_kKeyF9;
|
||||
case 109: return GHOST_kKeyF10;
|
||||
case 103: return GHOST_kKeyF11;
|
||||
case 111: return GHOST_kKeyF12; // FIXME : Never get, is used for ejecting the CD!
|
||||
}
|
||||
} else {
|
||||
switch (asciiCharacter) {
|
||||
case kUpArrowCharCode: return GHOST_kKeyUpArrow;
|
||||
case kDownArrowCharCode: return GHOST_kKeyDownArrow;
|
||||
case kLeftArrowCharCode: return GHOST_kKeyLeftArrow;
|
||||
case kRightArrowCharCode: return GHOST_kKeyRightArrow;
|
||||
|
||||
case kReturnCharCode: return GHOST_kKeyEnter;
|
||||
case kBackspaceCharCode: return GHOST_kKeyBackSpace;
|
||||
case kDeleteCharCode: return GHOST_kKeyDelete;
|
||||
case kEscapeCharCode: return GHOST_kKeyEsc;
|
||||
case kTabCharCode: return GHOST_kKeyTab;
|
||||
case kSpaceCharCode: return GHOST_kKeySpace;
|
||||
|
||||
case kHomeCharCode: return GHOST_kKeyHome;
|
||||
case kEndCharCode: return GHOST_kKeyEnd;
|
||||
case kPageUpCharCode: return GHOST_kKeyUpPage;
|
||||
case kPageDownCharCode: return GHOST_kKeyDownPage;
|
||||
|
||||
case '-': return GHOST_kKeyMinus;
|
||||
case '=': return GHOST_kKeyEqual;
|
||||
case ',': return GHOST_kKeyComma;
|
||||
case '.': return GHOST_kKeyPeriod;
|
||||
case '/': return GHOST_kKeySlash;
|
||||
case ';': return GHOST_kKeySemicolon;
|
||||
case '\'': return GHOST_kKeyQuote;
|
||||
case '\\': return GHOST_kKeyBackslash;
|
||||
case '[': return GHOST_kKeyLeftBracket;
|
||||
case ']': return GHOST_kKeyRightBracket;
|
||||
case '`': return GHOST_kKeyAccentGrave;
|
||||
}
|
||||
}
|
||||
|
||||
// printf("GHOST: unknown key: %d %d\n", vk, rawCode);
|
||||
|
||||
return GHOST_kKeyUnknown;
|
||||
}
|
||||
|
||||
/* MacOSX returns a Roman charset with kEventParamKeyMacCharCodes
|
||||
* as defined here: http://developer.apple.com/documentation/mac/Text/Text-516.html
|
||||
* I am not sure how international this works...
|
||||
* For cross-platform convention, we'll use the Latin ascii set instead.
|
||||
* As defined at: http://www.ramsch.org/martin/uni/fmi-hp/iso8859-1.html
|
||||
*
|
||||
*/
|
||||
static unsigned char convertRomanToLatin(unsigned char ascii)
|
||||
{
|
||||
|
||||
if(ascii<128) return ascii;
|
||||
|
||||
switch(ascii) {
|
||||
case 128: return 142;
|
||||
case 129: return 143;
|
||||
case 130: return 128;
|
||||
case 131: return 201;
|
||||
case 132: return 209;
|
||||
case 133: return 214;
|
||||
case 134: return 220;
|
||||
case 135: return 225;
|
||||
case 136: return 224;
|
||||
case 137: return 226;
|
||||
case 138: return 228;
|
||||
case 139: return 227;
|
||||
case 140: return 229;
|
||||
case 141: return 231;
|
||||
case 142: return 233;
|
||||
case 143: return 232;
|
||||
case 144: return 234;
|
||||
case 145: return 235;
|
||||
case 146: return 237;
|
||||
case 147: return 236;
|
||||
case 148: return 238;
|
||||
case 149: return 239;
|
||||
case 150: return 241;
|
||||
case 151: return 243;
|
||||
case 152: return 242;
|
||||
case 153: return 244;
|
||||
case 154: return 246;
|
||||
case 155: return 245;
|
||||
case 156: return 250;
|
||||
case 157: return 249;
|
||||
case 158: return 251;
|
||||
case 159: return 252;
|
||||
case 160: return 0;
|
||||
case 161: return 176;
|
||||
case 162: return 162;
|
||||
case 163: return 163;
|
||||
case 164: return 167;
|
||||
case 165: return 183;
|
||||
case 166: return 182;
|
||||
case 167: return 223;
|
||||
case 168: return 174;
|
||||
case 169: return 169;
|
||||
case 170: return 174;
|
||||
case 171: return 180;
|
||||
case 172: return 168;
|
||||
case 173: return 0;
|
||||
case 174: return 198;
|
||||
case 175: return 216;
|
||||
case 176: return 0;
|
||||
case 177: return 177;
|
||||
case 178: return 0;
|
||||
case 179: return 0;
|
||||
case 180: return 165;
|
||||
case 181: return 181;
|
||||
case 182: return 0;
|
||||
case 183: return 0;
|
||||
case 184: return 215;
|
||||
case 185: return 0;
|
||||
case 186: return 0;
|
||||
case 187: return 170;
|
||||
case 188: return 186;
|
||||
case 189: return 0;
|
||||
case 190: return 230;
|
||||
case 191: return 248;
|
||||
case 192: return 191;
|
||||
case 193: return 161;
|
||||
case 194: return 172;
|
||||
case 195: return 0;
|
||||
case 196: return 0;
|
||||
case 197: return 0;
|
||||
case 198: return 0;
|
||||
case 199: return 171;
|
||||
case 200: return 187;
|
||||
case 201: return 201;
|
||||
case 202: return 0;
|
||||
case 203: return 192;
|
||||
case 204: return 195;
|
||||
case 205: return 213;
|
||||
case 206: return 0;
|
||||
case 207: return 0;
|
||||
case 208: return 0;
|
||||
case 209: return 0;
|
||||
case 210: return 0;
|
||||
|
||||
case 214: return 247;
|
||||
|
||||
case 229: return 194;
|
||||
case 230: return 202;
|
||||
case 231: return 193;
|
||||
case 232: return 203;
|
||||
case 233: return 200;
|
||||
case 234: return 205;
|
||||
case 235: return 206;
|
||||
case 236: return 207;
|
||||
case 237: return 204;
|
||||
case 238: return 211;
|
||||
case 239: return 212;
|
||||
case 240: return 0;
|
||||
case 241: return 210;
|
||||
case 242: return 218;
|
||||
case 243: return 219;
|
||||
case 244: return 217;
|
||||
case 245: return 0;
|
||||
case 246: return 0;
|
||||
case 247: return 0;
|
||||
case 248: return 0;
|
||||
case 249: return 0;
|
||||
case 250: return 0;
|
||||
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#define FIRSTFILEBUFLG 512
|
||||
static bool g_hasFirstFile = false;
|
||||
static char g_firstFileBuf[512];
|
||||
|
||||
extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) {
|
||||
if (g_hasFirstFile) {
|
||||
strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1);
|
||||
buf[FIRSTFILEBUFLG - 1] = '\0';
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Cocoa objects
|
||||
|
||||
/**
|
||||
* CocoaAppDelegate
|
||||
* ObjC object to capture applicationShouldTerminate, and send quit event
|
||||
**/
|
||||
@interface CocoaAppDelegate : NSObject
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
|
||||
@end
|
||||
|
||||
@implementation CocoaAppDelegate : NSObject
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
//Note that Cmd+Q is already handled by keyhandler
|
||||
//FIXME: Cocoa_SendQuit();
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark initialization/finalization
|
||||
|
||||
/***/
|
||||
|
||||
GHOST_SystemCocoa::GHOST_SystemCocoa()
|
||||
{
|
||||
m_modifierMask =0;
|
||||
m_pressedMouseButtons =0;
|
||||
m_displayManager = new GHOST_DisplayManagerCocoa ();
|
||||
GHOST_ASSERT(m_displayManager, "GHOST_SystemCocoa::GHOST_SystemCocoa(): m_displayManager==0\n");
|
||||
m_displayManager->initialize();
|
||||
|
||||
//NSEvent timeStamp is given in system uptime, state start date is boot time
|
||||
//FIXME : replace by Cocoa equivalent
|
||||
int mib[2];
|
||||
struct timeval boottime;
|
||||
size_t len;
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_BOOTTIME;
|
||||
len = sizeof(struct timeval);
|
||||
|
||||
sysctl(mib, 2, &boottime, &len, NULL, 0);
|
||||
m_start_time = ((boottime.tv_sec*1000)+(boottime.tv_usec/1000));
|
||||
|
||||
m_ignoreWindowSizedMessages = false;
|
||||
}
|
||||
|
||||
GHOST_SystemCocoa::~GHOST_SystemCocoa()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::init()
|
||||
{
|
||||
|
||||
GHOST_TSuccess success = GHOST_System::init();
|
||||
if (success) {
|
||||
//ProcessSerialNumber psn;
|
||||
|
||||
//FIXME: Carbon stuff to move window & menu to foreground
|
||||
/*if (!GetCurrentProcess(&psn)) {
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
SetFrontProcess(&psn);
|
||||
}*/
|
||||
|
||||
autoReleasePool = [[NSAutoreleasePool alloc] init];
|
||||
if (NSApp == nil) {
|
||||
[NSApplication sharedApplication];
|
||||
|
||||
if ([NSApp mainMenu] == nil) {
|
||||
//FIXME: CreateApplicationMenus();
|
||||
printf("Creating main menu");
|
||||
}
|
||||
[NSApp finishLaunching];
|
||||
}
|
||||
if ([NSApp delegate] == nil) {
|
||||
[NSApp setDelegate:[[CocoaAppDelegate alloc] init]];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the cursor to the standard arrow shape (so that we can change it later on).
|
||||
* This initializes the cursor's visibility counter to 0.
|
||||
*/
|
||||
/*::InitCursor();
|
||||
|
||||
MenuRef windMenu;
|
||||
::CreateStandardWindowMenu(0, &windMenu);
|
||||
::InsertMenu(windMenu, 0);
|
||||
::DrawMenuBar();
|
||||
|
||||
::InstallApplicationEventHandler(sEventHandlerProc, GetEventTypeCount(kEvents), kEvents, this, &m_handler);
|
||||
|
||||
::AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, sAEHandlerLaunch, (SInt32) this, false);
|
||||
::AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, sAEHandlerOpenDocs, (SInt32) this, false);
|
||||
::AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, sAEHandlerPrintDocs, (SInt32) this, false);
|
||||
::AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, sAEHandlerQuit, (SInt32) this, false);
|
||||
*/
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::exit()
|
||||
{
|
||||
NSAutoreleasePool* pool = (NSAutoreleasePool *)autoReleasePool;
|
||||
[pool release];
|
||||
return GHOST_System::exit();
|
||||
}
|
||||
|
||||
#pragma mark window management
|
||||
|
||||
GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const
|
||||
{
|
||||
//FIXME : replace by Cocoa equivalent
|
||||
int mib[2];
|
||||
struct timeval boottime;
|
||||
size_t len;
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_BOOTTIME;
|
||||
len = sizeof(struct timeval);
|
||||
|
||||
sysctl(mib, 2, &boottime, &len, NULL, 0);
|
||||
|
||||
return ((boottime.tv_sec*1000)+(boottime.tv_usec/1000));
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const
|
||||
{
|
||||
//Note that OS X supports monitor hot plug
|
||||
// We do not support multiple monitors at the moment
|
||||
return [[NSScreen screens] count];
|
||||
}
|
||||
|
||||
|
||||
void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
|
||||
{
|
||||
//TODO: Provide visible frame or total frame, check for consistency with rest of code
|
||||
NSRect frame = [[NSScreen mainScreen] visibleFrame];
|
||||
|
||||
width = frame.size.width;
|
||||
height = frame.size.height;
|
||||
}
|
||||
|
||||
|
||||
GHOST_IWindow* GHOST_SystemCocoa::createWindow(
|
||||
const STR_String& title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_TDrawingContextType type,
|
||||
bool stereoVisual,
|
||||
const GHOST_TEmbedderWindowID parentWindow
|
||||
)
|
||||
{
|
||||
GHOST_IWindow* window = 0;
|
||||
|
||||
window = new GHOST_WindowCocoa (title, left, top, width, height, state, type);
|
||||
|
||||
if (window) {
|
||||
if (window->getValid()) {
|
||||
// Store the pointer to the window
|
||||
GHOST_ASSERT(m_windowManager, "m_windowManager not initialized");
|
||||
m_windowManager->addWindow(window);
|
||||
m_windowManager->setActiveWindow(window);
|
||||
pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
|
||||
}
|
||||
else {
|
||||
GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n");
|
||||
delete window;
|
||||
window = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n");
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
|
||||
//TODO: update this method
|
||||
// need yo make this Carbon all on 10.5 for fullscreen to work correctly
|
||||
CGCaptureAllDisplays();
|
||||
|
||||
success = GHOST_System::beginFullScreen( setting, window, stereoVisual);
|
||||
|
||||
if( success != GHOST_kSuccess ) {
|
||||
// fullscreen failed for other reasons, release
|
||||
CGReleaseAllDisplays();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void)
|
||||
{
|
||||
//TODO: update this method
|
||||
CGReleaseAllDisplays();
|
||||
return GHOST_System::endFullScreen();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
|
||||
{
|
||||
NSPoint mouseLoc = [NSEvent mouseLocation];
|
||||
|
||||
// Convert the coordinates to screen coordinates
|
||||
x = (GHOST_TInt32)mouseLoc.x;
|
||||
y = (GHOST_TInt32)mouseLoc.y;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const
|
||||
{
|
||||
float xf=(float)x, yf=(float)y;
|
||||
//TODO:cocoatize this
|
||||
CGAssociateMouseAndMouseCursorPosition(false);
|
||||
CGSetLocalEventsSuppressionInterval(0);
|
||||
CGWarpMouseCursorPosition(CGPointMake(xf, yf));
|
||||
CGAssociateMouseAndMouseCursorPosition(true);
|
||||
|
||||
//this doesn't work properly, see game engine mouse-look scripts
|
||||
// CGWarpMouseCursorPosition(CGPointMake(xf, yf));
|
||||
// this call below sends event, but empties other events (like shift)
|
||||
// CGPostMouseEvent(CGPointMake(xf, yf), TRUE, 1, FALSE, 0);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) const
|
||||
{
|
||||
NSUInteger modifiers = [[NSApp currentEvent] modifierFlags];
|
||||
//Direct query to modifierFlags can be used in 10.6
|
||||
|
||||
keys.set(GHOST_kModifierKeyCommand, (modifiers & NSCommandKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & NSAlternateKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftShift, (modifiers & NSShiftKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftControl, (modifiers & NSControlKeyMask) ? true : false);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const
|
||||
{
|
||||
buttons.clear();
|
||||
buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft);
|
||||
buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight);
|
||||
buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle);
|
||||
buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4);
|
||||
buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark Event handlers
|
||||
|
||||
/**
|
||||
* The event queue polling function
|
||||
*/
|
||||
bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
|
||||
{
|
||||
bool anyProcessed = false;
|
||||
NSEvent *event;
|
||||
|
||||
// SetMouseCoalescingEnabled(false, NULL);
|
||||
//TODO : implement timer ??
|
||||
|
||||
do {
|
||||
//GHOST_TimerManager* timerMgr = getTimerManager();
|
||||
/*
|
||||
if (waitForEvent) {
|
||||
GHOST_TUns64 next = timerMgr->nextFireTime();
|
||||
double timeOut;
|
||||
|
||||
if (next == GHOST_kFireTimeNever) {
|
||||
timeOut = kEventDurationForever;
|
||||
} else {
|
||||
timeOut = (double)(next - getMilliSeconds())/1000.0;
|
||||
if (timeOut < 0.0)
|
||||
timeOut = 0.0;
|
||||
}
|
||||
|
||||
::ReceiveNextEvent(0, NULL, timeOut, false, &event);
|
||||
}
|
||||
|
||||
if (timerMgr->fireTimers(getMilliSeconds())) {
|
||||
anyProcessed = true;
|
||||
}
|
||||
|
||||
//TODO: check fullscreen redrawing issues
|
||||
if (getFullScreen()) {
|
||||
// Check if the full-screen window is dirty
|
||||
GHOST_IWindow* window = m_windowManager->getFullScreenWindow();
|
||||
if (((GHOST_WindowCarbon*)window)->getFullScreenDirty()) {
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
|
||||
anyProcessed = true;
|
||||
}
|
||||
}*/
|
||||
|
||||
do {
|
||||
event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
if (event==nil)
|
||||
break;
|
||||
|
||||
anyProcessed = true;
|
||||
|
||||
switch ([event type]) {
|
||||
case NSKeyDown:
|
||||
case NSKeyUp:
|
||||
case NSFlagsChanged:
|
||||
handleKeyEvent(event);
|
||||
|
||||
/* Support system-wide keyboard shortcuts, like Exposé, ...) */
|
||||
/* if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged) {
|
||||
[NSApp sendEvent:event];
|
||||
}*/
|
||||
break;
|
||||
|
||||
case NSLeftMouseDown:
|
||||
case NSLeftMouseUp:
|
||||
case NSRightMouseDown:
|
||||
case NSRightMouseUp:
|
||||
case NSMouseMoved:
|
||||
case NSLeftMouseDragged:
|
||||
case NSRightMouseDragged:
|
||||
case NSScrollWheel:
|
||||
case NSOtherMouseDown:
|
||||
case NSOtherMouseUp:
|
||||
case NSOtherMouseDragged:
|
||||
handleMouseEvent(event);
|
||||
break;
|
||||
|
||||
case NSTabletPoint:
|
||||
case NSTabletProximity:
|
||||
handleTabletEvent(event);
|
||||
break;
|
||||
|
||||
/* Trackpad features, will need OS X 10.6 for implementation
|
||||
case NSEventTypeGesture:
|
||||
case NSEventTypeMagnify:
|
||||
case NSEventTypeSwipe:
|
||||
case NSEventTypeRotate:
|
||||
case NSEventTypeBeginGesture:
|
||||
case NSEventTypeEndGesture:
|
||||
break; */
|
||||
|
||||
/*Unused events
|
||||
NSMouseEntered = 8,
|
||||
NSMouseExited = 9,
|
||||
NSAppKitDefined = 13,
|
||||
NSSystemDefined = 14,
|
||||
NSApplicationDefined = 15,
|
||||
NSPeriodic = 16,
|
||||
NSCursorUpdate = 17,*/
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//Resend event to NSApp to ensure Mac wide events are handled
|
||||
[NSApp sendEvent:event];
|
||||
} while (event!= nil);
|
||||
} while (waitForEvent && !anyProcessed);
|
||||
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
//TODO: To be called from NSWindow delegate
|
||||
int GHOST_SystemCocoa::handleWindowEvent(void *eventPtr)
|
||||
{
|
||||
int err = eventNotHandledErr;
|
||||
/*WindowRef windowRef;
|
||||
GHOST_WindowCocoa *window;
|
||||
|
||||
// Check if the event was send to a GHOST window
|
||||
::GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &windowRef);
|
||||
window = (GHOST_WindowCarbon*) ::GetWRefCon(windowRef);
|
||||
if (!validWindow(window)) {
|
||||
return err;
|
||||
}
|
||||
|
||||
//if (!getFullScreen()) {
|
||||
err = noErr;
|
||||
switch([event ])
|
||||
{
|
||||
case kEventWindowClose:
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
|
||||
break;
|
||||
case kEventWindowActivated:
|
||||
m_windowManager->setActiveWindow(window);
|
||||
window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
|
||||
break;
|
||||
case kEventWindowDeactivated:
|
||||
m_windowManager->setWindowInactive(window);
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
|
||||
break;
|
||||
case kEventWindowUpdate:
|
||||
//if (getFullScreen()) GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen update event\n");
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
|
||||
break;
|
||||
case kEventWindowBoundsChanged:
|
||||
if (!m_ignoreWindowSizedMessages)
|
||||
{
|
||||
window->updateDrawingContext();
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
err = eventNotHandledErr;
|
||||
break;
|
||||
}
|
||||
// }
|
||||
//else {
|
||||
//window = (GHOST_WindowCarbon*) m_windowManager->getFullScreenWindow();
|
||||
//GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen window event, " << window << "\n");
|
||||
//::RemoveEventFromQueue(::GetMainEventQueue(), event);
|
||||
//}
|
||||
*/
|
||||
return err;
|
||||
}
|
||||
|
||||
int GHOST_SystemCocoa::handleTabletEvent(void *eventPtr)
|
||||
{
|
||||
NSEvent *event = (NSEvent *)eventPtr;
|
||||
GHOST_IWindow* window = m_windowManager->getActiveWindow();
|
||||
GHOST_TabletData& ct=((GHOST_WindowCocoa*)window)->GetCocoaTabletData();
|
||||
|
||||
ct.Pressure = 0;
|
||||
ct.Xtilt = 0;
|
||||
ct.Ytilt = 0;
|
||||
|
||||
|
||||
switch ([event type]) {
|
||||
case NSTabletPoint:
|
||||
ct.Pressure = [event tangentialPressure];
|
||||
ct.Xtilt = [event tilt].x;
|
||||
ct.Ytilt = [event tilt].y;
|
||||
break;
|
||||
|
||||
case NSTabletProximity:
|
||||
if ([event isEnteringProximity])
|
||||
{
|
||||
//pointer is entering tablet area proximity
|
||||
switch ([event pointingDeviceType]) {
|
||||
case NSPenPointingDevice:
|
||||
ct.Active = GHOST_kTabletModeStylus;
|
||||
break;
|
||||
case NSEraserPointingDevice:
|
||||
ct.Active = GHOST_kTabletModeEraser;
|
||||
break;
|
||||
case NSCursorPointingDevice:
|
||||
case NSUnknownPointingDevice:
|
||||
default:
|
||||
ct.Active = GHOST_kTabletModeNone;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// pointer is leaving - return to mouse
|
||||
ct.Active = GHOST_kTabletModeNone;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
GHOST_ASSERT(FALSE,"GHOST_SystemCocoa::handleTabletEvent : unknown event received");
|
||||
break;
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
int GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
|
||||
{
|
||||
NSEvent *event = (NSEvent *)eventPtr;
|
||||
GHOST_IWindow* window = m_windowManager->getActiveWindow();
|
||||
|
||||
switch ([event type])
|
||||
{
|
||||
//TODO: check for tablet subtype events
|
||||
case NSLeftMouseDown:
|
||||
case NSRightMouseDown:
|
||||
case NSOtherMouseDown:
|
||||
if (m_windowManager->getActiveWindow()) {
|
||||
pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonDown, window, convertButton([event buttonNumber])));
|
||||
}
|
||||
break;
|
||||
|
||||
case NSLeftMouseUp:
|
||||
case NSRightMouseUp:
|
||||
case NSOtherMouseUp:
|
||||
if (m_windowManager->getActiveWindow()) {
|
||||
pushEvent(new GHOST_EventButton([event timestamp], GHOST_kEventButtonUp, window, convertButton([event buttonNumber])));
|
||||
}
|
||||
break;
|
||||
|
||||
case NSMouseMoved:
|
||||
case NSLeftMouseDragged:
|
||||
case NSRightMouseDragged:
|
||||
case NSOtherMouseDragged:
|
||||
{
|
||||
NSPoint mousePos = [event locationInWindow];
|
||||
pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, mousePos.x, mousePos.y));
|
||||
break;
|
||||
}
|
||||
|
||||
case NSScrollWheel:
|
||||
{
|
||||
GHOST_TInt32 delta;
|
||||
delta = [event deltaY] > 0 ? 1 : -1;
|
||||
pushEvent(new GHOST_EventWheel(getMilliSeconds(), window, delta));
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
int GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
|
||||
{
|
||||
NSEvent *event = (NSEvent *)eventPtr;
|
||||
OSStatus err = eventNotHandledErr;
|
||||
GHOST_IWindow* window = m_windowManager->getActiveWindow();
|
||||
NSUInteger modifiers;
|
||||
unsigned short rawCode;
|
||||
GHOST_TKey key;
|
||||
unsigned char ascii;
|
||||
|
||||
/* Can happen, very rarely - seems to only be when command-H makes
|
||||
* the window go away and we still get an HKey up.
|
||||
*/
|
||||
if (!window) {
|
||||
//::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode);
|
||||
//key = convertKey(rawCode);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = noErr;
|
||||
switch ([event type]) {
|
||||
case NSKeyDown:
|
||||
case NSKeyUp:
|
||||
rawCode = [event keyCode];
|
||||
ascii = [[event characters] characterAtIndex:0];
|
||||
|
||||
key = convertKey(rawCode,ascii);
|
||||
ascii= convertRomanToLatin(ascii);
|
||||
|
||||
if ([event type] == NSKeyDown) {
|
||||
pushEvent( new GHOST_EventKey([event timestamp], GHOST_kEventKeyDown, window, key, ascii) );
|
||||
} else {
|
||||
pushEvent( new GHOST_EventKey([event timestamp], GHOST_kEventKeyUp, window, key, ascii) );
|
||||
}
|
||||
break;
|
||||
|
||||
case NSFlagsChanged:
|
||||
modifiers = [event modifierFlags];
|
||||
if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
|
||||
}
|
||||
if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
|
||||
}
|
||||
if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
|
||||
}
|
||||
if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) );
|
||||
}
|
||||
|
||||
m_modifierMask = modifiers;
|
||||
break;
|
||||
|
||||
default:
|
||||
err = eventNotHandledErr;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* System wide mouse clicks are handled directly through systematic event forwarding to Cocoa
|
||||
bool GHOST_SystemCarbon::handleMouseDown(void *eventPtr)
|
||||
{
|
||||
NSEvent *event = (NSEvent *)eventPtr;
|
||||
WindowPtr window;
|
||||
short part;
|
||||
BitMap screenBits;
|
||||
bool handled = true;
|
||||
GHOST_WindowCarbon* ghostWindow;
|
||||
Point mousePos = {0 , 0};
|
||||
|
||||
::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos);
|
||||
|
||||
part = ::FindWindow(mousePos, &window);
|
||||
ghostWindow = (GHOST_WindowCarbon*) ::GetWRefCon(window);
|
||||
|
||||
switch (part) {
|
||||
case inMenuBar:
|
||||
handleMenuCommand(::MenuSelect(mousePos));
|
||||
break;
|
||||
|
||||
case inDrag:
|
||||
// *
|
||||
// * The DragWindow() routine creates a lot of kEventWindowBoundsChanged
|
||||
// * events. By setting m_ignoreWindowSizedMessages these are suppressed.
|
||||
// * @see GHOST_SystemCarbon::handleWindowEvent(EventRef event)
|
||||
// *
|
||||
// even worse: scale window also generates a load of events, and nothing
|
||||
// is handled (read: client's event proc called) until you release mouse (ton)
|
||||
|
||||
GHOST_ASSERT(validWindow(ghostWindow), "GHOST_SystemCarbon::handleMouseDown: invalid window");
|
||||
m_ignoreWindowSizedMessages = true;
|
||||
::DragWindow(window, mousePos, &GetQDGlobalsScreenBits(&screenBits)->bounds);
|
||||
m_ignoreWindowSizedMessages = false;
|
||||
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, ghostWindow) );
|
||||
|
||||
break;
|
||||
|
||||
case inContent:
|
||||
if (window != ::FrontWindow()) {
|
||||
::SelectWindow(window);
|
||||
//
|
||||
// * We add a mouse down event on the newly actived window
|
||||
// *
|
||||
//GHOST_PRINT("GHOST_SystemCarbon::handleMouseDown(): adding mouse down event, " << ghostWindow << "\n");
|
||||
EventMouseButton button;
|
||||
::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button);
|
||||
pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonDown, ghostWindow, convertButton(button)));
|
||||
} else {
|
||||
handled = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case inGoAway:
|
||||
GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0");
|
||||
if (::TrackGoAway(window, mousePos))
|
||||
{
|
||||
// todo: add option-close, because itÿs in the HIG
|
||||
// if (event.modifiers & optionKey) {
|
||||
// Close the clean documents, others will be confirmed one by one.
|
||||
//}
|
||||
// else {
|
||||
pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, ghostWindow));
|
||||
//}
|
||||
}
|
||||
break;
|
||||
|
||||
case inGrow:
|
||||
GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0");
|
||||
::ResizeWindow(window, mousePos, NULL, NULL);
|
||||
break;
|
||||
|
||||
case inZoomIn:
|
||||
case inZoomOut:
|
||||
GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0");
|
||||
if (::TrackBox(window, mousePos, part)) {
|
||||
int macState;
|
||||
|
||||
macState = ghostWindow->getMac_windowState();
|
||||
if ( macState== 0)
|
||||
::ZoomWindow(window, part, true);
|
||||
else
|
||||
if (macState == 2) { // always ok
|
||||
::ZoomWindow(window, part, true);
|
||||
ghostWindow->setMac_windowState(1);
|
||||
} else { // need to force size again
|
||||
// GHOST_TUns32 scr_x,scr_y; //unused
|
||||
Rect outAvailableRect;
|
||||
|
||||
ghostWindow->setMac_windowState(2);
|
||||
::GetAvailableWindowPositioningBounds ( GetMainDevice(), &outAvailableRect);
|
||||
|
||||
//this->getMainDisplayDimensions(scr_x,scr_y);
|
||||
::SizeWindow (window, outAvailableRect.right-outAvailableRect.left,outAvailableRect.bottom-outAvailableRect.top-1,false);
|
||||
::MoveWindow (window, outAvailableRect.left, outAvailableRect.top,true);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_SystemCarbon::handleMenuCommand(GHOST_TInt32 menuResult)
|
||||
{
|
||||
short menuID;
|
||||
short menuItem;
|
||||
UInt32 command;
|
||||
bool handled;
|
||||
OSErr err;
|
||||
|
||||
menuID = HiWord(menuResult);
|
||||
menuItem = LoWord(menuResult);
|
||||
|
||||
err = ::GetMenuItemCommandID(::GetMenuHandle(menuID), menuItem, &command);
|
||||
|
||||
handled = false;
|
||||
|
||||
if (err || command == 0) {
|
||||
}
|
||||
else {
|
||||
switch(command) {
|
||||
}
|
||||
}
|
||||
|
||||
::HiliteMenu(0);
|
||||
return handled;
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
#pragma mark Clipboard get/set
|
||||
|
||||
GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const
|
||||
{
|
||||
GHOST_TUns8 * temp_buff;
|
||||
size_t pastedTextSize;
|
||||
|
||||
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
|
||||
|
||||
if (pasteBoard = nil) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSArray *supportedTypes =
|
||||
[NSArray arrayWithObjects: @"public.utf8-plain-text", nil];
|
||||
|
||||
NSString *bestType = [[NSPasteboard generalPasteboard]
|
||||
availableTypeFromArray:supportedTypes];
|
||||
|
||||
if (bestType == nil) { return NULL; }
|
||||
|
||||
NSString * textPasted = [pasteBoard stringForType:@"public.utf8-plain-text"];
|
||||
|
||||
pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1);
|
||||
|
||||
if (temp_buff == NULL) return NULL;
|
||||
|
||||
strncpy((char*)temp_buff, [textPasted UTF8String], pastedTextSize);
|
||||
|
||||
temp_buff[pastedTextSize] = '\0';
|
||||
|
||||
if(temp_buff) {
|
||||
return temp_buff;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const
|
||||
{
|
||||
NSString *textToCopy;
|
||||
|
||||
if(selection) {return;} // for copying the selection, used on X11
|
||||
|
||||
|
||||
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
|
||||
|
||||
if (pasteBoard = nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray *supportedTypes = [NSArray arrayWithObjects: @"public.utf8-plain-text",nil];
|
||||
|
||||
[pasteBoard declareTypes:supportedTypes owner:nil];
|
||||
|
||||
textToCopy = [NSString stringWithUTF8String:buffer];
|
||||
|
||||
[pasteBoard setString:textToCopy forType:@"public.utf8-plain-text"];
|
||||
|
||||
}
|
||||
|
||||
#pragma mark Carbon stuff to remove
|
||||
|
||||
#ifdef WITH_CARBON
|
||||
|
||||
|
||||
OSErr GHOST_SystemCarbon::sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
|
||||
{
|
||||
//GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSErr GHOST_SystemCarbon::sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
|
||||
{
|
||||
//GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
|
||||
AEDescList docs;
|
||||
SInt32 ndocs;
|
||||
OSErr err;
|
||||
|
||||
err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docs);
|
||||
if (err != noErr) return err;
|
||||
|
||||
err = AECountItems(&docs, &ndocs);
|
||||
if (err==noErr) {
|
||||
int i;
|
||||
|
||||
for (i=0; i<ndocs; i++) {
|
||||
FSSpec fss;
|
||||
AEKeyword kwd;
|
||||
DescType actType;
|
||||
Size actSize;
|
||||
|
||||
err = AEGetNthPtr(&docs, i+1, typeFSS, &kwd, &actType, &fss, sizeof(fss), &actSize);
|
||||
if (err!=noErr)
|
||||
break;
|
||||
|
||||
if (i==0) {
|
||||
FSRef fsref;
|
||||
|
||||
if (FSpMakeFSRef(&fss, &fsref)!=noErr)
|
||||
break;
|
||||
if (FSRefMakePath(&fsref, (UInt8*) g_firstFileBuf, sizeof(g_firstFileBuf))!=noErr)
|
||||
break;
|
||||
|
||||
g_hasFirstFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AEDisposeDesc(&docs);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
OSErr GHOST_SystemCarbon::sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
|
||||
{
|
||||
//GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSErr GHOST_SystemCarbon::sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon)
|
||||
{
|
||||
GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon;
|
||||
|
||||
sys->pushEvent( new GHOST_Event(sys->getMilliSeconds(), GHOST_kEventQuit, NULL) );
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
OSStatus GHOST_SystemCarbon::sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData)
|
||||
{
|
||||
GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) userData;
|
||||
OSStatus err = eventNotHandledErr;
|
||||
GHOST_IWindow* window;
|
||||
GHOST_TEventNDOFData data;
|
||||
UInt32 kind;
|
||||
|
||||
switch (::GetEventClass(event))
|
||||
{
|
||||
case kEventClassAppleEvent:
|
||||
EventRecord eventrec;
|
||||
if (ConvertEventRefToEventRecord(event, &eventrec)) {
|
||||
err = AEProcessAppleEvent(&eventrec);
|
||||
}
|
||||
break;
|
||||
case kEventClassMouse:
|
||||
err = sys->handleMouseEvent(event);
|
||||
break;
|
||||
case kEventClassWindow:
|
||||
err = sys->handleWindowEvent(event);
|
||||
break;
|
||||
case kEventClassKeyboard:
|
||||
err = sys->handleKeyEvent(event);
|
||||
break;
|
||||
case kEventClassBlender :
|
||||
window = sys->m_windowManager->getActiveWindow();
|
||||
sys->m_ndofManager->GHOST_NDOFGetDatas(data);
|
||||
kind = ::GetEventKind(event);
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case 1:
|
||||
sys->m_eventManager->pushEvent(new GHOST_EventNDOF(sys->getMilliSeconds(), GHOST_kEventNDOFMotion, window, data));
|
||||
// printf("motion\n");
|
||||
break;
|
||||
case 2:
|
||||
sys->m_eventManager->pushEvent(new GHOST_EventNDOF(sys->getMilliSeconds(), GHOST_kEventNDOFButton, window, data));
|
||||
// printf("button\n");
|
||||
break;
|
||||
}
|
||||
err = noErr;
|
||||
break;
|
||||
default :
|
||||
;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
308
intern/ghost/intern/GHOST_WindowCocoa.h
Normal file
308
intern/ghost/intern/GHOST_WindowCocoa.h
Normal file
@@ -0,0 +1,308 @@
|
||||
/**
|
||||
* $Id: GHOST_WindowCocoa.h 13161 2008-01-07 19:13:47Z hos $
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
/**
|
||||
* @file GHOST_WindowCocoa.h
|
||||
* Declaration of GHOST_WindowCocoa class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_WINDOW_COCOA_H_
|
||||
#define _GHOST_WINDOW_COCOA_H_
|
||||
|
||||
#ifndef __APPLE__
|
||||
#error Apple OSX only!
|
||||
#endif // __APPLE__
|
||||
|
||||
#include "GHOST_Window.h"
|
||||
#include "STR_String.h"
|
||||
|
||||
#include <AGL/agl.h>
|
||||
|
||||
|
||||
/**
|
||||
* Window on Mac OSX/Cocoa.
|
||||
* Carbon windows have a size widget in the lower right corner of the window.
|
||||
* To force it to be visible, the height of the client rectangle is reduced so
|
||||
* that applications do not draw in that area. GHOST will manage that area
|
||||
* which is called the gutter.
|
||||
* When OpenGL contexts are active, GHOST will use AGL_BUFFER_RECT to prevent
|
||||
* OpenGL drawing outside the reduced client rectangle.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 23, 2001
|
||||
*/
|
||||
class GHOST_WindowCocoa : public GHOST_Window {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* Creates a new window and opens it.
|
||||
* To check if the window was created properly, use the getValid() method.
|
||||
* @param title The text shown in the title bar of the window.
|
||||
* @param left The coordinate of the left edge of the window.
|
||||
* @param top The coordinate of the top edge of the window.
|
||||
* @param width The width the window.
|
||||
* @param height The height the window.
|
||||
* @param state The state the window is initially opened with.
|
||||
* @param type The type of drawing context installed in this window.
|
||||
* @param stereoVisual Stereo visual for quad buffered stereo.
|
||||
*/
|
||||
GHOST_WindowCocoa(
|
||||
const STR_String& title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
|
||||
const bool stereoVisual = false
|
||||
);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* Closes the window and disposes resources allocated.
|
||||
*/
|
||||
virtual ~GHOST_WindowCocoa();
|
||||
|
||||
/**
|
||||
* Returns indication as to whether the window is valid.
|
||||
* @return The validity of the window.
|
||||
*/
|
||||
virtual bool getValid() const;
|
||||
|
||||
/**
|
||||
* Sets the title displayed in the title bar.
|
||||
* @param title The title to display in the title bar.
|
||||
*/
|
||||
virtual void setTitle(const STR_String& title);
|
||||
|
||||
/**
|
||||
* Returns the title displayed in the title bar.
|
||||
* @param title The title displayed in the title bar.
|
||||
*/
|
||||
virtual void getTitle(STR_String& title) const;
|
||||
|
||||
/**
|
||||
* Returns the window rectangle dimensions.
|
||||
* The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
|
||||
* @param bounds The bounding rectangle of the window.
|
||||
*/
|
||||
virtual void getWindowBounds(GHOST_Rect& bounds) const;
|
||||
|
||||
/**
|
||||
* Returns the client rectangle dimensions.
|
||||
* The left and top members of the rectangle are always zero.
|
||||
* @param bounds The bounding rectangle of the cleient area of the window.
|
||||
*/
|
||||
virtual void getClientBounds(GHOST_Rect& bounds) const;
|
||||
|
||||
/**
|
||||
* Resizes client rectangle width.
|
||||
* @param width The new width of the client area of the window.
|
||||
*/
|
||||
virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width);
|
||||
|
||||
/**
|
||||
* Resizes client rectangle height.
|
||||
* @param height The new height of the client area of the window.
|
||||
*/
|
||||
virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height);
|
||||
|
||||
/**
|
||||
* Resizes client rectangle.
|
||||
* @param width The new width of the client area of the window.
|
||||
* @param height The new height of the client area of the window.
|
||||
*/
|
||||
virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height);
|
||||
|
||||
/**
|
||||
* Returns the state of the window (normal, minimized, maximized).
|
||||
* @return The state of the window.
|
||||
*/
|
||||
virtual GHOST_TWindowState getState() const;
|
||||
|
||||
/**
|
||||
* Converts a point in screen coordinates to client rectangle coordinates
|
||||
* @param inX The x-coordinate on the screen.
|
||||
* @param inY The y-coordinate on the screen.
|
||||
* @param outX The x-coordinate in the client rectangle.
|
||||
* @param outY The y-coordinate in the client rectangle.
|
||||
*/
|
||||
virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
|
||||
|
||||
/**
|
||||
* Converts a point in screen coordinates to client rectangle coordinates
|
||||
* @param inX The x-coordinate in the client rectangle.
|
||||
* @param inY The y-coordinate in the client rectangle.
|
||||
* @param outX The x-coordinate on the screen.
|
||||
* @param outY The y-coordinate on the screen.
|
||||
*/
|
||||
virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const;
|
||||
|
||||
/**
|
||||
* Sets the state of the window (normal, minimized, maximized).
|
||||
* @param state The state of the window.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setState(GHOST_TWindowState state);
|
||||
|
||||
/**
|
||||
* Sets the order of the window (bottom, top).
|
||||
* @param order The order of the window.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order);
|
||||
|
||||
/**
|
||||
* Swaps front and back buffers of a window.
|
||||
* @return A boolean success indicator.
|
||||
*/
|
||||
virtual GHOST_TSuccess swapBuffers();
|
||||
|
||||
/**
|
||||
* Updates the drawing context of this window. Needed
|
||||
* whenever the window is changed.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
GHOST_TSuccess updateDrawingContext();
|
||||
|
||||
/**
|
||||
* Activates the drawing context of this window.
|
||||
* @return A boolean success indicator.
|
||||
*/
|
||||
virtual GHOST_TSuccess activateDrawingContext();
|
||||
|
||||
virtual void loadCursor(bool visible, GHOST_TStandardCursor cursor) const;
|
||||
|
||||
/**
|
||||
* Returns the dirty state of the window when in full-screen mode.
|
||||
* @return Whether it is dirty.
|
||||
*/
|
||||
virtual bool getFullScreenDirty();
|
||||
|
||||
/* accessor for fullscreen window */
|
||||
virtual void setMac_windowState(short value);
|
||||
virtual short getMac_windowState();
|
||||
|
||||
|
||||
const GHOST_TabletData* GetTabletData()
|
||||
{ return &m_tablet; }
|
||||
|
||||
GHOST_TabletData& GetCocoaTabletData()
|
||||
{ return m_tablet; }
|
||||
protected:
|
||||
/**
|
||||
* Tries to install a rendering context in this window.
|
||||
* @param type The type of rendering context installed.
|
||||
* @return Indication as to whether installation has succeeded.
|
||||
*/
|
||||
virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type);
|
||||
|
||||
/**
|
||||
* Removes the current drawing context.
|
||||
* @return Indication as to whether removal has succeeded.
|
||||
*/
|
||||
virtual GHOST_TSuccess removeDrawingContext();
|
||||
|
||||
/**
|
||||
* Invalidates the contents of this window.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess invalidate();
|
||||
|
||||
/**
|
||||
* Sets the cursor visibility on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
|
||||
|
||||
/**
|
||||
* Sets the cursor shape on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape);
|
||||
|
||||
/**
|
||||
* Sets the cursor shape on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
|
||||
int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color);
|
||||
|
||||
virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY);
|
||||
|
||||
/**
|
||||
* Converts a string object to a Mac Pascal string.
|
||||
* @param in The string object to be converted.
|
||||
* @param out The converted string.
|
||||
*/
|
||||
virtual void gen2mac(const STR_String& in, Str255 out) const;
|
||||
|
||||
/**
|
||||
* Converts a Mac Pascal string to a string object.
|
||||
* @param in The string to be converted.
|
||||
* @param out The converted string object.
|
||||
*/
|
||||
virtual void mac2gen(const Str255 in, STR_String& out) const;
|
||||
|
||||
WindowRef m_windowRef;
|
||||
CGrafPtr m_grafPtr;
|
||||
AGLContext m_aglCtx;
|
||||
|
||||
/** The first created OpenGL context (for sharing display lists) */
|
||||
static AGLContext s_firstaglCtx;
|
||||
|
||||
Cursor* m_customCursor;
|
||||
|
||||
GHOST_TabletData m_tablet;
|
||||
|
||||
/** When running in full-screen this tells whether to refresh the window. */
|
||||
bool m_fullScreenDirty;
|
||||
|
||||
/** specific MacOs X full screen window setting as we use partially system mechanism
|
||||
values : 0 not maximizable default
|
||||
1 normal state
|
||||
2 maximized state
|
||||
|
||||
this will be reworked when rebuilding GHOST carbon to use new OS X apis
|
||||
in order to be unified with GHOST fullscreen/maximised settings
|
||||
|
||||
(lukep)
|
||||
**/
|
||||
|
||||
short mac_windowState;
|
||||
|
||||
|
||||
/**
|
||||
* The width/height of the size rectangle in the lower right corner of a
|
||||
* Mac/Carbon window. This is also the height of the gutter area.
|
||||
*/
|
||||
#ifdef GHOST_DRAW_CARBON_GUTTER
|
||||
static const GHOST_TInt32 s_sizeRectSize;
|
||||
#endif // GHOST_DRAW_CARBON_GUTTER
|
||||
};
|
||||
|
||||
#endif // _GHOST_WINDOW_COCOA_H_
|
||||
|
||||
747
intern/ghost/intern/GHOST_WindowCocoa.mm
Normal file
747
intern/ghost/intern/GHOST_WindowCocoa.mm
Normal file
@@ -0,0 +1,747 @@
|
||||
/**
|
||||
* $Id: GHOST_WindowCocoa.mm 23275 2009-09-16 15:55:00Z campbellbarton $
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
* $Id: GHOST_WindowCocoa.mm 23275 2009-09-16 15:55:00Z campbellbarton $
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 10, 2001
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include "GHOST_WindowCocoa.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
AGLContext GHOST_WindowCocoa::s_firstaglCtx = NULL;
|
||||
#ifdef GHOST_DRAW_CARBON_GUTTER
|
||||
const GHOST_TInt32 GHOST_WindowCocoa::s_sizeRectSize = 16;
|
||||
#endif //GHOST_DRAW_CARBON_GUTTER
|
||||
|
||||
static const GLint sPreferredFormatWindow[8] = {
|
||||
AGL_RGBA,
|
||||
AGL_DOUBLEBUFFER,
|
||||
AGL_ACCELERATED,
|
||||
AGL_DEPTH_SIZE, 32,
|
||||
AGL_NONE,
|
||||
};
|
||||
|
||||
static const GLint sPreferredFormatFullScreen[9] = {
|
||||
AGL_RGBA,
|
||||
AGL_DOUBLEBUFFER,
|
||||
AGL_ACCELERATED,
|
||||
AGL_FULLSCREEN,
|
||||
AGL_DEPTH_SIZE, 32,
|
||||
AGL_NONE,
|
||||
};
|
||||
|
||||
|
||||
|
||||
WindowRef ugly_hack=NULL;
|
||||
|
||||
const EventTypeSpec kWEvents[] = {
|
||||
{ kEventClassWindow, kEventWindowZoom }, /* for new zoom behaviour */
|
||||
};
|
||||
|
||||
static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData) {
|
||||
WindowRef mywindow;
|
||||
GHOST_WindowCocoa *ghost_window;
|
||||
OSStatus err;
|
||||
int theState;
|
||||
|
||||
if (::GetEventKind(event) == kEventWindowZoom) {
|
||||
err = ::GetEventParameter (event,kEventParamDirectObject,typeWindowRef,NULL,sizeof(mywindow),NULL, &mywindow);
|
||||
ghost_window = (GHOST_WindowCocoa *) GetWRefCon(mywindow);
|
||||
theState = ghost_window->getMac_windowState();
|
||||
if (theState == 1)
|
||||
ghost_window->setMac_windowState(2);
|
||||
else if (theState == 2)
|
||||
ghost_window->setMac_windowState(1);
|
||||
|
||||
}
|
||||
return eventNotHandledErr;
|
||||
}
|
||||
|
||||
GHOST_WindowCocoa::GHOST_WindowCocoa(
|
||||
const STR_String& title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_TDrawingContextType type,
|
||||
const bool stereoVisual
|
||||
) :
|
||||
GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone),
|
||||
m_windowRef(0),
|
||||
m_grafPtr(0),
|
||||
m_aglCtx(0),
|
||||
m_customCursor(0),
|
||||
m_fullScreenDirty(false)
|
||||
{
|
||||
Str255 title255;
|
||||
OSStatus err;
|
||||
|
||||
//fprintf(stderr," main screen top %i left %i height %i width %i\n", top, left, height, width);
|
||||
|
||||
if (state >= GHOST_kWindowState8Normal ) {
|
||||
if(state == GHOST_kWindowState8Normal) state= GHOST_kWindowStateNormal;
|
||||
else if(state == GHOST_kWindowState8Maximized) state= GHOST_kWindowStateMaximized;
|
||||
else if(state == GHOST_kWindowState8Minimized) state= GHOST_kWindowStateMinimized;
|
||||
else if(state == GHOST_kWindowState8FullScreen) state= GHOST_kWindowStateFullScreen;
|
||||
|
||||
// state = state - 8; this was the simple version of above code, doesnt work in gcc 4.0
|
||||
|
||||
setMac_windowState(1);
|
||||
} else
|
||||
setMac_windowState(0);
|
||||
|
||||
if (state != GHOST_kWindowStateFullScreen) {
|
||||
Rect bnds = { top, left, top+height, left+width };
|
||||
// Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); /*unused*/
|
||||
gen2mac(title, title255);
|
||||
|
||||
err = ::CreateNewWindow( kDocumentWindowClass,
|
||||
kWindowStandardDocumentAttributes+kWindowLiveResizeAttribute,
|
||||
&bnds,
|
||||
&m_windowRef);
|
||||
|
||||
if ( err != noErr) {
|
||||
fprintf(stderr," error creating window %i \n",err);
|
||||
} else {
|
||||
|
||||
::SetWRefCon(m_windowRef,(SInt32)this);
|
||||
setTitle(title);
|
||||
err = InstallWindowEventHandler (m_windowRef, myWEventHandlerProc, GetEventTypeCount(kWEvents), kWEvents,NULL,NULL);
|
||||
if ( err != noErr) {
|
||||
fprintf(stderr," error creating handler %i \n",err);
|
||||
} else {
|
||||
// ::TransitionWindow (m_windowRef,kWindowZoomTransitionEffect,kWindowShowTransitionAction,NULL);
|
||||
::ShowWindow(m_windowRef);
|
||||
::MoveWindow (m_windowRef, left, top,true);
|
||||
|
||||
}
|
||||
}
|
||||
if (m_windowRef) {
|
||||
m_grafPtr = ::GetWindowPort(m_windowRef);
|
||||
setDrawingContextType(type);
|
||||
updateDrawingContext();
|
||||
activateDrawingContext();
|
||||
}
|
||||
if(ugly_hack==NULL) {
|
||||
ugly_hack= m_windowRef;
|
||||
// when started from commandline, window remains in the back... also for play anim
|
||||
ProcessSerialNumber psn;
|
||||
GetCurrentProcess(&psn);
|
||||
SetFrontProcess(&psn);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
Rect bnds = { top, left, top+height, left+width };
|
||||
gen2mac("", title255);
|
||||
m_windowRef = ::NewCWindow(
|
||||
nil, // Storage
|
||||
&bnds, // Bounding rectangle of the window
|
||||
title255, // Title of the window
|
||||
0, // Window initially visible
|
||||
plainDBox, // procID
|
||||
(WindowRef)-1L, // Put window before all other windows
|
||||
0, // Window has minimize box
|
||||
(SInt32)this); // Store a pointer to the class in the refCon
|
||||
*/
|
||||
//GHOST_PRINT("GHOST_WindowCocoa::GHOST_WindowCocoa(): creating full-screen OpenGL context\n");
|
||||
setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);;installDrawingContext(GHOST_kDrawingContextTypeOpenGL);
|
||||
updateDrawingContext();
|
||||
activateDrawingContext();
|
||||
|
||||
m_tablet.Active = GHOST_kTabletModeNone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_WindowCocoa::~GHOST_WindowCocoa()
|
||||
{
|
||||
if (m_customCursor) delete m_customCursor;
|
||||
|
||||
if(ugly_hack==m_windowRef) ugly_hack= NULL;
|
||||
|
||||
// printf("GHOST_WindowCocoa::~GHOST_WindowCocoa(): removing drawing context\n");
|
||||
if(ugly_hack==NULL) setDrawingContextType(GHOST_kDrawingContextTypeNone);
|
||||
if (m_windowRef) {
|
||||
::DisposeWindow(m_windowRef);
|
||||
m_windowRef = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool GHOST_WindowCocoa::getValid() const
|
||||
{
|
||||
bool valid;
|
||||
if (!m_fullScreen) {
|
||||
valid = (m_windowRef != 0) && (m_grafPtr != 0) && ::IsValidWindowPtr(m_windowRef);
|
||||
}
|
||||
else {
|
||||
valid = true;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::setTitle(const STR_String& title)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid")
|
||||
Str255 title255;
|
||||
gen2mac(title, title255);
|
||||
::SetWTitle(m_windowRef, title255);
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::getTitle(STR_String& title) const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid")
|
||||
Str255 title255;
|
||||
::GetWTitle(m_windowRef, title255);
|
||||
mac2gen(title255, title);
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const
|
||||
{
|
||||
OSStatus success;
|
||||
Rect rect;
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid")
|
||||
success = ::GetWindowBounds(m_windowRef, kWindowStructureRgn, &rect);
|
||||
bounds.m_b = rect.bottom;
|
||||
bounds.m_l = rect.left;
|
||||
bounds.m_r = rect.right;
|
||||
bounds.m_t = rect.top;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const
|
||||
{
|
||||
Rect rect;
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid")
|
||||
//::GetPortBounds(m_grafPtr, &rect);
|
||||
::GetWindowBounds(m_windowRef, kWindowContentRgn, &rect);
|
||||
|
||||
bounds.m_b = rect.bottom;
|
||||
bounds.m_l = rect.left;
|
||||
bounds.m_r = rect.right;
|
||||
bounds.m_t = rect.top;
|
||||
|
||||
// Subtract gutter height from bottom
|
||||
#ifdef GHOST_DRAW_CARBON_GUTTER
|
||||
if ((bounds.m_b - bounds.m_t) > s_sizeRectSize)
|
||||
{
|
||||
bounds.m_b -= s_sizeRectSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
bounds.m_t = bounds.m_b;
|
||||
}
|
||||
#endif //GHOST_DRAW_CARBON_GUTTER
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid")
|
||||
GHOST_Rect cBnds, wBnds;
|
||||
getClientBounds(cBnds);
|
||||
if (((GHOST_TUns32)cBnds.getWidth()) != width) {
|
||||
::SizeWindow(m_windowRef, width, cBnds.getHeight(), true);
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid")
|
||||
GHOST_Rect cBnds, wBnds;
|
||||
getClientBounds(cBnds);
|
||||
#ifdef GHOST_DRAW_CARBON_GUTTER
|
||||
if (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize) {
|
||||
::SizeWindow(m_windowRef, cBnds.getWidth(), height+s_sizeRectSize, true);
|
||||
}
|
||||
#else //GHOST_DRAW_CARBON_GUTTER
|
||||
if (((GHOST_TUns32)cBnds.getHeight()) != height) {
|
||||
::SizeWindow(m_windowRef, cBnds.getWidth(), height, true);
|
||||
}
|
||||
#endif //GHOST_DRAW_CARBON_GUTTER
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid")
|
||||
GHOST_Rect cBnds, wBnds;
|
||||
getClientBounds(cBnds);
|
||||
#ifdef GHOST_DRAW_CARBON_GUTTER
|
||||
if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
|
||||
(((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize)) {
|
||||
::SizeWindow(m_windowRef, width, height+s_sizeRectSize, true);
|
||||
}
|
||||
#else //GHOST_DRAW_CARBON_GUTTER
|
||||
if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
|
||||
(((GHOST_TUns32)cBnds.getHeight()) != height)) {
|
||||
::SizeWindow(m_windowRef, width, height, true);
|
||||
}
|
||||
#endif //GHOST_DRAW_CARBON_GUTTER
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TWindowState GHOST_WindowCocoa::getState() const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid")
|
||||
GHOST_TWindowState state;
|
||||
if (::IsWindowVisible(m_windowRef) == false) {
|
||||
state = GHOST_kWindowStateMinimized;
|
||||
}
|
||||
else if (::IsWindowInStandardState(m_windowRef, nil, nil)) {
|
||||
state = GHOST_kWindowStateMaximized;
|
||||
}
|
||||
else {
|
||||
state = GHOST_kWindowStateNormal;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid")
|
||||
Point point;
|
||||
point.h = inX;
|
||||
point.v = inY;
|
||||
GrafPtr oldPort;
|
||||
::GetPort(&oldPort);
|
||||
::SetPort(m_grafPtr);
|
||||
::GlobalToLocal(&point);
|
||||
::SetPort(oldPort);
|
||||
outX = point.h;
|
||||
outY = point.v;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid")
|
||||
Point point;
|
||||
point.h = inX;
|
||||
point.v = inY;
|
||||
GrafPtr oldPort;
|
||||
::GetPort(&oldPort);
|
||||
::SetPort(m_grafPtr);
|
||||
::LocalToGlobal(&point);
|
||||
::SetPort(oldPort);
|
||||
outX = point.h;
|
||||
outY = point.v;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid")
|
||||
switch (state) {
|
||||
case GHOST_kWindowStateMinimized:
|
||||
::HideWindow(m_windowRef);
|
||||
break;
|
||||
case GHOST_kWindowStateModified:
|
||||
SetWindowModified(m_windowRef, 1);
|
||||
break;
|
||||
case GHOST_kWindowStateUnModified:
|
||||
SetWindowModified(m_windowRef, 0);
|
||||
break;
|
||||
case GHOST_kWindowStateMaximized:
|
||||
case GHOST_kWindowStateNormal:
|
||||
default:
|
||||
::ShowWindow(m_windowRef);
|
||||
break;
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid")
|
||||
if (order == GHOST_kWindowOrderTop) {
|
||||
//::BringToFront(m_windowRef); is wrong, front window should be active for input too
|
||||
::SelectWindow(m_windowRef);
|
||||
}
|
||||
else {
|
||||
/* doesnt work if you do this with a mouseclick */
|
||||
::SendBehind(m_windowRef, nil);
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
/*#define WAIT_FOR_VSYNC 1*/
|
||||
#ifdef WAIT_FOR_VSYNC
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#endif
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::swapBuffers()
|
||||
{
|
||||
#ifdef WAIT_FOR_VSYNC
|
||||
/* wait for vsync, to avoid tearing artifacts */
|
||||
long VBL = 1;
|
||||
CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL);
|
||||
#endif
|
||||
|
||||
GHOST_TSuccess succeeded = GHOST_kSuccess;
|
||||
if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
|
||||
if (m_aglCtx) {
|
||||
::aglSwapBuffers(m_aglCtx);
|
||||
}
|
||||
else {
|
||||
succeeded = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext()
|
||||
{
|
||||
GHOST_TSuccess succeeded = GHOST_kSuccess;
|
||||
if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
|
||||
if (m_aglCtx) {
|
||||
::aglUpdateContext(m_aglCtx);
|
||||
}
|
||||
else {
|
||||
succeeded = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
|
||||
{
|
||||
GHOST_TSuccess succeeded = GHOST_kSuccess;
|
||||
if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
|
||||
if (m_aglCtx) {
|
||||
::aglSetCurrentContext(m_aglCtx);
|
||||
#ifdef GHOST_DRAW_CARBON_GUTTER
|
||||
// Restrict drawing to non-gutter area
|
||||
::aglEnable(m_aglCtx, AGL_BUFFER_RECT);
|
||||
GHOST_Rect bnds;
|
||||
getClientBounds(bnds);
|
||||
GLint b[4] =
|
||||
{
|
||||
bnds.m_l,
|
||||
bnds.m_t+s_sizeRectSize,
|
||||
bnds.m_r-bnds.m_l,
|
||||
bnds.m_b-bnds.m_t
|
||||
};
|
||||
GLboolean result = ::aglSetInteger(m_aglCtx, AGL_BUFFER_RECT, b);
|
||||
#endif //GHOST_DRAW_CARBON_GUTTER
|
||||
}
|
||||
else {
|
||||
succeeded = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
switch (type) {
|
||||
case GHOST_kDrawingContextTypeOpenGL:
|
||||
{
|
||||
if (!getValid()) break;
|
||||
|
||||
AGLPixelFormat pixelFormat;
|
||||
if (!m_fullScreen) {
|
||||
pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatWindow);
|
||||
m_aglCtx = ::aglCreateContext(pixelFormat, s_firstaglCtx);
|
||||
if (!m_aglCtx) break;
|
||||
if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx;
|
||||
success = ::aglSetDrawable(m_aglCtx, m_grafPtr) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
//GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): init full-screen OpenGL\n");
|
||||
GDHandle device=::GetMainDevice();pixelFormat=::aglChoosePixelFormat(&device,1,sPreferredFormatFullScreen);
|
||||
m_aglCtx = ::aglCreateContext(pixelFormat, 0);
|
||||
if (!m_aglCtx) break;
|
||||
if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx;
|
||||
//GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): created OpenGL context\n");
|
||||
//::CGGetActiveDisplayList(0, NULL, &m_numDisplays)
|
||||
success = ::aglSetFullScreen(m_aglCtx, m_fullScreenWidth, m_fullScreenHeight, 75, 0) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
/*
|
||||
if (success == GHOST_kSuccess) {
|
||||
GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): init full-screen OpenGL succeeded\n");
|
||||
}
|
||||
else {
|
||||
GHOST_PRINT("GHOST_WindowCocoa::installDrawingContext(): init full-screen OpenGL failed\n");
|
||||
}
|
||||
*/
|
||||
}
|
||||
::aglDestroyPixelFormat(pixelFormat);
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kDrawingContextTypeNone:
|
||||
success = GHOST_kSuccess;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext()
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
switch (m_drawingContextType) {
|
||||
case GHOST_kDrawingContextTypeOpenGL:
|
||||
if (m_aglCtx) {
|
||||
aglSetCurrentContext(NULL);
|
||||
aglSetDrawable(m_aglCtx, NULL);
|
||||
//aglDestroyContext(m_aglCtx);
|
||||
if (s_firstaglCtx == m_aglCtx) s_firstaglCtx = NULL;
|
||||
success = ::aglDestroyContext(m_aglCtx) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
m_aglCtx = 0;
|
||||
}
|
||||
break;
|
||||
case GHOST_kDrawingContextTypeNone:
|
||||
success = GHOST_kSuccess;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::invalidate()
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid")
|
||||
if (!m_fullScreen) {
|
||||
Rect rect;
|
||||
::GetPortBounds(m_grafPtr, &rect);
|
||||
::InvalWindowRect(m_windowRef, &rect);
|
||||
}
|
||||
else {
|
||||
//EventRef event;
|
||||
//OSStatus status = ::CreateEvent(NULL, kEventClassWindow, kEventWindowUpdate, 0, 0, &event);
|
||||
//GHOST_PRINT("GHOST_WindowCocoa::invalidate(): created event " << status << " \n");
|
||||
//status = ::SetEventParameter(event, kEventParamDirectObject, typeWindowRef, sizeof(WindowRef), this);
|
||||
//GHOST_PRINT("GHOST_WindowCocoa::invalidate(): set event parameter " << status << " \n");
|
||||
//status = ::PostEventToQueue(::GetMainEventQueue(), event, kEventPriorityStandard);
|
||||
//status = ::SendEventToEventTarget(event, ::GetApplicationEventTarget());
|
||||
//GHOST_PRINT("GHOST_WindowCocoa::invalidate(): added event to queue " << status << " \n");
|
||||
m_fullScreenDirty = true;
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::gen2mac(const STR_String& in, Str255 out) const
|
||||
{
|
||||
STR_String tempStr = in;
|
||||
int num = tempStr.Length();
|
||||
if (num > 255) num = 255;
|
||||
::memcpy(out+1, tempStr.Ptr(), num);
|
||||
out[0] = num;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::mac2gen(const Str255 in, STR_String& out) const
|
||||
{
|
||||
char tmp[256];
|
||||
::memcpy(tmp, in+1, in[0]);
|
||||
tmp[in[0]] = '\0';
|
||||
out = tmp;
|
||||
}
|
||||
|
||||
void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
|
||||
{
|
||||
static bool systemCursorVisible = true;
|
||||
|
||||
if (visible != systemCursorVisible) {
|
||||
if (visible) {
|
||||
::ShowCursor();
|
||||
systemCursorVisible = true;
|
||||
}
|
||||
else {
|
||||
::HideCursor();
|
||||
systemCursorVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
|
||||
::SetCursor( m_customCursor );
|
||||
} else {
|
||||
int carbon_cursor;
|
||||
|
||||
#define GCMAP(ghostCursor, carbonCursor) case ghostCursor: carbon_cursor = carbonCursor; break
|
||||
switch (cursor) {
|
||||
default:
|
||||
GCMAP( GHOST_kStandardCursorDefault, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorRightArrow, kThemeAliasArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorLeftArrow, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorInfo, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorDestroy, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorHelp, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorCycle, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorSpray, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorWait, kThemeWatchCursor);
|
||||
GCMAP( GHOST_kStandardCursorText, kThemeIBeamCursor);
|
||||
GCMAP( GHOST_kStandardCursorCrosshair, kThemeCrossCursor);
|
||||
GCMAP( GHOST_kStandardCursorUpDown, kThemeClosedHandCursor);
|
||||
GCMAP( GHOST_kStandardCursorLeftRight, kThemeClosedHandCursor);
|
||||
GCMAP( GHOST_kStandardCursorTopSide, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorBottomSide, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorLeftSide, kThemeResizeLeftCursor);
|
||||
GCMAP( GHOST_kStandardCursorRightSide, kThemeResizeRightCursor);
|
||||
GCMAP( GHOST_kStandardCursorTopLeftCorner, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorTopRightCorner, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorBottomRightCorner, kThemeArrowCursor);
|
||||
GCMAP( GHOST_kStandardCursorBottomLeftCorner, kThemeArrowCursor);
|
||||
};
|
||||
#undef GCMAP
|
||||
|
||||
::SetThemeCursor(carbon_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_WindowCocoa::getFullScreenDirty()
|
||||
{
|
||||
return m_fullScreen && m_fullScreenDirty;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
|
||||
{
|
||||
if (::FrontWindow() == m_windowRef) {
|
||||
loadCursor(visible, getCursorShape());
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
|
||||
{
|
||||
if (m_customCursor) {
|
||||
delete m_customCursor;
|
||||
m_customCursor = 0;
|
||||
}
|
||||
|
||||
if (::FrontWindow() == m_windowRef) {
|
||||
loadCursor(getCursorVisibility(), shape);
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Reverse the bits in a GHOST_TUns8 */
|
||||
static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
|
||||
{
|
||||
ch= ((ch>>1)&0x55) | ((ch<<1)&0xAA);
|
||||
ch= ((ch>>2)&0x33) | ((ch<<2)&0xCC);
|
||||
ch= ((ch>>4)&0x0F) | ((ch<<4)&0xF0);
|
||||
return ch;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** Reverse the bits in a GHOST_TUns16 */
|
||||
static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt)
|
||||
{
|
||||
shrt= ((shrt>>1)&0x5555) | ((shrt<<1)&0xAAAA);
|
||||
shrt= ((shrt>>2)&0x3333) | ((shrt<<2)&0xCCCC);
|
||||
shrt= ((shrt>>4)&0x0F0F) | ((shrt<<4)&0xF0F0);
|
||||
shrt= ((shrt>>8)&0x00FF) | ((shrt<<8)&0xFF00);
|
||||
return shrt;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
|
||||
int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color)
|
||||
{
|
||||
int y;
|
||||
|
||||
if (m_customCursor) {
|
||||
delete m_customCursor;
|
||||
m_customCursor = 0;
|
||||
}
|
||||
|
||||
m_customCursor = new Cursor;
|
||||
if (!m_customCursor) return GHOST_kFailure;
|
||||
|
||||
for (y=0; y<16; y++) {
|
||||
#if !defined(__LITTLE_ENDIAN__)
|
||||
m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8));
|
||||
m_customCursor->mask[y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8));
|
||||
#else
|
||||
m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8));
|
||||
m_customCursor->mask[y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
m_customCursor->hotSpot.h = hotX;
|
||||
m_customCursor->hotSpot.v = hotY;
|
||||
|
||||
if (::FrontWindow() == m_windowRef) {
|
||||
loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2],
|
||||
GHOST_TUns8 mask[16][2], int hotX, int hotY)
|
||||
{
|
||||
return setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*) mask, 16, 16, hotX, hotY, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::setMac_windowState(short value)
|
||||
{
|
||||
mac_windowState = value;
|
||||
}
|
||||
|
||||
short GHOST_WindowCocoa::getMac_windowState()
|
||||
{
|
||||
return mac_windowState;
|
||||
}
|
||||
Reference in New Issue
Block a user