add back ghost/guardedalloc from trunk
This commit is contained in:
173
intern/ghost/CMakeLists.txt
Normal file
173
intern/ghost/CMakeLists.txt
Normal file
@@ -0,0 +1,173 @@
|
||||
# $Id$
|
||||
# ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2006, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# Contributor(s): Jacques Beaurain.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(INC
|
||||
.
|
||||
../string
|
||||
../../source/blender/imbuf
|
||||
../../source/blender/makesdna
|
||||
${GLEW_INCLUDE_PATH}
|
||||
)
|
||||
|
||||
set(SRC
|
||||
intern/GHOST_Buttons.cpp
|
||||
intern/GHOST_CallbackEventConsumer.cpp
|
||||
intern/GHOST_C-api.cpp
|
||||
intern/GHOST_Path-api.cpp
|
||||
intern/GHOST_DisplayManager.cpp
|
||||
intern/GHOST_EventManager.cpp
|
||||
intern/GHOST_EventPrinter.cpp
|
||||
intern/GHOST_ISystem.cpp
|
||||
intern/GHOST_ISystemPaths.cpp
|
||||
intern/GHOST_ModifierKeys.cpp
|
||||
intern/GHOST_NDOFManager.cpp
|
||||
intern/GHOST_Path-api.cpp
|
||||
intern/GHOST_Rect.cpp
|
||||
intern/GHOST_System.cpp
|
||||
intern/GHOST_TimerManager.cpp
|
||||
intern/GHOST_Window.cpp
|
||||
intern/GHOST_WindowManager.cpp
|
||||
|
||||
GHOST_C-api.h
|
||||
GHOST_IEvent.h
|
||||
GHOST_IEventConsumer.h
|
||||
GHOST_ISystem.h
|
||||
GHOST_ISystemPaths.h
|
||||
GHOST_ITimerTask.h
|
||||
GHOST_IWindow.h
|
||||
GHOST_Path-api.h
|
||||
GHOST_Rect.h
|
||||
GHOST_Types.h
|
||||
intern/GHOST_Buttons.h
|
||||
intern/GHOST_CallbackEventConsumer.h
|
||||
intern/GHOST_Debug.h
|
||||
intern/GHOST_DisplayManager.h
|
||||
intern/GHOST_Event.h
|
||||
intern/GHOST_EventButton.h
|
||||
intern/GHOST_EventCursor.h
|
||||
intern/GHOST_EventDragnDrop.h
|
||||
intern/GHOST_EventKey.h
|
||||
intern/GHOST_EventManager.h
|
||||
intern/GHOST_EventNDOF.h
|
||||
intern/GHOST_EventPrinter.h
|
||||
intern/GHOST_EventString.h
|
||||
intern/GHOST_EventTrackpad.h
|
||||
intern/GHOST_EventWheel.h
|
||||
intern/GHOST_ModifierKeys.h
|
||||
intern/GHOST_NDOFManager.h
|
||||
intern/GHOST_System.h
|
||||
intern/GHOST_SystemPaths.h
|
||||
intern/GHOST_TimerManager.h
|
||||
intern/GHOST_TimerTask.h
|
||||
intern/GHOST_Window.h
|
||||
intern/GHOST_WindowManager.h
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
if(WITH_COCOA)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DisplayManagerCocoa.mm
|
||||
intern/GHOST_SystemCocoa.mm
|
||||
intern/GHOST_SystemPathsCocoa.mm
|
||||
intern/GHOST_WindowCocoa.mm
|
||||
|
||||
intern/GHOST_DisplayManagerCocoa.h
|
||||
intern/GHOST_SystemCocoa.h
|
||||
intern/GHOST_SystemPathsCocoa.h
|
||||
intern/GHOST_WindowCocoa.h
|
||||
)
|
||||
else()
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DisplayManagerCarbon.cpp
|
||||
intern/GHOST_SystemCarbon.cpp
|
||||
intern/GHOST_SystemPathsCarbon.cpp
|
||||
intern/GHOST_WindowCarbon.cpp
|
||||
|
||||
intern/GHOST_DisplayManagerCarbon.h
|
||||
intern/GHOST_SystemCarbon.h
|
||||
intern/GHOST_SystemPathsCarbon.h
|
||||
intern/GHOST_WindowCarbon.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_CODEC_QUICKTIME)
|
||||
add_definitions(-DWITH_QUICKTIME)
|
||||
endif()
|
||||
|
||||
elseif(UNIX)
|
||||
|
||||
if(WITH_X11_XINPUT)
|
||||
add_definitions(-DWITH_X11_XINPUT)
|
||||
endif()
|
||||
|
||||
list(APPEND INC ${X11_X11_INCLUDE_PATH})
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DisplayManagerX11.cpp
|
||||
intern/GHOST_SystemX11.cpp
|
||||
intern/GHOST_SystemPathsX11.cpp
|
||||
intern/GHOST_WindowX11.cpp
|
||||
|
||||
intern/GHOST_DisplayManagerX11.h
|
||||
intern/GHOST_SystemX11.h
|
||||
intern/GHOST_SystemPathsX11.h
|
||||
intern/GHOST_WindowX11.h
|
||||
)
|
||||
|
||||
if(NOT WITH_INSTALL_PORTABLE)
|
||||
add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}")
|
||||
endif()
|
||||
|
||||
if(X11_XF86keysym_INCLUDE_PATH)
|
||||
add_definitions(-DWITH_XF86KEYSYM)
|
||||
list(APPEND INC ${X11_XF86keysym_INCLUDE_PATH})
|
||||
endif()
|
||||
|
||||
elseif(WIN32)
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX")
|
||||
endif()
|
||||
|
||||
list(APPEND INC ${WINTAB_INC})
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DisplayManagerWin32.cpp
|
||||
intern/GHOST_SystemWin32.cpp
|
||||
intern/GHOST_SystemPathsWin32.cpp
|
||||
intern/GHOST_WindowWin32.cpp
|
||||
intern/GHOST_DropTargetWin32.cpp
|
||||
|
||||
intern/GHOST_DisplayManagerWin32.h
|
||||
intern/GHOST_DropTargetWin32.h
|
||||
intern/GHOST_SystemWin32.h
|
||||
intern/GHOST_SystemPathsWin32.h
|
||||
intern/GHOST_WindowWin32.h
|
||||
intern/GHOST_TaskbarWin32.h
|
||||
)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_intern_ghost "${SRC}" "${INC}")
|
||||
|
||||
864
intern/ghost/GHOST_C-api.h
Normal file
864
intern/ghost/GHOST_C-api.h
Normal file
@@ -0,0 +1,864 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
/** \ingroup GHOST
|
||||
*
|
||||
* \file GHOST_C-api.h
|
||||
* \brief GHOST C-API function and type declarations.
|
||||
*/
|
||||
|
||||
#ifndef GHOST_C_API_H
|
||||
#define GHOST_C_API_H
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Creates a "handle" for a C++ GHOST object.
|
||||
* A handle is just an opaque pointer to an empty struct.
|
||||
* In the API the pointer is casted to the actual C++ class.
|
||||
* \param name Name of the handle to create.
|
||||
*/
|
||||
|
||||
GHOST_DECLARE_HANDLE(GHOST_SystemHandle);
|
||||
GHOST_DECLARE_HANDLE(GHOST_TimerTaskHandle);
|
||||
GHOST_DECLARE_HANDLE(GHOST_WindowHandle);
|
||||
GHOST_DECLARE_HANDLE(GHOST_EventHandle);
|
||||
GHOST_DECLARE_HANDLE(GHOST_RectangleHandle);
|
||||
GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
|
||||
|
||||
|
||||
/**
|
||||
* Definition of a callback routine that receives events.
|
||||
* @param event The event received.
|
||||
* @param userdata The callback's user data, supplied to GHOST_CreateSystem.
|
||||
*/
|
||||
typedef int (*GHOST_EventCallbackProcPtr)(GHOST_EventHandle event, GHOST_TUserDataPtr userdata);
|
||||
|
||||
|
||||
/**
|
||||
* Creates the one and only system.
|
||||
* @return a handle to the system.
|
||||
*/
|
||||
extern GHOST_SystemHandle GHOST_CreateSystem(void);
|
||||
|
||||
/**
|
||||
* Disposes the one and only system.
|
||||
* @param systemhandle The handle to the system
|
||||
* @return An indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle);
|
||||
|
||||
|
||||
/**
|
||||
* Creates an event consumer object
|
||||
* @param eventCallback The event callback routine.
|
||||
* @param userdata Pointer to user data returned to the callback routine.
|
||||
*/
|
||||
extern GHOST_EventConsumerHandle GHOST_CreateEventConsumer(GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userdata);
|
||||
|
||||
/**
|
||||
* Disposes an event consumer object
|
||||
* @param consumerhandle Handle to the event consumer.
|
||||
* @return An indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consumerhandle);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the system time.
|
||||
* Returns the number of milliseconds since the start of the system process.
|
||||
* Based on ANSI clock() routine.
|
||||
* @param systemhandle The handle to the system
|
||||
* @return The number of milliseconds.
|
||||
*/
|
||||
extern GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle);
|
||||
|
||||
/**
|
||||
* Installs a timer.
|
||||
* Note that, on most operating systems, messages need to be processed in order
|
||||
* for the timer callbacks to be invoked.
|
||||
* @param systemhandle The handle to the system
|
||||
* @param delay The time to wait for the first call to the timerProc (in milliseconds)
|
||||
* @param interval The interval between calls to the timerProc (in milliseconds)
|
||||
* @param timerProc The callback invoked when the interval expires,
|
||||
* @param userData Placeholder for user data.
|
||||
* @return A timer task (0 if timer task installation failed).
|
||||
*/
|
||||
extern GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TUns64 delay,
|
||||
GHOST_TUns64 interval,
|
||||
GHOST_TimerProcPtr timerProc,
|
||||
GHOST_TUserDataPtr userData);
|
||||
|
||||
/**
|
||||
* Removes a timer.
|
||||
* @param systemhandle The handle to the system
|
||||
* @param timerTask Timer task to be removed.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TimerTaskHandle timertaskhandle);
|
||||
|
||||
/***************************************************************************************
|
||||
** Display/window management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the number of displays on this system.
|
||||
* @param systemhandle The handle to the system
|
||||
* @return The number of displays.
|
||||
*/
|
||||
extern GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle);
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the main display on this system.
|
||||
* @param systemhandle The handle to the system
|
||||
* @param width A pointer the width gets put in
|
||||
* @param height A pointer the height gets put in
|
||||
* @return void.
|
||||
*/
|
||||
extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TUns32* width,
|
||||
GHOST_TUns32* height);
|
||||
|
||||
/**
|
||||
* Create a new window.
|
||||
* The new window is added to the list of windows managed.
|
||||
* Never explicitly delete the window, use disposeWindow() instead.
|
||||
* @param systemhandle The handle to the system
|
||||
* @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 stereoVisual Stereo visual for quad buffered stereo.
|
||||
* @param numOfAASamples Number of samples used for AA (zero if no AA)
|
||||
* @return A handle to the new window ( == NULL if creation failed).
|
||||
*/
|
||||
extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
|
||||
const char* title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_TDrawingContextType type,
|
||||
const int stereoVisual,
|
||||
const GHOST_TUns16 numOfAASamples);
|
||||
|
||||
/**
|
||||
* Returns the window user data.
|
||||
* @param windowhandle The handle to the window
|
||||
* @return The window user data.
|
||||
*/
|
||||
extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Changes the window user data.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param data The window user data.
|
||||
*/
|
||||
extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUserDataPtr userdata);
|
||||
|
||||
/**
|
||||
* Dispose a window.
|
||||
* @param systemhandle The handle to the system
|
||||
* @param window Handle to the window to be disposed.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
|
||||
GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Returns whether a window is valid.
|
||||
* @param systemhandle The handle to the system
|
||||
* @param window Handle to the window to be checked.
|
||||
* @return Indication of validity.
|
||||
*/
|
||||
extern int GHOST_ValidWindow(GHOST_SystemHandle systemhandle,
|
||||
GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Begins full screen mode.
|
||||
* @param systemhandle The handle to the system
|
||||
* @param setting The new setting of the display.
|
||||
* @return A handle to the window displayed in full screen.
|
||||
* This window is invalid after full screen has been ended.
|
||||
*/
|
||||
extern GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle,
|
||||
GHOST_DisplaySetting* setting,
|
||||
const int stereoVisual);
|
||||
|
||||
/**
|
||||
* Ends full screen mode.
|
||||
* @param systemhandle The handle to the system
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle);
|
||||
|
||||
/**
|
||||
* Returns current full screen mode status.
|
||||
* @param systemhandle The handle to the system
|
||||
* @return The current status.
|
||||
*/
|
||||
extern int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle);
|
||||
|
||||
/***************************************************************************************
|
||||
** Event management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Retrieves events from the system and stores them in the queue.
|
||||
* @param systemhandle The handle to the system
|
||||
* @param waitForEvent Boolean to indicate that ProcessEvents should
|
||||
* wait (block) until the next event before returning.
|
||||
* @return Indication of the presence of events.
|
||||
*/
|
||||
extern int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent);
|
||||
|
||||
/**
|
||||
* Retrieves events from the queue and send them to the event consumers.
|
||||
* @param systemhandle The handle to the system
|
||||
* @return Indication of the presence of events.
|
||||
*/
|
||||
extern int GHOST_DispatchEvents(GHOST_SystemHandle systemhandle);
|
||||
|
||||
/**
|
||||
* Adds the given event consumer to our list.
|
||||
* @param systemhandle The handle to the system
|
||||
* @param consumerhandle The event consumer to add.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle,
|
||||
GHOST_EventConsumerHandle consumerhandle);
|
||||
|
||||
/**
|
||||
* Remove the given event consumer to our list.
|
||||
* @param systemhandle The handle to the system
|
||||
* @param consumerhandle The event consumer to remove.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_RemoveEventConsumer(GHOST_SystemHandle systemhandle,
|
||||
GHOST_EventConsumerHandle consumerhandle);
|
||||
|
||||
/***************************************************************************************
|
||||
** Progress bar functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Sets the progress bar value displayed in the window/application icon
|
||||
* @param windowhandle The handle to the window
|
||||
* @param progress The progress % (0.0 to 1.0)
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, float progress);
|
||||
|
||||
/**
|
||||
* Hides the progress bar in the icon
|
||||
* @param windowhandle The handle to the window
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle);
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** N-degree of freedom device management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Open N-degree of freedom devices
|
||||
*/
|
||||
extern int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle,
|
||||
GHOST_WindowHandle windowhandle,
|
||||
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
|
||||
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
|
||||
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen
|
||||
);
|
||||
|
||||
/***************************************************************************************
|
||||
** Cursor management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the current cursor shape.
|
||||
* @param windowhandle The handle to the window
|
||||
* @return The current cursor shape.
|
||||
*/
|
||||
extern GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Set the shape of the cursor.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param cursor The new cursor shape type id.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetCursorShape(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TStandardCursor cursorshape);
|
||||
|
||||
/**
|
||||
* Set the shape of the cursor to a custom cursor.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param bitmap The bitmap data for the cursor.
|
||||
* @param mask The mask data for the cursor.
|
||||
* @param hotX The X coordinate of the cursor hotspot.
|
||||
* @param hotY The Y coordinate of the cursor hotspot.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns8 bitmap[16][2],
|
||||
GHOST_TUns8 mask[16][2],
|
||||
int hotX,
|
||||
int hotY);
|
||||
/**
|
||||
* Set the shape of the cursor to a custom cursor of specified size.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param bitmap The bitmap data for the cursor.
|
||||
* @param mask The mask data for the cursor.
|
||||
* @parm sizex, sizey The size of the cursor
|
||||
* @param hotX The X coordinate of the cursor hotspot.
|
||||
* @param hotY The Y coordinate of the cursor hotspot.
|
||||
* @param fg_color, bg_color Colors of the cursor
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetCustomCursorShapeEx(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask,
|
||||
int sizex, int sizey,
|
||||
int hotX, int hotY,
|
||||
int fg_color, int bg_color );
|
||||
|
||||
/**
|
||||
* Returns the visibility state of the cursor.
|
||||
* @param windowhandle The handle to the window
|
||||
* @return The visibility state of the cursor.
|
||||
*/
|
||||
extern int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Shows or hides the cursor.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param visible The new visibility state of the cursor.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle,
|
||||
int visible);
|
||||
|
||||
/**
|
||||
* Returns the current location of the cursor (location in screen coordinates)
|
||||
* @param systemhandle The handle to the system
|
||||
* @param x The x-coordinate of the cursor.
|
||||
* @param y The y-coordinate of the cursor.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TInt32* x,
|
||||
GHOST_TInt32* y);
|
||||
|
||||
/**
|
||||
* Updates the location of the cursor (location in screen coordinates).
|
||||
* Not all operating systems allow the cursor to be moved (without the input device being moved).
|
||||
* @param systemhandle The handle to the system
|
||||
* @param x The x-coordinate of the cursor.
|
||||
* @param y The y-coordinate of the cursor.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TInt32 x,
|
||||
GHOST_TInt32 y);
|
||||
|
||||
/**
|
||||
* Grabs the cursor for a modal operation, to keep receiving
|
||||
* events when the mouse is outside the window. X11 only, others
|
||||
* do this automatically.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param mode The new grab state of the cursor.
|
||||
* @param bounds The grab ragion (optional) - left,top,right,bottom
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TGrabCursorMode mode,
|
||||
int* bounds);
|
||||
|
||||
/***************************************************************************************
|
||||
** Access to mouse button and keyboard states.
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the state of a modifier key (ouside the message queue).
|
||||
* @param systemhandle The handle to the system
|
||||
* @param mask The modifier key state to retrieve.
|
||||
* @param isDown Pointer to return modifier state in.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TModifierKeyMask mask,
|
||||
int* isDown);
|
||||
|
||||
/**
|
||||
* Returns the state of a mouse button (ouside the message queue).
|
||||
* @param systemhandle The handle to the system
|
||||
* @param mask The button state to retrieve.
|
||||
* @param isDown Pointer to return button state in.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TButtonMask mask,
|
||||
int* isDown);
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Drag'n'drop operations
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Tells if the ongoing drag'n'drop object can be accepted upon mouse drop
|
||||
*/
|
||||
extern void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_TInt8 canAccept);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the event type.
|
||||
* @param eventhandle The handle to the event
|
||||
* @return The event type.
|
||||
*/
|
||||
extern GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle);
|
||||
|
||||
/**
|
||||
* Returns the time this event was generated.
|
||||
* @param eventhandle The handle to the event
|
||||
* @return The event generation time.
|
||||
*/
|
||||
extern GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle);
|
||||
|
||||
/**
|
||||
* Returns the window this event was generated on,
|
||||
* or NULL if it is a 'system' event.
|
||||
* @param eventhandle The handle to the event
|
||||
* @return The generating window.
|
||||
*/
|
||||
extern GHOST_WindowHandle GHOST_GetEventWindow(GHOST_EventHandle eventhandle);
|
||||
|
||||
/**
|
||||
* Returns the event data.
|
||||
* @param eventhandle The handle to the event
|
||||
* @return The event data.
|
||||
*/
|
||||
extern GHOST_TEventDataPtr GHOST_GetEventData(GHOST_EventHandle eventhandle);
|
||||
|
||||
/**
|
||||
* Returns the timer callback.
|
||||
* @param timertaskhandle The handle to the timertask
|
||||
* @return The timer callback.
|
||||
*/
|
||||
extern GHOST_TimerProcPtr GHOST_GetTimerProc(GHOST_TimerTaskHandle timertaskhandle);
|
||||
|
||||
/**
|
||||
* Changes the timer callback.
|
||||
* @param timertaskhandle The handle to the timertask
|
||||
* @param timerProc The timer callback.
|
||||
*/
|
||||
extern void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle,
|
||||
GHOST_TimerProcPtr timerProc);
|
||||
|
||||
/**
|
||||
* Returns the timer user data.
|
||||
* @param timertaskhandle The handle to the timertask
|
||||
* @return The timer user data.
|
||||
*/
|
||||
extern GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle);
|
||||
|
||||
/**
|
||||
* Changes the time user data.
|
||||
* @param timertaskhandle The handle to the timertask
|
||||
* @param data The timer user data.
|
||||
*/
|
||||
extern void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle,
|
||||
GHOST_TUserDataPtr userData);
|
||||
|
||||
/**
|
||||
* Returns indication as to whether the window is valid.
|
||||
* @param windowhandle The handle to the window
|
||||
* @return The validity of the window.
|
||||
*/
|
||||
extern int GHOST_GetValid(GHOST_WindowHandle windowhandle) ;
|
||||
|
||||
/**
|
||||
* Returns the type of drawing context used in this window.
|
||||
* @param windowhandle The handle to the window
|
||||
* @return The current type of drawing context.
|
||||
*/
|
||||
extern GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Tries to install a rendering context in this window.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param type The type of rendering context installed.
|
||||
* @return Indication as to whether installation has succeeded.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TDrawingContextType type);
|
||||
|
||||
/**
|
||||
* Sets the title displayed in the title bar.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param title The title to display in the title bar.
|
||||
*/
|
||||
extern void GHOST_SetTitle(GHOST_WindowHandle windowhandle,
|
||||
const char* title);
|
||||
|
||||
/**
|
||||
* Returns the title displayed in the title bar. The title
|
||||
* should be free'd with free().
|
||||
*
|
||||
* @param windowhandle The handle to the window
|
||||
* @return The title, free with free().
|
||||
*/
|
||||
extern char* GHOST_GetTitle(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Returns the window rectangle dimensions.
|
||||
* These are screen coordinates.
|
||||
* @param windowhandle The handle to the window
|
||||
* @return A handle to the bounding rectangle of the window.
|
||||
*/
|
||||
extern GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Returns the client rectangle dimensions.
|
||||
* The left and top members of the rectangle are always zero.
|
||||
* @param windowhandle The handle to the window
|
||||
* @return A handle to the bounding rectangle of the window.
|
||||
*/
|
||||
extern GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Disposes a rectangle object
|
||||
* @param rectanglehandle Handle to the rectangle.
|
||||
*/
|
||||
void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle);
|
||||
|
||||
/**
|
||||
* Resizes client rectangle width.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param width The new width of the client area of the window.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns32 width);
|
||||
|
||||
/**
|
||||
* Resizes client rectangle height.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param height The new height of the client area of the window.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns32 height);
|
||||
|
||||
/**
|
||||
* Resizes client rectangle.
|
||||
* @param windowhandle The handle to the window
|
||||
* @param width The new width of the client area of the window.
|
||||
* @param height The new height of the client area of the window.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height);
|
||||
|
||||
/**
|
||||
* Converts a point in screen coordinates to client rectangle coordinates
|
||||
* @param windowhandle The handle to the window
|
||||
* @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.
|
||||
*/
|
||||
extern void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32* outX,
|
||||
GHOST_TInt32* outY) ;
|
||||
|
||||
/**
|
||||
* Converts a point in screen coordinates to client rectangle coordinates
|
||||
* @param windowhandle The handle to the window
|
||||
* @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.
|
||||
*/
|
||||
extern void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32* outX,
|
||||
GHOST_TInt32* outY);
|
||||
|
||||
/**
|
||||
* Returns the state of the window (normal, minimized, maximized).
|
||||
* @param windowhandle The handle to the window
|
||||
* @return The state of the window.
|
||||
*/
|
||||
extern GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Sets the state of the window (normal, minimized, maximized).
|
||||
* @param windowhandle The handle to the window
|
||||
* @param state The state of the window.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TWindowState state);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the window "modified" status, indicating unsaved changes
|
||||
* @param windowhandle The handle to the window
|
||||
* @param isUnsavedChanges Unsaved changes or not
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns8 isUnsavedChanges);
|
||||
|
||||
/**
|
||||
* Sets the order of the window (bottom, top).
|
||||
* @param windowhandle The handle to the window
|
||||
* @param order The order of the window.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TWindowOrder order);
|
||||
|
||||
/**
|
||||
* Swaps front and back buffers of a window.
|
||||
* @param windowhandle The handle to the window
|
||||
* @return An intean success indicator.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Activates the drawing context of this window.
|
||||
* @param windowhandle The handle to the window
|
||||
* @return An intean success indicator.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Invalidates the contents of this window.
|
||||
* @param windowhandle The handle to the window
|
||||
* @return Indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Returns the status of the tablet
|
||||
* @param windowhandle The handle to the window
|
||||
* @return Status of tablet
|
||||
*/
|
||||
extern const GHOST_TabletData *GHOST_GetTabletData(GHOST_WindowHandle windowhandle);
|
||||
|
||||
/**
|
||||
* Access to rectangle width.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @return width of the rectangle
|
||||
*/
|
||||
extern GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle);
|
||||
|
||||
/**
|
||||
* Access to rectangle height.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @return height of the rectangle
|
||||
*/
|
||||
extern GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle);
|
||||
|
||||
/**
|
||||
* Gets all members of the rectangle.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @param l Pointer to return left coordinate in.
|
||||
* @param t Pointer to return top coordinate in.
|
||||
* @param r Pointer to return right coordinate in.
|
||||
* @param b Pointer to return bottom coordinate in.
|
||||
*/
|
||||
extern void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32* l,
|
||||
GHOST_TInt32* t,
|
||||
GHOST_TInt32* r,
|
||||
GHOST_TInt32* b);
|
||||
|
||||
/**
|
||||
* Sets all members of the rectangle.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @param l requested left coordinate of the rectangle
|
||||
* @param t requested top coordinate of the rectangle
|
||||
* @param r requested right coordinate of the rectangle
|
||||
* @param b requested bottom coordinate of the rectangle
|
||||
*/
|
||||
extern void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 l,
|
||||
GHOST_TInt32 t,
|
||||
GHOST_TInt32 r,
|
||||
GHOST_TInt32 b);
|
||||
|
||||
/**
|
||||
* Returns whether this rectangle is empty.
|
||||
* Empty rectangles are rectangles that have width==0 and/or height==0.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @return intean value (true == empty rectangle)
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle);
|
||||
|
||||
/**
|
||||
* Returns whether this rectangle is valid.
|
||||
* Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @return intean value (true==valid rectangle)
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle);
|
||||
|
||||
/**
|
||||
* Grows (or shrinks the rectangle).
|
||||
* The method avoids negative insets making the rectangle invalid
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @param i The amount of offset given to each extreme (negative values shrink the rectangle).
|
||||
*/
|
||||
extern void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 i);
|
||||
|
||||
/**
|
||||
* Does a union of the rectangle given and this rectangle.
|
||||
* The result is stored in this rectangle.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @param r The rectangle that is input for the union operation.
|
||||
*/
|
||||
extern void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_RectangleHandle anotherrectanglehandle);
|
||||
|
||||
/**
|
||||
* Grows the rectangle to included a point.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @param x The x-coordinate of the point.
|
||||
* @param y The y-coordinate of the point.
|
||||
*/
|
||||
extern void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 x,
|
||||
GHOST_TInt32 y);
|
||||
|
||||
/**
|
||||
* Returns whether the point is inside this rectangle.
|
||||
* Point on the boundary is considered inside.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @param x x-coordinate of point to test.
|
||||
* @param y y-coordinate of point to test.
|
||||
* @return intean value (true if point is inside).
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 x,
|
||||
GHOST_TInt32 y);
|
||||
|
||||
/**
|
||||
* Returns whether the rectangle is inside this rectangle.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @param r rectangle to test.
|
||||
* @return visibility (not, partially or fully visible).
|
||||
*/
|
||||
extern GHOST_TVisibility GHOST_GetRectangleVisibility(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_RectangleHandle anotherrectanglehandle);
|
||||
|
||||
/**
|
||||
* Sets rectangle members.
|
||||
* Sets rectangle members such that it is centered at the given location.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @param cx requested center x-coordinate of the rectangle
|
||||
* @param cy requested center y-coordinate of the rectangle
|
||||
*/
|
||||
extern void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 cx,
|
||||
GHOST_TInt32 cy);
|
||||
|
||||
/**
|
||||
* Sets rectangle members.
|
||||
* Sets rectangle members such that it is centered at the given location,
|
||||
* with the width requested.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @param cx requested center x-coordinate of the rectangle
|
||||
* @param cy requested center y-coordinate of the rectangle
|
||||
* @param w requested width of the rectangle
|
||||
* @param h requested height of the rectangle
|
||||
*/
|
||||
extern void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 cx,
|
||||
GHOST_TInt32 cy,
|
||||
GHOST_TInt32 w,
|
||||
GHOST_TInt32 h);
|
||||
|
||||
/**
|
||||
* Clips a rectangle.
|
||||
* Updates the rectangle given such that it will fit within this one.
|
||||
* This can result in an empty rectangle.
|
||||
* @param rectanglehandle The handle to the rectangle
|
||||
* @param r the rectangle to clip
|
||||
* @return whether clipping has occurred
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_RectangleHandle anotherrectanglehandle);
|
||||
|
||||
/**
|
||||
* Return the data from the clipboad
|
||||
* @param return the selection instead, X11 only feature
|
||||
* @return clipboard data
|
||||
*/
|
||||
extern GHOST_TUns8* GHOST_getClipboard(int selection);
|
||||
|
||||
/**
|
||||
* Put data to the Clipboard
|
||||
* @param set the selection instead, X11 only feature
|
||||
*/
|
||||
extern void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Toggles console
|
||||
* @action 0 - Hides
|
||||
* 1 - Shows
|
||||
* 2 - Toggles
|
||||
* 3 - Hides if it runs not from command line
|
||||
* * - Does nothing
|
||||
* @return current status (1 -visible, 0 - hidden)
|
||||
*/
|
||||
extern int GHOST_toggleConsole(int action);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
97
intern/ghost/GHOST_IEvent.h
Normal file
97
intern/ghost/GHOST_IEvent.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/GHOST_IEvent.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_IEvent interface class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_IEVENT_H_
|
||||
#define _GHOST_IEVENT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
class GHOST_IWindow;
|
||||
|
||||
/**
|
||||
* Interface class for events received from GHOST.
|
||||
* You should not need to inherit this class. The system will pass these events
|
||||
* to the GHOST_IEventConsumer::processEvent() method of event consumers.<br>
|
||||
* Use the getType() method to retrieve the type of event and the getData()
|
||||
* method to get the event data out. Using the event type you can cast the
|
||||
* event data to the correct event dat structure.
|
||||
* @see GHOST_IEventConsumer#processEvent
|
||||
* @see GHOST_TEventType
|
||||
* @author Maarten Gribnau
|
||||
* @date May 31, 2001
|
||||
*/
|
||||
class GHOST_IEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_IEvent()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event type.
|
||||
* @return The event type.
|
||||
*/
|
||||
virtual GHOST_TEventType getType() = 0;
|
||||
|
||||
/**
|
||||
* Returns the time this event was generated.
|
||||
* @return The event generation time.
|
||||
*/
|
||||
virtual GHOST_TUns64 getTime() = 0;
|
||||
|
||||
/**
|
||||
* Returns the window this event was generated on,
|
||||
* or NULL if it is a 'system' event.
|
||||
* @return The generating window.
|
||||
*/
|
||||
virtual GHOST_IWindow* getWindow() = 0;
|
||||
|
||||
/**
|
||||
* Returns the event data.
|
||||
* @return The event data.
|
||||
*/
|
||||
virtual GHOST_TEventDataPtr getData() = 0;
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
public:
|
||||
void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GHOST:GHOST_IEvent"); }
|
||||
void operator delete( void *mem ) { MEM_freeN(mem); }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // _GHOST_IEVENT_H_
|
||||
|
||||
75
intern/ghost/GHOST_IEventConsumer.h
Normal file
75
intern/ghost/GHOST_IEventConsumer.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/GHOST_IEventConsumer.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_IEventConsumer interface class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_IEVENT_CONSUMER_H_
|
||||
#define _GHOST_IEVENT_CONSUMER_H_
|
||||
|
||||
#include "GHOST_IEvent.h"
|
||||
|
||||
/**
|
||||
* Interface class for objects interested in receiving events.
|
||||
* Objects interested in events should inherit this class and implement the
|
||||
* processEvent() method. They should then be registered with the system that
|
||||
* they want to receive events. The system will call the processEvent() method
|
||||
* for every installed event consumer to pass events.
|
||||
* @see GHOST_ISystem#addEventConsumer
|
||||
* @author Maarten Gribnau
|
||||
* @date May 14, 2001
|
||||
*/
|
||||
class GHOST_IEventConsumer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_IEventConsumer()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by the system when it has events to dispatch.
|
||||
* @see GHOST_ISystem#dispatchEvents
|
||||
* @param event The event that can be handled or ignored.
|
||||
* @return Indication as to whether the event was handled.
|
||||
*/
|
||||
virtual bool processEvent(GHOST_IEvent* event) = 0;
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
public:
|
||||
void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GHOST:GHOST_IEventConsumer"); }
|
||||
void operator delete( void *mem ) { MEM_freeN(mem); }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // _GHOST_EVENT_CONSUMER_H_
|
||||
|
||||
410
intern/ghost/GHOST_ISystem.h
Normal file
410
intern/ghost/GHOST_ISystem.h
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/GHOST_ISystem.h
|
||||
* \ingroup GHOST
|
||||
* %Main interface file for C++ Api with declaration of GHOST_ISystem interface
|
||||
* class.
|
||||
* Contains the doxygen documentation main page.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_ISYSTEM_H_
|
||||
#define _GHOST_ISYSTEM_H_
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
#include "GHOST_ITimerTask.h"
|
||||
#include "GHOST_IWindow.h"
|
||||
|
||||
class GHOST_IEventConsumer;
|
||||
|
||||
/**
|
||||
* \page GHOSTPage GHOST
|
||||
*
|
||||
* \section intro Introduction
|
||||
*
|
||||
* GHOST is yet another acronym. It stands for "Generic Handy Operating System
|
||||
* Toolkit". It has been created to replace the OpenGL utility tool kit
|
||||
* <a href="http://www.opengl.org/developers/documentation/glut.html">GLUT</a>.
|
||||
* GLUT was used in <a href="http://www.blender3d.com">Blender</a> until the
|
||||
* point that Blender needed to be ported to Apple's Mac OSX. Blender needed a
|
||||
* number of modifications in GLUT to work but the GLUT sources for OSX were
|
||||
* unavailable at the time. The decision was made to build our own replacement
|
||||
* for GLUT. In those days, NaN Technologies BV was the company that developed
|
||||
* Blender.
|
||||
* <br><br>
|
||||
* Enough history. What does GHOST have to offer?<br>
|
||||
* In short: everything that Blender needed from GLUT to run on all it's supported
|
||||
* operating systems and some extra's.
|
||||
* This includes :
|
||||
* <ul>
|
||||
* <li> Time(r) management.</li>
|
||||
* <li> Display/window management (windows are only created on the main display).
|
||||
* <li> Event management.</li>
|
||||
* <li> Cursor shape management (no custom cursors for now).</li>
|
||||
* <li> Access to the state of the mouse buttons and the keyboard.</li>
|
||||
* <li> Menus for windows with events generated when they are accessed (this is
|
||||
* work in progress).</li>
|
||||
* </ul>
|
||||
* Font management has been moved to a separate library.
|
||||
*
|
||||
* \section platforms Platforms
|
||||
*
|
||||
* \section Building GHOST
|
||||
*
|
||||
* \section interface Interface
|
||||
* GHOST has two programming interfaces:
|
||||
* <ul>
|
||||
* <li>The C-API. For programs written in C.</li>
|
||||
* <li>The C++-API. For programs written in C++.</li>
|
||||
* </ul>
|
||||
* GHOST itself is writtem in C++ and the C-API is a wrapper around the C++
|
||||
* API.
|
||||
*
|
||||
* \subsection cplusplus_api The C++ API consists of the following files:
|
||||
* <ul>
|
||||
* <li>GHOST_IEvent.h</li>
|
||||
* <li>GHOST_IEventConsumer.h</li>
|
||||
* <li>GHOST_ISystem.h</li>
|
||||
* <li>GHOST_ITimerTask.h</li>
|
||||
* <li>GHOST_IWindow.h</li>
|
||||
* <li>GHOST_Rect.h</li>
|
||||
* <li>GHOST_Types.h</li>
|
||||
* </ul>
|
||||
* For an example of using the C++-API, have a look at the GHOST_C-Test.cpp
|
||||
* program in the ?/ghost/test/gears/ directory.
|
||||
*
|
||||
* \subsection c_api The C-API
|
||||
* To use GHOST in programs written in C, include the file GHOST_C-API.h in
|
||||
* your program. This file includes the GHOST_Types.h file for all GHOST types
|
||||
* and defines functions that give you access to the same functionality present
|
||||
* in the C++ API.<br>
|
||||
* For an example of using the C-API, have a look at the GHOST_C-Test.c program
|
||||
* in the ?/ghost/test/gears/ directory.
|
||||
*
|
||||
* \section work Work in progress
|
||||
* \todo write WIP section
|
||||
*/
|
||||
|
||||
/** \interface GHOST_ISystem
|
||||
* Interface for classes that provide access to the operating system.
|
||||
* There should be only one system class in an application.
|
||||
* Therefore, the routines to create and dispose the system are static.
|
||||
* Provides:
|
||||
* -# Time(r) management.
|
||||
* -# Display/window management (windows are only created on the main display).
|
||||
* -# Event management.
|
||||
* -# Cursor shape management (no custom cursors for now).
|
||||
* -# Access to the state of the mouse buttons and the keyboard.
|
||||
* -# Menus for windows with events generated when they are accessed (this is
|
||||
* work in progress).
|
||||
* @author Maarten Gribnau
|
||||
* @date May 30, 2001
|
||||
*/
|
||||
class GHOST_ISystem
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates the one and only system.
|
||||
* @return An indication of success.
|
||||
*/
|
||||
static GHOST_TSuccess createSystem();
|
||||
|
||||
/**
|
||||
* Disposes the one and only system.
|
||||
* @return An indication of success.
|
||||
*/
|
||||
static GHOST_TSuccess disposeSystem();
|
||||
|
||||
/**
|
||||
* Returns a pointer to the one and only system (nil if it hasn't been created).
|
||||
* @return A pointer to the system.
|
||||
*/
|
||||
static GHOST_ISystem* getSystem();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructor.
|
||||
* Protected default constructor to force use of static createSystem member.
|
||||
*/
|
||||
GHOST_ISystem() {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* Protected default constructor to force use of static dispose member.
|
||||
*/
|
||||
virtual ~GHOST_ISystem() {}
|
||||
|
||||
public:
|
||||
/***************************************************************************************
|
||||
** 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 = 0;
|
||||
|
||||
/**
|
||||
* Installs a timer.
|
||||
* Note that, on most operating systems, messages need to be processed in order
|
||||
* for the timer callbacks to be invoked.
|
||||
* @param delay The time to wait for the first call to the timerProc (in milliseconds)
|
||||
* @param interval The interval between calls to the timerProc (in milliseconds)
|
||||
* @param timerProc The callback invoked when the interval expires,
|
||||
* @param userData Placeholder for user data.
|
||||
* @return A timer task (0 if timer task installation failed).
|
||||
*/
|
||||
virtual GHOST_ITimerTask* installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = 0) = 0;
|
||||
|
||||
/**
|
||||
* Removes a timer.
|
||||
* @param timerTask Timer task to be removed.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask* timerTask) = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
** Display/window management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the number of displays on this system.
|
||||
* @return The number of displays.
|
||||
*/
|
||||
virtual GHOST_TUns8 getNumDisplays() const = 0;
|
||||
|
||||
/**
|
||||
* 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 = 0;
|
||||
|
||||
/**
|
||||
* 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 stereoVisual Create a stereo visual for quad buffered stereo.
|
||||
* @param numOfAASamples Number of samples used for AA (zero if no AA)
|
||||
* @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 = false,
|
||||
const GHOST_TUns16 numOfAASamples = 0,
|
||||
const GHOST_TEmbedderWindowID parentWindow = 0) = 0;
|
||||
|
||||
/**
|
||||
* Dispose a window.
|
||||
* @param window Pointer to the window to be disposed.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess disposeWindow(GHOST_IWindow* window) = 0;
|
||||
|
||||
/**
|
||||
* Returns whether a window is valid.
|
||||
* @param window Pointer to the window to be checked.
|
||||
* @return Indication of validity.
|
||||
*/
|
||||
virtual bool validWindow(GHOST_IWindow* window) = 0;
|
||||
|
||||
/**
|
||||
* Begins full screen mode.
|
||||
* @param setting The new setting of the display.
|
||||
* @param window Window displayed in full screen.
|
||||
* This window is invalid after full screen has been ended.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
|
||||
const bool stereoVisual) = 0;
|
||||
|
||||
/**
|
||||
* Ends full screen mode.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess endFullScreen(void) = 0;
|
||||
|
||||
/**
|
||||
* Returns current full screen mode status.
|
||||
* @return The current status.
|
||||
*/
|
||||
virtual bool getFullScreen(void) = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
** Event management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Retrieves 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) = 0;
|
||||
|
||||
/**
|
||||
* Retrieves events from the queue and send them to the event consumers.
|
||||
* @return Indication of the presence of events.
|
||||
*/
|
||||
virtual bool dispatchEvents() = 0;
|
||||
|
||||
/**
|
||||
* Adds the given event consumer to our list.
|
||||
* @param consumer The event consumer to add.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer* consumer) = 0;
|
||||
|
||||
/**
|
||||
* Removes the given event consumer to our list.
|
||||
* @param consumer The event consumer to remove.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer) = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
** N-degree of freedom device management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Starts the N-degree of freedom device manager
|
||||
*/
|
||||
virtual int openNDOF(GHOST_IWindow*,
|
||||
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
|
||||
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
|
||||
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen
|
||||
// original patch only
|
||||
// GHOST_NDOFEventHandler_fp setNdofEventHandler
|
||||
) = 0;
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** 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 = 0;
|
||||
|
||||
/**
|
||||
* Updates the location of the cursor (location in screen coordinates).
|
||||
* Not all operating systems allow the cursor to be moved (without the input device being moved).
|
||||
* @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) = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
** Access to mouse button and keyboard states.
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the state of a modifier key (ouside the message queue).
|
||||
* @param mask The modifier key state to retrieve.
|
||||
* @param isDown The state of a modifier key (true == pressed).
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the state of a mouse button (ouside the message queue).
|
||||
* @param mask The button state to retrieve.
|
||||
* @param isDown Button state.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0;
|
||||
|
||||
/**
|
||||
* Toggles console
|
||||
* @action 0 - Hides
|
||||
* 1 - Shows
|
||||
* 2 - Toggles
|
||||
* 3 - Hides if it runs not from command line
|
||||
* * - Does nothing
|
||||
* @return current status (1 -visible, 0 - hidden)
|
||||
*/
|
||||
virtual int toggleConsole(int action) = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
** Access to clipboard.
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the selection buffer
|
||||
* @return Returns "unsinged char" from X11 XA_CUT_BUFFER0 buffer
|
||||
*
|
||||
*/
|
||||
virtual GHOST_TUns8* getClipboard(bool selection) const = 0;
|
||||
|
||||
/**
|
||||
* Put data to the Clipboard
|
||||
*/
|
||||
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0;
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initialize the system.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess init() = 0;
|
||||
|
||||
/**
|
||||
* Shut the system down.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess exit() = 0;
|
||||
|
||||
/** The one and only system */
|
||||
static GHOST_ISystem* m_system;
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
public:
|
||||
void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GHOST:GHOST_ISystem"); }
|
||||
void operator delete( void *mem ) { MEM_freeN(mem); }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // _GHOST_ISYSTEM_H_
|
||||
|
||||
103
intern/ghost/GHOST_ISystemPaths.h
Normal file
103
intern/ghost/GHOST_ISystemPaths.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/GHOST_ISystemPaths.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_ISYSTEMPATHS_H_
|
||||
#define _GHOST_ISYSTEMPATHS_H_
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
class GHOST_ISystemPaths
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates the one and only system.
|
||||
* @return An indication of success.
|
||||
*/
|
||||
static GHOST_TSuccess create();
|
||||
|
||||
/**
|
||||
* Disposes the one and only system.
|
||||
* @return An indication of success.
|
||||
*/
|
||||
static GHOST_TSuccess dispose();
|
||||
|
||||
/**
|
||||
* Returns a pointer to the one and only system (nil if it hasn't been created).
|
||||
* @return A pointer to the system.
|
||||
*/
|
||||
static GHOST_ISystemPaths* get();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructor.
|
||||
* Protected default constructor to force use of static createSystem member.
|
||||
*/
|
||||
GHOST_ISystemPaths() {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* Protected default constructor to force use of static dispose member.
|
||||
*/
|
||||
virtual ~GHOST_ISystemPaths() {}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Determine the base dir in which shared resources are located. It will first try to use
|
||||
* "unpack and run" path, then look for properly installed path, not including versioning.
|
||||
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
|
||||
*/
|
||||
virtual const GHOST_TUns8* getSystemDir() const = 0;
|
||||
|
||||
/**
|
||||
* Determine the base dir in which user configuration is stored, not including versioning.
|
||||
* If needed, it will create the base directory.
|
||||
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
|
||||
*/
|
||||
virtual const GHOST_TUns8* getUserDir() const = 0;
|
||||
|
||||
/**
|
||||
* Determine the directory of the current binary
|
||||
* @return Unsigned char string pointing to the binary dir
|
||||
*/
|
||||
virtual const GHOST_TUns8* getBinaryDir() const = 0;
|
||||
|
||||
/**
|
||||
* Add the file to the operating system most recently used files
|
||||
*/
|
||||
virtual void addToSystemRecentFiles(const char* filename) const = 0;
|
||||
|
||||
private:
|
||||
/** The one and only system paths*/
|
||||
static GHOST_ISystemPaths* m_systemPaths;
|
||||
};
|
||||
|
||||
#endif
|
||||
96
intern/ghost/GHOST_ITimerTask.h
Normal file
96
intern/ghost/GHOST_ITimerTask.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/GHOST_ITimerTask.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_ITimerTask interface class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_ITIMER_TASK_H_
|
||||
#define _GHOST_ITIMER_TASK_H_
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a timer task.
|
||||
* Timer tasks are created by the system and can be installed by the system.
|
||||
* After installation, the timer callback-procedure or "timerProc" will be called
|
||||
* periodically. You should not need to inherit this class. It is passed to the
|
||||
* application in the timer-callback.<br>
|
||||
* <br>
|
||||
* Note that GHOST processes timers in the UI thread. You should ask GHOST
|
||||
* process messages in order for the timer-callbacks to be called.
|
||||
* @see GHOST_ISystem#installTimer
|
||||
* @see GHOST_TimerProcPtr
|
||||
* @author Maarten Gribnau
|
||||
* @date May 31, 2001
|
||||
*/
|
||||
class GHOST_ITimerTask
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_ITimerTask()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timer callback.
|
||||
* @return The timer callback.
|
||||
*/
|
||||
virtual GHOST_TimerProcPtr getTimerProc() const = 0;
|
||||
|
||||
/**
|
||||
* Changes the timer callback.
|
||||
* @param timerProc The timer callback.
|
||||
*/
|
||||
virtual void setTimerProc(const GHOST_TimerProcPtr timerProc) = 0;
|
||||
|
||||
/**
|
||||
* Returns the timer user data.
|
||||
* @return The timer user data.
|
||||
*/
|
||||
virtual GHOST_TUserDataPtr getUserData() const = 0;
|
||||
|
||||
/**
|
||||
* Changes the time user data.
|
||||
* @param data The timer user data.
|
||||
*/
|
||||
virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
public:
|
||||
void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GHOST:GHOST_ITimerTask"); }
|
||||
void operator delete( void *mem ) { MEM_freeN(mem); }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // _GHOST_ITIMER_TASK_H_
|
||||
|
||||
317
intern/ghost/GHOST_IWindow.h
Normal file
317
intern/ghost/GHOST_IWindow.h
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/GHOST_IWindow.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_IWindow interface class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_IWINDOW_H_
|
||||
#define _GHOST_IWINDOW_H_
|
||||
|
||||
#include "STR_String.h"
|
||||
#include "GHOST_Rect.h"
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
|
||||
/**
|
||||
* Interface for GHOST windows.
|
||||
*
|
||||
* You can create a window with the system's GHOST_ISystem::createWindow
|
||||
* method.
|
||||
* @see GHOST_ISystem#createWindow
|
||||
*
|
||||
* There are two coordinate systems:
|
||||
* <ul>
|
||||
* <li>The screen coordinate system. The origin of the screen is located in the
|
||||
* upper left corner of the screen.</li>
|
||||
* <li>The client rectangle coordinate system. The client rectangle of a window
|
||||
* is the area that is drawable by the application (excluding title bars etc.).
|
||||
* </li>
|
||||
* </ul>
|
||||
* @author Maarten Gribnau
|
||||
* @date May 31, 2001
|
||||
*/
|
||||
class GHOST_IWindow
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_IWindow()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns indication as to whether the window is valid.
|
||||
* @return The validity of the window.
|
||||
*/
|
||||
virtual bool getValid() const = 0;
|
||||
|
||||
/**
|
||||
* Returns the associated OS object/handle
|
||||
* @return The associated OS object/handle
|
||||
*/
|
||||
virtual void* getOSWindow() const = 0;
|
||||
|
||||
/**
|
||||
* Returns the type of drawing context used in this window.
|
||||
* @return The current type of drawing context.
|
||||
*/
|
||||
virtual GHOST_TDrawingContextType getDrawingContextType() = 0;
|
||||
|
||||
/**
|
||||
* 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 setDrawingContextType(GHOST_TDrawingContextType type) = 0;
|
||||
|
||||
/**
|
||||
* 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) = 0;
|
||||
|
||||
/**
|
||||
* Returns the title displayed in the title bar.
|
||||
* @param title The title displayed in the title bar.
|
||||
*/
|
||||
virtual void getTitle(STR_String& title) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the window rectangle dimensions.
|
||||
* These are screen coordinates.
|
||||
* @param bounds The bounding rectangle of the window.
|
||||
*/
|
||||
virtual void getWindowBounds(GHOST_Rect& bounds) const = 0;
|
||||
|
||||
/**
|
||||
* Returns the client rectangle dimensions.
|
||||
* The left and top members of the rectangle are always zero.
|
||||
* @param bounds The bounding rectangle of the client area of the window.
|
||||
*/
|
||||
virtual void getClientBounds(GHOST_Rect& bounds) const = 0;
|
||||
|
||||
/**
|
||||
* Resizes client rectangle width.
|
||||
* @param width The new width of the client area of the window.
|
||||
*/
|
||||
virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
|
||||
|
||||
/**
|
||||
* Resizes client rectangle height.
|
||||
* @param height The new height of the client area of the window.
|
||||
*/
|
||||
virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0;
|
||||
|
||||
/**
|
||||
* 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) = 0;
|
||||
|
||||
/**
|
||||
* 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 = 0;
|
||||
|
||||
/**
|
||||
* 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 = 0;
|
||||
|
||||
/**
|
||||
* Tells if the ongoing drag'n'drop object can be accepted upon mouse drop
|
||||
*/
|
||||
virtual void setAcceptDragOperation(bool canAccept) = 0;
|
||||
|
||||
/**
|
||||
* Returns acceptance of the dropped object
|
||||
* Usually called by the "object dropped" event handling function
|
||||
*/
|
||||
virtual bool canAcceptDragOperation() const = 0;
|
||||
|
||||
/**
|
||||
* Returns the state of the window (normal, minimized, maximized).
|
||||
* @return The state of the window.
|
||||
*/
|
||||
virtual GHOST_TWindowState getState() const = 0;
|
||||
|
||||
/**
|
||||
* 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) = 0;
|
||||
|
||||
/**
|
||||
* Sets the window "modified" status, indicating unsaved changes
|
||||
* @param isUnsavedChanges Unsaved changes or not
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges) = 0;
|
||||
|
||||
/**
|
||||
* Gets the window "modified" status, indicating unsaved changes
|
||||
* @return True if there are unsaved changes
|
||||
*/
|
||||
virtual bool getModifiedState() = 0;
|
||||
|
||||
/**
|
||||
* 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) = 0;
|
||||
|
||||
/**
|
||||
* Swaps front and back buffers of a window.
|
||||
* @return A boolean success indicator.
|
||||
*/
|
||||
virtual GHOST_TSuccess swapBuffers() = 0;
|
||||
|
||||
/**
|
||||
* Activates the drawing context of this window.
|
||||
* @return A boolean success indicator.
|
||||
*/
|
||||
virtual GHOST_TSuccess activateDrawingContext() = 0;
|
||||
|
||||
/**
|
||||
* Invalidates the contents of this window.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess invalidate() = 0;
|
||||
|
||||
/**
|
||||
* Returns the window user data.
|
||||
* @return The window user data.
|
||||
*/
|
||||
virtual GHOST_TUserDataPtr getUserData() const = 0;
|
||||
|
||||
/**
|
||||
* Changes the window user data.
|
||||
* @param data The window user data.
|
||||
*/
|
||||
virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
|
||||
|
||||
/**
|
||||
* Returns the tablet data (pressure etc).
|
||||
* @return The tablet data (pressure etc).
|
||||
*/
|
||||
virtual const GHOST_TabletData* GetTabletData() = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
** Progress bar functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Sets the progress bar value displayed in the window/application icon
|
||||
* @param progress The progress %
|
||||
*/
|
||||
virtual GHOST_TSuccess setProgressBar(float progress) = 0;
|
||||
|
||||
/**
|
||||
* Hides the progress bar in the icon
|
||||
*/
|
||||
virtual GHOST_TSuccess endProgressBar() = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
** Cursor management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the current cursor shape.
|
||||
* @return The current cursor shape.
|
||||
*/
|
||||
virtual GHOST_TStandardCursor getCursorShape() const = 0;
|
||||
|
||||
/**
|
||||
* Set the shape of the cursor.
|
||||
* @param cursor The new cursor shape type id.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0;
|
||||
|
||||
/**
|
||||
* Set the shape of the cursor to a custom cursor.
|
||||
* @param bitmap The bitmap data for the cursor.
|
||||
* @param mask The mask data for the cursor.
|
||||
* @param hotX The X coordinate of the cursor hotspot.
|
||||
* @param hotY The Y coordinate of the cursor hotspot.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2],
|
||||
GHOST_TUns8 mask[16][2],
|
||||
int hotX,
|
||||
int hotY) = 0;
|
||||
|
||||
virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask,
|
||||
int sizex, int sizey,
|
||||
int hotX, int hotY,
|
||||
int fg_color, int bg_color) = 0;
|
||||
|
||||
/**
|
||||
* Returns the visibility state of the cursor.
|
||||
* @return The visibility state of the cursor.
|
||||
*/
|
||||
virtual bool getCursorVisibility() const = 0;
|
||||
|
||||
/**
|
||||
* Shows or hides the cursor.
|
||||
* @param visible The new visibility state of the cursor.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0;
|
||||
|
||||
/**
|
||||
* Grabs the cursor for a modal operation.
|
||||
* @param grab The new grab state of the cursor.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds) { return GHOST_kSuccess; };
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
public:
|
||||
void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GHOST:GHOST_IWindow"); }
|
||||
void operator delete( void *mem ) { MEM_freeN(mem); }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // _GHOST_IWINDOW_H_
|
||||
|
||||
87
intern/ghost/GHOST_Path-api.h
Normal file
87
intern/ghost/GHOST_Path-api.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2010 by Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/GHOST_Path-api.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GHOST_PATH_API_H
|
||||
#define GHOST_PATH_API_H
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
GHOST_DECLARE_HANDLE(GHOST_SystemPathsHandle);
|
||||
|
||||
/**
|
||||
* Creates the one and only instance of the system path access.
|
||||
* @return An indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_CreateSystemPaths(void);
|
||||
|
||||
/**
|
||||
* Disposes the one and only system.
|
||||
* @return An indication of success.
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_DisposeSystemPaths(void);
|
||||
|
||||
/**
|
||||
* Determine the base dir in which shared resources are located. It will first try to use
|
||||
* "unpack and run" path, then look for properly installed path, not including versioning.
|
||||
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
|
||||
*/
|
||||
extern const GHOST_TUns8* GHOST_getSystemDir(void);
|
||||
|
||||
/**
|
||||
* Determine the base dir in which user configuration is stored, not including versioning.
|
||||
* @return Unsigned char string pointing to user dir (eg ~).
|
||||
*/
|
||||
extern const GHOST_TUns8* GHOST_getUserDir(void);
|
||||
|
||||
|
||||
/**
|
||||
* Determine the dir in which the binary file is found.
|
||||
* @return Unsigned char string pointing to binary dir (eg ~/usr/local/bin/).
|
||||
*/
|
||||
extern const GHOST_TUns8* GHOST_getBinaryDir(void);
|
||||
|
||||
/**
|
||||
* Add the file to the operating system most recently used files
|
||||
*/
|
||||
extern void GHOST_addToSystemRecentFiles(const char* filename);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
259
intern/ghost/GHOST_Rect.h
Normal file
259
intern/ghost/GHOST_Rect.h
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_Debug.h
|
||||
* \ingroup GHOST
|
||||
* Macro's used in GHOST debug target.
|
||||
*/
|
||||
|
||||
#ifndef _H_GHOST_Rect
|
||||
#define _H_GHOST_Rect
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
|
||||
/**
|
||||
* Implements rectangle functionality.
|
||||
* The four extreme coordinates are stored as left, top, right and bottom.
|
||||
* To be valid, a rectangle should have a left coordinate smaller than or equal to right.
|
||||
* To be valid, a rectangle should have a top coordinate smaller than or equal to bottom.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 10, 2001
|
||||
*/
|
||||
|
||||
class GHOST_Rect {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a rectangle with the given values.
|
||||
* @param l requested left coordinate of the rectangle
|
||||
* @param t requested top coordinate of the rectangle
|
||||
* @param r requested right coordinate of the rectangle
|
||||
* @param b requested bottom coordinate of the rectangle
|
||||
*/
|
||||
GHOST_Rect(GHOST_TInt32 l=0, GHOST_TInt32 t=0, GHOST_TInt32 r=0, GHOST_TInt32 b=0)
|
||||
: m_l(l), m_t(t), m_r(r), m_b(b) {}
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
* @param r rectangle to copy
|
||||
*/
|
||||
GHOST_Rect(const GHOST_Rect& r)
|
||||
: m_l(r.m_l), m_t(r.m_t), m_r(r.m_r), m_b(r.m_b) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_Rect() {};
|
||||
|
||||
/**
|
||||
* Access to rectangle width.
|
||||
* @return width of the rectangle
|
||||
*/
|
||||
virtual inline GHOST_TInt32 getWidth() const;
|
||||
|
||||
/**
|
||||
* Access to rectangle height.
|
||||
* @return height of the rectangle
|
||||
*/
|
||||
virtual inline GHOST_TInt32 getHeight() const;
|
||||
|
||||
/**
|
||||
* Sets all members of the rectangle.
|
||||
* @param l requested left coordinate of the rectangle
|
||||
* @param t requested top coordinate of the rectangle
|
||||
* @param r requested right coordinate of the rectangle
|
||||
* @param b requested bottom coordinate of the rectangle
|
||||
*/
|
||||
virtual inline void set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b);
|
||||
|
||||
/**
|
||||
* Returns whether this rectangle is empty.
|
||||
* Empty rectangles are rectangles that have width==0 and/or height==0.
|
||||
* @return boolean value (true==empty rectangle)
|
||||
*/
|
||||
virtual inline bool isEmpty() const;
|
||||
|
||||
/**
|
||||
* Returns whether this rectangle is valid.
|
||||
* Valid rectangles are rectangles that have m_l <= m_r and m_t <= m_b. Thus, emapty rectangles are valid.
|
||||
* @return boolean value (true==valid rectangle)
|
||||
*/
|
||||
virtual inline bool isValid() const;
|
||||
|
||||
/**
|
||||
* Grows (or shrinks the rectangle).
|
||||
* The method avoids negative insets making the rectangle invalid
|
||||
* @param i The amount of offset given to each extreme (negative values shrink the rectangle).
|
||||
*/
|
||||
virtual void inset(GHOST_TInt32 i);
|
||||
|
||||
/**
|
||||
* Does a union of the rectangle given and this rectangle.
|
||||
* The result is stored in this rectangle.
|
||||
* @param r The rectangle that is input for the union operation.
|
||||
*/
|
||||
virtual inline void unionRect(const GHOST_Rect& r);
|
||||
|
||||
/**
|
||||
* Grows the rectangle to included a point.
|
||||
* @param x The x-coordinate of the point.
|
||||
* @param y The y-coordinate of the point.
|
||||
*/
|
||||
virtual inline void unionPoint(GHOST_TInt32 x, GHOST_TInt32 y);
|
||||
|
||||
/**
|
||||
* Grows the rectangle to included a point.
|
||||
* @param x The x-coordinate of the point.
|
||||
* @param y The y-coordinate of the point.
|
||||
*/
|
||||
virtual inline void wrapPoint(GHOST_TInt32 &x, GHOST_TInt32 &y, GHOST_TInt32 ofs);
|
||||
|
||||
/**
|
||||
* Returns whether the point is inside this rectangle.
|
||||
* Point on the boundary is considered inside.
|
||||
* @param x x-coordinate of point to test.
|
||||
* @param y y-coordinate of point to test.
|
||||
* @return boolean value (true if point is inside).
|
||||
*/
|
||||
virtual inline bool isInside(GHOST_TInt32 x, GHOST_TInt32 y) const;
|
||||
|
||||
/**
|
||||
* Returns whether the rectangle is inside this rectangle.
|
||||
* @param r rectangle to test.
|
||||
* @return visibility (not, partially or fully visible).
|
||||
*/
|
||||
virtual GHOST_TVisibility getVisibility(GHOST_Rect& r) const;
|
||||
|
||||
/**
|
||||
* Sets rectangle members.
|
||||
* Sets rectangle members such that it is centered at the given location.
|
||||
* @param cx requested center x-coordinate of the rectangle
|
||||
* @param cy requested center y-coordinate of the rectangle
|
||||
*/
|
||||
virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy);
|
||||
|
||||
/**
|
||||
* Sets rectangle members.
|
||||
* Sets rectangle members such that it is centered at the given location,
|
||||
* with the width requested.
|
||||
* @param cx requested center x-coordinate of the rectangle
|
||||
* @param cy requested center y-coordinate of the rectangle
|
||||
* @param w requested width of the rectangle
|
||||
* @param h requested height of the rectangle
|
||||
*/
|
||||
virtual void setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h);
|
||||
|
||||
/**
|
||||
* Clips a rectangle.
|
||||
* Updates the rectangle given such that it will fit within this one.
|
||||
* This can result in an empty rectangle.
|
||||
* @param r the rectangle to clip
|
||||
* @return whether clipping has occurred
|
||||
*/
|
||||
virtual bool clip(GHOST_Rect& r) const;
|
||||
|
||||
/** Left coordinate of the rectangle */
|
||||
GHOST_TInt32 m_l;
|
||||
/** Top coordinate of the rectangle */
|
||||
GHOST_TInt32 m_t;
|
||||
/** Right coordinate of the rectangle */
|
||||
GHOST_TInt32 m_r;
|
||||
/** Bottom coordinate of the rectangle */
|
||||
GHOST_TInt32 m_b;
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
public:
|
||||
void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GHOST:GHOST_Rect"); }
|
||||
void operator delete( void *mem ) { MEM_freeN(mem); }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
inline GHOST_TInt32 GHOST_Rect::getWidth() const
|
||||
{
|
||||
return m_r - m_l;
|
||||
}
|
||||
|
||||
inline GHOST_TInt32 GHOST_Rect::getHeight() const
|
||||
{
|
||||
return m_b - m_t;
|
||||
}
|
||||
|
||||
inline void GHOST_Rect::set(GHOST_TInt32 l, GHOST_TInt32 t, GHOST_TInt32 r, GHOST_TInt32 b)
|
||||
{
|
||||
m_l = l; m_t = t; m_r = r; m_b = b;
|
||||
}
|
||||
|
||||
inline bool GHOST_Rect::isEmpty() const
|
||||
{
|
||||
return (getWidth() == 0) || (getHeight() == 0);
|
||||
}
|
||||
|
||||
inline bool GHOST_Rect::isValid() const
|
||||
{
|
||||
return (m_l <= m_r) && (m_t <= m_b);
|
||||
}
|
||||
|
||||
inline void GHOST_Rect::unionRect(const GHOST_Rect& r)
|
||||
{
|
||||
if (r.m_l < m_l) m_l = r.m_l;
|
||||
if (r.m_r > m_r) m_r = r.m_r;
|
||||
if (r.m_t < m_t) m_t = r.m_t;
|
||||
if (r.m_b > m_b) m_b = r.m_b;
|
||||
}
|
||||
|
||||
inline void GHOST_Rect::unionPoint(GHOST_TInt32 x, GHOST_TInt32 y)
|
||||
{
|
||||
if (x < m_l) m_l = x;
|
||||
if (x > m_r) m_r = x;
|
||||
if (y < m_t) m_t = y;
|
||||
if (y > m_b) m_b = y;
|
||||
}
|
||||
#include <stdio.h>
|
||||
inline void GHOST_Rect::wrapPoint(GHOST_TInt32 &x, GHOST_TInt32 &y, GHOST_TInt32 ofs)
|
||||
{
|
||||
GHOST_TInt32 w= getWidth();
|
||||
GHOST_TInt32 h= getHeight();
|
||||
|
||||
/* highly unlikely but avoid eternal loop */
|
||||
if(w-ofs*2 <= 0 || h-ofs*2 <= 0)
|
||||
return;
|
||||
while(x-ofs < m_l) x+= w-(ofs*2);
|
||||
while(y-ofs < m_t) y+= h-(ofs*2);
|
||||
while(x+ofs > m_r) x-= w-(ofs*2);
|
||||
while(y+ofs > m_b) y-= h-(ofs*2);
|
||||
}
|
||||
|
||||
inline bool GHOST_Rect::isInside(GHOST_TInt32 x, GHOST_TInt32 y) const
|
||||
{
|
||||
return (x >= m_l) && (x <= m_r) && (y >= m_t) && (y <= m_b);
|
||||
}
|
||||
|
||||
#endif // _H_GHOST_Rect
|
||||
|
||||
516
intern/ghost/GHOST_Types.h
Normal file
516
intern/ghost/GHOST_Types.h
Normal file
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/GHOST_Types.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GHOST_TYPES_H_
|
||||
#define _GHOST_TYPES_H_
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
#include "MEM_guardedalloc.h"
|
||||
#endif
|
||||
|
||||
#define GHOST_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
|
||||
|
||||
typedef char GHOST_TInt8;
|
||||
typedef unsigned char GHOST_TUns8;
|
||||
typedef short GHOST_TInt16;
|
||||
typedef unsigned short GHOST_TUns16;
|
||||
typedef int GHOST_TInt32;
|
||||
typedef unsigned int GHOST_TUns32;
|
||||
|
||||
#ifdef WIN32
|
||||
#define WM_BLND_NDOF_AXIS WM_USER + 1
|
||||
#define WM_BLND_NDOF_BTN WM_USER + 2
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(FREE_WINDOWS)
|
||||
typedef __int64 GHOST_TInt64;
|
||||
typedef unsigned __int64 GHOST_TUns64;
|
||||
#else
|
||||
typedef long long GHOST_TInt64;
|
||||
typedef unsigned long long GHOST_TUns64;
|
||||
#endif
|
||||
|
||||
typedef void* GHOST_TUserDataPtr;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GHOST_kFailure = 0,
|
||||
GHOST_kSuccess
|
||||
} GHOST_TSuccess;
|
||||
|
||||
/* Xtilt and Ytilt represent how much the pen is tilted away from
|
||||
* vertically upright in either the X or Y direction, with X and Y the
|
||||
* axes of the tablet surface.
|
||||
* In other words, Xtilt and Ytilt are components of a vector created by projecting
|
||||
* the pen's angle in 3D space vertically downwards on to the XY plane
|
||||
* --Matt
|
||||
*/
|
||||
typedef enum {
|
||||
GHOST_kTabletModeNone = 0,
|
||||
GHOST_kTabletModeStylus,
|
||||
GHOST_kTabletModeEraser
|
||||
} GHOST_TTabletMode;
|
||||
|
||||
typedef struct GHOST_TabletData {
|
||||
GHOST_TTabletMode Active; /* 0=None, 1=Stylus, 2=Eraser */
|
||||
float Pressure; /* range 0.0 (not touching) to 1.0 (full pressure) */
|
||||
float Xtilt; /* range 0.0 (upright) to 1.0 (tilted fully against the tablet surface) */
|
||||
float Ytilt; /* as above */
|
||||
} GHOST_TabletData;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GHOST_kNotVisible = 0,
|
||||
GHOST_kPartiallyVisible,
|
||||
GHOST_kFullyVisible
|
||||
} GHOST_TVisibility;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GHOST_kFireTimeNever = 0xFFFFFFFF
|
||||
} GHOST_TFireTimeConstant;
|
||||
|
||||
typedef enum {
|
||||
GHOST_kModifierKeyLeftShift = 0,
|
||||
GHOST_kModifierKeyRightShift,
|
||||
GHOST_kModifierKeyLeftAlt,
|
||||
GHOST_kModifierKeyRightAlt,
|
||||
GHOST_kModifierKeyLeftControl,
|
||||
GHOST_kModifierKeyRightControl,
|
||||
GHOST_kModifierKeyOS,
|
||||
GHOST_kModifierKeyNumMasks
|
||||
} GHOST_TModifierKeyMask;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GHOST_kWindowStateNormal = 0,
|
||||
GHOST_kWindowStateMaximized,
|
||||
GHOST_kWindowStateMinimized,
|
||||
GHOST_kWindowStateFullScreen,
|
||||
GHOST_kWindowStateEmbedded,
|
||||
GHOST_kWindowState8Normal = 8,
|
||||
GHOST_kWindowState8Maximized,
|
||||
GHOST_kWindowState8Minimized,
|
||||
GHOST_kWindowState8FullScreen,
|
||||
GHOST_kWindowStateModified,
|
||||
GHOST_kWindowStateUnModified
|
||||
} GHOST_TWindowState;
|
||||
|
||||
|
||||
/** Constants for the answer to the blender exit request */
|
||||
typedef enum {
|
||||
GHOST_kExitCancel = 0,
|
||||
GHOST_kExitNow
|
||||
} GHOST_TExitRequestResponse;
|
||||
|
||||
typedef enum {
|
||||
GHOST_kWindowOrderTop = 0,
|
||||
GHOST_kWindowOrderBottom
|
||||
} GHOST_TWindowOrder;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GHOST_kDrawingContextTypeNone = 0,
|
||||
GHOST_kDrawingContextTypeOpenGL
|
||||
} GHOST_TDrawingContextType;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GHOST_kButtonMaskLeft = 0,
|
||||
GHOST_kButtonMaskMiddle,
|
||||
GHOST_kButtonMaskRight,
|
||||
GHOST_kButtonMaskButton4,
|
||||
GHOST_kButtonMaskButton5,
|
||||
GHOST_kButtonNumMasks
|
||||
} GHOST_TButtonMask;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GHOST_kEventUnknown = 0,
|
||||
|
||||
GHOST_kEventCursorMove, /// Mouse move event
|
||||
GHOST_kEventButtonDown, /// Mouse button event
|
||||
GHOST_kEventButtonUp, /// Mouse button event
|
||||
GHOST_kEventWheel, /// Mouse wheel event
|
||||
GHOST_kEventTrackpad, /// Trackpad event
|
||||
|
||||
GHOST_kEventNDOFMotion, /// N degree of freedom device motion event
|
||||
GHOST_kEventNDOFButton, /// N degree of freedom device button event
|
||||
|
||||
GHOST_kEventKeyDown,
|
||||
GHOST_kEventKeyUp,
|
||||
// GHOST_kEventKeyAuto,
|
||||
|
||||
GHOST_kEventQuit,
|
||||
|
||||
GHOST_kEventWindowClose,
|
||||
GHOST_kEventWindowActivate,
|
||||
GHOST_kEventWindowDeactivate,
|
||||
GHOST_kEventWindowUpdate,
|
||||
GHOST_kEventWindowSize,
|
||||
GHOST_kEventWindowMove,
|
||||
|
||||
GHOST_kEventDraggingEntered,
|
||||
GHOST_kEventDraggingUpdated,
|
||||
GHOST_kEventDraggingExited,
|
||||
GHOST_kEventDraggingDropDone,
|
||||
|
||||
GHOST_kEventOpenMainFile, // Needed for Cocoa to open double-clicked .blend file at startup
|
||||
|
||||
GHOST_kEventTimer,
|
||||
|
||||
GHOST_kNumEventTypes
|
||||
} GHOST_TEventType;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GHOST_kStandardCursorFirstCursor = 0,
|
||||
GHOST_kStandardCursorDefault = 0,
|
||||
GHOST_kStandardCursorRightArrow,
|
||||
GHOST_kStandardCursorLeftArrow,
|
||||
GHOST_kStandardCursorInfo,
|
||||
GHOST_kStandardCursorDestroy,
|
||||
GHOST_kStandardCursorHelp,
|
||||
GHOST_kStandardCursorCycle,
|
||||
GHOST_kStandardCursorSpray,
|
||||
GHOST_kStandardCursorWait,
|
||||
GHOST_kStandardCursorText,
|
||||
GHOST_kStandardCursorCrosshair,
|
||||
GHOST_kStandardCursorUpDown,
|
||||
GHOST_kStandardCursorLeftRight,
|
||||
GHOST_kStandardCursorTopSide,
|
||||
GHOST_kStandardCursorBottomSide,
|
||||
GHOST_kStandardCursorLeftSide,
|
||||
GHOST_kStandardCursorRightSide,
|
||||
GHOST_kStandardCursorTopLeftCorner,
|
||||
GHOST_kStandardCursorTopRightCorner,
|
||||
GHOST_kStandardCursorBottomRightCorner,
|
||||
GHOST_kStandardCursorBottomLeftCorner,
|
||||
GHOST_kStandardCursorCopy,
|
||||
GHOST_kStandardCursorCustom,
|
||||
GHOST_kStandardCursorNumCursors,
|
||||
GHOST_kStandardCursorPencil
|
||||
} GHOST_TStandardCursor;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GHOST_kKeyUnknown = -1,
|
||||
GHOST_kKeyBackSpace,
|
||||
GHOST_kKeyTab,
|
||||
GHOST_kKeyLinefeed,
|
||||
GHOST_kKeyClear,
|
||||
GHOST_kKeyEnter = 0x0D,
|
||||
|
||||
GHOST_kKeyEsc = 0x1B,
|
||||
GHOST_kKeySpace = ' ',
|
||||
GHOST_kKeyQuote = 0x27,
|
||||
GHOST_kKeyComma = ',',
|
||||
GHOST_kKeyMinus = '-',
|
||||
GHOST_kKeyPeriod = '.',
|
||||
GHOST_kKeySlash = '/',
|
||||
|
||||
// Number keys
|
||||
GHOST_kKey0 = '0',
|
||||
GHOST_kKey1,
|
||||
GHOST_kKey2,
|
||||
GHOST_kKey3,
|
||||
GHOST_kKey4,
|
||||
GHOST_kKey5,
|
||||
GHOST_kKey6,
|
||||
GHOST_kKey7,
|
||||
GHOST_kKey8,
|
||||
GHOST_kKey9,
|
||||
|
||||
GHOST_kKeySemicolon = ';',
|
||||
GHOST_kKeyEqual = '=',
|
||||
|
||||
// Character keys
|
||||
GHOST_kKeyA = 'A',
|
||||
GHOST_kKeyB,
|
||||
GHOST_kKeyC,
|
||||
GHOST_kKeyD,
|
||||
GHOST_kKeyE,
|
||||
GHOST_kKeyF,
|
||||
GHOST_kKeyG,
|
||||
GHOST_kKeyH,
|
||||
GHOST_kKeyI,
|
||||
GHOST_kKeyJ,
|
||||
GHOST_kKeyK,
|
||||
GHOST_kKeyL,
|
||||
GHOST_kKeyM,
|
||||
GHOST_kKeyN,
|
||||
GHOST_kKeyO,
|
||||
GHOST_kKeyP,
|
||||
GHOST_kKeyQ,
|
||||
GHOST_kKeyR,
|
||||
GHOST_kKeyS,
|
||||
GHOST_kKeyT,
|
||||
GHOST_kKeyU,
|
||||
GHOST_kKeyV,
|
||||
GHOST_kKeyW,
|
||||
GHOST_kKeyX,
|
||||
GHOST_kKeyY,
|
||||
GHOST_kKeyZ,
|
||||
|
||||
GHOST_kKeyLeftBracket = '[',
|
||||
GHOST_kKeyRightBracket = ']',
|
||||
GHOST_kKeyBackslash = 0x5C,
|
||||
GHOST_kKeyAccentGrave = '`',
|
||||
|
||||
|
||||
GHOST_kKeyLeftShift = 0x100,
|
||||
GHOST_kKeyRightShift,
|
||||
GHOST_kKeyLeftControl,
|
||||
GHOST_kKeyRightControl,
|
||||
GHOST_kKeyLeftAlt,
|
||||
GHOST_kKeyRightAlt,
|
||||
GHOST_kKeyOS, // Command key on Apple, Windows key(s) on Windows
|
||||
GHOST_kKeyGrLess , // German PC only!
|
||||
|
||||
GHOST_kKeyCapsLock,
|
||||
GHOST_kKeyNumLock,
|
||||
GHOST_kKeyScrollLock,
|
||||
|
||||
GHOST_kKeyLeftArrow,
|
||||
GHOST_kKeyRightArrow,
|
||||
GHOST_kKeyUpArrow,
|
||||
GHOST_kKeyDownArrow,
|
||||
|
||||
GHOST_kKeyPrintScreen,
|
||||
GHOST_kKeyPause,
|
||||
|
||||
GHOST_kKeyInsert,
|
||||
GHOST_kKeyDelete,
|
||||
GHOST_kKeyHome,
|
||||
GHOST_kKeyEnd,
|
||||
GHOST_kKeyUpPage,
|
||||
GHOST_kKeyDownPage,
|
||||
|
||||
// Numpad keys
|
||||
GHOST_kKeyNumpad0,
|
||||
GHOST_kKeyNumpad1,
|
||||
GHOST_kKeyNumpad2,
|
||||
GHOST_kKeyNumpad3,
|
||||
GHOST_kKeyNumpad4,
|
||||
GHOST_kKeyNumpad5,
|
||||
GHOST_kKeyNumpad6,
|
||||
GHOST_kKeyNumpad7,
|
||||
GHOST_kKeyNumpad8,
|
||||
GHOST_kKeyNumpad9,
|
||||
GHOST_kKeyNumpadPeriod,
|
||||
GHOST_kKeyNumpadEnter,
|
||||
GHOST_kKeyNumpadPlus,
|
||||
GHOST_kKeyNumpadMinus,
|
||||
GHOST_kKeyNumpadAsterisk,
|
||||
GHOST_kKeyNumpadSlash,
|
||||
|
||||
// Function keys
|
||||
GHOST_kKeyF1,
|
||||
GHOST_kKeyF2,
|
||||
GHOST_kKeyF3,
|
||||
GHOST_kKeyF4,
|
||||
GHOST_kKeyF5,
|
||||
GHOST_kKeyF6,
|
||||
GHOST_kKeyF7,
|
||||
GHOST_kKeyF8,
|
||||
GHOST_kKeyF9,
|
||||
GHOST_kKeyF10,
|
||||
GHOST_kKeyF11,
|
||||
GHOST_kKeyF12,
|
||||
GHOST_kKeyF13,
|
||||
GHOST_kKeyF14,
|
||||
GHOST_kKeyF15,
|
||||
GHOST_kKeyF16,
|
||||
GHOST_kKeyF17,
|
||||
GHOST_kKeyF18,
|
||||
GHOST_kKeyF19,
|
||||
GHOST_kKeyF20,
|
||||
GHOST_kKeyF21,
|
||||
GHOST_kKeyF22,
|
||||
GHOST_kKeyF23,
|
||||
GHOST_kKeyF24,
|
||||
|
||||
// Multimedia keypad buttons
|
||||
GHOST_kKeyMediaPlay,
|
||||
GHOST_kKeyMediaStop,
|
||||
GHOST_kKeyMediaFirst,
|
||||
GHOST_kKeyMediaLast
|
||||
} GHOST_TKey;
|
||||
|
||||
typedef enum {
|
||||
GHOST_kGrabDisable = 0, /* grab not set */
|
||||
GHOST_kGrabNormal, /* no cursor adjustments */
|
||||
GHOST_kGrabWrap, /* wrap the mouse location to prevent limiting screen bounds */
|
||||
GHOST_kGrabHide, /* hide the mouse while grabbing and restore the original location on release (numbuts) */
|
||||
} GHOST_TGrabCursorMode;
|
||||
|
||||
typedef void* GHOST_TEventDataPtr;
|
||||
|
||||
typedef struct {
|
||||
/** The x-coordinate of the cursor position. */
|
||||
GHOST_TInt32 x;
|
||||
/** The y-coordinate of the cursor position. */
|
||||
GHOST_TInt32 y;
|
||||
} GHOST_TEventCursorData;
|
||||
|
||||
typedef struct {
|
||||
/** The mask of the mouse button. */
|
||||
GHOST_TButtonMask button;
|
||||
} GHOST_TEventButtonData;
|
||||
|
||||
typedef struct {
|
||||
/** Displacement of a mouse wheel. */
|
||||
GHOST_TInt32 z;
|
||||
} GHOST_TEventWheelData;
|
||||
|
||||
typedef enum {
|
||||
GHOST_kTrackpadEventUnknown =0,
|
||||
GHOST_kTrackpadEventScroll,
|
||||
GHOST_kTrackpadEventRotate,
|
||||
GHOST_kTrackpadEventSwipe, /* Reserved, not used for now */
|
||||
GHOST_kTrackpadEventMagnify
|
||||
} GHOST_TTrackpadEventSubTypes;
|
||||
|
||||
|
||||
typedef struct {
|
||||
/** The event subtype */
|
||||
GHOST_TTrackpadEventSubTypes subtype;
|
||||
/** The x-location of the trackpad event */
|
||||
GHOST_TInt32 x;
|
||||
/** The y-location of the trackpad event */
|
||||
GHOST_TInt32 y;
|
||||
/** The x-delta or value of the trackpad event */
|
||||
GHOST_TInt32 deltaX;
|
||||
/** The y-delta (currently only for scroll subtype) of the trackpad event */
|
||||
GHOST_TInt32 deltaY;
|
||||
} GHOST_TEventTrackpadData;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GHOST_kDragnDropTypeUnknown =0,
|
||||
GHOST_kDragnDropTypeFilenames, /*Array of strings representing file names (full path) */
|
||||
GHOST_kDragnDropTypeString, /* Unformatted text UTF-8 string */
|
||||
GHOST_kDragnDropTypeBitmap /*Bitmap image data */
|
||||
} GHOST_TDragnDropTypes;
|
||||
|
||||
typedef struct {
|
||||
/** The x-coordinate of the cursor position. */
|
||||
GHOST_TInt32 x;
|
||||
/** The y-coordinate of the cursor position. */
|
||||
GHOST_TInt32 y;
|
||||
/** The dropped item type */
|
||||
GHOST_TDragnDropTypes dataType;
|
||||
/** The "dropped content" */
|
||||
GHOST_TEventDataPtr data;
|
||||
} GHOST_TEventDragnDropData;
|
||||
|
||||
typedef struct {
|
||||
int count;
|
||||
GHOST_TUns8 **strings;
|
||||
} GHOST_TStringArray;
|
||||
|
||||
|
||||
/* original patch used floats, but the driver return ints and uns. We will calibrate in view, no sense on doing conversions twice */
|
||||
/* as all USB device controls are likely to use ints, this is also more future proof */
|
||||
//typedef struct {
|
||||
// /** N-degree of freedom device data */
|
||||
// float tx, ty, tz; /** -x left, +y up, +z forward */
|
||||
// float rx, ry, rz;
|
||||
// float dt;
|
||||
//} GHOST_TEventNDOFData;
|
||||
|
||||
typedef struct {
|
||||
/** N-degree of freedom device data v2*/
|
||||
int changed;
|
||||
GHOST_TUns64 client;
|
||||
GHOST_TUns64 address;
|
||||
GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */
|
||||
GHOST_TInt16 rx, ry, rz;
|
||||
GHOST_TInt16 buttons;
|
||||
GHOST_TUns64 time;
|
||||
GHOST_TUns64 delta;
|
||||
} GHOST_TEventNDOFData;
|
||||
|
||||
typedef int (*GHOST_NDOFLibraryInit_fp)(void);
|
||||
typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle);
|
||||
typedef void* (*GHOST_NDOFDeviceOpen_fp)(void* platformData);
|
||||
|
||||
// original patch windows callback. In mac os X version the callback is internal to the plug-in and post an event to main thead.
|
||||
// not necessary faster, but better integration with other events.
|
||||
|
||||
//typedef int (*GHOST_NDOFEventHandler_fp)(float* result7, void* deviceHandle, unsigned int message, unsigned int* wParam, unsigned long* lParam);
|
||||
//typedef void (*GHOST_NDOFCallBack_fp)(GHOST_TEventNDOFDataV2 *VolDatas);
|
||||
|
||||
typedef struct {
|
||||
/** The key code. */
|
||||
GHOST_TKey key;
|
||||
/** The ascii code for the key event ('\0' if none). */
|
||||
char ascii;
|
||||
} GHOST_TEventKeyData;
|
||||
|
||||
typedef struct {
|
||||
/** Number of pixels on a line. */
|
||||
GHOST_TUns32 xPixels;
|
||||
/** Number of lines. */
|
||||
GHOST_TUns32 yPixels;
|
||||
/** Numberof bits per pixel. */
|
||||
GHOST_TUns32 bpp;
|
||||
/** Refresh rate (in Hertz). */
|
||||
GHOST_TUns32 frequency;
|
||||
} GHOST_DisplaySetting;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef long GHOST_TEmbedderWindowID;
|
||||
#endif // _WIN32
|
||||
|
||||
#ifndef _WIN32
|
||||
// I can't use "Window" from "<X11/Xlib.h>" because it conflits with Window defined in winlay.h
|
||||
typedef int GHOST_TEmbedderWindowID;
|
||||
#endif // _WIN32
|
||||
|
||||
/**
|
||||
* A timer task callback routine.
|
||||
* @param task The timer task object.
|
||||
* @param time The current time.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
class GHOST_ITimerTask;
|
||||
typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask* task, GHOST_TUns64 time);
|
||||
#else
|
||||
struct GHOST_TimerTaskHandle__;
|
||||
typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__* task, GHOST_TUns64 time);
|
||||
#endif
|
||||
|
||||
#endif // _GHOST_TYPES_H_
|
||||
|
||||
70
intern/ghost/SConscript
Normal file
70
intern/ghost/SConscript
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/python
|
||||
import sys
|
||||
import os
|
||||
|
||||
Import ('env')
|
||||
|
||||
window_system = env['OURPLATFORM']
|
||||
|
||||
sources = env.Glob('intern/*.cpp')
|
||||
if window_system == 'darwin':
|
||||
sources += env.Glob('intern/*.mm')
|
||||
|
||||
|
||||
pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget']
|
||||
defs=['_USE_MATH_DEFINES']
|
||||
|
||||
if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd7', 'freebsd8', 'freebsd9', 'irix6', 'aix4', 'aix5'):
|
||||
for f in pf:
|
||||
try:
|
||||
sources.remove('intern' + os.sep + f + 'Win32.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'Carbon.cpp')
|
||||
except ValueError:
|
||||
pass
|
||||
defs += ['PREFIX=\\"/usr/local/\\"'] # XXX, make an option
|
||||
defs += ['WITH_X11_XINPUT'] # XXX, make an option
|
||||
|
||||
elif window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
|
||||
for f in pf:
|
||||
try:
|
||||
sources.remove('intern' + os.sep + f + 'X11.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'Carbon.cpp')
|
||||
except ValueError:
|
||||
pass
|
||||
elif window_system == 'darwin':
|
||||
if env['WITH_GHOST_COCOA']:
|
||||
if env['WITH_BF_QUICKTIME']:
|
||||
defs.append('WITH_QUICKTIME')
|
||||
if env['USE_QTKIT']:
|
||||
defs.append('USE_QTKIT')
|
||||
for f in pf:
|
||||
try:
|
||||
sources.remove('intern' + os.sep + f + 'Win32.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'X11.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'Carbon.cpp')
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
for f in pf:
|
||||
try:
|
||||
sources.remove('intern' + os.sep + f + 'Win32.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'X11.cpp')
|
||||
sources.remove('intern' + os.sep + f + 'Cocoa.mm')
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
else:
|
||||
print "Unknown window system specified."
|
||||
Exit()
|
||||
|
||||
if env['BF_GHOST_DEBUG']:
|
||||
defs.append('BF_GHOST_DEBUG')
|
||||
|
||||
incs = '. ../string #extern/glew/include #source/blender/imbuf #source/blender/makesdna ' + env['BF_OPENGL_INC']
|
||||
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
|
||||
incs = env['BF_WINTAB_INC'] + ' ' + incs
|
||||
|
||||
if window_system in ('win32-vc', 'win64-vc'):
|
||||
env.BlenderLib ('bf_intern_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15]) #, cc_compileflags=env['CCFLAGS'].append('/WX') )
|
||||
else:
|
||||
env.BlenderLib ('bf_intern_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] )
|
||||
626
intern/ghost/doc/ghost_interface.cfg
Normal file
626
intern/ghost/doc/ghost_interface.cfg
Normal file
@@ -0,0 +1,626 @@
|
||||
#---------------------------------------------------------------------------
|
||||
# General configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
|
||||
# by quotes) that should identify the project.
|
||||
PROJECT_NAME = "GHOST (Generic Handy Operating System Toolkit)"
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
PROJECT_NUMBER = 1.0
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
# If a relative path is entered, it will be relative to the location
|
||||
# where doxygen was started. If left blank the current directory will be used.
|
||||
OUTPUT_DIRECTORY = ./interface
|
||||
|
||||
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
|
||||
# documentation generated by doxygen is written. Doxygen will use this
|
||||
# information to generate all constant output in the proper language.
|
||||
# The default language is English, other supported languages are:
|
||||
# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese,
|
||||
# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian,
|
||||
# Polish, Portuguese and Slovene.
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
|
||||
# documentation are documented, even if no documentation was available.
|
||||
# Private class members and static file members will be hidden unless
|
||||
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
|
||||
EXTRACT_ALL = YES
|
||||
|
||||
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
|
||||
# will be included in the documentation.
|
||||
EXTRACT_PRIVATE = NO
|
||||
|
||||
# If the EXTRACT_STATIC tag is set to YES all static members of a file
|
||||
# will be included in the documentation.
|
||||
EXTRACT_STATIC = YES
|
||||
|
||||
# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
|
||||
# undocumented members of documented classes, files or namespaces.
|
||||
# If set to NO (the default) these members will be included in the
|
||||
# various overviews, but no documentation section is generated.
|
||||
# This option has no effect if EXTRACT_ALL is enabled.
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
|
||||
# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
|
||||
# undocumented classes that are normally visible in the class hierarchy.
|
||||
# If set to NO (the default) these class will be included in the various
|
||||
# overviews. This option has no effect if EXTRACT_ALL is enabled.
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
|
||||
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
|
||||
# include brief member descriptions after the members that are listed in
|
||||
# the file and class documentation (similar to JavaDoc).
|
||||
# Set to NO to disable this.
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
|
||||
# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
|
||||
# the brief description of a member or function before the detailed description.
|
||||
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
|
||||
# brief descriptions will be completely suppressed.
|
||||
REPEAT_BRIEF = YES
|
||||
|
||||
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
|
||||
# Doxygen will generate a detailed section even if there is only a brief
|
||||
# description.
|
||||
ALWAYS_DETAILED_SEC = YES
|
||||
|
||||
# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
|
||||
# path before files name in the file list and in the header files. If set
|
||||
# to NO the shortest path that makes the file name unique will be used.
|
||||
FULL_PATH_NAMES = NO
|
||||
|
||||
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
|
||||
# can be used to strip a user defined part of the path. Stripping is
|
||||
# only done if one of the specified strings matches the left-hand part of
|
||||
# the path. It is allowed to use relative paths in the argument list.
|
||||
STRIP_FROM_PATH =
|
||||
|
||||
# The INTERNAL_DOCS tag determines if documentation
|
||||
# that is typed after a \internal command is included. If the tag is set
|
||||
# to NO (the default) then the documentation will be excluded.
|
||||
# Set it to YES to include the internal documentation.
|
||||
INTERNAL_DOCS = NO
|
||||
|
||||
# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
|
||||
# generate a class diagram (in Html and LaTeX) for classes with base or
|
||||
# super classes. Setting the tag to NO turns the diagrams off.
|
||||
CLASS_DIAGRAMS = YES
|
||||
|
||||
# If the SOURCE_BROWSER tag is set to YES then a list of source files will
|
||||
# be generated. Documented entities will be cross-referenced with these sources.
|
||||
SOURCE_BROWSER = YES
|
||||
|
||||
# Setting the INLINE_SOURCES tag to YES will include the body
|
||||
# of functions and classes directly in the documentation.
|
||||
INLINE_SOURCES = NO
|
||||
|
||||
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
|
||||
# doxygen to hide any special comment blocks from generated source code
|
||||
# fragments. Normal C and C++ comments will always remain visible.
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
|
||||
# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
|
||||
# file names in lower case letters. If set to YES upper case letters are also
|
||||
# allowed. This is useful if you have classes or files whose names only differ
|
||||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# users are adviced to set this option to NO.
|
||||
CASE_SENSE_NAMES = YES
|
||||
|
||||
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
|
||||
# will show members with their full class and namespace scopes in the
|
||||
# documentation. If set to YES the scope will be hidden.
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
|
||||
# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
|
||||
# will generate a verbatim copy of the header file for each class for
|
||||
# which an include is specified. Set to NO to disable this.
|
||||
VERBATIM_HEADERS = YES
|
||||
|
||||
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
|
||||
# will put list of the files that are included by a file in the documentation
|
||||
# of that file.
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
|
||||
# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
|
||||
# will interpret the first line (until the first dot) of a JavaDoc-style
|
||||
# comment as the brief description. If set to NO, the JavaDoc
|
||||
# comments will behave just like the Qt-style comments (thus requiring an
|
||||
# explict @brief command for a brief description.
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
|
||||
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
|
||||
# member inherits the documentation from any documented member that it
|
||||
# reimplements.
|
||||
INHERIT_DOCS = YES
|
||||
|
||||
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
|
||||
# is inserted in the documentation for inline members.
|
||||
INLINE_INFO = YES
|
||||
|
||||
# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
|
||||
# will sort the (detailed) documentation of file and class members
|
||||
# alphabetically by member name. If set to NO the members will appear in
|
||||
# declaration order.
|
||||
SORT_MEMBER_DOCS = YES
|
||||
|
||||
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
|
||||
# tag is set to YES, then doxygen will reuse the documentation of the first
|
||||
# member in the group (if any) for the other members of the group. By default
|
||||
# all members of a group must be documented explicitly.
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
|
||||
# The TAB_SIZE tag can be used to set the number of spaces in a tab.
|
||||
# Doxygen uses this value to replace tabs by spaces in code fragments.
|
||||
TAB_SIZE = 4
|
||||
|
||||
# The ENABLE_SECTIONS tag can be used to enable conditional
|
||||
# documentation sections, marked by \if sectionname ... \endif.
|
||||
ENABLED_SECTION =
|
||||
|
||||
# The GENERATE_TODOLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the todo list. This list is created by putting \todo
|
||||
# commands in the documentation
|
||||
GENERATE_TODOLIST = YES
|
||||
|
||||
# The GENERATE_TESTLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the test list. This list is created by putting \test
|
||||
# commands in the documentation.
|
||||
GENERATE_TESTLIST = YES
|
||||
|
||||
# This tag can be used to specify a number of aliases that acts
|
||||
# as commands in the documentation. An alias has the form "name=value".
|
||||
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
|
||||
# put the command \sideeffect (or @sideeffect) in the documentation, which
|
||||
# will result in a user defined paragraph with heading "Side Effects:".
|
||||
# You can put \n's in the value part of an alias to insert newlines.
|
||||
ALIASES =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The QUIET tag can be used to turn on/off the messages that are generated
|
||||
# by doxygen. Possible values are YES and NO. If left blank NO is used.
|
||||
QUIET = NO
|
||||
|
||||
# The WARNINGS tag can be used to turn on/off the warning messages that are
|
||||
# generated by doxygen. Possible values are YES and NO. If left blank
|
||||
# NO is used.
|
||||
WARNINGS = YES
|
||||
|
||||
# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
|
||||
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
|
||||
# automatically be disabled.
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
|
||||
# The WARN_FORMAT tag determines the format of the warning messages that
|
||||
# doxygen can produce. The string should contain the $file, $line, and $text
|
||||
# tags, which will be replaced by the file and line number from which the
|
||||
# warning originated and the warning text.
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
|
||||
# The WARN_LOGFILE tag can be used to specify a file to which warning
|
||||
# and error messages should be written. If left blank the output is written
|
||||
# to stderr.
|
||||
WARN_LOGFILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The INPUT tag can be used to specify the files and/or directories that contain
|
||||
# documented source files. You may enter file names like "myfile.cpp" or
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
INPUT = ..
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
# and *.h) to filter out the source-files in the directories. If left
|
||||
# blank all files are included.
|
||||
FILE_PATTERNS = *.h *.cpp *.c
|
||||
|
||||
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
|
||||
# should be searched for input files as well. Possible values are YES and NO.
|
||||
# If left blank NO is used.
|
||||
RECURSIVE = NO
|
||||
|
||||
# The EXCLUDE tag can be used to specify files and/or directories that should
|
||||
# excluded from the INPUT source files. This way you can easily exclude a
|
||||
# subdirectory from a directory tree whose root is specified with the INPUT tag.
|
||||
EXCLUDE =
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
|
||||
# certain files from those directories.
|
||||
EXCLUDE_PATTERNS =
|
||||
|
||||
# The EXAMPLE_PATH tag can be used to specify one or more files or
|
||||
# directories that contain example code fragments that are included (see
|
||||
# the \include command).
|
||||
EXAMPLE_PATH = ../test
|
||||
|
||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
# and *.h) to filter out the source-files in the directories. If left
|
||||
# blank all files are included.
|
||||
EXAMPLE_PATTERNS = *.h *.cpp *.c
|
||||
|
||||
# The IMAGE_PATH tag can be used to specify one or more files or
|
||||
# directories that contain image that are included in the documentation (see
|
||||
# the \image command).
|
||||
IMAGE_PATH =
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
# by executing (via popen()) the command <filter> <input-file>, where <filter>
|
||||
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
|
||||
# input file. Doxygen will then use the output that the filter program writes
|
||||
# to standard output.
|
||||
INPUT_FILTER =
|
||||
|
||||
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
|
||||
# INPUT_FILTER) will be used to filter the input files when producing source
|
||||
# files to browse.
|
||||
FILTER_SOURCE_FILES = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
|
||||
# of all compounds will be generated. Enable this if the project
|
||||
# contains a lot of classes, structs, unions or interfaces.
|
||||
ALPHABETICAL_INDEX = YES
|
||||
|
||||
# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
|
||||
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
|
||||
# in which this list will be split (can be a number in the range [1..20])
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
|
||||
# In case all classes in a project start with a common prefix, all
|
||||
# classes will be put under the same header in the alphabetical index.
|
||||
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
|
||||
# should be ignored while generating the index headers.
|
||||
IGNORE_PREFIX =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
|
||||
# generate HTML output.
|
||||
GENERATE_HTML = YES
|
||||
|
||||
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `html' will be used as the default path.
|
||||
HTML_OUTPUT = html
|
||||
|
||||
# The HTML_HEADER tag can be used to specify a personal HTML header for
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard header.
|
||||
HTML_HEADER =
|
||||
|
||||
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard footer.
|
||||
HTML_FOOTER =
|
||||
|
||||
# The HTML_STYLESHEET tag can be used to specify a user defined cascading
|
||||
# style sheet that is used by each HTML page. It can be used to
|
||||
# fine-tune the look of the HTML output. If the tag is left blank doxygen
|
||||
# will generate a default style sheet
|
||||
HTML_STYLESHEET =
|
||||
|
||||
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
|
||||
# files or namespaces will be aligned in HTML using tables. If set to
|
||||
# NO a bullet list will be used.
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
|
||||
# If the GENERATE_HTMLHELP tag is set to YES, additional index files
|
||||
# will be generated that can be used as input for tools like the
|
||||
# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
|
||||
# of the generated HTML documentation.
|
||||
GENERATE_HTMLHELP = YES
|
||||
|
||||
# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
|
||||
# top of each HTML page. The value NO (the default) enables the index and
|
||||
# the value YES disables it.
|
||||
DISABLE_INDEX = NO
|
||||
|
||||
# This tag can be used to set the number of enum values (range [1..20])
|
||||
# that doxygen will group on one line in the generated HTML documentation.
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
|
||||
# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be
|
||||
# generated containing a tree-like index structure (just like the one that
|
||||
# is generated for HTML Help). For this to work a browser that supports
|
||||
# JavaScript and frames is required (for instance Netscape 4.0+
|
||||
# or Internet explorer 4.0+).
|
||||
GENERATE_TREEVIEW = YES
|
||||
|
||||
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
|
||||
# used to set the initial width (in pixels) of the frame in which the tree
|
||||
# is shown.
|
||||
TREEVIEW_WIDTH = 250
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
|
||||
# generate Latex output.
|
||||
GENERATE_LATEX = NO
|
||||
|
||||
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `latex' will be used as the default path.
|
||||
LATEX_OUTPUT = latex
|
||||
|
||||
# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
|
||||
# LaTeX documents. This may be useful for small projects and may help to
|
||||
# save some trees in general.
|
||||
COMPACT_LATEX = NO
|
||||
|
||||
# The PAPER_TYPE tag can be used to set the paper type that is used
|
||||
# by the printer. Possible values are: a4, a4wide, letter, legal and
|
||||
# executive. If left blank a4wide will be used.
|
||||
PAPER_TYPE = a4wide
|
||||
|
||||
# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
|
||||
# packages that should be included in the LaTeX output.
|
||||
EXTRA_PACKAGES =
|
||||
|
||||
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
|
||||
# the generated latex document. The header should contain everything until
|
||||
# the first chapter. If it is left blank doxygen will generate a
|
||||
# standard header. Notice: only use this tag if you know what you are doing!
|
||||
LATEX_HEADER =
|
||||
|
||||
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
|
||||
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
|
||||
# contain links (just like the HTML output) instead of page references
|
||||
# This makes the output suitable for online browsing using a pdf viewer.
|
||||
PDF_HYPERLINKS = NO
|
||||
|
||||
# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
|
||||
# plain latex in the generated Makefile. Set this option to YES to get a
|
||||
# higher quality PDF documentation.
|
||||
USE_PDFLATEX = NO
|
||||
|
||||
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
|
||||
# command to the generated LaTeX files. This will instruct LaTeX to keep
|
||||
# running if errors occur, instead of asking the user for help.
|
||||
# This option is also used when generating formulas in HTML.
|
||||
LATEX_BATCHMODE = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
|
||||
# The RTF output is optimised for Word 97 and may not look very pretty with
|
||||
# other RTF readers or editors.
|
||||
GENERATE_RTF = NO
|
||||
|
||||
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `rtf' will be used as the default path.
|
||||
RTF_OUTPUT = rtf
|
||||
|
||||
# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
|
||||
# RTF documents. This may be useful for small projects and may help to
|
||||
# save some trees in general.
|
||||
COMPACT_RTF = NO
|
||||
|
||||
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
|
||||
# will contain hyperlink fields. The RTF file will
|
||||
# contain links (just like the HTML output) instead of page references.
|
||||
# This makes the output suitable for online browsing using a WORD or other.
|
||||
# programs which support those fields.
|
||||
# Note: wordpad (write) and others do not support links.
|
||||
RTF_HYPERLINKS = NO
|
||||
|
||||
# Load stylesheet definitions from file. Syntax is similar to doxygen's
|
||||
# config file, i.e. a series of assigments. You only have to provide
|
||||
# replacements, missing definitions are set to their default value.
|
||||
RTF_STYLESHEET_FILE =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
|
||||
# generate man pages
|
||||
GENERATE_MAN = NO
|
||||
|
||||
# The MAN_OUTPUT tag is used to specify where the man pages will be put.
|
||||
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
|
||||
# put in front of it. If left blank `man' will be used as the default path.
|
||||
MAN_OUTPUT = man
|
||||
|
||||
# The MAN_EXTENSION tag determines the extension that is added to
|
||||
# the generated man pages (default is the subroutine's section .3)
|
||||
MAN_EXTENSION = .3
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the GENERATE_XML tag is set to YES Doxygen will
|
||||
# generate an XML file that captures the structure of
|
||||
# the code including all documentation. Warning: This feature
|
||||
# is still experimental and very incomplete.
|
||||
GENERATE_XML = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
|
||||
# evaluate all C-preprocessor directives found in the sources and include
|
||||
# files.
|
||||
ENABLE_PREPROCESSING = YES
|
||||
|
||||
# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
|
||||
# names in the source code. If set to NO (the default) only conditional
|
||||
# compilation will be performed. Macro expansion can be done in a controlled
|
||||
# way by setting EXPAND_ONLY_PREDEF to YES.
|
||||
MACRO_EXPANSION = NO
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
|
||||
# then the macro expansion is limited to the macros specified with the
|
||||
# PREDEFINED and EXPAND_AS_PREDEFINED tags.
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
|
||||
# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
|
||||
# in the INCLUDE_PATH (see below) will be search if a #include is found.
|
||||
SEARCH_INCLUDES = YES
|
||||
|
||||
# The INCLUDE_PATH tag can be used to specify one or more directories that
|
||||
# contain include files that are not input files but should be processed by
|
||||
# the preprocessor.
|
||||
INCLUDE_PATH =
|
||||
|
||||
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
|
||||
# patterns (like *.h and *.hpp) to filter out the header-files in the
|
||||
# directories. If left blank, the patterns specified with FILE_PATTERNS will
|
||||
# be used.
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
|
||||
# The PREDEFINED tag can be used to specify one or more macro names that
|
||||
# are defined before the preprocessor is started (similar to the -D option of
|
||||
# gcc). The argument of the tag is a list of macros of the form: name
|
||||
# or name=definition (no spaces). If the definition and the = are
|
||||
# omitted =1 is assumed.
|
||||
PREDEFINED =
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
||||
# The macro definition that is found in the sources will be used.
|
||||
# Use the PREDEFINED tag if you want to use a different macro definition.
|
||||
EXPAND_AS_DEFINED =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The TAGFILES tag can be used to specify one or more tagfiles.
|
||||
TAGFILES =
|
||||
|
||||
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
|
||||
# a tag file that is based on the input files it reads.
|
||||
GENERATE_TAGFILE =
|
||||
|
||||
# If the ALLEXTERNALS tag is set to YES all external classes will be listed
|
||||
# in the class index. If set to NO only the inherited external classes
|
||||
# will be listed.
|
||||
ALLEXTERNALS =
|
||||
|
||||
# The PERL_PATH should be the absolute path and name of the perl script
|
||||
# interpreter (i.e. the result of `which perl').
|
||||
PERL_PATH = /usr/bin/perl
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
|
||||
# available from the path. This tool is part of Graphviz, a graph visualization
|
||||
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
|
||||
# have no effect if this option is set to NO (the default)
|
||||
HAVE_DOT = YES
|
||||
|
||||
# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
|
||||
# will generate a graph for each documented class showing the direct and
|
||||
# indirect inheritance relations. Setting this tag to YES will force the
|
||||
# the CLASS_DIAGRAMS tag to NO.
|
||||
CLASS_GRAPH = YES
|
||||
|
||||
# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
|
||||
# will generate a graph for each documented class showing the direct and
|
||||
# indirect implementation dependencies (inheritance, containment, and
|
||||
# class references variables) of the class with other documented classes.
|
||||
COLLABORATION_GRAPH = YES
|
||||
|
||||
# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to
|
||||
# YES then doxygen will generate a graph for each documented file showing
|
||||
# the direct and indirect include dependencies of the file with other
|
||||
# documented files.
|
||||
INCLUDE_GRAPH = YES
|
||||
|
||||
# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to
|
||||
# YES then doxygen will generate a graph for each documented header file showing
|
||||
# the documented files that directly or indirectly include this file
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
|
||||
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
|
||||
# will graphical hierarchy of all classes instead of a textual one.
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
|
||||
# The tag DOT_PATH can be used to specify the path where the dot tool can be
|
||||
# found. If left blank, it is assumed the dot tool can be found on the path.
|
||||
DOT_PATH =
|
||||
|
||||
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
|
||||
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
|
||||
# this value, doxygen will try to truncate the graph, so that it fits within
|
||||
# the specified constraint. Beware that most browsers cannot cope with very
|
||||
# large images.
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
|
||||
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
|
||||
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
|
||||
# this value, doxygen will try to truncate the graph, so that it fits within
|
||||
# the specified constraint. Beware that most browsers cannot cope with very
|
||||
# large images.
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
|
||||
# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
|
||||
# generate a legend page explaining the meaning of the various boxes and
|
||||
# arrows in the dot generated graphs.
|
||||
GENERATE_LEGEND = YES
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::addtions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# The SEARCHENGINE tag specifies whether or not a search engine should be
|
||||
# used. If set to NO the values of all tags below this one will be ignored.
|
||||
SEARCHENGINE = NO
|
||||
|
||||
# The CGI_NAME tag should be the name of the CGI script that
|
||||
# starts the search engine (doxysearch) with the correct parameters.
|
||||
# A script with this name will be generated by doxygen.
|
||||
CGI_NAME= search.cgi
|
||||
|
||||
# The CGI_URL tag should be the absolute URL to the directory where the
|
||||
# cgi binaries are located. See the documentation of your http daemon for
|
||||
# details.
|
||||
CGI_URL=
|
||||
|
||||
# The DOC_URL tag should be the absolute URL to the directory where the
|
||||
# documentation is located. If left blank the absolute path to the
|
||||
# documentation, with file:// prepended to it, will be used.
|
||||
DOC_URL=
|
||||
|
||||
# The DOC_ABSPATH tag should be the absolute path to the directory where the
|
||||
# documentation is located. If left blank the directory on the local machine
|
||||
# will be used.
|
||||
DOC_ABSPATH=
|
||||
|
||||
# The BIN_ABSPATH tag must point to the directory where the doxysearch binary
|
||||
# is installed.
|
||||
BIN_ABSPATH= /bin
|
||||
|
||||
# The EXT_DOC_PATHS tag can be used to specify one or more paths to
|
||||
# documentation generated for other projects. This allows doxysearch to search
|
||||
# the documentation for these projects as well.
|
||||
EXT_DOC_PATHS=
|
||||
79
intern/ghost/intern/GHOST_Buttons.cpp
Normal file
79
intern/ghost/intern/GHOST_Buttons.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_Buttons.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include "GHOST_Buttons.h"
|
||||
|
||||
|
||||
|
||||
GHOST_Buttons::GHOST_Buttons()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_Buttons::get(GHOST_TButtonMask mask) const
|
||||
{
|
||||
switch (mask) {
|
||||
case GHOST_kButtonMaskLeft:
|
||||
return m_ButtonLeft;
|
||||
case GHOST_kButtonMaskMiddle:
|
||||
return m_ButtonMiddle;
|
||||
case GHOST_kButtonMaskRight:
|
||||
return m_ButtonRight;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_Buttons::set(GHOST_TButtonMask mask, bool down)
|
||||
{
|
||||
switch (mask) {
|
||||
case GHOST_kButtonMaskLeft:
|
||||
m_ButtonLeft = down; break;
|
||||
case GHOST_kButtonMaskMiddle:
|
||||
m_ButtonMiddle = down; break;
|
||||
case GHOST_kButtonMaskRight:
|
||||
m_ButtonRight = down; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_Buttons::clear()
|
||||
{
|
||||
m_ButtonLeft = false;
|
||||
m_ButtonMiddle = false;
|
||||
m_ButtonRight = false;
|
||||
}
|
||||
|
||||
GHOST_Buttons::~GHOST_Buttons() {}
|
||||
79
intern/ghost/intern/GHOST_Buttons.h
Normal file
79
intern/ghost/intern/GHOST_Buttons.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_Buttons.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_Buttons struct.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_BUTTONS_H_
|
||||
#define _GHOST_BUTTONS_H_
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
|
||||
/**
|
||||
* This struct stores the state of the mouse buttons.
|
||||
* Buttons can be set using button masks.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 15, 2001
|
||||
*/
|
||||
struct GHOST_Buttons {
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_Buttons();
|
||||
|
||||
virtual ~GHOST_Buttons();
|
||||
|
||||
/**
|
||||
* Returns the state of a single button.
|
||||
* @param mask. Key button to return.
|
||||
* @return The state of the button (pressed == true).
|
||||
*/
|
||||
virtual bool get(GHOST_TButtonMask mask) const;
|
||||
|
||||
/**
|
||||
* Updates the state of a single button.
|
||||
* @param mask. Button state to update.
|
||||
* @param down. The new state of the button.
|
||||
*/
|
||||
virtual void set(GHOST_TButtonMask mask, bool down);
|
||||
|
||||
/**
|
||||
* Sets the state of all buttons to up.
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
GHOST_TUns8 m_ButtonLeft : 1;
|
||||
GHOST_TUns8 m_ButtonMiddle : 1;
|
||||
GHOST_TUns8 m_ButtonRight : 1;
|
||||
};
|
||||
|
||||
#endif // _GHOST_BUTTONS_H_
|
||||
|
||||
885
intern/ghost/intern/GHOST_C-api.cpp
Normal file
885
intern/ghost/intern/GHOST_C-api.cpp
Normal file
@@ -0,0 +1,885 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_C-api.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
* GHOST_C-Api.cpp
|
||||
*
|
||||
* C Api for GHOST
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "intern/GHOST_Debug.h"
|
||||
#include "GHOST_C-api.h"
|
||||
#include "GHOST_ISystem.h"
|
||||
#include "GHOST_IEvent.h"
|
||||
#include "GHOST_IEventConsumer.h"
|
||||
#include "intern/GHOST_CallbackEventConsumer.h"
|
||||
|
||||
GHOST_SystemHandle GHOST_CreateSystem(void)
|
||||
{
|
||||
GHOST_ISystem::createSystem();
|
||||
GHOST_ISystem* system = GHOST_ISystem::getSystem();
|
||||
|
||||
return (GHOST_SystemHandle)system;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return system->disposeSystem();
|
||||
}
|
||||
|
||||
|
||||
GHOST_EventConsumerHandle GHOST_CreateEventConsumer(GHOST_EventCallbackProcPtr eventCallback, GHOST_TUserDataPtr userdata)
|
||||
{
|
||||
return (GHOST_EventConsumerHandle) new GHOST_CallbackEventConsumer (eventCallback, userdata);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisposeEventConsumer(GHOST_EventConsumerHandle consumerhandle)
|
||||
{
|
||||
delete ((GHOST_CallbackEventConsumer*)consumerhandle);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns64 GHOST_GetMilliSeconds(GHOST_SystemHandle systemhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return system->getMilliSeconds();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TimerTaskHandle GHOST_InstallTimer(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TUns64 delay,
|
||||
GHOST_TUns64 interval,
|
||||
GHOST_TimerProcPtr timerproc,
|
||||
GHOST_TUserDataPtr userdata)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return (GHOST_TimerTaskHandle) system->installTimer(delay, interval, timerproc, userdata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_RemoveTimer(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TimerTaskHandle timertaskhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle;
|
||||
|
||||
return system->removeTimer(timertask);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TUns8 GHOST_GetNumDisplays(GHOST_SystemHandle systemhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return system->getNumDisplays();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TUns32* width,
|
||||
GHOST_TUns32* height)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
system->getMainDisplayDimensions(*width, *height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
|
||||
const char* title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
GHOST_TDrawingContextType type,
|
||||
const int stereoVisual,
|
||||
const GHOST_TUns16 numOfAASamples)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
bool bstereoVisual;
|
||||
|
||||
if(stereoVisual)
|
||||
bstereoVisual = true;
|
||||
else
|
||||
bstereoVisual = false;
|
||||
|
||||
return (GHOST_WindowHandle) system->createWindow(title, left, top, width, height,
|
||||
state, type, bstereoVisual, numOfAASamples);
|
||||
}
|
||||
|
||||
GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->getUserData();
|
||||
}
|
||||
void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
window->setUserData(userdata);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
|
||||
GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return system->disposeWindow(window);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GHOST_ValidWindow(GHOST_SystemHandle systemhandle,
|
||||
GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return (int) system->validWindow(window);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_WindowHandle GHOST_BeginFullScreen(GHOST_SystemHandle systemhandle,
|
||||
GHOST_DisplaySetting* setting,
|
||||
const int stereoVisual)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
GHOST_IWindow* window = NULL;
|
||||
bool bstereoVisual;
|
||||
|
||||
if(stereoVisual)
|
||||
bstereoVisual = true;
|
||||
else
|
||||
bstereoVisual = false;
|
||||
|
||||
system->beginFullScreen(*setting, &window, bstereoVisual);
|
||||
|
||||
return (GHOST_WindowHandle)window;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return system->endFullScreen();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return (int) system->getFullScreen();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return (int) system->processEvents(waitForEvent?true:false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GHOST_DispatchEvents(GHOST_SystemHandle systemhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return (int) system->dispatchEvents();
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_AddEventConsumer(GHOST_SystemHandle systemhandle, GHOST_EventConsumerHandle consumerhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return system->addEventConsumer((GHOST_CallbackEventConsumer*)consumerhandle);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_RemoveEventConsumer(GHOST_SystemHandle systemhandle, GHOST_EventConsumerHandle consumerhandle)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return system->removeEventConsumer((GHOST_CallbackEventConsumer*)consumerhandle);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle,float progress)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setProgressBar(progress);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->endProgressBar();
|
||||
}
|
||||
|
||||
|
||||
int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle,
|
||||
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
|
||||
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
|
||||
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen)
|
||||
//original patch only
|
||||
/* GHOST_NDOFEventHandler_fp setNdofEventHandler)*/
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return system->openNDOF((GHOST_IWindow*) windowhandle,
|
||||
setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen);
|
||||
// original patch
|
||||
// setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen, setNdofEventHandler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->getCursorShape();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetCursorShape(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TStandardCursor cursorshape)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setCursorShape(cursorshape);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SetCustomCursorShape(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns8 bitmap[16][2],
|
||||
GHOST_TUns8 mask[16][2],
|
||||
int hotX,
|
||||
int hotY)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setCustomCursorShape(bitmap, mask, hotX, hotY);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SetCustomCursorShapeEx(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask,
|
||||
int sizex,
|
||||
int sizey,
|
||||
int hotX,
|
||||
int hotY,
|
||||
int fg_color,
|
||||
int bg_color)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setCustomCursorShape(bitmap, mask, sizex, sizey,
|
||||
hotX, hotY, fg_color, bg_color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GHOST_GetCursorVisibility(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return (int) window->getCursorVisibility();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetCursorVisibility(GHOST_WindowHandle windowhandle,
|
||||
int visible)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setCursorVisibility(visible?true:false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_GetCursorPosition(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TInt32* x,
|
||||
GHOST_TInt32* y)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return system->getCursorPosition(*x, *y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TInt32 x,
|
||||
GHOST_TInt32 y)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
|
||||
return system->setCursorPosition(x, y);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TGrabCursorMode mode,
|
||||
int *bounds)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
GHOST_Rect bounds_rect, bounds_win;
|
||||
|
||||
if(bounds) {
|
||||
/* if this is X11 specific we need a function that converts */
|
||||
window->getClientBounds(bounds_win);
|
||||
window->clientToScreen(bounds[0], bounds_win.getHeight() - bounds[1], bounds_rect.m_l, bounds_rect.m_t);
|
||||
window->clientToScreen(bounds[2], bounds_win.getHeight() - bounds[3], bounds_rect.m_r, bounds_rect.m_b);
|
||||
|
||||
}
|
||||
|
||||
return window->setCursorGrab(mode, bounds ? &bounds_rect:NULL);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TModifierKeyMask mask,
|
||||
int* isDown)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
GHOST_TSuccess result;
|
||||
bool isdown= false;
|
||||
|
||||
result = system->getModifierKeyState(mask, isdown);
|
||||
*isDown = (int) isdown;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_GetButtonState(GHOST_SystemHandle systemhandle,
|
||||
GHOST_TButtonMask mask,
|
||||
int* isDown)
|
||||
{
|
||||
GHOST_ISystem* system = (GHOST_ISystem*) systemhandle;
|
||||
GHOST_TSuccess result;
|
||||
bool isdown= false;
|
||||
|
||||
result = system->getButtonState(mask, isdown);
|
||||
*isDown = (int) isdown;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_setAcceptDragOperation(GHOST_WindowHandle windowhandle, GHOST_TInt8 canAccept)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
window->setAcceptDragOperation(canAccept);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TEventType GHOST_GetEventType(GHOST_EventHandle eventhandle)
|
||||
{
|
||||
GHOST_IEvent* event = (GHOST_IEvent*) eventhandle;
|
||||
|
||||
return event->getType();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TUns64 GHOST_GetEventTime(GHOST_EventHandle eventhandle)
|
||||
{
|
||||
GHOST_IEvent* event = (GHOST_IEvent*) eventhandle;
|
||||
|
||||
return event->getTime();
|
||||
}
|
||||
|
||||
|
||||
GHOST_WindowHandle GHOST_GetEventWindow(GHOST_EventHandle eventhandle)
|
||||
{
|
||||
GHOST_IEvent* event = (GHOST_IEvent*) eventhandle;
|
||||
|
||||
return (GHOST_WindowHandle) event->getWindow();
|
||||
}
|
||||
|
||||
|
||||
GHOST_TEventDataPtr GHOST_GetEventData(GHOST_EventHandle eventhandle)
|
||||
{
|
||||
GHOST_IEvent* event = (GHOST_IEvent*) eventhandle;
|
||||
|
||||
return event->getData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TimerProcPtr GHOST_GetTimerProc(GHOST_TimerTaskHandle timertaskhandle)
|
||||
{
|
||||
GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle;
|
||||
|
||||
return timertask->getTimerProc();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_SetTimerProc(GHOST_TimerTaskHandle timertaskhandle,
|
||||
GHOST_TimerProcPtr timerproc)
|
||||
{
|
||||
GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle;
|
||||
|
||||
timertask->setTimerProc(timerproc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TUserDataPtr GHOST_GetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle)
|
||||
{
|
||||
GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle;
|
||||
|
||||
return timertask->getUserData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_SetTimerTaskUserData(GHOST_TimerTaskHandle timertaskhandle,
|
||||
GHOST_TUserDataPtr userdata)
|
||||
{
|
||||
GHOST_ITimerTask* timertask = (GHOST_ITimerTask*) timertaskhandle;
|
||||
|
||||
timertask->setUserData(userdata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GHOST_GetValid(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return (int) window->getValid();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TDrawingContextType GHOST_GetDrawingContextType(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->getDrawingContextType();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetDrawingContextType(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TDrawingContextType type)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setDrawingContextType(type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_SetTitle(GHOST_WindowHandle windowhandle,
|
||||
const char* title)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
window->setTitle(title);
|
||||
}
|
||||
|
||||
|
||||
char* GHOST_GetTitle(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
STR_String title;
|
||||
|
||||
window->getTitle(title);
|
||||
|
||||
char *ctitle = (char*) malloc(title.Length() + 1);
|
||||
|
||||
if (ctitle == NULL) return NULL;
|
||||
strcpy(ctitle, title.Ptr());
|
||||
|
||||
return ctitle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_RectangleHandle GHOST_GetWindowBounds(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
GHOST_Rect* rectangle = NULL;
|
||||
|
||||
rectangle = new GHOST_Rect();
|
||||
window->getWindowBounds(*rectangle);
|
||||
|
||||
return (GHOST_RectangleHandle)rectangle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_RectangleHandle GHOST_GetClientBounds(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
GHOST_Rect* rectangle = NULL;
|
||||
|
||||
rectangle = new GHOST_Rect();
|
||||
window->getClientBounds(*rectangle);
|
||||
|
||||
return (GHOST_RectangleHandle)rectangle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_DisposeRectangle(GHOST_RectangleHandle rectanglehandle)
|
||||
{
|
||||
delete (GHOST_Rect*) rectanglehandle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetClientWidth(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns32 width)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setClientWidth(width);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetClientHeight(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns32 height)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setClientHeight(height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetClientSize(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setClientSize(width, height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_ScreenToClient(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32* outX,
|
||||
GHOST_TInt32* outY)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
window->screenToClient(inX, inY, *outX, *outY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_ClientToScreen(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32* outX,
|
||||
GHOST_TInt32* outY)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
window->clientToScreen(inX, inY, *outX, *outY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TWindowState GHOST_GetWindowState(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->getState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetWindowState(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TWindowState state)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setState(state);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetWindowModifiedState(GHOST_WindowHandle windowhandle, GHOST_TUns8 isUnsavedChanges)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setModifiedState(isUnsavedChanges);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SetWindowOrder(GHOST_WindowHandle windowhandle,
|
||||
GHOST_TWindowOrder order)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->setOrder(order);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SwapWindowBuffers(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->swapBuffers();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->activateDrawingContext();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
|
||||
|
||||
return window->invalidate();
|
||||
}
|
||||
|
||||
|
||||
extern const GHOST_TabletData* GHOST_GetTabletData(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
return ((GHOST_IWindow*)windowhandle)->GetTabletData();
|
||||
}
|
||||
|
||||
|
||||
GHOST_TInt32 GHOST_GetWidthRectangle(GHOST_RectangleHandle rectanglehandle)
|
||||
{
|
||||
return ((GHOST_Rect*)rectanglehandle)->getWidth();
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TInt32 GHOST_GetHeightRectangle(GHOST_RectangleHandle rectanglehandle)
|
||||
{
|
||||
return ((GHOST_Rect*)rectanglehandle)->getHeight();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_GetRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32* l,
|
||||
GHOST_TInt32* t,
|
||||
GHOST_TInt32* r,
|
||||
GHOST_TInt32* b)
|
||||
{
|
||||
GHOST_Rect *rect= (GHOST_Rect*) rectanglehandle;
|
||||
|
||||
*l= rect->m_l;
|
||||
*t= rect->m_t;
|
||||
*r= rect->m_r;
|
||||
*b= rect->m_b;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_SetRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 l,
|
||||
GHOST_TInt32 t,
|
||||
GHOST_TInt32 r,
|
||||
GHOST_TInt32 b)
|
||||
{
|
||||
((GHOST_Rect*)rectanglehandle)->set(l, t, r, b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_IsEmptyRectangle(GHOST_RectangleHandle rectanglehandle)
|
||||
{
|
||||
GHOST_TSuccess result = GHOST_kFailure;
|
||||
|
||||
if (((GHOST_Rect*)rectanglehandle)->isEmpty())
|
||||
result = GHOST_kSuccess;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_IsValidRectangle(GHOST_RectangleHandle rectanglehandle)
|
||||
{
|
||||
GHOST_TSuccess result = GHOST_kFailure;
|
||||
|
||||
if(((GHOST_Rect*)rectanglehandle)->isValid())
|
||||
result = GHOST_kSuccess;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_InsetRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 i)
|
||||
{
|
||||
((GHOST_Rect*)rectanglehandle)->inset(i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_UnionRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_RectangleHandle anotherrectanglehandle)
|
||||
{
|
||||
((GHOST_Rect*)rectanglehandle)->unionRect(*(GHOST_Rect*)anotherrectanglehandle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_UnionPointRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 x,
|
||||
GHOST_TInt32 y)
|
||||
{
|
||||
((GHOST_Rect*)rectanglehandle)->unionPoint(x, y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_IsInsideRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 x,
|
||||
GHOST_TInt32 y)
|
||||
{
|
||||
GHOST_TSuccess result = GHOST_kFailure;
|
||||
|
||||
if (((GHOST_Rect*)rectanglehandle)->isInside(x, y))
|
||||
result = GHOST_kSuccess;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TVisibility GHOST_GetRectangleVisibility(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_RectangleHandle anotherrectanglehandle)
|
||||
{
|
||||
GHOST_TVisibility visible = GHOST_kNotVisible;
|
||||
|
||||
visible = ((GHOST_Rect*)rectanglehandle)->getVisibility(*(GHOST_Rect*)anotherrectanglehandle);
|
||||
|
||||
return visible;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_SetCenterRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 cx,
|
||||
GHOST_TInt32 cy)
|
||||
{
|
||||
((GHOST_Rect*)rectanglehandle)->setCenter(cx, cy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GHOST_SetRectangleCenter(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_TInt32 cx,
|
||||
GHOST_TInt32 cy,
|
||||
GHOST_TInt32 w,
|
||||
GHOST_TInt32 h)
|
||||
{
|
||||
((GHOST_Rect*)rectanglehandle)->setCenter(cx, cy, w, h);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_ClipRectangle(GHOST_RectangleHandle rectanglehandle,
|
||||
GHOST_RectangleHandle anotherrectanglehandle)
|
||||
{
|
||||
GHOST_TSuccess result = GHOST_kFailure;
|
||||
|
||||
if (((GHOST_Rect*)rectanglehandle)->clip(*(GHOST_Rect*)anotherrectanglehandle))
|
||||
result = GHOST_kSuccess;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GHOST_TUns8* GHOST_getClipboard(int selection)
|
||||
{
|
||||
GHOST_ISystem* system = GHOST_ISystem::getSystem();
|
||||
return system->getClipboard(selection);
|
||||
}
|
||||
|
||||
void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection)
|
||||
{
|
||||
GHOST_ISystem* system = GHOST_ISystem::getSystem();
|
||||
system->putClipboard(buffer, selection);
|
||||
}
|
||||
|
||||
int GHOST_toggleConsole(int action)
|
||||
{
|
||||
GHOST_ISystem* system = GHOST_ISystem::getSystem();
|
||||
return system->toggleConsole(action);
|
||||
}
|
||||
57
intern/ghost/intern/GHOST_CallbackEventConsumer.cpp
Normal file
57
intern/ghost/intern/GHOST_CallbackEventConsumer.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_CallbackEventConsumer.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date October 25, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_Debug.h"
|
||||
#include "GHOST_C-api.h"
|
||||
#include "GHOST_CallbackEventConsumer.h"
|
||||
|
||||
GHOST_CallbackEventConsumer::GHOST_CallbackEventConsumer(GHOST_EventCallbackProcPtr eventCallback,
|
||||
GHOST_TUserDataPtr userData)
|
||||
{
|
||||
m_eventCallback = eventCallback;
|
||||
m_userData = userData;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_CallbackEventConsumer::processEvent(GHOST_IEvent* event)
|
||||
{
|
||||
return m_eventCallback((GHOST_EventHandle)event, m_userData) != 0;
|
||||
}
|
||||
80
intern/ghost/intern/GHOST_CallbackEventConsumer.h
Normal file
80
intern/ghost/intern/GHOST_CallbackEventConsumer.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_CallbackEventConsumer.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_CallbackEventConsumer class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_CALLBACK_EVENT_CONSUMER_H_
|
||||
#define _GHOST_CALLBACK_EVENT_CONSUMER_H_
|
||||
|
||||
#include "GHOST_IEventConsumer.h"
|
||||
#include "GHOST_C-api.h"
|
||||
|
||||
/**
|
||||
* Event consumer that will forward events to a call-back routine.
|
||||
* Especially useful for the C-API.
|
||||
* @author Maarten Gribnau
|
||||
* @date October 25, 2001
|
||||
*/
|
||||
class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param eventCallback The call-back routine invoked.
|
||||
* @param userData The data passed back though the call-back routine.
|
||||
*/
|
||||
GHOST_CallbackEventConsumer(
|
||||
GHOST_EventCallbackProcPtr eventCallback,
|
||||
GHOST_TUserDataPtr userData);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_CallbackEventConsumer(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by an event producer when an event is available.
|
||||
* @param event The event that can be handled or ignored.
|
||||
* @return Indication as to whether the event was handled.
|
||||
*/
|
||||
virtual bool processEvent(GHOST_IEvent* event);
|
||||
|
||||
protected:
|
||||
/** The call-back routine invoked. */
|
||||
GHOST_EventCallbackProcPtr m_eventCallback;
|
||||
/** The data passed back though the call-back routine. */
|
||||
GHOST_TUserDataPtr m_userData;
|
||||
};
|
||||
|
||||
#endif // _GHOST_CALLBACK_EVENT_CONSUMER_H_
|
||||
|
||||
70
intern/ghost/intern/GHOST_Debug.h
Normal file
70
intern/ghost/intern/GHOST_Debug.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_Debug.h
|
||||
* \ingroup GHOST
|
||||
* Macro's used in GHOST debug target.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_DEBUG_H_
|
||||
#define _GHOST_DEBUG_H_
|
||||
|
||||
#if defined(WIN32) && !defined(FREE_WINDOWS)
|
||||
#ifdef DEBUG
|
||||
#pragma warning (disable:4786) // suppress stl-MSVC debug info warning
|
||||
// #define GHOST_DEBUG
|
||||
#endif // DEBUG
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef BF_GHOST_DEBUG
|
||||
#define GHOST_DEBUG // spit ghost events to stdout
|
||||
#endif // BF_GHOST_DEBUG
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
#include <iostream>
|
||||
#include <stdio.h> //for printf()
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
#define GHOST_PRINT(x) { std::cout << x; }
|
||||
#define GHOST_PRINTF(x, ...) { printf(x, __VA_ARGS__); }
|
||||
#else // GHOST_DEBUG
|
||||
#define GHOST_PRINT(x)
|
||||
#define GHOST_PRINTF(x, ...)
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
#define GHOST_ASSERT(x, info) { if (!(x)) {GHOST_PRINT("assertion failed: "); GHOST_PRINT(info); GHOST_PRINT("\n"); } }
|
||||
#else // GHOST_DEBUG
|
||||
#define GHOST_ASSERT(x, info)
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
#endif // _GHOST_DEBUG_H_
|
||||
|
||||
218
intern/ghost/intern/GHOST_DisplayManager.cpp
Normal file
218
intern/ghost/intern/GHOST_DisplayManager.cpp
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DisplayManager.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date September 21, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_DisplayManager.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
|
||||
GHOST_DisplayManager::GHOST_DisplayManager(
|
||||
void)
|
||||
: m_settingsInitialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_DisplayManager::~GHOST_DisplayManager(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManager::initialize(
|
||||
void)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (!m_settingsInitialized) {
|
||||
success = initializeSettings();
|
||||
m_settingsInitialized = true;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManager::getNumDisplays(
|
||||
GHOST_TUns8& /*numDisplays*/) const
|
||||
{
|
||||
// Don't know if we have a display...
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManager::getNumDisplaySettings(
|
||||
GHOST_TUns8 display,
|
||||
GHOST_TInt32& numSettings) const
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
|
||||
GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::getNumDisplaySettings(): m_settingsInitialized=false");
|
||||
GHOST_TUns8 numDisplays;
|
||||
success = getNumDisplays(numDisplays);
|
||||
if (success == GHOST_kSuccess) {
|
||||
if (display < numDisplays) {
|
||||
numSettings = m_settings[display].size();
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManager::getDisplaySetting(
|
||||
GHOST_TUns8 display,
|
||||
GHOST_TInt32 index,
|
||||
GHOST_DisplaySetting& setting) const
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
|
||||
GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::getNumDisplaySettings(): m_settingsInitialized=false");
|
||||
GHOST_TUns8 numDisplays;
|
||||
success = getNumDisplays(numDisplays);
|
||||
if (success == GHOST_kSuccess) {
|
||||
if (display < numDisplays && ((GHOST_TUns8)index < m_settings[display].size())) {
|
||||
setting = m_settings[display][index];
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManager::getCurrentDisplaySetting(
|
||||
GHOST_TUns8 /*display*/,
|
||||
GHOST_DisplaySetting& /*setting*/) const
|
||||
{
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManager::setCurrentDisplaySetting(
|
||||
GHOST_TUns8 /*display*/,
|
||||
const GHOST_DisplaySetting& /*setting*/)
|
||||
{
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManager::findMatch(
|
||||
GHOST_TUns8 display,
|
||||
const GHOST_DisplaySetting& setting,
|
||||
GHOST_DisplaySetting& match) const
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kSuccess;
|
||||
GHOST_ASSERT(m_settingsInitialized, "GHOST_DisplayManager::findMatch(): m_settingsInitialized=false");
|
||||
|
||||
int criteria[4] = { setting.xPixels, setting.yPixels, setting.bpp, setting.frequency };
|
||||
int capabilities[4];
|
||||
double field, score;
|
||||
double best = 1e12; // A big number
|
||||
int found = 0;
|
||||
|
||||
// Look at all the display modes
|
||||
for (int i = 0; (i < (int)m_settings[display].size()); i++) {
|
||||
// Store the capabilities of the display device
|
||||
capabilities[0] = m_settings[display][i].xPixels;
|
||||
capabilities[1] = m_settings[display][i].yPixels;
|
||||
capabilities[2] = m_settings[display][i].bpp;
|
||||
capabilities[3] = m_settings[display][i].frequency;
|
||||
|
||||
// Match against all the fields of the display settings
|
||||
score = 0;
|
||||
for (int j = 0; j < 4; j++) {
|
||||
field = capabilities[j] - criteria[j];
|
||||
score += field * field;
|
||||
}
|
||||
|
||||
if (score < best) {
|
||||
found = i;
|
||||
best = score;
|
||||
}
|
||||
}
|
||||
|
||||
match = m_settings[display][found];
|
||||
|
||||
GHOST_PRINT("GHOST_DisplayManager::findMatch(): settings of match:\n");
|
||||
GHOST_PRINT(" setting.xPixels=" << match.xPixels << "\n");
|
||||
GHOST_PRINT(" setting.yPixels=" << match.yPixels << "\n");
|
||||
GHOST_PRINT(" setting.bpp=" << match.bpp << "\n");
|
||||
GHOST_PRINT(" setting.frequency=" << match.frequency << "\n");
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManager::initializeSettings(
|
||||
void)
|
||||
{
|
||||
GHOST_TUns8 numDisplays;
|
||||
GHOST_TSuccess success = getNumDisplays(numDisplays);
|
||||
if (success == GHOST_kSuccess) {
|
||||
for (GHOST_TUns8 display = 0; (display < numDisplays) && (success == GHOST_kSuccess); display++) {
|
||||
GHOST_DisplaySettings displaySettings;
|
||||
m_settings.push_back(displaySettings);
|
||||
GHOST_TInt32 numSettings;
|
||||
success = getNumDisplaySettings(display, numSettings);
|
||||
if (success == GHOST_kSuccess) {
|
||||
GHOST_TInt32 index;
|
||||
GHOST_DisplaySetting setting;
|
||||
for (index = 0; (index < numSettings) && (success == GHOST_kSuccess); index++) {
|
||||
success = getDisplaySetting(display, index, setting);
|
||||
m_settings[display].push_back(setting);
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
134
intern/ghost/intern/GHOST_DisplayManager.h
Normal file
134
intern/ghost/intern/GHOST_DisplayManager.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DisplayManager.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_DisplayManager class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_DISPLAY_MANAGER_H_
|
||||
#define _GHOST_DISPLAY_MANAGER_H_
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Manages system displays (platform independent implementation).
|
||||
* @author Maarten Gribnau
|
||||
* @date September 21, 2001
|
||||
*/
|
||||
class GHOST_DisplayManager
|
||||
{
|
||||
public:
|
||||
enum { kMainDisplay = 0 };
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_DisplayManager(void);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_DisplayManager(void);
|
||||
|
||||
/**
|
||||
* Initializes the list with devices and settings.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess initialize(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.
|
||||
* The setting given to this method is matched againts the available diplay settings.
|
||||
* The best match is activated (@see findMatch()).
|
||||
* @param display The index of the display to query with 0 <= display < getNumDisplays().
|
||||
* @param setting The setting of the display device to be matched and activated.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting);
|
||||
|
||||
protected:
|
||||
typedef std::vector<GHOST_DisplaySetting> GHOST_DisplaySettings;
|
||||
|
||||
/**
|
||||
* Finds the best display settings match.
|
||||
* @param display The index of the display device.
|
||||
* @param setting The setting to match.
|
||||
* @param match The optimal display setting.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
GHOST_TSuccess findMatch(GHOST_TUns8 display, const GHOST_DisplaySetting& setting, GHOST_DisplaySetting& match) const;
|
||||
|
||||
/**
|
||||
* Retrieves settings for each display device and stores them.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
GHOST_TSuccess initializeSettings(void);
|
||||
|
||||
/** Tells whether the list of display modes has been stored already. */
|
||||
bool m_settingsInitialized;
|
||||
/** The list with display settings for the main display. */
|
||||
std::vector<GHOST_DisplaySettings> m_settings;
|
||||
};
|
||||
|
||||
|
||||
#endif // _GHOST_DISPLAY_MANAGER_H_
|
||||
|
||||
179
intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp
Normal file
179
intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DisplayManagerCarbon.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date September 21, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_DisplayManagerCarbon.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
// We do not support multiple monitors at the moment
|
||||
|
||||
|
||||
GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(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_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(): memory allocation failed");
|
||||
::CGGetActiveDisplayList(m_numDisplays, m_displayIDs, &m_numDisplays);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplays(GHOST_TUns8& numDisplays) const
|
||||
{
|
||||
numDisplays = (GHOST_TUns8) m_numDisplays;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::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_DisplayManagerCarbon::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::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_DisplayManagerCarbon::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::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_DisplayManagerCarbon::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting)
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): only main display is supported");
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
printf("GHOST_DisplayManagerCarbon::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_DisplayManagerCarbon::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_DisplayManagerCarbon::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;
|
||||
}
|
||||
|
||||
117
intern/ghost/intern/GHOST_DisplayManagerCarbon.h
Normal file
117
intern/ghost/intern/GHOST_DisplayManagerCarbon.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DisplayManagerCarbon.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_DisplayManagerCarbon class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_DISPLAY_MANAGER_CARBON_H_
|
||||
#define _GHOST_DISPLAY_MANAGER_CARBON_H_
|
||||
|
||||
#ifndef __APPLE__
|
||||
#error Apple only!
|
||||
#endif // __APPLE__
|
||||
|
||||
#include "GHOST_DisplayManager.h"
|
||||
|
||||
#define __CARBONSOUND__
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
/**
|
||||
* Manages system displays (Mac OSX/Carbon implementation).
|
||||
* @see GHOST_DisplayManager
|
||||
* @author Maarten Gribnau
|
||||
* @date September 21, 2001
|
||||
*/
|
||||
class GHOST_DisplayManagerCarbon : public GHOST_DisplayManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_DisplayManagerCarbon(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_CARBON_H_
|
||||
|
||||
107
intern/ghost/intern/GHOST_DisplayManagerCocoa.h
Normal file
107
intern/ghost/intern/GHOST_DisplayManagerCocoa.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DisplayManagerCocoa.h
|
||||
* \ingroup GHOST
|
||||
* 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:
|
||||
//Do not cache values as OS X supports screen hot plug
|
||||
/** Cached number of displays. */
|
||||
//CGDisplayCount m_numDisplays;
|
||||
/** Cached display id's for each display. */
|
||||
//CGDirectDisplayID* m_displayIDs;
|
||||
};
|
||||
|
||||
|
||||
#endif // _GHOST_DISPLAY_MANAGER_COCOA_H_
|
||||
|
||||
168
intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
Normal file
168
intern/ghost/intern/GHOST_DisplayManagerCocoa.mm
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 09/2001
|
||||
Damien Plisson 10/2009
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
#include "GHOST_DisplayManagerCocoa.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
// We do not support multiple monitors at the moment
|
||||
|
||||
|
||||
GHOST_DisplayManagerCocoa::GHOST_DisplayManagerCocoa(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerCocoa::getNumDisplays(GHOST_TUns8& numDisplays) const
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
numDisplays = (GHOST_TUns8) [[NSScreen screens] count];
|
||||
|
||||
[pool drain];
|
||||
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");
|
||||
|
||||
numSettings = (GHOST_TInt32)3; //Width, Height, BitsPerPixel
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerCocoa::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
|
||||
{
|
||||
//Note that only current display setting is available
|
||||
NSScreen *askedDisplay;
|
||||
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getDisplaySetting(): only main display is supported");
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (display == kMainDisplay) //Screen #0 may not be the main one
|
||||
askedDisplay = [NSScreen mainScreen];
|
||||
else
|
||||
askedDisplay = [[NSScreen screens] objectAtIndex:display];
|
||||
|
||||
if(askedDisplay == nil) {
|
||||
[pool drain];
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
NSRect frame = [askedDisplay visibleFrame];
|
||||
setting.xPixels = frame.size.width;
|
||||
setting.yPixels = frame.size.height;
|
||||
|
||||
setting.bpp = NSBitsPerPixelFromDepth([askedDisplay depth]);
|
||||
|
||||
setting.frequency = 0; //No more CRT display...
|
||||
|
||||
#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
|
||||
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
|
||||
{
|
||||
NSScreen *askedDisplay;
|
||||
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCocoa::getCurrentDisplaySetting(): only main display is supported");
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (display == kMainDisplay) //Screen #0 may not be the main one
|
||||
askedDisplay = [NSScreen mainScreen];
|
||||
else
|
||||
askedDisplay = [[NSScreen screens] objectAtIndex:display];
|
||||
|
||||
if(askedDisplay == nil) {
|
||||
[pool drain];
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
NSRect frame = [askedDisplay visibleFrame];
|
||||
setting.xPixels = frame.size.width;
|
||||
setting.yPixels = frame.size.height;
|
||||
|
||||
setting.bpp = NSBitsPerPixelFromDepth([askedDisplay depth]);
|
||||
|
||||
setting.frequency = 0; //No more CRT display...
|
||||
|
||||
#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
|
||||
|
||||
[pool drain];
|
||||
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
|
||||
|
||||
//Display configuration is no more available in 10.6
|
||||
|
||||
/* 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;
|
||||
}
|
||||
182
intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
Normal file
182
intern/ghost/intern/GHOST_DisplayManagerWin32.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DisplayManagerWin32.cpp
|
||||
* \ingroup GHOST
|
||||
* \author Maarten Gribnau
|
||||
* \date September 21, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_DisplayManagerWin32.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
// We do not support multiple monitors at the moment
|
||||
#include <windows.h>
|
||||
#define COMPILE_MULTIMON_STUBS
|
||||
#ifndef FREE_WINDOWS
|
||||
#include <multimon.h>
|
||||
#endif
|
||||
|
||||
|
||||
GHOST_DisplayManagerWin32::GHOST_DisplayManagerWin32(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplays(GHOST_TUns8& numDisplays) const
|
||||
{
|
||||
// We do not support multiple monitors at the moment
|
||||
numDisplays = ::GetSystemMetrics(SM_CMONITORS);
|
||||
return numDisplays > 0 ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When you call EnumDisplaySettings with iModeNum set to zero, the operating system
|
||||
* initializes and caches information about the display device. When you call
|
||||
* EnumDisplaySettings with iModeNum set to a non-zero value, the function returns
|
||||
* the information that was cached the last time the function was called with iModeNum
|
||||
* set to zero.
|
||||
*/
|
||||
GHOST_TSuccess GHOST_DisplayManagerWin32::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::getNumDisplaySettings(): only main displlay is supported");
|
||||
numSettings = 0;
|
||||
DEVMODE dm;
|
||||
while (::EnumDisplaySettings(NULL, numSettings, &dm)) {
|
||||
numSettings++;
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerWin32::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::getDisplaySetting(): only main display is supported");
|
||||
GHOST_TSuccess success;
|
||||
DEVMODE dm;
|
||||
if (::EnumDisplaySettings(NULL, index, &dm)) {
|
||||
#ifdef GHOST_DEBUG
|
||||
printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency);
|
||||
#endif // GHOST_DEBUG
|
||||
setting.xPixels = dm.dmPelsWidth;
|
||||
setting.yPixels = dm.dmPelsHeight;
|
||||
setting.bpp = dm.dmBitsPerPel;
|
||||
/* When you call the EnumDisplaySettings function, the dmDisplayFrequency member
|
||||
* may return with the value 0 or 1. These values represent the display hardware's
|
||||
* default refresh rate. This default rate is typically set by switches on a display
|
||||
* card or computer motherboard, or by a configuration program that does not use
|
||||
* Win32 display functions such as ChangeDisplaySettings.
|
||||
*/
|
||||
/* First, we tried to explicitly set the frequency to 60 if EnumDisplaySettings
|
||||
* returned 0 or 1 but this doesn't work since later on an exact match will
|
||||
* be searched. And this will never happen if we change it to 60. Now we rely
|
||||
* on the default h/w setting.
|
||||
*/
|
||||
setting.frequency = dm.dmDisplayFrequency;
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerWin32::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::getCurrentDisplaySetting(): only main display is supported");
|
||||
return getDisplaySetting(kMainDisplay, ENUM_CURRENT_SETTINGS, setting);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_DisplayManagerWin32::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting)
|
||||
{
|
||||
GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerWin32::setCurrentDisplaySetting(): only main display is supported");
|
||||
|
||||
GHOST_DisplaySetting match;
|
||||
findMatch(display, setting, match);
|
||||
DEVMODE dm;
|
||||
int i = 0;
|
||||
while (::EnumDisplaySettings(NULL, i++, &dm)) {
|
||||
if ((dm.dmBitsPerPel == match.bpp) &&
|
||||
(dm.dmPelsWidth == match.xPixels) &&
|
||||
(dm.dmPelsHeight == match.yPixels) &&
|
||||
(dm.dmDisplayFrequency == match.frequency)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
dm.dmBitsPerPel = match.bpp;
|
||||
dm.dmPelsWidth = match.xPixels;
|
||||
dm.dmPelsHeight = match.yPixels;
|
||||
dm.dmDisplayFrequency = match.frequency;
|
||||
dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
|
||||
dm.dmSize = sizeof(DEVMODE);
|
||||
dm.dmDriverExtra = 0;
|
||||
*/
|
||||
#ifdef GHOST_DEBUG
|
||||
printf("display change: Requested settings:\n");
|
||||
printf(" dmBitsPerPel=%d\n", dm.dmBitsPerPel);
|
||||
printf(" dmPelsWidth=%d\n", dm.dmPelsWidth);
|
||||
printf(" dmPelsHeight=%d\n", dm.dmPelsHeight);
|
||||
printf(" dmDisplayFrequency=%d\n", dm.dmDisplayFrequency);
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
LONG status = ::ChangeDisplaySettings(&dm, CDS_FULLSCREEN);
|
||||
#ifdef GHOST_DEBUG
|
||||
switch (status)
|
||||
{
|
||||
case DISP_CHANGE_SUCCESSFUL:
|
||||
printf("display change: The settings change was successful.\n");
|
||||
break;
|
||||
case DISP_CHANGE_RESTART:
|
||||
printf("display change: The computer must be restarted in order for the graphics mode to work.\n");
|
||||
break;
|
||||
case DISP_CHANGE_BADFLAGS:
|
||||
printf("display change: An invalid set of flags was passed in.\n");
|
||||
break;
|
||||
case DISP_CHANGE_BADPARAM:
|
||||
printf("display change: An invalid parameter was passed in. This can include an invalid flag or combination of flags.\n");
|
||||
break;
|
||||
case DISP_CHANGE_FAILED:
|
||||
printf("display change: The display driver failed the specified graphics mode.\n");
|
||||
break;
|
||||
case DISP_CHANGE_BADMODE:
|
||||
printf("display change: The graphics mode is not supported.\n");
|
||||
break;
|
||||
case DISP_CHANGE_NOTUPDATED:
|
||||
printf("display change: Windows NT: Unable to write settings to the registry.\n");
|
||||
break;
|
||||
default:
|
||||
printf("display change: Return value invalid\n");
|
||||
break;
|
||||
}
|
||||
#endif // GHOST_DEBUG
|
||||
return status == DISP_CHANGE_SUCCESSFUL? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
102
intern/ghost/intern/GHOST_DisplayManagerWin32.h
Normal file
102
intern/ghost/intern/GHOST_DisplayManagerWin32.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DisplayManagerWin32.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_DisplayManagerWin32 class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_DISPLAY_MANAGER_WIN32_H_
|
||||
#define _GHOST_DISPLAY_MANAGER_WIN32_H_
|
||||
|
||||
#ifndef WIN32
|
||||
#error WIN32 only!
|
||||
#endif // WIN32
|
||||
|
||||
#include "GHOST_DisplayManager.h"
|
||||
|
||||
|
||||
/**
|
||||
* Manages system displays (WIN32 implementation).
|
||||
* @author Maarten Gribnau
|
||||
* @date September 21, 2001
|
||||
*/
|
||||
class GHOST_DisplayManagerWin32 : public GHOST_DisplayManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_DisplayManagerWin32(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:
|
||||
};
|
||||
|
||||
|
||||
#endif // _GHOST_DISPLAY_MANAGER_WIN32_H_
|
||||
|
||||
126
intern/ghost/intern/GHOST_DisplayManagerX11.cpp
Normal file
126
intern/ghost/intern/GHOST_DisplayManagerX11.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DisplayManagerX11.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include "GHOST_DisplayManagerX11.h"
|
||||
#include "GHOST_SystemX11.h"
|
||||
|
||||
|
||||
|
||||
GHOST_DisplayManagerX11::
|
||||
GHOST_DisplayManagerX11(
|
||||
GHOST_SystemX11 *system
|
||||
) :
|
||||
GHOST_DisplayManager(),
|
||||
m_system(system)
|
||||
{
|
||||
//nothing to do.
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManagerX11::
|
||||
getNumDisplays(
|
||||
GHOST_TUns8& numDisplays
|
||||
) const{
|
||||
numDisplays = m_system->getNumDisplays();
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManagerX11::
|
||||
getNumDisplaySettings(
|
||||
GHOST_TUns8 display,
|
||||
GHOST_TInt32& numSettings
|
||||
) const{
|
||||
|
||||
// We only have one X11 setting at the moment.
|
||||
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
|
||||
numSettings = GHOST_TInt32(1);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManagerX11::
|
||||
getDisplaySetting(
|
||||
GHOST_TUns8 display,
|
||||
GHOST_TInt32 index,
|
||||
GHOST_DisplaySetting& setting
|
||||
) const {
|
||||
|
||||
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
|
||||
GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n");
|
||||
|
||||
Display * x_display = m_system->getXDisplay();
|
||||
|
||||
if (x_display == NULL) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
setting.xPixels = DisplayWidth(x_display, DefaultScreen(x_display));
|
||||
setting.yPixels = DisplayHeight(x_display, DefaultScreen(x_display));
|
||||
setting.bpp = DefaultDepth(x_display,DefaultScreen(x_display));
|
||||
|
||||
// Don't think it's possible to get this value from X!
|
||||
// So let's guess!!
|
||||
setting.frequency = 60;
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManagerX11::
|
||||
getCurrentDisplaySetting(
|
||||
GHOST_TUns8 display,
|
||||
GHOST_DisplaySetting& setting
|
||||
) const {
|
||||
return getDisplaySetting(display,GHOST_TInt32(0),setting);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_DisplayManagerX11::
|
||||
setCurrentDisplaySetting(
|
||||
GHOST_TUns8 display,
|
||||
const GHOST_DisplaySetting& setting
|
||||
){
|
||||
// This is never going to work robustly in X
|
||||
// but it's currently part of the full screen interface
|
||||
|
||||
// we fudge it for now.
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
124
intern/ghost/intern/GHOST_DisplayManagerX11.h
Normal file
124
intern/ghost/intern/GHOST_DisplayManagerX11.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DisplayManagerX11.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_DisplayManagerX11 class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_DISPLAY_MANAGER_X11_H_
|
||||
#define _GHOST_DISPLAY_MANAGER_X11_H_
|
||||
|
||||
#include "GHOST_DisplayManager.h"
|
||||
|
||||
|
||||
class GHOST_SystemX11;
|
||||
|
||||
/**
|
||||
* Manages system displays (X11 implementation).
|
||||
* @author Laurence Bourn
|
||||
* @date October 26, 2001
|
||||
*/
|
||||
class GHOST_DisplayManagerX11 : public GHOST_DisplayManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_DisplayManagerX11(
|
||||
GHOST_SystemX11 *system
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the number of display devices on this system.
|
||||
* @param numDisplays The number of displays on this system.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
setCurrentDisplaySetting(
|
||||
GHOST_TUns8 display,
|
||||
const GHOST_DisplaySetting& setting
|
||||
);
|
||||
|
||||
private :
|
||||
|
||||
GHOST_SystemX11 * m_system;
|
||||
};
|
||||
|
||||
|
||||
#endif //
|
||||
|
||||
431
intern/ghost/intern/GHOST_DropTargetWin32.cpp
Normal file
431
intern/ghost/intern/GHOST_DropTargetWin32.cpp
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DropTargetWin32.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include "GHOST_Debug.h"
|
||||
#include "GHOST_DropTargetWin32.h"
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
// utility
|
||||
void printLastError(void);
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
|
||||
GHOST_DropTargetWin32::GHOST_DropTargetWin32(GHOST_WindowWin32 * window, GHOST_SystemWin32 * system)
|
||||
:
|
||||
m_window(window),
|
||||
m_system(system)
|
||||
{
|
||||
m_cRef = 1;
|
||||
m_hWnd = window->getHWND();
|
||||
m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
|
||||
|
||||
// register our window as drop target
|
||||
::RegisterDragDrop(m_hWnd, this);
|
||||
}
|
||||
|
||||
GHOST_DropTargetWin32::~GHOST_DropTargetWin32()
|
||||
{
|
||||
::RevokeDragDrop(m_hWnd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* IUnknown::QueryInterface
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::QueryInterface (REFIID riid, void ** ppvObj)
|
||||
{
|
||||
|
||||
if (!ppvObj)
|
||||
return E_INVALIDARG;
|
||||
*ppvObj = NULL;
|
||||
|
||||
if(riid == IID_IUnknown || riid == IID_IDropTarget)
|
||||
{
|
||||
AddRef();
|
||||
*ppvObj = (void*)this;
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppvObj = 0;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* IUnknown::AddRef
|
||||
*/
|
||||
|
||||
ULONG __stdcall GHOST_DropTargetWin32::AddRef(void)
|
||||
{
|
||||
return ::InterlockedIncrement(&m_cRef);
|
||||
}
|
||||
|
||||
/*
|
||||
* IUnknown::Release
|
||||
*/
|
||||
ULONG __stdcall GHOST_DropTargetWin32::Release(void)
|
||||
{
|
||||
ULONG refs = ::InterlockedDecrement(&m_cRef);
|
||||
|
||||
if(refs == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return refs;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of IDropTarget::DragEnter
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::DragEnter(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
|
||||
{
|
||||
// we accept all drop by default
|
||||
m_window->setAcceptDragOperation(true);
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
|
||||
m_draggedObjectType = getGhostType(pDataObject);
|
||||
m_system->pushDragDropEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, m_window, pt.x, pt.y, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of IDropTarget::DragOver
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
|
||||
{
|
||||
if(m_window->canAcceptDragOperation())
|
||||
{
|
||||
*pdwEffect = allowedDropEffect(*pdwEffect);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
//*pdwEffect = DROPEFFECT_COPY; // XXX Uncomment to test drop. Drop will not be called if pdwEffect == DROPEFFECT_NONE.
|
||||
}
|
||||
m_system->pushDragDropEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, m_window, pt.x, pt.y, NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of IDropTarget::DragLeave
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::DragLeave(void)
|
||||
{
|
||||
m_system->pushDragDropEvent(GHOST_kEventDraggingExited, m_draggedObjectType, m_window, 0, 0, NULL);
|
||||
m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* Implementation of IDropTarget::Drop
|
||||
* This function will not be called if pdwEffect is set to DROPEFFECT_NONE in
|
||||
* the implementation of IDropTarget::DragOver
|
||||
*/
|
||||
HRESULT __stdcall GHOST_DropTargetWin32::Drop(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect)
|
||||
{
|
||||
void * data = getGhostData(pDataObject);
|
||||
if(m_window->canAcceptDragOperation())
|
||||
{
|
||||
*pdwEffect = allowedDropEffect(*pdwEffect);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdwEffect = DROPEFFECT_NONE;
|
||||
}
|
||||
if (data)
|
||||
m_system->pushDragDropEvent(GHOST_kEventDraggingDropDone, m_draggedObjectType, m_window, pt.x, pt.y, data );
|
||||
|
||||
m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
DWORD GHOST_DropTargetWin32::allowedDropEffect(DWORD dwAllowed)
|
||||
{
|
||||
DWORD dwEffect = DROPEFFECT_NONE;
|
||||
if(dwAllowed & DROPEFFECT_COPY)
|
||||
dwEffect = DROPEFFECT_COPY;
|
||||
|
||||
return dwEffect;
|
||||
}
|
||||
|
||||
GHOST_TDragnDropTypes GHOST_DropTargetWin32::getGhostType(IDataObject * pDataObject)
|
||||
{
|
||||
/* Text
|
||||
* Note: Unicode text is aviable as CF_TEXT too, the system can do the
|
||||
* conversion, but we do the conversion ourself with WC_NO_BEST_FIT_CHARS.
|
||||
*/
|
||||
FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
if(pDataObject->QueryGetData(&fmtetc) == S_OK)
|
||||
{
|
||||
return GHOST_kDragnDropTypeString;
|
||||
}
|
||||
|
||||
// Filesnames
|
||||
fmtetc.cfFormat = CF_HDROP;
|
||||
if(pDataObject->QueryGetData(&fmtetc) == S_OK)
|
||||
{
|
||||
return GHOST_kDragnDropTypeFilenames;
|
||||
}
|
||||
|
||||
return GHOST_kDragnDropTypeUnknown;
|
||||
}
|
||||
|
||||
void * GHOST_DropTargetWin32::getGhostData(IDataObject * pDataObject)
|
||||
{
|
||||
GHOST_TDragnDropTypes type = getGhostType(pDataObject);
|
||||
switch(type)
|
||||
{
|
||||
case GHOST_kDragnDropTypeFilenames:
|
||||
return getDropDataAsFilenames(pDataObject);
|
||||
break;
|
||||
case GHOST_kDragnDropTypeString:
|
||||
return getDropDataAsString(pDataObject);
|
||||
break;
|
||||
case GHOST_kDragnDropTypeBitmap:
|
||||
//return getDropDataAsBitmap(pDataObject);
|
||||
break;
|
||||
default:
|
||||
#ifdef GHOST_DEBUG
|
||||
::printf("\nGHOST_kDragnDropTypeUnknown");
|
||||
#endif // GHOST_DEBUG
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject * pDataObject)
|
||||
{
|
||||
UINT totfiles, nvalid=0;
|
||||
WCHAR fpath [MAX_PATH];
|
||||
char * temp_path;
|
||||
GHOST_TStringArray *strArray = NULL;
|
||||
FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
STGMEDIUM stgmed;
|
||||
HDROP hdrop;
|
||||
|
||||
// Check if dataobject supplies the format we want.
|
||||
// Double checking here, first in getGhostType.
|
||||
if(pDataObject->QueryGetData(&fmtetc) == S_OK)
|
||||
{
|
||||
if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
|
||||
{
|
||||
hdrop = (HDROP)::GlobalLock(stgmed.hGlobal);
|
||||
|
||||
totfiles = ::DragQueryFileW ( hdrop, -1, NULL, 0 );
|
||||
if (!totfiles)
|
||||
{
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strArray = (GHOST_TStringArray*) ::malloc(sizeof(GHOST_TStringArray));
|
||||
strArray->count = 0;
|
||||
strArray->strings = (GHOST_TUns8**) ::malloc(totfiles*sizeof(GHOST_TUns8*));
|
||||
|
||||
for ( UINT nfile = 0; nfile < totfiles; nfile++ )
|
||||
{
|
||||
if ( ::DragQueryFileW ( hdrop, nfile, fpath, MAX_PATH ) > 0 )
|
||||
{
|
||||
if ( !WideCharToANSI(fpath, temp_path) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Just ignore paths that could not be converted verbatim.
|
||||
if (strpbrk(temp_path, "?"))
|
||||
{
|
||||
#ifdef GHOST_DEBUG
|
||||
::printf("\ndiscarding path that contains illegal characters: %s", temp_path);
|
||||
#endif // GHOST_DEBUG
|
||||
::free(temp_path);
|
||||
temp_path = NULL;
|
||||
continue;
|
||||
}
|
||||
strArray->strings[nvalid] = (GHOST_TUns8*) temp_path;
|
||||
strArray->count = nvalid+1;
|
||||
nvalid++;
|
||||
}
|
||||
}
|
||||
// Free up memory.
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
::ReleaseStgMedium(&stgmed);
|
||||
|
||||
return strArray;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * GHOST_DropTargetWin32::getDropDataAsString(IDataObject * pDataObject)
|
||||
{
|
||||
char* tmp_string;
|
||||
FORMATETC fmtetc = { CF_UNICODETEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
STGMEDIUM stgmed;
|
||||
|
||||
// Try unicode first.
|
||||
// Check if dataobject supplies the format we want.
|
||||
if(pDataObject->QueryGetData(&fmtetc) == S_OK)
|
||||
{
|
||||
if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
|
||||
{
|
||||
LPCWSTR wstr = (LPCWSTR)::GlobalLock(stgmed.hGlobal);
|
||||
if ( !WideCharToANSI(wstr, tmp_string) )
|
||||
{
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
return NULL;
|
||||
}
|
||||
// Free memory
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
::ReleaseStgMedium(&stgmed);
|
||||
#ifdef GHOST_DEBUG
|
||||
::printf("\n<converted droped unicode string>\n%s\n</droped converted unicode string>\n",tmp_string);
|
||||
#endif // GHOST_DEBUG
|
||||
return tmp_string;
|
||||
}
|
||||
}
|
||||
|
||||
fmtetc.cfFormat = CF_TEXT;
|
||||
|
||||
if(pDataObject->QueryGetData(&fmtetc) == S_OK)
|
||||
{
|
||||
if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
|
||||
{
|
||||
char * str = (char*)::GlobalLock(stgmed.hGlobal);
|
||||
|
||||
tmp_string = (char*)::malloc(::strlen(str)+1);
|
||||
if ( !tmp_string )
|
||||
{
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( !::strcpy(tmp_string, str) )
|
||||
{
|
||||
::free(tmp_string);
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
return NULL;
|
||||
}
|
||||
// Free memory
|
||||
::GlobalUnlock(stgmed.hGlobal);
|
||||
::ReleaseStgMedium(&stgmed);
|
||||
|
||||
return tmp_string;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char * &out)
|
||||
{
|
||||
int size;
|
||||
out = NULL; //caller should free if != NULL
|
||||
|
||||
// Get the required size.
|
||||
size = ::WideCharToMultiByte(CP_ACP, //System Default Codepage
|
||||
0x00000400, // WC_NO_BEST_FIT_CHARS
|
||||
in,
|
||||
-1, //-1 null terminated, makes output null terminated too.
|
||||
NULL,
|
||||
0,
|
||||
NULL,NULL
|
||||
);
|
||||
|
||||
if(!size)
|
||||
{
|
||||
#ifdef GHOST_DEBUG
|
||||
::printLastError();
|
||||
#endif // GHOST_DEBUG
|
||||
return 0;
|
||||
}
|
||||
|
||||
out = (char*)::malloc(size);
|
||||
if (!out)
|
||||
{
|
||||
::printf("\nmalloc failed!!!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = ::WideCharToMultiByte(CP_ACP,
|
||||
0x00000400,
|
||||
in,
|
||||
-1,
|
||||
(LPSTR) out,
|
||||
size,
|
||||
NULL,NULL
|
||||
);
|
||||
|
||||
if(!size)
|
||||
{
|
||||
#ifdef GHOST_DEBUG
|
||||
::printLastError();
|
||||
#endif //GHOST_DEBUG
|
||||
::free(out);
|
||||
out = NULL;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
void printLastError(void)
|
||||
{
|
||||
LPTSTR s;
|
||||
DWORD err;
|
||||
|
||||
err = GetLastError();
|
||||
if(FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
err,
|
||||
0,
|
||||
(LPTSTR)&s,
|
||||
0,
|
||||
NULL)
|
||||
)
|
||||
{
|
||||
printf("\nLastError: (%d) %s\n", (int)err, s);
|
||||
LocalFree(s);
|
||||
}
|
||||
}
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
160
intern/ghost/intern/GHOST_DropTargetWin32.h
Normal file
160
intern/ghost/intern/GHOST_DropTargetWin32.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_DropTargetWin32.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_DROP_TARGET_WIN32_H_
|
||||
#define _GHOST_DROP_TARGET_WIN32_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include <string.h>
|
||||
#include <GHOST_Types.h>
|
||||
#include "GHOST_WindowWin32.h"
|
||||
#include "GHOST_SystemWin32.h"
|
||||
|
||||
class GHOST_DropTargetWin32 : public IDropTarget
|
||||
{
|
||||
public:
|
||||
/* IUnknownd implementation.
|
||||
* Enables clients to get pointers to other interfaces on a given object
|
||||
* through the QueryInterface method, and manage the existence of the object
|
||||
* through the AddRef and Release methods. All other COM interfaces are
|
||||
* inherited, directly or indirectly, from IUnknown. Therefore, the three
|
||||
* methods in IUnknown are the first entries in the VTable for every interface.
|
||||
*/
|
||||
HRESULT __stdcall QueryInterface (REFIID riid, void ** ppvObj);
|
||||
ULONG __stdcall AddRef (void);
|
||||
ULONG __stdcall Release (void);
|
||||
|
||||
/* IDropTarget implementation
|
||||
+ The IDropTarget interface is one of the interfaces you implement to
|
||||
provide drag-and-drop operations in your application. It contains methods
|
||||
used in any application that can be a target for data during a
|
||||
drag-and-drop operation. A drop-target application is responsible for:
|
||||
*
|
||||
* - Determining the effect of the drop on the target application.
|
||||
* - Incorporating any valid dropped data when the drop occurs.
|
||||
* - Communicating target feedback to the source so the source application
|
||||
* can provide appropriate visual feedback such as setting the cursor.
|
||||
* - Implementing drag scrolling.
|
||||
* - Registering and revoking its application windows as drop targets.
|
||||
*
|
||||
* The IDropTarget interface contains methods that handle all these
|
||||
* responsibilities except registering and revoking the application window
|
||||
* as a drop target, for which you must call the RegisterDragDrop and the
|
||||
* RevokeDragDrop functions.
|
||||
*/
|
||||
|
||||
HRESULT __stdcall DragEnter (IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
|
||||
HRESULT __stdcall DragOver (DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
|
||||
HRESULT __stdcall DragLeave (void);
|
||||
HRESULT __stdcall Drop (IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* With the modifier keys, we want to distinguish left and right keys.
|
||||
* Sometimes this is not possible (Windows ME for instance). Then, we want
|
||||
* events generated for both keys.
|
||||
* @param window The window to register as drop target.
|
||||
* @param system The associated system.
|
||||
*/
|
||||
GHOST_DropTargetWin32(GHOST_WindowWin32 * window, GHOST_SystemWin32 * system);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
* Do NOT destroy directly. Use Release() instead to make COM happy.
|
||||
*/
|
||||
~GHOST_DropTargetWin32();
|
||||
|
||||
private:
|
||||
|
||||
/* Internal helper functions */
|
||||
|
||||
/**
|
||||
* Base the effect on those allowed by the dropsource.
|
||||
* @param dwAllowed Drop sources allowed drop effect.
|
||||
* @return The allowed drop effect.
|
||||
*/
|
||||
DWORD allowedDropEffect(DWORD dwAllowed);
|
||||
|
||||
/**
|
||||
* Query DataObject for the data types it supports.
|
||||
* @param pDataObject Pointer to the DataObject.
|
||||
* @return GHOST data type.
|
||||
*/
|
||||
GHOST_TDragnDropTypes getGhostType(IDataObject * pDataObject);
|
||||
|
||||
/**
|
||||
* Get data to pass in event.
|
||||
* It checks the type and calls specific functions for each type.
|
||||
* @param pDataObject Pointer to the DataObject.
|
||||
* @return Pointer to data.
|
||||
*/
|
||||
void * getGhostData(IDataObject * pDataObject);
|
||||
|
||||
/**
|
||||
* Allocate data as file array to pass in event.
|
||||
* @param pDataObject Pointer to the DataObject.
|
||||
* @return Pointer to data.
|
||||
*/
|
||||
void * getDropDataAsFilenames(IDataObject * pDataObject);
|
||||
|
||||
/**
|
||||
* Allocate data as string to pass in event.
|
||||
* @param pDataObject Pointer to the DataObject.
|
||||
* @return Pointer to data.
|
||||
*/
|
||||
void * getDropDataAsString(IDataObject * pDataObject);
|
||||
|
||||
/**
|
||||
* Convert Unicode to ANSI, replacing unconvertable chars with '?'.
|
||||
* The ANSI codepage is the system default codepage,
|
||||
* and can change from system to system.
|
||||
* @param in LPCWSTR.
|
||||
* @param out char *. Is set to NULL on failure.
|
||||
* @return 0 on failure. Else the size of the string including '\0'.
|
||||
*/
|
||||
int WideCharToANSI(LPCWSTR in, char * &out);
|
||||
|
||||
/* Private member variables */
|
||||
/* COM reference count. */
|
||||
LONG m_cRef;
|
||||
/* Handle of the associated window. */
|
||||
HWND m_hWnd;
|
||||
/* The associated GHOST_WindowWin32. */
|
||||
GHOST_WindowWin32 * m_window;
|
||||
/* The System. */
|
||||
GHOST_SystemWin32 * m_system;
|
||||
/* Data type of the dragged object */
|
||||
GHOST_TDragnDropTypes m_draggedObjectType;
|
||||
|
||||
};
|
||||
|
||||
#endif // _GHOST_DROP_TARGET_WIN32_H_
|
||||
108
intern/ghost/intern/GHOST_Event.h
Normal file
108
intern/ghost/intern/GHOST_Event.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_Event.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_Event class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_EVENT_H_
|
||||
#define _GHOST_EVENT_H_
|
||||
|
||||
#include "GHOST_IEvent.h"
|
||||
|
||||
|
||||
/**
|
||||
* Base class for events received the operating system.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 11, 2001
|
||||
*/
|
||||
class GHOST_Event : public GHOST_IEvent
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param msec The time this event was generated.
|
||||
* @param type The type of this event.
|
||||
* @param window The generating window (or NULL if system event).
|
||||
*/
|
||||
GHOST_Event(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window)
|
||||
: m_type(type), m_time(msec), m_window(window), m_data(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event type.
|
||||
* @return The event type.
|
||||
*/
|
||||
virtual GHOST_TEventType getType()
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time this event was generated.
|
||||
* @return The event generation time.
|
||||
*/
|
||||
virtual GHOST_TUns64 getTime()
|
||||
{
|
||||
return m_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the window this event was generated on,
|
||||
* or NULL if it is a 'system' event.
|
||||
* @return The generating window.
|
||||
*/
|
||||
virtual GHOST_IWindow* getWindow()
|
||||
{
|
||||
return m_window;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the event data.
|
||||
* @return The event data.
|
||||
*/
|
||||
virtual GHOST_TEventDataPtr getData()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Type of this event. */
|
||||
GHOST_TEventType m_type;
|
||||
/** The time this event was generated. */
|
||||
GHOST_TUns64 m_time;
|
||||
/** Pointer to the generating window. */
|
||||
GHOST_IWindow* m_window;
|
||||
/** Pointer to the event data. */
|
||||
GHOST_TEventDataPtr m_data;
|
||||
};
|
||||
|
||||
#endif // _GHOST_EVENT_H_
|
||||
|
||||
68
intern/ghost/intern/GHOST_EventButton.h
Normal file
68
intern/ghost/intern/GHOST_EventButton.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_EventButton.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_EventButton class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_EVENT_BUTTON_H_
|
||||
#define _GHOST_EVENT_BUTTON_H_
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
|
||||
/**
|
||||
* Mouse button event.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 11, 2001
|
||||
*/
|
||||
class GHOST_EventButton : public GHOST_Event
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param time The time this event was generated.
|
||||
* @param type The type of this event.
|
||||
* @param x The x-coordinate of the location the cursor was at at the time of the event.
|
||||
* @param y The y-coordinate of the location the cursor was at at the time of the event.
|
||||
* @param buttons The state of the buttons was at at the time of the event.
|
||||
*/
|
||||
GHOST_EventButton(GHOST_TUns64 time, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TButtonMask button)
|
||||
: GHOST_Event(time, type, window)
|
||||
{
|
||||
m_buttonEventData.button = button;
|
||||
m_data = &m_buttonEventData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** The button event data. */
|
||||
GHOST_TEventButtonData m_buttonEventData;
|
||||
};
|
||||
|
||||
#endif // _GHOST_EVENT_BUTTON_H_
|
||||
|
||||
69
intern/ghost/intern/GHOST_EventCursor.h
Normal file
69
intern/ghost/intern/GHOST_EventCursor.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_EventCursor.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_EventCursor class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_EVENT_CURSOR_H_
|
||||
#define _GHOST_EVENT_CURSOR_H_
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
|
||||
/**
|
||||
* Cursor event.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 11, 2001
|
||||
*/
|
||||
class GHOST_EventCursor : public GHOST_Event
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param msec The time this event was generated.
|
||||
* @param type The type of this event.
|
||||
* @param x The x-coordinate of the location the cursor was at at the time of the event.
|
||||
* @param y The y-coordinate of the location the cursor was at at the time of the event.
|
||||
*/
|
||||
GHOST_EventCursor(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TInt32 x, GHOST_TInt32 y)
|
||||
: GHOST_Event(msec, type, window)
|
||||
{
|
||||
m_cursorEventData.x = x;
|
||||
m_cursorEventData.y = y;
|
||||
m_data = &m_cursorEventData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** The x,y-coordinates of the cursor position. */
|
||||
GHOST_TEventCursorData m_cursorEventData;
|
||||
};
|
||||
|
||||
|
||||
#endif // _GHOST_EVENT_CURSOR_H_
|
||||
|
||||
131
intern/ghost/intern/GHOST_EventDragnDrop.h
Normal file
131
intern/ghost/intern/GHOST_EventDragnDrop.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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): Damien Plisson 11/2009
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_EventDragnDrop.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GHOST_EVENT_DRAGNDROP_H_
|
||||
#define _GHOST_EVENT_DRAGNDROP_H_
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
extern "C" {
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
};
|
||||
|
||||
/**
|
||||
* Drag & drop event
|
||||
*
|
||||
* The dragging sequence is performed in four phases:
|
||||
*
|
||||
* <li> Start sequence (GHOST_kEventDraggingEntered) that tells a drag'n'drop operation has started. Already gives the object data type,
|
||||
* and the entering mouse location
|
||||
*
|
||||
* <li> Update mouse position (GHOST_kEventDraggingUpdated) sent upon each mouse move until the drag'n'drop operation stops, to give the updated mouse position.
|
||||
* Useful to highlight a potential destination, and update the status (through GHOST_setAcceptDragOperation) telling if the object can be dropped at
|
||||
* the current cursor position.
|
||||
*
|
||||
* <li> Abort drag'n'drop sequence (GHOST_kEventDraggingExited) sent when the user moved the mouse outside the window.
|
||||
*
|
||||
* <li> Send the dropped data (GHOST_kEventDraggingDropDone)
|
||||
*
|
||||
* <li> Outside of the normal sequence, dropped data can be sent (GHOST_kEventDraggingDropOnIcon). This can happen when the user drops an object
|
||||
* on the application icon. (Also used in OSX to pass the filename of the document the user doubled-clicked in the finder)
|
||||
*
|
||||
* <br><br>Note that the mouse positions are given in Blender coordinates (y=0 at bottom)
|
||||
*
|
||||
* <br>Currently supported object types :
|
||||
* <li>UTF-8 string
|
||||
* <li>array of strings representing filenames (GHOST_TStringArray)
|
||||
* <li>bitmap ImBuf
|
||||
*/
|
||||
class GHOST_EventDragnDrop : public GHOST_Event
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param time The time this event was generated.
|
||||
* @param type The type of this event.
|
||||
* @param dataType The type of the drop candidate object
|
||||
* @param window The window where the event occurred
|
||||
* @param x The x-coordinate of the location the cursor was at at the time of the event.
|
||||
* @param y The y-coordinate of the location the cursor was at at the time of the event.
|
||||
* @param data The "content" dropped in the window
|
||||
*/
|
||||
GHOST_EventDragnDrop(GHOST_TUns64 time, GHOST_TEventType type, GHOST_TDragnDropTypes dataType, GHOST_IWindow* window,
|
||||
int x, int y, GHOST_TEventDataPtr data)
|
||||
: GHOST_Event(time, type, window)
|
||||
{
|
||||
m_dragnDropEventData.x = x;
|
||||
m_dragnDropEventData.y = y;
|
||||
m_dragnDropEventData.dataType = dataType;
|
||||
m_dragnDropEventData.data = data;
|
||||
m_data = &m_dragnDropEventData;
|
||||
}
|
||||
|
||||
~GHOST_EventDragnDrop()
|
||||
{
|
||||
//Free the dropped object data
|
||||
if (m_dragnDropEventData.data == NULL)
|
||||
return;
|
||||
|
||||
switch (m_dragnDropEventData.dataType) {
|
||||
case GHOST_kDragnDropTypeBitmap:
|
||||
IMB_freeImBuf((ImBuf*)m_dragnDropEventData.data);
|
||||
break;
|
||||
case GHOST_kDragnDropTypeFilenames:
|
||||
{
|
||||
GHOST_TStringArray *strArray = (GHOST_TStringArray*)m_dragnDropEventData.data;
|
||||
int i;
|
||||
|
||||
for (i=0;i<strArray->count;i++)
|
||||
free(strArray->strings[i]);
|
||||
|
||||
free(strArray);
|
||||
}
|
||||
break;
|
||||
case GHOST_kDragnDropTypeString:
|
||||
free(m_dragnDropEventData.data);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
/** The x,y-coordinates of the cursor position. */
|
||||
GHOST_TEventDragnDropData m_dragnDropEventData;
|
||||
};
|
||||
|
||||
#endif // _GHOST_EVENT_DRAGNDROP_H_
|
||||
|
||||
82
intern/ghost/intern/GHOST_EventKey.h
Normal file
82
intern/ghost/intern/GHOST_EventKey.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_EventKey.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_EventKey class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_EVENT_KEY_H_
|
||||
#define _GHOST_EVENT_KEY_H_
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
|
||||
/**
|
||||
* Key event.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 11, 2001
|
||||
*/
|
||||
class GHOST_EventKey : public GHOST_Event
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param msec The time this event was generated.
|
||||
* @param type The type of key event.
|
||||
* @param key The key code of the key.
|
||||
*/
|
||||
GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TKey key)
|
||||
: GHOST_Event(msec, type, window)
|
||||
{
|
||||
m_keyEventData.key = key;
|
||||
m_keyEventData.ascii = '\0';
|
||||
m_data = &m_keyEventData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param msec The time this event was generated.
|
||||
* @param type The type of key event.
|
||||
* @param key The key code of the key.
|
||||
* @param ascii The ascii code for the key event.
|
||||
*/
|
||||
GHOST_EventKey(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TKey key, char ascii)
|
||||
: GHOST_Event(msec, type, window)
|
||||
{
|
||||
m_keyEventData.key = key;
|
||||
m_keyEventData.ascii = ascii;
|
||||
m_data = &m_keyEventData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** The key event data. */
|
||||
GHOST_TEventKeyData m_keyEventData;
|
||||
};
|
||||
|
||||
#endif // _GHOST_EVENT_KEY_H_
|
||||
|
||||
268
intern/ghost/intern/GHOST_EventManager.cpp
Normal file
268
intern/ghost/intern/GHOST_EventManager.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_EventManager.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 14, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_EventManager.h"
|
||||
#include <algorithm>
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
|
||||
GHOST_EventManager::GHOST_EventManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_EventManager::~GHOST_EventManager()
|
||||
{
|
||||
disposeEvents();
|
||||
|
||||
TConsumerVector::iterator iter= m_consumers.begin();
|
||||
while (iter != m_consumers.end())
|
||||
{
|
||||
GHOST_IEventConsumer* consumer = *iter;
|
||||
delete consumer;
|
||||
m_consumers.erase(iter);
|
||||
iter = m_consumers.begin();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns32 GHOST_EventManager::getNumEvents()
|
||||
{
|
||||
return (GHOST_TUns32) m_events.size();
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type)
|
||||
{
|
||||
GHOST_TUns32 numEvents = 0;
|
||||
TEventStack::iterator p;
|
||||
for (p = m_events.begin(); p != m_events.end(); p++) {
|
||||
if ((*p)->getType() == type) {
|
||||
numEvents++;
|
||||
}
|
||||
}
|
||||
return numEvents;
|
||||
}
|
||||
|
||||
|
||||
GHOST_IEvent* GHOST_EventManager::peekEvent()
|
||||
{
|
||||
GHOST_IEvent* event = 0;
|
||||
if (m_events.size() > 0) {
|
||||
event = m_events.back();
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
GHOST_ASSERT(event, "invalid event");
|
||||
if (m_events.size() < m_events.max_size()) {
|
||||
m_events.push_front(event);
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event)
|
||||
{
|
||||
bool handled;
|
||||
if (event) {
|
||||
handled = true;
|
||||
TConsumerVector::iterator iter;
|
||||
for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) {
|
||||
if ((*iter)->processEvent(event)) {
|
||||
handled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
handled = false;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_EventManager::dispatchEvent()
|
||||
{
|
||||
GHOST_IEvent* event = popEvent();
|
||||
bool handled = false;
|
||||
if (event) {
|
||||
handled = dispatchEvent(event);
|
||||
delete event;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_EventManager::dispatchEvents()
|
||||
{
|
||||
bool handled;
|
||||
if (getNumEvents()) {
|
||||
handled = true;
|
||||
while (getNumEvents()) {
|
||||
if (!dispatchEvent()) {
|
||||
handled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
handled = false;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_EventManager::addConsumer(GHOST_IEventConsumer* consumer)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
GHOST_ASSERT(consumer, "invalid consumer");
|
||||
|
||||
// Check to see whether the consumer is already in our list
|
||||
TConsumerVector::const_iterator iter = std::find(m_consumers.begin(), m_consumers.end(), consumer);
|
||||
|
||||
if (iter == m_consumers.end()) {
|
||||
// Add the consumer
|
||||
m_consumers.push_back(consumer);
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_EventManager::removeConsumer(GHOST_IEventConsumer* consumer)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
GHOST_ASSERT(consumer, "invalid consumer");
|
||||
|
||||
// Check to see whether the consumer is in our list
|
||||
TConsumerVector::iterator iter = std::find(m_consumers.begin(), m_consumers.end(), consumer);
|
||||
|
||||
if (iter != m_consumers.end()) {
|
||||
// Remove the consumer
|
||||
m_consumers.erase(iter);
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_EventManager::removeWindowEvents(GHOST_IWindow* window)
|
||||
{
|
||||
TEventStack::iterator iter;
|
||||
iter = m_events.begin();
|
||||
while (iter != m_events.end())
|
||||
{
|
||||
GHOST_IEvent* event = *iter;
|
||||
if (event->getWindow() == window)
|
||||
{
|
||||
GHOST_PRINT("GHOST_EventManager::removeWindowEvents(): removing event\n");
|
||||
/*
|
||||
* Found an event for this window, remove it.
|
||||
* The iterator will become invalid.
|
||||
*/
|
||||
delete event;
|
||||
m_events.erase(iter);
|
||||
iter = m_events.begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_EventManager::removeTypeEvents(GHOST_TEventType type, GHOST_IWindow* window)
|
||||
{
|
||||
TEventStack::iterator iter;
|
||||
iter = m_events.begin();
|
||||
while (iter != m_events.end())
|
||||
{
|
||||
GHOST_IEvent* event = *iter;
|
||||
if ((event->getType() == type) && (!window || (event->getWindow() == window)))
|
||||
{
|
||||
GHOST_PRINT("GHOST_EventManager::removeTypeEvents(): removing event\n");
|
||||
/*
|
||||
* Found an event of this type for the window, remove it.
|
||||
* The iterator will become invalid.
|
||||
*/
|
||||
delete event;
|
||||
m_events.erase(iter);
|
||||
iter = m_events.begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_IEvent* GHOST_EventManager::popEvent()
|
||||
{
|
||||
GHOST_IEvent* event = peekEvent();
|
||||
if (event) {
|
||||
m_events.pop_back();
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_EventManager::disposeEvents()
|
||||
{
|
||||
while (m_events.size() > 0) {
|
||||
GHOST_ASSERT(m_events[0], "invalid event");
|
||||
delete m_events[0];
|
||||
m_events.pop_front();
|
||||
}
|
||||
}
|
||||
175
intern/ghost/intern/GHOST_EventManager.h
Normal file
175
intern/ghost/intern/GHOST_EventManager.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_EventManager.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_EventManager class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_EVENT_MANAGER_H_
|
||||
#define _GHOST_EVENT_MANAGER_H_
|
||||
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
#include "GHOST_IEventConsumer.h"
|
||||
|
||||
|
||||
/**
|
||||
* Manages an event stack and a list of event consumers.
|
||||
* The stack works on a FIFO (First In First Out) basis.
|
||||
* Events are pushed on the front of the stack and retrieved from the back.
|
||||
* Ownership of the event is transferred to the event manager as soon as an event is pushed.
|
||||
* Ownership of the event is transferred from the event manager as soon as an event is popped.
|
||||
* Events can be dispatched to the event consumers.
|
||||
*/
|
||||
class GHOST_EventManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_EventManager();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_EventManager();
|
||||
|
||||
/**
|
||||
* Returns the number of events currently on the stack.
|
||||
* @return The number of events on the stack.
|
||||
*/
|
||||
virtual GHOST_TUns32 getNumEvents();
|
||||
|
||||
/**
|
||||
* Returns the number of events of a certain type currently on the stack.
|
||||
* @param type The type of events to be counted.
|
||||
* @return The number of events on the stack of this type.
|
||||
*/
|
||||
virtual GHOST_TUns32 getNumEvents(GHOST_TEventType type);
|
||||
|
||||
/**
|
||||
* Return the event at the top of the stack without removal.
|
||||
* Do not delete the event!
|
||||
* @return The event at the top of the stack.
|
||||
*/
|
||||
virtual GHOST_IEvent* peekEvent();
|
||||
|
||||
/**
|
||||
* Pushes an event on the stack.
|
||||
* To dispatch it, call dispatchEvent() or dispatchEvents().
|
||||
* Do not delete the event!
|
||||
* @param event The event to push on the stack.
|
||||
*/
|
||||
virtual GHOST_TSuccess pushEvent(GHOST_IEvent* event);
|
||||
|
||||
/**
|
||||
* Dispatches the given event directly, bypassing the event stack.
|
||||
* @return Indication as to whether any of the consumers handled the event.
|
||||
*/
|
||||
virtual bool dispatchEvent(GHOST_IEvent* event);
|
||||
|
||||
/**
|
||||
* Dispatches the event at the back of the stack.
|
||||
* The event will be removed from the stack.
|
||||
* @return Indication as to whether any of the consumers handled the event.
|
||||
*/
|
||||
virtual bool dispatchEvent();
|
||||
|
||||
/**
|
||||
* Dispatches all the events on the stack.
|
||||
* The event stack will be empty afterwards.
|
||||
* @return Indication as to whether any of the consumers handled the events.
|
||||
*/
|
||||
virtual bool dispatchEvents();
|
||||
|
||||
/**
|
||||
* Adds a consumer to the list of event consumers.
|
||||
* @param consumer The consumer added to the list.
|
||||
* @return Indication as to whether addition has succeeded.
|
||||
*/
|
||||
virtual GHOST_TSuccess addConsumer(GHOST_IEventConsumer* consumer);
|
||||
|
||||
/**
|
||||
* Removes a consumer from the list of event consumers.
|
||||
* @param consumer The consumer removed from the list.
|
||||
* @return Indication as to whether removal has succeeded.
|
||||
*/
|
||||
virtual GHOST_TSuccess removeConsumer(GHOST_IEventConsumer* consumer);
|
||||
|
||||
/**
|
||||
* Removes all events for a window from the stack.
|
||||
* @param window The window to remove events for.
|
||||
*/
|
||||
virtual void
|
||||
removeWindowEvents(
|
||||
GHOST_IWindow* window
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes all events of a certain type from the stack.
|
||||
* The window parameter is optional. If non-null, the routine will remove
|
||||
* events only associated with that window.
|
||||
* @param type The type of events to be removed.
|
||||
* @param window The window to remove the events for.
|
||||
*/
|
||||
virtual void
|
||||
removeTypeEvents(
|
||||
GHOST_TEventType type,
|
||||
GHOST_IWindow* window = 0
|
||||
);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Returns the event at the top of the stack and removes it.
|
||||
* Delete the event after use!
|
||||
* @return The event at the top of the stack.
|
||||
*/
|
||||
virtual GHOST_IEvent* popEvent();
|
||||
|
||||
/**
|
||||
* Removes all events from the stack.
|
||||
*/
|
||||
virtual void disposeEvents();
|
||||
|
||||
/** A stack with events. */
|
||||
typedef std::deque<GHOST_IEvent*> TEventStack;
|
||||
|
||||
/** The event stack. */
|
||||
std::deque<GHOST_IEvent*> m_events;
|
||||
|
||||
/** A vector with event consumers. */
|
||||
typedef std::vector<GHOST_IEventConsumer*> TConsumerVector;
|
||||
|
||||
/** The list with event consumers. */
|
||||
TConsumerVector m_consumers;
|
||||
};
|
||||
|
||||
#endif // _GHOST_EVENT_MANAGER_H_
|
||||
|
||||
62
intern/ghost/intern/GHOST_EventNDOF.h
Normal file
62
intern/ghost/intern/GHOST_EventNDOF.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_EventNDOF.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _GHOST_EVENT_NDOF_H_
|
||||
#define _GHOST_EVENT_NDOF_H_
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
|
||||
/**
|
||||
* N-degree of freedom device event.
|
||||
*/
|
||||
class GHOST_EventNDOF : public GHOST_Event
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param msec The time this event was generated.
|
||||
* @param type The type of this event.
|
||||
* @param x The x-coordinate of the location the cursor was at at the time of the event.
|
||||
* @param y The y-coordinate of the location the cursor was at at the time of the event.
|
||||
*/
|
||||
GHOST_EventNDOF(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window,
|
||||
GHOST_TEventNDOFData data)
|
||||
: GHOST_Event(msec, type, window)
|
||||
{
|
||||
m_ndofEventData = data;
|
||||
m_data = &m_ndofEventData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** translation & rotation from the device. */
|
||||
GHOST_TEventNDOFData m_ndofEventData;
|
||||
};
|
||||
|
||||
|
||||
#endif // _GHOST_EVENT_NDOF_H_
|
||||
|
||||
347
intern/ghost/intern/GHOST_EventPrinter.cpp
Normal file
347
intern/ghost/intern/GHOST_EventPrinter.cpp
Normal file
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_EventPrinter.cpp
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_EventPrinter class.
|
||||
*/
|
||||
|
||||
#include "GHOST_EventPrinter.h"
|
||||
#include <iostream>
|
||||
#include "GHOST_EventKey.h"
|
||||
#include "GHOST_EventDragnDrop.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
|
||||
bool GHOST_EventPrinter::processEvent(GHOST_IEvent* event)
|
||||
{
|
||||
bool handled = true;
|
||||
|
||||
GHOST_ASSERT(event, "event==0");
|
||||
|
||||
if (event->getType() == GHOST_kEventWindowUpdate) return false;
|
||||
|
||||
std::cout << "\nGHOST_EventPrinter::processEvent, time: " << (GHOST_TInt32)event->getTime() << ", type: ";
|
||||
switch (event->getType()) {
|
||||
case GHOST_kEventUnknown:
|
||||
std::cout << "GHOST_kEventUnknown"; handled = false;
|
||||
break;
|
||||
|
||||
case GHOST_kEventButtonUp:
|
||||
{
|
||||
GHOST_TEventButtonData* buttonData = (GHOST_TEventButtonData*)((GHOST_IEvent*)event)->getData();
|
||||
std::cout << "GHOST_kEventCursorButtonUp, button: " << buttonData->button;
|
||||
}
|
||||
break;
|
||||
case GHOST_kEventButtonDown:
|
||||
{
|
||||
GHOST_TEventButtonData* buttonData = (GHOST_TEventButtonData*)((GHOST_IEvent*)event)->getData();
|
||||
std::cout << "GHOST_kEventButtonDown, button: " << buttonData->button;
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventWheel:
|
||||
{
|
||||
GHOST_TEventWheelData* wheelData = (GHOST_TEventWheelData*)((GHOST_IEvent*)event)->getData();
|
||||
std::cout << "GHOST_kEventWheel, z: " << wheelData->z;
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventCursorMove:
|
||||
{
|
||||
GHOST_TEventCursorData* cursorData = (GHOST_TEventCursorData*)((GHOST_IEvent*)event)->getData();
|
||||
std::cout << "GHOST_kEventCursorMove, (x,y): (" << cursorData->x << "," << cursorData->y << ")";
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventKeyUp:
|
||||
{
|
||||
GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*)((GHOST_IEvent*)event)->getData();
|
||||
STR_String str;
|
||||
getKeyString(keyData->key, str);
|
||||
std::cout << "GHOST_kEventKeyUp, key: " << str.Ptr();
|
||||
}
|
||||
break;
|
||||
case GHOST_kEventKeyDown:
|
||||
{
|
||||
GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*)((GHOST_IEvent*)event)->getData();
|
||||
STR_String str;
|
||||
getKeyString(keyData->key, str);
|
||||
std::cout << "GHOST_kEventKeyDown, key: " << str.Ptr();
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventDraggingEntered:
|
||||
{
|
||||
GHOST_TEventDragnDropData* dragnDropData = (GHOST_TEventDragnDropData*)((GHOST_IEvent*)event)->getData();
|
||||
std::cout << "GHOST_kEventDraggingEntered, dragged object type : " << dragnDropData->dataType;
|
||||
std::cout << " mouse at x=" << dragnDropData->x << " y=" << dragnDropData->y;
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventDraggingUpdated:
|
||||
{
|
||||
GHOST_TEventDragnDropData* dragnDropData = (GHOST_TEventDragnDropData*)((GHOST_IEvent*)event)->getData();
|
||||
std::cout << "GHOST_kEventDraggingUpdated, dragged object type : " << dragnDropData->dataType;
|
||||
std::cout << " mouse at x=" << dragnDropData->x << " y=" << dragnDropData->y;
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventDraggingExited:
|
||||
{
|
||||
GHOST_TEventDragnDropData* dragnDropData = (GHOST_TEventDragnDropData*)((GHOST_IEvent*)event)->getData();
|
||||
std::cout << "GHOST_kEventDraggingExited, dragged object type : " << dragnDropData->dataType;
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventDraggingDropDone:
|
||||
{
|
||||
GHOST_TEventDragnDropData* dragnDropData = (GHOST_TEventDragnDropData*)((GHOST_IEvent*)event)->getData();
|
||||
std::cout << "GHOST_kEventDraggingDropDone,";
|
||||
std::cout << " mouse at x=" << dragnDropData->x << " y=" << dragnDropData->y;
|
||||
switch (dragnDropData->dataType) {
|
||||
case GHOST_kDragnDropTypeString:
|
||||
std::cout << " type : GHOST_kDragnDropTypeString,";
|
||||
std::cout << "\n String received = " << (char*)dragnDropData->data;
|
||||
break;
|
||||
case GHOST_kDragnDropTypeFilenames:
|
||||
{
|
||||
GHOST_TStringArray *strArray = (GHOST_TStringArray*)dragnDropData->data;
|
||||
int i;
|
||||
std::cout << " type : GHOST_kDragnDropTypeFilenames,";
|
||||
std::cout << "\n Received " << strArray->count << " filename" << (strArray->count > 1 ? "s:" : ":");
|
||||
for (i=0;i<strArray->count;i++)
|
||||
std::cout << "\n File[" << i << "] : " << strArray->strings[i];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventOpenMainFile:
|
||||
{
|
||||
GHOST_TEventDataPtr eventData = ((GHOST_IEvent*)event)->getData();
|
||||
|
||||
if (eventData)
|
||||
std::cout << "GHOST_kEventOpenMainFile for path : " << (char*)eventData;
|
||||
else
|
||||
std::cout << "GHOST_kEventOpenMainFile with no path specified!!";
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventQuit:
|
||||
std::cout << "GHOST_kEventQuit";
|
||||
break;
|
||||
case GHOST_kEventWindowClose:
|
||||
std::cout << "GHOST_kEventWindowClose";
|
||||
break;
|
||||
case GHOST_kEventWindowActivate:
|
||||
std::cout << "GHOST_kEventWindowActivate";
|
||||
break;
|
||||
case GHOST_kEventWindowDeactivate:
|
||||
std::cout << "GHOST_kEventWindowDeactivate";
|
||||
break;
|
||||
case GHOST_kEventWindowUpdate:
|
||||
std::cout << "GHOST_kEventWindowUpdate";
|
||||
break;
|
||||
case GHOST_kEventWindowSize:
|
||||
std::cout << "GHOST_kEventWindowSize";
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cout << "not found"; handled = false;
|
||||
break;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_EventPrinter::getKeyString(GHOST_TKey key, STR_String& str) const
|
||||
{
|
||||
if ((key >= GHOST_kKeyComma) && (key <= GHOST_kKeyRightBracket)) {
|
||||
str = ((char)key);
|
||||
} else if ((key >= GHOST_kKeyNumpad0) && (key <= GHOST_kKeyNumpad9)) {
|
||||
int number = key - GHOST_kKeyNumpad0;
|
||||
STR_String numberStr (number);
|
||||
str = "Numpad";
|
||||
str += numberStr;
|
||||
#if defined(__sun__) || defined(__sun)
|
||||
} else if (key == 268828432) { /* solaris keyboards are messed up */
|
||||
/* This should really test XK_F11 but that doesn't work */
|
||||
str = "F11";
|
||||
} else if (key == 268828433) { /* solaris keyboards are messed up */
|
||||
/* This should really test XK_F12 but that doesn't work */
|
||||
str = "F12";
|
||||
#endif
|
||||
} else if ((key >= GHOST_kKeyF1) && (key <= GHOST_kKeyF24)) {
|
||||
int number = key - GHOST_kKeyF1 + 1;
|
||||
STR_String numberStr (number);
|
||||
str = "F";
|
||||
str += numberStr;
|
||||
} else {
|
||||
switch (key)
|
||||
{
|
||||
case GHOST_kKeyBackSpace:
|
||||
str = "BackSpace";
|
||||
break;
|
||||
case GHOST_kKeyTab:
|
||||
str = "Tab";
|
||||
break;
|
||||
case GHOST_kKeyLinefeed:
|
||||
str = "Linefeed";
|
||||
break;
|
||||
case GHOST_kKeyClear:
|
||||
str = "Clear";
|
||||
break;
|
||||
case GHOST_kKeyEnter:
|
||||
str = "Enter";
|
||||
break;
|
||||
case GHOST_kKeyEsc:
|
||||
str = "Esc";
|
||||
break;
|
||||
case GHOST_kKeySpace:
|
||||
str = "Space";
|
||||
break;
|
||||
case GHOST_kKeyQuote:
|
||||
str = "Quote";
|
||||
break;
|
||||
case GHOST_kKeyBackslash:
|
||||
str = "\\";
|
||||
break;
|
||||
case GHOST_kKeyAccentGrave:
|
||||
str = "`";
|
||||
break;
|
||||
case GHOST_kKeyLeftShift:
|
||||
str = "LeftShift";
|
||||
break;
|
||||
case GHOST_kKeyRightShift:
|
||||
str = "RightShift";
|
||||
break;
|
||||
case GHOST_kKeyLeftControl:
|
||||
str = "LeftControl";
|
||||
break;
|
||||
case GHOST_kKeyRightControl:
|
||||
str = "RightControl";
|
||||
break;
|
||||
case GHOST_kKeyLeftAlt:
|
||||
str = "LeftAlt";
|
||||
break;
|
||||
case GHOST_kKeyRightAlt:
|
||||
str = "RightAlt";
|
||||
break;
|
||||
case GHOST_kKeyOS:
|
||||
str = "OS";
|
||||
break;
|
||||
case GHOST_kKeyGrLess:
|
||||
// PC german!
|
||||
str = "GrLess";
|
||||
break;
|
||||
case GHOST_kKeyCapsLock:
|
||||
str = "CapsLock";
|
||||
break;
|
||||
case GHOST_kKeyNumLock:
|
||||
str = "NumLock";
|
||||
break;
|
||||
case GHOST_kKeyScrollLock:
|
||||
str = "ScrollLock";
|
||||
break;
|
||||
case GHOST_kKeyLeftArrow:
|
||||
str = "LeftArrow";
|
||||
break;
|
||||
case GHOST_kKeyRightArrow:
|
||||
str = "RightArrow";
|
||||
break;
|
||||
case GHOST_kKeyUpArrow:
|
||||
str = "UpArrow";
|
||||
break;
|
||||
case GHOST_kKeyDownArrow:
|
||||
str = "DownArrow";
|
||||
break;
|
||||
case GHOST_kKeyPrintScreen:
|
||||
str = "PrintScreen";
|
||||
break;
|
||||
case GHOST_kKeyPause:
|
||||
str = "Pause";
|
||||
break;
|
||||
case GHOST_kKeyInsert:
|
||||
str = "Insert";
|
||||
break;
|
||||
case GHOST_kKeyDelete:
|
||||
str = "Delete";
|
||||
break;
|
||||
case GHOST_kKeyHome:
|
||||
str = "Home";
|
||||
break;
|
||||
case GHOST_kKeyEnd:
|
||||
str = "End";
|
||||
break;
|
||||
case GHOST_kKeyUpPage:
|
||||
str = "UpPage";
|
||||
break;
|
||||
case GHOST_kKeyDownPage:
|
||||
str = "DownPage";
|
||||
break;
|
||||
case GHOST_kKeyNumpadPeriod:
|
||||
str = "NumpadPeriod";
|
||||
break;
|
||||
case GHOST_kKeyNumpadEnter:
|
||||
str = "NumpadEnter";
|
||||
break;
|
||||
case GHOST_kKeyNumpadPlus:
|
||||
str = "NumpadPlus";
|
||||
break;
|
||||
case GHOST_kKeyNumpadMinus:
|
||||
str = "NumpadMinus";
|
||||
break;
|
||||
case GHOST_kKeyNumpadAsterisk:
|
||||
str = "NumpadAsterisk";
|
||||
break;
|
||||
case GHOST_kKeyNumpadSlash:
|
||||
str = "NumpadSlash";
|
||||
break;
|
||||
case GHOST_kKeyMediaPlay:
|
||||
str = "MediaPlayPause";
|
||||
break;
|
||||
case GHOST_kKeyMediaStop:
|
||||
str = "MediaStop";
|
||||
break;
|
||||
case GHOST_kKeyMediaFirst:
|
||||
str = "MediaFirst";
|
||||
break;
|
||||
case GHOST_kKeyMediaLast:
|
||||
str = "MediaLast";
|
||||
break;
|
||||
default:
|
||||
str = "unknown";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
65
intern/ghost/intern/GHOST_EventPrinter.h
Normal file
65
intern/ghost/intern/GHOST_EventPrinter.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_EventPrinter.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_EventPrinter class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_EVENT_PRINTER_H_
|
||||
#define _GHOST_EVENT_PRINTER_H_
|
||||
|
||||
#include "GHOST_IEventConsumer.h"
|
||||
|
||||
#include "STR_String.h"
|
||||
|
||||
/**
|
||||
* An Event consumer that prints all the events to standard out.
|
||||
* Really useful when debugging.
|
||||
*/
|
||||
class GHOST_EventPrinter : public GHOST_IEventConsumer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Prints all the events received to std out.
|
||||
* @param event The event that can be handled or not.
|
||||
* @return Indication as to whether the event was handled.
|
||||
*/
|
||||
virtual bool processEvent(GHOST_IEvent* event);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Converts GHOST key code to a readable string.
|
||||
* @param key The GHOST key code to convert.
|
||||
* @param str The GHOST key code converted to a readable string.
|
||||
*/
|
||||
void getKeyString(GHOST_TKey key, STR_String& str) const;
|
||||
};
|
||||
|
||||
#endif // _GHOST_EVENT_PRINTER_H_
|
||||
|
||||
67
intern/ghost/intern/GHOST_EventString.h
Normal file
67
intern/ghost/intern/GHOST_EventString.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_EventString.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_EventString class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_EVENTSTRING_H_
|
||||
#define _GHOST_EVENTSTRING_H_
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
|
||||
|
||||
/**
|
||||
* Generic class for events with string data
|
||||
* @author Damien Plisson
|
||||
* @date Feb 1, 2010
|
||||
*/
|
||||
class GHOST_EventString : public GHOST_Event
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param msec The time this event was generated.
|
||||
* @param type The type of this event.
|
||||
* @param window The generating window (or NULL if system event).
|
||||
* @param data_ptr Pointer to the (unformatted) data associated with the event
|
||||
*/
|
||||
GHOST_EventString(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, GHOST_TEventDataPtr data_ptr)
|
||||
: GHOST_Event(msec, type, window) {
|
||||
m_data = data_ptr;
|
||||
}
|
||||
|
||||
~GHOST_EventString()
|
||||
{
|
||||
if (m_data) free(m_data);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _GHOST_EVENTSTRING_H_
|
||||
|
||||
72
intern/ghost/intern/GHOST_EventTrackpad.h
Normal file
72
intern/ghost/intern/GHOST_EventTrackpad.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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): James Deery 11/2009
|
||||
* Damien Plisson 12/2009
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_EventTrackpad.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_EventTrackpad class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_EVENT_TRACKPAD_H_
|
||||
#define _GHOST_EVENT_TRACKPAD_H_
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
|
||||
/**
|
||||
* Trackpad (scroll, magnify, rotate, ...) event.
|
||||
*/
|
||||
class GHOST_EventTrackpad : public GHOST_Event
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param msec The time this event was generated.
|
||||
* @param type The type of this event.
|
||||
* @param subtype The subtype of the event.
|
||||
* @param x The x-delta of the pan event.
|
||||
* @param y The y-delta of the pan event.
|
||||
*/
|
||||
GHOST_EventTrackpad(GHOST_TUns64 msec, GHOST_IWindow* window, GHOST_TTrackpadEventSubTypes subtype, GHOST_TInt32 x, GHOST_TInt32 y, GHOST_TInt32 deltaX, GHOST_TInt32 deltaY)
|
||||
: GHOST_Event(msec, GHOST_kEventTrackpad, window)
|
||||
{
|
||||
m_trackpadEventData.subtype = subtype;
|
||||
m_trackpadEventData.x = x;
|
||||
m_trackpadEventData.y = y;
|
||||
m_trackpadEventData.deltaX = deltaX;
|
||||
m_trackpadEventData.deltaY = deltaY;
|
||||
m_data = &m_trackpadEventData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** The mouse pan data */
|
||||
GHOST_TEventTrackpadData m_trackpadEventData;
|
||||
};
|
||||
|
||||
|
||||
#endif // _GHOST_EVENT_PAN_H_
|
||||
|
||||
69
intern/ghost/intern/GHOST_EventWheel.h
Normal file
69
intern/ghost/intern/GHOST_EventWheel.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_EventWheel.h
|
||||
* \ingroup GHOSTeel.h
|
||||
* Declaration of GHOST_EventWheel class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_EVENT_WHEEL_H_
|
||||
#define _GHOST_EVENT_WHEEL_H_
|
||||
|
||||
#include "GHOST_Event.h"
|
||||
|
||||
/**
|
||||
* Mouse wheel event.
|
||||
* The displacement of the mouse wheel is counted in ticks.
|
||||
* A positive value means the wheel is turned away from the user.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 11, 2001
|
||||
*/
|
||||
class GHOST_EventWheel : public GHOST_Event
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param msec The time this event was generated.
|
||||
* @param type The type of this event.
|
||||
* @param z The displacement of the mouse wheel.
|
||||
*/
|
||||
GHOST_EventWheel(GHOST_TUns64 msec, GHOST_IWindow* window, GHOST_TInt32 z)
|
||||
: GHOST_Event(msec, GHOST_kEventWheel, window)
|
||||
{
|
||||
m_wheelEventData.z = z;
|
||||
m_data = &m_wheelEventData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** The z-displacement of the mouse wheel. */
|
||||
GHOST_TEventWheelData m_wheelEventData;
|
||||
};
|
||||
|
||||
|
||||
#endif // _GHOST_EVENT_WHEEL_H_
|
||||
|
||||
108
intern/ghost/intern/GHOST_ISystem.cpp
Normal file
108
intern/ghost/intern/GHOST_ISystem.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_ISystem.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 7, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_ISystem.h"
|
||||
|
||||
#ifdef WIN32
|
||||
# include "GHOST_SystemWin32.h"
|
||||
#else
|
||||
# ifdef __APPLE__
|
||||
# ifdef GHOST_COCOA
|
||||
# include "GHOST_SystemCocoa.h"
|
||||
# else
|
||||
# include "GHOST_SystemCarbon.h"
|
||||
# endif
|
||||
# else
|
||||
# include "GHOST_SystemX11.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
GHOST_ISystem* GHOST_ISystem::m_system = 0;
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_ISystem::createSystem()
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (!m_system) {
|
||||
#ifdef WIN32
|
||||
m_system = new GHOST_SystemWin32 ();
|
||||
#else
|
||||
# ifdef __APPLE__
|
||||
# ifdef GHOST_COCOA
|
||||
m_system = new GHOST_SystemCocoa ();
|
||||
# else
|
||||
m_system = new GHOST_SystemCarbon ();
|
||||
# endif
|
||||
# else
|
||||
m_system = new GHOST_SystemX11 ();
|
||||
# endif
|
||||
#endif
|
||||
success = m_system != 0 ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
if (success) {
|
||||
success = m_system->init();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ISystem::disposeSystem()
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kSuccess;
|
||||
if (m_system) {
|
||||
delete m_system;
|
||||
m_system = 0;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_ISystem* GHOST_ISystem::getSystem()
|
||||
{
|
||||
return m_system;
|
||||
}
|
||||
|
||||
109
intern/ghost/intern/GHOST_ISystemPaths.cpp
Normal file
109
intern/ghost/intern/GHOST_ISystemPaths.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_ISystemPaths.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 7, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_ISystemPaths.h"
|
||||
|
||||
#ifdef WIN32
|
||||
# include "GHOST_SystemPathsWin32.h"
|
||||
#else
|
||||
# ifdef __APPLE__
|
||||
# ifdef GHOST_COCOA
|
||||
# include "GHOST_SystemPathsCocoa.h"
|
||||
# else
|
||||
# include "GHOST_SystemPathsCarbon.h"
|
||||
# endif
|
||||
# else
|
||||
# include "GHOST_SystemPathsX11.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
GHOST_ISystemPaths* GHOST_ISystemPaths::m_systemPaths = 0;
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_ISystemPaths::create()
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (!m_systemPaths) {
|
||||
#ifdef WIN32
|
||||
m_systemPaths = new GHOST_SystemPathsWin32 ();
|
||||
#else
|
||||
# ifdef __APPLE__
|
||||
# ifdef GHOST_COCOA
|
||||
m_systemPaths = new GHOST_SystemPathsCocoa ();
|
||||
# else
|
||||
m_systemPaths = new GHOST_SystemPathsarbon ();
|
||||
# endif
|
||||
# else
|
||||
m_systemPaths = new GHOST_SystemPathsX11 ();
|
||||
# endif
|
||||
#endif
|
||||
success = m_systemPaths != 0 ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_ISystemPaths::dispose()
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kSuccess;
|
||||
if (m_systemPaths) {
|
||||
delete m_systemPaths;
|
||||
m_systemPaths = 0;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_ISystemPaths* GHOST_ISystemPaths::get()
|
||||
{
|
||||
if (!m_systemPaths) {
|
||||
create();
|
||||
}
|
||||
return m_systemPaths;
|
||||
}
|
||||
|
||||
|
||||
|
||||
140
intern/ghost/intern/GHOST_ModifierKeys.cpp
Normal file
140
intern/ghost/intern/GHOST_ModifierKeys.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_ModifierKeys.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 31, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_ModifierKeys.h"
|
||||
|
||||
|
||||
GHOST_ModifierKeys::GHOST_ModifierKeys()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
GHOST_ModifierKeys::~GHOST_ModifierKeys() {}
|
||||
|
||||
|
||||
GHOST_TKey GHOST_ModifierKeys::getModifierKeyCode(GHOST_TModifierKeyMask mask)
|
||||
{
|
||||
GHOST_TKey key;
|
||||
switch (mask) {
|
||||
case GHOST_kModifierKeyLeftShift: key = GHOST_kKeyLeftShift; break;
|
||||
case GHOST_kModifierKeyRightShift: key = GHOST_kKeyRightShift; break;
|
||||
case GHOST_kModifierKeyLeftAlt: key = GHOST_kKeyLeftAlt; break;
|
||||
case GHOST_kModifierKeyRightAlt: key = GHOST_kKeyRightAlt; break;
|
||||
case GHOST_kModifierKeyLeftControl: key = GHOST_kKeyLeftControl; break;
|
||||
case GHOST_kModifierKeyRightControl: key = GHOST_kKeyRightControl; break;
|
||||
case GHOST_kModifierKeyOS: key = GHOST_kKeyOS; break;
|
||||
default:
|
||||
// Should not happen
|
||||
key = GHOST_kKeyUnknown;
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_ModifierKeys::get(GHOST_TModifierKeyMask mask) const
|
||||
{
|
||||
switch (mask) {
|
||||
case GHOST_kModifierKeyLeftShift:
|
||||
return m_LeftShift;
|
||||
case GHOST_kModifierKeyRightShift:
|
||||
return m_RightShift;
|
||||
case GHOST_kModifierKeyLeftAlt:
|
||||
return m_LeftAlt;
|
||||
case GHOST_kModifierKeyRightAlt:
|
||||
return m_RightAlt;
|
||||
case GHOST_kModifierKeyLeftControl:
|
||||
return m_LeftControl;
|
||||
case GHOST_kModifierKeyRightControl:
|
||||
return m_RightControl;
|
||||
case GHOST_kModifierKeyOS:
|
||||
return m_OS;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GHOST_ModifierKeys::set(GHOST_TModifierKeyMask mask, bool down)
|
||||
{
|
||||
switch (mask) {
|
||||
case GHOST_kModifierKeyLeftShift:
|
||||
m_LeftShift = down; break;
|
||||
case GHOST_kModifierKeyRightShift:
|
||||
m_RightShift = down; break;
|
||||
case GHOST_kModifierKeyLeftAlt:
|
||||
m_LeftAlt = down; break;
|
||||
case GHOST_kModifierKeyRightAlt:
|
||||
m_RightAlt = down; break;
|
||||
case GHOST_kModifierKeyLeftControl:
|
||||
m_LeftControl = down; break;
|
||||
case GHOST_kModifierKeyRightControl:
|
||||
m_RightControl = down; break;
|
||||
case GHOST_kModifierKeyOS:
|
||||
m_OS = down; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GHOST_ModifierKeys::clear()
|
||||
{
|
||||
m_LeftShift = false;
|
||||
m_RightShift = false;
|
||||
m_LeftAlt = false;
|
||||
m_RightAlt = false;
|
||||
m_LeftControl = false;
|
||||
m_RightControl = false;
|
||||
m_OS = false;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_ModifierKeys::equals(const GHOST_ModifierKeys& keys) const
|
||||
{
|
||||
return (m_LeftShift == keys.m_LeftShift) &&
|
||||
(m_RightShift == keys.m_RightShift) &&
|
||||
(m_LeftAlt == keys.m_LeftAlt) &&
|
||||
(m_RightAlt == keys.m_RightAlt) &&
|
||||
(m_LeftControl == keys.m_LeftControl) &&
|
||||
(m_RightControl == keys.m_RightControl) &&
|
||||
(m_OS == keys.m_OS);
|
||||
}
|
||||
105
intern/ghost/intern/GHOST_ModifierKeys.h
Normal file
105
intern/ghost/intern/GHOST_ModifierKeys.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_ModifierKeys.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_ModifierKeys struct.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_MODIFIER_KEYS_H_
|
||||
#define _GHOST_MODIFIER_KEYS_H_
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
/**
|
||||
* Stores the state of modifier keys.
|
||||
* Discriminates between left and right modifier keys.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 17, 2001
|
||||
*/
|
||||
struct GHOST_ModifierKeys
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_ModifierKeys();
|
||||
|
||||
virtual ~GHOST_ModifierKeys();
|
||||
|
||||
/**
|
||||
* Returns the modifier key's key code from a modifier key mask.
|
||||
* @param mask The mask of the modifier key.
|
||||
* @return The modifier key's key code.
|
||||
*/
|
||||
static GHOST_TKey getModifierKeyCode(GHOST_TModifierKeyMask mask);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the state of a single modifier key.
|
||||
* @param mask. Key state to return.
|
||||
* @return The state of the key (pressed == true).
|
||||
*/
|
||||
virtual bool get(GHOST_TModifierKeyMask mask) const;
|
||||
|
||||
/**
|
||||
* Updates the state of a single modifier key.
|
||||
* @param mask. Key state to update.
|
||||
* @param down. The new state of the key.
|
||||
*/
|
||||
virtual void set(GHOST_TModifierKeyMask mask, bool down);
|
||||
|
||||
/**
|
||||
* Sets the state of all modifier keys to up.
|
||||
*/
|
||||
virtual void clear();
|
||||
|
||||
/**
|
||||
* Determines whether to modifier key states are equal.
|
||||
* @param keys. The modifier key state to compare to.
|
||||
* @return Indication of equality.
|
||||
*/
|
||||
virtual bool equals(const GHOST_ModifierKeys& keys) const;
|
||||
|
||||
/** Bitfield that stores the appropriate key state. */
|
||||
GHOST_TUns8 m_LeftShift : 1;
|
||||
/** Bitfield that stores the appropriate key state. */
|
||||
GHOST_TUns8 m_RightShift : 1;
|
||||
/** Bitfield that stores the appropriate key state. */
|
||||
GHOST_TUns8 m_LeftAlt : 1;
|
||||
/** Bitfield that stores the appropriate key state. */
|
||||
GHOST_TUns8 m_RightAlt : 1;
|
||||
/** Bitfield that stores the appropriate key state. */
|
||||
GHOST_TUns8 m_LeftControl : 1;
|
||||
/** Bitfield that stores the appropriate key state. */
|
||||
GHOST_TUns8 m_RightControl : 1;
|
||||
/** Bitfield that stores the appropriate key state. */
|
||||
GHOST_TUns8 m_OS : 1;
|
||||
};
|
||||
|
||||
#endif // _GHOST_MODIFIER_KEYS_H_
|
||||
|
||||
132
intern/ghost/intern/GHOST_NDOFManager.cpp
Normal file
132
intern/ghost/intern/GHOST_NDOFManager.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_NDOFManager.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h> /* just for printf */
|
||||
|
||||
#include "GHOST_NDOFManager.h"
|
||||
|
||||
|
||||
// the variable is outside the class because it must be accessed from plugin
|
||||
static volatile GHOST_TEventNDOFData currentNdofValues = {0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
#include "GHOST_SystemX11.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
GHOST_NDOFLibraryInit_fp ndofLibraryInit = 0;
|
||||
GHOST_NDOFLibraryShutdown_fp ndofLibraryShutdown = 0;
|
||||
GHOST_NDOFDeviceOpen_fp ndofDeviceOpen = 0;
|
||||
}
|
||||
|
||||
GHOST_NDOFManager::GHOST_NDOFManager()
|
||||
{
|
||||
m_DeviceHandle = 0;
|
||||
|
||||
// discover the API from the plugin
|
||||
ndofLibraryInit = 0;
|
||||
ndofLibraryShutdown = 0;
|
||||
ndofDeviceOpen = 0;
|
||||
}
|
||||
|
||||
GHOST_NDOFManager::~GHOST_NDOFManager()
|
||||
{
|
||||
if (ndofLibraryShutdown)
|
||||
ndofLibraryShutdown(m_DeviceHandle);
|
||||
|
||||
m_DeviceHandle = 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window,
|
||||
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
|
||||
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
|
||||
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen)
|
||||
{
|
||||
int Pid;
|
||||
|
||||
ndofLibraryInit = setNdofLibraryInit;
|
||||
ndofLibraryShutdown = setNdofLibraryShutdown;
|
||||
ndofDeviceOpen = setNdofDeviceOpen;
|
||||
|
||||
if (ndofLibraryInit && ndofDeviceOpen)
|
||||
{
|
||||
Pid= ndofLibraryInit();
|
||||
#if 0
|
||||
printf("%i client \n", Pid);
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
m_DeviceHandle = ndofDeviceOpen((void *)¤tNdofValues);
|
||||
#else
|
||||
GHOST_SystemX11 *sys;
|
||||
sys = static_cast<GHOST_SystemX11*>(GHOST_ISystem::getSystem());
|
||||
void *ndofInfo = sys->prepareNdofInfo(¤tNdofValues);
|
||||
m_DeviceHandle = ndofDeviceOpen(ndofInfo);
|
||||
#endif
|
||||
return (Pid > 0) ? 0 : 1;
|
||||
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GHOST_NDOFManager::available() const
|
||||
{
|
||||
return m_DeviceHandle != 0;
|
||||
}
|
||||
|
||||
bool
|
||||
GHOST_NDOFManager::event_present() const
|
||||
{
|
||||
if( currentNdofValues.changed >0) {
|
||||
printf("time %llu but%u x%i y%i z%i rx%i ry%i rz%i \n" ,
|
||||
currentNdofValues.time, currentNdofValues.buttons,
|
||||
currentNdofValues.tx,currentNdofValues.ty,currentNdofValues.tz,
|
||||
currentNdofValues.rx,currentNdofValues.ry,currentNdofValues.rz);
|
||||
return true;
|
||||
}else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void GHOST_NDOFManager::GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const
|
||||
{
|
||||
datas.tx = currentNdofValues.tx;
|
||||
datas.ty = currentNdofValues.ty;
|
||||
datas.tz = currentNdofValues.tz;
|
||||
datas.rx = currentNdofValues.rx;
|
||||
datas.ry = currentNdofValues.ry;
|
||||
datas.rz = currentNdofValues.rz;
|
||||
datas.buttons = currentNdofValues.buttons;
|
||||
datas.client = currentNdofValues.client;
|
||||
datas.address = currentNdofValues.address;
|
||||
datas.time = currentNdofValues.time;
|
||||
datas.delta = currentNdofValues.delta;
|
||||
}
|
||||
57
intern/ghost/intern/GHOST_NDOFManager.h
Normal file
57
intern/ghost/intern/GHOST_NDOFManager.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_NDOFManager.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GHOST_NDOFMANAGER_H_
|
||||
#define _GHOST_NDOFMANAGER_H_
|
||||
|
||||
#include "GHOST_System.h"
|
||||
#include "GHOST_IWindow.h"
|
||||
|
||||
|
||||
|
||||
class GHOST_NDOFManager
|
||||
{
|
||||
public:
|
||||
GHOST_NDOFManager();
|
||||
virtual ~GHOST_NDOFManager();
|
||||
|
||||
int deviceOpen(GHOST_IWindow* window,
|
||||
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
|
||||
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
|
||||
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen);
|
||||
|
||||
void GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const;
|
||||
|
||||
bool available() const;
|
||||
bool event_present() const;
|
||||
|
||||
protected:
|
||||
void* m_DeviceHandle;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
74
intern/ghost/intern/GHOST_Path-api.cpp
Normal file
74
intern/ghost/intern/GHOST_Path-api.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2010 by Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_Path-api.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include "intern/GHOST_Debug.h"
|
||||
#include "GHOST_Types.h"
|
||||
#include "GHOST_Path-api.h"
|
||||
#include "GHOST_ISystemPaths.h"
|
||||
|
||||
GHOST_TSuccess GHOST_CreateSystemPaths(void)
|
||||
{
|
||||
return GHOST_ISystemPaths::create();;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_DisposeSystemPaths(void)
|
||||
{
|
||||
return GHOST_ISystemPaths::dispose();
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_getSystemDir()
|
||||
{
|
||||
GHOST_ISystemPaths* systemPaths = GHOST_ISystemPaths::get();
|
||||
return systemPaths ? systemPaths->getSystemDir() : 0;
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_getUserDir()
|
||||
{
|
||||
GHOST_ISystemPaths* systemPaths = GHOST_ISystemPaths::get();
|
||||
return systemPaths ? systemPaths->getUserDir() : 0; /* shouldn't be NULL */
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_getBinaryDir()
|
||||
{
|
||||
GHOST_ISystemPaths* systemPaths = GHOST_ISystemPaths::get();
|
||||
return systemPaths ? systemPaths->getBinaryDir() : 0; /* shouldn't be NULL */
|
||||
}
|
||||
|
||||
void GHOST_addToSystemRecentFiles(const char* filename)
|
||||
{
|
||||
GHOST_ISystemPaths* systemPaths = GHOST_ISystemPaths::get();
|
||||
if (systemPaths) {
|
||||
systemPaths->addToSystemRecentFiles(filename);
|
||||
}
|
||||
}
|
||||
142
intern/ghost/intern/GHOST_Rect.cpp
Normal file
142
intern/ghost/intern/GHOST_Rect.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_Rect.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include "GHOST_Rect.h"
|
||||
|
||||
|
||||
|
||||
void GHOST_Rect::inset(GHOST_TInt32 i)
|
||||
{
|
||||
if (i > 0) {
|
||||
// Grow the rectangle
|
||||
m_l -= i;
|
||||
m_r += i;
|
||||
m_t -= i;
|
||||
m_b += i;
|
||||
}
|
||||
else if (i < 0) {
|
||||
// Shrink the rectangle, check for insets larger than half the size
|
||||
GHOST_TInt32 i2 = i * 2;
|
||||
if (getWidth() > i2) {
|
||||
m_l += i;
|
||||
m_r -= i;
|
||||
}
|
||||
else {
|
||||
m_l = m_l + ((m_r - m_l) / 2);
|
||||
m_r = m_l;
|
||||
}
|
||||
if (getHeight() > i2) {
|
||||
m_t += i;
|
||||
m_b -= i;
|
||||
}
|
||||
else {
|
||||
m_t = m_t + ((m_b - m_t) / 2);
|
||||
m_b = m_t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_TVisibility GHOST_Rect::getVisibility(GHOST_Rect& r) const
|
||||
{
|
||||
bool lt = isInside(r.m_l, r.m_t);
|
||||
bool rt = isInside(r.m_r, r.m_t);
|
||||
bool lb = isInside(r.m_l, r.m_b);
|
||||
bool rb = isInside(r.m_r, r.m_b);
|
||||
GHOST_TVisibility v;
|
||||
if (lt && rt && lb && rb) {
|
||||
// All points inside, rectangle is inside this
|
||||
v = GHOST_kFullyVisible;
|
||||
}
|
||||
else if (!(lt || rt || lb || rb)) {
|
||||
// None of the points inside
|
||||
// Check to see whether the rectangle is larger than this one
|
||||
if ((r.m_l < m_l) && (r.m_t < m_t) && (r.m_r > m_r) && (r.m_b > m_b)) {
|
||||
v = GHOST_kPartiallyVisible;
|
||||
}
|
||||
else {
|
||||
v = GHOST_kNotVisible;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Some of the points inside, rectangle is partially inside
|
||||
v = GHOST_kPartiallyVisible;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy)
|
||||
{
|
||||
GHOST_TInt32 offset = cx - (m_l + (m_r - m_l)/2);
|
||||
m_l += offset;
|
||||
m_r += offset;
|
||||
offset = cy - (m_t + (m_b - m_t)/2);
|
||||
m_t += offset;
|
||||
m_b += offset;
|
||||
}
|
||||
|
||||
void GHOST_Rect::setCenter(GHOST_TInt32 cx, GHOST_TInt32 cy, GHOST_TInt32 w, GHOST_TInt32 h)
|
||||
{
|
||||
long w_2, h_2;
|
||||
|
||||
w_2 = w >> 1;
|
||||
h_2 = h >> 1;
|
||||
m_l = cx - w_2;
|
||||
m_t = cy - h_2;
|
||||
m_r = m_l + w;
|
||||
m_b = m_t + h;
|
||||
}
|
||||
|
||||
bool GHOST_Rect::clip(GHOST_Rect& r) const
|
||||
{
|
||||
bool clipped = false;
|
||||
if (r.m_l < m_l) {
|
||||
r.m_l = m_l;
|
||||
clipped = true;
|
||||
}
|
||||
if (r.m_t < m_t) {
|
||||
r.m_t = m_t;
|
||||
clipped = true;
|
||||
}
|
||||
if (r.m_r > m_r) {
|
||||
r.m_r = m_r;
|
||||
clipped = true;
|
||||
}
|
||||
if (r.m_b > m_b) {
|
||||
r.m_b = m_b;
|
||||
clipped = true;
|
||||
}
|
||||
return clipped;
|
||||
}
|
||||
|
||||
357
intern/ghost/intern/GHOST_System.cpp
Normal file
357
intern/ghost/intern/GHOST_System.cpp
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_System.cpp
|
||||
* \ingroup GHOST
|
||||
* \author Maarten Gribnau
|
||||
* \date May 7, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_System.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <stdio.h> /* just for printf */
|
||||
|
||||
#include "GHOST_DisplayManager.h"
|
||||
#include "GHOST_EventManager.h"
|
||||
#include "GHOST_NDOFManager.h"
|
||||
#include "GHOST_TimerTask.h"
|
||||
#include "GHOST_TimerManager.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
|
||||
|
||||
GHOST_System::GHOST_System()
|
||||
: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_System::~GHOST_System()
|
||||
{
|
||||
exit();
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns64 GHOST_System::getMilliSeconds() const
|
||||
{
|
||||
GHOST_TUns64 millis = ::clock();
|
||||
if (CLOCKS_PER_SEC != 1000) {
|
||||
millis *= 1000;
|
||||
millis /= CLOCKS_PER_SEC;
|
||||
}
|
||||
return millis;
|
||||
}
|
||||
|
||||
|
||||
GHOST_ITimerTask* GHOST_System::installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData)
|
||||
{
|
||||
GHOST_TUns64 millis = getMilliSeconds();
|
||||
GHOST_TimerTask* timer = new GHOST_TimerTask(millis+delay, interval, timerProc, userData);
|
||||
if (timer) {
|
||||
if (m_timerManager->addTimer(timer) == GHOST_kSuccess) {
|
||||
// Check to see whether we need to fire the timer right away
|
||||
m_timerManager->fireTimers(millis);
|
||||
}
|
||||
else {
|
||||
delete timer;
|
||||
timer = 0;
|
||||
}
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_System::removeTimer(GHOST_ITimerTask* timerTask)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
if (timerTask) {
|
||||
success = m_timerManager->removeTimer((GHOST_TimerTask*)timerTask);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_System::disposeWindow(GHOST_IWindow* window)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
|
||||
/*
|
||||
* Remove all pending events for the window.
|
||||
*/
|
||||
if (m_windowManager->getWindowFound(window)) {
|
||||
m_eventManager->removeWindowEvents(window);
|
||||
}
|
||||
if (window == m_windowManager->getFullScreenWindow()) {
|
||||
success = endFullScreen();
|
||||
}
|
||||
else {
|
||||
if (m_windowManager->getWindowFound(window)) {
|
||||
success = m_windowManager->removeWindow(window);
|
||||
if (success) {
|
||||
delete window;
|
||||
}
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_System::validWindow(GHOST_IWindow* window)
|
||||
{
|
||||
return m_windowManager->getWindowFound(window);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
|
||||
const bool stereoVisual)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
GHOST_ASSERT(m_windowManager, "GHOST_System::beginFullScreen(): invalid window manager")
|
||||
if (m_displayManager) {
|
||||
if (!m_windowManager->getFullScreen()) {
|
||||
m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
|
||||
|
||||
//GHOST_PRINT("GHOST_System::beginFullScreen(): activating new display settings\n");
|
||||
success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
|
||||
if (success == GHOST_kSuccess) {
|
||||
//GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
|
||||
success = createFullScreenWindow((GHOST_Window**)window, stereoVisual);
|
||||
if (success == GHOST_kSuccess) {
|
||||
m_windowManager->beginFullScreen(*window, stereoVisual);
|
||||
}
|
||||
else {
|
||||
m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success == GHOST_kFailure) {
|
||||
GHOST_PRINT("GHOST_System::beginFullScreen(): could not enter full-screen mode\n");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_System::endFullScreen(void)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
GHOST_ASSERT(m_windowManager, "GHOST_System::endFullScreen(): invalid window manager")
|
||||
if (m_windowManager->getFullScreen()) {
|
||||
//GHOST_IWindow* window = m_windowManager->getFullScreenWindow();
|
||||
//GHOST_PRINT("GHOST_System::endFullScreen(): leaving window manager full-screen mode\n");
|
||||
success = m_windowManager->endFullScreen();
|
||||
GHOST_ASSERT(m_displayManager, "GHOST_System::endFullScreen(): invalid display manager")
|
||||
//GHOST_PRINT("GHOST_System::endFullScreen(): leaving full-screen mode\n");
|
||||
success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, m_preFullScreenSetting);
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_System::getFullScreen(void)
|
||||
{
|
||||
bool fullScreen;
|
||||
if (m_windowManager) {
|
||||
fullScreen = m_windowManager->getFullScreen();
|
||||
}
|
||||
else {
|
||||
fullScreen = false;
|
||||
}
|
||||
return fullScreen;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_System::dispatchEvents()
|
||||
{
|
||||
bool handled;
|
||||
if (m_eventManager) {
|
||||
handled = m_eventManager->dispatchEvents();
|
||||
}
|
||||
else {
|
||||
handled = false;
|
||||
}
|
||||
|
||||
m_timerManager->fireTimers(getMilliSeconds());
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_System::addEventConsumer(GHOST_IEventConsumer* consumer)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (m_eventManager) {
|
||||
success = m_eventManager->addConsumer(consumer);
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_System::removeEventConsumer(GHOST_IEventConsumer* consumer)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (m_eventManager) {
|
||||
success = m_eventManager->removeConsumer(consumer);
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent* event)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (m_eventManager) {
|
||||
success = m_eventManager->pushEvent(event);
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
int GHOST_System::openNDOF(GHOST_IWindow* w,
|
||||
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
|
||||
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
|
||||
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen)
|
||||
{
|
||||
return m_ndofManager->deviceOpen(w,
|
||||
setNdofLibraryInit,
|
||||
setNdofLibraryShutdown,
|
||||
setNdofDeviceOpen);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const
|
||||
{
|
||||
GHOST_ModifierKeys keys;
|
||||
// Get the state of all modifier keys
|
||||
GHOST_TSuccess success = getModifierKeys(keys);
|
||||
if (success) {
|
||||
// Isolate the state of the key requested
|
||||
isDown = keys.get(mask);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown) const
|
||||
{
|
||||
GHOST_Buttons buttons;
|
||||
// Get the state of all mouse buttons
|
||||
GHOST_TSuccess success = getButtons(buttons);
|
||||
if (success) {
|
||||
// Isolate the state of the mouse button requested
|
||||
isDown = buttons.get(mask);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_System::init()
|
||||
{
|
||||
m_timerManager = new GHOST_TimerManager ();
|
||||
m_windowManager = new GHOST_WindowManager ();
|
||||
m_eventManager = new GHOST_EventManager ();
|
||||
m_ndofManager = new GHOST_NDOFManager();
|
||||
|
||||
#if 0
|
||||
if(m_ndofManager)
|
||||
printf("ndof manager \n");
|
||||
#endif
|
||||
|
||||
#ifdef GHOST_DEBUG
|
||||
if (m_eventManager) {
|
||||
m_eventPrinter = new GHOST_EventPrinter();
|
||||
m_eventManager->addConsumer(m_eventPrinter);
|
||||
}
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
if (m_timerManager && m_windowManager && m_eventManager) {
|
||||
return GHOST_kSuccess;
|
||||
} else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_System::exit()
|
||||
{
|
||||
if (getFullScreen()) {
|
||||
endFullScreen();
|
||||
}
|
||||
if (m_displayManager) {
|
||||
delete m_displayManager;
|
||||
m_displayManager = 0;
|
||||
}
|
||||
if (m_windowManager) {
|
||||
delete m_windowManager;
|
||||
m_windowManager = 0;
|
||||
}
|
||||
if (m_timerManager) {
|
||||
delete m_timerManager;
|
||||
m_timerManager = 0;
|
||||
}
|
||||
if (m_eventManager) {
|
||||
delete m_eventManager;
|
||||
m_eventManager = 0;
|
||||
}
|
||||
if (m_ndofManager) {
|
||||
delete m_ndofManager;
|
||||
m_ndofManager = 0;
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, const bool stereoVisual)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
GHOST_ASSERT(m_displayManager, "GHOST_System::createFullScreenWindow(): invalid display manager")
|
||||
GHOST_DisplaySetting settings;
|
||||
|
||||
success = m_displayManager->getCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, settings);
|
||||
if (success) {
|
||||
//GHOST_PRINT("GHOST_System::createFullScreenWindow(): creating full-screen window\n");
|
||||
*window = (GHOST_Window*)createWindow(
|
||||
STR_String (""),
|
||||
0, 0, settings.xPixels, settings.yPixels,
|
||||
GHOST_kWindowStateFullScreen,
|
||||
GHOST_kDrawingContextTypeOpenGL,
|
||||
stereoVisual);
|
||||
success = *window == 0 ? GHOST_kFailure : GHOST_kSuccess;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
373
intern/ghost/intern/GHOST_System.h
Normal file
373
intern/ghost/intern/GHOST_System.h
Normal file
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_System.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_System class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_SYSTEM_H_
|
||||
#define _GHOST_SYSTEM_H_
|
||||
|
||||
#include "GHOST_ISystem.h"
|
||||
|
||||
#include "GHOST_Debug.h"
|
||||
#include "GHOST_Buttons.h"
|
||||
#include "GHOST_ModifierKeys.h"
|
||||
#include "GHOST_EventManager.h"
|
||||
#ifdef GHOST_DEBUG
|
||||
#include "GHOST_EventPrinter.h"
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
class GHOST_DisplayManager;
|
||||
class GHOST_Event;
|
||||
class GHOST_TimerManager;
|
||||
class GHOST_Window;
|
||||
class GHOST_WindowManager;
|
||||
class GHOST_NDOFManager;
|
||||
|
||||
/**
|
||||
* Implementation of platform independent functionality of the GHOST_ISystem
|
||||
* interface.
|
||||
* GHOST_System is an abstract class because not all methods of GHOST_ISystem
|
||||
* are implemented.
|
||||
* @see GHOST_ISystem.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 7, 2001
|
||||
*/
|
||||
class GHOST_System : public GHOST_ISystem
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Constructor.
|
||||
* Protected default constructor to force use of static createSystem member.
|
||||
*/
|
||||
GHOST_System();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* Protected default constructor to force use of static dispose member.
|
||||
*/
|
||||
virtual ~GHOST_System();
|
||||
|
||||
public:
|
||||
/***************************************************************************************
|
||||
** 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;
|
||||
|
||||
/**
|
||||
* Installs a timer.
|
||||
* Note that, on most operating systems, messages need to be processed in order
|
||||
* for the timer callbacks to be invoked.
|
||||
* @param delay The time to wait for the first call to the timerProc (in milliseconds)
|
||||
* @param interval The interval between calls to the timerProc
|
||||
* @param timerProc The callback invoked when the interval expires,
|
||||
* @param userData Placeholder for user data.
|
||||
* @return A timer task (0 if timer task installation failed).
|
||||
*/
|
||||
virtual GHOST_ITimerTask* installTimer(GHOST_TUns64 delay, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = 0);
|
||||
|
||||
/**
|
||||
* Removes a timer.
|
||||
* @param timerTask Timer task to be removed.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess removeTimer(GHOST_ITimerTask* timerTask);
|
||||
|
||||
/***************************************************************************************
|
||||
** Display/window management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Inherited from GHOST_ISystem but left pure virtual
|
||||
*
|
||||
* virtual GHOST_TUns8 getNumDisplays() const = 0;
|
||||
* virtual void getMainDisplayDimensions(...) const = 0;
|
||||
* virtual GHOST_IWindow* createWindow(..)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Dispose a window.
|
||||
* @param window Pointer to the window to be disposed.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess disposeWindow(GHOST_IWindow* window);
|
||||
|
||||
/**
|
||||
* Returns whether a window is valid.
|
||||
* @param window Pointer to the window to be checked.
|
||||
* @return Indication of validity.
|
||||
*/
|
||||
virtual bool validWindow(GHOST_IWindow* window);
|
||||
|
||||
/**
|
||||
* Begins full screen mode.
|
||||
* @param setting The new setting of the display.
|
||||
* @param window Window displayed in full screen.
|
||||
* @param stereoVisual Stereo visual for quad buffered stereo.
|
||||
* This window is invalid after full screen has been ended.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
|
||||
const bool stereoVisual);
|
||||
|
||||
/**
|
||||
* Ends full screen mode.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess endFullScreen(void);
|
||||
|
||||
/**
|
||||
* Returns current full screen mode status.
|
||||
* @return The current status.
|
||||
*/
|
||||
virtual bool getFullScreen(void);
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Event management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Inherited from GHOST_ISystem but left pure virtual
|
||||
*
|
||||
* virtual bool processEvents(bool waitForEvent) = 0;
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches all the events on the stack.
|
||||
* The event stack will be empty afterwards.
|
||||
* @return Indication as to whether any of the consumers handled the events.
|
||||
*/
|
||||
virtual bool dispatchEvents();
|
||||
|
||||
/**
|
||||
* Adds the given event consumer to our list.
|
||||
* @param consumer The event consumer to add.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer* consumer);
|
||||
|
||||
/**
|
||||
* Remove the given event consumer to our list.
|
||||
* @param consumer The event consumer to remove.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer);
|
||||
|
||||
/***************************************************************************************
|
||||
** N-degree of freedom devcice management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/** Inherited from GHOST_ISystem
|
||||
* Opens the N-degree of freedom device manager
|
||||
* return 0 if device found, 1 otherwise
|
||||
*/
|
||||
virtual int openNDOF(GHOST_IWindow* w,
|
||||
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
|
||||
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
|
||||
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen);
|
||||
|
||||
// original patch only
|
||||
// GHOST_NDOFEventHandler_fp setNdofEventHandler);
|
||||
|
||||
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Cursor management functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/** Inherited from GHOST_ISystem but left pure virtual
|
||||
* GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const = 0;
|
||||
* GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
|
||||
*/
|
||||
|
||||
/***************************************************************************************
|
||||
** Access to mouse button and keyboard states.
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the state of a modifier key (ouside the message queue).
|
||||
* @param mask The modifier key state to retrieve.
|
||||
* @param isDown The state of a modifier key (true == pressed).
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const;
|
||||
|
||||
/**
|
||||
* Returns the state of a mouse button (ouside the message queue).
|
||||
* @param mask The button state to retrieve.
|
||||
* @param isDown Button state.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const;
|
||||
|
||||
/***************************************************************************************
|
||||
** Other (internal) functionality.
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Pushes an event on the stack.
|
||||
* To dispatch it, call dispatchEvent() or dispatchEvents().
|
||||
* Do not delete the event!
|
||||
* @param event The event to push on the stack.
|
||||
*/
|
||||
virtual GHOST_TSuccess pushEvent(GHOST_IEvent* event);
|
||||
|
||||
/**
|
||||
* Returns the timer manager.
|
||||
* @return The timer manager.
|
||||
*/
|
||||
inline virtual GHOST_TimerManager* getTimerManager() const;
|
||||
|
||||
/**
|
||||
* Returns a pointer to our event manager.
|
||||
* @return A pointer to our event manager.
|
||||
*/
|
||||
virtual inline GHOST_EventManager* getEventManager() const;
|
||||
|
||||
/**
|
||||
* Returns a pointer to our window manager.
|
||||
* @return A pointer to our window manager.
|
||||
*/
|
||||
virtual inline GHOST_WindowManager* getWindowManager() const;
|
||||
|
||||
/**
|
||||
* Returns a pointer to our n-degree of freedeom manager.
|
||||
* @return A pointer to our n-degree of freedeom manager.
|
||||
*/
|
||||
virtual inline GHOST_NDOFManager* getNDOFManager() const;
|
||||
|
||||
/**
|
||||
* 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 = 0;
|
||||
|
||||
/**
|
||||
* 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 = 0;
|
||||
|
||||
/**
|
||||
* Returns the selection buffer
|
||||
* @param selection Only used on X11
|
||||
* @return Returns the clipboard data
|
||||
*
|
||||
*/
|
||||
virtual GHOST_TUns8* getClipboard(bool selection) const = 0;
|
||||
|
||||
/**
|
||||
* Put data to the Clipboard
|
||||
* @param buffer The buffer to copy to the clipboard
|
||||
* @param selection The clipboard to copy too only used on X11
|
||||
*/
|
||||
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0;
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initialize the system.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess init();
|
||||
|
||||
/**
|
||||
* Shut the system down.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess exit();
|
||||
|
||||
/**
|
||||
* Creates a fullscreen window.
|
||||
* @param window The window created.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess createFullScreenWindow(GHOST_Window** window,
|
||||
const bool stereoVisual);
|
||||
|
||||
/** The display manager (platform dependant). */
|
||||
GHOST_DisplayManager* m_displayManager;
|
||||
|
||||
/** The timer manager. */
|
||||
GHOST_TimerManager* m_timerManager;
|
||||
|
||||
/** The window manager. */
|
||||
GHOST_WindowManager* m_windowManager;
|
||||
|
||||
/** The event manager. */
|
||||
GHOST_EventManager* m_eventManager;
|
||||
|
||||
/** The N-degree of freedom device manager */
|
||||
GHOST_NDOFManager* m_ndofManager;
|
||||
|
||||
/** Prints all the events. */
|
||||
#ifdef GHOST_DEBUG
|
||||
GHOST_EventPrinter* m_eventPrinter;
|
||||
#endif // GHOST_DEBUG
|
||||
|
||||
/** Settings of the display before the display went fullscreen. */
|
||||
GHOST_DisplaySetting m_preFullScreenSetting;
|
||||
};
|
||||
|
||||
inline GHOST_TimerManager* GHOST_System::getTimerManager() const
|
||||
{
|
||||
return m_timerManager;
|
||||
}
|
||||
|
||||
inline GHOST_EventManager* GHOST_System::getEventManager() const
|
||||
{
|
||||
return m_eventManager;
|
||||
}
|
||||
|
||||
inline GHOST_WindowManager* GHOST_System::getWindowManager() const
|
||||
{
|
||||
return m_windowManager;
|
||||
}
|
||||
|
||||
inline GHOST_NDOFManager* GHOST_System::getNDOFManager() const
|
||||
{
|
||||
return m_ndofManager;
|
||||
}
|
||||
|
||||
#endif // _GHOST_SYSTEM_H_
|
||||
|
||||
1221
intern/ghost/intern/GHOST_SystemCarbon.cpp
Normal file
1221
intern/ghost/intern/GHOST_SystemCarbon.cpp
Normal file
@@ -0,0 +1,1221 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_SystemCarbon.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 7, 2001
|
||||
*/
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include "GHOST_SystemCarbon.h"
|
||||
|
||||
#include "GHOST_DisplayManagerCarbon.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_WindowCarbon.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
|
||||
};
|
||||
|
||||
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 kEventMouseButtonPrimary:
|
||||
return GHOST_kButtonMaskLeft;
|
||||
case kEventMouseButtonSecondary:
|
||||
return GHOST_kButtonMaskRight;
|
||||
case kEventMouseButtonTertiary:
|
||||
default:
|
||||
return GHOST_kButtonMaskMiddle;
|
||||
}
|
||||
}
|
||||
|
||||
static GHOST_TKey convertKey(int rawCode)
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
static UInt32 dummy= 0;
|
||||
Handle transData = (Handle) GetScriptManagerVariable(smKCHRCache);
|
||||
unsigned char vk = KeyTranslate(transData, rawCode, &dummy);
|
||||
/* 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", vk, vk, rawCode);
|
||||
|
||||
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 ((vk >= 'a') && (vk <= 'z')) {
|
||||
return (GHOST_TKey) (vk - 'a' + GHOST_kKeyA);
|
||||
} else if ((vk >= '0') && (vk <= '9')) {
|
||||
return (GHOST_TKey) (vk - '0' + GHOST_kKey0);
|
||||
} else if (vk==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; // Never get, is used for ejecting the CD!
|
||||
}
|
||||
} else {
|
||||
switch (vk) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/***/
|
||||
|
||||
GHOST_SystemCarbon::GHOST_SystemCarbon() :
|
||||
m_modifierMask(0)
|
||||
{
|
||||
m_displayManager = new GHOST_DisplayManagerCarbon ();
|
||||
GHOST_ASSERT(m_displayManager, "GHOST_SystemCarbon::GHOST_SystemCarbon(): m_displayManager==0\n");
|
||||
m_displayManager->initialize();
|
||||
|
||||
UnsignedWide micros;
|
||||
::Microseconds(µs);
|
||||
m_start_time = UnsignedWideToUInt64(micros)/1000;
|
||||
m_ignoreWindowSizedMessages = false;
|
||||
}
|
||||
|
||||
GHOST_SystemCarbon::~GHOST_SystemCarbon()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns64 GHOST_SystemCarbon::getMilliSeconds() const
|
||||
{
|
||||
UnsignedWide micros;
|
||||
::Microseconds(µs);
|
||||
UInt64 millis;
|
||||
millis = UnsignedWideToUInt64(micros);
|
||||
return (millis / 1000) - m_start_time;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns8 GHOST_SystemCarbon::getNumDisplays() const
|
||||
{
|
||||
// We do not support multiple monitors at the moment
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_SystemCarbon::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
|
||||
{
|
||||
BitMap screenBits;
|
||||
Rect bnds = GetQDGlobalsScreenBits(&screenBits)->bounds;
|
||||
width = bnds.right - bnds.left;
|
||||
height = bnds.bottom - bnds.top;
|
||||
}
|
||||
|
||||
|
||||
GHOST_IWindow* GHOST_SystemCarbon::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_TUns16 numOfAASamples,
|
||||
const GHOST_TEmbedderWindowID parentWindow
|
||||
)
|
||||
{
|
||||
GHOST_IWindow* window = 0;
|
||||
|
||||
window = new GHOST_WindowCarbon (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_SystemCarbon::createWindow(): window invalid\n");
|
||||
delete window;
|
||||
window = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
GHOST_PRINT("GHOST_SystemCarbon::createWindow(): could not create window\n");
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCarbon::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
|
||||
// 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_SystemCarbon::endFullScreen(void)
|
||||
{
|
||||
CGReleaseAllDisplays();
|
||||
return GHOST_System::endFullScreen();
|
||||
}
|
||||
|
||||
/* this is an old style low level event queue.
|
||||
As we want to handle our own timers, this is ok.
|
||||
the full screen hack should be removed */
|
||||
bool GHOST_SystemCarbon::processEvents(bool waitForEvent)
|
||||
{
|
||||
bool anyProcessed = false;
|
||||
EventRef event;
|
||||
|
||||
// SetMouseCoalescingEnabled(false, NULL);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* end loop when no more events available */
|
||||
while (::ReceiveNextEvent(0, NULL, 0, true, &event)==noErr) {
|
||||
OSStatus status= ::SendEventToEventTarget(event, ::GetEventDispatcherTarget());
|
||||
if (status==noErr) {
|
||||
anyProcessed = true;
|
||||
} else {
|
||||
UInt32 i= ::GetEventClass(event);
|
||||
|
||||
/* Ignore 'cgs ' class, no documentation on what they
|
||||
* are, but we get a lot of them
|
||||
*/
|
||||
if (i!='cgs ') {
|
||||
if (i!='tblt') { // tablet event. we use the one packaged in the mouse event
|
||||
; //printf("Missed - Class: '%.4s', Kind: %d\n", &i, ::GetEventKind(event));
|
||||
}
|
||||
}
|
||||
}
|
||||
::ReleaseEvent(event);
|
||||
}
|
||||
} while (waitForEvent && !anyProcessed);
|
||||
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCarbon::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
|
||||
{
|
||||
Point mouseLoc;
|
||||
// Get the position of the mouse in the active port
|
||||
::GetGlobalMouse(&mouseLoc);
|
||||
// Convert the coordinates to screen coordinates
|
||||
x = (GHOST_TInt32)mouseLoc.h;
|
||||
y = (GHOST_TInt32)mouseLoc.v;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCarbon::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
|
||||
{
|
||||
float xf=(float)x, yf=(float)y;
|
||||
|
||||
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_SystemCarbon::getModifierKeys(GHOST_ModifierKeys& keys) const
|
||||
{
|
||||
UInt32 modifiers = ::GetCurrentKeyModifiers();
|
||||
|
||||
keys.set(GHOST_kModifierKeyOS, (modifiers & cmdKey) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & optionKey) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftShift, (modifiers & shiftKey) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftControl, (modifiers & controlKey) ? true : false);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
/* XXX, incorrect for multibutton mice */
|
||||
GHOST_TSuccess GHOST_SystemCarbon::getButtons(GHOST_Buttons& buttons) const
|
||||
{
|
||||
Boolean theOnlyButtonIsDown = ::Button();
|
||||
buttons.clear();
|
||||
buttons.set(GHOST_kButtonMaskLeft, theOnlyButtonIsDown);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCarbon::init()
|
||||
{
|
||||
|
||||
GHOST_TSuccess success = GHOST_System::init();
|
||||
if (success) {
|
||||
/*
|
||||
* 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_SystemCarbon::exit()
|
||||
{
|
||||
return GHOST_System::exit();
|
||||
}
|
||||
|
||||
|
||||
OSStatus GHOST_SystemCarbon::handleWindowEvent(EventRef event)
|
||||
{
|
||||
WindowRef windowRef;
|
||||
GHOST_WindowCarbon *window;
|
||||
OSStatus err = eventNotHandledErr;
|
||||
|
||||
// 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(::GetEventKind(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;
|
||||
}
|
||||
|
||||
OSStatus GHOST_SystemCarbon::handleTabletEvent(EventRef event)
|
||||
{
|
||||
GHOST_IWindow* window = m_windowManager->getActiveWindow();
|
||||
TabletPointRec tabletPointRecord;
|
||||
TabletProximityRec tabletProximityRecord;
|
||||
UInt32 anInt32;
|
||||
GHOST_TabletData& ct=((GHOST_WindowCarbon*)window)->GetCarbonTabletData();
|
||||
OSStatus err = eventNotHandledErr;
|
||||
|
||||
ct.Pressure = 0;
|
||||
ct.Xtilt = 0;
|
||||
ct.Ytilt = 0;
|
||||
|
||||
// is there an embedded tablet event inside this mouse event?
|
||||
if(noErr == GetEventParameter(event, kEventParamTabletEventType, typeUInt32, NULL, sizeof(UInt32), NULL, (void *)&anInt32))
|
||||
{
|
||||
// yes there is one!
|
||||
// Embedded tablet events can either be a proximity or pointer event.
|
||||
if(anInt32 == kEventTabletPoint)
|
||||
{
|
||||
//GHOST_PRINT("Embedded pointer event!\n");
|
||||
|
||||
// Extract the tablet Pointer Event. If there is no Tablet Pointer data
|
||||
// in this event, then this call will return an error. Just ignore the
|
||||
// error and go on. This can occur when a proximity event is embedded in
|
||||
// a mouse event and you did not check the mouse event to see which type
|
||||
// of tablet event was embedded.
|
||||
if(noErr == GetEventParameter(event, kEventParamTabletPointRec,
|
||||
typeTabletPointRec, NULL,
|
||||
sizeof(TabletPointRec),
|
||||
NULL, (void *)&tabletPointRecord))
|
||||
{
|
||||
ct.Pressure = tabletPointRecord.pressure / 65535.0f;
|
||||
ct.Xtilt = tabletPointRecord.tiltX / 32767.0f; /* can be positive or negative */
|
||||
ct.Ytilt = tabletPointRecord.tiltY / 32767.0f; /* can be positive or negative */
|
||||
}
|
||||
} else {
|
||||
//GHOST_PRINT("Embedded proximity event\n");
|
||||
|
||||
// Extract the Tablet Proximity record from the event.
|
||||
if(noErr == GetEventParameter(event, kEventParamTabletProximityRec,
|
||||
typeTabletProximityRec, NULL,
|
||||
sizeof(TabletProximityRec),
|
||||
NULL, (void *)&tabletProximityRecord))
|
||||
{
|
||||
if (tabletProximityRecord.enterProximity) {
|
||||
//pointer is entering tablet area proximity
|
||||
|
||||
switch(tabletProximityRecord.pointerType)
|
||||
{
|
||||
case 1: /* stylus */
|
||||
ct.Active = GHOST_kTabletModeStylus;
|
||||
break;
|
||||
case 2: /* puck, not supported so far */
|
||||
ct.Active = GHOST_kTabletModeNone;
|
||||
break;
|
||||
case 3: /* eraser */
|
||||
ct.Active = GHOST_kTabletModeEraser;
|
||||
break;
|
||||
default:
|
||||
ct.Active = GHOST_kTabletModeNone;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// pointer is leaving - return to mouse
|
||||
ct.Active = GHOST_kTabletModeNone;
|
||||
}
|
||||
}
|
||||
}
|
||||
err = noErr;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
OSStatus GHOST_SystemCarbon::handleMouseEvent(EventRef event)
|
||||
{
|
||||
OSStatus err = eventNotHandledErr;
|
||||
GHOST_IWindow* window = m_windowManager->getActiveWindow();
|
||||
UInt32 kind = ::GetEventKind(event);
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case kEventMouseDown:
|
||||
case kEventMouseUp:
|
||||
// Handle Mac application responsibilities
|
||||
if ((kind == kEventMouseDown) && handleMouseDown(event)) {
|
||||
err = noErr;
|
||||
}
|
||||
else {
|
||||
GHOST_TEventType type = (kind == kEventMouseDown) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp;
|
||||
EventMouseButton button;
|
||||
|
||||
/* Window still gets mouse up after command-H */
|
||||
if (m_windowManager->getActiveWindow()) {
|
||||
// handle any tablet events that may have come with the mouse event (optional)
|
||||
handleTabletEvent(event);
|
||||
|
||||
::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button);
|
||||
pushEvent(new GHOST_EventButton(getMilliSeconds(), type, window, convertButton(button)));
|
||||
err = noErr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kEventMouseMoved:
|
||||
case kEventMouseDragged: {
|
||||
Point mousePos;
|
||||
|
||||
if (window) {
|
||||
//handle any tablet events that may have come with the mouse event (optional)
|
||||
handleTabletEvent(event);
|
||||
|
||||
::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos);
|
||||
pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, mousePos.h, mousePos.v));
|
||||
err = noErr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kEventMouseWheelMoved:
|
||||
{
|
||||
OSStatus status;
|
||||
//UInt32 modifiers;
|
||||
EventMouseWheelAxis axis;
|
||||
SInt32 delta;
|
||||
//status = ::GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers);
|
||||
//GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed");
|
||||
status = ::GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis);
|
||||
GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed");
|
||||
if (axis == kEventMouseWheelAxisY)
|
||||
{
|
||||
status = ::GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(delta), NULL, &delta);
|
||||
GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed");
|
||||
/*
|
||||
* Limit mouse wheel delta to plus and minus one.
|
||||
*/
|
||||
delta = delta > 0 ? 1 : -1;
|
||||
pushEvent(new GHOST_EventWheel(getMilliSeconds(), window, delta));
|
||||
err = noErr;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
OSStatus GHOST_SystemCarbon::handleKeyEvent(EventRef event)
|
||||
{
|
||||
OSStatus err = eventNotHandledErr;
|
||||
GHOST_IWindow* window = m_windowManager->getActiveWindow();
|
||||
UInt32 kind = ::GetEventKind(event);
|
||||
UInt32 modifiers;
|
||||
UInt32 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 (kind) {
|
||||
case kEventRawKeyDown:
|
||||
case kEventRawKeyRepeat:
|
||||
case kEventRawKeyUp:
|
||||
::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode);
|
||||
::GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &ascii);
|
||||
|
||||
key = convertKey(rawCode);
|
||||
ascii= convertRomanToLatin(ascii);
|
||||
|
||||
// if (key!=GHOST_kKeyUnknown) {
|
||||
GHOST_TEventType type;
|
||||
if (kind == kEventRawKeyDown) {
|
||||
type = GHOST_kEventKeyDown;
|
||||
} else if (kind == kEventRawKeyRepeat) {
|
||||
type = GHOST_kEventKeyDown; /* XXX, fixme */
|
||||
} else {
|
||||
type = GHOST_kEventKeyUp;
|
||||
}
|
||||
pushEvent( new GHOST_EventKey( getMilliSeconds(), type, window, key, ascii) );
|
||||
// }
|
||||
break;
|
||||
|
||||
case kEventRawKeyModifiersChanged:
|
||||
/* ugh */
|
||||
::GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
|
||||
if ((modifiers & shiftKey) != (m_modifierMask & shiftKey)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & shiftKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
|
||||
}
|
||||
if ((modifiers & controlKey) != (m_modifierMask & controlKey)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & controlKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
|
||||
}
|
||||
if ((modifiers & optionKey) != (m_modifierMask & optionKey)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & optionKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
|
||||
}
|
||||
if ((modifiers & cmdKey) != (m_modifierMask & cmdKey)) {
|
||||
pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & cmdKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyOS) );
|
||||
}
|
||||
|
||||
m_modifierMask = modifiers;
|
||||
break;
|
||||
|
||||
default:
|
||||
err = eventNotHandledErr;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_SystemCarbon::handleMouseDown(EventRef event)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
GHOST_TUns8* GHOST_SystemCarbon::getClipboard(bool selection) const
|
||||
{
|
||||
PasteboardRef inPasteboard;
|
||||
PasteboardItemID itemID;
|
||||
CFDataRef flavorData;
|
||||
OSStatus err = noErr;
|
||||
GHOST_TUns8 * temp_buff;
|
||||
CFRange range;
|
||||
OSStatus syncFlags;
|
||||
|
||||
err = PasteboardCreate(kPasteboardClipboard, &inPasteboard);
|
||||
if(err != noErr) { return NULL;}
|
||||
|
||||
syncFlags = PasteboardSynchronize( inPasteboard );
|
||||
/* as we always get in a new string, we can safely ignore sync flags if not an error*/
|
||||
if(syncFlags <0) { return NULL;}
|
||||
|
||||
|
||||
err = PasteboardGetItemIdentifier( inPasteboard, 1, &itemID );
|
||||
if(err != noErr) { return NULL;}
|
||||
|
||||
err = PasteboardCopyItemFlavorData( inPasteboard, itemID, CFSTR("public.utf8-plain-text"), &flavorData);
|
||||
if(err != noErr) { return NULL;}
|
||||
|
||||
range = CFRangeMake(0, CFDataGetLength(flavorData));
|
||||
|
||||
temp_buff = (GHOST_TUns8*) malloc(range.length+1);
|
||||
|
||||
CFDataGetBytes(flavorData, range, (UInt8*)temp_buff);
|
||||
|
||||
temp_buff[range.length] = '\0';
|
||||
|
||||
if(temp_buff) {
|
||||
return temp_buff;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_SystemCarbon::putClipboard(GHOST_TInt8 *buffer, bool selection) const
|
||||
{
|
||||
if(selection) {return;} // for copying the selection, used on X11
|
||||
|
||||
PasteboardRef inPasteboard;
|
||||
CFDataRef textData = NULL;
|
||||
OSStatus err = noErr; /*For error checking*/
|
||||
OSStatus syncFlags;
|
||||
|
||||
err = PasteboardCreate(kPasteboardClipboard, &inPasteboard);
|
||||
if(err != noErr) { return;}
|
||||
|
||||
syncFlags = PasteboardSynchronize( inPasteboard );
|
||||
/* as we always put in a new string, we can safely ignore sync flags */
|
||||
if(syncFlags <0) { return;}
|
||||
|
||||
err = PasteboardClear( inPasteboard );
|
||||
if(err != noErr) { return;}
|
||||
|
||||
textData = CFDataCreate(kCFAllocatorDefault, (UInt8*)buffer, strlen(buffer));
|
||||
|
||||
if (textData) {
|
||||
err = PasteboardPutItemFlavor( inPasteboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), textData, 0);
|
||||
if(err != noErr) {
|
||||
if(textData) { CFRelease(textData);}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(textData) {
|
||||
CFRelease(textData);
|
||||
}
|
||||
}
|
||||
290
intern/ghost/intern/GHOST_SystemCarbon.h
Normal file
290
intern/ghost/intern/GHOST_SystemCarbon.h
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_SystemCarbon.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_SystemCarbon class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_SYSTEM_CARBON_H_
|
||||
#define _GHOST_SYSTEM_CARBON_H_
|
||||
|
||||
#ifndef __APPLE__
|
||||
#error Apple OSX only!
|
||||
#endif // __APPLE__
|
||||
|
||||
#define __CARBONSOUND__
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include "GHOST_System.h"
|
||||
|
||||
class GHOST_EventCursor;
|
||||
class GHOST_EventKey;
|
||||
class GHOST_EventWindow;
|
||||
|
||||
/**
|
||||
* OSX/Carbon Implementation of GHOST_System class.
|
||||
* @see GHOST_System.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 21, 2001
|
||||
*/
|
||||
class GHOST_SystemCarbon : public GHOST_System {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_SystemCarbon();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~GHOST_SystemCarbon();
|
||||
|
||||
/***************************************************************************************
|
||||
** 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_TUns16 numOfAASamples = 0,
|
||||
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);
|
||||
|
||||
/***************************************************************************************
|
||||
** 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;
|
||||
|
||||
/**
|
||||
* @see GHOST_ISystem
|
||||
*/
|
||||
int toggleConsole(int action) { return 0; }
|
||||
|
||||
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 event A Mac event.
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
OSStatus handleTabletEvent(EventRef event);
|
||||
/**
|
||||
* Handles a mouse event.
|
||||
* @param event A Mac event.
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
OSStatus handleMouseEvent(EventRef event);
|
||||
|
||||
/**
|
||||
* Handles a key event.
|
||||
* @param event A Mac event.
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
OSStatus handleKeyEvent(EventRef event);
|
||||
|
||||
/**
|
||||
* Handles a window event.
|
||||
* @param event A Mac event.
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
OSStatus handleWindowEvent(EventRef event);
|
||||
|
||||
/**
|
||||
* Handles all basic Mac application stuff for a mouse down event.
|
||||
* @param event A Mac event.
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
bool handleMouseDown(EventRef event);
|
||||
|
||||
/**
|
||||
* 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 Carbon when it has events.
|
||||
*/
|
||||
static OSStatus sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData);
|
||||
|
||||
/** Apple Event Handlers */
|
||||
static OSErr sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
|
||||
static OSErr sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
|
||||
static OSErr sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
|
||||
static OSErr sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon);
|
||||
|
||||
/**
|
||||
* Callback for Mac Timer tasks that expire.
|
||||
* @param tmTask Pointer to the timer task that expired.
|
||||
*/
|
||||
//static void s_timerCallback(TMTaskPtr tmTask);
|
||||
|
||||
/** Event handler reference. */
|
||||
EventHandlerRef m_handler;
|
||||
|
||||
/** Start time at initialization. */
|
||||
GHOST_TUns64 m_start_time;
|
||||
|
||||
/** State of the modifiers. */
|
||||
UInt32 m_modifierMask;
|
||||
|
||||
/** Ignores window size messages (when window is dragged). */
|
||||
bool m_ignoreWindowSizedMessages;
|
||||
};
|
||||
|
||||
#endif // _GHOST_SYSTEM_CARBON_H_
|
||||
|
||||
306
intern/ghost/intern/GHOST_SystemCocoa.h
Normal file
306
intern/ghost/intern/GHOST_SystemCocoa.h
Normal file
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_SystemCocoa.h
|
||||
* \ingroup GHOST
|
||||
* 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_WindowCocoa;
|
||||
|
||||
|
||||
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 stereoVisual Stereo visual for quad buffered stereo.
|
||||
* @param numOfAASamples Number of samples used for AA (zero if no AA)
|
||||
* @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 = false,
|
||||
const GHOST_TUns16 numOfAASamples = 0,
|
||||
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);
|
||||
|
||||
/**
|
||||
* Handle User request to quit, from Menu bar Quit, and Cmd+Q
|
||||
* Display alert panel if changes performed since last save
|
||||
*/
|
||||
GHOST_TUns8 handleQuitRequest();
|
||||
|
||||
/**
|
||||
* Handle Cocoa openFile event
|
||||
* Display confirmation request panel if changes performed since last save
|
||||
*/
|
||||
bool handleOpenDocumentRequest(void *filepathStr);
|
||||
|
||||
/**
|
||||
* Handles a drag'n'drop destination event. Called by GHOST_WindowCocoa window subclass
|
||||
* @param eventType The type of drag'n'drop event
|
||||
* @param draggedObjectType The type object concerned (currently array of file names, string, TIFF image)
|
||||
* @param mouseX x mouse coordinate (in cocoa base window coordinates)
|
||||
* @param mouseY y mouse coordinate
|
||||
* @param window The window on which the event occurred
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
GHOST_TSuccess handleDraggingEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType,
|
||||
GHOST_WindowCocoa* window, int mouseX, int mouseY, void* data);
|
||||
|
||||
/***************************************************************************************
|
||||
** 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);
|
||||
|
||||
/***************************************************************************************
|
||||
** 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;
|
||||
|
||||
/**
|
||||
* Handles a window event. Called by GHOST_WindowCocoa window delegate
|
||||
* @param eventType The type of window event
|
||||
* @param window The window on which the event occurred
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window);
|
||||
|
||||
/**
|
||||
* Handles the Cocoa event telling the application has become active (again)
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
GHOST_TSuccess handleApplicationBecomeActiveEvent();
|
||||
|
||||
/**
|
||||
* @see GHOST_ISystem
|
||||
*/
|
||||
int toggleConsole(int action) { return 0; }
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initializes the system.
|
||||
* For now, it justs registers the window class (WNDCLASS).
|
||||
* @return A success value.
|
||||
*/
|
||||
virtual GHOST_TSuccess init();
|
||||
|
||||
/**
|
||||
* Handles a tablet event.
|
||||
* @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++)
|
||||
* @param eventType The type of the event. It needs to be passed separately as it can be either directly in the event type, or as a subtype if combined with a mouse button event
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
GHOST_TSuccess handleTabletEvent(void *eventPtr, short eventType);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
GHOST_TSuccess 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.
|
||||
*/
|
||||
GHOST_TSuccess handleKeyEvent(void *eventPtr);
|
||||
|
||||
/**
|
||||
* Performs the actual cursor position update (location in screen coordinates).
|
||||
* @param x The x-coordinate of the cursor.
|
||||
* @param y The y-coordinate of the cursor.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
GHOST_TSuccess setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y);
|
||||
|
||||
/** Start time at initialization. */
|
||||
GHOST_TUns64 m_start_time;
|
||||
|
||||
/** Event has been processed directly by Cocoa and has sent a ghost event to be dispatched */
|
||||
bool m_outsideLoopEventProcessed;
|
||||
|
||||
/** Raised window is not yet known by the window manager, so delay application become active event handling */
|
||||
bool m_needDelayedApplicationBecomeActiveEventProcessing;
|
||||
|
||||
/** 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;
|
||||
|
||||
/** Stores the mouse cursor delta due to setting a new cursor position
|
||||
* Needed because cocoa event delta cursor move takes setCursorPosition changes too.
|
||||
*/
|
||||
GHOST_TInt32 m_cursorDelta_x, m_cursorDelta_y;
|
||||
|
||||
/** Multitouch trackpad availability */
|
||||
bool m_hasMultiTouchTrackpad;
|
||||
|
||||
/** Multitouch gesture in progress, useful to distinguish trackpad from mouse scroll events */
|
||||
bool m_isGestureInProgress;
|
||||
};
|
||||
|
||||
#endif // _GHOST_SYSTEM_COCOA_H_
|
||||
|
||||
1798
intern/ghost/intern/GHOST_SystemCocoa.mm
Normal file
1798
intern/ghost/intern/GHOST_SystemCocoa.mm
Normal file
@@ -0,0 +1,1798 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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>
|
||||
|
||||
/*For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible)*/
|
||||
#include <Carbon/Carbon.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_EventTrackpad.h"
|
||||
#include "GHOST_EventDragnDrop.h"
|
||||
#include "GHOST_EventString.h"
|
||||
|
||||
#include "GHOST_TimerManager.h"
|
||||
#include "GHOST_TimerTask.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
#include "GHOST_WindowCocoa.h"
|
||||
#include "GHOST_NDOFManager.h"
|
||||
#include "AssertMacros.h"
|
||||
|
||||
#pragma mark KeyMap, mouse converters
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
|
||||
/* Keycodes not defined in Tiger */
|
||||
/*
|
||||
* Summary:
|
||||
* Virtual keycodes
|
||||
*
|
||||
* Discussion:
|
||||
* These constants are the virtual keycodes defined originally in
|
||||
* Inside Mac Volume V, pg. V-191. They identify physical keys on a
|
||||
* keyboard. Those constants with "ANSI" in the name are labeled
|
||||
* according to the key position on an ANSI-standard US keyboard.
|
||||
* For example, kVK_ANSI_A indicates the virtual keycode for the key
|
||||
* with the letter 'A' in the US keyboard layout. Other keyboard
|
||||
* layouts may have the 'A' key label on a different physical key;
|
||||
* in this case, pressing 'A' will generate a different virtual
|
||||
* keycode.
|
||||
*/
|
||||
enum {
|
||||
kVK_ANSI_A = 0x00,
|
||||
kVK_ANSI_S = 0x01,
|
||||
kVK_ANSI_D = 0x02,
|
||||
kVK_ANSI_F = 0x03,
|
||||
kVK_ANSI_H = 0x04,
|
||||
kVK_ANSI_G = 0x05,
|
||||
kVK_ANSI_Z = 0x06,
|
||||
kVK_ANSI_X = 0x07,
|
||||
kVK_ANSI_C = 0x08,
|
||||
kVK_ANSI_V = 0x09,
|
||||
kVK_ANSI_B = 0x0B,
|
||||
kVK_ANSI_Q = 0x0C,
|
||||
kVK_ANSI_W = 0x0D,
|
||||
kVK_ANSI_E = 0x0E,
|
||||
kVK_ANSI_R = 0x0F,
|
||||
kVK_ANSI_Y = 0x10,
|
||||
kVK_ANSI_T = 0x11,
|
||||
kVK_ANSI_1 = 0x12,
|
||||
kVK_ANSI_2 = 0x13,
|
||||
kVK_ANSI_3 = 0x14,
|
||||
kVK_ANSI_4 = 0x15,
|
||||
kVK_ANSI_6 = 0x16,
|
||||
kVK_ANSI_5 = 0x17,
|
||||
kVK_ANSI_Equal = 0x18,
|
||||
kVK_ANSI_9 = 0x19,
|
||||
kVK_ANSI_7 = 0x1A,
|
||||
kVK_ANSI_Minus = 0x1B,
|
||||
kVK_ANSI_8 = 0x1C,
|
||||
kVK_ANSI_0 = 0x1D,
|
||||
kVK_ANSI_RightBracket = 0x1E,
|
||||
kVK_ANSI_O = 0x1F,
|
||||
kVK_ANSI_U = 0x20,
|
||||
kVK_ANSI_LeftBracket = 0x21,
|
||||
kVK_ANSI_I = 0x22,
|
||||
kVK_ANSI_P = 0x23,
|
||||
kVK_ANSI_L = 0x25,
|
||||
kVK_ANSI_J = 0x26,
|
||||
kVK_ANSI_Quote = 0x27,
|
||||
kVK_ANSI_K = 0x28,
|
||||
kVK_ANSI_Semicolon = 0x29,
|
||||
kVK_ANSI_Backslash = 0x2A,
|
||||
kVK_ANSI_Comma = 0x2B,
|
||||
kVK_ANSI_Slash = 0x2C,
|
||||
kVK_ANSI_N = 0x2D,
|
||||
kVK_ANSI_M = 0x2E,
|
||||
kVK_ANSI_Period = 0x2F,
|
||||
kVK_ANSI_Grave = 0x32,
|
||||
kVK_ANSI_KeypadDecimal = 0x41,
|
||||
kVK_ANSI_KeypadMultiply = 0x43,
|
||||
kVK_ANSI_KeypadPlus = 0x45,
|
||||
kVK_ANSI_KeypadClear = 0x47,
|
||||
kVK_ANSI_KeypadDivide = 0x4B,
|
||||
kVK_ANSI_KeypadEnter = 0x4C,
|
||||
kVK_ANSI_KeypadMinus = 0x4E,
|
||||
kVK_ANSI_KeypadEquals = 0x51,
|
||||
kVK_ANSI_Keypad0 = 0x52,
|
||||
kVK_ANSI_Keypad1 = 0x53,
|
||||
kVK_ANSI_Keypad2 = 0x54,
|
||||
kVK_ANSI_Keypad3 = 0x55,
|
||||
kVK_ANSI_Keypad4 = 0x56,
|
||||
kVK_ANSI_Keypad5 = 0x57,
|
||||
kVK_ANSI_Keypad6 = 0x58,
|
||||
kVK_ANSI_Keypad7 = 0x59,
|
||||
kVK_ANSI_Keypad8 = 0x5B,
|
||||
kVK_ANSI_Keypad9 = 0x5C
|
||||
};
|
||||
|
||||
/* keycodes for keys that are independent of keyboard layout*/
|
||||
enum {
|
||||
kVK_Return = 0x24,
|
||||
kVK_Tab = 0x30,
|
||||
kVK_Space = 0x31,
|
||||
kVK_Delete = 0x33,
|
||||
kVK_Escape = 0x35,
|
||||
kVK_Command = 0x37,
|
||||
kVK_Shift = 0x38,
|
||||
kVK_CapsLock = 0x39,
|
||||
kVK_Option = 0x3A,
|
||||
kVK_Control = 0x3B,
|
||||
kVK_RightShift = 0x3C,
|
||||
kVK_RightOption = 0x3D,
|
||||
kVK_RightControl = 0x3E,
|
||||
kVK_Function = 0x3F,
|
||||
kVK_F17 = 0x40,
|
||||
kVK_VolumeUp = 0x48,
|
||||
kVK_VolumeDown = 0x49,
|
||||
kVK_Mute = 0x4A,
|
||||
kVK_F18 = 0x4F,
|
||||
kVK_F19 = 0x50,
|
||||
kVK_F20 = 0x5A,
|
||||
kVK_F5 = 0x60,
|
||||
kVK_F6 = 0x61,
|
||||
kVK_F7 = 0x62,
|
||||
kVK_F3 = 0x63,
|
||||
kVK_F8 = 0x64,
|
||||
kVK_F9 = 0x65,
|
||||
kVK_F11 = 0x67,
|
||||
kVK_F13 = 0x69,
|
||||
kVK_F16 = 0x6A,
|
||||
kVK_F14 = 0x6B,
|
||||
kVK_F10 = 0x6D,
|
||||
kVK_F12 = 0x6F,
|
||||
kVK_F15 = 0x71,
|
||||
kVK_Help = 0x72,
|
||||
kVK_Home = 0x73,
|
||||
kVK_PageUp = 0x74,
|
||||
kVK_ForwardDelete = 0x75,
|
||||
kVK_F4 = 0x76,
|
||||
kVK_End = 0x77,
|
||||
kVK_F2 = 0x78,
|
||||
kVK_PageDown = 0x79,
|
||||
kVK_F1 = 0x7A,
|
||||
kVK_LeftArrow = 0x7B,
|
||||
kVK_RightArrow = 0x7C,
|
||||
kVK_DownArrow = 0x7D,
|
||||
kVK_UpArrow = 0x7E
|
||||
};
|
||||
|
||||
/* ISO keyboards only*/
|
||||
enum {
|
||||
kVK_ISO_Section = 0x0A
|
||||
};
|
||||
|
||||
/* JIS keyboards only*/
|
||||
enum {
|
||||
kVK_JIS_Yen = 0x5D,
|
||||
kVK_JIS_Underscore = 0x5E,
|
||||
kVK_JIS_KeypadComma = 0x5F,
|
||||
kVK_JIS_Eisu = 0x66,
|
||||
kVK_JIS_Kana = 0x68
|
||||
};
|
||||
#endif
|
||||
|
||||
static GHOST_TButtonMask convertButton(int 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Mac rawkey codes (same for Cocoa & Carbon)
|
||||
* into GHOST key codes
|
||||
* @param rawCode The raw physical key code
|
||||
* @param recvChar the character ignoring modifiers (except for shift)
|
||||
* @return Ghost key code
|
||||
*/
|
||||
static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
|
||||
{
|
||||
|
||||
//printf("\nrecvchar %c 0x%x",recvChar,recvChar);
|
||||
switch (rawCode) {
|
||||
/*Physical keycodes not used due to map changes in int'l keyboards
|
||||
case kVK_ANSI_A: return GHOST_kKeyA;
|
||||
case kVK_ANSI_B: return GHOST_kKeyB;
|
||||
case kVK_ANSI_C: return GHOST_kKeyC;
|
||||
case kVK_ANSI_D: return GHOST_kKeyD;
|
||||
case kVK_ANSI_E: return GHOST_kKeyE;
|
||||
case kVK_ANSI_F: return GHOST_kKeyF;
|
||||
case kVK_ANSI_G: return GHOST_kKeyG;
|
||||
case kVK_ANSI_H: return GHOST_kKeyH;
|
||||
case kVK_ANSI_I: return GHOST_kKeyI;
|
||||
case kVK_ANSI_J: return GHOST_kKeyJ;
|
||||
case kVK_ANSI_K: return GHOST_kKeyK;
|
||||
case kVK_ANSI_L: return GHOST_kKeyL;
|
||||
case kVK_ANSI_M: return GHOST_kKeyM;
|
||||
case kVK_ANSI_N: return GHOST_kKeyN;
|
||||
case kVK_ANSI_O: return GHOST_kKeyO;
|
||||
case kVK_ANSI_P: return GHOST_kKeyP;
|
||||
case kVK_ANSI_Q: return GHOST_kKeyQ;
|
||||
case kVK_ANSI_R: return GHOST_kKeyR;
|
||||
case kVK_ANSI_S: return GHOST_kKeyS;
|
||||
case kVK_ANSI_T: return GHOST_kKeyT;
|
||||
case kVK_ANSI_U: return GHOST_kKeyU;
|
||||
case kVK_ANSI_V: return GHOST_kKeyV;
|
||||
case kVK_ANSI_W: return GHOST_kKeyW;
|
||||
case kVK_ANSI_X: return GHOST_kKeyX;
|
||||
case kVK_ANSI_Y: return GHOST_kKeyY;
|
||||
case kVK_ANSI_Z: return GHOST_kKeyZ;*/
|
||||
|
||||
/* Numbers keys mapped to handle some int'l keyboard (e.g. French)*/
|
||||
case kVK_ISO_Section: return GHOST_kKeyUnknown;
|
||||
case kVK_ANSI_1: return GHOST_kKey1;
|
||||
case kVK_ANSI_2: return GHOST_kKey2;
|
||||
case kVK_ANSI_3: return GHOST_kKey3;
|
||||
case kVK_ANSI_4: return GHOST_kKey4;
|
||||
case kVK_ANSI_5: return GHOST_kKey5;
|
||||
case kVK_ANSI_6: return GHOST_kKey6;
|
||||
case kVK_ANSI_7: return GHOST_kKey7;
|
||||
case kVK_ANSI_8: return GHOST_kKey8;
|
||||
case kVK_ANSI_9: return GHOST_kKey9;
|
||||
case kVK_ANSI_0: return GHOST_kKey0;
|
||||
|
||||
case kVK_ANSI_Keypad0: return GHOST_kKeyNumpad0;
|
||||
case kVK_ANSI_Keypad1: return GHOST_kKeyNumpad1;
|
||||
case kVK_ANSI_Keypad2: return GHOST_kKeyNumpad2;
|
||||
case kVK_ANSI_Keypad3: return GHOST_kKeyNumpad3;
|
||||
case kVK_ANSI_Keypad4: return GHOST_kKeyNumpad4;
|
||||
case kVK_ANSI_Keypad5: return GHOST_kKeyNumpad5;
|
||||
case kVK_ANSI_Keypad6: return GHOST_kKeyNumpad6;
|
||||
case kVK_ANSI_Keypad7: return GHOST_kKeyNumpad7;
|
||||
case kVK_ANSI_Keypad8: return GHOST_kKeyNumpad8;
|
||||
case kVK_ANSI_Keypad9: return GHOST_kKeyNumpad9;
|
||||
case kVK_ANSI_KeypadDecimal: return GHOST_kKeyNumpadPeriod;
|
||||
case kVK_ANSI_KeypadEnter: return GHOST_kKeyNumpadEnter;
|
||||
case kVK_ANSI_KeypadPlus: return GHOST_kKeyNumpadPlus;
|
||||
case kVK_ANSI_KeypadMinus: return GHOST_kKeyNumpadMinus;
|
||||
case kVK_ANSI_KeypadMultiply: return GHOST_kKeyNumpadAsterisk;
|
||||
case kVK_ANSI_KeypadDivide: return GHOST_kKeyNumpadSlash;
|
||||
case kVK_ANSI_KeypadClear: return GHOST_kKeyUnknown;
|
||||
|
||||
case kVK_F1: return GHOST_kKeyF1;
|
||||
case kVK_F2: return GHOST_kKeyF2;
|
||||
case kVK_F3: return GHOST_kKeyF3;
|
||||
case kVK_F4: return GHOST_kKeyF4;
|
||||
case kVK_F5: return GHOST_kKeyF5;
|
||||
case kVK_F6: return GHOST_kKeyF6;
|
||||
case kVK_F7: return GHOST_kKeyF7;
|
||||
case kVK_F8: return GHOST_kKeyF8;
|
||||
case kVK_F9: return GHOST_kKeyF9;
|
||||
case kVK_F10: return GHOST_kKeyF10;
|
||||
case kVK_F11: return GHOST_kKeyF11;
|
||||
case kVK_F12: return GHOST_kKeyF12;
|
||||
case kVK_F13: return GHOST_kKeyF13;
|
||||
case kVK_F14: return GHOST_kKeyF14;
|
||||
case kVK_F15: return GHOST_kKeyF15;
|
||||
case kVK_F16: return GHOST_kKeyF16;
|
||||
case kVK_F17: return GHOST_kKeyF17;
|
||||
case kVK_F18: return GHOST_kKeyF18;
|
||||
case kVK_F19: return GHOST_kKeyF19;
|
||||
case kVK_F20: return GHOST_kKeyF20;
|
||||
|
||||
case kVK_UpArrow: return GHOST_kKeyUpArrow;
|
||||
case kVK_DownArrow: return GHOST_kKeyDownArrow;
|
||||
case kVK_LeftArrow: return GHOST_kKeyLeftArrow;
|
||||
case kVK_RightArrow: return GHOST_kKeyRightArrow;
|
||||
|
||||
case kVK_Return: return GHOST_kKeyEnter;
|
||||
case kVK_Delete: return GHOST_kKeyBackSpace;
|
||||
case kVK_ForwardDelete: return GHOST_kKeyDelete;
|
||||
case kVK_Escape: return GHOST_kKeyEsc;
|
||||
case kVK_Tab: return GHOST_kKeyTab;
|
||||
case kVK_Space: return GHOST_kKeySpace;
|
||||
|
||||
case kVK_Home: return GHOST_kKeyHome;
|
||||
case kVK_End: return GHOST_kKeyEnd;
|
||||
case kVK_PageUp: return GHOST_kKeyUpPage;
|
||||
case kVK_PageDown: return GHOST_kKeyDownPage;
|
||||
|
||||
/*case kVK_ANSI_Minus: return GHOST_kKeyMinus;
|
||||
case kVK_ANSI_Equal: return GHOST_kKeyEqual;
|
||||
case kVK_ANSI_Comma: return GHOST_kKeyComma;
|
||||
case kVK_ANSI_Period: return GHOST_kKeyPeriod;
|
||||
case kVK_ANSI_Slash: return GHOST_kKeySlash;
|
||||
case kVK_ANSI_Semicolon: return GHOST_kKeySemicolon;
|
||||
case kVK_ANSI_Quote: return GHOST_kKeyQuote;
|
||||
case kVK_ANSI_Backslash: return GHOST_kKeyBackslash;
|
||||
case kVK_ANSI_LeftBracket: return GHOST_kKeyLeftBracket;
|
||||
case kVK_ANSI_RightBracket: return GHOST_kKeyRightBracket;
|
||||
case kVK_ANSI_Grave: return GHOST_kKeyAccentGrave;*/
|
||||
|
||||
case kVK_VolumeUp:
|
||||
case kVK_VolumeDown:
|
||||
case kVK_Mute:
|
||||
return GHOST_kKeyUnknown;
|
||||
|
||||
default:
|
||||
/* alphanumerical or punctuation key that is remappable in int'l keyboards */
|
||||
if ((recvChar >= 'A') && (recvChar <= 'Z')) {
|
||||
return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA);
|
||||
} else if ((recvChar >= 'a') && (recvChar <= 'z')) {
|
||||
return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);
|
||||
} else {
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
|
||||
KeyboardLayoutRef keyLayout;
|
||||
UCKeyboardLayout *uchrData;
|
||||
|
||||
KLGetCurrentKeyboardLayout(&keyLayout);
|
||||
KLGetKeyboardLayoutProperty(keyLayout, kKLuchrData, (const void **)
|
||||
&uchrData);
|
||||
/*get actual character value of the "remappable" keys in int'l keyboards,
|
||||
if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
|
||||
then fallback on using the received charactersIgnoringModifiers */
|
||||
if (uchrData)
|
||||
{
|
||||
UInt32 deadKeyState=0;
|
||||
UniCharCount actualStrLength=0;
|
||||
|
||||
UCKeyTranslate(uchrData, rawCode, keyAction, 0,
|
||||
LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
|
||||
|
||||
}
|
||||
#else
|
||||
/* Leopard and Snow Leopard 64bit compatible API*/
|
||||
CFDataRef uchrHandle; /*the keyboard layout*/
|
||||
TISInputSourceRef kbdTISHandle;
|
||||
|
||||
kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource();
|
||||
uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData);
|
||||
CFRelease(kbdTISHandle);
|
||||
|
||||
/*get actual character value of the "remappable" keys in int'l keyboards,
|
||||
if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
|
||||
then fallback on using the received charactersIgnoringModifiers */
|
||||
if (uchrHandle)
|
||||
{
|
||||
UInt32 deadKeyState=0;
|
||||
UniCharCount actualStrLength=0;
|
||||
|
||||
UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0,
|
||||
LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
|
||||
|
||||
}
|
||||
#endif
|
||||
switch (recvChar) {
|
||||
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;
|
||||
default:
|
||||
return GHOST_kKeyUnknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
return GHOST_kKeyUnknown;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark defines for 10.6 api not documented in 10.5
|
||||
#ifndef MAC_OS_X_VERSION_10_6
|
||||
enum {
|
||||
/* The following event types are available on some hardware on 10.5.2 and later */
|
||||
NSEventTypeGesture = 29,
|
||||
NSEventTypeMagnify = 30,
|
||||
NSEventTypeSwipe = 31,
|
||||
NSEventTypeRotate = 18,
|
||||
NSEventTypeBeginGesture = 19,
|
||||
NSEventTypeEndGesture = 20
|
||||
};
|
||||
|
||||
@interface NSEvent(GestureEvents)
|
||||
/* This message is valid for events of type NSEventTypeMagnify, on 10.5.2 or later */
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
|
||||
- (float)magnification; // change in magnification.
|
||||
#else
|
||||
- (CGFloat)magnification; // change in magnification.
|
||||
#endif
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#pragma mark Utility functions
|
||||
|
||||
#define FIRSTFILEBUFLG 512
|
||||
static bool g_hasFirstFile = false;
|
||||
static char g_firstFileBuf[512];
|
||||
|
||||
//TODO:Need to investigate this. Function called too early in creator.c to have g_hasFirstFile == true
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WITH_QUICKTIME) && !defined(USE_QTKIT)
|
||||
//Need to place this quicktime function in an ObjC file
|
||||
//It is used to avoid memory leak when raising the quicktime "compression settings" standard dialog
|
||||
extern "C" {
|
||||
struct bContext;
|
||||
struct wmOperator;
|
||||
extern int fromcocoa_request_qtcodec_settings(bContext *C, wmOperator *op);
|
||||
|
||||
|
||||
int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op)
|
||||
{
|
||||
int result;
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
result = fromcocoa_request_qtcodec_settings(C, op);
|
||||
|
||||
[pool drain];
|
||||
return result;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#pragma mark Cocoa objects
|
||||
|
||||
/**
|
||||
* CocoaAppDelegate
|
||||
* ObjC object to capture applicationShouldTerminate, and send quit event
|
||||
**/
|
||||
@interface CocoaAppDelegate : NSObject {
|
||||
GHOST_SystemCocoa *systemCocoa;
|
||||
}
|
||||
- (void)setSystemCocoa:(GHOST_SystemCocoa *)sysCocoa;
|
||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename;
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification;
|
||||
- (void)applicationWillBecomeActive:(NSNotification *)aNotification;
|
||||
@end
|
||||
|
||||
@implementation CocoaAppDelegate : NSObject
|
||||
-(void)setSystemCocoa:(GHOST_SystemCocoa *)sysCocoa
|
||||
{
|
||||
systemCocoa = sysCocoa;
|
||||
}
|
||||
|
||||
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
|
||||
{
|
||||
return systemCocoa->handleOpenDocumentRequest(filename);
|
||||
}
|
||||
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
//TODO: implement graceful termination through Cocoa mechanism to avoid session log off to be cancelled
|
||||
//Note that Cmd+Q is already handled by keyhandler
|
||||
if (systemCocoa->handleQuitRequest() == GHOST_kExitNow)
|
||||
return NSTerminateCancel;//NSTerminateNow;
|
||||
else
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
|
||||
// To avoid cancelling a log off process, we must use Cocoa termination process
|
||||
// And this function is the only chance to perform clean up
|
||||
// So WM_exit needs to be called directly, as the event loop will never run before termination
|
||||
- (void)applicationWillTerminate:(NSNotification *)aNotification
|
||||
{
|
||||
/*G.afbreek = 0; //Let Cocoa perform the termination at the end
|
||||
WM_exit(C);*/
|
||||
}
|
||||
|
||||
- (void)applicationWillBecomeActive:(NSNotification *)aNotification
|
||||
{
|
||||
systemCocoa->handleApplicationBecomeActiveEvent();
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark initialization/finalization
|
||||
|
||||
|
||||
GHOST_SystemCocoa::GHOST_SystemCocoa()
|
||||
{
|
||||
int mib[2];
|
||||
struct timeval boottime;
|
||||
size_t len;
|
||||
char *rstring = NULL;
|
||||
|
||||
m_modifierMask =0;
|
||||
m_pressedMouseButtons =0;
|
||||
m_isGestureInProgress = false;
|
||||
m_cursorDelta_x=0;
|
||||
m_cursorDelta_y=0;
|
||||
m_outsideLoopEventProcessed = false;
|
||||
m_needDelayedApplicationBecomeActiveEventProcessing = false;
|
||||
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
|
||||
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));
|
||||
|
||||
//Detect multitouch trackpad
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_MODEL;
|
||||
sysctl( mib, 2, NULL, &len, NULL, 0 );
|
||||
rstring = (char*)malloc( len );
|
||||
sysctl( mib, 2, rstring, &len, NULL, 0 );
|
||||
|
||||
//Hack on MacBook revision, as multitouch avail. function missing
|
||||
if (strstr(rstring,"MacBookAir") ||
|
||||
(strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9')))
|
||||
m_hasMultiTouchTrackpad = true;
|
||||
else m_hasMultiTouchTrackpad = false;
|
||||
|
||||
free( rstring );
|
||||
rstring = NULL;
|
||||
|
||||
m_ignoreWindowSizedMessages = false;
|
||||
}
|
||||
|
||||
GHOST_SystemCocoa::~GHOST_SystemCocoa()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::init()
|
||||
{
|
||||
|
||||
GHOST_TSuccess success = GHOST_System::init();
|
||||
if (success) {
|
||||
//ProcessSerialNumber psn;
|
||||
|
||||
//Carbon stuff to move window & menu to foreground
|
||||
/*if (!GetCurrentProcess(&psn)) {
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
SetFrontProcess(&psn);
|
||||
}*/
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
if (NSApp == nil) {
|
||||
[NSApplication sharedApplication];
|
||||
|
||||
if ([NSApp mainMenu] == nil) {
|
||||
NSMenu *mainMenubar = [[NSMenu alloc] init];
|
||||
NSMenuItem *menuItem;
|
||||
NSMenu *windowMenu;
|
||||
NSMenu *appMenu;
|
||||
|
||||
//Create the application menu
|
||||
appMenu = [[NSMenu alloc] initWithTitle:@"Blender"];
|
||||
|
||||
[appMenu addItemWithTitle:@"About Blender" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
|
||||
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
menuItem = [appMenu addItemWithTitle:@"Hide Blender" action:@selector(hide:) keyEquivalent:@"h"];
|
||||
[menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
|
||||
|
||||
menuItem = [appMenu addItemWithTitle:@"Hide others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
|
||||
[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask)];
|
||||
|
||||
[appMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
|
||||
|
||||
menuItem = [appMenu addItemWithTitle:@"Quit Blender" action:@selector(terminate:) keyEquivalent:@"q"];
|
||||
[menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
|
||||
|
||||
menuItem = [[NSMenuItem alloc] init];
|
||||
[menuItem setSubmenu:appMenu];
|
||||
|
||||
[mainMenubar addItem:menuItem];
|
||||
[menuItem release];
|
||||
[NSApp performSelector:@selector(setAppleMenu:) withObject:appMenu]; //Needed for 10.5
|
||||
[appMenu release];
|
||||
|
||||
//Create the window menu
|
||||
windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
|
||||
|
||||
menuItem = [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
|
||||
[menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
|
||||
|
||||
[windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
|
||||
|
||||
menuItem = [windowMenu addItemWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"];
|
||||
[menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
|
||||
|
||||
menuItem = [[NSMenuItem alloc] init];
|
||||
[menuItem setSubmenu:windowMenu];
|
||||
|
||||
[mainMenubar addItem:menuItem];
|
||||
[menuItem release];
|
||||
|
||||
[NSApp setMainMenu:mainMenubar];
|
||||
[NSApp setWindowsMenu:windowMenu];
|
||||
[windowMenu release];
|
||||
}
|
||||
}
|
||||
if ([NSApp delegate] == nil) {
|
||||
CocoaAppDelegate *appDelegate = [[CocoaAppDelegate alloc] init];
|
||||
[appDelegate setSystemCocoa:this];
|
||||
[NSApp setDelegate:appDelegate];
|
||||
}
|
||||
|
||||
[NSApp finishLaunching];
|
||||
|
||||
[pool drain];
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark window management
|
||||
|
||||
GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const
|
||||
{
|
||||
//Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime])
|
||||
struct timeval currentTime;
|
||||
|
||||
gettimeofday(¤tTime, NULL);
|
||||
|
||||
//Return timestamp of system uptime
|
||||
|
||||
return ((currentTime.tv_sec*1000)+(currentTime.tv_usec/1000)-m_start_time);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const
|
||||
{
|
||||
//Note that OS X supports monitor hot plug
|
||||
// We do not support multiple monitors at the moment
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
GHOST_TUns8 count = [[NSScreen screens] count];
|
||||
|
||||
[pool drain];
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
//Get visible frame, that is frame excluding dock and top menu bar
|
||||
NSRect frame = [[NSScreen mainScreen] visibleFrame];
|
||||
|
||||
//Returns max window contents (excluding title bar...)
|
||||
NSRect contentRect = [NSWindow contentRectForFrameRect:frame
|
||||
styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
|
||||
|
||||
width = contentRect.size.width;
|
||||
height = contentRect.size.height;
|
||||
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
|
||||
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_TUns16 numOfAASamples,
|
||||
const GHOST_TEmbedderWindowID parentWindow
|
||||
)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
GHOST_IWindow* window = 0;
|
||||
|
||||
//Get the available rect for including window contents
|
||||
NSRect frame = [[NSScreen mainScreen] visibleFrame];
|
||||
NSRect contentRect = [NSWindow contentRectForFrameRect:frame
|
||||
styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)];
|
||||
|
||||
//Ensures window top left is inside this available rect
|
||||
left = left > contentRect.origin.x ? left : contentRect.origin.x;
|
||||
top = top > contentRect.origin.y ? top : contentRect.origin.y;
|
||||
|
||||
window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples);
|
||||
|
||||
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);
|
||||
//Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation)
|
||||
pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, 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");
|
||||
}
|
||||
[pool drain];
|
||||
return window;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual)
|
||||
{
|
||||
GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();
|
||||
*window = currentWindow;
|
||||
|
||||
if(!currentWindow) return GHOST_kFailure;
|
||||
|
||||
return currentWindow->setState(GHOST_kWindowStateFullScreen);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void)
|
||||
{
|
||||
GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow();
|
||||
if(!currentWindow) return GHOST_kFailure;
|
||||
|
||||
return currentWindow->setState(GHOST_kWindowStateNormal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @note : returns coordinates in Cocoa screen coordinates
|
||||
*/
|
||||
GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
|
||||
{
|
||||
NSPoint mouseLoc = [NSEvent mouseLocation];
|
||||
|
||||
// Returns the mouse location in screen coordinates
|
||||
x = (GHOST_TInt32)mouseLoc.x;
|
||||
y = (GHOST_TInt32)mouseLoc.y;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* @note : expect Cocoa screen coordinates
|
||||
*/
|
||||
GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
|
||||
{
|
||||
GHOST_TInt32 wx,wy;
|
||||
GHOST_WindowCocoa* window = (GHOST_WindowCocoa*)m_windowManager->getActiveWindow();
|
||||
if (!window) return GHOST_kFailure;
|
||||
|
||||
//Cursor and mouse dissociation placed here not to interfere with continuous grab
|
||||
// (in cont. grab setMouseCursorPosition is directly called)
|
||||
CGAssociateMouseAndMouseCursorPosition(false);
|
||||
setMouseCursorPosition(x, y);
|
||||
CGAssociateMouseAndMouseCursorPosition(true);
|
||||
|
||||
//Force mouse move event (not pushed by Cocoa)
|
||||
window->screenToClient(x, y, wx, wy);
|
||||
pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, wx,wy));
|
||||
m_outsideLoopEventProcessed = true;
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
|
||||
{
|
||||
float xf=(float)x, yf=(float)y;
|
||||
GHOST_WindowCocoa* window = (GHOST_WindowCocoa*)m_windowManager->getActiveWindow();
|
||||
if (!window) return GHOST_kFailure;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSScreen *windowScreen = window->getScreen();
|
||||
NSRect screenRect = [windowScreen frame];
|
||||
|
||||
//Set position relative to current screen
|
||||
xf -= screenRect.origin.x;
|
||||
yf -= screenRect.origin.y;
|
||||
|
||||
//Quartz Display Services uses the old coordinates (top left origin)
|
||||
yf = screenRect.size.height -yf;
|
||||
|
||||
CGDisplayMoveCursorToPoint((CGDirectDisplayID)[[[windowScreen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue], CGPointMake(xf, yf));
|
||||
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) const
|
||||
{
|
||||
keys.set(GHOST_kModifierKeyOS, (m_modifierMask & NSCommandKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftAlt, (m_modifierMask & NSAlternateKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftShift, (m_modifierMask & NSShiftKeyMask) ? true : false);
|
||||
keys.set(GHOST_kModifierKeyLeftControl, (m_modifierMask & 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;
|
||||
}*/
|
||||
|
||||
do {
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
if (event==nil) {
|
||||
[pool drain];
|
||||
break;
|
||||
}
|
||||
|
||||
anyProcessed = true;
|
||||
|
||||
switch ([event type]) {
|
||||
case NSKeyDown:
|
||||
case NSKeyUp:
|
||||
case NSFlagsChanged:
|
||||
handleKeyEvent(event);
|
||||
|
||||
/* Support system-wide keyboard shortcuts, like Exposé, ...) =>included in always NSApp sendEvent */
|
||||
/* 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:
|
||||
case NSEventTypeMagnify:
|
||||
case NSEventTypeRotate:
|
||||
case NSEventTypeBeginGesture:
|
||||
case NSEventTypeEndGesture:
|
||||
handleMouseEvent(event);
|
||||
break;
|
||||
|
||||
case NSTabletPoint:
|
||||
case NSTabletProximity:
|
||||
handleTabletEvent(event,[event type]);
|
||||
break;
|
||||
|
||||
/* Trackpad features, fired only from OS X 10.5.2
|
||||
case NSEventTypeGesture:
|
||||
case NSEventTypeSwipe:
|
||||
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];
|
||||
[pool drain];
|
||||
} while (event!= nil);
|
||||
//} while (waitForEvent && !anyProcessed); Needed only for timer implementation
|
||||
|
||||
if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent();
|
||||
|
||||
if (m_outsideLoopEventProcessed) {
|
||||
m_outsideLoopEventProcessed = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_ignoreWindowSizedMessages = false;
|
||||
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
//Note: called from NSApplication delegate
|
||||
GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent()
|
||||
{
|
||||
//Update the modifiers key mask, as its status may have changed when the application was not active
|
||||
//(that is when update events are sent to another application)
|
||||
unsigned int modifiers;
|
||||
GHOST_IWindow* window = m_windowManager->getActiveWindow();
|
||||
|
||||
if (!window) {
|
||||
m_needDelayedApplicationBecomeActiveEventProcessing = true;
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
else m_needDelayedApplicationBecomeActiveEventProcessing = false;
|
||||
|
||||
modifiers = [[[NSApplication sharedApplication] currentEvent] 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_kKeyOS) );
|
||||
}
|
||||
|
||||
m_modifierMask = modifiers;
|
||||
|
||||
m_outsideLoopEventProcessed = true;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
//Note: called from NSWindow delegate
|
||||
GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window)
|
||||
{
|
||||
if (!validWindow(window)) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
switch(eventType)
|
||||
{
|
||||
case GHOST_kEventWindowClose:
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) );
|
||||
break;
|
||||
case GHOST_kEventWindowActivate:
|
||||
m_windowManager->setActiveWindow(window);
|
||||
window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) );
|
||||
break;
|
||||
case GHOST_kEventWindowDeactivate:
|
||||
m_windowManager->setWindowInactive(window);
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) );
|
||||
break;
|
||||
case GHOST_kEventWindowUpdate:
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) );
|
||||
break;
|
||||
case GHOST_kEventWindowMove:
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) );
|
||||
break;
|
||||
case GHOST_kEventWindowSize:
|
||||
if (!m_ignoreWindowSizedMessages)
|
||||
{
|
||||
//Enforce only one resize message per event loop (coalescing all the live resize messages)
|
||||
window->updateDrawingContext();
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
|
||||
//Mouse up event is trapped by the resizing event loop, so send it anyway to the window manager
|
||||
pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonUp, window, convertButton(0)));
|
||||
m_ignoreWindowSizedMessages = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return GHOST_kFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
m_outsideLoopEventProcessed = true;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
//Note: called from NSWindow subclass
|
||||
GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType,
|
||||
GHOST_WindowCocoa* window, int mouseX, int mouseY, void* data)
|
||||
{
|
||||
if (!validWindow(window)) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
switch(eventType)
|
||||
{
|
||||
case GHOST_kEventDraggingEntered:
|
||||
case GHOST_kEventDraggingUpdated:
|
||||
case GHOST_kEventDraggingExited:
|
||||
pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,NULL));
|
||||
break;
|
||||
|
||||
case GHOST_kEventDraggingDropDone:
|
||||
{
|
||||
GHOST_TUns8 * temp_buff;
|
||||
GHOST_TStringArray *strArray;
|
||||
NSArray *droppedArray;
|
||||
size_t pastedTextSize;
|
||||
NSString *droppedStr;
|
||||
GHOST_TEventDataPtr eventData;
|
||||
int i;
|
||||
|
||||
if (!data) return GHOST_kFailure;
|
||||
|
||||
switch (draggedObjectType) {
|
||||
case GHOST_kDragnDropTypeFilenames:
|
||||
droppedArray = (NSArray*)data;
|
||||
|
||||
strArray = (GHOST_TStringArray*)malloc(sizeof(GHOST_TStringArray));
|
||||
if (!strArray) return GHOST_kFailure;
|
||||
|
||||
strArray->count = [droppedArray count];
|
||||
if (strArray->count == 0) return GHOST_kFailure;
|
||||
|
||||
strArray->strings = (GHOST_TUns8**) malloc(strArray->count*sizeof(GHOST_TUns8*));
|
||||
|
||||
for (i=0;i<strArray->count;i++)
|
||||
{
|
||||
droppedStr = [droppedArray objectAtIndex:i];
|
||||
|
||||
pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1);
|
||||
|
||||
if (!temp_buff) {
|
||||
strArray->count = i;
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy((char*)temp_buff, [droppedStr cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize);
|
||||
temp_buff[pastedTextSize] = '\0';
|
||||
|
||||
strArray->strings[i] = temp_buff;
|
||||
}
|
||||
|
||||
eventData = (GHOST_TEventDataPtr) strArray;
|
||||
break;
|
||||
|
||||
case GHOST_kDragnDropTypeString:
|
||||
droppedStr = (NSString*)data;
|
||||
pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1);
|
||||
|
||||
if (temp_buff == NULL) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
strncpy((char*)temp_buff, [droppedStr cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize);
|
||||
|
||||
temp_buff[pastedTextSize] = '\0';
|
||||
|
||||
eventData = (GHOST_TEventDataPtr) temp_buff;
|
||||
break;
|
||||
|
||||
case GHOST_kDragnDropTypeBitmap:
|
||||
{
|
||||
NSImage *droppedImg = (NSImage*)data;
|
||||
NSSize imgSize = [droppedImg size];
|
||||
ImBuf *ibuf = NULL;
|
||||
GHOST_TUns8 *rasterRGB = NULL;
|
||||
GHOST_TUns8 *rasterRGBA = NULL;
|
||||
GHOST_TUns8 *toIBuf = NULL;
|
||||
int x, y, to_i, from_i;
|
||||
NSBitmapImageRep *blBitmapFormatImageRGB,*blBitmapFormatImageRGBA,*bitmapImage=nil;
|
||||
NSEnumerator *enumerator;
|
||||
NSImageRep *representation;
|
||||
|
||||
ibuf = IMB_allocImBuf (imgSize.width , imgSize.height, 32, IB_rect);
|
||||
if (!ibuf) {
|
||||
[droppedImg release];
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
/*Get the bitmap of the image*/
|
||||
enumerator = [[droppedImg representations] objectEnumerator];
|
||||
while ((representation = [enumerator nextObject])) {
|
||||
if ([representation isKindOfClass:[NSBitmapImageRep class]]) {
|
||||
bitmapImage = (NSBitmapImageRep *)representation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bitmapImage == nil) return GHOST_kFailure;
|
||||
|
||||
if (([bitmapImage bitsPerPixel] == 32) && (([bitmapImage bitmapFormat] & 0x5) == 0)
|
||||
&& ![bitmapImage isPlanar]) {
|
||||
/* Try a fast copy if the image is a meshed RGBA 32bit bitmap*/
|
||||
toIBuf = (GHOST_TUns8*)ibuf->rect;
|
||||
rasterRGB = (GHOST_TUns8*)[bitmapImage bitmapData];
|
||||
for (y = 0; y < imgSize.height; y++) {
|
||||
to_i = (imgSize.height-y-1)*imgSize.width;
|
||||
from_i = y*imgSize.width;
|
||||
memcpy(toIBuf+4*to_i, rasterRGB+4*from_i, 4*imgSize.width);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Tell cocoa image resolution is same as current system one */
|
||||
[bitmapImage setSize:imgSize];
|
||||
|
||||
/* Convert the image in a RGBA 32bit format */
|
||||
/* As Core Graphics does not support contextes with non premutliplied alpha,
|
||||
we need to get alpha key values in a separate batch */
|
||||
|
||||
/* First get RGB values w/o Alpha to avoid pre-multiplication, 32bit but last byte is unused */
|
||||
blBitmapFormatImageRGB = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
|
||||
pixelsWide:imgSize.width
|
||||
pixelsHigh:imgSize.height
|
||||
bitsPerSample:8 samplesPerPixel:3 hasAlpha:NO isPlanar:NO
|
||||
colorSpaceName:NSDeviceRGBColorSpace
|
||||
bitmapFormat:(NSBitmapFormat)0
|
||||
bytesPerRow:4*imgSize.width
|
||||
bitsPerPixel:32/*RGB format padded to 32bits*/];
|
||||
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:blBitmapFormatImageRGB]];
|
||||
[bitmapImage draw];
|
||||
[NSGraphicsContext restoreGraphicsState];
|
||||
|
||||
rasterRGB = (GHOST_TUns8*)[blBitmapFormatImageRGB bitmapData];
|
||||
if (rasterRGB == NULL) {
|
||||
[bitmapImage release];
|
||||
[blBitmapFormatImageRGB release];
|
||||
[droppedImg release];
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
/* Then get Alpha values by getting the RGBA image (that is premultiplied btw) */
|
||||
blBitmapFormatImageRGBA = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
|
||||
pixelsWide:imgSize.width
|
||||
pixelsHigh:imgSize.height
|
||||
bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO
|
||||
colorSpaceName:NSDeviceRGBColorSpace
|
||||
bitmapFormat:(NSBitmapFormat)0
|
||||
bytesPerRow:4*imgSize.width
|
||||
bitsPerPixel:32/* RGBA */];
|
||||
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:blBitmapFormatImageRGBA]];
|
||||
[bitmapImage draw];
|
||||
[NSGraphicsContext restoreGraphicsState];
|
||||
|
||||
rasterRGBA = (GHOST_TUns8*)[blBitmapFormatImageRGBA bitmapData];
|
||||
if (rasterRGBA == NULL) {
|
||||
[bitmapImage release];
|
||||
[blBitmapFormatImageRGB release];
|
||||
[blBitmapFormatImageRGBA release];
|
||||
[droppedImg release];
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
/*Copy the image to ibuf, flipping it vertically*/
|
||||
toIBuf = (GHOST_TUns8*)ibuf->rect;
|
||||
for (y = 0; y < imgSize.height; y++) {
|
||||
for (x = 0; x < imgSize.width; x++) {
|
||||
to_i = (imgSize.height-y-1)*imgSize.width + x;
|
||||
from_i = y*imgSize.width + x;
|
||||
|
||||
toIBuf[4*to_i] = rasterRGB[4*from_i]; /* R */
|
||||
toIBuf[4*to_i+1] = rasterRGB[4*from_i+1]; /* G */
|
||||
toIBuf[4*to_i+2] = rasterRGB[4*from_i+2]; /* B */
|
||||
toIBuf[4*to_i+3] = rasterRGBA[4*from_i+3]; /* A */
|
||||
}
|
||||
}
|
||||
|
||||
[blBitmapFormatImageRGB release];
|
||||
[blBitmapFormatImageRGBA release];
|
||||
[droppedImg release];
|
||||
}
|
||||
|
||||
eventData = (GHOST_TEventDataPtr) ibuf;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return GHOST_kFailure;
|
||||
break;
|
||||
}
|
||||
pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,eventData));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
m_outsideLoopEventProcessed = true;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
|
||||
{
|
||||
GHOST_Window* window = (GHOST_Window*)m_windowManager->getActiveWindow();
|
||||
|
||||
//Discard quit event if we are in cursor grab sequence
|
||||
if (window && (window->getCursorGrabMode() != GHOST_kGrabDisable) && (window->getCursorGrabMode() != GHOST_kGrabNormal))
|
||||
return GHOST_kExitCancel;
|
||||
|
||||
//Check open windows if some changes are not saved
|
||||
if (m_windowManager->getAnyModifiedState())
|
||||
{
|
||||
int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved.\nDo you really want to quit ?",
|
||||
@"Cancel", @"Quit Anyway", nil);
|
||||
if (shouldQuit == NSAlertAlternateReturn)
|
||||
{
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) );
|
||||
return GHOST_kExitNow;
|
||||
} else {
|
||||
//Give back focus to the blender window if user selected cancel quit
|
||||
NSArray *windowsList = [NSApp orderedWindows];
|
||||
if ([windowsList count]) {
|
||||
[[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
|
||||
//Handle the modifiers keyes changed state issue
|
||||
//as recovering from the quit dialog is like application
|
||||
//gaining focus back.
|
||||
//Main issue fixed is Cmd modifier not being cleared
|
||||
handleApplicationBecomeActiveEvent();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) );
|
||||
m_outsideLoopEventProcessed = true;
|
||||
return GHOST_kExitNow;
|
||||
}
|
||||
|
||||
return GHOST_kExitCancel;
|
||||
}
|
||||
|
||||
bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr)
|
||||
{
|
||||
NSString *filepath = (NSString*)filepathStr;
|
||||
int confirmOpen = NSAlertAlternateReturn;
|
||||
NSArray *windowsList;
|
||||
char * temp_buff;
|
||||
size_t filenameTextSize;
|
||||
GHOST_Window* window= (GHOST_Window*)m_windowManager->getActiveWindow();
|
||||
|
||||
if (!window) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
//Discard event if we are in cursor grab sequence, it'll lead to "stuck cursor" situation if the alert panel is raised
|
||||
if (window && (window->getCursorGrabMode() != GHOST_kGrabDisable) && (window->getCursorGrabMode() != GHOST_kGrabNormal))
|
||||
return GHOST_kExitCancel;
|
||||
|
||||
//Check open windows if some changes are not saved
|
||||
if (m_windowManager->getAnyModifiedState())
|
||||
{
|
||||
confirmOpen = NSRunAlertPanel([NSString stringWithFormat:@"Opening %@",[filepath lastPathComponent]],
|
||||
@"Current document has not been saved.\nDo you really want to proceed?",
|
||||
@"Cancel", @"Open", nil);
|
||||
}
|
||||
|
||||
//Give back focus to the blender window
|
||||
windowsList = [NSApp orderedWindows];
|
||||
if ([windowsList count]) {
|
||||
[[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
if (confirmOpen == NSAlertAlternateReturn)
|
||||
{
|
||||
filenameTextSize = [filepath lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
temp_buff = (char*) malloc(filenameTextSize+1);
|
||||
|
||||
if (temp_buff == NULL) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
strncpy(temp_buff, [filepath cStringUsingEncoding:NSUTF8StringEncoding], filenameTextSize);
|
||||
|
||||
temp_buff[filenameTextSize] = '\0';
|
||||
|
||||
pushEvent(new GHOST_EventString(getMilliSeconds(),GHOST_kEventOpenMainFile,window,(GHOST_TEventDataPtr) temp_buff));
|
||||
|
||||
return YES;
|
||||
}
|
||||
else return NO;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventType)
|
||||
{
|
||||
NSEvent *event = (NSEvent *)eventPtr;
|
||||
GHOST_IWindow* window;
|
||||
|
||||
window = m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
|
||||
if (!window) {
|
||||
//printf("\nW failure for event 0x%x",[event type]);
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TabletData& ct=((GHOST_WindowCocoa*)window)->GetCocoaTabletData();
|
||||
|
||||
switch (eventType) {
|
||||
case NSTabletPoint:
|
||||
ct.Pressure = [event pressure];
|
||||
ct.Xtilt = [event tilt].x;
|
||||
ct.Ytilt = [event tilt].y;
|
||||
break;
|
||||
|
||||
case NSTabletProximity:
|
||||
ct.Pressure = 0;
|
||||
ct.Xtilt = 0;
|
||||
ct.Ytilt = 0;
|
||||
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");
|
||||
return GHOST_kFailure;
|
||||
break;
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
|
||||
{
|
||||
NSEvent *event = (NSEvent *)eventPtr;
|
||||
GHOST_Window* window;
|
||||
|
||||
window = (GHOST_Window*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
|
||||
if (!window) {
|
||||
//printf("\nW failure for event 0x%x",[event type]);
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
switch ([event type])
|
||||
{
|
||||
case NSLeftMouseDown:
|
||||
case NSRightMouseDown:
|
||||
case NSOtherMouseDown:
|
||||
pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber])));
|
||||
//Handle tablet events combined with mouse events
|
||||
switch ([event subtype]) {
|
||||
case NX_SUBTYPE_TABLET_POINT:
|
||||
handleTabletEvent(eventPtr, NSTabletPoint);
|
||||
break;
|
||||
case NX_SUBTYPE_TABLET_PROXIMITY:
|
||||
handleTabletEvent(eventPtr, NSTabletProximity);
|
||||
break;
|
||||
default:
|
||||
//No tablet event included : do nothing
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case NSLeftMouseUp:
|
||||
case NSRightMouseUp:
|
||||
case NSOtherMouseUp:
|
||||
pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber])));
|
||||
//Handle tablet events combined with mouse events
|
||||
switch ([event subtype]) {
|
||||
case NX_SUBTYPE_TABLET_POINT:
|
||||
handleTabletEvent(eventPtr, NSTabletPoint);
|
||||
break;
|
||||
case NX_SUBTYPE_TABLET_PROXIMITY:
|
||||
handleTabletEvent(eventPtr, NSTabletProximity);
|
||||
break;
|
||||
default:
|
||||
//No tablet event included : do nothing
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case NSLeftMouseDragged:
|
||||
case NSRightMouseDragged:
|
||||
case NSOtherMouseDragged:
|
||||
//Handle tablet events combined with mouse events
|
||||
switch ([event subtype]) {
|
||||
case NX_SUBTYPE_TABLET_POINT:
|
||||
handleTabletEvent(eventPtr, NSTabletPoint);
|
||||
break;
|
||||
case NX_SUBTYPE_TABLET_PROXIMITY:
|
||||
handleTabletEvent(eventPtr, NSTabletProximity);
|
||||
break;
|
||||
default:
|
||||
//No tablet event included : do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
case NSMouseMoved:
|
||||
switch (window->getCursorGrabMode()) {
|
||||
case GHOST_kGrabHide: //Cursor hidden grab operation : no cursor move
|
||||
{
|
||||
GHOST_TInt32 x_warp, y_warp, x_accum, y_accum;
|
||||
|
||||
window->getCursorGrabInitPos(x_warp, y_warp);
|
||||
|
||||
window->getCursorGrabAccum(x_accum, y_accum);
|
||||
x_accum += [event deltaX];
|
||||
y_accum += -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ...
|
||||
window->setCursorGrabAccum(x_accum, y_accum);
|
||||
|
||||
pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum));
|
||||
}
|
||||
break;
|
||||
case GHOST_kGrabWrap: //Wrap cursor at area/window boundaries
|
||||
{
|
||||
NSPoint mousePos = [event locationInWindow];
|
||||
GHOST_TInt32 x_mouse= mousePos.x;
|
||||
GHOST_TInt32 y_mouse= mousePos.y;
|
||||
GHOST_TInt32 x_accum, y_accum, x_cur, y_cur;
|
||||
GHOST_Rect bounds, windowBounds, correctedBounds;
|
||||
|
||||
/* fallback to window bounds */
|
||||
if(window->getCursorGrabBounds(bounds)==GHOST_kFailure)
|
||||
window->getClientBounds(bounds);
|
||||
|
||||
//Switch back to Cocoa coordinates orientation (y=0 at botton,the same as blender internal btw!), and to client coordinates
|
||||
window->getClientBounds(windowBounds);
|
||||
window->screenToClient(bounds.m_l,bounds.m_b, correctedBounds.m_l, correctedBounds.m_t);
|
||||
window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_b);
|
||||
correctedBounds.m_b = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_b;
|
||||
correctedBounds.m_t = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_t;
|
||||
|
||||
//Update accumulation counts
|
||||
window->getCursorGrabAccum(x_accum, y_accum);
|
||||
x_accum += [event deltaX]-m_cursorDelta_x;
|
||||
y_accum += -[event deltaY]-m_cursorDelta_y; //Strange Apple implementation (inverted coordinates for the deltaY) ...
|
||||
window->setCursorGrabAccum(x_accum, y_accum);
|
||||
|
||||
|
||||
//Warp mouse cursor if needed
|
||||
x_mouse += [event deltaX]-m_cursorDelta_x;
|
||||
y_mouse += -[event deltaY]-m_cursorDelta_y;
|
||||
correctedBounds.wrapPoint(x_mouse, y_mouse, 2);
|
||||
|
||||
//Compensate for mouse moved event taking cursor position set into account
|
||||
m_cursorDelta_x = x_mouse-mousePos.x;
|
||||
m_cursorDelta_y = y_mouse-mousePos.y;
|
||||
|
||||
//Set new cursor position
|
||||
window->clientToScreen(x_mouse, y_mouse, x_cur, y_cur);
|
||||
setMouseCursorPosition(x_cur, y_cur); /* wrap */
|
||||
|
||||
//Post event
|
||||
window->getCursorGrabInitPos(x_cur, y_cur);
|
||||
pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_cur + x_accum, y_cur + y_accum));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
//Normal cursor operation: send mouse position in window
|
||||
NSPoint mousePos = [event locationInWindow];
|
||||
pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, mousePos.x, mousePos.y));
|
||||
m_cursorDelta_x=0;
|
||||
m_cursorDelta_y=0; //Mouse motion occurred between two cursor warps, so we can reset the delta counter
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case NSScrollWheel:
|
||||
{
|
||||
/* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */
|
||||
if (!m_hasMultiTouchTrackpad || !m_isGestureInProgress) {
|
||||
GHOST_TInt32 delta;
|
||||
|
||||
double deltaF = [event deltaY];
|
||||
if (deltaF == 0.0) break; //discard trackpad delta=0 events
|
||||
|
||||
delta = deltaF > 0.0 ? 1 : -1;
|
||||
pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta));
|
||||
}
|
||||
else {
|
||||
NSPoint mousePos = [event locationInWindow];
|
||||
double dx = [event deltaX];
|
||||
double dy = -[event deltaY];
|
||||
|
||||
const double deltaMax = 50.0;
|
||||
|
||||
if ((dx == 0) && (dy == 0)) break;
|
||||
|
||||
/* Quadratic acceleration */
|
||||
dx = dx*(fabs(dx)+0.5);
|
||||
if (dx<0.0) dx-=0.5; else dx+=0.5;
|
||||
if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax;
|
||||
|
||||
dy = dy*(fabs(dy)+0.5);
|
||||
if (dy<0.0) dy-=0.5; else dy+=0.5;
|
||||
if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax;
|
||||
|
||||
pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, mousePos.x, mousePos.y, dx, dy));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NSEventTypeMagnify:
|
||||
{
|
||||
NSPoint mousePos = [event locationInWindow];
|
||||
pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y,
|
||||
[event magnification]*250.0 + 0.1, 0));
|
||||
}
|
||||
break;
|
||||
|
||||
case NSEventTypeRotate:
|
||||
{
|
||||
NSPoint mousePos = [event locationInWindow];
|
||||
pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y,
|
||||
-[event rotation] * 5.0, 0));
|
||||
}
|
||||
case NSEventTypeBeginGesture:
|
||||
m_isGestureInProgress = true;
|
||||
break;
|
||||
case NSEventTypeEndGesture:
|
||||
m_isGestureInProgress = false;
|
||||
break;
|
||||
default:
|
||||
return GHOST_kFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
|
||||
{
|
||||
NSEvent *event = (NSEvent *)eventPtr;
|
||||
GHOST_IWindow* window;
|
||||
unsigned int modifiers;
|
||||
NSString *characters;
|
||||
NSData *convertedCharacters;
|
||||
GHOST_TKey keyCode;
|
||||
unsigned char ascii;
|
||||
NSString* charsIgnoringModifiers;
|
||||
|
||||
window = m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]);
|
||||
if (!window) {
|
||||
//printf("\nW failure for event 0x%x",[event type]);
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
switch ([event type]) {
|
||||
case NSKeyDown:
|
||||
case NSKeyUp:
|
||||
charsIgnoringModifiers = [event charactersIgnoringModifiers];
|
||||
if ([charsIgnoringModifiers length]>0)
|
||||
keyCode = convertKey([event keyCode],
|
||||
[charsIgnoringModifiers characterAtIndex:0],
|
||||
[event type] == NSKeyDown?kUCKeyActionDown:kUCKeyActionUp);
|
||||
else
|
||||
keyCode = convertKey([event keyCode],0,
|
||||
[event type] == NSKeyDown?kUCKeyActionDown:kUCKeyActionUp);
|
||||
|
||||
|
||||
characters = [event characters];
|
||||
if ([characters length]>0) { //Check for dead keys
|
||||
//Convert characters to iso latin 1 encoding
|
||||
convertedCharacters = [characters dataUsingEncoding:NSISOLatin1StringEncoding];
|
||||
if ([convertedCharacters length]>0)
|
||||
ascii =((char*)[convertedCharacters bytes])[0];
|
||||
else
|
||||
ascii = 0; //Character not available in iso latin 1 encoding
|
||||
}
|
||||
else
|
||||
ascii= 0;
|
||||
|
||||
if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask))
|
||||
break; //Cmd-Q is directly handled by Cocoa
|
||||
|
||||
if ([event type] == NSKeyDown) {
|
||||
pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyDown, window, keyCode, ascii) );
|
||||
//printf("\nKey down rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii);
|
||||
} else {
|
||||
pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyUp, window, keyCode, ascii) );
|
||||
//printf("\nKey up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii);
|
||||
}
|
||||
break;
|
||||
|
||||
case NSFlagsChanged:
|
||||
modifiers = [event modifierFlags];
|
||||
|
||||
if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) );
|
||||
}
|
||||
if ((modifiers & NSControlKeyMask) != (m_modifierMask & NSControlKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSControlKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) );
|
||||
}
|
||||
if ((modifiers & NSAlternateKeyMask) != (m_modifierMask & NSAlternateKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSAlternateKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) );
|
||||
}
|
||||
if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) {
|
||||
pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyOS) );
|
||||
}
|
||||
|
||||
m_modifierMask = modifiers;
|
||||
break;
|
||||
|
||||
default:
|
||||
return GHOST_kFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark Clipboard get/set
|
||||
|
||||
GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const
|
||||
{
|
||||
GHOST_TUns8 * temp_buff;
|
||||
size_t pastedTextSize;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
|
||||
|
||||
if (pasteBoard == nil) {
|
||||
[pool drain];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSArray *supportedTypes =
|
||||
[NSArray arrayWithObjects: NSStringPboardType, nil];
|
||||
|
||||
NSString *bestType = [[NSPasteboard generalPasteboard]
|
||||
availableTypeFromArray:supportedTypes];
|
||||
|
||||
if (bestType == nil) {
|
||||
[pool drain];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSString * textPasted = [pasteBoard stringForType:NSStringPboardType];
|
||||
|
||||
if (textPasted == nil) {
|
||||
[pool drain];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding];
|
||||
|
||||
temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1);
|
||||
|
||||
if (temp_buff == NULL) {
|
||||
[pool drain];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy((char*)temp_buff, [textPasted cStringUsingEncoding:NSISOLatin1StringEncoding], pastedTextSize);
|
||||
|
||||
temp_buff[pastedTextSize] = '\0';
|
||||
|
||||
[pool drain];
|
||||
|
||||
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
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
|
||||
|
||||
if (pasteBoard == nil) {
|
||||
[pool drain];
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray *supportedTypes = [NSArray arrayWithObject:NSStringPboardType];
|
||||
|
||||
[pasteBoard declareTypes:supportedTypes owner:nil];
|
||||
|
||||
textToCopy = [NSString stringWithCString:buffer encoding:NSISOLatin1StringEncoding];
|
||||
|
||||
[pasteBoard setString:textToCopy forType:NSStringPboardType];
|
||||
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
84
intern/ghost/intern/GHOST_SystemPaths.h
Normal file
84
intern/ghost/intern/GHOST_SystemPaths.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_SystemPaths.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_SYSTEMPATHS_H_
|
||||
#define _GHOST_SYSTEMPATHS_H_
|
||||
|
||||
#include "GHOST_ISystemPaths.h"
|
||||
|
||||
class GHOST_SystemPaths : public GHOST_ISystemPaths
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* Constructor.
|
||||
* Protected default constructor to force use of static createSystem member.
|
||||
*/
|
||||
GHOST_SystemPaths(){};
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* Protected default constructor to force use of static dispose member.
|
||||
*/
|
||||
virtual ~GHOST_SystemPaths(){};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Determine the base dir in which shared resources are located. It will first try to use
|
||||
* "unpack and run" path, then look for properly installed path, not including versioning.
|
||||
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
|
||||
*/
|
||||
virtual const GHOST_TUns8* getSystemDir() const = 0;
|
||||
|
||||
/**
|
||||
* Determine the base dir in which user configuration is stored, not including versioning.
|
||||
* If needed, it will create the base directory.
|
||||
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
|
||||
*/
|
||||
virtual const GHOST_TUns8* getUserDir() const = 0;
|
||||
|
||||
/**
|
||||
* Determine the directory of the current binary
|
||||
* @return Unsigned char string pointing to the binary dir
|
||||
*/
|
||||
virtual const GHOST_TUns8* getBinaryDir() const = 0;
|
||||
|
||||
/**
|
||||
* Add the file to the operating system most recently used files
|
||||
*/
|
||||
virtual void addToSystemRecentFiles(const char* filename) const = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
88
intern/ghost/intern/GHOST_SystemPathsCarbon.cpp
Normal file
88
intern/ghost/intern/GHOST_SystemPathsCarbon.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2009 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Damien Plisson 2010
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_SystemPathsCarbon.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include "GHOST_SystemPathsCarbon.h"
|
||||
|
||||
|
||||
/***/
|
||||
|
||||
GHOST_SystemPathsCarbon::GHOST_SystemPathsCarbon()
|
||||
{
|
||||
}
|
||||
|
||||
GHOST_SystemPathsCarbon::~GHOST_SystemPathsCarbon()
|
||||
{
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsCarbon::getSystemDir() const
|
||||
{
|
||||
return (GHOST_TUns8*)"/Library/Application Support";
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsCarbon::getUserDir() const
|
||||
{
|
||||
static char usrPath[256] = "";
|
||||
char* env = getenv("HOME");
|
||||
|
||||
if (env) {
|
||||
strncpy(usrPath, env, 245);
|
||||
usrPath[245]=0;
|
||||
strcat(usrPath, "/Library/Application Support");
|
||||
return (GHOST_TUns8*) usrPath;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsCarbon::getBinaryDir() const
|
||||
{
|
||||
CFURLRef bundleURL;
|
||||
CFStringRef pathStr;
|
||||
static char path[256];
|
||||
CFBundleRef mainBundle = CFBundleGetMainBundle();
|
||||
|
||||
bundleURL = CFBundleCopyBundleURL(mainBundle);
|
||||
pathStr = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
|
||||
CFStringGetCString(pathStr, path, 255, kCFStringEncodingASCII);
|
||||
CFRelease(pathStr);
|
||||
CFRelease(bundleURL);
|
||||
return (GHOST_TUns8*)path;
|
||||
}
|
||||
|
||||
void GHOST_SystemPathsCarbon::addToSystemRecentFiles(const char* filename) const
|
||||
{
|
||||
/* XXXXX TODO: Implementation for Carbon if possible */
|
||||
|
||||
}
|
||||
92
intern/ghost/intern/GHOST_SystemPathsCarbon.h
Normal file
92
intern/ghost/intern/GHOST_SystemPathsCarbon.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Damien Plisson 2010
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_SystemPathsCarbon.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GHOST_SYSTEM_PATHS_CARBON_H_
|
||||
#define _GHOST_SYSTEM_PATHS_CARBON_H_
|
||||
|
||||
#ifndef __APPLE__
|
||||
#error Apple OSX only!
|
||||
#endif // __APPLE__
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include "GHOST_SystemPaths.h"
|
||||
|
||||
/**
|
||||
* OSX/Carbon Implementation of GHOST_SystemPaths class.
|
||||
* @see GHOST_System.
|
||||
* @author Andrea Weikert
|
||||
* @date Aug 1, 2010
|
||||
*/
|
||||
class GHOST_SystemPathsCarbon : public GHOST_SystemPaths {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_SystemPathsCarbon();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~GHOST_SystemPathsCarbon();
|
||||
|
||||
/**
|
||||
* Determine the base dir in which shared resources are located. It will first try to use
|
||||
* "unpack and run" path, then look for properly installed path, not including versioning.
|
||||
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
|
||||
*/
|
||||
virtual const GHOST_TUns8* getSystemDir() const;
|
||||
|
||||
/**
|
||||
* Determine the base dir in which user configuration is stored, not including versioning.
|
||||
* If needed, it will create the base directory.
|
||||
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
|
||||
*/
|
||||
virtual const GHOST_TUns8* getUserDir() const;
|
||||
|
||||
/**
|
||||
* Determine the directory of the current binary
|
||||
* @return Unsigned char string pointing to the binary dir
|
||||
*/
|
||||
virtual const GHOST_TUns8* getBinaryDir() const;
|
||||
|
||||
/**
|
||||
* Add the file to the operating system most recently used files
|
||||
*/
|
||||
void addToSystemRecentFiles(const char* filename) const;
|
||||
};
|
||||
|
||||
#endif // _GHOST_SYSTEM_CARBON_H_
|
||||
|
||||
|
||||
|
||||
84
intern/ghost/intern/GHOST_SystemPathsCocoa.h
Normal file
84
intern/ghost/intern/GHOST_SystemPathsCocoa.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Damien Plisson 2010
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_SystemPathsCocoa.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GHOST_SYSTEM_PATHS_COCOA_H_
|
||||
#define _GHOST_SYSTEM_PATHS_COCOA_H_
|
||||
|
||||
#ifndef __APPLE__
|
||||
#error Apple OSX only!
|
||||
#endif // __APPLE__
|
||||
|
||||
|
||||
#include "GHOST_SystemPaths.h"
|
||||
|
||||
|
||||
class GHOST_SystemPathsCocoa : public GHOST_SystemPaths {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_SystemPathsCocoa();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~GHOST_SystemPathsCocoa();
|
||||
|
||||
/**
|
||||
* Determine the base dir in which shared resources are located. It will first try to use
|
||||
* "unpack and run" path, then look for properly installed path, not including versioning.
|
||||
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
|
||||
*/
|
||||
virtual const GHOST_TUns8* getSystemDir() const;
|
||||
|
||||
/**
|
||||
* Determine the base dir in which user configuration is stored, not including versioning.
|
||||
* If needed, it will create the base directory.
|
||||
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
|
||||
*/
|
||||
virtual const GHOST_TUns8* getUserDir() const;
|
||||
|
||||
/**
|
||||
* Determine the directory of the current binary
|
||||
* @return Unsigned char string pointing to the binary dir
|
||||
*/
|
||||
virtual const GHOST_TUns8* getBinaryDir() const;
|
||||
|
||||
/**
|
||||
* Add the file to the operating system most recently used files
|
||||
*/
|
||||
void addToSystemRecentFiles(const char* filename) const;
|
||||
};
|
||||
|
||||
#endif // _GHOST_SYSTEM_COCOA_H_
|
||||
|
||||
121
intern/ghost/intern/GHOST_SystemPathsCocoa.mm
Normal file
121
intern/ghost/intern/GHOST_SystemPathsCocoa.mm
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Damien Plisson 2010
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
/*For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible)*/
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include "GHOST_SystemPathsCocoa.h"
|
||||
|
||||
|
||||
#pragma mark initialization/finalization
|
||||
|
||||
|
||||
GHOST_SystemPathsCocoa::GHOST_SystemPathsCocoa()
|
||||
{
|
||||
}
|
||||
|
||||
GHOST_SystemPathsCocoa::~GHOST_SystemPathsCocoa()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
#pragma mark Base directories retrieval
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsCocoa::getSystemDir() const
|
||||
{
|
||||
static GHOST_TUns8 tempPath[512] = "";
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSString *basePath;
|
||||
NSArray *paths;
|
||||
|
||||
paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSLocalDomainMask, YES);
|
||||
|
||||
if ([paths count] > 0)
|
||||
basePath = [paths objectAtIndex:0];
|
||||
else {
|
||||
[pool drain];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);
|
||||
|
||||
[pool drain];
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsCocoa::getUserDir() const
|
||||
{
|
||||
static GHOST_TUns8 tempPath[512] = "";
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSString *basePath;
|
||||
NSArray *paths;
|
||||
|
||||
paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
|
||||
if ([paths count] > 0)
|
||||
basePath = [paths objectAtIndex:0];
|
||||
else {
|
||||
[pool drain];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);
|
||||
|
||||
[pool drain];
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsCocoa::getBinaryDir() const
|
||||
{
|
||||
static GHOST_TUns8 tempPath[512] = "";
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSString *basePath;
|
||||
|
||||
basePath = [[NSBundle mainBundle] bundlePath];
|
||||
|
||||
if (basePath == nil) {
|
||||
[pool drain];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]);
|
||||
|
||||
[pool drain];
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
void GHOST_SystemPathsCocoa::addToSystemRecentFiles(const char* filename) const
|
||||
{
|
||||
/* XXXXX TODO: Implementation for X11 if possible */
|
||||
}
|
||||
115
intern/ghost/intern/GHOST_SystemPathsWin32.cpp
Normal file
115
intern/ghost/intern/GHOST_SystemPathsWin32.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2011 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
* Andrea Weikert
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_SystemPathsWin32.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include "GHOST_SystemPathsWin32.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#ifdef _WIN32_IE
|
||||
#undef _WIN32_IE
|
||||
#endif
|
||||
#define _WIN32_IE 0x0501
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
|
||||
#if !defined(SHARD_PIDL)
|
||||
#define SHARD_PIDL 0x00000001L
|
||||
#endif
|
||||
|
||||
#if !defined(SHARD_PATHA)
|
||||
#define SHARD_PATHA 0x00000002L
|
||||
#endif
|
||||
|
||||
#if !defined(SHARD_PATHA)
|
||||
#define SHARD_PATHW 0x00000003L
|
||||
#endif
|
||||
|
||||
#if !defined(SHARD_PATH)
|
||||
#ifdef UNICODE
|
||||
#define SHARD_PATH SHARD_PATHW
|
||||
#else
|
||||
#define SHARD_PATH SHARD_PATHA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
GHOST_SystemPathsWin32::GHOST_SystemPathsWin32()
|
||||
{
|
||||
}
|
||||
|
||||
GHOST_SystemPathsWin32::~GHOST_SystemPathsWin32()
|
||||
{
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsWin32::getSystemDir() const
|
||||
{
|
||||
static char knownpath[MAX_PATH];
|
||||
HRESULT hResult = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath);
|
||||
|
||||
if (hResult == S_OK)
|
||||
{
|
||||
return (GHOST_TUns8*)knownpath;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsWin32::getUserDir() const
|
||||
{
|
||||
static char knownpath[MAX_PATH];
|
||||
HRESULT hResult = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath);
|
||||
|
||||
if (hResult == S_OK)
|
||||
{
|
||||
return (GHOST_TUns8*)knownpath;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsWin32::getBinaryDir() const
|
||||
{
|
||||
static char fullname[MAX_PATH];
|
||||
if(GetModuleFileName(0, fullname, MAX_PATH)) {
|
||||
return (GHOST_TUns8*)fullname;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GHOST_SystemPathsWin32::addToSystemRecentFiles(const char* filename) const
|
||||
{
|
||||
/* SHARD_PATH resolves to SHARD_PATHA for non-UNICODE build */
|
||||
SHAddToRecentDocs(SHARD_PATH,filename);
|
||||
}
|
||||
91
intern/ghost/intern/GHOST_SystemPathsWin32.h
Normal file
91
intern/ghost/intern/GHOST_SystemPathsWin32.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_SystemPathsWin32.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GHOST_SYSTEM_PATHS_WIN32_H_
|
||||
#define _GHOST_SYSTEM_PATHS_WIN32_H_
|
||||
|
||||
#ifndef WIN32
|
||||
#error WIN32 only!
|
||||
#endif // WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "GHOST_SystemPaths.h"
|
||||
|
||||
|
||||
/**
|
||||
* WIN32 Implementation of GHOST_SystemPaths class.
|
||||
* @see GHOST_SystemPaths.
|
||||
* @author Andrea Weikert
|
||||
* @date August 1, 2010
|
||||
*/
|
||||
class GHOST_SystemPathsWin32 : public GHOST_SystemPaths {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_SystemPathsWin32();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_SystemPathsWin32();
|
||||
|
||||
/**
|
||||
* Determine the base dir in which shared resources are located. It will first try to use
|
||||
* "unpack and run" path, then look for properly installed path, not including versioning.
|
||||
* @return Unsigned char string pointing to system dir (eg /usr/share/).
|
||||
*/
|
||||
const GHOST_TUns8* getSystemDir() const;
|
||||
|
||||
/**
|
||||
* Determine the base dir in which user configuration is stored, not including versioning.
|
||||
* If needed, it will create the base directory.
|
||||
* @return Unsigned char string pointing to user dir (eg ~/).
|
||||
*/
|
||||
const GHOST_TUns8* getUserDir() const;
|
||||
|
||||
/**
|
||||
* Determine the directory of the current binary
|
||||
* @return Unsigned char string pointing to the binary dir
|
||||
*/
|
||||
const GHOST_TUns8* getBinaryDir() const;
|
||||
|
||||
/**
|
||||
* Add the file to the operating system most recently used files
|
||||
*/
|
||||
void addToSystemRecentFiles(const char* filename) const;
|
||||
};
|
||||
|
||||
#endif // _GHOST_SYSTEM_PATHS_WIN32_H_
|
||||
|
||||
85
intern/ghost/intern/GHOST_SystemPathsX11.cpp
Normal file
85
intern/ghost/intern/GHOST_SystemPathsX11.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_SystemPathsX11.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include "GHOST_SystemPathsX11.h"
|
||||
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
// For timing
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdio.h> // for fprintf only
|
||||
#include <cstdlib> // for exit
|
||||
|
||||
using namespace std;
|
||||
|
||||
GHOST_SystemPathsX11::GHOST_SystemPathsX11()
|
||||
{
|
||||
}
|
||||
|
||||
GHOST_SystemPathsX11::~GHOST_SystemPathsX11()
|
||||
{
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsX11::getSystemDir() const
|
||||
{
|
||||
/* no prefix assumes a portable build which only uses bundled scripts */
|
||||
#ifdef PREFIX
|
||||
return (GHOST_TUns8*) PREFIX "/share";
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsX11::getUserDir() const
|
||||
{
|
||||
const char* env = getenv("HOME");
|
||||
if(env) {
|
||||
return (GHOST_TUns8*) env;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const GHOST_TUns8* GHOST_SystemPathsX11::getBinaryDir() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GHOST_SystemPathsX11::addToSystemRecentFiles(const char* filename) const
|
||||
{
|
||||
/* XXXXX TODO: Implementation for X11 if possible */
|
||||
|
||||
}
|
||||
82
intern/ghost/intern/GHOST_SystemPathsX11.h
Normal file
82
intern/ghost/intern/GHOST_SystemPathsX11.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2010 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Contributor(s): Blender Foundation
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_SystemPathsX11.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GHOST_SYSTEM_PATHS_X11_H_
|
||||
#define _GHOST_SYSTEM_PATHS_X11_H_
|
||||
|
||||
#include "GHOST_SystemPaths.h"
|
||||
#include "../GHOST_Types.h"
|
||||
|
||||
|
||||
class GHOST_SystemPathsX11 : public GHOST_SystemPaths {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* this class should only be instanciated by GHOST_ISystem.
|
||||
*/
|
||||
GHOST_SystemPathsX11();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_SystemPathsX11();
|
||||
|
||||
/**
|
||||
* Determine the base dir in which shared resources are located. It will first try to use
|
||||
* "unpack and run" path, then look for properly installed path, not including versioning.
|
||||
* @return Unsigned char string pointing to system dir (eg /usr/share/blender/).
|
||||
*/
|
||||
const GHOST_TUns8* getSystemDir() const;
|
||||
|
||||
/**
|
||||
* Determine the base dir in which user configuration is stored, not including versioning.
|
||||
* If needed, it will create the base directory.
|
||||
* @return Unsigned char string pointing to user dir (eg ~/.blender/).
|
||||
*/
|
||||
const GHOST_TUns8* getUserDir() const;
|
||||
|
||||
/**
|
||||
* Determine the directory of the current binary
|
||||
* @return Unsigned char string pointing to the binary dir
|
||||
*/
|
||||
const GHOST_TUns8* getBinaryDir() const;
|
||||
|
||||
/**
|
||||
* Add the file to the operating system most recently used files
|
||||
*/
|
||||
void addToSystemRecentFiles(const char* filename) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
1257
intern/ghost/intern/GHOST_SystemWin32.cpp
Normal file
1257
intern/ghost/intern/GHOST_SystemWin32.cpp
Normal file
@@ -0,0 +1,1257 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_SystemWin32.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 7, 2001
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifdef FREE_WINDOWS
|
||||
# define _WIN32_WINNT 0x0500 /* GetConsoleWindow() for MinGW */
|
||||
#endif
|
||||
|
||||
#include "GHOST_SystemWin32.h"
|
||||
#include "GHOST_EventDragnDrop.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#ifdef _WIN32_IE
|
||||
#undef _WIN32_IE
|
||||
#endif
|
||||
#define _WIN32_IE 0x0501
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
// win64 doesn't define GWL_USERDATA
|
||||
#ifdef WIN32
|
||||
#ifndef GWL_USERDATA
|
||||
#define GWL_USERDATA GWLP_USERDATA
|
||||
#define GWL_WNDPROC GWLP_WNDPROC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* According to the docs the mouse wheel message is supported from windows 98
|
||||
* upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the
|
||||
* wheel detent value are undefined.
|
||||
*/
|
||||
#ifndef WM_MOUSEWHEEL
|
||||
#define WM_MOUSEWHEEL 0x020A
|
||||
#endif // WM_MOUSEWHEEL
|
||||
#ifndef WHEEL_DELTA
|
||||
#define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */
|
||||
#endif // WHEEL_DELTA
|
||||
|
||||
/*
|
||||
* Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2.
|
||||
* MSDN: Declared in Winuser.h, include Windows.h
|
||||
* This does not seem to work with MinGW so we define our own here.
|
||||
*/
|
||||
#ifndef XBUTTON1
|
||||
#define XBUTTON1 0x0001
|
||||
#endif // XBUTTON1
|
||||
#ifndef XBUTTON2
|
||||
#define XBUTTON2 0x0002
|
||||
#endif // XBUTTON2
|
||||
#ifndef WM_XBUTTONUP
|
||||
#define WM_XBUTTONUP 524
|
||||
#endif // WM_XBUTTONUP
|
||||
#ifndef WM_XBUTTONDOWN
|
||||
#define WM_XBUTTONDOWN 523
|
||||
#endif // WM_XBUTTONDOWN
|
||||
|
||||
#include "GHOST_Debug.h"
|
||||
#include "GHOST_DisplayManagerWin32.h"
|
||||
#include "GHOST_EventButton.h"
|
||||
#include "GHOST_EventCursor.h"
|
||||
#include "GHOST_EventKey.h"
|
||||
#include "GHOST_EventWheel.h"
|
||||
#include "GHOST_EventNDOF.h"
|
||||
#include "GHOST_TimerTask.h"
|
||||
#include "GHOST_TimerManager.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
#include "GHOST_WindowWin32.h"
|
||||
#include "GHOST_NDOFManager.h"
|
||||
|
||||
// Key code values not found in winuser.h
|
||||
#ifndef VK_MINUS
|
||||
#define VK_MINUS 0xBD
|
||||
#endif // VK_MINUS
|
||||
#ifndef VK_SEMICOLON
|
||||
#define VK_SEMICOLON 0xBA
|
||||
#endif // VK_SEMICOLON
|
||||
#ifndef VK_PERIOD
|
||||
#define VK_PERIOD 0xBE
|
||||
#endif // VK_PERIOD
|
||||
#ifndef VK_COMMA
|
||||
#define VK_COMMA 0xBC
|
||||
#endif // VK_COMMA
|
||||
#ifndef VK_QUOTE
|
||||
#define VK_QUOTE 0xDE
|
||||
#endif // VK_QUOTE
|
||||
#ifndef VK_BACK_QUOTE
|
||||
#define VK_BACK_QUOTE 0xC0
|
||||
#endif // VK_BACK_QUOTE
|
||||
#ifndef VK_SLASH
|
||||
#define VK_SLASH 0xBF
|
||||
#endif // VK_SLASH
|
||||
#ifndef VK_BACK_SLASH
|
||||
#define VK_BACK_SLASH 0xDC
|
||||
#endif // VK_BACK_SLASH
|
||||
#ifndef VK_EQUALS
|
||||
#define VK_EQUALS 0xBB
|
||||
#endif // VK_EQUALS
|
||||
#ifndef VK_OPEN_BRACKET
|
||||
#define VK_OPEN_BRACKET 0xDB
|
||||
#endif // VK_OPEN_BRACKET
|
||||
#ifndef VK_CLOSE_BRACKET
|
||||
#define VK_CLOSE_BRACKET 0xDD
|
||||
#endif // VK_CLOSE_BRACKET
|
||||
#ifndef VK_GR_LESS
|
||||
#define VK_GR_LESS 0xE2
|
||||
#endif // VK_GR_LESS
|
||||
|
||||
#ifndef VK_MEDIA_NEXT_TRACK
|
||||
#define VK_MEDIA_NEXT_TRACK 0xB0
|
||||
#endif // VK_MEDIA_NEXT_TRACK
|
||||
#ifndef VK_MEDIA_PREV_TRACK
|
||||
#define VK_MEDIA_PREV_TRACK 0xB1
|
||||
#endif // VK_MEDIA_PREV_TRACK
|
||||
#ifndef VK_MEDIA_STOP
|
||||
#define VK_MEDIA_STOP 0xB2
|
||||
#endif // VK_MEDIA_STOP
|
||||
#ifndef VK_MEDIA_PLAY_PAUSE
|
||||
#define VK_MEDIA_PLAY_PAUSE 0xB3
|
||||
#endif // VK_MEDIA_PLAY_PAUSE
|
||||
|
||||
/*
|
||||
Initiates WM_INPUT messages from keyboard
|
||||
That way GHOST can retrieve true keys
|
||||
*/
|
||||
GHOST_TInt32 GHOST_SystemWin32::initKeyboardRawInput(void)
|
||||
{
|
||||
RAWINPUTDEVICE device = {0};
|
||||
device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/
|
||||
device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
|
||||
|
||||
return RegisterRawInputDevices(&device, 1, sizeof(device));
|
||||
};
|
||||
|
||||
GHOST_SystemWin32::GHOST_SystemWin32()
|
||||
: m_hasPerformanceCounter(false), m_freq(0), m_start(0)
|
||||
{
|
||||
m_displayManager = new GHOST_DisplayManagerWin32 ();
|
||||
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
|
||||
m_displayManager->initialize();
|
||||
|
||||
m_consoleStatus = 1;
|
||||
|
||||
// Check if current keyboard layout uses AltGr and save keylayout ID for
|
||||
// specialized handling if keys like VK_OEM_*. I.e. french keylayout
|
||||
// generates VK_OEM_8 for their exclamation key (key left of right shift)
|
||||
this->handleKeyboardChange();
|
||||
// Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
|
||||
OleInitialize(0);
|
||||
}
|
||||
|
||||
GHOST_SystemWin32::~GHOST_SystemWin32()
|
||||
{
|
||||
// Shutdown COM
|
||||
OleUninitialize();
|
||||
toggleConsole(1);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const
|
||||
{
|
||||
// Hardware does not support high resolution timers. We will use GetTickCount instead then.
|
||||
if (!m_hasPerformanceCounter) {
|
||||
return ::GetTickCount();
|
||||
}
|
||||
|
||||
// Retrieve current count
|
||||
__int64 count = 0;
|
||||
::QueryPerformanceCounter((LARGE_INTEGER*)&count);
|
||||
|
||||
// Calculate the time passed since system initialization.
|
||||
__int64 delta = 1000*(count-m_start);
|
||||
|
||||
GHOST_TUns64 t = (GHOST_TUns64)(delta/m_freq);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns8 GHOST_SystemWin32::getNumDisplays() const
|
||||
{
|
||||
GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::getNumDisplays(): m_displayManager==0\n");
|
||||
GHOST_TUns8 numDisplays;
|
||||
m_displayManager->getNumDisplays(numDisplays);
|
||||
return numDisplays;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const
|
||||
{
|
||||
width = ::GetSystemMetrics(SM_CXSCREEN);
|
||||
height= ::GetSystemMetrics(SM_CYSCREEN);
|
||||
}
|
||||
|
||||
|
||||
GHOST_IWindow* GHOST_SystemWin32::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_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow )
|
||||
{
|
||||
GHOST_Window* window = 0;
|
||||
window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples, parentWindow);
|
||||
if (window) {
|
||||
if (window->getValid()) {
|
||||
// Store the pointer to the window
|
||||
// if (state != GHOST_kWindowStateFullScreen) {
|
||||
m_windowManager->addWindow(window);
|
||||
// }
|
||||
}
|
||||
else {
|
||||
|
||||
// Invalid parent window hwnd
|
||||
if (((GHOST_WindowWin32*)window)->getNextWindow() == NULL) {
|
||||
delete window;
|
||||
window = 0;
|
||||
return window;
|
||||
}
|
||||
|
||||
// An invalid window could be one that was used to test for AA
|
||||
window = ((GHOST_WindowWin32*)window)->getNextWindow();
|
||||
|
||||
// If another window is found, let the wm know about that one, but not the old one
|
||||
if (window->getValid()) {
|
||||
m_windowManager->addWindow(window);
|
||||
}
|
||||
else {
|
||||
delete window;
|
||||
window = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_SystemWin32::processEvents(bool waitForEvent)
|
||||
{
|
||||
MSG msg;
|
||||
bool anyProcessed = false;
|
||||
|
||||
do {
|
||||
GHOST_TimerManager* timerMgr = getTimerManager();
|
||||
|
||||
if (waitForEvent && !::PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE)) {
|
||||
#if 1
|
||||
::Sleep(1);
|
||||
#else
|
||||
GHOST_TUns64 next = timerMgr->nextFireTime();
|
||||
GHOST_TInt64 maxSleep = next - getMilliSeconds();
|
||||
|
||||
if (next == GHOST_kFireTimeNever) {
|
||||
::WaitMessage();
|
||||
} else if(maxSleep >= 0.0) {
|
||||
::SetTimer(NULL, 0, maxSleep, NULL);
|
||||
::WaitMessage();
|
||||
::KillTimer(NULL, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (timerMgr->fireTimers(getMilliSeconds())) {
|
||||
anyProcessed = true;
|
||||
}
|
||||
|
||||
// Process all the events waiting for us
|
||||
while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0) {
|
||||
::DispatchMessage(&msg);
|
||||
anyProcessed = true;
|
||||
}
|
||||
} while (waitForEvent && !anyProcessed);
|
||||
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
|
||||
{
|
||||
POINT point;
|
||||
if(::GetCursorPos(&point)){
|
||||
x = point.x;
|
||||
y = point.y;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y)
|
||||
{
|
||||
if (!GetActiveWindow())
|
||||
return GHOST_kFailure;
|
||||
return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const
|
||||
{
|
||||
bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
|
||||
keys.set(GHOST_kModifierKeyLeftShift, down);
|
||||
down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
|
||||
keys.set(GHOST_kModifierKeyRightShift, down);
|
||||
|
||||
down = HIBYTE(::GetKeyState(VK_LMENU)) != 0;
|
||||
keys.set(GHOST_kModifierKeyLeftAlt, down);
|
||||
down = HIBYTE(::GetKeyState(VK_RMENU)) != 0;
|
||||
keys.set(GHOST_kModifierKeyRightAlt, down);
|
||||
|
||||
down = HIBYTE(::GetKeyState(VK_LCONTROL)) != 0;
|
||||
keys.set(GHOST_kModifierKeyLeftControl, down);
|
||||
down = HIBYTE(::GetKeyState(VK_RCONTROL)) != 0;
|
||||
keys.set(GHOST_kModifierKeyRightControl, down);
|
||||
|
||||
bool lwindown = HIBYTE(::GetKeyState(VK_LWIN)) != 0;
|
||||
bool rwindown = HIBYTE(::GetKeyState(VK_RWIN)) != 0;
|
||||
if(lwindown || rwindown)
|
||||
keys.set(GHOST_kModifierKeyOS, true);
|
||||
else
|
||||
keys.set(GHOST_kModifierKeyOS, false);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons& buttons) const
|
||||
{
|
||||
/* Check for swapped buttons (left-handed mouse buttons)
|
||||
* GetAsyncKeyState() will give back the state of the physical mouse buttons.
|
||||
*/
|
||||
bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE;
|
||||
|
||||
bool down = HIBYTE(::GetKeyState(VK_LBUTTON)) != 0;
|
||||
buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down);
|
||||
|
||||
down = HIBYTE(::GetKeyState(VK_MBUTTON)) != 0;
|
||||
buttons.set(GHOST_kButtonMaskMiddle, down);
|
||||
|
||||
down = HIBYTE(::GetKeyState(VK_RBUTTON)) != 0;
|
||||
buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::init()
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_System::init();
|
||||
|
||||
/* Disable scaling on high DPI displays on Vista */
|
||||
user32 = ::LoadLibraryA("user32.dll");
|
||||
typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)();
|
||||
LPFNSETPROCESSDPIAWARE SetProcessDPIAware =
|
||||
(LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware");
|
||||
if (SetProcessDPIAware)
|
||||
SetProcessDPIAware();
|
||||
#ifdef NEED_RAW_PROC
|
||||
pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices");
|
||||
pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData");
|
||||
#else
|
||||
FreeLibrary(user32);
|
||||
#endif
|
||||
|
||||
/* Initiates WM_INPUT messages from keyboard */
|
||||
initKeyboardRawInput();
|
||||
|
||||
|
||||
// Determine whether this system has a high frequency performance counter. */
|
||||
m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE;
|
||||
if (m_hasPerformanceCounter) {
|
||||
GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer available\n")
|
||||
::QueryPerformanceCounter((LARGE_INTEGER*)&m_start);
|
||||
}
|
||||
else {
|
||||
GHOST_PRINT("GHOST_SystemWin32::init: High Frequency Performance Timer not available\n")
|
||||
}
|
||||
|
||||
if (success) {
|
||||
WNDCLASS wc;
|
||||
wc.style= CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc= s_wndProc;
|
||||
wc.cbClsExtra= 0;
|
||||
wc.cbWndExtra= 0;
|
||||
wc.hInstance= ::GetModuleHandle(0);
|
||||
wc.hIcon = ::LoadIcon(wc.hInstance, "APPICON");
|
||||
|
||||
if (!wc.hIcon) {
|
||||
::LoadIcon(NULL, IDI_APPLICATION);
|
||||
}
|
||||
wc.hCursor = ::LoadCursor(0, IDC_ARROW);
|
||||
wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH);
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName= GHOST_WindowWin32::getWindowClassName();
|
||||
|
||||
// Use RegisterClassEx for setting small icon
|
||||
if (::RegisterClass(&wc) == 0) {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::exit()
|
||||
{
|
||||
#ifdef NEED_RAW_PROC
|
||||
FreeLibrary(user32);
|
||||
#endif
|
||||
|
||||
return GHOST_System::exit();
|
||||
}
|
||||
|
||||
GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk)
|
||||
{
|
||||
unsigned int size = 0;
|
||||
char * data;
|
||||
GHOST_TKey key = GHOST_kKeyUnknown;
|
||||
|
||||
|
||||
if(!keyDown)
|
||||
return GHOST_kKeyUnknown;
|
||||
|
||||
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER));
|
||||
|
||||
|
||||
if((data = (char*)malloc(size)) &&
|
||||
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER)))
|
||||
{
|
||||
RAWINPUT ri;
|
||||
memcpy(&ri,data,(size < sizeof(ri)) ? size : sizeof(ri));
|
||||
|
||||
if (ri.header.dwType == RIM_TYPEKEYBOARD)
|
||||
{
|
||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
|
||||
|
||||
GHOST_ModifierKeys modifiers;
|
||||
system->retrieveModifierKeys(modifiers);
|
||||
|
||||
*keyDown = !(ri.data.keyboard.Flags & RI_KEY_BREAK);
|
||||
key = this->convertKey(window, ri.data.keyboard.VKey, ri.data.keyboard.MakeCode, (ri.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0)));
|
||||
|
||||
// extra handling of modifier keys: don't send repeats out from GHOST
|
||||
if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt)
|
||||
{
|
||||
bool changed = false;
|
||||
GHOST_TModifierKeyMask modifier;
|
||||
switch(key) {
|
||||
case GHOST_kKeyLeftShift:
|
||||
{
|
||||
changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown);
|
||||
modifier = GHOST_kModifierKeyLeftShift;
|
||||
}
|
||||
break;
|
||||
case GHOST_kKeyRightShift:
|
||||
{
|
||||
changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown);
|
||||
modifier = GHOST_kModifierKeyRightShift;
|
||||
}
|
||||
break;
|
||||
case GHOST_kKeyLeftControl:
|
||||
{
|
||||
changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown);
|
||||
modifier = GHOST_kModifierKeyLeftControl;
|
||||
}
|
||||
break;
|
||||
case GHOST_kKeyRightControl:
|
||||
{
|
||||
changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown);
|
||||
modifier = GHOST_kModifierKeyRightControl;
|
||||
}
|
||||
break;
|
||||
case GHOST_kKeyLeftAlt:
|
||||
{
|
||||
changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown);
|
||||
modifier = GHOST_kModifierKeyLeftAlt;
|
||||
}
|
||||
break;
|
||||
case GHOST_kKeyRightAlt:
|
||||
{
|
||||
changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown);
|
||||
modifier = GHOST_kModifierKeyRightAlt;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if(changed)
|
||||
{
|
||||
modifiers.set(modifier, (bool)*keyDown);
|
||||
system->storeModifierKeys(modifiers);
|
||||
}
|
||||
else
|
||||
{
|
||||
key = GHOST_kKeyUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(vk) *vk = ri.data.keyboard.VKey;
|
||||
};
|
||||
|
||||
};
|
||||
free(data);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
//! note: this function can be extended to include other exotic cases as they arise.
|
||||
// This function was added in response to bug [#25715]
|
||||
GHOST_TKey GHOST_SystemWin32::processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const
|
||||
{
|
||||
GHOST_TKey key = GHOST_kKeyUnknown;
|
||||
switch(PRIMARYLANGID(m_langId)) {
|
||||
case LANG_FRENCH:
|
||||
if(vKey==VK_OEM_8) key = GHOST_kKeyF13; // oem key; used purely for shortcuts .
|
||||
break;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
GHOST_TKey GHOST_SystemWin32::convertKey(GHOST_IWindow *window, short vKey, short scanCode, short extend) const
|
||||
{
|
||||
GHOST_TKey key;
|
||||
|
||||
if ((vKey >= '0') && (vKey <= '9')) {
|
||||
// VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39)
|
||||
key = (GHOST_TKey)(vKey - '0' + GHOST_kKey0);
|
||||
}
|
||||
else if ((vKey >= 'A') && (vKey <= 'Z')) {
|
||||
// VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A)
|
||||
key = (GHOST_TKey)(vKey - 'A' + GHOST_kKeyA);
|
||||
}
|
||||
else if ((vKey >= VK_F1) && (vKey <= VK_F24)) {
|
||||
key = (GHOST_TKey)(vKey - VK_F1 + GHOST_kKeyF1);
|
||||
}
|
||||
else {
|
||||
switch (vKey) {
|
||||
case VK_RETURN:
|
||||
key = (extend)?GHOST_kKeyNumpadEnter : GHOST_kKeyEnter; break;
|
||||
|
||||
case VK_BACK: key = GHOST_kKeyBackSpace; break;
|
||||
case VK_TAB: key = GHOST_kKeyTab; break;
|
||||
case VK_ESCAPE: key = GHOST_kKeyEsc; break;
|
||||
case VK_SPACE: key = GHOST_kKeySpace; break;
|
||||
|
||||
case VK_INSERT:
|
||||
case VK_NUMPAD0:
|
||||
key = (extend) ? GHOST_kKeyInsert : GHOST_kKeyNumpad0; break;
|
||||
case VK_END:
|
||||
case VK_NUMPAD1:
|
||||
key = (extend) ? GHOST_kKeyEnd : GHOST_kKeyNumpad1; break;
|
||||
case VK_DOWN:
|
||||
case VK_NUMPAD2:
|
||||
key = (extend) ? GHOST_kKeyDownArrow : GHOST_kKeyNumpad2; break;
|
||||
case VK_NEXT:
|
||||
case VK_NUMPAD3:
|
||||
key = (extend) ? GHOST_kKeyDownPage : GHOST_kKeyNumpad3; break;
|
||||
case VK_LEFT:
|
||||
case VK_NUMPAD4:
|
||||
key = (extend) ? GHOST_kKeyLeftArrow : GHOST_kKeyNumpad4; break;
|
||||
case VK_CLEAR:
|
||||
case VK_NUMPAD5:
|
||||
key = (extend) ? GHOST_kKeyUnknown: GHOST_kKeyNumpad5; break;
|
||||
case VK_RIGHT:
|
||||
case VK_NUMPAD6:
|
||||
key = (extend) ? GHOST_kKeyRightArrow : GHOST_kKeyNumpad6; break;
|
||||
case VK_HOME:
|
||||
case VK_NUMPAD7:
|
||||
key = (extend) ? GHOST_kKeyHome : GHOST_kKeyNumpad7; break;
|
||||
case VK_UP:
|
||||
case VK_NUMPAD8:
|
||||
key = (extend) ? GHOST_kKeyUpArrow : GHOST_kKeyNumpad8; break;
|
||||
case VK_PRIOR:
|
||||
case VK_NUMPAD9:
|
||||
key = (extend) ? GHOST_kKeyUpPage : GHOST_kKeyNumpad9; break;
|
||||
case VK_DECIMAL:
|
||||
case VK_DELETE:
|
||||
key = (extend) ? GHOST_kKeyDelete : GHOST_kKeyNumpadPeriod; break;
|
||||
|
||||
case VK_SNAPSHOT: key = GHOST_kKeyPrintScreen; break;
|
||||
case VK_PAUSE: key = GHOST_kKeyPause; break;
|
||||
case VK_MULTIPLY: key = GHOST_kKeyNumpadAsterisk; break;
|
||||
case VK_SUBTRACT: key = GHOST_kKeyNumpadMinus; break;
|
||||
case VK_DIVIDE: key = GHOST_kKeyNumpadSlash; break;
|
||||
case VK_ADD: key = GHOST_kKeyNumpadPlus; break;
|
||||
|
||||
case VK_SEMICOLON: key = GHOST_kKeySemicolon; break;
|
||||
case VK_EQUALS: key = GHOST_kKeyEqual; break;
|
||||
case VK_COMMA: key = GHOST_kKeyComma; break;
|
||||
case VK_MINUS: key = GHOST_kKeyMinus; break;
|
||||
case VK_PERIOD: key = GHOST_kKeyPeriod; break;
|
||||
case VK_SLASH: key = GHOST_kKeySlash; break;
|
||||
case VK_BACK_QUOTE: key = GHOST_kKeyAccentGrave; break;
|
||||
case VK_OPEN_BRACKET: key = GHOST_kKeyLeftBracket; break;
|
||||
case VK_BACK_SLASH: key = GHOST_kKeyBackslash; break;
|
||||
case VK_CLOSE_BRACKET: key = GHOST_kKeyRightBracket; break;
|
||||
case VK_QUOTE: key = GHOST_kKeyQuote; break;
|
||||
case VK_GR_LESS: key = GHOST_kKeyGrLess; break;
|
||||
|
||||
case VK_SHIFT:
|
||||
key = (scanCode == 0x36)? GHOST_kKeyRightShift : GHOST_kKeyLeftShift;
|
||||
break;
|
||||
case VK_CONTROL:
|
||||
key = (extend)? GHOST_kKeyRightControl : GHOST_kKeyLeftControl;
|
||||
break;
|
||||
case VK_MENU:
|
||||
key = (extend)? GHOST_kKeyRightAlt : GHOST_kKeyLeftAlt;
|
||||
break;
|
||||
case VK_LWIN:
|
||||
case VK_RWIN:
|
||||
key = GHOST_kKeyOS;
|
||||
break;
|
||||
case VK_NUMLOCK: key = GHOST_kKeyNumLock; break;
|
||||
case VK_SCROLL: key = GHOST_kKeyScrollLock; break;
|
||||
case VK_CAPITAL: key = GHOST_kKeyCapsLock; break;
|
||||
case VK_OEM_8:
|
||||
key = ((GHOST_SystemWin32*)getSystem())->processSpecialKey(window, vKey, scanCode);
|
||||
break;
|
||||
case VK_MEDIA_PLAY_PAUSE: key = GHOST_kKeyMediaPlay; break;
|
||||
case VK_MEDIA_STOP: key = GHOST_kKeyMediaStop; break;
|
||||
case VK_MEDIA_PREV_TRACK: key = GHOST_kKeyMediaFirst; break;
|
||||
case VK_MEDIA_NEXT_TRACK: key = GHOST_kKeyMediaLast; break;
|
||||
default:
|
||||
key = GHOST_kKeyUnknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask)
|
||||
{
|
||||
return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask);
|
||||
}
|
||||
|
||||
|
||||
GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
|
||||
{
|
||||
GHOST_TInt32 x_screen, y_screen;
|
||||
GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem());
|
||||
GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow;
|
||||
|
||||
system->getCursorPosition(x_screen, y_screen);
|
||||
|
||||
if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
|
||||
{
|
||||
GHOST_TInt32 x_new= x_screen;
|
||||
GHOST_TInt32 y_new= y_screen;
|
||||
GHOST_TInt32 x_accum, y_accum;
|
||||
GHOST_Rect bounds;
|
||||
|
||||
/* fallback to window bounds */
|
||||
if(window->getCursorGrabBounds(bounds)==GHOST_kFailure){
|
||||
window->getClientBounds(bounds);
|
||||
}
|
||||
|
||||
/* could also clamp to screen bounds
|
||||
* wrap with a window outside the view will fail atm */
|
||||
|
||||
bounds.wrapPoint(x_new, y_new, 2); /* offset of one incase blender is at screen bounds */
|
||||
|
||||
window->getCursorGrabAccum(x_accum, y_accum);
|
||||
if(x_new != x_screen|| y_new != y_screen) {
|
||||
/* when wrapping we don't need to add an event because the
|
||||
* setCursorPosition call will cause a new event after */
|
||||
system->setCursorPosition(x_new, y_new); /* wrap */
|
||||
window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
|
||||
}else{
|
||||
return new GHOST_EventCursor(system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
window,
|
||||
x_screen + x_accum,
|
||||
y_screen + y_accum
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
return new GHOST_EventCursor(system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
window,
|
||||
x_screen,
|
||||
y_screen
|
||||
);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
// short fwKeys = LOWORD(wParam); // key flags
|
||||
int zDelta = (short) HIWORD(wParam); // wheel rotation
|
||||
|
||||
// zDelta /= WHEEL_DELTA;
|
||||
// temporary fix below: microsoft now has added more precision, making the above division not work
|
||||
if (zDelta <= 0 ) zDelta= -1; else zDelta= 1;
|
||||
|
||||
// short xPos = (short) LOWORD(lParam); // horizontal position of pointer
|
||||
// short yPos = (short) HIWORD(lParam); // vertical position of pointer
|
||||
return new GHOST_EventWheel (getSystem()->getMilliSeconds(), window, zDelta);
|
||||
}
|
||||
|
||||
|
||||
GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
int keyDown=0;
|
||||
char vk;
|
||||
GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem();
|
||||
GHOST_TKey key = system->hardKey(window, wParam, lParam, &keyDown, &vk);
|
||||
GHOST_EventKey* event;
|
||||
if (key != GHOST_kKeyUnknown) {
|
||||
char ascii = '\0';
|
||||
|
||||
unsigned short utf16[2]={0};
|
||||
BYTE state[256];
|
||||
GetKeyboardState((PBYTE)state);
|
||||
|
||||
if(ToAsciiEx(vk, 0, state, utf16, 0, system->m_keylayout))
|
||||
WideCharToMultiByte(CP_ACP, 0x00000400,
|
||||
(wchar_t*)utf16, 1,
|
||||
(LPSTR) &ascii, 1,
|
||||
NULL,NULL);
|
||||
|
||||
event = new GHOST_EventKey(system->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii);
|
||||
|
||||
#ifdef BF_GHOST_DEBUG
|
||||
std::cout << ascii << std::endl;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
event = 0;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window)
|
||||
{
|
||||
return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType,
|
||||
GHOST_TDragnDropTypes draggedObjectType,
|
||||
GHOST_IWindow* window,
|
||||
int mouseX, int mouseY,
|
||||
void* data)
|
||||
{
|
||||
GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
|
||||
return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
|
||||
eventType,
|
||||
draggedObjectType,
|
||||
window,mouseX,mouseY,data)
|
||||
);
|
||||
}
|
||||
|
||||
void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
|
||||
{
|
||||
minmax->ptMinTrackSize.x=320;
|
||||
minmax->ptMinTrackSize.y=240;
|
||||
}
|
||||
|
||||
LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
GHOST_Event* event = 0;
|
||||
LRESULT lResult = 0;
|
||||
GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
|
||||
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized")
|
||||
|
||||
if (hwnd) {
|
||||
GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA);
|
||||
if (window) {
|
||||
switch (msg) {
|
||||
// we need to check if new key layout has AltGr
|
||||
case WM_INPUTLANGCHANGE:
|
||||
system->handleKeyboardChange();
|
||||
break;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Keyboard events, processed
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WM_INPUT:
|
||||
// check WM_INPUT from input sink when ghost window is not in the foreground
|
||||
if (wParam == RIM_INPUTSINK) {
|
||||
if (GetFocus() != hwnd) // WM_INPUT message not for this window
|
||||
return 0;
|
||||
} //else wPAram == RIM_INPUT
|
||||
event = processKeyEvent(window, wParam, lParam);
|
||||
if (!event) {
|
||||
GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
|
||||
GHOST_PRINT(msg)
|
||||
GHOST_PRINT(" key ignored\n")
|
||||
}
|
||||
break;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Keyboard events, ignored
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
/* These functions were replaced by WM_INPUT*/
|
||||
case WM_CHAR:
|
||||
/* The WM_CHAR message is posted to the window with the keyboard focus when
|
||||
* a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR
|
||||
* contains the character code of the key that was pressed.
|
||||
*/
|
||||
case WM_DEADCHAR:
|
||||
/* The WM_DEADCHAR message is posted to the window with the keyboard focus when a
|
||||
* WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR
|
||||
* specifies a character code generated by a dead key. A dead key is a key that
|
||||
* generates a character, such as the umlaut (double-dot), that is combined with
|
||||
* another character to form a composite character. For example, the umlaut-O
|
||||
* character (Ö) is generated by typing the dead key for the umlaut character, and
|
||||
* then typing the O key.
|
||||
*/
|
||||
break;
|
||||
case WM_SYSDEADCHAR:
|
||||
/* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when
|
||||
* a WM_SYSKEYDOWN message is translated by the TranslateMessage function.
|
||||
* WM_SYSDEADCHAR specifies the character code of a system dead key - that is,
|
||||
* a dead key that is pressed while holding down the alt key.
|
||||
*/
|
||||
case WM_SYSCHAR:
|
||||
/* The WM_SYSCHAR message is sent to the window with the keyboard focus when
|
||||
* a WM_SYSCHAR message is translated by the TranslateMessage function.
|
||||
* WM_SYSCHAR specifies the character code of a dead key - that is,
|
||||
* a dead key that is pressed while holding down the alt key.
|
||||
* To prevent the sound, DefWindowProc must be avoided by return
|
||||
*/
|
||||
break;
|
||||
case WM_SYSCOMMAND:
|
||||
/* The WM_SYSCHAR message is sent to the window when system commands such as
|
||||
* maximize, minimize or close the window are triggered. Also it is sent when ALT
|
||||
* button is press for menu. To prevent this we must return preventing DefWindowProc.
|
||||
*/
|
||||
if(wParam==SC_KEYMENU) return 0;
|
||||
break;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Tablet events, processed
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WT_PACKET:
|
||||
((GHOST_WindowWin32*)window)->processWin32TabletEvent(wParam, lParam);
|
||||
break;
|
||||
case WT_CSRCHANGE:
|
||||
case WT_PROXIMITY:
|
||||
((GHOST_WindowWin32*)window)->processWin32TabletInitEvent();
|
||||
break;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Mouse events, processed
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WM_LBUTTONDOWN:
|
||||
window->registerMouseClickEvent(0);
|
||||
event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft);
|
||||
break;
|
||||
case WM_MBUTTONDOWN:
|
||||
window->registerMouseClickEvent(0);
|
||||
event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle);
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
window->registerMouseClickEvent(0);
|
||||
event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
|
||||
break;
|
||||
case WM_XBUTTONDOWN:
|
||||
window->registerMouseClickEvent(0);
|
||||
if ((short) HIWORD(wParam) == XBUTTON1){
|
||||
event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4);
|
||||
}else if((short) HIWORD(wParam) == XBUTTON2){
|
||||
event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5);
|
||||
}
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
window->registerMouseClickEvent(1);
|
||||
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
|
||||
break;
|
||||
case WM_MBUTTONUP:
|
||||
window->registerMouseClickEvent(1);
|
||||
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle);
|
||||
break;
|
||||
case WM_RBUTTONUP:
|
||||
window->registerMouseClickEvent(1);
|
||||
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
|
||||
break;
|
||||
case WM_XBUTTONUP:
|
||||
window->registerMouseClickEvent(1);
|
||||
if ((short) HIWORD(wParam) == XBUTTON1){
|
||||
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4);
|
||||
}else if((short) HIWORD(wParam) == XBUTTON2){
|
||||
event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5);
|
||||
}
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
event = processCursorEvent(GHOST_kEventCursorMove, window);
|
||||
break;
|
||||
case WM_MOUSEWHEEL:
|
||||
/* The WM_MOUSEWHEEL message is sent to the focus window
|
||||
* when the mouse wheel is rotated. The DefWindowProc
|
||||
* function propagates the message to the window's parent.
|
||||
* There should be no internal forwarding of the message,
|
||||
* since DefWindowProc propagates it up the parent chain
|
||||
* until it finds a window that processes it.
|
||||
*/
|
||||
event = processWheelEvent(window, wParam, lParam);
|
||||
break;
|
||||
case WM_SETCURSOR:
|
||||
/* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor
|
||||
* to move within a window and mouse input is not captured.
|
||||
* This means we have to set the cursor shape every time the mouse moves!
|
||||
* The DefWindowProc function uses this message to set the cursor to an
|
||||
* arrow if it is not in the client area.
|
||||
*/
|
||||
if (LOWORD(lParam) == HTCLIENT) {
|
||||
// Load the current cursor
|
||||
window->loadCursor(window->getCursorVisibility(), window->getCursorShape());
|
||||
// Bypass call to DefWindowProc
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
// Outside of client area show standard cursor
|
||||
window->loadCursor(true, GHOST_kStandardCursorDefault);
|
||||
}
|
||||
break;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Mouse events, ignored
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WM_NCMOUSEMOVE:
|
||||
/* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved
|
||||
* within the nonclient area of the window. This message is posted to the window
|
||||
* that contains the cursor. If a window has captured the mouse, this message is not posted.
|
||||
*/
|
||||
case WM_NCHITTEST:
|
||||
/* The WM_NCHITTEST message is sent to a window when the cursor moves, or
|
||||
* when a mouse button is pressed or released. If the mouse is not captured,
|
||||
* the message is sent to the window beneath the cursor. Otherwise, the message
|
||||
* is sent to the window that has captured the mouse.
|
||||
*/
|
||||
break;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Window events, processed
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WM_CLOSE:
|
||||
/* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */
|
||||
event = processWindowEvent(GHOST_kEventWindowClose, window);
|
||||
break;
|
||||
case WM_ACTIVATE:
|
||||
/* The WM_ACTIVATE message is sent to both the window being activated and the window being
|
||||
* deactivated. If the windows use the same input queue, the message is sent synchronously,
|
||||
* first to the window procedure of the top-level window being deactivated, then to the window
|
||||
* procedure of the top-level window being activated. If the windows use different input queues,
|
||||
* the message is sent asynchronously, so the window is activated immediately.
|
||||
*/
|
||||
event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window);
|
||||
/* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL
|
||||
will not be dispatched to OUR active window if we minimize one of OUR windows. */
|
||||
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
break;
|
||||
case WM_PAINT:
|
||||
/* An application sends the WM_PAINT message when the system or another application
|
||||
* makes a request to paint a portion of an application's window. The message is sent
|
||||
* when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage
|
||||
* function when the application obtains a WM_PAINT message by using the GetMessage or
|
||||
* PeekMessage function.
|
||||
*/
|
||||
event = processWindowEvent(GHOST_kEventWindowUpdate, window);
|
||||
::ValidateRect(hwnd, NULL);
|
||||
break;
|
||||
case WM_GETMINMAXINFO:
|
||||
/* The WM_GETMINMAXINFO message is sent to a window when the size or
|
||||
* position of the window is about to change. An application can use
|
||||
* this message to override the window's default maximized size and
|
||||
* position, or its default minimum or maximum tracking size.
|
||||
*/
|
||||
processMinMaxInfo((MINMAXINFO *) lParam);
|
||||
/* Let DefWindowProc handle it. */
|
||||
break;
|
||||
case WM_SIZE:
|
||||
/* The WM_SIZE message is sent to a window after its size has changed.
|
||||
* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
|
||||
* WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
|
||||
* to perform any move or size change processing during the WM_WINDOWPOSCHANGED
|
||||
* message without calling DefWindowProc.
|
||||
*/
|
||||
event = processWindowEvent(GHOST_kEventWindowSize, window);
|
||||
break;
|
||||
case WM_CAPTURECHANGED:
|
||||
window->lostMouseCapture();
|
||||
break;
|
||||
case WM_MOVING:
|
||||
/* The WM_MOVING message is sent to a window that the user is moving. By processing
|
||||
* this message, an application can monitor the size and position of the drag rectangle
|
||||
* and, if needed, change its size or position.
|
||||
*/
|
||||
case WM_MOVE:
|
||||
/* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
|
||||
* WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
|
||||
* to perform any move or size change processing during the WM_WINDOWPOSCHANGED
|
||||
* message without calling DefWindowProc.
|
||||
*/
|
||||
event = processWindowEvent(GHOST_kEventWindowMove, window);
|
||||
break;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Window events, ignored
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
/* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place
|
||||
* in the Z order has changed as a result of a call to the SetWindowPos function or
|
||||
* another window-management function.
|
||||
* The WM_SIZE and WM_MOVE messages are not sent if an application handles the
|
||||
* WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient
|
||||
* to perform any move or size change processing during the WM_WINDOWPOSCHANGED
|
||||
* message without calling DefWindowProc.
|
||||
*/
|
||||
case WM_ERASEBKGND:
|
||||
/* An application sends the WM_ERASEBKGND message when the window background must be
|
||||
* erased (for example, when a window is resized). The message is sent to prepare an
|
||||
* invalidated portion of a window for painting.
|
||||
*/
|
||||
case WM_NCPAINT:
|
||||
/* An application sends the WM_NCPAINT message to a window when its frame must be painted. */
|
||||
case WM_NCACTIVATE:
|
||||
/* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed
|
||||
* to indicate an active or inactive state.
|
||||
*/
|
||||
case WM_DESTROY:
|
||||
/* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window
|
||||
* procedure of the window being destroyed after the window is removed from the screen.
|
||||
* This message is sent first to the window being destroyed and then to the child windows
|
||||
* (if any) as they are destroyed. During the processing of the message, it can be assumed
|
||||
* that all child windows still exist.
|
||||
*/
|
||||
case WM_NCDESTROY:
|
||||
/* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The
|
||||
* DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY
|
||||
* message. WM_DESTROY is used to free the allocated memory object associated with the window.
|
||||
*/
|
||||
break;
|
||||
case WM_KILLFOCUS:
|
||||
/* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus.
|
||||
* We want to prevent this if a window is still active and it loses focus to nowhere*/
|
||||
if(!wParam && hwnd==GetActiveWindow())
|
||||
SetFocus(hwnd);
|
||||
case WM_SHOWWINDOW:
|
||||
/* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
/* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in
|
||||
* the Z order is about to change as a result of a call to the SetWindowPos function or
|
||||
* another window-management function.
|
||||
*/
|
||||
case WM_SETFOCUS:
|
||||
/* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */
|
||||
case WM_ENTERSIZEMOVE:
|
||||
/* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving
|
||||
* or sizing modal loop. The window enters the moving or sizing modal loop when the user
|
||||
* clicks the window's title bar or sizing border, or when the window passes the
|
||||
* WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the
|
||||
* message specifies the SC_MOVE or SC_SIZE value. The operation is complete when
|
||||
* DefWindowProc returns.
|
||||
*/
|
||||
break;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Other events
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WM_GETTEXT:
|
||||
/* An application sends a WM_GETTEXT message to copy the text that
|
||||
* corresponds to a window into a buffer provided by the caller.
|
||||
*/
|
||||
case WM_ACTIVATEAPP:
|
||||
/* The WM_ACTIVATEAPP message is sent when a window belonging to a
|
||||
* different application than the active window is about to be activated.
|
||||
* The message is sent to the application whose window is being activated
|
||||
* and to the application whose window is being deactivated.
|
||||
*/
|
||||
case WM_TIMER:
|
||||
/* The WIN32 docs say:
|
||||
* The WM_TIMER message is posted to the installing thread's message queue
|
||||
* when a timer expires. You can process the message by providing a WM_TIMER
|
||||
* case in the window procedure. Otherwise, the default window procedure will
|
||||
* call the TimerProc callback function specified in the call to the SetTimer
|
||||
* function used to install the timer.
|
||||
*
|
||||
* In GHOST, we let DefWindowProc call the timer callback.
|
||||
*/
|
||||
break;
|
||||
case WM_BLND_NDOF_AXIS:
|
||||
{
|
||||
GHOST_TEventNDOFData ndofdata;
|
||||
system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
|
||||
system->m_eventManager->
|
||||
pushEvent(new GHOST_EventNDOF(
|
||||
system->getMilliSeconds(),
|
||||
GHOST_kEventNDOFMotion,
|
||||
window, ndofdata));
|
||||
}
|
||||
break;
|
||||
case WM_BLND_NDOF_BTN:
|
||||
{
|
||||
GHOST_TEventNDOFData ndofdata;
|
||||
system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata);
|
||||
system->m_eventManager->
|
||||
pushEvent(new GHOST_EventNDOF(
|
||||
system->getMilliSeconds(),
|
||||
GHOST_kEventNDOFButton,
|
||||
window, ndofdata));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Event found for a window before the pointer to the class has been set.
|
||||
GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n")
|
||||
/* These are events we typically miss at this point:
|
||||
WM_GETMINMAXINFO 0x24
|
||||
WM_NCCREATE 0x81
|
||||
WM_NCCALCSIZE 0x83
|
||||
WM_CREATE 0x01
|
||||
We let DefWindowProc do the work.
|
||||
*/
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Events without valid hwnd
|
||||
GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n")
|
||||
}
|
||||
|
||||
if (event) {
|
||||
system->pushEvent(event);
|
||||
}
|
||||
else {
|
||||
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
return lResult;
|
||||
}
|
||||
|
||||
GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const
|
||||
{
|
||||
char *buffer;
|
||||
char *temp_buff;
|
||||
|
||||
if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) {
|
||||
HANDLE hData = GetClipboardData( CF_TEXT );
|
||||
if (hData == NULL) {
|
||||
CloseClipboard();
|
||||
return NULL;
|
||||
}
|
||||
buffer = (char*)GlobalLock( hData );
|
||||
|
||||
temp_buff = (char*) malloc(strlen(buffer)+1);
|
||||
strcpy(temp_buff, buffer);
|
||||
|
||||
GlobalUnlock( hData );
|
||||
CloseClipboard();
|
||||
|
||||
temp_buff[strlen(buffer)] = '\0';
|
||||
if (buffer) {
|
||||
return (GHOST_TUns8*)temp_buff;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
|
||||
{
|
||||
if(selection) {return;} // for copying the selection, used on X11
|
||||
|
||||
if (OpenClipboard(NULL)) {
|
||||
HLOCAL clipbuffer;
|
||||
char *data;
|
||||
|
||||
if (buffer) {
|
||||
EmptyClipboard();
|
||||
|
||||
clipbuffer = LocalAlloc(LMEM_FIXED,((strlen(buffer)+1)));
|
||||
data = (char*)GlobalLock(clipbuffer);
|
||||
|
||||
strcpy(data, (char*)buffer);
|
||||
data[strlen(buffer)] = '\0';
|
||||
LocalUnlock(clipbuffer);
|
||||
SetClipboardData(CF_TEXT,clipbuffer);
|
||||
}
|
||||
CloseClipboard();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int GHOST_SystemWin32::toggleConsole(int action)
|
||||
{
|
||||
switch(action)
|
||||
{
|
||||
case 3: //hide if no console
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi = {{0}};
|
||||
if(!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) || csbi.dwCursorPosition.X || csbi.dwCursorPosition.Y>1)
|
||||
break;
|
||||
}
|
||||
case 0: //hide
|
||||
ShowWindow(GetConsoleWindow(),SW_HIDE);
|
||||
m_consoleStatus = 0;
|
||||
break;
|
||||
case 1: //show
|
||||
ShowWindow(GetConsoleWindow(),SW_SHOW);
|
||||
m_consoleStatus = 1;
|
||||
break;
|
||||
case 2: //toggle
|
||||
ShowWindow(GetConsoleWindow(),m_consoleStatus?SW_HIDE:SW_SHOW);
|
||||
m_consoleStatus=!m_consoleStatus;
|
||||
break;
|
||||
|
||||
};
|
||||
|
||||
|
||||
return m_consoleStatus;
|
||||
}
|
||||
489
intern/ghost/intern/GHOST_SystemWin32.h
Normal file
489
intern/ghost/intern/GHOST_SystemWin32.h
Normal file
@@ -0,0 +1,489 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_SystemWin32.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_SystemWin32 class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_SYSTEM_WIN32_H_
|
||||
#define _GHOST_SYSTEM_WIN32_H_
|
||||
|
||||
#ifndef WIN32
|
||||
#error WIN32 only!
|
||||
#endif // WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "GHOST_System.h"
|
||||
|
||||
#if defined(__CYGWIN32__)
|
||||
# define __int64 long long
|
||||
#endif
|
||||
|
||||
#ifndef WM_INPUT
|
||||
#define WM_INPUT 0x00FF
|
||||
#endif
|
||||
#ifndef RID_INPUT
|
||||
#define RID_INPUT 0x10000003
|
||||
#endif
|
||||
#ifndef RI_KEY_BREAK
|
||||
#define RI_KEY_BREAK 0x1
|
||||
#endif
|
||||
#ifndef RI_KEY_E0
|
||||
#define RI_KEY_E0 0x2
|
||||
#endif
|
||||
#ifndef RI_KEY_E1
|
||||
#define RI_KEY_E1 0x4
|
||||
#endif
|
||||
#ifndef RIM_TYPEMOUSE
|
||||
#define RIM_TYPEMOUSE 0x0
|
||||
#define RIM_TYPEKEYBOARD 0x1
|
||||
#define RIM_TYPEHID 0x2
|
||||
|
||||
typedef struct tagRAWINPUTDEVICE {
|
||||
USHORT usUsagePage;
|
||||
USHORT usUsage;
|
||||
DWORD dwFlags;
|
||||
HWND hwndTarget;
|
||||
} RAWINPUTDEVICE;
|
||||
|
||||
|
||||
|
||||
typedef struct tagRAWINPUTHEADER {
|
||||
DWORD dwType;
|
||||
DWORD dwSize;
|
||||
HANDLE hDevice;
|
||||
WPARAM wParam;
|
||||
} RAWINPUTHEADER;
|
||||
|
||||
typedef struct tagRAWMOUSE {
|
||||
USHORT usFlags;
|
||||
union {
|
||||
ULONG ulButtons;
|
||||
struct {
|
||||
USHORT usButtonFlags;
|
||||
USHORT usButtonData;
|
||||
};
|
||||
};
|
||||
ULONG ulRawButtons;
|
||||
LONG lLastX;
|
||||
LONG lLastY;
|
||||
ULONG ulExtraInformation;
|
||||
} RAWMOUSE;
|
||||
|
||||
typedef struct tagRAWKEYBOARD {
|
||||
USHORT MakeCode;
|
||||
USHORT Flags;
|
||||
USHORT Reserved;
|
||||
USHORT VKey;
|
||||
UINT Message;
|
||||
ULONG ExtraInformation;
|
||||
} RAWKEYBOARD;
|
||||
|
||||
typedef struct tagRAWHID {
|
||||
DWORD dwSizeHid;
|
||||
DWORD dwCount;
|
||||
BYTE bRawData[1];
|
||||
} RAWHID;
|
||||
|
||||
typedef struct tagRAWINPUT {
|
||||
RAWINPUTHEADER header;
|
||||
union {
|
||||
RAWMOUSE mouse;
|
||||
RAWKEYBOARD keyboard;
|
||||
RAWHID hid;
|
||||
} data;
|
||||
} RAWINPUT;
|
||||
|
||||
DECLARE_HANDLE(HRAWINPUT);
|
||||
#endif
|
||||
|
||||
#ifdef FREE_WINDOWS
|
||||
#define NEED_RAW_PROC
|
||||
typedef BOOL (WINAPI * LPFNDLLRRID)(RAWINPUTDEVICE*,UINT, UINT);
|
||||
#define RegisterRawInputDevices(pRawInputDevices, uiNumDevices, cbSize) ((pRegisterRawInputDevices)?pRegisterRawInputDevices(pRawInputDevices, uiNumDevices, cbSize):0)
|
||||
|
||||
|
||||
typedef UINT (WINAPI * LPFNDLLGRID)(HRAWINPUT, UINT, LPVOID, PUINT, UINT);
|
||||
#define GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader) ((pGetRawInputData)?pGetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader):(UINT)-1)
|
||||
#endif
|
||||
|
||||
class GHOST_EventButton;
|
||||
class GHOST_EventCursor;
|
||||
class GHOST_EventKey;
|
||||
class GHOST_EventWheel;
|
||||
class GHOST_EventWindow;
|
||||
class GHOST_EventDragnDrop;
|
||||
|
||||
/**
|
||||
* WIN32 Implementation of GHOST_System class.
|
||||
* @see GHOST_System.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 10, 2001
|
||||
*/
|
||||
class GHOST_SystemWin32 : public GHOST_System {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_SystemWin32();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_SystemWin32();
|
||||
|
||||
/***************************************************************************************
|
||||
** Time(r) functionality
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Returns the system time.
|
||||
* Returns the number of milliseconds since the start of the system process.
|
||||
* This overloaded method uses the high frequency timer if available.
|
||||
* @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 stereoVisual Stereo visual for quad buffered stereo.
|
||||
* @param numOfAASamples Number of samples used for AA (zero if no AA)
|
||||
* @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 = false,
|
||||
const GHOST_TUns16 numOfAASamples = 0,
|
||||
const GHOST_TEmbedderWindowID parentWindow = 0 );
|
||||
|
||||
/***************************************************************************************
|
||||
** 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);
|
||||
|
||||
/***************************************************************************************
|
||||
** 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 unsinged char from CUT_BUFFER0
|
||||
* @param selection Used by X11 only
|
||||
* @return Returns the Clipboard
|
||||
*/
|
||||
virtual GHOST_TUns8* getClipboard(bool selection) const;
|
||||
|
||||
/**
|
||||
* Puts buffer to system clipboard
|
||||
* @param selection Used by X11 only
|
||||
* @return No return
|
||||
*/
|
||||
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
|
||||
|
||||
/**
|
||||
* Creates a drag'n'drop event and pushes it immediately onto the event queue.
|
||||
* Called by GHOST_DropTargetWin32 class.
|
||||
* @param eventType The type of drag'n'drop event
|
||||
* @param draggedObjectType The type object concerned (currently array of file names, string, ?bitmap)
|
||||
* @param mouseX x mouse coordinate (in window coordinates)
|
||||
* @param mouseY y mouse coordinate
|
||||
* @param window The window on which the event occurred
|
||||
* @return Indication whether the event was handled.
|
||||
*/
|
||||
static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType,GHOST_IWindow* window, int mouseX, int mouseY, void* data);
|
||||
|
||||
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();
|
||||
|
||||
/**
|
||||
* Converts raw WIN32 key codes from the wndproc to GHOST keys.
|
||||
* @param window-> The window for this handling
|
||||
* @param vKey The virtual key from hardKey
|
||||
* @param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1)
|
||||
* @param extend Flag if key is not primerly (left or right)
|
||||
* @return The GHOST key (GHOST_kKeyUnknown if no match).
|
||||
*/
|
||||
virtual GHOST_TKey convertKey(GHOST_IWindow *window, short vKey, short ScanCode, short extend) const;
|
||||
|
||||
/**
|
||||
* Catches raw WIN32 key codes from WM_INPUT in the wndproc.
|
||||
* @param window-> The window for this handling
|
||||
* @param wParam The wParam from the wndproc
|
||||
* @param lParam The lParam from the wndproc
|
||||
* @param keyDown Pointer flag that specify if a key is down
|
||||
* @param vk Pointer to virtual key
|
||||
* @return The GHOST key (GHOST_kKeyUnknown if no match).
|
||||
*/
|
||||
virtual GHOST_TKey hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk);
|
||||
|
||||
/**
|
||||
* Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys).
|
||||
* With the modifier keys, we want to distinguish left and right keys.
|
||||
* Sometimes this is not possible (Windows ME for instance). Then, we want
|
||||
* events generated for both keys.
|
||||
* @param window The window receiving the event (the active window).
|
||||
*/
|
||||
GHOST_EventKey* processModifierKeys(GHOST_IWindow *window);
|
||||
|
||||
/**
|
||||
* Creates mouse button event.
|
||||
* @param type The type of event to create.
|
||||
* @param window The window receiving the event (the active window).
|
||||
* @param mask The button mask of this event.
|
||||
* @return The event created.
|
||||
*/
|
||||
static GHOST_EventButton* processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask);
|
||||
|
||||
/**
|
||||
* Creates cursor event.
|
||||
* @param type The type of event to create.
|
||||
* @param window The window receiving the event (the active window).
|
||||
* @return The event created.
|
||||
*/
|
||||
static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow);
|
||||
|
||||
/**
|
||||
* Creates a mouse wheel event.
|
||||
* @param window The window receiving the event (the active window).
|
||||
* @param wParam The wParam from the wndproc
|
||||
* @param lParam The lParam from the wndproc
|
||||
*/
|
||||
static GHOST_EventWheel* processWheelEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
/**
|
||||
* Creates a key event and updates the key data stored locally (m_modifierKeys).
|
||||
* In most cases this is a straightforward conversion of key codes.
|
||||
* For the modifier keys however, we want to distinguish left and right keys.
|
||||
* @param window The window receiving the event (the active window).
|
||||
* @param wParam The wParam from the wndproc
|
||||
* @param lParam The lParam from the wndproc
|
||||
*/
|
||||
static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
/**
|
||||
* Process special keys (VK_OEM_*), to see if current key layout
|
||||
* gives us anything special, like ! on french AZERTY.
|
||||
* @param window The window receiving the event (the active window).
|
||||
* @param vKey The virtual key from hardKey
|
||||
* @param ScanCode The ScanCode of pressed key (simular to PS/2 Set 1)
|
||||
*/
|
||||
virtual GHOST_TKey processSpecialKey(GHOST_IWindow *window, short vKey, short scanCode) const;
|
||||
|
||||
/**
|
||||
* Creates a window event.
|
||||
* @param type The type of event to create.
|
||||
* @param window The window receiving the event (the active window).
|
||||
* @return The event created.
|
||||
*/
|
||||
static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window);
|
||||
/**
|
||||
* Handles minimum window size.
|
||||
* @param minmax The MINMAXINFO structure.
|
||||
*/
|
||||
static void processMinMaxInfo(MINMAXINFO * minmax);
|
||||
|
||||
/**
|
||||
* Returns the local state of the modifier keys (from the message queue).
|
||||
* @param keys The state of the keys.
|
||||
*/
|
||||
inline virtual void retrieveModifierKeys(GHOST_ModifierKeys& keys) const;
|
||||
|
||||
/**
|
||||
* Stores the state of the modifier keys locally.
|
||||
* For internal use only!
|
||||
* @param keys The new state of the modifier keys.
|
||||
*/
|
||||
inline virtual void storeModifierKeys(const GHOST_ModifierKeys& keys);
|
||||
|
||||
/**
|
||||
* Check current key layout for AltGr
|
||||
*/
|
||||
inline virtual void handleKeyboardChange(void);
|
||||
|
||||
/**
|
||||
* Windows call back routine for our window class.
|
||||
*/
|
||||
static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
/**
|
||||
* Initiates WM_INPUT messages from keyboard
|
||||
*/
|
||||
GHOST_TInt32 initKeyboardRawInput(void);
|
||||
|
||||
/**
|
||||
* Toggles console
|
||||
* @action 0 - Hides
|
||||
* 1 - Shows
|
||||
* 2 - Toggles
|
||||
* 3 - Hides if it runs not from command line
|
||||
* * - Does nothing
|
||||
* @return current status (1 -visible, 0 - hidden)
|
||||
*/
|
||||
int toggleConsole(int action);
|
||||
|
||||
/** The current state of the modifier keys. */
|
||||
GHOST_ModifierKeys m_modifierKeys;
|
||||
/** State variable set at initialization. */
|
||||
bool m_hasPerformanceCounter;
|
||||
/** High frequency timer variable. */
|
||||
__int64 m_freq;
|
||||
/** High frequency timer variable. */
|
||||
__int64 m_start;
|
||||
/** AltGr on current keyboard layout. */
|
||||
bool m_hasAltGr;
|
||||
/** language identifier. */
|
||||
WORD m_langId;
|
||||
/** stores keyboard layout. */
|
||||
HKL m_keylayout;
|
||||
|
||||
/** Console status */
|
||||
int m_consoleStatus;
|
||||
|
||||
/** handle for user32.dll*/
|
||||
HMODULE user32;
|
||||
#ifdef NEED_RAW_PROC
|
||||
/* pointer to RegisterRawInputDevices function */
|
||||
LPFNDLLRRID pRegisterRawInputDevices;
|
||||
/* pointer to GetRawInputData function */
|
||||
LPFNDLLGRID pGetRawInputData;
|
||||
#endif
|
||||
};
|
||||
|
||||
inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const
|
||||
{
|
||||
keys = m_modifierKeys;
|
||||
}
|
||||
|
||||
inline void GHOST_SystemWin32::storeModifierKeys(const GHOST_ModifierKeys& keys)
|
||||
{
|
||||
m_modifierKeys = keys;
|
||||
}
|
||||
|
||||
inline void GHOST_SystemWin32::handleKeyboardChange(void)
|
||||
{
|
||||
m_keylayout = GetKeyboardLayout(0); // get keylayout for current thread
|
||||
int i;
|
||||
SHORT s;
|
||||
|
||||
// save the language identifier.
|
||||
m_langId = LOWORD(m_keylayout);
|
||||
|
||||
for(m_hasAltGr = false, i = 32; i < 256; ++i) {
|
||||
s = VkKeyScanEx((char)i, m_keylayout);
|
||||
// s == -1 means no key that translates passed char code
|
||||
// high byte contains shift state. bit 2 ctrl pressed, bit 4 alt pressed
|
||||
// if both are pressed, we have AltGr keycombo on keylayout
|
||||
if(s!=-1 && (s & 0x600) == 0x600) {
|
||||
m_hasAltGr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // _GHOST_SYSTEM_WIN32_H_
|
||||
|
||||
1497
intern/ghost/intern/GHOST_SystemX11.cpp
Normal file
1497
intern/ghost/intern/GHOST_SystemX11.cpp
Normal file
@@ -0,0 +1,1497 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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.
|
||||
*
|
||||
* Part of this code has been taken from Qt, under LGPL license
|
||||
* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file ghost/intern/GHOST_SystemX11.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include "GHOST_SystemX11.h"
|
||||
#include "GHOST_WindowX11.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
#include "GHOST_TimerManager.h"
|
||||
#include "GHOST_EventCursor.h"
|
||||
#include "GHOST_EventKey.h"
|
||||
#include "GHOST_EventButton.h"
|
||||
#include "GHOST_EventWheel.h"
|
||||
#include "GHOST_EventNDOF.h"
|
||||
#include "GHOST_NDOFManager.h"
|
||||
#include "GHOST_DisplayManagerX11.h"
|
||||
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/XKBlib.h> /* allow detectable autorepeate */
|
||||
|
||||
#ifdef WITH_XF86KEYSYM
|
||||
#include <X11/XF86keysym.h>
|
||||
#endif
|
||||
|
||||
#ifdef __sgi
|
||||
|
||||
#if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS)
|
||||
#include <X11/SGIFastAtom.h>
|
||||
#else
|
||||
#define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// For timing
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <stdio.h> // for fprintf only
|
||||
#include <cstdlib> // for exit
|
||||
|
||||
typedef struct NDOFPlatformInfo {
|
||||
Display *display;
|
||||
Window window;
|
||||
volatile GHOST_TEventNDOFData *currValues;
|
||||
Atom cmdAtom;
|
||||
Atom motionAtom;
|
||||
Atom btnPressAtom;
|
||||
Atom btnRelAtom;
|
||||
} NDOFPlatformInfo;
|
||||
|
||||
static NDOFPlatformInfo sNdofInfo = {NULL, 0, NULL, 0, 0, 0, 0};
|
||||
|
||||
|
||||
//these are for copy and select copy
|
||||
static char *txt_cut_buffer= NULL;
|
||||
static char *txt_select_buffer= NULL;
|
||||
|
||||
using namespace std;
|
||||
|
||||
GHOST_SystemX11::
|
||||
GHOST_SystemX11(
|
||||
) :
|
||||
GHOST_System(),
|
||||
m_start_time(0)
|
||||
{
|
||||
m_display = XOpenDisplay(NULL);
|
||||
|
||||
if (!m_display) {
|
||||
std::cerr << "Unable to open a display" << std::endl;
|
||||
abort(); //was return before, but this would just mean it will crash later
|
||||
}
|
||||
|
||||
#ifdef __sgi
|
||||
m_delete_window_atom
|
||||
= XSGIFastInternAtom(m_display,
|
||||
"WM_DELETE_WINDOW",
|
||||
SGI_XA_WM_DELETE_WINDOW, False);
|
||||
#else
|
||||
m_delete_window_atom
|
||||
= XInternAtom(m_display, "WM_DELETE_WINDOW", True);
|
||||
#endif
|
||||
|
||||
m_wm_protocols= XInternAtom(m_display, "WM_PROTOCOLS", False);
|
||||
m_wm_take_focus= XInternAtom(m_display, "WM_TAKE_FOCUS", False);
|
||||
m_wm_state= XInternAtom(m_display, "WM_STATE", False);
|
||||
m_wm_change_state= XInternAtom(m_display, "WM_CHANGE_STATE", False);
|
||||
m_net_state= XInternAtom(m_display, "_NET_WM_STATE", False);
|
||||
m_net_max_horz= XInternAtom(m_display,
|
||||
"_NET_WM_STATE_MAXIMIZED_HORZ", False);
|
||||
m_net_max_vert= XInternAtom(m_display,
|
||||
"_NET_WM_STATE_MAXIMIZED_VERT", False);
|
||||
m_net_fullscreen= XInternAtom(m_display,
|
||||
"_NET_WM_STATE_FULLSCREEN", False);
|
||||
m_motif= XInternAtom(m_display, "_MOTIF_WM_HINTS", False);
|
||||
m_targets= XInternAtom(m_display, "TARGETS", False);
|
||||
m_string= XInternAtom(m_display, "STRING", False);
|
||||
m_compound_text= XInternAtom(m_display, "COMPOUND_TEXT", False);
|
||||
m_text= XInternAtom(m_display, "TEXT", False);
|
||||
m_clipboard= XInternAtom(m_display, "CLIPBOARD", False);
|
||||
m_primary= XInternAtom(m_display, "PRIMARY", False);
|
||||
m_xclip_out= XInternAtom(m_display, "XCLIP_OUT", False);
|
||||
m_incr= XInternAtom(m_display, "INCR", False);
|
||||
m_utf8_string= XInternAtom(m_display, "UTF8_STRING", False);
|
||||
m_last_warp = 0;
|
||||
|
||||
|
||||
// compute the initial time
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv,NULL) == -1) {
|
||||
GHOST_ASSERT(false,"Could not instantiate timer!");
|
||||
}
|
||||
|
||||
m_start_time = GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000);
|
||||
|
||||
|
||||
/* use detectable autorepeate, mac and windows also do this */
|
||||
int use_xkb;
|
||||
int xkb_opcode, xkb_event, xkb_error;
|
||||
int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion;
|
||||
|
||||
use_xkb = XkbQueryExtension(m_display, &xkb_opcode, &xkb_event, &xkb_error, &xkb_major, &xkb_minor);
|
||||
if (use_xkb) {
|
||||
XkbSetDetectableAutoRepeat(m_display, true, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GHOST_SystemX11::
|
||||
~GHOST_SystemX11()
|
||||
{
|
||||
XCloseDisplay(m_display);
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_SystemX11::
|
||||
init(
|
||||
){
|
||||
GHOST_TSuccess success = GHOST_System::init();
|
||||
|
||||
if (success) {
|
||||
m_displayManager = new GHOST_DisplayManagerX11(this);
|
||||
|
||||
if (m_displayManager) {
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TUns64
|
||||
GHOST_SystemX11::
|
||||
getMilliSeconds(
|
||||
) const {
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv,NULL) == -1) {
|
||||
GHOST_ASSERT(false,"Could not compute time!");
|
||||
}
|
||||
|
||||
return GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000) - m_start_time;
|
||||
}
|
||||
|
||||
GHOST_TUns8
|
||||
GHOST_SystemX11::
|
||||
getNumDisplays(
|
||||
) const {
|
||||
return GHOST_TUns8(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the main display on this system.
|
||||
* @return The dimension of the main display.
|
||||
*/
|
||||
void
|
||||
GHOST_SystemX11::
|
||||
getMainDisplayDimensions(
|
||||
GHOST_TUns32& width,
|
||||
GHOST_TUns32& height
|
||||
) const {
|
||||
if (m_display) {
|
||||
width = DisplayWidth(m_display, DefaultScreen(m_display));
|
||||
height = DisplayHeight(m_display, DefaultScreen(m_display));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 stereoVisual Stereo visual for quad buffered stereo.
|
||||
* @param numOfAASamples Number of samples used for AA (zero if no AA)
|
||||
* @param parentWindow Parent (embedder) window
|
||||
* @return The new window (or 0 if creation failed).
|
||||
*/
|
||||
GHOST_IWindow*
|
||||
GHOST_SystemX11::
|
||||
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_TUns16 numOfAASamples,
|
||||
const GHOST_TEmbedderWindowID parentWindow
|
||||
){
|
||||
GHOST_WindowX11 * window = 0;
|
||||
|
||||
if (!m_display) return 0;
|
||||
|
||||
|
||||
|
||||
|
||||
window = new GHOST_WindowX11 (
|
||||
this,m_display,title, left, top, width, height, state, parentWindow, type, stereoVisual
|
||||
);
|
||||
|
||||
if (window) {
|
||||
// Both are now handle in GHOST_WindowX11.cpp
|
||||
// Focus and Delete atoms.
|
||||
|
||||
if (window->getValid()) {
|
||||
// Store the pointer to the window
|
||||
m_windowManager->addWindow(window);
|
||||
|
||||
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
|
||||
}
|
||||
else {
|
||||
delete window;
|
||||
window = 0;
|
||||
}
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
GHOST_WindowX11 *
|
||||
GHOST_SystemX11::
|
||||
findGhostWindow(
|
||||
Window xwind
|
||||
) const {
|
||||
|
||||
if (xwind == 0) return NULL;
|
||||
|
||||
// It is not entirely safe to do this as the backptr may point
|
||||
// to a window that has recently been removed.
|
||||
// We should always check the window manager's list of windows
|
||||
// and only process events on these windows.
|
||||
|
||||
vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
|
||||
|
||||
vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
|
||||
vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
|
||||
|
||||
for (; win_it != win_end; ++win_it) {
|
||||
GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
|
||||
if (window->getXWindow() == xwind) {
|
||||
return window;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
static void SleepTillEvent(Display *display, GHOST_TInt64 maxSleep) {
|
||||
int fd = ConnectionNumber(display);
|
||||
fd_set fds;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
|
||||
if (maxSleep == -1) {
|
||||
select(fd + 1, &fds, NULL, NULL, NULL);
|
||||
} else {
|
||||
timeval tv;
|
||||
|
||||
tv.tv_sec = maxSleep/1000;
|
||||
tv.tv_usec = (maxSleep - tv.tv_sec*1000)*1000;
|
||||
|
||||
select(fd + 1, &fds, NULL, NULL, &tv);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function borrowed from Qt's X11 support
|
||||
* qclipboard_x11.cpp
|
||||
* */
|
||||
struct init_timestamp_data
|
||||
{
|
||||
Time timestamp;
|
||||
};
|
||||
|
||||
static Bool init_timestamp_scanner(Display*, XEvent *event, XPointer arg)
|
||||
{
|
||||
init_timestamp_data *data =
|
||||
reinterpret_cast<init_timestamp_data*>(arg);
|
||||
switch(event->type)
|
||||
{
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
data->timestamp = event->xbutton.time;
|
||||
break;
|
||||
case MotionNotify:
|
||||
data->timestamp = event->xmotion.time;
|
||||
break;
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
data->timestamp = event->xkey.time;
|
||||
break;
|
||||
case PropertyNotify:
|
||||
data->timestamp = event->xproperty.time;
|
||||
break;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
data->timestamp = event->xcrossing.time;
|
||||
break;
|
||||
case SelectionClear:
|
||||
data->timestamp = event->xselectionclear.time;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Time
|
||||
GHOST_SystemX11::
|
||||
lastEventTime(Time default_time) {
|
||||
init_timestamp_data data;
|
||||
data.timestamp = default_time;
|
||||
XEvent ev;
|
||||
XCheckIfEvent(m_display, &ev, &init_timestamp_scanner, (XPointer)&data);
|
||||
|
||||
return data.timestamp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
GHOST_SystemX11::
|
||||
processEvents(
|
||||
bool waitForEvent
|
||||
){
|
||||
// Get all the current events -- translate them into
|
||||
// ghost events and call base class pushEvent() method.
|
||||
|
||||
bool anyProcessed = false;
|
||||
|
||||
do {
|
||||
GHOST_TimerManager* timerMgr = getTimerManager();
|
||||
|
||||
if (waitForEvent && m_dirty_windows.empty() && !XPending(m_display)) {
|
||||
GHOST_TUns64 next = timerMgr->nextFireTime();
|
||||
|
||||
if (next==GHOST_kFireTimeNever) {
|
||||
SleepTillEvent(m_display, -1);
|
||||
} else {
|
||||
GHOST_TInt64 maxSleep = next - getMilliSeconds();
|
||||
|
||||
if(maxSleep >= 0)
|
||||
SleepTillEvent(m_display, next - getMilliSeconds());
|
||||
}
|
||||
}
|
||||
|
||||
if (timerMgr->fireTimers(getMilliSeconds())) {
|
||||
anyProcessed = true;
|
||||
}
|
||||
|
||||
while (XPending(m_display)) {
|
||||
XEvent xevent;
|
||||
XNextEvent(m_display, &xevent);
|
||||
processEvent(&xevent);
|
||||
anyProcessed = true;
|
||||
}
|
||||
|
||||
if (generateWindowExposeEvents()) {
|
||||
anyProcessed = true;
|
||||
}
|
||||
} while (waitForEvent && !anyProcessed);
|
||||
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
void
|
||||
GHOST_SystemX11::processEvent(XEvent *xe)
|
||||
{
|
||||
GHOST_WindowX11 * window = findGhostWindow(xe->xany.window);
|
||||
GHOST_Event * g_event = NULL;
|
||||
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (xe->type) {
|
||||
case Expose:
|
||||
{
|
||||
XExposeEvent & xee = xe->xexpose;
|
||||
|
||||
if (xee.count == 0) {
|
||||
// Only generate a single expose event
|
||||
// per read of the event queue.
|
||||
|
||||
g_event = new
|
||||
GHOST_Event(
|
||||
getMilliSeconds(),
|
||||
GHOST_kEventWindowUpdate,
|
||||
window
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MotionNotify:
|
||||
{
|
||||
XMotionEvent &xme = xe->xmotion;
|
||||
|
||||
if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
|
||||
{
|
||||
GHOST_TInt32 x_new= xme.x_root;
|
||||
GHOST_TInt32 y_new= xme.y_root;
|
||||
GHOST_TInt32 x_accum, y_accum;
|
||||
GHOST_Rect bounds;
|
||||
|
||||
/* fallback to window bounds */
|
||||
if(window->getCursorGrabBounds(bounds)==GHOST_kFailure)
|
||||
window->getClientBounds(bounds);
|
||||
|
||||
/* could also clamp to screen bounds
|
||||
* wrap with a window outside the view will fail atm */
|
||||
bounds.wrapPoint(x_new, y_new, 8); /* offset of one incase blender is at screen bounds */
|
||||
window->getCursorGrabAccum(x_accum, y_accum);
|
||||
|
||||
if(x_new != xme.x_root || y_new != xme.y_root) {
|
||||
if (xme.time > m_last_warp) {
|
||||
/* when wrapping we don't need to add an event because the
|
||||
* setCursorPosition call will cause a new event after */
|
||||
setCursorPosition(x_new, y_new); /* wrap */
|
||||
window->setCursorGrabAccum(x_accum + (xme.x_root - x_new), y_accum + (xme.y_root - y_new));
|
||||
m_last_warp = lastEventTime(xme.time);
|
||||
} else {
|
||||
setCursorPosition(x_new, y_new); /* wrap but don't accumulate */
|
||||
}
|
||||
}
|
||||
else {
|
||||
g_event = new
|
||||
GHOST_EventCursor(
|
||||
getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
window,
|
||||
xme.x_root + x_accum,
|
||||
xme.y_root + y_accum
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
g_event = new
|
||||
GHOST_EventCursor(
|
||||
getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
window,
|
||||
xme.x_root,
|
||||
xme.y_root
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
{
|
||||
XKeyEvent *xke = &(xe->xkey);
|
||||
|
||||
KeySym key_sym = XLookupKeysym(xke,0);
|
||||
char ascii;
|
||||
|
||||
GHOST_TKey gkey = convertXKey(key_sym);
|
||||
GHOST_TEventType type = (xke->type == KeyPress) ?
|
||||
GHOST_kEventKeyDown : GHOST_kEventKeyUp;
|
||||
|
||||
if (!XLookupString(xke, &ascii, 1, NULL, NULL)) {
|
||||
ascii = '\0';
|
||||
}
|
||||
|
||||
g_event = new
|
||||
GHOST_EventKey(
|
||||
getMilliSeconds(),
|
||||
type,
|
||||
window,
|
||||
gkey,
|
||||
ascii
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
{
|
||||
XButtonEvent & xbe = xe->xbutton;
|
||||
GHOST_TButtonMask gbmask = GHOST_kButtonMaskLeft;
|
||||
GHOST_TEventType type = (xbe.type == ButtonPress) ?
|
||||
GHOST_kEventButtonDown : GHOST_kEventButtonUp;
|
||||
|
||||
/* process wheel mouse events and break, only pass on press events */
|
||||
if(xbe.button == Button4) {
|
||||
if(xbe.type == ButtonPress)
|
||||
g_event = new GHOST_EventWheel(getMilliSeconds(), window, 1);
|
||||
break;
|
||||
}
|
||||
else if(xbe.button == Button5) {
|
||||
if(xbe.type == ButtonPress)
|
||||
g_event = new GHOST_EventWheel(getMilliSeconds(), window, -1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* process rest of normal mouse buttons */
|
||||
if(xbe.button == Button1)
|
||||
gbmask = GHOST_kButtonMaskLeft;
|
||||
else if(xbe.button == Button2)
|
||||
gbmask = GHOST_kButtonMaskMiddle;
|
||||
else if(xbe.button == Button3)
|
||||
gbmask = GHOST_kButtonMaskRight;
|
||||
/* It seems events 6 and 7 are for horizontal scrolling.
|
||||
* you can re-order button mapping like this... (swaps 6,7 with 8,9)
|
||||
* xmodmap -e "pointer = 1 2 3 4 5 8 9 6 7"
|
||||
*/
|
||||
else if(xbe.button == 8)
|
||||
gbmask = GHOST_kButtonMaskButton4;
|
||||
else if(xbe.button == 9)
|
||||
gbmask = GHOST_kButtonMaskButton5;
|
||||
else
|
||||
break;
|
||||
|
||||
g_event = new
|
||||
GHOST_EventButton(
|
||||
getMilliSeconds(),
|
||||
type,
|
||||
window,
|
||||
gbmask
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
// change of size, border, layer etc.
|
||||
case ConfigureNotify:
|
||||
{
|
||||
/* XConfigureEvent & xce = xe->xconfigure; */
|
||||
|
||||
g_event = new
|
||||
GHOST_Event(
|
||||
getMilliSeconds(),
|
||||
GHOST_kEventWindowSize,
|
||||
window
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case FocusIn:
|
||||
case FocusOut:
|
||||
{
|
||||
XFocusChangeEvent &xfe = xe->xfocus;
|
||||
|
||||
// May have to look at the type of event and filter some
|
||||
// out.
|
||||
|
||||
GHOST_TEventType gtype = (xfe.type == FocusIn) ?
|
||||
GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate;
|
||||
|
||||
g_event = new
|
||||
GHOST_Event(
|
||||
getMilliSeconds(),
|
||||
gtype,
|
||||
window
|
||||
);
|
||||
break;
|
||||
|
||||
}
|
||||
case ClientMessage:
|
||||
{
|
||||
XClientMessageEvent & xcme = xe->xclient;
|
||||
|
||||
#ifndef __sgi
|
||||
if (((Atom)xcme.data.l[0]) == m_delete_window_atom) {
|
||||
g_event = new
|
||||
GHOST_Event(
|
||||
getMilliSeconds(),
|
||||
GHOST_kEventWindowClose,
|
||||
window
|
||||
);
|
||||
} else
|
||||
#endif
|
||||
if (sNdofInfo.currValues) {
|
||||
static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0};
|
||||
if (xcme.message_type == sNdofInfo.motionAtom)
|
||||
{
|
||||
data.changed = 1;
|
||||
data.delta = xcme.data.s[8] - data.time;
|
||||
data.time = xcme.data.s[8];
|
||||
data.tx = xcme.data.s[2] >> 2;
|
||||
data.ty = xcme.data.s[3] >> 2;
|
||||
data.tz = xcme.data.s[4] >> 2;
|
||||
data.rx = xcme.data.s[5];
|
||||
data.ry = xcme.data.s[6];
|
||||
data.rz =-xcme.data.s[7];
|
||||
g_event = new GHOST_EventNDOF(getMilliSeconds(),
|
||||
GHOST_kEventNDOFMotion,
|
||||
window, data);
|
||||
} else if (xcme.message_type == sNdofInfo.btnPressAtom) {
|
||||
data.changed = 2;
|
||||
data.delta = xcme.data.s[8] - data.time;
|
||||
data.time = xcme.data.s[8];
|
||||
data.buttons = xcme.data.s[2];
|
||||
g_event = new GHOST_EventNDOF(getMilliSeconds(),
|
||||
GHOST_kEventNDOFButton,
|
||||
window, data);
|
||||
}
|
||||
} else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) {
|
||||
XWindowAttributes attr;
|
||||
Window fwin;
|
||||
int revert_to;
|
||||
|
||||
/* as ICCCM say, we need reply this event
|
||||
* with a SetInputFocus, the data[1] have
|
||||
* the valid timestamp (send by the wm).
|
||||
*
|
||||
* Some WM send this event before the
|
||||
* window is really mapped (for example
|
||||
* change from virtual desktop), so we need
|
||||
* to be sure that our windows is mapped
|
||||
* or this call fail and close blender.
|
||||
*/
|
||||
if (XGetWindowAttributes(m_display, xcme.window, &attr) == True) {
|
||||
if (XGetInputFocus(m_display, &fwin, &revert_to) == True) {
|
||||
if (attr.map_state == IsViewable) {
|
||||
if (fwin != xcme.window)
|
||||
XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Unknown client message, ignore */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DestroyNotify:
|
||||
::exit(-1);
|
||||
// We're not interested in the following things.(yet...)
|
||||
case NoExpose :
|
||||
case GraphicsExpose :
|
||||
break;
|
||||
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
{
|
||||
/* XCrossingEvents pointer leave enter window.
|
||||
also do cursor move here, MotionNotify only
|
||||
happens when motion starts & ends inside window.
|
||||
we only do moves when the crossing mode is 'normal'
|
||||
(really crossing between windows) since some windowmanagers
|
||||
also send grab/ungrab crossings for mousewheel events.
|
||||
*/
|
||||
XCrossingEvent &xce = xe->xcrossing;
|
||||
if( xce.mode == NotifyNormal ) {
|
||||
g_event = new
|
||||
GHOST_EventCursor(
|
||||
getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
window,
|
||||
xce.x_root,
|
||||
xce.y_root
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MapNotify:
|
||||
/*
|
||||
* From ICCCM:
|
||||
* [ Clients can select for StructureNotify on their
|
||||
* top-level windows to track transition between
|
||||
* Normal and Iconic states. Receipt of a MapNotify
|
||||
* event will indicate a transition to the Normal
|
||||
* state, and receipt of an UnmapNotify event will
|
||||
* indicate a transition to the Iconic state. ]
|
||||
*/
|
||||
if (window->m_post_init == True) {
|
||||
/*
|
||||
* Now we are sure that the window is
|
||||
* mapped, so only need change the state.
|
||||
*/
|
||||
window->setState (window->m_post_state);
|
||||
window->m_post_init = False;
|
||||
}
|
||||
break;
|
||||
case UnmapNotify:
|
||||
break;
|
||||
case MappingNotify:
|
||||
case ReparentNotify:
|
||||
break;
|
||||
case SelectionRequest:
|
||||
{
|
||||
XEvent nxe;
|
||||
Atom target, string, compound_text, c_string;
|
||||
XSelectionRequestEvent *xse = &xe->xselectionrequest;
|
||||
|
||||
target = XInternAtom(m_display, "TARGETS", False);
|
||||
string = XInternAtom(m_display, "STRING", False);
|
||||
compound_text = XInternAtom(m_display, "COMPOUND_TEXT", False);
|
||||
c_string = XInternAtom(m_display, "C_STRING", False);
|
||||
|
||||
/* support obsolete clients */
|
||||
if (xse->property == None) {
|
||||
xse->property = xse->target;
|
||||
}
|
||||
|
||||
nxe.xselection.type = SelectionNotify;
|
||||
nxe.xselection.requestor = xse->requestor;
|
||||
nxe.xselection.property = xse->property;
|
||||
nxe.xselection.display = xse->display;
|
||||
nxe.xselection.selection = xse->selection;
|
||||
nxe.xselection.target = xse->target;
|
||||
nxe.xselection.time = xse->time;
|
||||
|
||||
/*Check to see if the requestor is asking for String*/
|
||||
if(xse->target == string || xse->target == compound_text || xse->target == c_string) {
|
||||
if (xse->selection == XInternAtom(m_display, "PRIMARY", False)) {
|
||||
XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 8, PropModeReplace, (unsigned char*)txt_select_buffer, strlen(txt_select_buffer));
|
||||
} else if (xse->selection == XInternAtom(m_display, "CLIPBOARD", False)) {
|
||||
XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 8, PropModeReplace, (unsigned char*)txt_cut_buffer, strlen(txt_cut_buffer));
|
||||
}
|
||||
} else if (xse->target == target) {
|
||||
Atom alist[4];
|
||||
alist[0] = target;
|
||||
alist[1] = string;
|
||||
alist[2] = compound_text;
|
||||
alist[3] = c_string;
|
||||
XChangeProperty(m_display, xse->requestor, xse->property, xse->target, 32, PropModeReplace, (unsigned char*)alist, 4);
|
||||
XFlush(m_display);
|
||||
} else {
|
||||
//Change property to None because we do not support anything but STRING
|
||||
nxe.xselection.property = None;
|
||||
}
|
||||
|
||||
//Send the event to the client 0 0 == False, SelectionNotify
|
||||
XSendEvent(m_display, xse->requestor, 0, 0, &nxe);
|
||||
XFlush(m_display);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
if(xe->type == window->GetXTablet().MotionEvent)
|
||||
{
|
||||
XDeviceMotionEvent* data = (XDeviceMotionEvent*)xe;
|
||||
window->GetXTablet().CommonData.Pressure=
|
||||
data->axis_data[2]/((float)window->GetXTablet().PressureLevels);
|
||||
|
||||
/* the (short) cast and the &0xffff is bizarre and unexplained anywhere,
|
||||
* but I got garbage data without it. Found it in the xidump.c source --matt */
|
||||
window->GetXTablet().CommonData.Xtilt=
|
||||
(short)(data->axis_data[3]&0xffff)/((float)window->GetXTablet().XtiltLevels);
|
||||
window->GetXTablet().CommonData.Ytilt=
|
||||
(short)(data->axis_data[4]&0xffff)/((float)window->GetXTablet().YtiltLevels);
|
||||
}
|
||||
else if(xe->type == window->GetXTablet().ProxInEvent)
|
||||
{
|
||||
XProximityNotifyEvent* data = (XProximityNotifyEvent*)xe;
|
||||
if(data->deviceid == window->GetXTablet().StylusID)
|
||||
window->GetXTablet().CommonData.Active= GHOST_kTabletModeStylus;
|
||||
else if(data->deviceid == window->GetXTablet().EraserID)
|
||||
window->GetXTablet().CommonData.Active= GHOST_kTabletModeEraser;
|
||||
}
|
||||
else if(xe->type == window->GetXTablet().ProxOutEvent)
|
||||
window->GetXTablet().CommonData.Active= GHOST_kTabletModeNone;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_event) {
|
||||
pushEvent(g_event);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
GHOST_SystemX11::
|
||||
prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues)
|
||||
{
|
||||
const vector<GHOST_IWindow*>& v(m_windowManager->getWindows());
|
||||
if (v.size() > 0)
|
||||
sNdofInfo.window = static_cast<GHOST_WindowX11*>(v[0])->getXWindow();
|
||||
sNdofInfo.display = m_display;
|
||||
sNdofInfo.currValues = currentNdofValues;
|
||||
return (void*)&sNdofInfo;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_SystemX11::
|
||||
getModifierKeys(
|
||||
GHOST_ModifierKeys& keys
|
||||
) const {
|
||||
|
||||
// analyse the masks retuned from XQueryPointer.
|
||||
|
||||
memset((void *)m_keyboard_vector,0,sizeof(m_keyboard_vector));
|
||||
|
||||
XQueryKeymap(m_display,(char *)m_keyboard_vector);
|
||||
|
||||
// now translate key symobols into keycodes and
|
||||
// test with vector.
|
||||
|
||||
const KeyCode shift_l = XKeysymToKeycode(m_display,XK_Shift_L);
|
||||
const KeyCode shift_r = XKeysymToKeycode(m_display,XK_Shift_R);
|
||||
const KeyCode control_l = XKeysymToKeycode(m_display,XK_Control_L);
|
||||
const KeyCode control_r = XKeysymToKeycode(m_display,XK_Control_R);
|
||||
const KeyCode alt_l = XKeysymToKeycode(m_display,XK_Alt_L);
|
||||
const KeyCode alt_r = XKeysymToKeycode(m_display,XK_Alt_R);
|
||||
const KeyCode super_l = XKeysymToKeycode(m_display,XK_Super_L);
|
||||
const KeyCode super_r = XKeysymToKeycode(m_display,XK_Super_R);
|
||||
|
||||
// Shift
|
||||
if ((m_keyboard_vector[shift_l >> 3] >> (shift_l & 7)) & 1) {
|
||||
keys.set(GHOST_kModifierKeyLeftShift,true);
|
||||
} else {
|
||||
keys.set(GHOST_kModifierKeyLeftShift,false);
|
||||
}
|
||||
if ((m_keyboard_vector[shift_r >> 3] >> (shift_r & 7)) & 1) {
|
||||
|
||||
keys.set(GHOST_kModifierKeyRightShift,true);
|
||||
} else {
|
||||
keys.set(GHOST_kModifierKeyRightShift,false);
|
||||
}
|
||||
|
||||
// control (weep)
|
||||
if ((m_keyboard_vector[control_l >> 3] >> (control_l & 7)) & 1) {
|
||||
keys.set(GHOST_kModifierKeyLeftControl,true);
|
||||
} else {
|
||||
keys.set(GHOST_kModifierKeyLeftControl,false);
|
||||
}
|
||||
if ((m_keyboard_vector[control_r >> 3] >> (control_r & 7)) & 1) {
|
||||
keys.set(GHOST_kModifierKeyRightControl,true);
|
||||
} else {
|
||||
keys.set(GHOST_kModifierKeyRightControl,false);
|
||||
}
|
||||
|
||||
// Alt (yawn)
|
||||
if ((m_keyboard_vector[alt_l >> 3] >> (alt_l & 7)) & 1) {
|
||||
keys.set(GHOST_kModifierKeyLeftAlt,true);
|
||||
} else {
|
||||
keys.set(GHOST_kModifierKeyLeftAlt,false);
|
||||
}
|
||||
if ((m_keyboard_vector[alt_r >> 3] >> (alt_r & 7)) & 1) {
|
||||
keys.set(GHOST_kModifierKeyRightAlt,true);
|
||||
} else {
|
||||
keys.set(GHOST_kModifierKeyRightAlt,false);
|
||||
}
|
||||
|
||||
// Super (Windows) - only one GHOST-kModifierKeyOS, so mapping
|
||||
// to either
|
||||
if ( ((m_keyboard_vector[super_l >> 3] >> (super_l & 7)) & 1) ||
|
||||
((m_keyboard_vector[super_r >> 3] >> (super_r & 7)) & 1) ) {
|
||||
keys.set(GHOST_kModifierKeyOS,true);
|
||||
} else {
|
||||
keys.set(GHOST_kModifierKeyOS,false);
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_SystemX11::
|
||||
getButtons(
|
||||
GHOST_Buttons& buttons
|
||||
) const {
|
||||
|
||||
Window root_return, child_return;
|
||||
int rx,ry,wx,wy;
|
||||
unsigned int mask_return;
|
||||
|
||||
if (XQueryPointer(
|
||||
m_display,
|
||||
RootWindow(m_display,DefaultScreen(m_display)),
|
||||
&root_return,
|
||||
&child_return,
|
||||
&rx,&ry,
|
||||
&wx,&wy,
|
||||
&mask_return
|
||||
) == False) {
|
||||
return GHOST_kFailure;
|
||||
} else {
|
||||
|
||||
if (mask_return & Button1Mask) {
|
||||
buttons.set(GHOST_kButtonMaskLeft,true);
|
||||
} else {
|
||||
buttons.set(GHOST_kButtonMaskLeft,false);
|
||||
}
|
||||
|
||||
if (mask_return & Button2Mask) {
|
||||
buttons.set(GHOST_kButtonMaskMiddle,true);
|
||||
} else {
|
||||
buttons.set(GHOST_kButtonMaskMiddle,false);
|
||||
}
|
||||
|
||||
if (mask_return & Button3Mask) {
|
||||
buttons.set(GHOST_kButtonMaskRight,true);
|
||||
} else {
|
||||
buttons.set(GHOST_kButtonMaskRight,false);
|
||||
}
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_SystemX11::
|
||||
getCursorPosition(
|
||||
GHOST_TInt32& x,
|
||||
GHOST_TInt32& y
|
||||
) const {
|
||||
|
||||
Window root_return, child_return;
|
||||
int rx,ry,wx,wy;
|
||||
unsigned int mask_return;
|
||||
|
||||
if (XQueryPointer(
|
||||
m_display,
|
||||
RootWindow(m_display,DefaultScreen(m_display)),
|
||||
&root_return,
|
||||
&child_return,
|
||||
&rx,&ry,
|
||||
&wx,&wy,
|
||||
&mask_return
|
||||
) == False) {
|
||||
return GHOST_kFailure;
|
||||
} else {
|
||||
x = rx;
|
||||
y = ry;
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_SystemX11::
|
||||
setCursorPosition(
|
||||
GHOST_TInt32 x,
|
||||
GHOST_TInt32 y
|
||||
) {
|
||||
|
||||
// This is a brute force move in screen coordinates
|
||||
// XWarpPointer does relative moves so first determine the
|
||||
// current pointer position.
|
||||
|
||||
int cx,cy;
|
||||
if (getCursorPosition(cx,cy) == GHOST_kFailure) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
int relx = x-cx;
|
||||
int rely = y-cy;
|
||||
|
||||
XWarpPointer(m_display,None,None,0,0,0,0,relx,rely);
|
||||
XSync(m_display, 0); /* Sync to process all requests */
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GHOST_SystemX11::
|
||||
addDirtyWindow(
|
||||
GHOST_WindowX11 * bad_wind
|
||||
){
|
||||
|
||||
GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)");
|
||||
|
||||
m_dirty_windows.push_back(bad_wind);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GHOST_SystemX11::
|
||||
generateWindowExposeEvents(
|
||||
){
|
||||
|
||||
vector<GHOST_WindowX11 *>::iterator w_start = m_dirty_windows.begin();
|
||||
vector<GHOST_WindowX11 *>::const_iterator w_end = m_dirty_windows.end();
|
||||
bool anyProcessed = false;
|
||||
|
||||
for (;w_start != w_end; ++w_start) {
|
||||
GHOST_Event * g_event = new
|
||||
GHOST_Event(
|
||||
getMilliSeconds(),
|
||||
GHOST_kEventWindowUpdate,
|
||||
*w_start
|
||||
);
|
||||
|
||||
(*w_start)->validate();
|
||||
|
||||
if (g_event) {
|
||||
pushEvent(g_event);
|
||||
anyProcessed = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_dirty_windows.clear();
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
#define GXMAP(k,x,y) case x: k = y; break;
|
||||
|
||||
GHOST_TKey
|
||||
GHOST_SystemX11::
|
||||
convertXKey(
|
||||
KeySym key
|
||||
){
|
||||
GHOST_TKey type;
|
||||
|
||||
if ((key >= XK_A) && (key <= XK_Z)) {
|
||||
type = GHOST_TKey( key - XK_A + int(GHOST_kKeyA));
|
||||
} else if ((key >= XK_a) && (key <= XK_z)) {
|
||||
type = GHOST_TKey(key - XK_a + int(GHOST_kKeyA));
|
||||
} else if ((key >= XK_0) && (key <= XK_9)) {
|
||||
type = GHOST_TKey(key - XK_0 + int(GHOST_kKey0));
|
||||
} else if ((key >= XK_F1) && (key <= XK_F24)) {
|
||||
type = GHOST_TKey(key - XK_F1 + int(GHOST_kKeyF1));
|
||||
#if defined(__sun) || defined(__sun__)
|
||||
/* This is a bit of a hack, but it looks like sun
|
||||
Used F11 and friends for its special keys Stop,again etc..
|
||||
So this little patch enables F11 and F12 to work as expected
|
||||
following link has documentation on it:
|
||||
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4734408
|
||||
also from /usr/include/X11/Sunkeysym.h
|
||||
#define SunXK_F36 0x1005FF10 // Labeled F11
|
||||
#define SunXK_F37 0x1005FF11 // Labeled F12
|
||||
|
||||
mein@cs.umn.edu
|
||||
*/
|
||||
|
||||
} else if (key == 268828432) {
|
||||
type = GHOST_kKeyF11;
|
||||
} else if (key == 268828433) {
|
||||
type = GHOST_kKeyF12;
|
||||
#endif
|
||||
} else {
|
||||
switch(key) {
|
||||
GXMAP(type,XK_BackSpace, GHOST_kKeyBackSpace);
|
||||
GXMAP(type,XK_Tab, GHOST_kKeyTab);
|
||||
GXMAP(type,XK_Return, GHOST_kKeyEnter);
|
||||
GXMAP(type,XK_Escape, GHOST_kKeyEsc);
|
||||
GXMAP(type,XK_space, GHOST_kKeySpace);
|
||||
|
||||
GXMAP(type,XK_Linefeed, GHOST_kKeyLinefeed);
|
||||
GXMAP(type,XK_semicolon, GHOST_kKeySemicolon);
|
||||
GXMAP(type,XK_period, GHOST_kKeyPeriod);
|
||||
GXMAP(type,XK_comma, GHOST_kKeyComma);
|
||||
GXMAP(type,XK_quoteright, GHOST_kKeyQuote);
|
||||
GXMAP(type,XK_quoteleft, GHOST_kKeyAccentGrave);
|
||||
GXMAP(type,XK_minus, GHOST_kKeyMinus);
|
||||
GXMAP(type,XK_slash, GHOST_kKeySlash);
|
||||
GXMAP(type,XK_backslash, GHOST_kKeyBackslash);
|
||||
GXMAP(type,XK_equal, GHOST_kKeyEqual);
|
||||
GXMAP(type,XK_bracketleft, GHOST_kKeyLeftBracket);
|
||||
GXMAP(type,XK_bracketright, GHOST_kKeyRightBracket);
|
||||
GXMAP(type,XK_Pause, GHOST_kKeyPause);
|
||||
|
||||
GXMAP(type,XK_Shift_L, GHOST_kKeyLeftShift);
|
||||
GXMAP(type,XK_Shift_R, GHOST_kKeyRightShift);
|
||||
GXMAP(type,XK_Control_L, GHOST_kKeyLeftControl);
|
||||
GXMAP(type,XK_Control_R, GHOST_kKeyRightControl);
|
||||
GXMAP(type,XK_Alt_L, GHOST_kKeyLeftAlt);
|
||||
GXMAP(type,XK_Alt_R, GHOST_kKeyRightAlt);
|
||||
GXMAP(type,XK_Super_L, GHOST_kKeyOS);
|
||||
GXMAP(type,XK_Super_R, GHOST_kKeyOS);
|
||||
|
||||
GXMAP(type,XK_Insert, GHOST_kKeyInsert);
|
||||
GXMAP(type,XK_Delete, GHOST_kKeyDelete);
|
||||
GXMAP(type,XK_Home, GHOST_kKeyHome);
|
||||
GXMAP(type,XK_End, GHOST_kKeyEnd);
|
||||
GXMAP(type,XK_Page_Up, GHOST_kKeyUpPage);
|
||||
GXMAP(type,XK_Page_Down, GHOST_kKeyDownPage);
|
||||
|
||||
GXMAP(type,XK_Left, GHOST_kKeyLeftArrow);
|
||||
GXMAP(type,XK_Right, GHOST_kKeyRightArrow);
|
||||
GXMAP(type,XK_Up, GHOST_kKeyUpArrow);
|
||||
GXMAP(type,XK_Down, GHOST_kKeyDownArrow);
|
||||
|
||||
GXMAP(type,XK_Caps_Lock, GHOST_kKeyCapsLock);
|
||||
GXMAP(type,XK_Scroll_Lock, GHOST_kKeyScrollLock);
|
||||
GXMAP(type,XK_Num_Lock, GHOST_kKeyNumLock);
|
||||
|
||||
/* keypad events */
|
||||
|
||||
GXMAP(type,XK_KP_0, GHOST_kKeyNumpad0);
|
||||
GXMAP(type,XK_KP_1, GHOST_kKeyNumpad1);
|
||||
GXMAP(type,XK_KP_2, GHOST_kKeyNumpad2);
|
||||
GXMAP(type,XK_KP_3, GHOST_kKeyNumpad3);
|
||||
GXMAP(type,XK_KP_4, GHOST_kKeyNumpad4);
|
||||
GXMAP(type,XK_KP_5, GHOST_kKeyNumpad5);
|
||||
GXMAP(type,XK_KP_6, GHOST_kKeyNumpad6);
|
||||
GXMAP(type,XK_KP_7, GHOST_kKeyNumpad7);
|
||||
GXMAP(type,XK_KP_8, GHOST_kKeyNumpad8);
|
||||
GXMAP(type,XK_KP_9, GHOST_kKeyNumpad9);
|
||||
GXMAP(type,XK_KP_Decimal, GHOST_kKeyNumpadPeriod);
|
||||
|
||||
GXMAP(type,XK_KP_Insert, GHOST_kKeyNumpad0);
|
||||
GXMAP(type,XK_KP_End, GHOST_kKeyNumpad1);
|
||||
GXMAP(type,XK_KP_Down, GHOST_kKeyNumpad2);
|
||||
GXMAP(type,XK_KP_Page_Down, GHOST_kKeyNumpad3);
|
||||
GXMAP(type,XK_KP_Left, GHOST_kKeyNumpad4);
|
||||
GXMAP(type,XK_KP_Begin, GHOST_kKeyNumpad5);
|
||||
GXMAP(type,XK_KP_Right, GHOST_kKeyNumpad6);
|
||||
GXMAP(type,XK_KP_Home, GHOST_kKeyNumpad7);
|
||||
GXMAP(type,XK_KP_Up, GHOST_kKeyNumpad8);
|
||||
GXMAP(type,XK_KP_Page_Up, GHOST_kKeyNumpad9);
|
||||
GXMAP(type,XK_KP_Delete, GHOST_kKeyNumpadPeriod);
|
||||
|
||||
GXMAP(type,XK_KP_Enter, GHOST_kKeyNumpadEnter);
|
||||
GXMAP(type,XK_KP_Add, GHOST_kKeyNumpadPlus);
|
||||
GXMAP(type,XK_KP_Subtract, GHOST_kKeyNumpadMinus);
|
||||
GXMAP(type,XK_KP_Multiply, GHOST_kKeyNumpadAsterisk);
|
||||
GXMAP(type,XK_KP_Divide, GHOST_kKeyNumpadSlash);
|
||||
|
||||
/* Media keys in some keyboards and laptops with XFree86/Xorg */
|
||||
#ifdef WITH_XF86KEYSYM
|
||||
GXMAP(type,XF86XK_AudioPlay, GHOST_kKeyMediaPlay);
|
||||
GXMAP(type,XF86XK_AudioStop, GHOST_kKeyMediaStop);
|
||||
GXMAP(type,XF86XK_AudioPrev, GHOST_kKeyMediaFirst);
|
||||
GXMAP(type,XF86XK_AudioRewind, GHOST_kKeyMediaFirst);
|
||||
GXMAP(type,XF86XK_AudioNext, GHOST_kKeyMediaLast);
|
||||
GXMAP(type,XF86XK_AudioForward, GHOST_kKeyMediaLast);
|
||||
#endif
|
||||
|
||||
/* some extra sun cruft (NICE KEYBOARD!) */
|
||||
#ifdef __sun__
|
||||
GXMAP(type,0xffde, GHOST_kKeyNumpad1);
|
||||
GXMAP(type,0xffe0, GHOST_kKeyNumpad3);
|
||||
GXMAP(type,0xffdc, GHOST_kKeyNumpad5);
|
||||
GXMAP(type,0xffd8, GHOST_kKeyNumpad7);
|
||||
GXMAP(type,0xffda, GHOST_kKeyNumpad9);
|
||||
|
||||
GXMAP(type,0xffd6, GHOST_kKeyNumpadSlash);
|
||||
GXMAP(type,0xffd7, GHOST_kKeyNumpadAsterisk);
|
||||
#endif
|
||||
|
||||
default :
|
||||
type = GHOST_kKeyUnknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
#undef GXMAP
|
||||
|
||||
/* from xclip.c xcout() v0.11 */
|
||||
|
||||
#define XCLIB_XCOUT_NONE 0 /* no context */
|
||||
#define XCLIB_XCOUT_SENTCONVSEL 1 /* sent a request */
|
||||
#define XCLIB_XCOUT_INCR 2 /* in an incr loop */
|
||||
#define XCLIB_XCOUT_FALLBACK 3 /* STRING failed, need fallback to UTF8 */
|
||||
#define XCLIB_XCOUT_FALLBACK_UTF8 4 /* UTF8 failed, move to compouned */
|
||||
#define XCLIB_XCOUT_FALLBACK_COMP 5 /* compouned failed, move to text. */
|
||||
#define XCLIB_XCOUT_FALLBACK_TEXT 6
|
||||
|
||||
// Retrieves the contents of a selections.
|
||||
void GHOST_SystemX11::getClipboard_xcout(XEvent evt,
|
||||
Atom sel, Atom target, unsigned char **txt,
|
||||
unsigned long *len, unsigned int *context) const
|
||||
{
|
||||
Atom pty_type;
|
||||
int pty_format;
|
||||
unsigned char *buffer;
|
||||
unsigned long pty_size, pty_items;
|
||||
unsigned char *ltxt= *txt;
|
||||
|
||||
vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
|
||||
vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
|
||||
GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
|
||||
Window win = window->getXWindow();
|
||||
|
||||
switch (*context) {
|
||||
// There is no context, do an XConvertSelection()
|
||||
case XCLIB_XCOUT_NONE:
|
||||
// Initialise return length to 0
|
||||
if (*len > 0) {
|
||||
free(*txt);
|
||||
*len = 0;
|
||||
}
|
||||
|
||||
// Send a selection request
|
||||
XConvertSelection(m_display, sel, target, m_xclip_out, win, CurrentTime);
|
||||
*context = XCLIB_XCOUT_SENTCONVSEL;
|
||||
return;
|
||||
|
||||
case XCLIB_XCOUT_SENTCONVSEL:
|
||||
if (evt.type != SelectionNotify)
|
||||
return;
|
||||
|
||||
if (target == m_utf8_string && evt.xselection.property == None) {
|
||||
*context= XCLIB_XCOUT_FALLBACK_UTF8;
|
||||
return;
|
||||
}
|
||||
else if (target == m_compound_text && evt.xselection.property == None) {
|
||||
*context= XCLIB_XCOUT_FALLBACK_COMP;
|
||||
return;
|
||||
}
|
||||
else if (target == m_text && evt.xselection.property == None) {
|
||||
*context= XCLIB_XCOUT_FALLBACK_TEXT;
|
||||
return;
|
||||
}
|
||||
|
||||
// find the size and format of the data in property
|
||||
XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False,
|
||||
AnyPropertyType, &pty_type, &pty_format,
|
||||
&pty_items, &pty_size, &buffer);
|
||||
XFree(buffer);
|
||||
|
||||
if (pty_type == m_incr) {
|
||||
// start INCR mechanism by deleting property
|
||||
XDeleteProperty(m_display, win, m_xclip_out);
|
||||
XFlush(m_display);
|
||||
*context = XCLIB_XCOUT_INCR;
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's not incr, and not format == 8, then there's
|
||||
// nothing in the selection (that xclip understands, anyway)
|
||||
|
||||
if (pty_format != 8) {
|
||||
*context = XCLIB_XCOUT_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
// not using INCR mechanism, just read the property
|
||||
XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size,
|
||||
False, AnyPropertyType, &pty_type,
|
||||
&pty_format, &pty_items, &pty_size, &buffer);
|
||||
|
||||
// finished with property, delete it
|
||||
XDeleteProperty(m_display, win, m_xclip_out);
|
||||
|
||||
// copy the buffer to the pointer for returned data
|
||||
ltxt = (unsigned char *) malloc(pty_items);
|
||||
memcpy(ltxt, buffer, pty_items);
|
||||
|
||||
// set the length of the returned data
|
||||
*len = pty_items;
|
||||
*txt = ltxt;
|
||||
|
||||
// free the buffer
|
||||
XFree(buffer);
|
||||
|
||||
*context = XCLIB_XCOUT_NONE;
|
||||
|
||||
// complete contents of selection fetched, return 1
|
||||
return;
|
||||
|
||||
case XCLIB_XCOUT_INCR:
|
||||
// To use the INCR method, we basically delete the
|
||||
// property with the selection in it, wait for an
|
||||
// event indicating that the property has been created,
|
||||
// then read it, delete it, etc.
|
||||
|
||||
// make sure that the event is relevant
|
||||
if (evt.type != PropertyNotify)
|
||||
return;
|
||||
|
||||
// skip unless the property has a new value
|
||||
if (evt.xproperty.state != PropertyNewValue)
|
||||
return;
|
||||
|
||||
// check size and format of the property
|
||||
XGetWindowProperty(m_display, win, m_xclip_out, 0, 0, False,
|
||||
AnyPropertyType, &pty_type, &pty_format,
|
||||
&pty_items, &pty_size, (unsigned char **) &buffer);
|
||||
|
||||
if (pty_format != 8) {
|
||||
// property does not contain text, delete it
|
||||
// to tell the other X client that we have read
|
||||
// it and to send the next property
|
||||
XFree(buffer);
|
||||
XDeleteProperty(m_display, win, m_xclip_out);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pty_size == 0) {
|
||||
// no more data, exit from loop
|
||||
XFree(buffer);
|
||||
XDeleteProperty(m_display, win, m_xclip_out);
|
||||
*context = XCLIB_XCOUT_NONE;
|
||||
|
||||
// this means that an INCR transfer is now
|
||||
// complete, return 1
|
||||
return;
|
||||
}
|
||||
|
||||
XFree(buffer);
|
||||
|
||||
// if we have come this far, the propery contains
|
||||
// text, we know the size.
|
||||
XGetWindowProperty(m_display, win, m_xclip_out, 0, (long) pty_size,
|
||||
False, AnyPropertyType, &pty_type, &pty_format,
|
||||
&pty_items, &pty_size, (unsigned char **) &buffer);
|
||||
|
||||
// allocate memory to accommodate data in *txt
|
||||
if (*len == 0) {
|
||||
*len = pty_items;
|
||||
ltxt = (unsigned char *) malloc(*len);
|
||||
}
|
||||
else {
|
||||
*len += pty_items;
|
||||
ltxt = (unsigned char *) realloc(ltxt, *len);
|
||||
}
|
||||
|
||||
// add data to ltxt
|
||||
memcpy(<xt[*len - pty_items], buffer, pty_items);
|
||||
|
||||
*txt = ltxt;
|
||||
XFree(buffer);
|
||||
|
||||
// delete property to get the next item
|
||||
XDeleteProperty(m_display, win, m_xclip_out);
|
||||
XFlush(m_display);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const
|
||||
{
|
||||
Atom sseln;
|
||||
Atom target= m_string;
|
||||
Window owner;
|
||||
|
||||
// from xclip.c doOut() v0.11
|
||||
unsigned char *sel_buf;
|
||||
unsigned long sel_len= 0;
|
||||
XEvent evt;
|
||||
unsigned int context= XCLIB_XCOUT_NONE;
|
||||
|
||||
if (selection == True)
|
||||
sseln= m_primary;
|
||||
else
|
||||
sseln= m_clipboard;
|
||||
|
||||
vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
|
||||
vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
|
||||
GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
|
||||
Window win = window->getXWindow();
|
||||
|
||||
/* check if we are the owner. */
|
||||
owner= XGetSelectionOwner(m_display, sseln);
|
||||
if (owner == win) {
|
||||
if (sseln == m_clipboard) {
|
||||
sel_buf= (unsigned char *)malloc(strlen(txt_cut_buffer)+1);
|
||||
strcpy((char *)sel_buf, txt_cut_buffer);
|
||||
return((GHOST_TUns8*)sel_buf);
|
||||
}
|
||||
else {
|
||||
sel_buf= (unsigned char *)malloc(strlen(txt_select_buffer)+1);
|
||||
strcpy((char *)sel_buf, txt_select_buffer);
|
||||
return((GHOST_TUns8*)sel_buf);
|
||||
}
|
||||
}
|
||||
else if (owner == None)
|
||||
return(NULL);
|
||||
|
||||
while (1) {
|
||||
/* only get an event if xcout() is doing something */
|
||||
if (context != XCLIB_XCOUT_NONE)
|
||||
XNextEvent(m_display, &evt);
|
||||
|
||||
/* fetch the selection, or part of it */
|
||||
getClipboard_xcout(evt, sseln, target, &sel_buf, &sel_len, &context);
|
||||
|
||||
/* fallback is needed. set XA_STRING to target and restart the loop. */
|
||||
if (context == XCLIB_XCOUT_FALLBACK) {
|
||||
context= XCLIB_XCOUT_NONE;
|
||||
target= m_string;
|
||||
continue;
|
||||
}
|
||||
else if (context == XCLIB_XCOUT_FALLBACK_UTF8) {
|
||||
/* utf8 fail, move to compouned text. */
|
||||
context= XCLIB_XCOUT_NONE;
|
||||
target= m_compound_text;
|
||||
continue;
|
||||
}
|
||||
else if (context == XCLIB_XCOUT_FALLBACK_COMP) {
|
||||
/* compouned text faile, move to text. */
|
||||
context= XCLIB_XCOUT_NONE;
|
||||
target= m_text;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* only continue if xcout() is doing something */
|
||||
if (context == XCLIB_XCOUT_NONE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (sel_len) {
|
||||
/* only print the buffer out, and free it, if it's not
|
||||
* empty
|
||||
*/
|
||||
unsigned char *tmp_data = (unsigned char*) malloc(sel_len+1);
|
||||
memcpy((char*)tmp_data, (char*)sel_buf, sel_len);
|
||||
tmp_data[sel_len] = '\0';
|
||||
|
||||
if (sseln == m_string)
|
||||
XFree(sel_buf);
|
||||
else
|
||||
free(sel_buf);
|
||||
|
||||
return (GHOST_TUns8*)tmp_data;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const
|
||||
{
|
||||
Window m_window, owner;
|
||||
|
||||
vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
|
||||
vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
|
||||
GHOST_WindowX11 * window = static_cast<GHOST_WindowX11 *>(*win_it);
|
||||
m_window = window->getXWindow();
|
||||
|
||||
if (buffer) {
|
||||
if (selection == False) {
|
||||
XSetSelectionOwner(m_display, m_clipboard, m_window, CurrentTime);
|
||||
owner= XGetSelectionOwner(m_display, m_clipboard);
|
||||
if (txt_cut_buffer)
|
||||
free((void*)txt_cut_buffer);
|
||||
|
||||
txt_cut_buffer = (char*) malloc(strlen(buffer)+1);
|
||||
strcpy(txt_cut_buffer, buffer);
|
||||
} else {
|
||||
XSetSelectionOwner(m_display, m_primary, m_window, CurrentTime);
|
||||
owner= XGetSelectionOwner(m_display, m_primary);
|
||||
if (txt_select_buffer)
|
||||
free((void*)txt_select_buffer);
|
||||
|
||||
txt_select_buffer = (char*) malloc(strlen(buffer)+1);
|
||||
strcpy(txt_select_buffer, buffer);
|
||||
}
|
||||
|
||||
if (owner != m_window)
|
||||
fprintf(stderr, "failed to own primary\n");
|
||||
}
|
||||
}
|
||||
312
intern/ghost/intern/GHOST_SystemX11.h
Normal file
312
intern/ghost/intern/GHOST_SystemX11.h
Normal file
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_SystemX11.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_SystemX11 class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_SYSTEM_X11_H_
|
||||
#define _GHOST_SYSTEM_X11_H_
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
#include "GHOST_System.h"
|
||||
#include "../GHOST_Types.h"
|
||||
|
||||
class GHOST_WindowX11;
|
||||
|
||||
/**
|
||||
* X11 Implementation of GHOST_System class.
|
||||
* @see GHOST_System.
|
||||
* @author Laurence Bourn
|
||||
* @date October 26, 2001
|
||||
*/
|
||||
|
||||
class GHOST_SystemX11 : public GHOST_System {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* this class should only be instanciated by GHOST_ISystem.
|
||||
*/
|
||||
|
||||
GHOST_SystemX11(
|
||||
);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_SystemX11();
|
||||
|
||||
|
||||
GHOST_TSuccess
|
||||
init(
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* @section Interface Inherited from GHOST_ISystem
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the system time.
|
||||
* Returns the number of milliseconds since the start of the system process.
|
||||
* @return The number of milliseconds.
|
||||
*/
|
||||
GHOST_TUns64
|
||||
getMilliSeconds(
|
||||
) const;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of displays on this system.
|
||||
* @return The number of displays.
|
||||
*/
|
||||
GHOST_TUns8
|
||||
getNumDisplays(
|
||||
) const;
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the main display on this system.
|
||||
* @return The dimension of the main display.
|
||||
*/
|
||||
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 stereoVisual Create a stereo visual for quad buffered stereo.
|
||||
* @param parentWindow Parent (embedder) window
|
||||
* @return The new window (or 0 if creation failed).
|
||||
*/
|
||||
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_TUns16 numOfAASamples = 0,
|
||||
const GHOST_TEmbedderWindowID parentWindow = 0
|
||||
);
|
||||
|
||||
/**
|
||||
* @section Interface Inherited from GHOST_ISystem
|
||||
*/
|
||||
|
||||
/**
|
||||
* Retrieves 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.
|
||||
*/
|
||||
bool
|
||||
processEvents(
|
||||
bool waitForEvent
|
||||
);
|
||||
|
||||
/**
|
||||
* @section Interface Inherited from GHOST_System
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
getCursorPosition(
|
||||
GHOST_TInt32& x,
|
||||
GHOST_TInt32& y
|
||||
) const;
|
||||
|
||||
GHOST_TSuccess
|
||||
setCursorPosition(
|
||||
GHOST_TInt32 x,
|
||||
GHOST_TInt32 y
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the state of all modifier keys.
|
||||
* @param keys The state of all modifier keys (true == pressed).
|
||||
* @return Indication of success.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
getButtons(
|
||||
GHOST_Buttons& buttons
|
||||
) const;
|
||||
|
||||
/**
|
||||
* @section Interface Dirty
|
||||
* Flag a window as dirty. This will
|
||||
* generate a GHOST window update event on a call to processEvents()
|
||||
*/
|
||||
|
||||
void
|
||||
addDirtyWindow(
|
||||
GHOST_WindowX11 * bad_wind
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* return a pointer to the X11 display structure
|
||||
*/
|
||||
|
||||
Display *
|
||||
getXDisplay(
|
||||
) {
|
||||
return m_display;
|
||||
}
|
||||
|
||||
void *
|
||||
prepareNdofInfo(
|
||||
volatile GHOST_TEventNDOFData *current_values
|
||||
);
|
||||
|
||||
/* Helped function for get data from the clipboard. */
|
||||
void getClipboard_xcout(XEvent evt, Atom sel, Atom target,
|
||||
unsigned char **txt, unsigned long *len,
|
||||
unsigned int *context) const;
|
||||
|
||||
/**
|
||||
* Returns unsinged char from CUT_BUFFER0
|
||||
* @param selection Get selection, X11 only feature
|
||||
* @return Returns the Clipboard indicated by Flag
|
||||
*/
|
||||
GHOST_TUns8 *getClipboard(bool selection) const;
|
||||
|
||||
/**
|
||||
* Puts buffer to system clipboard
|
||||
* @param buffer The buffer to copy to the clipboard
|
||||
* @param selection Set the selection into the clipboard, X11 only feature
|
||||
*/
|
||||
void putClipboard(GHOST_TInt8 *buffer, bool selection) const;
|
||||
|
||||
/**
|
||||
* @see GHOST_ISystem
|
||||
*/
|
||||
int toggleConsole(int action) { return 0; }
|
||||
|
||||
/**
|
||||
* Atom used for ICCCM, WM-spec and Motif.
|
||||
* We only need get this atom at the start, it's relative
|
||||
* to the display not the window and are public for every
|
||||
* window that need it.
|
||||
*/
|
||||
Atom m_wm_state;
|
||||
Atom m_wm_change_state;
|
||||
Atom m_net_state;
|
||||
Atom m_net_max_horz;
|
||||
Atom m_net_max_vert;
|
||||
Atom m_net_fullscreen;
|
||||
Atom m_motif;
|
||||
Atom m_wm_take_focus;
|
||||
Atom m_wm_protocols;
|
||||
Atom m_delete_window_atom;
|
||||
|
||||
/* Atoms for Selection, copy & paste. */
|
||||
Atom m_targets;
|
||||
Atom m_string;
|
||||
Atom m_compound_text;
|
||||
Atom m_text;
|
||||
Atom m_clipboard;
|
||||
Atom m_primary;
|
||||
Atom m_xclip_out;
|
||||
Atom m_incr;
|
||||
Atom m_utf8_string;
|
||||
|
||||
private :
|
||||
|
||||
Display * m_display;
|
||||
|
||||
/// The vector of windows that need to be updated.
|
||||
std::vector<GHOST_WindowX11 *> m_dirty_windows;
|
||||
|
||||
/// Start time at initialization.
|
||||
GHOST_TUns64 m_start_time;
|
||||
|
||||
/// A vector of keyboard key masks
|
||||
char m_keyboard_vector[32];
|
||||
|
||||
/* to prevent multiple warp, we store the time of the last warp event
|
||||
* and stop accumulating all events generated before that */
|
||||
Time m_last_warp;
|
||||
|
||||
/**
|
||||
* Return the ghost window associated with the
|
||||
* X11 window xwind
|
||||
*/
|
||||
|
||||
GHOST_WindowX11 *
|
||||
findGhostWindow(
|
||||
Window xwind
|
||||
) const ;
|
||||
|
||||
void
|
||||
processEvent(
|
||||
XEvent *xe
|
||||
);
|
||||
|
||||
Time
|
||||
lastEventTime(
|
||||
Time default_time
|
||||
);
|
||||
|
||||
bool
|
||||
generateWindowExposeEvents(
|
||||
);
|
||||
|
||||
GHOST_TKey
|
||||
convertXKey(
|
||||
KeySym key
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
76
intern/ghost/intern/GHOST_TaskbarWin32.h
Normal file
76
intern/ghost/intern/GHOST_TaskbarWin32.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/** \file ghost/intern/GHOST_TaskbarWin32.h
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
#ifndef GHOST_TASKBARWIN32_H_
|
||||
#define GHOST_TASKBARWIN32_H_
|
||||
#ifndef WIN32
|
||||
#error WIN32 only!
|
||||
#endif // WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
/* MinGW needs it */
|
||||
#ifdef FREE_WINDOWS
|
||||
#ifdef WINVER
|
||||
#undef WINVER
|
||||
#endif
|
||||
#define WINVER 0x0501
|
||||
#endif /* FREE_WINDOWS */
|
||||
|
||||
// ITaskbarList, ITaskbarList2 and ITaskbarList3 might be missing, present here in that case.
|
||||
// Note, ITaskbarList3 is supported only since Windows 7, though. Check for that is done in
|
||||
// GHOST_WindowWin32
|
||||
#ifndef __ITaskbarList_INTERFACE_DEFINED__
|
||||
#define __ITaskbarList_INTERFACE_DEFINED__
|
||||
extern "C" {const GUID CLSID_TaskbarList = {0x56FDF344, 0xFD6D, 0x11D0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90} };
|
||||
const GUID IID_ITaskbarList = {0x56FDF342, 0xFD6D, 0x11D0, {0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90} }; }
|
||||
class ITaskbarList : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE HrInit (void) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE AddTab (HWND hwnd) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE DeleteTab (HWND hwnd) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE ActivateTab (HWND hwnd) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetActiveAlt (HWND hwnd) = 0;
|
||||
};
|
||||
#endif /* ITaskbarList */
|
||||
|
||||
#ifndef __ITaskbarList2_INTERFACE_DEFINED__
|
||||
#define __ITaskbarList2_INTERFACE_DEFINED__
|
||||
extern "C" {const GUID IID_ITaskbarList2 = {0x602D4995, 0xB13A, 0x429b, {0xA6, 0x6E, 0x19, 0x35, 0xE4, 0x4F, 0x43, 0x17} }; }
|
||||
class ITaskbarList2 : public ITaskbarList
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE MarkFullscreenWindow(HWND hwnd, BOOL fFullscreen) = 0;
|
||||
};
|
||||
#endif /* ITaskbarList2 */
|
||||
|
||||
#ifndef __ITaskbarList3_INTERFACE_DEFINED__
|
||||
#define __ITaskbarList3_INTERFACE_DEFINED__
|
||||
typedef enum THUMBBUTTONFLAGS {THBF_ENABLED = 0, THBF_DISABLED = 0x1, THBF_DISMISSONCLICK = 0x2, THBF_NOBACKGROUND = 0x4, THBF_HIDDEN = 0x8, THBF_NONINTERACTIVE = 0x10} THUMBBUTTONFLAGS;
|
||||
typedef enum THUMBBUTTONMASK {THB_BITMAP = 0x1, THB_ICON = 0x2, THB_TOOLTIP = 0x4, THB_FLAGS = 0x8} THUMBBUTTONMASK;
|
||||
typedef struct THUMBBUTTON {THUMBBUTTONMASK dwMask; UINT iId; UINT iBitmap; HICON hIcon; WCHAR szTip[260]; THUMBBUTTONFLAGS dwFlags; } THUMBBUTTON;
|
||||
typedef enum TBPFLAG {TBPF_NOPROGRESS = 0, TBPF_INDETERMINATE = 0x1, TBPF_NORMAL = 0x2, TBPF_ERROR = 0x4, TBPF_PAUSED = 0x8 } TBPFLAG;
|
||||
#define THBN_CLICKED 0x1800
|
||||
extern "C" {const GUID IID_ITaskList3 = { 0xEA1AFB91, 0x9E28, 0x4B86, {0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF} };}
|
||||
|
||||
class ITaskbarList3 : public ITaskbarList2
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE SetProgressValue (HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetProgressState (HWND hwnd, TBPFLAG tbpFlags) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE RegisterTab (HWND hwndTab, HWND hwndMDI) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE UnregisterTab (HWND hwndTab) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetTabOrder (HWND hwndTab, HWND hwndInsertBefore) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetTabActive (HWND hwndTab, HWND hwndMDI, DWORD dwReserved) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE ThumbBarAddButtons (HWND hwnd, UINT cButtons, THUMBBUTTON * pButton) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE ThumbBarUpdateButtons (HWND hwnd, UINT cButtons, THUMBBUTTON * pButton) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE ThumbBarSetImageList (HWND hwnd, HIMAGELIST himl) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetOverlayIcon (HWND hwnd, HICON hIcon, LPCWSTR pszDescription) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetThumbnailTooltip (HWND hwnd, LPCWSTR pszTip) = 0;
|
||||
virtual HRESULT STDMETHODCALLTYPE SetThumbnailClip (HWND hwnd, RECT *prcClip) = 0;
|
||||
};
|
||||
#endif /* ITaskbarList3 */
|
||||
|
||||
#endif /*GHOST_TASKBARWIN32_H_*/
|
||||
165
intern/ghost/intern/GHOST_TimerManager.cpp
Normal file
165
intern/ghost/intern/GHOST_TimerManager.cpp
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_TimerManager.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 31, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_TimerManager.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "GHOST_TimerTask.h"
|
||||
|
||||
|
||||
GHOST_TimerManager::GHOST_TimerManager()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_TimerManager::~GHOST_TimerManager()
|
||||
{
|
||||
disposeTimers();
|
||||
}
|
||||
|
||||
|
||||
GHOST_TUns32 GHOST_TimerManager::getNumTimers()
|
||||
{
|
||||
return (GHOST_TUns32)m_timers.size();
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_TimerManager::getTimerFound(GHOST_TimerTask* timer)
|
||||
{
|
||||
TTimerVector::const_iterator iter = std::find(m_timers.begin(), m_timers.end(), timer);
|
||||
return iter != m_timers.end();
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_TimerManager::addTimer(GHOST_TimerTask* timer)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (!getTimerFound(timer)) {
|
||||
// Add the timer task
|
||||
m_timers.push_back(timer);
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_TimerManager::removeTimer(GHOST_TimerTask* timer)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
TTimerVector::iterator iter = std::find(m_timers.begin(), m_timers.end(), timer);
|
||||
if (iter != m_timers.end()) {
|
||||
// Remove the timer task
|
||||
m_timers.erase(iter);
|
||||
delete timer;
|
||||
timer = 0;
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_TUns64 GHOST_TimerManager::nextFireTime()
|
||||
{
|
||||
GHOST_TUns64 smallest = GHOST_kFireTimeNever;
|
||||
TTimerVector::iterator iter;
|
||||
|
||||
for (iter = m_timers.begin(); iter != m_timers.end(); iter++) {
|
||||
GHOST_TUns64 next = (*iter)->getNext();
|
||||
|
||||
if (next<smallest)
|
||||
smallest = next;
|
||||
}
|
||||
|
||||
return smallest;
|
||||
}
|
||||
|
||||
bool GHOST_TimerManager::fireTimers(GHOST_TUns64 time)
|
||||
{
|
||||
TTimerVector::iterator iter;
|
||||
bool anyProcessed = false;
|
||||
|
||||
for (iter = m_timers.begin(); iter != m_timers.end(); iter++) {
|
||||
if (fireTimer(time, *iter))
|
||||
anyProcessed = true;
|
||||
}
|
||||
|
||||
return anyProcessed;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_TimerManager::fireTimer(GHOST_TUns64 time, GHOST_TimerTask* task)
|
||||
{
|
||||
GHOST_TUns64 next = task->getNext();
|
||||
|
||||
// Check if the timer should be fired
|
||||
if (time > next) {
|
||||
// Fire the timer
|
||||
GHOST_TimerProcPtr timerProc = task->getTimerProc();
|
||||
GHOST_TUns64 start = task->getStart();
|
||||
timerProc(task, time - start);
|
||||
|
||||
// Update the time at which we will fire it again
|
||||
GHOST_TUns64 interval = task->getInterval();
|
||||
GHOST_TUns64 numCalls = (next - start) / interval;
|
||||
numCalls++;
|
||||
next = start + numCalls * interval;
|
||||
task->setNext(next);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GHOST_TimerManager::disposeTimers()
|
||||
{
|
||||
while (m_timers.size() > 0) {
|
||||
delete m_timers[0];
|
||||
m_timers.erase(m_timers.begin());
|
||||
}
|
||||
}
|
||||
126
intern/ghost/intern/GHOST_TimerManager.h
Normal file
126
intern/ghost/intern/GHOST_TimerManager.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_TimerManager.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_TimerManager class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_TIMER_MANAGER_H_
|
||||
#define _GHOST_TIMER_MANAGER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
class GHOST_TimerTask;
|
||||
|
||||
|
||||
/**
|
||||
* Manages a list of timer tasks.
|
||||
* Timer tasks added are owned by the manager.
|
||||
* Don't delete timer task objects.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 31, 2001
|
||||
*/
|
||||
class GHOST_TimerManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_TimerManager();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_TimerManager();
|
||||
|
||||
/**
|
||||
* Returns the number of timer tasks.
|
||||
* @return The number of events on the stack.
|
||||
*/
|
||||
virtual GHOST_TUns32 getNumTimers();
|
||||
|
||||
/**
|
||||
* Returns whther this timer task ins in our list.
|
||||
* @return Indication of presence.
|
||||
*/
|
||||
virtual bool getTimerFound(GHOST_TimerTask* timer);
|
||||
|
||||
/**
|
||||
* Adds a timer task to the list.
|
||||
* It is only added when it not already present in the list.
|
||||
* @param timer The timer task added to the list.
|
||||
* @return Indication as to whether addition has succeeded.
|
||||
*/
|
||||
virtual GHOST_TSuccess addTimer(GHOST_TimerTask* timer);
|
||||
|
||||
/**
|
||||
* Removes a timer task from the list.
|
||||
* It is only removed when it is found in the list.
|
||||
* @param timer The timer task to be removed from the list.
|
||||
* @return Indication as to whether removal has succeeded.
|
||||
*/
|
||||
virtual GHOST_TSuccess removeTimer(GHOST_TimerTask* timer);
|
||||
|
||||
/**
|
||||
* Finds the soonest time the next timer would fire.
|
||||
* @return The soonest time the next timer would fire,
|
||||
* or GHOST_kFireTimeNever if no timers exist.
|
||||
*/
|
||||
virtual GHOST_TUns64 nextFireTime();
|
||||
|
||||
/**
|
||||
* Checks all timer tasks to see if they are expired and fires them if needed.
|
||||
* @param time The current time.
|
||||
* @return True if any timers were fired.
|
||||
*/
|
||||
virtual bool fireTimers(GHOST_TUns64 time);
|
||||
|
||||
/**
|
||||
* Checks this timer task to see if they are expired and fires them if needed.
|
||||
* @param time The current time.
|
||||
* @param task The timer task to check and optionally fire.
|
||||
* @return True if the timer fired.
|
||||
*/
|
||||
virtual bool fireTimer(GHOST_TUns64 time, GHOST_TimerTask* task);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Deletes all timers.
|
||||
*/
|
||||
void disposeTimers();
|
||||
|
||||
typedef std::vector<GHOST_TimerTask*> TTimerVector;
|
||||
/** The list with event consumers. */
|
||||
TTimerVector m_timers;
|
||||
};
|
||||
|
||||
#endif // _GHOST_TIMER_MANAGER_H_
|
||||
|
||||
189
intern/ghost/intern/GHOST_TimerTask.h
Normal file
189
intern/ghost/intern/GHOST_TimerTask.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_TimerTask.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_TimerTask class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_TIMER_TASK_H_
|
||||
#define _GHOST_TIMER_TASK_H_
|
||||
|
||||
#include "GHOST_ITimerTask.h"
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of a timer task.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 28, 2001
|
||||
*/
|
||||
class GHOST_TimerTask : public GHOST_ITimerTask
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param start The timer start time.
|
||||
* @param interval The interval between calls to the timerProc
|
||||
* @param timerProc The callbak invoked when the interval expires.
|
||||
* @param data The timer user data.
|
||||
*/
|
||||
GHOST_TimerTask(GHOST_TUns64 start, GHOST_TUns64 interval, GHOST_TimerProcPtr timerProc, GHOST_TUserDataPtr userData = 0)
|
||||
: m_start(start), m_interval(interval), m_next(start), m_timerProc(timerProc), m_userData(userData), m_auxData(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timer start time.
|
||||
* @return The timer start time.
|
||||
*/
|
||||
inline virtual GHOST_TUns64 getStart() const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the timer start time.
|
||||
* @param start The timer start time.
|
||||
*/
|
||||
virtual void setStart(GHOST_TUns64 start)
|
||||
{
|
||||
m_start = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timer interval.
|
||||
* @return The timer interval.
|
||||
*/
|
||||
inline virtual GHOST_TUns64 getInterval() const
|
||||
{
|
||||
return m_interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the timer interval.
|
||||
* @param interval The timer interval.
|
||||
*/
|
||||
virtual void setInterval(GHOST_TUns64 interval)
|
||||
{
|
||||
m_interval = interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time the timerProc will be called.
|
||||
* @return The time the timerProc will be called.
|
||||
*/
|
||||
inline virtual GHOST_TUns64 getNext() const
|
||||
{
|
||||
return m_next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the time the timerProc will be called.
|
||||
* @param next The time the timerProc will be called.
|
||||
*/
|
||||
virtual void setNext(GHOST_TUns64 next)
|
||||
{
|
||||
m_next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timer callback.
|
||||
* @return the timer callback.
|
||||
*/
|
||||
inline virtual GHOST_TimerProcPtr getTimerProc() const
|
||||
{
|
||||
return m_timerProc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the timer callback.
|
||||
* @param The timer callback.
|
||||
*/
|
||||
inline virtual void setTimerProc(const GHOST_TimerProcPtr timerProc)
|
||||
{
|
||||
m_timerProc = timerProc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timer user data.
|
||||
* @return The timer user data.
|
||||
*/
|
||||
inline virtual GHOST_TUserDataPtr getUserData() const
|
||||
{
|
||||
return m_userData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the time user data.
|
||||
* @param data The timer user data.
|
||||
*/
|
||||
virtual void setUserData(const GHOST_TUserDataPtr userData)
|
||||
{
|
||||
m_userData = userData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the auxiliary storage room.
|
||||
* @return The auxiliary storage room.
|
||||
*/
|
||||
inline virtual GHOST_TUns32 getAuxData() const
|
||||
{
|
||||
return m_auxData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the auxiliary storage room.
|
||||
* @param auxData The auxiliary storage room.
|
||||
*/
|
||||
virtual void setAuxData(GHOST_TUns32 auxData)
|
||||
{
|
||||
m_auxData = auxData;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** The time the timer task was started. */
|
||||
GHOST_TUns64 m_start;
|
||||
|
||||
/** The interval between calls. */
|
||||
GHOST_TUns64 m_interval;
|
||||
|
||||
/** The time the timerProc will be called. */
|
||||
GHOST_TUns64 m_next;
|
||||
|
||||
/** The callback invoked when the timer expires. */
|
||||
GHOST_TimerProcPtr m_timerProc;
|
||||
|
||||
/** The timer task user data. */
|
||||
GHOST_TUserDataPtr m_userData;
|
||||
|
||||
/** Auxiliary storage room. */
|
||||
GHOST_TUns32 m_auxData;
|
||||
};
|
||||
|
||||
#endif // _GHOST_TIMER_TASK_H_
|
||||
|
||||
189
intern/ghost/intern/GHOST_Window.cpp
Normal file
189
intern/ghost/intern/GHOST_Window.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_Window.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 10, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_Window.h"
|
||||
|
||||
|
||||
GHOST_Window::GHOST_Window(
|
||||
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_TUns16 numOfAASamples)
|
||||
:
|
||||
m_drawingContextType(type),
|
||||
m_cursorVisible(true),
|
||||
m_cursorGrab(GHOST_kGrabDisable),
|
||||
m_cursorShape(GHOST_kStandardCursorDefault),
|
||||
m_stereoVisual(stereoVisual),
|
||||
m_numOfAASamples(numOfAASamples)
|
||||
{
|
||||
m_isUnsavedChanges = false;
|
||||
m_canAcceptDragOperation = false;
|
||||
|
||||
m_progressBarVisible = false;
|
||||
|
||||
m_cursorGrabAccumPos[0] = 0;
|
||||
m_cursorGrabAccumPos[1] = 0;
|
||||
|
||||
m_fullScreen = state == GHOST_kWindowStateFullScreen;
|
||||
if (m_fullScreen) {
|
||||
m_fullScreenWidth = width;
|
||||
m_fullScreenHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_Window::~GHOST_Window()
|
||||
{
|
||||
}
|
||||
|
||||
void* GHOST_Window::getOSWindow() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_Window::setDrawingContextType(GHOST_TDrawingContextType type)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kSuccess;
|
||||
if (type != m_drawingContextType) {
|
||||
success = removeDrawingContext();
|
||||
if (success) {
|
||||
success = installDrawingContext(type);
|
||||
m_drawingContextType = type;
|
||||
}
|
||||
else {
|
||||
m_drawingContextType = GHOST_kDrawingContextTypeNone;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible)
|
||||
{
|
||||
if (setWindowCursorVisibility(visible)) {
|
||||
m_cursorVisible = visible;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds)
|
||||
{
|
||||
if(m_cursorGrab == mode)
|
||||
return GHOST_kSuccess;
|
||||
|
||||
if (setWindowCursorGrab(mode)) {
|
||||
|
||||
if(mode==GHOST_kGrabDisable)
|
||||
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1;
|
||||
else if (bounds) {
|
||||
m_cursorGrabBounds= *bounds;
|
||||
} else { /* if bounds not defined, use window */
|
||||
getClientBounds(m_cursorGrabBounds);
|
||||
}
|
||||
m_cursorGrab = mode;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_Window::getCursorGrabBounds(GHOST_Rect& bounds)
|
||||
{
|
||||
bounds= m_cursorGrabBounds;
|
||||
return (bounds.m_l==-1 && bounds.m_r==-1) ? GHOST_kFailure : GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_Window::setCursorShape(GHOST_TStandardCursor cursorShape)
|
||||
{
|
||||
if (setWindowCursorShape(cursorShape)) {
|
||||
m_cursorShape = cursorShape;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_Window::setCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2],
|
||||
int hotX, int hotY)
|
||||
{
|
||||
return setCustomCursorShape( (GHOST_TUns8 *)bitmap, (GHOST_TUns8 *)mask,
|
||||
16, 16, hotX, hotY, 0, 1 );
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_Window::setCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
|
||||
int sizex, int sizey, int hotX, int hotY,
|
||||
int fg_color, int bg_color )
|
||||
{
|
||||
if (setWindowCustomCursorShape(bitmap, mask, sizex, sizey,hotX, hotY, fg_color, bg_color)) {
|
||||
m_cursorShape = GHOST_kStandardCursorCustom;
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_Window::setAcceptDragOperation(bool canAccept)
|
||||
{
|
||||
m_canAcceptDragOperation = canAccept;
|
||||
}
|
||||
|
||||
bool GHOST_Window::canAcceptDragOperation() const
|
||||
{
|
||||
return m_canAcceptDragOperation;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_Window::setModifiedState(bool isUnsavedChanges)
|
||||
{
|
||||
m_isUnsavedChanges = isUnsavedChanges;
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
bool GHOST_Window::getModifiedState()
|
||||
{
|
||||
return m_isUnsavedChanges;
|
||||
}
|
||||
395
intern/ghost/intern/GHOST_Window.h
Normal file
395
intern/ghost/intern/GHOST_Window.h
Normal file
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_Window.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_Window class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_WINDOW_H_
|
||||
#define _GHOST_WINDOW_H_
|
||||
|
||||
#include "GHOST_IWindow.h"
|
||||
|
||||
class STR_String;
|
||||
|
||||
/**
|
||||
* Platform independent implementation of GHOST_IWindow.
|
||||
* Dimensions are given in screen coordinates that are relative to the
|
||||
* upper-left corner of the screen.
|
||||
* Implements part of the GHOST_IWindow interface and adds some methods to
|
||||
* be implemented by childs of this class.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 7, 2001
|
||||
*/
|
||||
class GHOST_Window : public GHOST_IWindow
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @section Interface inherited from GHOST_IWindow left for derived class
|
||||
* implementation.
|
||||
* virtual bool getValid() const = 0;
|
||||
* virtual void setTitle(const STR_String& title) = 0;
|
||||
* virtual void getTitle(STR_String& title) const = 0;
|
||||
* virtual void getWindowBounds(GHOST_Rect& bounds) const = 0;
|
||||
* virtual void getClientBounds(GHOST_Rect& bounds) const = 0;
|
||||
* virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
|
||||
* virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0;
|
||||
* virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0;
|
||||
* virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
|
||||
* virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
|
||||
* virtual GHOST_TWindowState getState() const = 0;
|
||||
* virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0;
|
||||
* virtual GHOST_TWindowOrder getOrder(void) = 0;
|
||||
* virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0;
|
||||
* virtual GHOST_TSuccess swapBuffers() = 0;
|
||||
* virtual GHOST_TSuccess activateDrawingContext() = 0;
|
||||
* virtual GHOST_TSuccess invalidate() = 0;
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 heigh 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.
|
||||
* @param numOfAASamples Number of samples used for AA (zero if no AA)
|
||||
*/
|
||||
GHOST_Window(
|
||||
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,
|
||||
const GHOST_TUns16 numOfAASamples = 0);
|
||||
|
||||
/**
|
||||
* @section Interface inherited from GHOST_IWindow left for derived class
|
||||
* implementation.
|
||||
* virtual bool getValid() const = 0;
|
||||
* virtual void setTitle(const STR_String& title) = 0;
|
||||
* virtual void getTitle(STR_String& title) const = 0;
|
||||
* virtual void getWindowBounds(GHOST_Rect& bounds) const = 0;
|
||||
* virtual void getClientBounds(GHOST_Rect& bounds) const = 0;
|
||||
* virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width) = 0;
|
||||
* virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height) = 0;
|
||||
* virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) = 0;
|
||||
* virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
|
||||
* virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const = 0;
|
||||
* virtual GHOST_TWindowState getState() const = 0;
|
||||
* virtual GHOST_TSuccess setState(GHOST_TWindowState state) = 0;
|
||||
* virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order) = 0;
|
||||
* virtual GHOST_TSuccess swapBuffers() = 0;
|
||||
* virtual GHOST_TSuccess activateDrawingContext() = 0;
|
||||
* virtual GHOST_TSuccess invalidate() = 0;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* Closes the window and disposes resources allocated.
|
||||
*/
|
||||
virtual ~GHOST_Window();
|
||||
|
||||
/**
|
||||
* Returns the associated OS object/handle
|
||||
* @return The associated OS object/handle
|
||||
*/
|
||||
virtual void* getOSWindow() const;
|
||||
|
||||
/**
|
||||
* Returns the current cursor shape.
|
||||
* @return The current cursor shape.
|
||||
*/
|
||||
inline virtual GHOST_TStandardCursor getCursorShape() const;
|
||||
|
||||
/**
|
||||
* Set the shape of the cursor.
|
||||
* @param cursor The new cursor shape type id.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape);
|
||||
|
||||
/**
|
||||
* Set the shape of the cursor to a custom cursor.
|
||||
* @param bitmap The bitmap data for the cursor.
|
||||
* @param mask The mask data for the cursor.
|
||||
* @param hotX The X coordinate of the cursor hotspot.
|
||||
* @param hotY The Y coordinate of the cursor hotspot.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 bitmap[16][2],
|
||||
GHOST_TUns8 mask[16][2],
|
||||
int hotX,
|
||||
int hotY);
|
||||
|
||||
virtual GHOST_TSuccess setCustomCursorShape(GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask,
|
||||
int sizex, int sizey,
|
||||
int hotX, int hotY,
|
||||
int fg_color, int bg_color);
|
||||
|
||||
/**
|
||||
* Returns the visibility state of the cursor.
|
||||
* @return The visibility state of the cursor.
|
||||
*/
|
||||
inline virtual bool getCursorVisibility() const;
|
||||
inline virtual GHOST_TGrabCursorMode getCursorGrabMode() const;
|
||||
inline virtual void getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
|
||||
inline virtual void getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
|
||||
inline virtual void setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y);
|
||||
|
||||
/**
|
||||
* Shows or hides the cursor.
|
||||
* @param visible The new visibility state of the cursor.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCursorVisibility(bool visible);
|
||||
|
||||
/**
|
||||
* Sets the cursor grab.
|
||||
* @param mode The new grab state of the cursor.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds);
|
||||
|
||||
/**
|
||||
* Gets the cursor grab region, if unset the window is used.
|
||||
* reset when grab is disabled.
|
||||
*/
|
||||
virtual GHOST_TSuccess getCursorGrabBounds(GHOST_Rect& bounds);
|
||||
|
||||
/**
|
||||
* Sets the progress bar value displayed in the window/application icon
|
||||
* @param progress The progress % (0.0 to 1.0)
|
||||
*/
|
||||
virtual GHOST_TSuccess setProgressBar(float progress) {return GHOST_kFailure;};
|
||||
|
||||
/**
|
||||
* Hides the progress bar in the icon
|
||||
*/
|
||||
virtual GHOST_TSuccess endProgressBar() {return GHOST_kFailure;};
|
||||
|
||||
/**
|
||||
* Tells if the ongoing drag'n'drop object can be accepted upon mouse drop
|
||||
*/
|
||||
virtual void setAcceptDragOperation(bool canAccept);
|
||||
|
||||
/**
|
||||
* Returns acceptance of the dropped object
|
||||
* Usually called by the "object dropped" event handling function
|
||||
*/
|
||||
virtual bool canAcceptDragOperation() const;
|
||||
|
||||
/**
|
||||
* Sets the window "modified" status, indicating unsaved changes
|
||||
* @param isUnsavedChanges Unsaved changes or not
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges);
|
||||
|
||||
/**
|
||||
* Gets the window "modified" status, indicating unsaved changes
|
||||
* @return True if there are unsaved changes
|
||||
*/
|
||||
virtual bool getModifiedState();
|
||||
|
||||
/**
|
||||
* Returns the type of drawing context used in this window.
|
||||
* @return The current type of drawing context.
|
||||
*/
|
||||
inline virtual GHOST_TDrawingContextType getDrawingContextType();
|
||||
|
||||
/**
|
||||
* Tries to install a rendering context in this window.
|
||||
* Child classes do not need to overload this method.
|
||||
* They should overload the installDrawingContext and removeDrawingContext instead.
|
||||
* @param type The type of rendering context installed.
|
||||
* @return Indication as to whether installation has succeeded.
|
||||
*/
|
||||
virtual GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type);
|
||||
|
||||
/**
|
||||
* Returns the window user data.
|
||||
* @return The window user data.
|
||||
*/
|
||||
inline virtual GHOST_TUserDataPtr getUserData() const
|
||||
{
|
||||
return m_userData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the window user data.
|
||||
* @param data The window user data.
|
||||
*/
|
||||
virtual void setUserData(const GHOST_TUserDataPtr userData)
|
||||
{
|
||||
m_userData = userData;
|
||||
}
|
||||
|
||||
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) = 0;
|
||||
|
||||
/**
|
||||
* Removes the current drawing context.
|
||||
* @return Indication as to whether removal has succeeded.
|
||||
*/
|
||||
virtual GHOST_TSuccess removeDrawingContext() = 0;
|
||||
|
||||
/**
|
||||
* Sets the cursor visibility on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCursorVisibility(bool visible) = 0;
|
||||
|
||||
/**
|
||||
* Sets the cursor grab on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) { return GHOST_kSuccess; };
|
||||
|
||||
/**
|
||||
* Sets the cursor shape on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) = 0;
|
||||
|
||||
/**
|
||||
* Sets the cursor shape on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2],
|
||||
int hotX, int hotY) = 0;
|
||||
|
||||
virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask,
|
||||
int szx, int szy, int hotX, int hotY, int fg, int bg) = 0;
|
||||
/** The the of drawing context installed in this window. */
|
||||
GHOST_TDrawingContextType m_drawingContextType;
|
||||
|
||||
/** The window user data */
|
||||
GHOST_TUserDataPtr m_userData;
|
||||
|
||||
/** The current visibility of the cursor */
|
||||
bool m_cursorVisible;
|
||||
|
||||
/** The current grabbed state of the cursor */
|
||||
GHOST_TGrabCursorMode m_cursorGrab;
|
||||
|
||||
/** Initial grab location. */
|
||||
GHOST_TInt32 m_cursorGrabInitPos[2];
|
||||
|
||||
/** Accumulated offset from m_cursorGrabInitPos. */
|
||||
GHOST_TInt32 m_cursorGrabAccumPos[2];
|
||||
|
||||
/** Wrap the cursor within this region. */
|
||||
GHOST_Rect m_cursorGrabBounds;
|
||||
|
||||
/** The current shape of the cursor */
|
||||
GHOST_TStandardCursor m_cursorShape;
|
||||
|
||||
/** The presence of progress indicator with the application icon */
|
||||
bool m_progressBarVisible;
|
||||
|
||||
/** The acceptance of the "drop candidate" of the current drag'n'drop operation */
|
||||
bool m_canAcceptDragOperation;
|
||||
|
||||
/** Modified state : are there unsaved changes */
|
||||
bool m_isUnsavedChanges;
|
||||
|
||||
/** Stores wether this is a full screen window. */
|
||||
bool m_fullScreen;
|
||||
|
||||
/** Stereo visual created. Only necessary for 'real' stereo support,
|
||||
* ie quad buffered stereo. This is not always possible, depends on
|
||||
* the graphics h/w
|
||||
*/
|
||||
bool m_stereoVisual;
|
||||
|
||||
/** Number of samples used in anti-aliasing, set to 0 if no AA **/
|
||||
GHOST_TUns16 m_numOfAASamples;
|
||||
|
||||
/** Full-screen width */
|
||||
GHOST_TUns32 m_fullScreenWidth;
|
||||
/** Full-screen height */
|
||||
GHOST_TUns32 m_fullScreenHeight;
|
||||
};
|
||||
|
||||
|
||||
inline GHOST_TDrawingContextType GHOST_Window::getDrawingContextType()
|
||||
{
|
||||
return m_drawingContextType;
|
||||
}
|
||||
|
||||
inline bool GHOST_Window::getCursorVisibility() const
|
||||
{
|
||||
return m_cursorVisible;
|
||||
}
|
||||
|
||||
inline GHOST_TGrabCursorMode GHOST_Window::getCursorGrabMode() const
|
||||
{
|
||||
return m_cursorGrab;
|
||||
}
|
||||
|
||||
inline void GHOST_Window::getCursorGrabInitPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const
|
||||
{
|
||||
x = m_cursorGrabInitPos[0];
|
||||
y = m_cursorGrabInitPos[1];
|
||||
}
|
||||
|
||||
inline void GHOST_Window::getCursorGrabAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const
|
||||
{
|
||||
x= m_cursorGrabAccumPos[0];
|
||||
y= m_cursorGrabAccumPos[1];
|
||||
}
|
||||
|
||||
inline void GHOST_Window::setCursorGrabAccum(GHOST_TInt32 x, GHOST_TInt32 y)
|
||||
{
|
||||
m_cursorGrabAccumPos[0]= x;
|
||||
m_cursorGrabAccumPos[1]= y;
|
||||
}
|
||||
|
||||
inline GHOST_TStandardCursor GHOST_Window::getCursorShape() const
|
||||
{
|
||||
return m_cursorShape;
|
||||
}
|
||||
|
||||
#endif // _GHOST_WINDOW_H
|
||||
|
||||
748
intern/ghost/intern/GHOST_WindowCarbon.cpp
Normal file
748
intern/ghost/intern/GHOST_WindowCarbon.cpp
Normal file
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_WindowCarbon.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 10, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_WindowCarbon.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
AGLContext GHOST_WindowCarbon::s_firstaglCtx = NULL;
|
||||
#ifdef GHOST_DRAW_CARBON_GUTTER
|
||||
const GHOST_TInt32 GHOST_WindowCarbon::s_sizeRectSize = 16;
|
||||
#endif //GHOST_DRAW_CARBON_GUTTER
|
||||
|
||||
static const GLint sPreferredFormatWindow[10] = {
|
||||
AGL_RGBA,
|
||||
AGL_DOUBLEBUFFER,
|
||||
AGL_ACCELERATED,
|
||||
AGL_DEPTH_SIZE, 32,
|
||||
AGL_NONE,
|
||||
};
|
||||
|
||||
static const GLint sPreferredFormatFullScreen[11] = {
|
||||
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_WindowCarbon *ghost_window;
|
||||
OSStatus err;
|
||||
int theState;
|
||||
|
||||
if (::GetEventKind(event) == kEventWindowZoom) {
|
||||
err = ::GetEventParameter (event,kEventParamDirectObject,typeWindowRef,NULL,sizeof(mywindow),NULL, &mywindow);
|
||||
ghost_window = (GHOST_WindowCarbon *) 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_WindowCarbon::GHOST_WindowCarbon(
|
||||
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_TUns16 numOfAASamples
|
||||
) :
|
||||
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",(int)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",(int)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_WindowCarbon::GHOST_WindowCarbon(): creating full-screen OpenGL context\n");
|
||||
setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);;installDrawingContext(GHOST_kDrawingContextTypeOpenGL);
|
||||
updateDrawingContext();
|
||||
activateDrawingContext();
|
||||
|
||||
m_tablet.Active = GHOST_kTabletModeNone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_WindowCarbon::~GHOST_WindowCarbon()
|
||||
{
|
||||
if (m_customCursor) delete m_customCursor;
|
||||
|
||||
if(ugly_hack==m_windowRef) ugly_hack= NULL;
|
||||
|
||||
// printf("GHOST_WindowCarbon::~GHOST_WindowCarbon(): removing drawing context\n");
|
||||
if(ugly_hack==NULL) setDrawingContextType(GHOST_kDrawingContextTypeNone);
|
||||
if (m_windowRef) {
|
||||
::DisposeWindow(m_windowRef);
|
||||
m_windowRef = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool GHOST_WindowCarbon::getValid() const
|
||||
{
|
||||
bool valid;
|
||||
if (!m_fullScreen) {
|
||||
valid = (m_windowRef != 0) && (m_grafPtr != 0) && ::IsValidWindowPtr(m_windowRef);
|
||||
}
|
||||
else {
|
||||
valid = true;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCarbon::setTitle(const STR_String& title)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setTitle(): window invalid")
|
||||
Str255 title255;
|
||||
gen2mac(title, title255);
|
||||
::SetWTitle(m_windowRef, title255);
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCarbon::getTitle(STR_String& title) const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getTitle(): window invalid")
|
||||
Str255 title255;
|
||||
::GetWTitle(m_windowRef, title255);
|
||||
mac2gen(title255, title);
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCarbon::getWindowBounds(GHOST_Rect& bounds) const
|
||||
{
|
||||
OSStatus success;
|
||||
Rect rect;
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::getClientBounds(GHOST_Rect& bounds) const
|
||||
{
|
||||
Rect rect;
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::setClientWidth(GHOST_TUns32 width)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::setClientHeight(GHOST_TUns32 height)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::getState() const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::setState(GHOST_TWindowState state)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::setOrder(GHOST_TWindowOrder order)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::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_WindowCarbon::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_WindowCarbon::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_WindowCarbon::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_WindowCarbon::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_WindowCarbon::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_WindowCarbon::installDrawingContext(): init full-screen OpenGL succeeded\n");
|
||||
}
|
||||
else {
|
||||
GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL failed\n");
|
||||
}
|
||||
*/
|
||||
}
|
||||
::aglDestroyPixelFormat(pixelFormat);
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kDrawingContextTypeNone:
|
||||
success = GHOST_kSuccess;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCarbon::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_WindowCarbon::invalidate()
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::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_WindowCarbon::invalidate(): created event " << status << " \n");
|
||||
//status = ::SetEventParameter(event, kEventParamDirectObject, typeWindowRef, sizeof(WindowRef), this);
|
||||
//GHOST_PRINT("GHOST_WindowCarbon::invalidate(): set event parameter " << status << " \n");
|
||||
//status = ::PostEventToQueue(::GetMainEventQueue(), event, kEventPriorityStandard);
|
||||
//status = ::SendEventToEventTarget(event, ::GetApplicationEventTarget());
|
||||
//GHOST_PRINT("GHOST_WindowCarbon::invalidate(): added event to queue " << status << " \n");
|
||||
m_fullScreenDirty = true;
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCarbon::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_WindowCarbon::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_WindowCarbon::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);
|
||||
GCMAP( GHOST_kStandardCursorCopy, kThemeCopyArrowCursor);
|
||||
};
|
||||
#undef GCMAP
|
||||
|
||||
::SetThemeCursor(carbon_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_WindowCarbon::getFullScreenDirty()
|
||||
{
|
||||
return m_fullScreen && m_fullScreenDirty;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorVisibility(bool visible)
|
||||
{
|
||||
if (::FrontWindow() == m_windowRef) {
|
||||
loadCursor(visible, getCursorShape());
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCarbon::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_WindowCarbon::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_WindowCarbon::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_WindowCarbon::setMac_windowState(short value)
|
||||
{
|
||||
mac_windowState = value;
|
||||
}
|
||||
|
||||
short GHOST_WindowCarbon::getMac_windowState()
|
||||
{
|
||||
return mac_windowState;
|
||||
}
|
||||
313
intern/ghost/intern/GHOST_WindowCarbon.h
Normal file
313
intern/ghost/intern/GHOST_WindowCarbon.h
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_WindowCarbon.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_WindowCarbon class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_WINDOW_CARBON_H_
|
||||
#define _GHOST_WINDOW_CARBON_H_
|
||||
|
||||
#ifndef __APPLE__
|
||||
#error Apple OSX only!
|
||||
#endif // __APPLE__
|
||||
|
||||
#include "GHOST_Window.h"
|
||||
#include "STR_String.h"
|
||||
|
||||
#define __CARBONSOUND__
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include <AGL/agl.h>
|
||||
|
||||
|
||||
/**
|
||||
* Window on Mac OSX/Carbon.
|
||||
* 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_WindowCarbon : 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_WindowCarbon(
|
||||
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,
|
||||
const GHOST_TUns16 numOfAASamples = 0
|
||||
);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* Closes the window and disposes resources allocated.
|
||||
*/
|
||||
virtual ~GHOST_WindowCarbon();
|
||||
|
||||
/**
|
||||
* 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& GetCarbonTabletData()
|
||||
{ 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_CARBON_H_
|
||||
|
||||
309
intern/ghost/intern/GHOST_WindowCocoa.h
Normal file
309
intern/ghost/intern/GHOST_WindowCocoa.h
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_WindowCocoa.h
|
||||
* \ingroup GHOST
|
||||
* 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"
|
||||
|
||||
@class CocoaWindow;
|
||||
|
||||
class GHOST_SystemCocoa;
|
||||
|
||||
/**
|
||||
* 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 systemCocoa The associated system class to forward events to
|
||||
* @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.
|
||||
* @param numOfAASamples Number of samples used for AA (zero if no AA)
|
||||
*/
|
||||
GHOST_WindowCocoa(
|
||||
GHOST_SystemCocoa *systemCocoa,
|
||||
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,
|
||||
const GHOST_TUns16 numOfAASamples = 0
|
||||
);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Returns the associated NSWindow object
|
||||
* @return The associated NSWindow object
|
||||
*/
|
||||
virtual void* getOSWindow() 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;
|
||||
|
||||
/**
|
||||
* Sets the window "modified" status, indicating unsaved changes
|
||||
* @param isUnsavedChanges Unsaved changes or not
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Gets the screen the window is displayed in
|
||||
* @return The NSScreen object
|
||||
*/
|
||||
NSScreen* getScreen();
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
|
||||
const GHOST_TabletData* GetTabletData()
|
||||
{ return &m_tablet; }
|
||||
|
||||
GHOST_TabletData& GetCocoaTabletData()
|
||||
{ return m_tablet; }
|
||||
|
||||
/**
|
||||
* Sets the progress bar value displayed in the window/application icon
|
||||
* @param progress The progress % (0.0 to 1.0)
|
||||
*/
|
||||
virtual GHOST_TSuccess setProgressBar(float progress);
|
||||
|
||||
/**
|
||||
* Hides the progress bar icon
|
||||
*/
|
||||
virtual GHOST_TSuccess endProgressBar();
|
||||
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 grab on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/** The window containing the OpenGL view */
|
||||
CocoaWindow *m_window;
|
||||
|
||||
/** The openGL view */
|
||||
NSOpenGLView *m_openGLView;
|
||||
|
||||
/** The opgnGL drawing context */
|
||||
NSOpenGLContext *m_openGLContext;
|
||||
|
||||
/** The mother SystemCocoa class to send events */
|
||||
GHOST_SystemCocoa *m_systemCocoa;
|
||||
|
||||
/** The first created OpenGL context (for sharing display lists) */
|
||||
static NSOpenGLContext *s_firstOpenGLcontext;
|
||||
|
||||
NSCursor* m_customCursor;
|
||||
|
||||
GHOST_TabletData m_tablet;
|
||||
};
|
||||
|
||||
#endif // _GHOST_WINDOW_COCOA_H_
|
||||
|
||||
1352
intern/ghost/intern/GHOST_WindowCocoa.mm
Normal file
1352
intern/ghost/intern/GHOST_WindowCocoa.mm
Normal file
@@ -0,0 +1,1352 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 10/2009
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_6
|
||||
//Use of the SetSystemUIMode function (64bit compatible)
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
|
||||
#include <OpenGL/gl.h>
|
||||
/***** Multithreaded opengl code : uncomment for enabling
|
||||
#include <OpenGL/OpenGL.h>
|
||||
*/
|
||||
|
||||
|
||||
#include "GHOST_WindowCocoa.h"
|
||||
#include "GHOST_SystemCocoa.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
|
||||
#pragma mark Cocoa window delegate object
|
||||
/* live resize ugly patch
|
||||
extern "C" {
|
||||
struct bContext;
|
||||
typedef struct bContext bContext;
|
||||
bContext* ghostC;
|
||||
extern int wm_window_timer(const bContext *C);
|
||||
extern void wm_window_process_events(const bContext *C);
|
||||
extern void wm_event_do_handlers(bContext *C);
|
||||
extern void wm_event_do_notifiers(bContext *C);
|
||||
extern void wm_draw_update(bContext *C);
|
||||
};*/
|
||||
@interface CocoaWindowDelegate : NSObject
|
||||
#ifdef MAC_OS_X_VERSION_10_6
|
||||
<NSWindowDelegate>
|
||||
#endif
|
||||
{
|
||||
GHOST_SystemCocoa *systemCocoa;
|
||||
GHOST_WindowCocoa *associatedWindow;
|
||||
}
|
||||
|
||||
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
|
||||
- (void)windowWillClose:(NSNotification *)notification;
|
||||
- (void)windowDidBecomeKey:(NSNotification *)notification;
|
||||
- (void)windowDidResignKey:(NSNotification *)notification;
|
||||
- (void)windowDidExpose:(NSNotification *)notification;
|
||||
- (void)windowDidResize:(NSNotification *)notification;
|
||||
- (void)windowDidMove:(NSNotification *)notification;
|
||||
- (void)windowWillMove:(NSNotification *)notification;
|
||||
@end
|
||||
|
||||
@implementation CocoaWindowDelegate : NSObject
|
||||
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
|
||||
{
|
||||
systemCocoa = sysCocoa;
|
||||
associatedWindow = winCocoa;
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow);
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeKey:(NSNotification *)notification
|
||||
{
|
||||
systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow);
|
||||
}
|
||||
|
||||
- (void)windowDidResignKey:(NSNotification *)notification
|
||||
{
|
||||
systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow);
|
||||
}
|
||||
|
||||
- (void)windowDidExpose:(NSNotification *)notification
|
||||
{
|
||||
systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow);
|
||||
}
|
||||
|
||||
- (void)windowDidMove:(NSNotification *)notification
|
||||
{
|
||||
systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, associatedWindow);
|
||||
}
|
||||
|
||||
- (void)windowWillMove:(NSNotification *)notification
|
||||
{
|
||||
systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, associatedWindow);
|
||||
}
|
||||
|
||||
- (void)windowDidResize:(NSNotification *)notification
|
||||
{
|
||||
#ifdef MAC_OS_X_VERSION_10_6
|
||||
//if (![[notification object] inLiveResize]) {
|
||||
//Send event only once, at end of resize operation (when user has released mouse button)
|
||||
#endif
|
||||
systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow);
|
||||
#ifdef MAC_OS_X_VERSION_10_6
|
||||
//}
|
||||
#endif
|
||||
/* Live resize ugly patch. Needed because live resize runs in a modal loop, not letting main loop run
|
||||
if ([[notification object] inLiveResize]) {
|
||||
systemCocoa->dispatchEvents();
|
||||
wm_window_timer(ghostC);
|
||||
wm_event_do_handlers(ghostC);
|
||||
wm_event_do_notifiers(ghostC);
|
||||
wm_draw_update(ghostC);
|
||||
}*/
|
||||
}
|
||||
@end
|
||||
|
||||
#pragma mark NSWindow subclass
|
||||
//We need to subclass it to tell that even borderless (fullscreen), it can become key (receive user events)
|
||||
@interface CocoaWindow: NSWindow
|
||||
{
|
||||
GHOST_SystemCocoa *systemCocoa;
|
||||
GHOST_WindowCocoa *associatedWindow;
|
||||
GHOST_TDragnDropTypes m_draggedObjectType;
|
||||
}
|
||||
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa;
|
||||
- (GHOST_SystemCocoa*)systemCocoa;
|
||||
@end
|
||||
@implementation CocoaWindow
|
||||
- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa
|
||||
{
|
||||
systemCocoa = sysCocoa;
|
||||
associatedWindow = winCocoa;
|
||||
}
|
||||
- (GHOST_SystemCocoa*)systemCocoa
|
||||
{
|
||||
return systemCocoa;
|
||||
}
|
||||
|
||||
-(BOOL)canBecomeKeyWindow
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
//The drag'n'drop dragging destination methods
|
||||
- (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender
|
||||
{
|
||||
NSPoint mouseLocation = [sender draggingLocation];
|
||||
NSPasteboard *draggingPBoard = [sender draggingPasteboard];
|
||||
|
||||
if ([[draggingPBoard types] containsObject:NSTIFFPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeBitmap;
|
||||
else if ([[draggingPBoard types] containsObject:NSFilenamesPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeFilenames;
|
||||
else if ([[draggingPBoard types] containsObject:NSStringPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeString;
|
||||
else return NSDragOperationNone;
|
||||
|
||||
associatedWindow->setAcceptDragOperation(TRUE); //Drag operation is accepted by default
|
||||
systemCocoa->handleDraggingEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil);
|
||||
return NSDragOperationCopy;
|
||||
}
|
||||
|
||||
- (BOOL)wantsPeriodicDraggingUpdates
|
||||
{
|
||||
return NO; //No need to overflow blender event queue. Events shall be sent only on changes
|
||||
}
|
||||
|
||||
- (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender
|
||||
{
|
||||
NSPoint mouseLocation = [sender draggingLocation];
|
||||
|
||||
systemCocoa->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil);
|
||||
return associatedWindow->canAcceptDragOperation()?NSDragOperationCopy:NSDragOperationNone;
|
||||
}
|
||||
|
||||
- (void)draggingExited:(id < NSDraggingInfo >)sender
|
||||
{
|
||||
systemCocoa->handleDraggingEvent(GHOST_kEventDraggingExited, m_draggedObjectType, associatedWindow, 0, 0, nil);
|
||||
m_draggedObjectType = GHOST_kDragnDropTypeUnknown;
|
||||
}
|
||||
|
||||
- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
|
||||
{
|
||||
if (associatedWindow->canAcceptDragOperation())
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender
|
||||
{
|
||||
NSPoint mouseLocation = [sender draggingLocation];
|
||||
NSPasteboard *draggingPBoard = [sender draggingPasteboard];
|
||||
NSImage *droppedImg;
|
||||
id data;
|
||||
|
||||
switch (m_draggedObjectType) {
|
||||
case GHOST_kDragnDropTypeBitmap:
|
||||
if([NSImage canInitWithPasteboard:draggingPBoard]) {
|
||||
droppedImg = [[NSImage alloc]initWithPasteboard:draggingPBoard];
|
||||
data = droppedImg; //[draggingPBoard dataForType:NSTIFFPboardType];
|
||||
}
|
||||
else return NO;
|
||||
break;
|
||||
case GHOST_kDragnDropTypeFilenames:
|
||||
data = [draggingPBoard propertyListForType:NSFilenamesPboardType];
|
||||
break;
|
||||
case GHOST_kDragnDropTypeString:
|
||||
data = [draggingPBoard stringForType:NSStringPboardType];
|
||||
break;
|
||||
default:
|
||||
return NO;
|
||||
break;
|
||||
}
|
||||
systemCocoa->handleDraggingEvent(GHOST_kEventDraggingDropDone, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, (void*)data);
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#pragma mark NSOpenGLView subclass
|
||||
//We need to subclass it in order to give Cocoa the feeling key events are trapped
|
||||
@interface CocoaOpenGLView : NSOpenGLView
|
||||
{
|
||||
}
|
||||
@end
|
||||
@implementation CocoaOpenGLView
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
//The trick to prevent Cocoa from complaining (beeping)
|
||||
- (void)keyDown:(NSEvent *)theEvent
|
||||
{}
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
|
||||
//Cmd+key are handled differently before 10.5
|
||||
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
|
||||
{
|
||||
NSString *chars = [theEvent charactersIgnoringModifiers];
|
||||
|
||||
if ([chars length] <1)
|
||||
return NO;
|
||||
|
||||
//Let cocoa handle menu shortcuts
|
||||
switch ([chars characterAtIndex:0]) {
|
||||
case 'q':
|
||||
case 'w':
|
||||
case 'h':
|
||||
case 'm':
|
||||
case '<':
|
||||
case '>':
|
||||
case '~':
|
||||
case '`':
|
||||
return NO;
|
||||
default:
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
- (BOOL)isOpaque
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void) drawRect:(NSRect)rect
|
||||
{
|
||||
if ([self inLiveResize])
|
||||
{
|
||||
//Don't redraw while in live resize
|
||||
}
|
||||
else
|
||||
{
|
||||
[super drawRect:rect];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark initialization / finalization
|
||||
|
||||
NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil;
|
||||
|
||||
GHOST_WindowCocoa::GHOST_WindowCocoa(
|
||||
GHOST_SystemCocoa *systemCocoa,
|
||||
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_TUns16 numOfAASamples
|
||||
) :
|
||||
GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, numOfAASamples),
|
||||
m_customCursor(0)
|
||||
{
|
||||
NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40];
|
||||
NSOpenGLPixelFormat *pixelFormat = nil;
|
||||
int i;
|
||||
|
||||
m_systemCocoa = systemCocoa;
|
||||
m_fullScreen = false;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
||||
//Creates the window
|
||||
NSRect rect;
|
||||
NSSize minSize;
|
||||
|
||||
rect.origin.x = left;
|
||||
rect.origin.y = top;
|
||||
rect.size.width = width;
|
||||
rect.size.height = height;
|
||||
|
||||
m_window = [[CocoaWindow alloc] initWithContentRect:rect
|
||||
styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask
|
||||
backing:NSBackingStoreBuffered defer:NO];
|
||||
if (m_window == nil) {
|
||||
[pool drain];
|
||||
return;
|
||||
}
|
||||
|
||||
[m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
|
||||
|
||||
//Forbid to resize the window below the blender defined minimum one
|
||||
minSize.width = 320;
|
||||
minSize.height = 240;
|
||||
[m_window setContentMinSize:minSize];
|
||||
|
||||
setTitle(title);
|
||||
|
||||
|
||||
// Pixel Format Attributes for the windowed NSOpenGLContext
|
||||
i=0;
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer;
|
||||
|
||||
// Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer
|
||||
// needed for 'Draw Overlap' drawing method
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore;
|
||||
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
|
||||
//pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
|
||||
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
|
||||
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
|
||||
|
||||
|
||||
if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
|
||||
|
||||
if (numOfAASamples>0) {
|
||||
// Multisample anti-aliasing
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample;
|
||||
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFASampleBuffers;
|
||||
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 1;
|
||||
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFASamples;
|
||||
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) numOfAASamples;
|
||||
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFANoRecovery;
|
||||
}
|
||||
|
||||
pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0;
|
||||
|
||||
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
|
||||
|
||||
|
||||
//Fall back to no multisampling if Antialiasing init failed
|
||||
if (pixelFormat == nil) {
|
||||
i=0;
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer;
|
||||
|
||||
// Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer
|
||||
// needed for 'Draw Overlap' drawing method
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore;
|
||||
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated;
|
||||
//pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway
|
||||
|
||||
pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize;
|
||||
pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32;
|
||||
|
||||
if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo;
|
||||
|
||||
pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0;
|
||||
|
||||
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow];
|
||||
|
||||
}
|
||||
|
||||
if (numOfAASamples>0) { //Set m_numOfAASamples to the actual value
|
||||
GLint gli;
|
||||
[pixelFormat getValues:&gli forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
|
||||
if (m_numOfAASamples != (GHOST_TUns16)gli) {
|
||||
m_numOfAASamples = (GHOST_TUns16)gli;
|
||||
printf("GHOST_Window could be created with anti-aliasing of only %i samples\n",m_numOfAASamples);
|
||||
}
|
||||
}
|
||||
|
||||
//Creates the OpenGL View inside the window
|
||||
m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect
|
||||
pixelFormat:pixelFormat];
|
||||
|
||||
[pixelFormat release];
|
||||
|
||||
m_openGLContext = [m_openGLView openGLContext]; //This context will be replaced by the proper one just after
|
||||
|
||||
[m_window setContentView:m_openGLView];
|
||||
[m_window setInitialFirstResponder:m_openGLView];
|
||||
|
||||
[m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window
|
||||
|
||||
[m_window makeKeyAndOrderFront:nil];
|
||||
|
||||
setDrawingContextType(type);
|
||||
updateDrawingContext();
|
||||
activateDrawingContext();
|
||||
|
||||
m_tablet.Active = GHOST_kTabletModeNone;
|
||||
|
||||
CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init];
|
||||
[windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this];
|
||||
[m_window setDelegate:windowDelegate];
|
||||
|
||||
[m_window setAcceptsMouseMovedEvents:YES];
|
||||
|
||||
[m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
|
||||
NSStringPboardType, NSTIFFPboardType, nil]];
|
||||
|
||||
if (state == GHOST_kWindowStateFullScreen)
|
||||
setState(GHOST_kWindowStateFullScreen);
|
||||
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
|
||||
GHOST_WindowCocoa::~GHOST_WindowCocoa()
|
||||
{
|
||||
if (m_customCursor) delete m_customCursor;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[m_openGLView release];
|
||||
|
||||
if (m_window) {
|
||||
[m_window close];
|
||||
[[m_window delegate] release];
|
||||
[m_window release];
|
||||
m_window = nil;
|
||||
}
|
||||
|
||||
//Check for other blender opened windows and make the frontmost key
|
||||
NSArray *windowsList = [NSApp orderedWindows];
|
||||
if ([windowsList count]) {
|
||||
[[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
|
||||
}
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
#pragma mark accessors
|
||||
|
||||
bool GHOST_WindowCocoa::getValid() const
|
||||
{
|
||||
return (m_window != 0);
|
||||
}
|
||||
|
||||
void* GHOST_WindowCocoa::getOSWindow() const
|
||||
{
|
||||
return (void*)m_window;
|
||||
}
|
||||
|
||||
void GHOST_WindowCocoa::setTitle(const STR_String& title)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid")
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSString *windowTitle = [[NSString alloc] initWithCString:title encoding:NSUTF8StringEncoding];
|
||||
|
||||
//Set associated file if applicable
|
||||
if (windowTitle && [windowTitle hasPrefix:@"Blender"])
|
||||
{
|
||||
NSRange fileStrRange;
|
||||
NSString *associatedFileName;
|
||||
int len;
|
||||
|
||||
fileStrRange.location = [windowTitle rangeOfString:@"["].location+1;
|
||||
len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location;
|
||||
|
||||
if (len >0)
|
||||
{
|
||||
fileStrRange.length = len;
|
||||
associatedFileName = [windowTitle substringWithRange:fileStrRange];
|
||||
[m_window setTitle:[associatedFileName lastPathComponent]];
|
||||
|
||||
//Blender used file open/save functions converte file names into legal URL ones
|
||||
associatedFileName = [associatedFileName stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
@try {
|
||||
[m_window setRepresentedFilename:associatedFileName];
|
||||
}
|
||||
@catch (NSException * e) {
|
||||
printf("\nInvalid file path given in window title");
|
||||
}
|
||||
}
|
||||
else {
|
||||
[m_window setTitle:windowTitle];
|
||||
[m_window setRepresentedFilename:@""];
|
||||
}
|
||||
|
||||
} else {
|
||||
[m_window setTitle:windowTitle];
|
||||
[m_window setRepresentedFilename:@""];
|
||||
}
|
||||
|
||||
|
||||
[windowTitle release];
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::getTitle(STR_String& title) const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid")
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSString *windowTitle = [m_window title];
|
||||
|
||||
if (windowTitle != nil) {
|
||||
title = [windowTitle UTF8String];
|
||||
}
|
||||
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const
|
||||
{
|
||||
NSRect rect;
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid")
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSRect screenSize = [[m_window screen] visibleFrame];
|
||||
|
||||
rect = [m_window frame];
|
||||
|
||||
bounds.m_b = screenSize.size.height - (rect.origin.y -screenSize.origin.y);
|
||||
bounds.m_l = rect.origin.x -screenSize.origin.x;
|
||||
bounds.m_r = rect.origin.x-screenSize.origin.x + rect.size.width;
|
||||
bounds.m_t = screenSize.size.height - (rect.origin.y + rect.size.height -screenSize.origin.y);
|
||||
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const
|
||||
{
|
||||
NSRect rect;
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid")
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (!m_fullScreen)
|
||||
{
|
||||
NSRect screenSize = [[m_window screen] visibleFrame];
|
||||
|
||||
//Max window contents as screen size (excluding title bar...)
|
||||
NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize
|
||||
styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
|
||||
|
||||
rect = [m_window contentRectForFrameRect:[m_window frame]];
|
||||
|
||||
bounds.m_b = contentRect.size.height - (rect.origin.y -contentRect.origin.y);
|
||||
bounds.m_l = rect.origin.x -contentRect.origin.x;
|
||||
bounds.m_r = rect.origin.x-contentRect.origin.x + rect.size.width;
|
||||
bounds.m_t = contentRect.size.height - (rect.origin.y + rect.size.height -contentRect.origin.y);
|
||||
}
|
||||
else {
|
||||
NSRect screenSize = [[m_window screen] frame];
|
||||
|
||||
bounds.m_b = screenSize.origin.y + screenSize.size.height;
|
||||
bounds.m_l = screenSize.origin.x;
|
||||
bounds.m_r = screenSize.origin.x + screenSize.size.width;
|
||||
bounds.m_t = screenSize.origin.y;
|
||||
}
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid")
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
GHOST_Rect cBnds, wBnds;
|
||||
getClientBounds(cBnds);
|
||||
if (((GHOST_TUns32)cBnds.getWidth()) != width) {
|
||||
NSSize size;
|
||||
size.width=width;
|
||||
size.height=cBnds.getHeight();
|
||||
[m_window setContentSize:size];
|
||||
}
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid")
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
GHOST_Rect cBnds, wBnds;
|
||||
getClientBounds(cBnds);
|
||||
if (((GHOST_TUns32)cBnds.getHeight()) != height) {
|
||||
NSSize size;
|
||||
size.width=cBnds.getWidth();
|
||||
size.height=height;
|
||||
[m_window setContentSize:size];
|
||||
}
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid")
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
GHOST_Rect cBnds, wBnds;
|
||||
getClientBounds(cBnds);
|
||||
if ((((GHOST_TUns32)cBnds.getWidth()) != width) ||
|
||||
(((GHOST_TUns32)cBnds.getHeight()) != height)) {
|
||||
NSSize size;
|
||||
size.width=width;
|
||||
size.height=height;
|
||||
[m_window setContentSize:size];
|
||||
}
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TWindowState GHOST_WindowCocoa::getState() const
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getState(): window invalid")
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
GHOST_TWindowState state;
|
||||
if (m_fullScreen) {
|
||||
state = GHOST_kWindowStateFullScreen;
|
||||
}
|
||||
else if ([m_window isMiniaturized]) {
|
||||
state = GHOST_kWindowStateMinimized;
|
||||
}
|
||||
else if ([m_window isZoomed]) {
|
||||
state = GHOST_kWindowStateMaximized;
|
||||
}
|
||||
else {
|
||||
state = GHOST_kWindowStateNormal;
|
||||
}
|
||||
[pool drain];
|
||||
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")
|
||||
|
||||
NSPoint screenCoord;
|
||||
NSPoint baseCoord;
|
||||
|
||||
screenCoord.x = inX;
|
||||
screenCoord.y = inY;
|
||||
|
||||
baseCoord = [m_window convertScreenToBase:screenCoord];
|
||||
|
||||
outX = baseCoord.x;
|
||||
outY = baseCoord.y;
|
||||
}
|
||||
|
||||
|
||||
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")
|
||||
|
||||
NSPoint screenCoord;
|
||||
NSPoint baseCoord;
|
||||
|
||||
baseCoord.x = inX;
|
||||
baseCoord.y = inY;
|
||||
|
||||
screenCoord = [m_window convertBaseToScreen:baseCoord];
|
||||
|
||||
outX = screenCoord.x;
|
||||
outY = screenCoord.y;
|
||||
}
|
||||
|
||||
|
||||
NSScreen* GHOST_WindowCocoa::getScreen()
|
||||
{
|
||||
return [m_window screen];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @note Fullscreen switch is not actual fullscreen with display capture. As this capture removes all OS X window manager features.
|
||||
* Instead, the menu bar and the dock are hidden, and the window is made borderless and enlarged.
|
||||
* Thus, process switch, exposé, spaces, ... still work in fullscreen mode
|
||||
*/
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid")
|
||||
switch (state) {
|
||||
case GHOST_kWindowStateMinimized:
|
||||
[m_window miniaturize:nil];
|
||||
break;
|
||||
case GHOST_kWindowStateMaximized:
|
||||
[m_window zoom:nil];
|
||||
break;
|
||||
|
||||
case GHOST_kWindowStateFullScreen:
|
||||
if (!m_fullScreen)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
//This status change needs to be done before Cocoa call to enter fullscreen mode
|
||||
//to give window delegate hint not to forward its deactivation to ghost wm that doesn't know view/window difference
|
||||
m_fullScreen = true;
|
||||
|
||||
#ifdef MAC_OS_X_VERSION_10_6
|
||||
//10.6 provides Cocoa functions to autoshow menu bar, and to change a window style
|
||||
//Hide menu & dock if needed
|
||||
if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]])
|
||||
{
|
||||
[NSApp setPresentationOptions:(NSApplicationPresentationHideDock | NSApplicationPresentationAutoHideMenuBar)];
|
||||
}
|
||||
//Make window borderless and enlarge it
|
||||
[m_window setStyleMask:NSBorderlessWindowMask];
|
||||
[m_window setFrame:[[m_window screen] frame] display:YES];
|
||||
[m_window makeFirstResponder:m_openGLView];
|
||||
#else
|
||||
//With 10.5, we need to create a new window to change its style to borderless
|
||||
//Hide menu & dock if needed
|
||||
if ([[m_window screen] isEqual:[[NSScreen screens] objectAtIndex:0]])
|
||||
{
|
||||
//Cocoa function in 10.5 does not allow to set the menu bar in auto-show mode [NSMenu setMenuBarVisible:NO];
|
||||
//One of the very few 64bit compatible Carbon function
|
||||
SetSystemUIMode(kUIModeAllHidden,kUIOptionAutoShowMenuBar);
|
||||
}
|
||||
//Create a fullscreen borderless window
|
||||
CocoaWindow *tmpWindow = [[CocoaWindow alloc]
|
||||
initWithContentRect:[[m_window screen] frame]
|
||||
styleMask:NSBorderlessWindowMask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:YES];
|
||||
//Copy current window parameters
|
||||
[tmpWindow setTitle:[m_window title]];
|
||||
[tmpWindow setRepresentedFilename:[m_window representedFilename]];
|
||||
[tmpWindow setReleasedWhenClosed:NO];
|
||||
[tmpWindow setAcceptsMouseMovedEvents:YES];
|
||||
[tmpWindow setDelegate:[m_window delegate]];
|
||||
[tmpWindow setSystemAndWindowCocoa:[m_window systemCocoa] windowCocoa:this];
|
||||
[tmpWindow registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
|
||||
NSStringPboardType, NSTIFFPboardType, nil]];
|
||||
|
||||
//Assign the openGL view to the new window
|
||||
[tmpWindow setContentView:m_openGLView];
|
||||
|
||||
//Show the new window
|
||||
[tmpWindow makeKeyAndOrderFront:m_openGLView];
|
||||
//Close and release old window
|
||||
[m_window setDelegate:nil]; // To avoid the notification of "window closed" event
|
||||
[m_window close];
|
||||
[m_window release];
|
||||
m_window = tmpWindow;
|
||||
#endif
|
||||
|
||||
//Tell WM of view new size
|
||||
m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this);
|
||||
|
||||
[pool drain];
|
||||
}
|
||||
break;
|
||||
case GHOST_kWindowStateNormal:
|
||||
default:
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
if (m_fullScreen)
|
||||
{
|
||||
m_fullScreen = false;
|
||||
|
||||
//Exit fullscreen
|
||||
#ifdef MAC_OS_X_VERSION_10_6
|
||||
//Show again menu & dock if needed
|
||||
if ([[m_window screen] isEqual:[NSScreen mainScreen]])
|
||||
{
|
||||
[NSApp setPresentationOptions:NSApplicationPresentationDefault];
|
||||
}
|
||||
//Make window normal and resize it
|
||||
[m_window setStyleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
|
||||
[m_window setFrame:[[m_window screen] visibleFrame] display:YES];
|
||||
//TODO for 10.6 only : window title is forgotten after the style change
|
||||
[m_window makeFirstResponder:m_openGLView];
|
||||
#else
|
||||
//With 10.5, we need to create a new window to change its style to borderless
|
||||
//Show menu & dock if needed
|
||||
if ([[m_window screen] isEqual:[NSScreen mainScreen]])
|
||||
{
|
||||
//Cocoa function in 10.5 does not allow to set the menu bar in auto-show mode [NSMenu setMenuBarVisible:YES];
|
||||
SetSystemUIMode(kUIModeNormal, 0); //One of the very few 64bit compatible Carbon function
|
||||
}
|
||||
//Create a fullscreen borderless window
|
||||
CocoaWindow *tmpWindow = [[CocoaWindow alloc]
|
||||
initWithContentRect:[[m_window screen] frame]
|
||||
styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:YES];
|
||||
//Copy current window parameters
|
||||
[tmpWindow setTitle:[m_window title]];
|
||||
[tmpWindow setRepresentedFilename:[m_window representedFilename]];
|
||||
[tmpWindow setReleasedWhenClosed:NO];
|
||||
[tmpWindow setAcceptsMouseMovedEvents:YES];
|
||||
[tmpWindow setDelegate:[m_window delegate]];
|
||||
[tmpWindow setSystemAndWindowCocoa:[m_window systemCocoa] windowCocoa:this];
|
||||
[tmpWindow registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType,
|
||||
NSStringPboardType, NSTIFFPboardType, nil]];
|
||||
//Forbid to resize the window below the blender defined minimum one
|
||||
[tmpWindow setContentMinSize:NSMakeSize(320, 240)];
|
||||
|
||||
//Assign the openGL view to the new window
|
||||
[tmpWindow setContentView:m_openGLView];
|
||||
|
||||
//Show the new window
|
||||
[tmpWindow makeKeyAndOrderFront:nil];
|
||||
//Close and release old window
|
||||
[m_window setDelegate:nil]; // To avoid the notification of "window closed" event
|
||||
[m_window close];
|
||||
[m_window release];
|
||||
m_window = tmpWindow;
|
||||
#endif
|
||||
|
||||
//Tell WM of view new size
|
||||
m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this);
|
||||
}
|
||||
else if ([m_window isMiniaturized])
|
||||
[m_window deminiaturize:nil];
|
||||
else if ([m_window isZoomed])
|
||||
[m_window zoom:nil];
|
||||
[pool drain];
|
||||
break;
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
[m_window setDocumentEdited:isUnsavedChanges];
|
||||
|
||||
[pool drain];
|
||||
return GHOST_Window::setModifiedState(isUnsavedChanges);
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid")
|
||||
if (order == GHOST_kWindowOrderTop) {
|
||||
[m_window makeKeyAndOrderFront:nil];
|
||||
}
|
||||
else {
|
||||
NSArray *windowsList;
|
||||
|
||||
[m_window orderBack:nil];
|
||||
|
||||
//Check for other blender opened windows and make the frontmost key
|
||||
windowsList = [NSApp orderedWindows];
|
||||
if ([windowsList count]) {
|
||||
[[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil];
|
||||
}
|
||||
}
|
||||
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
#pragma mark Drawing context
|
||||
|
||||
/*#define WAIT_FOR_VSYNC 1*/
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::swapBuffers()
|
||||
{
|
||||
if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
|
||||
if (m_openGLContext != nil) {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[m_openGLContext flushBuffer];
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext()
|
||||
{
|
||||
if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
|
||||
if (m_openGLContext != nil) {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[m_openGLContext update];
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext()
|
||||
{
|
||||
if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
|
||||
if (m_openGLContext != nil) {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[m_openGLContext makeCurrentContext];
|
||||
|
||||
// Disable AA by default
|
||||
if (m_numOfAASamples > 0) glDisable(GL_MULTISAMPLE_ARB);
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSOpenGLPixelFormat *pixelFormat;
|
||||
NSOpenGLContext *tmpOpenGLContext;
|
||||
|
||||
/***** Multithreaded opengl code : uncomment for enabling
|
||||
CGLContextObj cglCtx;
|
||||
*/
|
||||
|
||||
switch (type) {
|
||||
case GHOST_kDrawingContextTypeOpenGL:
|
||||
if (!getValid()) break;
|
||||
|
||||
pixelFormat = [m_openGLView pixelFormat];
|
||||
tmpOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
|
||||
shareContext:s_firstOpenGLcontext];
|
||||
if (tmpOpenGLContext == nil) {
|
||||
success = GHOST_kFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
//Switch openGL to multhreaded mode
|
||||
/******* Multithreaded opengl code : uncomment for enabling
|
||||
cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj];
|
||||
if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError)
|
||||
printf("\nSwitched openGL to multithreaded mode");
|
||||
*/
|
||||
|
||||
if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext;
|
||||
#ifdef WAIT_FOR_VSYNC
|
||||
{
|
||||
GLint swapInt = 1;
|
||||
/* wait for vsync, to avoid tearing artifacts */
|
||||
[tmpOpenGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
|
||||
}
|
||||
#endif
|
||||
[m_openGLView setOpenGLContext:tmpOpenGLContext];
|
||||
[tmpOpenGLContext setView:m_openGLView];
|
||||
|
||||
m_openGLContext = tmpOpenGLContext;
|
||||
break;
|
||||
|
||||
case GHOST_kDrawingContextTypeNone:
|
||||
success = GHOST_kSuccess;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[pool drain];
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext()
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
switch (m_drawingContextType) {
|
||||
case GHOST_kDrawingContextTypeOpenGL:
|
||||
if (m_openGLContext)
|
||||
{
|
||||
[m_openGLView clearGLContext];
|
||||
if (s_firstOpenGLcontext == m_openGLContext) s_firstOpenGLcontext = nil;
|
||||
m_openGLContext = nil;
|
||||
}
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
case GHOST_kDrawingContextTypeNone:
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
break;
|
||||
default:
|
||||
[pool drain];
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::invalidate()
|
||||
{
|
||||
GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid")
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[m_openGLView setNeedsDisplay:YES];
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
#pragma mark Progress bar
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setProgressBar(float progress)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if ((progress >=0.0) && (progress <=1.0)) {
|
||||
NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)];
|
||||
|
||||
[dockIcon lockFocus];
|
||||
NSRect progressBox = {{4, 4}, {120, 16}};
|
||||
|
||||
[[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0];
|
||||
|
||||
// Track & Outline
|
||||
[[NSColor blackColor] setFill];
|
||||
NSRectFill(progressBox);
|
||||
|
||||
[[NSColor whiteColor] set];
|
||||
NSFrameRect(progressBox);
|
||||
|
||||
// Progress fill
|
||||
progressBox = NSInsetRect(progressBox, 1, 1);
|
||||
[[NSColor knobColor] setFill];
|
||||
progressBox.size.width = progressBox.size.width * progress;
|
||||
NSRectFill(progressBox);
|
||||
|
||||
[dockIcon unlockFocus];
|
||||
|
||||
[NSApp setApplicationIconImage:dockIcon];
|
||||
[dockIcon release];
|
||||
|
||||
m_progressBarVisible = true;
|
||||
}
|
||||
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::endProgressBar()
|
||||
{
|
||||
if (!m_progressBarVisible) return GHOST_kFailure;
|
||||
m_progressBarVisible = false;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)];
|
||||
[dockIcon lockFocus];
|
||||
[[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0];
|
||||
[dockIcon unlockFocus];
|
||||
[NSApp setApplicationIconImage:dockIcon];
|
||||
[dockIcon release];
|
||||
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark Cursor handling
|
||||
|
||||
void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
|
||||
{
|
||||
static bool systemCursorVisible = true;
|
||||
|
||||
NSCursor *tmpCursor =nil;
|
||||
|
||||
if (visible != systemCursorVisible) {
|
||||
if (visible) {
|
||||
[NSCursor unhide];
|
||||
systemCursorVisible = true;
|
||||
}
|
||||
else {
|
||||
[NSCursor hide];
|
||||
systemCursorVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
|
||||
tmpCursor = m_customCursor;
|
||||
} else {
|
||||
switch (cursor) {
|
||||
case GHOST_kStandardCursorDestroy:
|
||||
tmpCursor = [NSCursor disappearingItemCursor];
|
||||
break;
|
||||
case GHOST_kStandardCursorText:
|
||||
tmpCursor = [NSCursor IBeamCursor];
|
||||
break;
|
||||
case GHOST_kStandardCursorCrosshair:
|
||||
tmpCursor = [NSCursor crosshairCursor];
|
||||
break;
|
||||
case GHOST_kStandardCursorUpDown:
|
||||
tmpCursor = [NSCursor resizeUpDownCursor];
|
||||
break;
|
||||
case GHOST_kStandardCursorLeftRight:
|
||||
tmpCursor = [NSCursor resizeLeftRightCursor];
|
||||
break;
|
||||
case GHOST_kStandardCursorTopSide:
|
||||
tmpCursor = [NSCursor resizeUpCursor];
|
||||
break;
|
||||
case GHOST_kStandardCursorBottomSide:
|
||||
tmpCursor = [NSCursor resizeDownCursor];
|
||||
break;
|
||||
case GHOST_kStandardCursorLeftSide:
|
||||
tmpCursor = [NSCursor resizeLeftCursor];
|
||||
break;
|
||||
case GHOST_kStandardCursorRightSide:
|
||||
tmpCursor = [NSCursor resizeRightCursor];
|
||||
break;
|
||||
case GHOST_kStandardCursorRightArrow:
|
||||
case GHOST_kStandardCursorInfo:
|
||||
case GHOST_kStandardCursorLeftArrow:
|
||||
case GHOST_kStandardCursorHelp:
|
||||
case GHOST_kStandardCursorCycle:
|
||||
case GHOST_kStandardCursorSpray:
|
||||
case GHOST_kStandardCursorWait:
|
||||
case GHOST_kStandardCursorTopLeftCorner:
|
||||
case GHOST_kStandardCursorTopRightCorner:
|
||||
case GHOST_kStandardCursorBottomRightCorner:
|
||||
case GHOST_kStandardCursorBottomLeftCorner:
|
||||
case GHOST_kStandardCursorCopy:
|
||||
case GHOST_kStandardCursorDefault:
|
||||
default:
|
||||
tmpCursor = [NSCursor arrowCursor];
|
||||
break;
|
||||
};
|
||||
}
|
||||
[tmpCursor set];
|
||||
}
|
||||
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
|
||||
|
||||
if ([m_window isVisible]) {
|
||||
loadCursor(visible, getCursorShape());
|
||||
}
|
||||
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
|
||||
{
|
||||
GHOST_TSuccess err = GHOST_kSuccess;
|
||||
|
||||
if (mode != GHOST_kGrabDisable)
|
||||
{
|
||||
//No need to perform grab without warp as it is always on in OS X
|
||||
if(mode != GHOST_kGrabNormal) {
|
||||
GHOST_TInt32 x_old,y_old;
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
m_systemCocoa->getCursorPosition(x_old,y_old);
|
||||
screenToClient(x_old, y_old, m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
|
||||
//Warp position is stored in client (window base) coordinates
|
||||
setCursorGrabAccum(0, 0);
|
||||
|
||||
if(mode == GHOST_kGrabHide) {
|
||||
setWindowCursorVisibility(false);
|
||||
}
|
||||
|
||||
//Make window key if it wasn't to get the mouse move events
|
||||
[m_window makeKeyWindow];
|
||||
|
||||
//Dissociate cursor position even for warp mode, to allow mouse acceleration to work even when warping the cursor
|
||||
err = CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
|
||||
|
||||
[pool drain];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(m_cursorGrab==GHOST_kGrabHide)
|
||||
{
|
||||
//No need to set again cursor position, as it has not changed for Cocoa
|
||||
setWindowCursorVisibility(true);
|
||||
}
|
||||
|
||||
err = CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
|
||||
/* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
|
||||
setCursorGrabAccum(0, 0);
|
||||
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (m_customCursor) {
|
||||
[m_customCursor release];
|
||||
m_customCursor = nil;
|
||||
}
|
||||
|
||||
if ([m_window isVisible]) {
|
||||
loadCursor(getCursorVisibility(), shape);
|
||||
}
|
||||
|
||||
[pool drain];
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/** 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,nbUns16;
|
||||
NSPoint hotSpotPoint;
|
||||
NSBitmapImageRep *cursorImageRep;
|
||||
NSImage *cursorImage;
|
||||
NSSize imSize;
|
||||
GHOST_TUns16 *cursorBitmap;
|
||||
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (m_customCursor) {
|
||||
[m_customCursor release];
|
||||
m_customCursor = nil;
|
||||
}
|
||||
|
||||
|
||||
cursorImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
|
||||
pixelsWide:sizex
|
||||
pixelsHigh:sizey
|
||||
bitsPerSample:1
|
||||
samplesPerPixel:2
|
||||
hasAlpha:YES
|
||||
isPlanar:YES
|
||||
colorSpaceName:NSDeviceWhiteColorSpace
|
||||
bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0))
|
||||
bitsPerPixel:1];
|
||||
|
||||
|
||||
cursorBitmap = (GHOST_TUns16*)[cursorImageRep bitmapData];
|
||||
nbUns16 = [cursorImageRep bytesPerPlane]/2;
|
||||
|
||||
for (y=0; y<nbUns16; y++) {
|
||||
#if !defined(__LITTLE_ENDIAN__)
|
||||
cursorBitmap[y] = ~uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8));
|
||||
cursorBitmap[nbUns16+y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8));
|
||||
#else
|
||||
cursorBitmap[y] = ~uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8));
|
||||
cursorBitmap[nbUns16+y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
imSize.width = sizex;
|
||||
imSize.height= sizey;
|
||||
cursorImage = [[NSImage alloc] initWithSize:imSize];
|
||||
[cursorImage addRepresentation:cursorImageRep];
|
||||
|
||||
hotSpotPoint.x = hotX;
|
||||
hotSpotPoint.y = hotY;
|
||||
|
||||
//foreground and background color parameter is not handled for now (10.6)
|
||||
m_customCursor = [[NSCursor alloc] initWithImage:cursorImage
|
||||
hotSpot:hotSpotPoint];
|
||||
|
||||
[cursorImageRep release];
|
||||
[cursorImage release];
|
||||
|
||||
if ([m_window isVisible]) {
|
||||
loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
|
||||
}
|
||||
[pool drain];
|
||||
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);
|
||||
}
|
||||
220
intern/ghost/intern/GHOST_WindowManager.cpp
Normal file
220
intern/ghost/intern/GHOST_WindowManager.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_WindowManager.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 11, 2001
|
||||
*/
|
||||
|
||||
#include "GHOST_WindowManager.h"
|
||||
#include <algorithm>
|
||||
#include "GHOST_Debug.h"
|
||||
#include "GHOST_Window.h"
|
||||
|
||||
|
||||
GHOST_WindowManager::GHOST_WindowManager() :
|
||||
m_fullScreenWindow(0),
|
||||
m_activeWindow(0),
|
||||
m_activeWindowBeforeFullScreen(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GHOST_WindowManager::~GHOST_WindowManager()
|
||||
{
|
||||
/* m_windows is freed by GHOST_System::disposeWindow */
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowManager::addWindow(GHOST_IWindow* window)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
if (window) {
|
||||
if (!getWindowFound(window)) {
|
||||
// Store the pointer to the window
|
||||
m_windows.push_back(window);
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowManager::removeWindow(const GHOST_IWindow* window)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
if (window) {
|
||||
if (window == m_fullScreenWindow) {
|
||||
endFullScreen();
|
||||
}
|
||||
else {
|
||||
vector<GHOST_IWindow*>::iterator result = find(m_windows.begin(), m_windows.end(), window);
|
||||
if (result != m_windows.end()) {
|
||||
setWindowInactive(window);
|
||||
m_windows.erase(result);
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_WindowManager::getWindowFound(const GHOST_IWindow* window) const
|
||||
{
|
||||
bool found = false;
|
||||
if (window) {
|
||||
if (getFullScreen() && (window == m_fullScreenWindow)) {
|
||||
found = true;
|
||||
}
|
||||
else {
|
||||
vector<GHOST_IWindow*>::const_iterator result = find(m_windows.begin(), m_windows.end(), window);
|
||||
if (result != m_windows.end()) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
bool GHOST_WindowManager::getFullScreen(void) const
|
||||
{
|
||||
return m_fullScreenWindow != 0;
|
||||
}
|
||||
|
||||
|
||||
GHOST_IWindow* GHOST_WindowManager::getFullScreenWindow(void) const
|
||||
{
|
||||
return m_fullScreenWindow;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowManager::beginFullScreen(GHOST_IWindow* window,
|
||||
bool stereoVisual)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
GHOST_ASSERT(window, "GHOST_WindowManager::beginFullScreen(): invalid window");
|
||||
GHOST_ASSERT(window->getValid(), "GHOST_WindowManager::beginFullScreen(): invalid window");
|
||||
if (!getFullScreen()) {
|
||||
m_fullScreenWindow = window;
|
||||
m_activeWindowBeforeFullScreen = getActiveWindow();
|
||||
setActiveWindow(m_fullScreenWindow);
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowManager::endFullScreen(void)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kFailure;
|
||||
if (getFullScreen()) {
|
||||
if (m_fullScreenWindow != 0) {
|
||||
//GHOST_PRINT("GHOST_WindowManager::endFullScreen(): deleting full-screen window\n");
|
||||
setWindowInactive(m_fullScreenWindow);
|
||||
delete m_fullScreenWindow;
|
||||
//GHOST_PRINT("GHOST_WindowManager::endFullScreen(): done\n");
|
||||
m_fullScreenWindow = 0;
|
||||
if (m_activeWindowBeforeFullScreen) {
|
||||
setActiveWindow(m_activeWindowBeforeFullScreen);
|
||||
}
|
||||
}
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowManager::setActiveWindow(GHOST_IWindow* window)
|
||||
{
|
||||
GHOST_TSuccess success = GHOST_kSuccess;
|
||||
if (window != m_activeWindow) {
|
||||
if (getWindowFound(window)) {
|
||||
m_activeWindow = window;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_IWindow* GHOST_WindowManager::getActiveWindow(void) const
|
||||
{
|
||||
return m_activeWindow;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowManager::setWindowInactive(const GHOST_IWindow* window)
|
||||
{
|
||||
if (window == m_activeWindow) {
|
||||
m_activeWindow = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<GHOST_IWindow *> &GHOST_WindowManager::getWindows()
|
||||
{
|
||||
return m_windows;
|
||||
}
|
||||
|
||||
|
||||
GHOST_IWindow* GHOST_WindowManager::getWindowAssociatedWithOSWindow(void* osWindow)
|
||||
{
|
||||
std::vector<GHOST_IWindow*>::iterator iter;
|
||||
|
||||
for (iter = m_windows.begin(); iter != m_windows.end(); iter++) {
|
||||
if ((*iter)->getOSWindow() == osWindow)
|
||||
return *iter;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool GHOST_WindowManager::getAnyModifiedState()
|
||||
{
|
||||
bool isAnyModified = false;
|
||||
std::vector<GHOST_IWindow*>::iterator iter;
|
||||
|
||||
for (iter = m_windows.begin(); iter != m_windows.end(); iter++) {
|
||||
if ((*iter)->getModifiedState())
|
||||
isAnyModified = true;
|
||||
}
|
||||
|
||||
return isAnyModified;
|
||||
}
|
||||
174
intern/ghost/intern/GHOST_WindowManager.h
Normal file
174
intern/ghost/intern/GHOST_WindowManager.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_WindowManager.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_WindowManager class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_WINDOW_MANAGER_H_
|
||||
#define _GHOST_WINDOW_MANAGER_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "GHOST_Rect.h"
|
||||
#include "GHOST_IWindow.h"
|
||||
|
||||
|
||||
/**
|
||||
* Manages system windows (platform independent implementation).
|
||||
* @author Maarten Gribnau
|
||||
* @date May 11, 2001
|
||||
*/
|
||||
class GHOST_WindowManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
GHOST_WindowManager();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~GHOST_WindowManager();
|
||||
|
||||
/**
|
||||
* Add a window to our list.
|
||||
* It is only added if it is not already in the list.
|
||||
* @param window Pointer to the window to be added.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess addWindow(GHOST_IWindow* window);
|
||||
|
||||
/**
|
||||
* Remove a window from our list.
|
||||
* @param window Pointer to the window to be removed.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess removeWindow(const GHOST_IWindow* window);
|
||||
|
||||
/**
|
||||
* Returns whether the window is in our list.
|
||||
* @param window Pointer to the window to query.
|
||||
* @return A boolean indicator.
|
||||
*/
|
||||
virtual bool getWindowFound(const GHOST_IWindow* window) const;
|
||||
|
||||
/**
|
||||
* Returns whether one of the windows is fullscreen.
|
||||
* @return A boolean indicator.
|
||||
*/
|
||||
virtual bool getFullScreen(void) const;
|
||||
|
||||
/**
|
||||
* Returns pointer to the full-screen window.
|
||||
* @return The fll-screen window (0 if not in full-screen).
|
||||
*/
|
||||
virtual GHOST_IWindow* getFullScreenWindow(void) const;
|
||||
|
||||
/**
|
||||
* Activates fullscreen mode for a window.
|
||||
* @param window The window displayed fullscreen.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess beginFullScreen(GHOST_IWindow* window, const bool stereoVisual);
|
||||
|
||||
/**
|
||||
* Closes fullscreen mode down.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess endFullScreen(void);
|
||||
|
||||
/**
|
||||
* Sets new window as active window (the window receiving events).
|
||||
* There can be only one window active which should be in the current window list.
|
||||
* @param window The new active window.
|
||||
*/
|
||||
virtual GHOST_TSuccess setActiveWindow(GHOST_IWindow* window);
|
||||
|
||||
/**
|
||||
* Returns the active window (the window receiving events).
|
||||
* There can be only one window active which should be in the current window list.
|
||||
* @return window The active window (or NULL if there is none).
|
||||
*/
|
||||
virtual GHOST_IWindow* getActiveWindow(void) const;
|
||||
|
||||
|
||||
/**
|
||||
* Set this window to be inactive (not receiving events).
|
||||
* @param window The window to decativate.
|
||||
*/
|
||||
virtual void setWindowInactive(const GHOST_IWindow* window);
|
||||
|
||||
|
||||
/**
|
||||
* Return a vector of the windows currently managed by this
|
||||
* class.
|
||||
* @warning It is very dangerous to mess with the contents of
|
||||
* this vector. Please do not destroy or add windows use the
|
||||
* interface above for this,
|
||||
*/
|
||||
std::vector<GHOST_IWindow *> & getWindows();
|
||||
|
||||
/**
|
||||
* Finds the window associated with an OS window object/handle
|
||||
* @param osWindow The OS window object/handle
|
||||
* @return The associated window, null if none corresponds
|
||||
*/
|
||||
virtual GHOST_IWindow* getWindowAssociatedWithOSWindow(void* osWindow);
|
||||
|
||||
/**
|
||||
* Return true if any windows has a modified status
|
||||
* @return True if any window has unsaved changes
|
||||
*/
|
||||
bool getAnyModifiedState();
|
||||
|
||||
protected:
|
||||
/** The list of windows managed */
|
||||
std::vector<GHOST_IWindow*> m_windows;
|
||||
|
||||
/** Window in fullscreen state. There can be only one of this which is not in or window list. */
|
||||
GHOST_IWindow* m_fullScreenWindow;
|
||||
|
||||
/** The active window. */
|
||||
GHOST_IWindow* m_activeWindow;
|
||||
|
||||
/** Window that was active before entering fullscreen state. */
|
||||
GHOST_IWindow* m_activeWindowBeforeFullScreen;
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
public:
|
||||
void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GHOST:GHOST_WindowManager"); }
|
||||
void operator delete( void *mem ) { MEM_freeN(mem); }
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // _GHOST_WINDOW_MANAGER_H_
|
||||
|
||||
1351
intern/ghost/intern/GHOST_WindowWin32.cpp
Normal file
1351
intern/ghost/intern/GHOST_WindowWin32.cpp
Normal file
@@ -0,0 +1,1351 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_WindowWin32.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 10, 2001
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "GHOST_WindowWin32.h"
|
||||
#include "GHOST_SystemWin32.h"
|
||||
#include "GHOST_DropTargetWin32.h"
|
||||
|
||||
// Need glew for some defines
|
||||
#include <GL/glew.h>
|
||||
#include <GL/wglew.h>
|
||||
#include <math.h>
|
||||
|
||||
// MSVC6 still doesn't define M_PI
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926536
|
||||
#endif
|
||||
|
||||
// Some more multisample defines
|
||||
#define WGL_SAMPLE_BUFERS_ARB 0x2041
|
||||
#define WGL_SAMPLES_ARB 0x2042
|
||||
|
||||
// win64 doesn't define GWL_USERDATA
|
||||
#ifdef WIN32
|
||||
#ifndef GWL_USERDATA
|
||||
#define GWL_USERDATA GWLP_USERDATA
|
||||
#define GWL_WNDPROC GWLP_WNDPROC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass";
|
||||
const int GHOST_WindowWin32::s_maxTitleLength = 128;
|
||||
HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL;
|
||||
HDC GHOST_WindowWin32::s_firstHDC = NULL;
|
||||
|
||||
static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd);
|
||||
static int EnumPixelFormats(HDC hdc);
|
||||
|
||||
/*
|
||||
* Color and depth bit values are not to be trusted.
|
||||
* For instance, on TNT2:
|
||||
* When the screen color depth is set to 16 bit, we get 5 color bits
|
||||
* and 16 depth bits.
|
||||
* When the screen color depth is set to 32 bit, we get 8 color bits
|
||||
* and 24 depth bits.
|
||||
* Just to be safe, we request high waulity settings.
|
||||
*/
|
||||
static PIXELFORMATDESCRIPTOR sPreferredFormat = {
|
||||
sizeof(PIXELFORMATDESCRIPTOR), /* size */
|
||||
1, /* version */
|
||||
PFD_SUPPORT_OPENGL |
|
||||
PFD_DRAW_TO_WINDOW |
|
||||
PFD_SWAP_COPY | /* support swap copy */
|
||||
PFD_DOUBLEBUFFER, /* support double-buffering */
|
||||
PFD_TYPE_RGBA, /* color type */
|
||||
32, /* prefered color depth */
|
||||
0, 0, 0, 0, 0, 0, /* color bits (ignored) */
|
||||
0, /* no alpha buffer */
|
||||
0, /* alpha bits (ignored) */
|
||||
0, /* no accumulation buffer */
|
||||
0, 0, 0, 0, /* accum bits (ignored) */
|
||||
32, /* depth buffer */
|
||||
0, /* no stencil buffer */
|
||||
0, /* no auxiliary buffers */
|
||||
PFD_MAIN_PLANE, /* main layer */
|
||||
0, /* reserved */
|
||||
0, 0, 0 /* no layer, visible, damage masks */
|
||||
};
|
||||
|
||||
/* Intel videocards don't work fine with multiple contexts and
|
||||
have to share the same context for all windows.
|
||||
But if we just share context for all windows it could work incorrect
|
||||
with multiple videocards configuration. Suppose, that Intel videocards
|
||||
can't be in multiple-devices configuration. */
|
||||
static int is_crappy_intel_card(void)
|
||||
{
|
||||
int crappy = 0;
|
||||
const char *vendor = (const char*)glGetString(GL_VENDOR);
|
||||
|
||||
if (strstr(vendor, "Intel"))
|
||||
crappy = 1;
|
||||
|
||||
return crappy;
|
||||
}
|
||||
|
||||
GHOST_WindowWin32::GHOST_WindowWin32(
|
||||
GHOST_SystemWin32 * system,
|
||||
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_TUns16 numOfAASamples,
|
||||
GHOST_TEmbedderWindowID parentwindowhwnd,
|
||||
GHOST_TSuccess msEnabled,
|
||||
int msPixelFormat)
|
||||
:
|
||||
GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone,
|
||||
stereoVisual,numOfAASamples),
|
||||
m_system(system),
|
||||
m_hDC(0),
|
||||
m_hGlRc(0),
|
||||
m_hasMouseCaptured(false),
|
||||
m_hasGrabMouse(false),
|
||||
m_nPressedButtons(0),
|
||||
m_customCursor(0),
|
||||
m_wintab(NULL),
|
||||
m_tabletData(NULL),
|
||||
m_tablet(0),
|
||||
m_maxPressure(0),
|
||||
m_multisample(numOfAASamples),
|
||||
m_parentWindowHwnd(parentwindowhwnd),
|
||||
m_multisampleEnabled(msEnabled),
|
||||
m_msPixelFormat(msPixelFormat),
|
||||
//For recreation
|
||||
m_title(title),
|
||||
m_left(left),
|
||||
m_top(top),
|
||||
m_width(width),
|
||||
m_height(height),
|
||||
m_normal_state(GHOST_kWindowStateNormal),
|
||||
m_stereo(stereoVisual),
|
||||
m_nextWindow(NULL)
|
||||
{
|
||||
OSVERSIONINFOEX versionInfo;
|
||||
bool hasMinVersionForTaskbar = false;
|
||||
|
||||
ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX));
|
||||
|
||||
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
|
||||
if(!GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
|
||||
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
if(GetVersionEx((OSVERSIONINFO*)&versionInfo)) {
|
||||
if((versionInfo.dwMajorVersion==6 && versionInfo.dwMinorVersion>=1) || versionInfo.dwMajorVersion >= 7) {
|
||||
hasMinVersionForTaskbar = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if((versionInfo.dwMajorVersion==6 && versionInfo.dwMinorVersion>=1) || versionInfo.dwMajorVersion >= 7) {
|
||||
hasMinVersionForTaskbar = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (state != GHOST_kWindowStateFullScreen) {
|
||||
RECT rect;
|
||||
MONITORINFO monitor;
|
||||
GHOST_TUns32 tw, th;
|
||||
|
||||
width += GetSystemMetrics(SM_CXSIZEFRAME)*2;
|
||||
height += GetSystemMetrics(SM_CYSIZEFRAME)*2 + GetSystemMetrics(SM_CYCAPTION);
|
||||
|
||||
rect.left = left;
|
||||
rect.right = left + width;
|
||||
rect.top = top;
|
||||
rect.bottom = top + height;
|
||||
|
||||
monitor.cbSize=sizeof(monitor);
|
||||
monitor.dwFlags=0;
|
||||
|
||||
// take taskbar into account
|
||||
GetMonitorInfo(MonitorFromRect(&rect,MONITOR_DEFAULTTONEAREST),&monitor);
|
||||
|
||||
th = monitor.rcWork.bottom - monitor.rcWork.top;
|
||||
tw = monitor.rcWork.right - monitor.rcWork.left;
|
||||
|
||||
if(tw < width)
|
||||
{
|
||||
width = tw;
|
||||
left = monitor.rcWork.left;
|
||||
}
|
||||
else if(monitor.rcWork.right < left + (int)width)
|
||||
left = monitor.rcWork.right - width;
|
||||
else if(left < monitor.rcWork.left)
|
||||
left = monitor.rcWork.left;
|
||||
|
||||
if(th < height)
|
||||
{
|
||||
height = th;
|
||||
top = monitor.rcWork.top;
|
||||
}
|
||||
else if(monitor.rcWork.bottom < top + (int)height)
|
||||
top = monitor.rcWork.bottom - height;
|
||||
else if(top < monitor.rcWork.top)
|
||||
top = monitor.rcWork.top;
|
||||
|
||||
int wintype = WS_OVERLAPPEDWINDOW;
|
||||
if (m_parentWindowHwnd != 0)
|
||||
{
|
||||
wintype = WS_CHILD;
|
||||
GetWindowRect((HWND)m_parentWindowHwnd, &rect);
|
||||
left = 0;
|
||||
top = 0;
|
||||
width = rect.right - rect.left;
|
||||
height = rect.bottom - rect.top;
|
||||
}
|
||||
|
||||
m_hWnd = ::CreateWindow(
|
||||
s_windowClassName, // pointer to registered class name
|
||||
title, // pointer to window name
|
||||
wintype, // window style
|
||||
left, // horizontal position of window
|
||||
top, // vertical position of window
|
||||
width, // window width
|
||||
height, // window height
|
||||
(HWND) m_parentWindowHwnd, // handle to parent or owner window
|
||||
0, // handle to menu or child-window identifier
|
||||
::GetModuleHandle(0), // handle to application instance
|
||||
0); // pointer to window-creation data
|
||||
}
|
||||
else {
|
||||
m_hWnd = ::CreateWindow(
|
||||
s_windowClassName, // pointer to registered class name
|
||||
title, // pointer to window name
|
||||
WS_POPUP | WS_MAXIMIZE, // window style
|
||||
left, // horizontal position of window
|
||||
top, // vertical position of window
|
||||
width, // window width
|
||||
height, // window height
|
||||
HWND_DESKTOP, // handle to parent or owner window
|
||||
0, // handle to menu or child-window identifier
|
||||
::GetModuleHandle(0), // handle to application instance
|
||||
0); // pointer to window-creation data
|
||||
}
|
||||
if (m_hWnd) {
|
||||
// Register this window as a droptarget. Requires m_hWnd to be valid.
|
||||
// Note that OleInitialize(0) has to be called prior to this. Done in GHOST_SystemWin32.
|
||||
m_dropTarget = new GHOST_DropTargetWin32(this, m_system);
|
||||
// Store a pointer to this class in the window structure
|
||||
::SetWindowLongPtr(m_hWnd, GWL_USERDATA, (LONG_PTR)this);
|
||||
|
||||
// Store the device context
|
||||
m_hDC = ::GetDC(m_hWnd);
|
||||
|
||||
if(!s_firstHDC) {
|
||||
s_firstHDC = m_hDC;
|
||||
}
|
||||
|
||||
// Show the window
|
||||
int nCmdShow;
|
||||
switch (state) {
|
||||
case GHOST_kWindowStateMaximized:
|
||||
nCmdShow = SW_SHOWMAXIMIZED;
|
||||
break;
|
||||
case GHOST_kWindowStateMinimized:
|
||||
nCmdShow = SW_SHOWMINIMIZED;
|
||||
break;
|
||||
case GHOST_kWindowStateNormal:
|
||||
default:
|
||||
nCmdShow = SW_SHOWNORMAL;
|
||||
break;
|
||||
}
|
||||
GHOST_TSuccess success;
|
||||
success = setDrawingContextType(type);
|
||||
|
||||
if (success)
|
||||
{
|
||||
::ShowWindow(m_hWnd, nCmdShow);
|
||||
// Force an initial paint of the window
|
||||
::UpdateWindow(m_hWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
//invalidate the window
|
||||
m_hWnd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (parentwindowhwnd != 0) {
|
||||
RAWINPUTDEVICE device = {0};
|
||||
device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/
|
||||
device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
|
||||
device.dwFlags |= RIDEV_INPUTSINK; // makes WM_INPUT is visible for ghost when has parent window
|
||||
device.hwndTarget = m_hWnd;
|
||||
RegisterRawInputDevices(&device, 1, sizeof(device));
|
||||
}
|
||||
|
||||
m_wintab = ::LoadLibrary("Wintab32.dll");
|
||||
if (m_wintab) {
|
||||
GHOST_WIN32_WTInfo fpWTInfo = ( GHOST_WIN32_WTInfo ) ::GetProcAddress( m_wintab, "WTInfoA" );
|
||||
GHOST_WIN32_WTOpen fpWTOpen = ( GHOST_WIN32_WTOpen ) ::GetProcAddress( m_wintab, "WTOpenA" );
|
||||
|
||||
// let's see if we can initialize tablet here
|
||||
/* check if WinTab available. */
|
||||
if (fpWTInfo && fpWTInfo(0, 0, NULL)) {
|
||||
// Now init the tablet
|
||||
LOGCONTEXT lc;
|
||||
AXIS TabletX, TabletY, Pressure, Orientation[3]; /* The maximum tablet size, pressure and orientation (tilt) */
|
||||
|
||||
// Open a Wintab context
|
||||
|
||||
// Get default context information
|
||||
fpWTInfo( WTI_DEFCONTEXT, 0, &lc );
|
||||
|
||||
// Open the context
|
||||
lc.lcPktData = PACKETDATA;
|
||||
lc.lcPktMode = PACKETMODE;
|
||||
lc.lcOptions |= CXO_MESSAGES | CXO_SYSTEM;
|
||||
|
||||
/* Set the entire tablet as active */
|
||||
fpWTInfo(WTI_DEVICES,DVC_X,&TabletX);
|
||||
fpWTInfo(WTI_DEVICES,DVC_Y,&TabletY);
|
||||
|
||||
/* get the max pressure, to divide into a float */
|
||||
BOOL pressureSupport = fpWTInfo (WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
||||
if (pressureSupport)
|
||||
m_maxPressure = Pressure.axMax;
|
||||
else
|
||||
m_maxPressure = 0;
|
||||
|
||||
/* get the max tilt axes, to divide into floats */
|
||||
BOOL tiltSupport = fpWTInfo (WTI_DEVICES, DVC_ORIENTATION, &Orientation);
|
||||
if (tiltSupport) {
|
||||
/* does the tablet support azimuth ([0]) and altitude ([1]) */
|
||||
if (Orientation[0].axResolution && Orientation[1].axResolution) {
|
||||
/* all this assumes the minimum is 0 */
|
||||
m_maxAzimuth = Orientation[0].axMax;
|
||||
m_maxAltitude = Orientation[1].axMax;
|
||||
}
|
||||
else { /* no so dont do tilt stuff */
|
||||
m_maxAzimuth = m_maxAltitude = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (fpWTOpen) {
|
||||
m_tablet = fpWTOpen( m_hWnd, &lc, TRUE );
|
||||
if (m_tablet) {
|
||||
m_tabletData = new GHOST_TabletData();
|
||||
m_tabletData->Active = GHOST_kTabletModeNone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(hasMinVersionForTaskbar)
|
||||
CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList ,(LPVOID*)&m_Bar);
|
||||
else
|
||||
m_Bar=NULL;
|
||||
}
|
||||
|
||||
|
||||
GHOST_WindowWin32::~GHOST_WindowWin32()
|
||||
{
|
||||
if(m_Bar)
|
||||
{
|
||||
m_Bar->SetProgressState(m_hWnd, TBPF_NOPROGRESS);
|
||||
m_Bar->Release();
|
||||
};
|
||||
|
||||
if (m_wintab) {
|
||||
GHOST_WIN32_WTClose fpWTClose = ( GHOST_WIN32_WTClose ) ::GetProcAddress( m_wintab, "WTClose" );
|
||||
if (fpWTClose) {
|
||||
if (m_tablet)
|
||||
fpWTClose(m_tablet);
|
||||
if (m_tabletData)
|
||||
delete m_tabletData;
|
||||
m_tabletData = NULL;
|
||||
}
|
||||
}
|
||||
if (m_customCursor) {
|
||||
DestroyCursor(m_customCursor);
|
||||
m_customCursor = NULL;
|
||||
}
|
||||
|
||||
::wglMakeCurrent(NULL, NULL);
|
||||
m_multisampleEnabled = GHOST_kFailure;
|
||||
m_multisample = 0;
|
||||
setDrawingContextType(GHOST_kDrawingContextTypeNone);
|
||||
if (m_hDC && m_hDC != s_firstHDC) {
|
||||
::ReleaseDC(m_hWnd, m_hDC);
|
||||
m_hDC = 0;
|
||||
}
|
||||
if (m_hWnd) {
|
||||
m_dropTarget->Release(); // frees itself.
|
||||
::DestroyWindow(m_hWnd);
|
||||
m_hWnd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_Window *GHOST_WindowWin32::getNextWindow()
|
||||
{
|
||||
return m_nextWindow;
|
||||
}
|
||||
|
||||
bool GHOST_WindowWin32::getValid() const
|
||||
{
|
||||
return m_hWnd != 0;
|
||||
}
|
||||
|
||||
HWND GHOST_WindowWin32::getHWND() const
|
||||
{
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::setTitle(const STR_String& title)
|
||||
{
|
||||
::SetWindowText(m_hWnd, title);
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowWin32::getTitle(STR_String& title) const
|
||||
{
|
||||
char buf[s_maxTitleLength];
|
||||
::GetWindowText(m_hWnd, buf, s_maxTitleLength);
|
||||
STR_String temp (buf);
|
||||
title = buf;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowWin32::getWindowBounds(GHOST_Rect& bounds) const
|
||||
{
|
||||
RECT rect;
|
||||
::GetWindowRect(m_hWnd, &rect);
|
||||
bounds.m_b = rect.bottom;
|
||||
bounds.m_l = rect.left;
|
||||
bounds.m_r = rect.right;
|
||||
bounds.m_t = rect.top;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowWin32::getClientBounds(GHOST_Rect& bounds) const
|
||||
{
|
||||
RECT rect;
|
||||
GHOST_TWindowState state= this->getState();
|
||||
LONG_PTR result = ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
|
||||
int sm_cysizeframe = GetSystemMetrics(SM_CYSIZEFRAME);
|
||||
::GetWindowRect(m_hWnd, &rect);
|
||||
|
||||
if((result & (WS_POPUP | WS_MAXIMIZE)) != (WS_POPUP | WS_MAXIMIZE)) {
|
||||
if(state==GHOST_kWindowStateMaximized) {
|
||||
// in maximized state we don't have borders on the window
|
||||
bounds.m_b = rect.bottom-GetSystemMetrics(SM_CYCAPTION)- sm_cysizeframe*2;
|
||||
bounds.m_l = rect.left + sm_cysizeframe;
|
||||
bounds.m_r = rect.right - sm_cysizeframe;
|
||||
bounds.m_t = rect.top;
|
||||
} else if (state == GHOST_kWindowStateEmbedded) {
|
||||
bounds.m_b = rect.bottom;
|
||||
bounds.m_l = rect.left;
|
||||
bounds.m_r = rect.right;
|
||||
bounds.m_t = rect.top;
|
||||
} else {
|
||||
bounds.m_b = rect.bottom-GetSystemMetrics(SM_CYCAPTION)-sm_cysizeframe*2;
|
||||
bounds.m_l = rect.left;
|
||||
bounds.m_r = rect.right-sm_cysizeframe*2;
|
||||
bounds.m_t = rect.top;
|
||||
}
|
||||
} else {
|
||||
bounds.m_b = rect.bottom;
|
||||
bounds.m_l = rect.left;
|
||||
bounds.m_r = rect.right;
|
||||
bounds.m_t = rect.top;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setClientWidth(GHOST_TUns32 width)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
GHOST_Rect cBnds, wBnds;
|
||||
getClientBounds(cBnds);
|
||||
if (cBnds.getWidth() != (GHOST_TInt32)width) {
|
||||
getWindowBounds(wBnds);
|
||||
int cx = wBnds.getWidth() + width - cBnds.getWidth();
|
||||
int cy = wBnds.getHeight();
|
||||
success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
|
||||
GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setClientHeight(GHOST_TUns32 height)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
GHOST_Rect cBnds, wBnds;
|
||||
getClientBounds(cBnds);
|
||||
if (cBnds.getHeight() != (GHOST_TInt32)height) {
|
||||
getWindowBounds(wBnds);
|
||||
int cx = wBnds.getWidth();
|
||||
int cy = wBnds.getHeight() + height - cBnds.getHeight();
|
||||
success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
|
||||
GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
GHOST_Rect cBnds, wBnds;
|
||||
getClientBounds(cBnds);
|
||||
if ((cBnds.getWidth() != (GHOST_TInt32)width) || (cBnds.getHeight() != (GHOST_TInt32)height)) {
|
||||
getWindowBounds(wBnds);
|
||||
int cx = wBnds.getWidth() + width - cBnds.getWidth();
|
||||
int cy = wBnds.getHeight() + height - cBnds.getHeight();
|
||||
success = ::SetWindowPos(m_hWnd, HWND_TOP, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER) ?
|
||||
GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TWindowState GHOST_WindowWin32::getState() const
|
||||
{
|
||||
GHOST_TWindowState state;
|
||||
|
||||
// XXX 27.04.2011
|
||||
// we need to find a way to combine parented windows + resizing if we simply set the
|
||||
// state as GHOST_kWindowStateEmbedded we will need to check for them somewhere else.
|
||||
// It's also strange that in Windows is the only platform we need to make this separation.
|
||||
if (m_parentWindowHwnd != 0) {
|
||||
state = GHOST_kWindowStateEmbedded;
|
||||
return state;
|
||||
}
|
||||
if (::IsIconic(m_hWnd)) {
|
||||
state = GHOST_kWindowStateMinimized;
|
||||
}
|
||||
else if (::IsZoomed(m_hWnd)) {
|
||||
LONG_PTR result = ::GetWindowLongPtr(m_hWnd, GWL_STYLE);
|
||||
if((result & (WS_POPUP | WS_MAXIMIZE)) != (WS_POPUP | WS_MAXIMIZE))
|
||||
state = GHOST_kWindowStateMaximized;
|
||||
else
|
||||
state = GHOST_kWindowStateFullScreen;
|
||||
}
|
||||
else {
|
||||
state = GHOST_kWindowStateNormal;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowWin32::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
|
||||
{
|
||||
POINT point = { inX, inY };
|
||||
::ScreenToClient(m_hWnd, &point);
|
||||
outX = point.x;
|
||||
outY = point.y;
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowWin32::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const
|
||||
{
|
||||
POINT point = { inX, inY };
|
||||
::ClientToScreen(m_hWnd, &point);
|
||||
outX = point.x;
|
||||
outY = point.y;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
|
||||
{
|
||||
GHOST_TWindowState curstate = getState();
|
||||
WINDOWPLACEMENT wp;
|
||||
wp.length = sizeof(WINDOWPLACEMENT);
|
||||
::GetWindowPlacement(m_hWnd, &wp);
|
||||
|
||||
if (state == GHOST_kWindowStateNormal)
|
||||
state = m_normal_state;
|
||||
switch (state) {
|
||||
case GHOST_kWindowStateMinimized:
|
||||
wp.showCmd = SW_SHOWMINIMIZED;
|
||||
break;
|
||||
case GHOST_kWindowStateMaximized:
|
||||
ShowWindow(m_hWnd, SW_HIDE);
|
||||
wp.showCmd = SW_SHOWMAXIMIZED;
|
||||
SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
|
||||
break;
|
||||
case GHOST_kWindowStateFullScreen:
|
||||
if (curstate != state && curstate != GHOST_kWindowStateMinimized)
|
||||
m_normal_state = curstate;
|
||||
wp.showCmd = SW_SHOWMAXIMIZED;
|
||||
wp.ptMaxPosition.x = 0;
|
||||
wp.ptMaxPosition.y = 0;
|
||||
SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_POPUP | WS_MAXIMIZE);
|
||||
break;
|
||||
case GHOST_kWindowStateEmbedded:
|
||||
SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_CHILD);
|
||||
break;
|
||||
case GHOST_kWindowStateNormal:
|
||||
default:
|
||||
ShowWindow(m_hWnd, SW_HIDE);
|
||||
wp.showCmd = SW_SHOWNORMAL;
|
||||
SetWindowLongPtr(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
|
||||
break;
|
||||
}
|
||||
return ::SetWindowPlacement(m_hWnd, &wp) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setOrder(GHOST_TWindowOrder order)
|
||||
{
|
||||
HWND hWndInsertAfter = order == GHOST_kWindowOrderTop ? HWND_TOP : HWND_BOTTOM;
|
||||
return ::SetWindowPos(m_hWnd, hWndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::swapBuffers()
|
||||
{
|
||||
HDC hDC = m_hDC;
|
||||
|
||||
if (is_crappy_intel_card())
|
||||
hDC = ::wglGetCurrentDC();
|
||||
|
||||
return ::SwapBuffers(hDC) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::activateDrawingContext()
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) {
|
||||
if (m_hDC && m_hGlRc) {
|
||||
success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
else {
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::invalidate()
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
if (m_hWnd) {
|
||||
success = ::InvalidateRect(m_hWnd, 0, FALSE) != 0 ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::initMultisample(PIXELFORMATDESCRIPTOR pfd)
|
||||
{
|
||||
int pixelFormat;
|
||||
bool success = FALSE;
|
||||
UINT numFormats;
|
||||
HDC hDC = GetDC(getHWND());
|
||||
float fAttributes[] = {0, 0};
|
||||
UINT nMaxFormats = 1;
|
||||
|
||||
// The attributes to look for
|
||||
int iAttributes[] = {
|
||||
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
||||
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
||||
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
|
||||
WGL_COLOR_BITS_ARB, pfd.cColorBits,
|
||||
WGL_DEPTH_BITS_ARB, pfd.cDepthBits,
|
||||
WGL_STENCIL_BITS_ARB, pfd.cStencilBits,
|
||||
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
|
||||
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
|
||||
WGL_SAMPLES_ARB, m_multisample,
|
||||
0, 0
|
||||
};
|
||||
|
||||
// Get the function
|
||||
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
||||
|
||||
if (!wglChoosePixelFormatARB)
|
||||
{
|
||||
m_multisampleEnabled = GHOST_kFailure;
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
// iAttributes[17] is the initial multisample. If not valid try to use the closest valid value under it.
|
||||
while (iAttributes[17] > 0) {
|
||||
// See if the format is valid
|
||||
success = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, nMaxFormats, &pixelFormat, &numFormats);
|
||||
GHOST_PRINTF("WGL_SAMPLES_ARB = %i --> success = %i, %i formats\n", iAttributes[17], success, numFormats);
|
||||
|
||||
if (success && numFormats >= 1 && m_multisampleEnabled == GHOST_kFailure) {
|
||||
GHOST_PRINTF("valid pixel format with %i multisamples\n", iAttributes[17]);
|
||||
m_multisampleEnabled = GHOST_kSuccess;
|
||||
m_msPixelFormat = pixelFormat;
|
||||
}
|
||||
iAttributes[17] -= 1;
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
if (m_multisampleEnabled == GHOST_kSuccess) {
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
GHOST_PRINT("no available pixel format\n");
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextType type)
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
switch (type) {
|
||||
case GHOST_kDrawingContextTypeOpenGL:
|
||||
{
|
||||
// If this window has multisample enabled, use the supplied format
|
||||
if (m_multisampleEnabled)
|
||||
{
|
||||
if (SetPixelFormat(m_hDC, m_msPixelFormat, &sPreferredFormat)==FALSE)
|
||||
{
|
||||
success = GHOST_kFailure;
|
||||
break;
|
||||
}
|
||||
|
||||
// Create the context
|
||||
m_hGlRc = ::wglCreateContext(m_hDC);
|
||||
if (m_hGlRc) {
|
||||
if (::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE) {
|
||||
if (s_firsthGLRc) {
|
||||
if (is_crappy_intel_card()) {
|
||||
if (::wglMakeCurrent(NULL, NULL) == TRUE) {
|
||||
::wglDeleteContext(m_hGlRc);
|
||||
m_hGlRc = s_firsthGLRc;
|
||||
}
|
||||
else {
|
||||
::wglDeleteContext(m_hGlRc);
|
||||
m_hGlRc = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
::wglCopyContext(s_firsthGLRc, m_hGlRc, GL_ALL_ATTRIB_BITS);
|
||||
::wglShareLists(s_firsthGLRc, m_hGlRc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
s_firsthGLRc = m_hGlRc;
|
||||
}
|
||||
|
||||
if (m_hGlRc) {
|
||||
success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
|
||||
if (success == GHOST_kFailure) {
|
||||
printf("Failed to get a context....\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_stereoVisual)
|
||||
sPreferredFormat.dwFlags |= PFD_STEREO;
|
||||
|
||||
// Attempt to match device context pixel format to the preferred format
|
||||
int iPixelFormat = EnumPixelFormats(m_hDC);
|
||||
if (iPixelFormat == 0) {
|
||||
success = GHOST_kFailure;
|
||||
break;
|
||||
}
|
||||
if (::SetPixelFormat(m_hDC, iPixelFormat, &sPreferredFormat) == FALSE) {
|
||||
success = GHOST_kFailure;
|
||||
break;
|
||||
}
|
||||
// For debugging only: retrieve the pixel format chosen
|
||||
PIXELFORMATDESCRIPTOR preferredFormat;
|
||||
::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &preferredFormat);
|
||||
|
||||
// Create the context
|
||||
m_hGlRc = ::wglCreateContext(m_hDC);
|
||||
if (m_hGlRc) {
|
||||
if (::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE) {
|
||||
if (s_firsthGLRc) {
|
||||
if (is_crappy_intel_card()) {
|
||||
if (::wglMakeCurrent(NULL, NULL) == TRUE) {
|
||||
::wglDeleteContext(m_hGlRc);
|
||||
m_hGlRc = s_firsthGLRc;
|
||||
}
|
||||
else {
|
||||
::wglDeleteContext(m_hGlRc);
|
||||
m_hGlRc = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
::wglShareLists(s_firsthGLRc, m_hGlRc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
s_firsthGLRc = m_hGlRc;
|
||||
}
|
||||
|
||||
if (m_hGlRc) {
|
||||
success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
|
||||
if (success == GHOST_kFailure) {
|
||||
printf("Failed to get a context....\n");
|
||||
}
|
||||
|
||||
// Attempt to enable multisample
|
||||
if (m_multisample && WGL_ARB_multisample && !m_multisampleEnabled)
|
||||
{
|
||||
success = initMultisample(preferredFormat);
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
||||
// Make sure we don't screw up the context
|
||||
m_drawingContextType = GHOST_kDrawingContextTypeOpenGL;
|
||||
removeDrawingContext();
|
||||
|
||||
// Create a new window
|
||||
GHOST_TWindowState new_state = getState();
|
||||
|
||||
m_nextWindow = new GHOST_WindowWin32((GHOST_SystemWin32*)GHOST_ISystem::getSystem(),
|
||||
m_title,
|
||||
m_left,
|
||||
m_top,
|
||||
m_width,
|
||||
m_height,
|
||||
new_state,
|
||||
type,
|
||||
m_stereo,
|
||||
m_multisample,
|
||||
m_parentWindowHwnd,
|
||||
m_multisampleEnabled,
|
||||
m_msPixelFormat);
|
||||
|
||||
// Return failure so we can trash this window.
|
||||
success = GHOST_kFailure;
|
||||
break;
|
||||
} else {
|
||||
m_multisampleEnabled = GHOST_kSuccess;
|
||||
printf("Multisample failed to initialized\n");
|
||||
success = GHOST_kSuccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kDrawingContextTypeNone:
|
||||
success = GHOST_kSuccess;
|
||||
break;
|
||||
|
||||
default:
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::removeDrawingContext()
|
||||
{
|
||||
GHOST_TSuccess success;
|
||||
switch (m_drawingContextType) {
|
||||
case GHOST_kDrawingContextTypeOpenGL:
|
||||
// we shouldn't remove the drawing context if it's the first OpenGL context
|
||||
// If we do, we get corrupted drawing. See #19997
|
||||
if (m_hGlRc && m_hGlRc!=s_firsthGLRc) {
|
||||
success = ::wglDeleteContext(m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure;
|
||||
m_hGlRc = 0;
|
||||
}
|
||||
else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
break;
|
||||
case GHOST_kDrawingContextTypeNone:
|
||||
success = GHOST_kSuccess;
|
||||
break;
|
||||
default:
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::lostMouseCapture()
|
||||
{
|
||||
if(m_hasMouseCaptured)
|
||||
{ m_hasGrabMouse = false;
|
||||
m_nPressedButtons = 0;
|
||||
m_hasMouseCaptured = false;
|
||||
};
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::registerMouseClickEvent(int press)
|
||||
{
|
||||
|
||||
switch(press)
|
||||
{
|
||||
case 0: m_nPressedButtons++; break;
|
||||
case 1: if(m_nPressedButtons) m_nPressedButtons--; break;
|
||||
case 2: m_hasGrabMouse=true; break;
|
||||
case 3: m_hasGrabMouse=false; break;
|
||||
}
|
||||
|
||||
if(!m_nPressedButtons && !m_hasGrabMouse && m_hasMouseCaptured)
|
||||
{
|
||||
::ReleaseCapture();
|
||||
m_hasMouseCaptured = false;
|
||||
}
|
||||
else if((m_nPressedButtons || m_hasGrabMouse) && !m_hasMouseCaptured)
|
||||
{
|
||||
::SetCapture(m_hWnd);
|
||||
m_hasMouseCaptured = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GHOST_WindowWin32::loadCursor(bool visible, GHOST_TStandardCursor cursor) const
|
||||
{
|
||||
if (!visible) {
|
||||
while (::ShowCursor(FALSE) >= 0);
|
||||
}
|
||||
else {
|
||||
while (::ShowCursor(TRUE) < 0);
|
||||
}
|
||||
|
||||
if (cursor == GHOST_kStandardCursorCustom && m_customCursor) {
|
||||
::SetCursor( m_customCursor );
|
||||
} else {
|
||||
// Convert GHOST cursor to Windows OEM cursor
|
||||
bool success = true;
|
||||
LPCSTR id;
|
||||
switch (cursor) {
|
||||
case GHOST_kStandardCursorDefault: id = IDC_ARROW; break;
|
||||
case GHOST_kStandardCursorRightArrow: id = IDC_ARROW; break;
|
||||
case GHOST_kStandardCursorLeftArrow: id = IDC_ARROW; break;
|
||||
case GHOST_kStandardCursorInfo: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west
|
||||
case GHOST_kStandardCursorDestroy: id = IDC_NO; break; // Slashed circle
|
||||
case GHOST_kStandardCursorHelp: id = IDC_HELP; break; // Arrow and question mark
|
||||
case GHOST_kStandardCursorCycle: id = IDC_NO; break; // Slashed circle
|
||||
case GHOST_kStandardCursorSpray: id = IDC_SIZEALL; break; // Four-pointed arrow pointing north, south, east, and west
|
||||
case GHOST_kStandardCursorWait: id = IDC_WAIT; break; // Hourglass
|
||||
case GHOST_kStandardCursorText: id = IDC_IBEAM; break; // I-beam
|
||||
case GHOST_kStandardCursorCrosshair: id = IDC_CROSS; break; // Crosshair
|
||||
case GHOST_kStandardCursorUpDown: id = IDC_SIZENS; break; // Double-pointed arrow pointing north and south
|
||||
case GHOST_kStandardCursorLeftRight: id = IDC_SIZEWE; break; // Double-pointed arrow pointing west and east
|
||||
case GHOST_kStandardCursorTopSide: id = IDC_UPARROW; break; // Vertical arrow
|
||||
case GHOST_kStandardCursorBottomSide: id = IDC_SIZENS; break;
|
||||
case GHOST_kStandardCursorLeftSide: id = IDC_SIZEWE; break;
|
||||
case GHOST_kStandardCursorTopLeftCorner: id = IDC_SIZENWSE; break;
|
||||
case GHOST_kStandardCursorTopRightCorner: id = IDC_SIZENESW; break;
|
||||
case GHOST_kStandardCursorBottomRightCorner: id = IDC_SIZENWSE; break;
|
||||
case GHOST_kStandardCursorBottomLeftCorner: id = IDC_SIZENESW; break;
|
||||
case GHOST_kStandardCursorPencil: id = IDC_ARROW; break;
|
||||
case GHOST_kStandardCursorCopy: id = IDC_ARROW; break;
|
||||
default:
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
::SetCursor(::LoadCursor(0, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setWindowCursorVisibility(bool visible)
|
||||
{
|
||||
if (::GetForegroundWindow() == m_hWnd) {
|
||||
loadCursor(visible, getCursorShape());
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode)
|
||||
{
|
||||
if(mode != GHOST_kGrabDisable) {
|
||||
if(mode != GHOST_kGrabNormal) {
|
||||
m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
|
||||
setCursorGrabAccum(0, 0);
|
||||
|
||||
if(mode == GHOST_kGrabHide)
|
||||
setWindowCursorVisibility(false);
|
||||
}
|
||||
registerMouseClickEvent(2);
|
||||
}
|
||||
else {
|
||||
if (m_cursorGrab==GHOST_kGrabHide) {
|
||||
m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
|
||||
setWindowCursorVisibility(true);
|
||||
}
|
||||
if(m_cursorGrab != GHOST_kGrabNormal) {
|
||||
/* use to generate a mouse move event, otherwise the last event
|
||||
* blender gets can be outside the screen causing menus not to show
|
||||
* properly unless the user moves the mouse */
|
||||
GHOST_TInt32 pos[2];
|
||||
m_system->getCursorPosition(pos[0], pos[1]);
|
||||
m_system->setCursorPosition(pos[0], pos[1]);
|
||||
}
|
||||
|
||||
/* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
|
||||
setCursorGrabAccum(0, 0);
|
||||
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */
|
||||
registerMouseClickEvent(3);
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cursorShape)
|
||||
{
|
||||
if (m_customCursor) {
|
||||
DestroyCursor(m_customCursor);
|
||||
m_customCursor = NULL;
|
||||
}
|
||||
|
||||
if (::GetForegroundWindow() == m_hWnd) {
|
||||
loadCursor(getCursorVisibility(), cursorShape);
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::processWin32TabletInitEvent()
|
||||
{
|
||||
if (m_wintab) {
|
||||
GHOST_WIN32_WTInfo fpWTInfo = ( GHOST_WIN32_WTInfo ) ::GetProcAddress( m_wintab, "WTInfoA" );
|
||||
|
||||
// let's see if we can initialize tablet here
|
||||
/* check if WinTab available. */
|
||||
if (fpWTInfo) {
|
||||
AXIS Pressure, Orientation[3]; /* The maximum tablet size */
|
||||
|
||||
BOOL pressureSupport = fpWTInfo (WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
||||
if (pressureSupport)
|
||||
m_maxPressure = Pressure.axMax;
|
||||
else
|
||||
m_maxPressure = 0;
|
||||
|
||||
BOOL tiltSupport = fpWTInfo (WTI_DEVICES, DVC_ORIENTATION, &Orientation);
|
||||
if (tiltSupport) {
|
||||
/* does the tablet support azimuth ([0]) and altitude ([1]) */
|
||||
if (Orientation[0].axResolution && Orientation[1].axResolution) {
|
||||
m_maxAzimuth = Orientation[0].axMax;
|
||||
m_maxAltitude = Orientation[1].axMax;
|
||||
}
|
||||
else { /* no so dont do tilt stuff */
|
||||
m_maxAzimuth = m_maxAltitude = 0;
|
||||
}
|
||||
}
|
||||
|
||||
m_tabletData->Active = GHOST_kTabletModeNone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
PACKET pkt;
|
||||
if (m_wintab) {
|
||||
GHOST_WIN32_WTPacket fpWTPacket = ( GHOST_WIN32_WTPacket ) ::GetProcAddress( m_wintab, "WTPacket" );
|
||||
if (fpWTPacket) {
|
||||
if (fpWTPacket((HCTX)lParam, wParam, &pkt)) {
|
||||
if (m_tabletData) {
|
||||
switch (pkt.pkCursor) {
|
||||
case 0: /* first device */
|
||||
case 3: /* second device */
|
||||
m_tabletData->Active = GHOST_kTabletModeNone; /* puck - not yet supported */
|
||||
break;
|
||||
case 1:
|
||||
case 4:
|
||||
m_tabletData->Active = GHOST_kTabletModeStylus; /* stylus */
|
||||
break;
|
||||
case 2:
|
||||
case 5:
|
||||
m_tabletData->Active = GHOST_kTabletModeEraser; /* eraser */
|
||||
break;
|
||||
}
|
||||
if (m_maxPressure > 0) {
|
||||
m_tabletData->Pressure = (float)pkt.pkNormalPressure / (float)m_maxPressure;
|
||||
} else {
|
||||
m_tabletData->Pressure = 1.0f;
|
||||
}
|
||||
|
||||
if ((m_maxAzimuth > 0) && (m_maxAltitude > 0)) {
|
||||
ORIENTATION ort = pkt.pkOrientation;
|
||||
float vecLen;
|
||||
float altRad, azmRad; /* in radians */
|
||||
|
||||
/*
|
||||
from the wintab spec:
|
||||
orAzimuth Specifies the clockwise rotation of the
|
||||
cursor about the z axis through a full circular range.
|
||||
|
||||
orAltitude Specifies the angle with the x-y plane
|
||||
through a signed, semicircular range. Positive values
|
||||
specify an angle upward toward the positive z axis;
|
||||
negative values specify an angle downward toward the negative z axis.
|
||||
|
||||
wintab.h defines .orAltitude as a UINT but documents .orAltitude
|
||||
as positive for upward angles and negative for downward angles.
|
||||
WACOM uses negative altitude values to show that the pen is inverted;
|
||||
therefore we cast .orAltitude as an (int) and then use the absolute value.
|
||||
*/
|
||||
|
||||
/* convert raw fixed point data to radians */
|
||||
altRad = (float)((fabs((float)ort.orAltitude)/(float)m_maxAltitude) * M_PI/2.0);
|
||||
azmRad = (float)(((float)ort.orAzimuth/(float)m_maxAzimuth) * M_PI*2.0);
|
||||
|
||||
/* find length of the stylus' projected vector on the XY plane */
|
||||
vecLen = cos(altRad);
|
||||
|
||||
/* from there calculate X and Y components based on azimuth */
|
||||
m_tabletData->Xtilt = sin(azmRad) * vecLen;
|
||||
m_tabletData->Ytilt = (float)(sin(M_PI/2.0 - azmRad) * vecLen);
|
||||
|
||||
} else {
|
||||
m_tabletData->Xtilt = 0.0f;
|
||||
m_tabletData->Ytilt = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
/** 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_WindowWin32::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);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask, int sizeX, int sizeY, int hotX, int hotY,
|
||||
int fg_color, int bg_color)
|
||||
{
|
||||
GHOST_TUns32 andData[32];
|
||||
GHOST_TUns32 xorData[32];
|
||||
GHOST_TUns32 fullBitRow, fullMaskRow;
|
||||
int x, y, cols;
|
||||
|
||||
cols=sizeX/8; /* Num of whole bytes per row (width of bm/mask) */
|
||||
if (sizeX%8) cols++;
|
||||
|
||||
if (m_customCursor) {
|
||||
DestroyCursor(m_customCursor);
|
||||
m_customCursor = NULL;
|
||||
}
|
||||
|
||||
memset(&andData, 0xFF, sizeof(andData));
|
||||
memset(&xorData, 0, sizeof(xorData));
|
||||
|
||||
for (y=0; y<sizeY; y++) {
|
||||
fullBitRow=0;
|
||||
fullMaskRow=0;
|
||||
for (x=cols-1; x>=0; x--){
|
||||
fullBitRow<<=8;
|
||||
fullMaskRow<<=8;
|
||||
fullBitRow |= uns8ReverseBits(bitmap[cols*y + x]);
|
||||
fullMaskRow |= uns8ReverseBits( mask[cols*y + x]);
|
||||
}
|
||||
xorData[y]= fullBitRow & fullMaskRow;
|
||||
andData[y]= ~fullMaskRow;
|
||||
}
|
||||
|
||||
m_customCursor = ::CreateCursor(::GetModuleHandle(0), hotX, hotY, 32, 32, andData, xorData);
|
||||
if (!m_customCursor) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
if (::GetForegroundWindow() == m_hWnd) {
|
||||
loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom);
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::setProgressBar(float progress)
|
||||
{
|
||||
/*SetProgressValue sets state to TBPF_NORMAL automaticly*/
|
||||
if(m_Bar && S_OK == m_Bar->SetProgressValue(m_hWnd,10000*progress,10000))
|
||||
return GHOST_kSuccess;
|
||||
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowWin32::endProgressBar()
|
||||
{
|
||||
if(m_Bar && S_OK == m_Bar->SetProgressState(m_hWnd,TBPF_NOPROGRESS))
|
||||
return GHOST_kSuccess;
|
||||
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
/* Ron Fosner's code for weighting pixel formats and forcing software.
|
||||
See http://www.opengl.org/resources/faq/technical/weight.cpp */
|
||||
|
||||
static int WeightPixelFormat(PIXELFORMATDESCRIPTOR& pfd) {
|
||||
int weight = 0;
|
||||
|
||||
/* assume desktop color depth is 32 bits per pixel */
|
||||
|
||||
/* cull unusable pixel formats */
|
||||
/* if no formats can be found, can we determine why it was rejected? */
|
||||
if( !(pfd.dwFlags & PFD_SUPPORT_OPENGL) ||
|
||||
!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
|
||||
!(pfd.dwFlags & PFD_DOUBLEBUFFER) || /* Blender _needs_ this */
|
||||
( pfd.cDepthBits <= 8 ) ||
|
||||
!(pfd.iPixelType == PFD_TYPE_RGBA))
|
||||
return 0;
|
||||
|
||||
weight = 1; /* it's usable */
|
||||
|
||||
/* the bigger the depth buffer the better */
|
||||
/* give no weight to a 16-bit depth buffer, because those are crap */
|
||||
weight += pfd.cDepthBits - 16;
|
||||
|
||||
weight += pfd.cColorBits - 8;
|
||||
|
||||
/* want swap copy capability -- it matters a lot */
|
||||
if(pfd.dwFlags & PFD_SWAP_COPY) weight += 16;
|
||||
|
||||
/* but if it's a generic (not accelerated) view, it's really bad */
|
||||
if(pfd.dwFlags & PFD_GENERIC_FORMAT) weight /= 10;
|
||||
|
||||
return weight;
|
||||
}
|
||||
|
||||
/* A modification of Ron Fosner's replacement for ChoosePixelFormat */
|
||||
/* returns 0 on error, else returns the pixel format number to be used */
|
||||
static int EnumPixelFormats(HDC hdc) {
|
||||
int iPixelFormat;
|
||||
int i, n, w, weight = 0;
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
|
||||
/* we need a device context to do anything */
|
||||
if(!hdc) return 0;
|
||||
|
||||
iPixelFormat = 1; /* careful! PFD numbers are 1 based, not zero based */
|
||||
|
||||
/* obtain detailed information about
|
||||
the device context's first pixel format */
|
||||
n = 1+::DescribePixelFormat(hdc, iPixelFormat,
|
||||
sizeof(PIXELFORMATDESCRIPTOR), &pfd);
|
||||
|
||||
/* choose a pixel format using the useless Windows function in case
|
||||
we come up empty handed */
|
||||
iPixelFormat = ::ChoosePixelFormat( hdc, &sPreferredFormat );
|
||||
|
||||
if(!iPixelFormat) return 0; /* couldn't find one to use */
|
||||
|
||||
for(i=1; i<=n; i++) { /* not the idiom, but it's right */
|
||||
::DescribePixelFormat( hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd );
|
||||
w = WeightPixelFormat(pfd);
|
||||
// be strict on stereo
|
||||
if (!((sPreferredFormat.dwFlags ^ pfd.dwFlags) & PFD_STEREO)) {
|
||||
if(w > weight) {
|
||||
weight = w;
|
||||
iPixelFormat = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (weight == 0) {
|
||||
// we could find the correct stereo setting, just find any suitable format
|
||||
for(i=1; i<=n; i++) { /* not the idiom, but it's right */
|
||||
::DescribePixelFormat( hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd );
|
||||
w = WeightPixelFormat(pfd);
|
||||
if(w > weight) {
|
||||
weight = w;
|
||||
iPixelFormat = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return iPixelFormat;
|
||||
}
|
||||
|
||||
|
||||
400
intern/ghost/intern/GHOST_WindowWin32.h
Normal file
400
intern/ghost/intern/GHOST_WindowWin32.h
Normal file
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_WindowWin32.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_WindowWin32 class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_WINDOW_WIN32_H_
|
||||
#define _GHOST_WINDOW_WIN32_H_
|
||||
|
||||
#ifndef WIN32
|
||||
#error WIN32 only!
|
||||
#endif // WIN32
|
||||
|
||||
#include "GHOST_Window.h"
|
||||
|
||||
/* MinGW needs it */
|
||||
#ifdef FREE_WINDOWS
|
||||
#ifdef WINVER
|
||||
#undef WINVER
|
||||
#endif
|
||||
#define WINVER 0x0501
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include "GHOST_TaskbarWin32.h"
|
||||
|
||||
|
||||
#include <wintab.h>
|
||||
#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
|
||||
#define PACKETMODE PK_BUTTONS
|
||||
#include <pktdef.h>
|
||||
|
||||
class GHOST_SystemWin32;
|
||||
class GHOST_DropTargetWin32;
|
||||
|
||||
// typedefs for WinTab functions to allow dynamic loading
|
||||
typedef UINT (API * GHOST_WIN32_WTInfo) ( UINT, UINT, LPVOID );
|
||||
typedef HCTX (API * GHOST_WIN32_WTOpen) (HWND, LPLOGCONTEXTA, BOOL);
|
||||
typedef BOOL (API * GHOST_WIN32_WTClose) (HCTX);
|
||||
typedef BOOL (API * GHOST_WIN32_WTPacket) (HCTX, UINT, LPVOID);
|
||||
|
||||
/**
|
||||
* GHOST window on M$ Windows OSs.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 10, 2001
|
||||
*/
|
||||
class GHOST_WindowWin32 : 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.
|
||||
* @param numOfAASamples Number of samples used for AA (zero if no AA)
|
||||
*/
|
||||
GHOST_WindowWin32(
|
||||
GHOST_SystemWin32 * system,
|
||||
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,
|
||||
const GHOST_TUns16 numOfAASamples = 0,
|
||||
GHOST_TEmbedderWindowID parentWindowHwnd=0,
|
||||
GHOST_TSuccess msEnabled = GHOST_kFailure,
|
||||
int msPixelFormat = 0
|
||||
);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* Closes the window and disposes resources allocated.
|
||||
*/
|
||||
virtual ~GHOST_WindowWin32();
|
||||
|
||||
/**
|
||||
* Returns the window to replace this one if it's getting replaced
|
||||
* @return The window replacing this one.
|
||||
*/
|
||||
|
||||
GHOST_Window *getNextWindow();
|
||||
|
||||
/**
|
||||
* Returns indication as to whether the window is valid.
|
||||
* @return The validity of the window.
|
||||
*/
|
||||
virtual bool getValid() const;
|
||||
|
||||
/**
|
||||
* Access to the handle of the window.
|
||||
* @return The handle of the window.
|
||||
*/
|
||||
virtual HWND getHWND() 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 Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess swapBuffers();
|
||||
|
||||
/**
|
||||
* Activates the drawing context of this window.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess activateDrawingContext();
|
||||
|
||||
/**
|
||||
* Invalidates the contents of this window.
|
||||
*/
|
||||
virtual GHOST_TSuccess invalidate();
|
||||
|
||||
/**
|
||||
* Sets the progress bar value displayed in the window/application icon
|
||||
* @param progress The progress %
|
||||
*/
|
||||
virtual GHOST_TSuccess setProgressBar(float progress);
|
||||
|
||||
/**
|
||||
* Hides the progress bar in the icon
|
||||
*/
|
||||
virtual GHOST_TSuccess endProgressBar();
|
||||
|
||||
/**
|
||||
* Returns the name of the window class.
|
||||
* @return The name of the window class.
|
||||
*/
|
||||
static LPCSTR getWindowClassName() { return s_windowClassName; }
|
||||
|
||||
/**
|
||||
* Register a mouse click event (should be called
|
||||
* for any real button press, controls mouse
|
||||
* capturing).
|
||||
*
|
||||
* @param press
|
||||
* 0 - mouse pressed
|
||||
* 1 - mouse released
|
||||
* 2 - operator grab
|
||||
* 3 - operator ungrab
|
||||
*/
|
||||
void registerMouseClickEvent(int press);
|
||||
|
||||
/**
|
||||
* Inform the window that it has lost mouse capture,
|
||||
* called in response to native window system messages.
|
||||
*/
|
||||
void lostMouseCapture();
|
||||
|
||||
/**
|
||||
* Loads the windows equivalent of a standard GHOST cursor.
|
||||
* @param visible Flag for cursor visibility.
|
||||
* @param cursorShape The cursor shape.
|
||||
*/
|
||||
void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const;
|
||||
|
||||
const GHOST_TabletData* GetTabletData()
|
||||
{ return m_tabletData; }
|
||||
|
||||
void processWin32TabletInitEvent();
|
||||
void processWin32TabletEvent(WPARAM wParam, LPARAM lParam);
|
||||
|
||||
protected:
|
||||
GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd);
|
||||
|
||||
/**
|
||||
* Tries to install a rendering context in this window.
|
||||
* @param type The type of rendering context installed.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type);
|
||||
|
||||
/**
|
||||
* Removes the current drawing context.
|
||||
* @return Indication of success.
|
||||
*/
|
||||
virtual GHOST_TSuccess removeDrawingContext();
|
||||
|
||||
/**
|
||||
* Sets the cursor visibility on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
|
||||
|
||||
/**
|
||||
* Sets the cursor grab on the window using native window system calls.
|
||||
* Using registerMouseClickEvent.
|
||||
* @param mode GHOST_TGrabCursorMode.
|
||||
*/
|
||||
virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode);
|
||||
|
||||
/**
|
||||
* 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[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY);
|
||||
|
||||
virtual GHOST_TSuccess setWindowCustomCursorShape(
|
||||
GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask,
|
||||
int sizex,
|
||||
int sizey,
|
||||
int hotX,
|
||||
int hotY,
|
||||
int fg_color,
|
||||
int bg_color
|
||||
);
|
||||
|
||||
/** Pointer to system */
|
||||
GHOST_SystemWin32 * m_system;
|
||||
/** Pointer to COM IDropTarget implementor */
|
||||
GHOST_DropTargetWin32 * m_dropTarget;
|
||||
/** Window handle. */
|
||||
HWND m_hWnd;
|
||||
/** Device context handle. */
|
||||
HDC m_hDC;
|
||||
/** OpenGL rendering context. */
|
||||
HGLRC m_hGlRc;
|
||||
/** The first created OpenGL context (for sharing display lists) */
|
||||
static HGLRC s_firsthGLRc;
|
||||
/** The first created device context handle. */
|
||||
static HDC s_firstHDC;
|
||||
/** Flag for if window has captured the mouse */
|
||||
bool m_hasMouseCaptured;
|
||||
/** Flag if an operator grabs the mouse with WM_cursor_grab/ungrab()
|
||||
* Multiple grabs must be realesed with a single ungrab*/
|
||||
bool m_hasGrabMouse;
|
||||
/** Count of number of pressed buttons */
|
||||
int m_nPressedButtons;
|
||||
/** HCURSOR structure of the custom cursor */
|
||||
HCURSOR m_customCursor;
|
||||
|
||||
/** ITaskbarList3 structure for progress bar*/
|
||||
ITaskbarList3 * m_Bar;
|
||||
|
||||
static LPCSTR s_windowClassName;
|
||||
static const int s_maxTitleLength;
|
||||
|
||||
/** WinTab dll handle */
|
||||
HMODULE m_wintab;
|
||||
|
||||
/** Tablet data for GHOST */
|
||||
GHOST_TabletData* m_tabletData;
|
||||
|
||||
/** Stores the Tablet context if detected Tablet features using WinTab.dll */
|
||||
HCTX m_tablet;
|
||||
LONG m_maxPressure;
|
||||
LONG m_maxAzimuth, m_maxAltitude;
|
||||
|
||||
/** Preferred number of samples */
|
||||
GHOST_TUns16 m_multisample;
|
||||
|
||||
/** Check if multisample is supported */
|
||||
GHOST_TSuccess m_multisampleEnabled;
|
||||
|
||||
/** The pixelFormat to use for multisample */
|
||||
int m_msPixelFormat;
|
||||
|
||||
/** We need to following to recreate the window */
|
||||
const STR_String& m_title;
|
||||
GHOST_TInt32 m_left;
|
||||
GHOST_TInt32 m_top;
|
||||
GHOST_TUns32 m_width;
|
||||
GHOST_TUns32 m_height;
|
||||
GHOST_TWindowState m_normal_state;
|
||||
bool m_stereo;
|
||||
|
||||
/** The GHOST_System passes this to wm if this window is being replaced */
|
||||
GHOST_Window *m_nextWindow;
|
||||
|
||||
/** Hwnd to parent window */
|
||||
GHOST_TEmbedderWindowID m_parentWindowHwnd;
|
||||
};
|
||||
|
||||
#endif // _GHOST_WINDOW_WIN32_H_
|
||||
1598
intern/ghost/intern/GHOST_WindowX11.cpp
Normal file
1598
intern/ghost/intern/GHOST_WindowX11.cpp
Normal file
@@ -0,0 +1,1598 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_WindowX11.cpp
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
|
||||
#include "GHOST_WindowX11.h"
|
||||
#include "GHOST_SystemX11.h"
|
||||
#include "STR_String.h"
|
||||
#include "GHOST_Debug.h"
|
||||
|
||||
// For standard X11 cursors
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__) || defined (_AIX)
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
// For obscure full screen mode stuuf
|
||||
// lifted verbatim from blut.
|
||||
|
||||
typedef struct {
|
||||
long flags;
|
||||
long functions;
|
||||
long decorations;
|
||||
long input_mode;
|
||||
} MotifWmHints;
|
||||
|
||||
#define MWM_HINTS_DECORATIONS (1L << 1)
|
||||
|
||||
|
||||
// #define GHOST_X11_GRAB
|
||||
|
||||
/*
|
||||
* A Client can't change the window property, that is
|
||||
* the work of the window manager. In case, we send
|
||||
* a ClientMessage to the RootWindow with the property
|
||||
* and the Action (WM-spec define this):
|
||||
*/
|
||||
#define _NET_WM_STATE_REMOVE 0
|
||||
#define _NET_WM_STATE_ADD 1
|
||||
#define _NET_WM_STATE_TOGGLE 2
|
||||
|
||||
/*
|
||||
import bpy
|
||||
I = bpy.data.images['blender.png'] # the 48x48 icon
|
||||
|
||||
# Write to a file that can be
|
||||
# used within static unsigned char BLENDER_ICON_48x48x24[] = {...}
|
||||
f = open('/myicon.txt', 'w')
|
||||
for j in xrange(48):
|
||||
for k in xrange(48):
|
||||
v = I.getPixelI(j,47-k)
|
||||
v.pop()
|
||||
for p in v:
|
||||
f.write(str(hex(p))+',')
|
||||
|
||||
f.write('\n')
|
||||
*/
|
||||
|
||||
// See the python script above to regenerate the 48x48 icon within blender
|
||||
#define BLENDER_ICON_WIDTH 48
|
||||
#define BLENDER_ICON_HEIGHT 48
|
||||
static unsigned char BLENDER_ICON_48x48x24[] = {
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x4f,0x2a,0xd,0xa7,0x5b,0x1f,0xb8,0x66,0x22,0x6c,0x3b,0x14,0x5,0x3,0x1,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x6f,0x3a,0x13,0xea,0x7f,0x2c,0xee,0x7e,0x2b,0xee,0x7e,0x2b,0xef,0x85,0x2e,0x5f,0x35,0x12,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x43,0x22,0xb,0xed,0x7f,0x2c,0xed,0x7c,0x2b,0xee,0x7f,0x2c,0xee,0x80,0x2c,0xee,0x80,0x2c,0xa8,0x5f,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x2e,0x16,0x6,0xd0,0x6f,0x26,0xed,0x7b,0x2a,0xed,0x7d,0x2b,0xee,0x7f,0x2c,0xee,0x80,0x2c,0xee,0x82,0x2d,0x9a,0x57,0x1d,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x17,0xb,0x4,0xb9,0x60,0x21,0xed,0x7a,0x2a,0xed,0x7b,0x2a,0xed,0x7e,0x2b,0xee,0x7f,0x2c,0xee,0x7f,0x2c,0xee,0x86,0x2e,0x4e,0x2b,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x1,0x0,0x0,0x96,0x4d,0x19,0xee,0x7a,0x2a,0xed,0x79,0x2a,0xed,0x7c,0x2b,0xed,0x7e,0x2b,0xed,0x7e,0x2b,0xef,0x83,0x2d,0x98,0x55,0x1c,0x3,0x1,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x20,0xf,0x5,0x4b,0x27,0xe,0x21,0x11,0x5,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x67,0x34,0x11,0xed,0x7b,0x2a,0xec,0x79,0x29,0xed,0x7b,0x2a,0xed,0x7c,0x2b,0xed,0x7d,0x2b,0xee,0x7f,0x2c,0xbb,0x69,0x24,0x11,0x9,0x3,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x38,0x1c,0x9,0xc9,0x6d,0x2c,0xf1,0x86,0x36,0xd7,0x79,0x2a,0x22,0x12,0x5,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x3b,0x1d,0x9,0xe0,0x74,0x27,0xed,0x7a,0x2a,0xed,0x7c,0x2a,0xed,0x7d,0x2b,0xed,0x7d,0x2b,0xed,0x7d,0x2b,0xdc,0x7a,0x2a,0x1e,0xf,0x5,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xa6,0x56,0x23,0xee,0x83,0x3b,0xed,0x7d,0x2c,0xf0,0x85,0x2e,0x75,0x43,0x17,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x25,0x12,0x5,0xc9,0x68,0x24,0xed,0x7b,0x2a,0xed,0x7d,0x2b,0xed,0x7e,0x2b,0xee,0x7e,0x2c,0xed,0x7d,0x2b,0xe3,0x7d,0x2b,0x3b,0x1f,0xa,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x1c,0xd,0x4,0xd9,0x74,0x35,0xee,0x83,0x3a,0xee,0x7f,0x2b,0xf0,0x86,0x2e,0x83,0x4d,0x1a,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xa,0x5,0x1,0xa1,0x54,0x1c,0xee,0x7e,0x2c,0xed,0x7e,0x2c,0xed,0x7f,0x2c,0xed,0x80,0x2c,0xed,0x7f,0x2b,0xec,0x81,0x2d,0x60,0x33,0x11,0x1,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x24,0x11,0x5,0xe0,0x7a,0x38,0xee,0x84,0x3a,0xee,0x82,0x2c,0xf0,0x88,0x2f,0x82,0x4d,0x1a,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x6f,0x39,0x13,0xef,0x82,0x30,0xed,0x82,0x2f,0xee,0x82,0x2e,0xee,0x82,0x2d,0xee,0x81,0x2c,0xf0,0x83,0x2d,0x88,0x49,0x18,0x3,0x2,0x1,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x24,0x11,0x5,0xe0,0x7c,0x3a,0xee,0x86,0x3b,0xee,0x84,0x2d,0xf1,0x8b,0x30,0x82,0x4d,0x1a,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0x54,0x2b,0xf,0xe9,0x80,0x30,0xee,0x87,0x33,0xef,0x88,0x32,0xef,0x88,0x30,0xee,0x85,0x2f,0xef,0x83,0x2e,0xae,0x5f,0x20,0x4,0x2,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x24,0x11,0x5,0xe0,0x7e,0x3d,0xef,0x8a,0x3d,0xef,0x88,0x2e,0xf1,0x8d,0x31,0x81,0x4d,0x1a,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0x29,0x15,0x7,0xd2,0x74,0x2d,0xf0,0x8b,0x36,0xf0,0x8d,0x35,0xef,0x8d,0x35,0xef,0x8b,0x33,0xef,0x88,0x30,0xc4,0x6d,0x26,0x18,0xc,0x4,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x24,0x11,0x5,0xe1,0x80,0x3f,0xf0,0x8d,0x3f,0xef,0x8a,0x2f,0xf1,0x8f,0x32,0x81,0x4e,0x1a,0x0,0x0,0x0,0x0,0x0,0x0,0x9,0x3,0x0,0xb1,0x61,0x26,0xf1,0x8e,0x3a,0xf1,0x90,0x3a,0xf0,0x90,0x38,0xf0,0x90,0x36,0xef,0x8e,0x35,0xd3,0x7a,0x2c,0x22,0x11,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x24,0x12,0x5,0xe1,0x83,0x42,0xf0,0x90,0x42,0xf0,0x8d,0x30,0xf2,0x92,0x33,0x80,0x4e,0x1b,0x0,0x0,0x0,0x3,0x2,0x0,0x81,0x45,0x1b,0xf1,0x90,0x3e,0xf1,0x94,0x3d,0xf1,0x95,0x3c,0xf0,0x94,0x3b,0xf0,0x92,0x39,0xf0,0x90,0x35,0xd0,0x7b,0x2b,0xc2,0x6e,0x26,0xbe,0x6c,0x25,0x94,0x54,0x1c,0x5b,0x33,0x11,0x1a,0xe,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x25,0x14,0x6,0xe2,0x86,0x44,0xf1,0x94,0x45,0xf0,0x90,0x31,0xf2,0x94,0x33,0x80,0x4e,0x1b,0x0,0x0,0x0,0x60,0x34,0x14,0xed,0x8c,0x3e,0xf0,0x96,0x42,0xf1,0x97,0x40,0xf1,0x95,0x3f,0xf0,0x91,0x39,0xef,0x8e,0x33,0xef,0x8d,0x31,0xf0,0x8d,0x31,0xef,0x8c,0x30,0xef,0x8c,0x30,0xf0,0x8d,0x31,0xf1,0x8e,0x31,0xe1,0x85,0x2e,0x92,0x55,0x1d,0x25,0x14,0x7,0x1,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x26,0x14,0x6,0xe2,0x89,0x46,0xf2,0x97,0x47,0xf1,0x92,0x32,0xf2,0x96,0x34,0x80,0x4e,0x1a,0x32,0x1a,0xa,0xe3,0x87,0x3d,0xf1,0x97,0x45,0xf1,0x98,0x44,0xf1,0x95,0x41,0xf0,0x90,0x39,0xef,0x8d,0x30,0xef,0x8f,0x31,0xf0,0x90,0x32,0xf0,0x92,0x33,0xf1,0x93,0x33,0xf1,0x94,0x34,0xf1,0x94,0x34,0xf0,0x93,0x34,0xf0,0x91,0x32,0xf1,0x91,0x33,0xe2,0x8a,0x30,0x6b,0x3f,0x15,0x1,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x26,0x14,0x6,0xe3,0x8b,0x49,0xf2,0x9a,0x49,0xf1,0x93,0x32,0xf2,0x98,0x35,0x8f,0x57,0x1d,0xcf,0x7c,0x38,0xf2,0x99,0x48,0xf1,0x98,0x47,0xf1,0x96,0x44,0xf0,0x90,0x39,0xef,0x8d,0x31,0xf0,0x90,0x31,0xf0,0x92,0x33,0xf1,0x94,0x33,0xf1,0x96,0x35,0xf1,0x98,0x35,0xf1,0x9a,0x36,0xf1,0x9c,0x37,0xf2,0x9d,0x37,0xf2,0x9c,0x37,0xf2,0x99,0x36,0xf0,0x94,0x34,0xf3,0x97,0x35,0x9f,0x60,0x21,0x13,0xb,0x3,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x26,0x14,0x6,0xe3,0x8d,0x4b,0xf2,0x9b,0x4c,0xf1,0x93,0x32,0xf1,0x97,0x35,0xea,0x98,0x43,0xf2,0x9d,0x4d,0xf1,0x9a,0x4b,0xf1,0x99,0x49,0xf0,0x93,0x3d,0xf0,0x8d,0x30,0xf0,0x90,0x32,0xf0,0x92,0x32,0xf0,0x94,0x34,0xf1,0x96,0x34,0xf1,0x98,0x36,0xf1,0x9a,0x36,0xf2,0x9c,0x38,0xf2,0x9f,0x38,0xf2,0xa2,0x39,0xf3,0xa2,0x39,0xf3,0xa2,0x39,0xf2,0x9f,0x38,0xf1,0x99,0x35,0xf2,0x97,0x35,0xba,0x74,0x29,0x13,0xb,0x4,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x26,0x14,0x6,0xe4,0x8e,0x4d,0xf2,0x9d,0x4e,0xf1,0x93,0x32,0xf2,0x9d,0x3f,0xf3,0xa4,0x54,0xf2,0x9d,0x50,0xf1,0x9b,0x4d,0xf2,0x98,0x46,0xef,0x8d,0x31,0xf0,0x8f,0x31,0xf0,0x91,0x32,0xf0,0x93,0x32,0xf1,0x94,0x32,0xf1,0x95,0x32,0xf1,0x98,0x34,0xf1,0x9b,0x36,0xf2,0x9e,0x38,0xf2,0xa1,0x39,0xf2,0xa4,0x3a,0xf3,0xa6,0x3b,0xf4,0xa8,0x3c,0xf3,0xa7,0x3c,0xf3,0xa4,0x3a,0xf2,0x9c,0x37,0xf2,0x99,0x36,0xa9,0x69,0x25,0x2,0x1,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x26,0x14,0x6,0xe4,0x90,0x50,0xf2,0x9e,0x51,0xf1,0x95,0x35,0xf4,0xa6,0x54,0xf3,0xa2,0x55,0xf2,0x9e,0x51,0xf2,0x9c,0x4e,0xf0,0x8f,0x35,0xf0,0x8e,0x31,0xf0,0x90,0x32,0xf3,0xa5,0x56,0xf7,0xc4,0x8e,0xfa,0xd8,0xb6,0xfb,0xdf,0xc2,0xfa,0xd8,0xb2,0xf7,0xc4,0x89,0xf4,0xae,0x59,0xf2,0xa1,0x38,0xf3,0xa5,0x3b,0xf4,0xa8,0x3c,0xf4,0xab,0x3d,0xf4,0xac,0x3e,0xf4,0xab,0x3d,0xf3,0xa7,0x3b,0xf2,0x9e,0x38,0xf4,0x9e,0x38,0x6f,0x45,0x17,0x1,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x19,0xc,0x5,0x63,0x36,0x18,0x3f,0x20,0x9,0x2,0x1,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x26,0x14,0x6,0xe4,0x91,0x52,0xf3,0xa2,0x55,0xf2,0x9d,0x43,0xf4,0xa7,0x5b,0xf3,0xa2,0x57,0xf3,0xa0,0x55,0xf1,0x97,0x43,0xf0,0x8d,0x30,0xf2,0x9d,0x4c,0xfa,0xda,0xbc,0xfe,0xfb,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfb,0xf6,0xfa,0xdc,0xb5,0xf4,0xae,0x4e,0xf4,0xa9,0x3c,0xf4,0xac,0x3d,0xf4,0xae,0x3f,0xf4,0xaf,0x3f,0xf4,0xad,0x3f,0xf3,0xa8,0x3d,0xf2,0x9d,0x38,0xe2,0x94,0x34,0x23,0x14,0x6,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x11,0x8,0x3,0x9e,0x62,0x39,0xf2,0x91,0x4e,0xe7,0x79,0x29,0x48,0x25,0xc,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0x27,0x13,0x6,0xe5,0x93,0x54,0xf3,0xa7,0x59,0xf4,0xa6,0x56,0xf4,0xa7,0x5d,0xf3,0xa4,0x59,0xf3,0xa2,0x57,0xf1,0x90,0x36,0xf4,0xa7,0x5d,0xfe,0xf4,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xf2,0xe3,0xf6,0xb8,0x5f,0xf4,0xac,0x3e,0xf4,0xaf,0x3f,0xf4,0xb1,0x40,0xf4,0xb2,0x40,0xf5,0xaf,0x3f,0xf3,0xa6,0x3c,0xf3,0x9f,0x38,0x90,0x5d,0x21,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x3d,0x1f,0xf,0xed,0x9c,0x6a,0xef,0x8b,0x4a,0xec,0x78,0x29,0xe4,0x79,0x2a,0x29,0x15,0x7,0x0,0x0,0x0,0xff,0x0,0xff,0x28,0x14,0x6,0xe6,0x97,0x57,0xf5,0xad,0x63,0xf5,0xac,0x62,0xf4,0xa8,0x5f,0xf4,0xa6,0x5c,0xf3,0xa0,0x53,0xf4,0xa9,0x64,0xfe,0xf8,0xf4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xff,0xf2,0xf7,0xfa,0xed,0xf4,0xf8,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xf7,0xed,0xf5,0xb5,0x53,0xf5,0xb0,0x3f,0xf5,0xb3,0x41,0xf5,0xb4,0x42,0xf5,0xb3,0x41,0xf4,0xad,0x3f,0xf3,0xa1,0x39,0xe4,0x98,0x37,0x1d,0x11,0x5,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x43,0x23,0x10,0xf2,0xa1,0x70,0xf1,0x99,0x61,0xec,0x78,0x2a,0xed,0x7b,0x2a,0xc4,0x69,0x23,0x15,0xa,0x3,0x0,0x0,0x0,0x1d,0xf,0x5,0xe7,0x9b,0x5b,0xf5,0xb1,0x68,0xf5,0xad,0x65,0xf4,0xaa,0x62,0xf4,0xa8,0x5f,0xf3,0xa4,0x59,0xfd,0xec,0xde,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xfd,0xfe,0xc3,0xda,0xe9,0x5c,0x9a,0xc5,0x2a,0x7b,0xb4,0x17,0x6f,0xae,0x36,0x81,0xb8,0x91,0xbb,0xd9,0xf0,0xf6,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xe7,0xc7,0xf5,0xb2,0x43,0xf6,0xb3,0x41,0xf5,0xb5,0x43,0xf5,0xb6,0x43,0xf5,0xb3,0x42,0xf4,0xa8,0x3c,0xf4,0xa2,0x3a,0x66,0x41,0x17,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x22,0x10,0x7,0xd6,0x88,0x5b,0xf2,0xa5,0x76,0xee,0x84,0x3f,0xed,0x7a,0x2a,0xee,0x80,0x2c,0xa5,0x59,0x1e,0x7,0x3,0x1,0x19,0xd,0x4,0xe7,0x9e,0x5e,0xf6,0xb2,0x6b,0xf5,0xae,0x67,0xf5,0xac,0x65,0xf4,0xa9,0x61,0xf8,0xcc,0xa1,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xfe,0xfe,0x97,0xbf,0xdb,0x33,0x83,0xbb,0x24,0x7e,0xb9,0x3,0x6a,0xae,0x0,0x66,0xab,0x0,0x64,0xa9,0x1,0x63,0xa9,0x3c,0x87,0xbd,0xee,0xf5,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xf8,0xc7,0x76,0xf6,0xb4,0x41,0xf5,0xb7,0x43,0xf6,0xb8,0x44,0xf6,0xb6,0x43,0xf5,0xae,0x3f,0xf3,0xa2,0x3a,0xac,0x71,0x29,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x52,0x2c,0x16,0xf0,0xa1,0x71,0xf2,0xa2,0x6f,0xed,0x7e,0x32,0xed,0x7e,0x2b,0xef,0x82,0x2d,0x8a,0x49,0x18,0x1b,0xe,0x4,0xe7,0xa2,0x61,0xf6,0xb3,0x6e,0xf6,0xb0,0x6a,0xf5,0xae,0x67,0xf5,0xab,0x64,0xfe,0xf4,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xb4,0xd1,0xe5,0x3e,0x8d,0xc3,0x37,0x8e,0xc5,0x16,0x7a,0xb9,0x0,0x6b,0xaf,0x0,0x68,0xac,0x0,0x65,0xaa,0x0,0x65,0xab,0x0,0x66,0xac,0x4d,0x93,0xc4,0xf8,0xfb,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xe7,0xc5,0xf6,0xb3,0x40,0xf6,0xb7,0x43,0xf6,0xb9,0x44,0xf6,0xb8,0x45,0xf5,0xb2,0x41,0xf3,0xa5,0x3b,0xe2,0x98,0x37,0x3,0x1,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x86,0x4e,0x2e,0xf3,0xa6,0x77,0xf1,0x9e,0x66,0xed,0x7e,0x2d,0xee,0x82,0x2c,0xf0,0x85,0x2d,0x7e,0x47,0x17,0xe8,0xa6,0x64,0xf6,0xb5,0x70,0xf6,0xb2,0x6d,0xf5,0xb0,0x6a,0xf7,0xbb,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xf9,0xfb,0xfd,0x5b,0x9c,0xca,0x42,0x96,0xcb,0x3c,0x93,0xc9,0x9,0x73,0xb6,0x0,0x6b,0xb0,0x0,0x69,0xad,0x0,0x66,0xab,0x0,0x66,0xab,0x0,0x67,0xad,0x4,0x6a,0xaf,0xbb,0xd7,0xe9,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xf8,0xee,0xf6,0xb9,0x4f,0xf6,0xb7,0x44,0xf6,0xba,0x45,0xf6,0xba,0x45,0xf5,0xb5,0x43,0xf4,0xa8,0x3d,0xf5,0xa7,0x3d,0x1b,0xf,0x4,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x11,0x8,0x3,0xb0,0x6d,0x45,0xf4,0xaa,0x7b,0xf1,0x9a,0x5b,0xee,0x82,0x2d,0xef,0x86,0x2e,0xee,0x91,0x36,0xf5,0xb5,0x70,0xf6,0xb7,0x73,0xf6,0xb4,0x70,0xf5,0xb1,0x6c,0xf9,0xcc,0xa1,0xff,0xff,0xff,0xff,0xff,0xff,0xd1,0xe2,0xef,0x4b,0x97,0xca,0x47,0x9a,0xce,0x3f,0x95,0xcb,0x3,0x71,0xb5,0x0,0x6c,0xb0,0x0,0x69,0xae,0x0,0x67,0xac,0x0,0x66,0xac,0x0,0x67,0xad,0x0,0x69,0xaf,0x66,0xa5,0xcf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xfa,0xf8,0xc3,0x67,0xf6,0xb8,0x44,0xf6,0xba,0x45,0xf6,0xbb,0x46,0xf6,0xb7,0x44,0xf4,0xab,0x3e,0xf8,0xab,0x3f,0x2a,0x19,0x8,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x2b,0x15,0x9,0xd4,0x8a,0x5c,0xf4,0xac,0x7c,0xf1,0x98,0x54,0xee,0x85,0x2e,0xf1,0x93,0x38,0xf6,0xba,0x75,0xf6,0xb9,0x75,0xf6,0xb6,0x72,0xf6,0xb3,0x6f,0xfa,0xd5,0xb1,0xff,0xff,0xff,0xff,0xff,0xff,0xb0,0xcf,0xe5,0x51,0x9e,0xcf,0x4b,0x9d,0xd0,0x43,0x97,0xcc,0x3,0x71,0xb5,0x0,0x6d,0xb1,0x0,0x6a,0xae,0x0,0x67,0xac,0x0,0x67,0xad,0x0,0x68,0xae,0x0,0x6a,0xb0,0x3b,0x8c,0xc2,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xf9,0xc9,0x77,0xf6,0xb8,0x44,0xf6,0xba,0x45,0xf6,0xbc,0x46,0xf6,0xb8,0x44,0xf4,0xad,0x3f,0xf8,0xac,0x3f,0x2a,0x1a,0x8,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x47,0x26,0x12,0xee,0xa3,0x72,0xf4,0xae,0x7b,0xf1,0x97,0x4e,0xf1,0x92,0x38,0xf6,0xbb,0x78,0xf6,0xbb,0x78,0xf6,0xb7,0x75,0xf6,0xb5,0x71,0xfa,0xd6,0xb2,0xff,0xff,0xff,0xff,0xff,0xff,0xad,0xcd,0xe4,0x54,0xa0,0xd1,0x4e,0xa0,0xd1,0x48,0x9b,0xce,0xb,0x76,0xb8,0x0,0x6d,0xb2,0x0,0x6a,0xaf,0x0,0x68,0xad,0x0,0x68,0xad,0x0,0x69,0xae,0x0,0x6b,0xb1,0x36,0x89,0xc1,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xf9,0xc9,0x76,0xf6,0xb9,0x44,0xf6,0xbb,0x46,0xf6,0xbc,0x47,0xf6,0xb9,0x44,0xf4,0xad,0x3f,0xf8,0xad,0x40,0x2a,0x1a,0x8,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x70,0x42,0x26,0xf4,0xad,0x7b,0xf5,0xb1,0x7d,0xf3,0x9f,0x50,0xf7,0xbc,0x7b,0xf7,0xbc,0x7b,0xf6,0xb9,0x78,0xf6,0xb7,0x74,0xf9,0xd0,0xa6,0xff,0xff,0xff,0xff,0xff,0xff,0xc3,0xda,0xeb,0x56,0xa0,0xd0,0x51,0xa1,0xd2,0x4a,0x9c,0xcf,0x20,0x82,0xbf,0x0,0x6e,0xb2,0x0,0x6b,0xb0,0x0,0x68,0xae,0x0,0x68,0xae,0x0,0x69,0xaf,0x0,0x6b,0xb1,0x50,0x98,0xc9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xf9,0xf8,0xc3,0x66,0xf6,0xb9,0x45,0xf7,0xbb,0x46,0xf6,0xbc,0x47,0xf6,0xb8,0x45,0xf4,0xad,0x3f,0xf8,0xac,0x3f,0x2a,0x19,0x7,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xc,0x5,0x0,0xa5,0x67,0x40,0xf5,0xb1,0x7f,0xf5,0xb7,0x7e,0xf7,0xbf,0x80,0xf7,0xbe,0x7d,0xf7,0xbb,0x7b,0xf6,0xb9,0x78,0xf8,0xc2,0x8b,0xff,0xff,0xff,0xff,0xff,0xff,0xee,0xf5,0xf9,0x5b,0xa0,0xce,0x53,0xa2,0xd2,0x4c,0x9e,0xd0,0x3c,0x93,0xc8,0x6,0x71,0xb4,0x0,0x6c,0xb0,0x0,0x69,0xae,0x0,0x69,0xae,0x0,0x6a,0xaf,0x0,0x6b,0xb1,0x9b,0xc5,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xf7,0xec,0xf6,0xba,0x4e,0xf6,0xb9,0x45,0xf7,0xbb,0x46,0xf6,0xbc,0x47,0xf5,0xb7,0x44,0xf4,0xab,0x3e,0xf5,0xa8,0x3e,0x18,0xd,0x4,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x1f,0x10,0x7,0xc9,0x84,0x56,0xf5,0xb5,0x81,0xf7,0xbf,0x82,0xf8,0xc0,0x80,0xf7,0xbd,0x7d,0xf7,0xba,0x7a,0xf6,0xb8,0x77,0xfe,0xf5,0xec,0xff,0xff,0xff,0xff,0xff,0xff,0x9a,0xc2,0xdf,0x55,0x9f,0xd0,0x4e,0x9f,0xd0,0x47,0x99,0xcc,0x2a,0x87,0xc1,0x3,0x6d,0xb1,0x0,0x69,0xaf,0x0,0x6a,0xaf,0x0,0x6a,0xb0,0x27,0x80,0xbc,0xec,0xf4,0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xe5,0xbf,0xf6,0xb6,0x42,0xf6,0xba,0x46,0xf7,0xbb,0x46,0xf7,0xbb,0x47,0xf5,0xb5,0x43,0xf3,0xa8,0x3d,0xdd,0x97,0x37,0x2,0x1,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x32,0x1a,0xb,0xe4,0x9d,0x6a,0xf7,0xbd,0x84,0xf8,0xc1,0x83,0xf8,0xbe,0x80,0xf7,0xbd,0x7d,0xf7,0xba,0x79,0xfa,0xd9,0xb6,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xf6,0xfa,0x74,0xac,0xd4,0x4f,0x9b,0xcd,0x48,0x99,0xcc,0x41,0x94,0xc8,0x2c,0x85,0xbe,0xb,0x70,0xb3,0x1,0x6a,0xb0,0xb,0x6e,0xb2,0xbf,0xd9,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xf8,0xc8,0x74,0xf6,0xb7,0x44,0xf6,0xba,0x46,0xf7,0xbb,0x46,0xf7,0xb9,0x46,0xf6,0xb2,0x42,0xf4,0xa7,0x3d,0xa6,0x70,0x29,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x4f,0x2e,0x18,0xef,0xaf,0x78,0xf8,0xc1,0x85,0xf8,0xc0,0x82,0xf7,0xbe,0x7f,0xf7,0xbc,0x7d,0xf7,0xbe,0x81,0xfe,0xf3,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0xf2,0xf7,0xfa,0x91,0xbd,0xdb,0x4f,0x97,0xc8,0x40,0x8e,0xc3,0x37,0x8a,0xc0,0x34,0x88,0xbf,0x57,0x9c,0xca,0xcc,0xe1,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xe4,0xbf,0xf5,0xb6,0x45,0xf6,0xb8,0x45,0xf6,0xba,0x46,0xf7,0xba,0x46,0xf6,0xb7,0x45,0xf5,0xad,0x3f,0xf4,0xa9,0x40,0x5c,0x3d,0x18,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x85,0x55,0x31,0xf7,0xbd,0x84,0xf8,0xc2,0x85,0xf8,0xc0,0x82,0xf7,0xbe,0x80,0xf7,0xbc,0x7d,0xf9,0xcb,0x99,0xfe,0xf9,0xf4,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xfe,0xfe,0xe5,0xef,0xf6,0xc1,0xda,0xeb,0xba,0xd5,0xe9,0xd8,0xe8,0xf2,0xf9,0xfb,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xf3,0xe4,0xf6,0xb9,0x51,0xf5,0xb5,0x43,0xf6,0xb8,0x45,0xf6,0xb9,0x46,0xf6,0xb8,0x46,0xf6,0xb3,0x43,0xf4,0xa7,0x3e,0xdf,0x9d,0x43,0x17,0xd,0x4,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x14,0xa,0x4,0xb2,0x7b,0x4b,0xf8,0xc2,0x88,0xf8,0xc1,0x85,0xf7,0xbf,0x82,0xf7,0xbe,0x80,0xf7,0xbd,0x7d,0xf9,0xca,0x97,0xfe,0xf9,0xf4,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xf2,0xe1,0xf7,0xbc,0x5d,0xf5,0xb3,0x42,0xf5,0xb6,0x44,0xf5,0xb7,0x45,0xf6,0xb8,0x45,0xf6,0xb5,0x44,0xf5,0xad,0x40,0xf6,0xae,0x4c,0x88,0x5d,0x27,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x1d,0x10,0x6,0xdb,0xa0,0x68,0xf8,0xc3,0x88,0xf7,0xc1,0x85,0xf7,0xc0,0x82,0xf7,0xbf,0x80,0xf7,0xbe,0x7e,0xf8,0xc4,0x88,0xfc,0xe6,0xcc,0xfe,0xfb,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfa,0xf3,0xfa,0xda,0xa9,0xf5,0xb3,0x4a,0xf5,0xb2,0x42,0xf5,0xb3,0x43,0xf5,0xb6,0x44,0xf5,0xb7,0x45,0xf5,0xb5,0x44,0xf5,0xb0,0x42,0xf5,0xad,0x4d,0xdd,0x9e,0x4a,0x19,0xf,0x5,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x50,0x33,0x19,0xec,0xb4,0x7a,0xf8,0xc2,0x87,0xf7,0xc1,0x85,0xf7,0xc1,0x83,0xf7,0xc0,0x80,0xf7,0xc0,0x7f,0xf7,0xc0,0x7c,0xf7,0xc2,0x7e,0xf8,0xcc,0x92,0xfa,0xda,0xb0,0xfb,0xdf,0xb9,0xfa,0xd9,0xad,0xf7,0xc8,0x84,0xf5,0xb4,0x54,0xf4,0xad,0x3f,0xf4,0xaf,0x41,0xf5,0xb2,0x42,0xf5,0xb4,0x43,0xf5,0xb5,0x44,0xf5,0xb4,0x44,0xf5,0xb2,0x46,0xf5,0xb2,0x54,0xf5,0xb4,0x5a,0x5e,0x3e,0x1a,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x71,0x4b,0x29,0xf8,0xc0,0x86,0xf7,0xc3,0x87,0xf7,0xc2,0x85,0xf7,0xc1,0x83,0xf7,0xc2,0x82,0xf7,0xc2,0x7f,0xf7,0xc2,0x7e,0xf6,0xc0,0x76,0xf4,0xb4,0x59,0xf3,0xa8,0x3e,0xf3,0xa7,0x39,0xf3,0xa9,0x3d,0xf4,0xab,0x3e,0xf4,0xad,0x40,0xf4,0xb0,0x41,0xf4,0xb2,0x42,0xf5,0xb2,0x42,0xf5,0xb3,0x45,0xf6,0xb7,0x54,0xf6,0xb7,0x60,0xf6,0xb5,0x5f,0x9d,0x6b,0x31,0x2,0x1,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x8b,0x5f,0x36,0xf9,0xc1,0x87,0xf7,0xc3,0x88,0xf8,0xc3,0x86,0xf7,0xc3,0x84,0xf8,0xc3,0x81,0xf7,0xc4,0x80,0xf7,0xc4,0x7e,0xf7,0xc4,0x7d,0xf7,0xc3,0x7a,0xf6,0xbd,0x6c,0xf5,0xb7,0x5c,0xf5,0xb5,0x54,0xf5,0xb4,0x50,0xf5,0xb6,0x52,0xf6,0xb9,0x58,0xf6,0xbd,0x62,0xf7,0xbf,0x6a,0xf6,0xba,0x66,0xf6,0xb6,0x63,0xab,0x78,0x39,0xa,0x6,0x2,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x83,0x58,0x32,0xf0,0xb9,0x7f,0xf7,0xc3,0x88,0xf7,0xc3,0x86,0xf8,0xc4,0x84,0xf7,0xc5,0x82,0xf7,0xc5,0x80,0xf7,0xc5,0x7f,0xf8,0xc5,0x7d,0xf7,0xc4,0x7b,0xf7,0xc4,0x79,0xf7,0xc4,0x78,0xf7,0xc3,0x76,0xf7,0xc3,0x74,0xf7,0xc2,0x71,0xf6,0xbe,0x6d,0xf6,0xba,0x6a,0xf4,0xb6,0x65,0x8a,0x5e,0x2c,0xc,0x7,0x3,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x4f,0x33,0x1a,0xd2,0x99,0x60,0xf8,0xc4,0x89,0xf8,0xc3,0x86,0xf8,0xc4,0x84,0xf7,0xc5,0x82,0xf7,0xc5,0x80,0xf7,0xc5,0x7f,0xf7,0xc4,0x7e,0xf7,0xc4,0x7b,0xf7,0xc3,0x79,0xf7,0xc2,0x77,0xf6,0xc0,0x74,0xf6,0xbd,0x71,0xf6,0xbb,0x6e,0xe1,0xa4,0x59,0x5c,0x3d,0x1b,0x1,0x1,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xe,0x6,0x0,0x72,0x4b,0x28,0xd0,0x9a,0x62,0xf7,0xbf,0x80,0xf8,0xc4,0x85,0xf7,0xc3,0x82,0xf7,0xc3,0x80,0xf7,0xc3,0x7e,0xf7,0xc1,0x7c,0xf6,0xc0,0x7a,0xf7,0xbf,0x78,0xf8,0xbc,0x72,0xde,0xa2,0x5d,0x80,0x57,0x2b,0x13,0xb,0x4,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x19,0xe,0x5,0x44,0x2c,0x15,0x81,0x59,0x32,0xb2,0x80,0x4c,0xcb,0x95,0x5b,0xd2,0x9c,0x5f,0xcd,0x97,0x5a,0xb9,0x86,0x4d,0x8b,0x61,0x34,0x4a,0x30,0x17,0x15,0xc,0x5,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0x0,0x0,0x0,0x1,0x0,0x0,0x3,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,0xff,0x0,0xff,
|
||||
};
|
||||
|
||||
|
||||
GLXContext GHOST_WindowX11::s_firstContext = NULL;
|
||||
|
||||
GHOST_WindowX11::
|
||||
GHOST_WindowX11(
|
||||
GHOST_SystemX11 *system,
|
||||
Display * display,
|
||||
const STR_String& title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
const GHOST_TEmbedderWindowID parentWindow,
|
||||
GHOST_TDrawingContextType type,
|
||||
const bool stereoVisual,
|
||||
const GHOST_TUns16 numOfAASamples
|
||||
) :
|
||||
GHOST_Window(title,left,top,width,height,state,type,stereoVisual,numOfAASamples),
|
||||
m_context(NULL),
|
||||
m_display(display),
|
||||
m_normal_state(GHOST_kWindowStateNormal),
|
||||
m_system (system),
|
||||
m_valid_setup (false),
|
||||
m_invalid_window(false),
|
||||
m_empty_cursor(None),
|
||||
m_custom_cursor(None)
|
||||
{
|
||||
|
||||
// Set up the minimum atrributes that we require and see if
|
||||
// X can find us a visual matching those requirements.
|
||||
|
||||
int attributes[40], i, samples;
|
||||
Atom atoms[2];
|
||||
int natom;
|
||||
int glxVersionMajor, glxVersionMinor; // As in GLX major.minor
|
||||
|
||||
/* initialize incase X11 fails to load */
|
||||
memset(&m_xtablet, 0, sizeof(m_xtablet));
|
||||
m_visual= NULL;
|
||||
|
||||
if (!glXQueryVersion(m_display, &glxVersionMajor, &glxVersionMinor)) {
|
||||
printf("%s:%d: X11 glXQueryVersion() failed, verify working openGL system!\n", __FILE__, __LINE__);
|
||||
|
||||
/* exit if this is the first window */
|
||||
if(s_firstContext==NULL) {
|
||||
printf("initial window could not find the GLX extension, exit!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the display with highest samples, starting at level requested */
|
||||
for (samples = m_numOfAASamples; samples >= 0; samples--) {
|
||||
i = 0; /* Reusing attributes array, so reset counter */
|
||||
|
||||
if(m_stereoVisual)
|
||||
attributes[i++] = GLX_STEREO;
|
||||
|
||||
attributes[i++] = GLX_RGBA;
|
||||
attributes[i++] = GLX_DOUBLEBUFFER;
|
||||
attributes[i++] = GLX_RED_SIZE; attributes[i++] = 1;
|
||||
attributes[i++] = GLX_BLUE_SIZE; attributes[i++] = 1;
|
||||
attributes[i++] = GLX_GREEN_SIZE; attributes[i++] = 1;
|
||||
attributes[i++] = GLX_DEPTH_SIZE; attributes[i++] = 1;
|
||||
/* GLX >= 1.4 required for multi-sample */
|
||||
if(samples && (glxVersionMajor >= 1) && (glxVersionMinor >= 4)) {
|
||||
attributes[i++] = GLX_SAMPLE_BUFFERS; attributes[i++] = 1;
|
||||
attributes[i++] = GLX_SAMPLES; attributes[i++] = samples;
|
||||
}
|
||||
attributes[i] = None;
|
||||
|
||||
m_visual = glXChooseVisual(m_display, DefaultScreen(m_display), attributes);
|
||||
|
||||
/* Any sample level or even zero, which means oversampling disabled, is good
|
||||
but we need a valid visual to continue */
|
||||
if (m_visual == NULL) {
|
||||
if (samples == 0) {
|
||||
/* All options exhausted, cannot continue */
|
||||
printf("%s:%d: X11 glXChooseVisual() failed, verify working openGL system!\n", __FILE__, __LINE__);
|
||||
|
||||
if(s_firstContext==NULL) {
|
||||
printf("initial window could not find the GLX extension, exit!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (m_numOfAASamples && (m_numOfAASamples > samples)) {
|
||||
printf("%s:%d: oversampling requested %i but using %i samples\n", __FILE__, __LINE__, m_numOfAASamples, samples);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a bunch of attributes needed to create an X window.
|
||||
|
||||
|
||||
// First create a colormap for the window and visual.
|
||||
// This seems pretty much a legacy feature as we are in rgba mode anyway.
|
||||
|
||||
XSetWindowAttributes xattributes;
|
||||
memset(&xattributes, 0, sizeof(xattributes));
|
||||
|
||||
xattributes.colormap= XCreateColormap(
|
||||
m_display,
|
||||
RootWindow(m_display, m_visual->screen),
|
||||
m_visual->visual,
|
||||
AllocNone
|
||||
);
|
||||
|
||||
xattributes.border_pixel= 0;
|
||||
|
||||
// Specify which events we are interested in hearing.
|
||||
|
||||
xattributes.event_mask=
|
||||
ExposureMask | StructureNotifyMask |
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
EnterWindowMask | LeaveWindowMask |
|
||||
ButtonPressMask | ButtonReleaseMask |
|
||||
PointerMotionMask | FocusChangeMask | PropertyChangeMask;
|
||||
|
||||
// create the window!
|
||||
|
||||
;
|
||||
if (parentWindow == 0) {
|
||||
m_window =
|
||||
XCreateWindow(
|
||||
m_display,
|
||||
RootWindow(m_display, m_visual->screen),
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height,
|
||||
0, // no border.
|
||||
m_visual->depth,
|
||||
InputOutput,
|
||||
m_visual->visual,
|
||||
CWBorderPixel|CWColormap|CWEventMask,
|
||||
&xattributes
|
||||
);
|
||||
} else {
|
||||
|
||||
Window root_return;
|
||||
int x_return,y_return;
|
||||
unsigned int w_return,h_return,border_w_return,depth_return;
|
||||
|
||||
XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return,
|
||||
&w_return, &h_return, &border_w_return, &depth_return );
|
||||
|
||||
left = 0;
|
||||
top = 0;
|
||||
width = w_return;
|
||||
height = h_return;
|
||||
|
||||
|
||||
m_window = XCreateWindow(
|
||||
m_display,
|
||||
parentWindow, // reparent against embedder
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height,
|
||||
0, // no border.
|
||||
m_visual->depth,
|
||||
InputOutput,
|
||||
m_visual->visual,
|
||||
CWBorderPixel|CWColormap|CWEventMask,
|
||||
&xattributes
|
||||
);
|
||||
|
||||
XSelectInput(m_display , parentWindow, SubstructureNotifyMask);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* One of the problem with WM-spec is that can't set a property
|
||||
* to a window that isn't mapped. That is why we can't "just
|
||||
* call setState" here.
|
||||
*
|
||||
* To fix this, we first need know that the window is really
|
||||
* map waiting for the MapNotify event.
|
||||
*
|
||||
* So, m_post_init indicate that we need wait for the MapNotify
|
||||
* event and then set the Window state to the m_post_state.
|
||||
*/
|
||||
if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) {
|
||||
m_post_init = True;
|
||||
m_post_state = state;
|
||||
}
|
||||
else {
|
||||
m_post_init = False;
|
||||
m_post_state = GHOST_kWindowStateNormal;
|
||||
}
|
||||
|
||||
// Create some hints for the window manager on how
|
||||
// we want this window treated.
|
||||
|
||||
XSizeHints * xsizehints = XAllocSizeHints();
|
||||
xsizehints->flags = PPosition | PSize | PMinSize | PMaxSize;
|
||||
xsizehints->x = left;
|
||||
xsizehints->y = top;
|
||||
xsizehints->width = width;
|
||||
xsizehints->height = height;
|
||||
xsizehints->min_width= 320; // size hints, could be made apart of the ghost api
|
||||
xsizehints->min_height= 240; // limits are also arbitrary, but should not allow 1x1 window
|
||||
xsizehints->max_width= 65535;
|
||||
xsizehints->max_height= 65535;
|
||||
XSetWMNormalHints(m_display, m_window, xsizehints);
|
||||
XFree(xsizehints);
|
||||
|
||||
XClassHint * xclasshint = XAllocClassHint();
|
||||
int len = title.Length() +1 ;
|
||||
char *wmclass = (char *)malloc(sizeof(char) * len);
|
||||
strncpy(wmclass, (const char*)title, sizeof(char) * len);
|
||||
xclasshint->res_name = wmclass;
|
||||
xclasshint->res_class = wmclass;
|
||||
XSetClassHint(m_display, m_window, xclasshint);
|
||||
free(wmclass);
|
||||
XFree(xclasshint);
|
||||
|
||||
/* The basic for a good ICCCM "work" */
|
||||
if (m_system->m_wm_protocols) {
|
||||
natom= 0;
|
||||
|
||||
if (m_system->m_delete_window_atom) {
|
||||
atoms[natom]= m_system->m_delete_window_atom;
|
||||
natom++;
|
||||
}
|
||||
|
||||
if (m_system->m_wm_take_focus) {
|
||||
atoms[natom]= m_system->m_wm_take_focus;
|
||||
natom++;
|
||||
}
|
||||
|
||||
if (natom) {
|
||||
/* printf("Register atoms: %d\n", natom); */
|
||||
XSetWMProtocols(m_display, m_window, atoms, natom);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the window icon
|
||||
XWMHints *xwmhints = XAllocWMHints();
|
||||
XImage *x_image, *mask_image;
|
||||
Pixmap icon_pixmap, mask_pixmap;
|
||||
icon_pixmap = XCreatePixmap(display, m_window, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT, 24);
|
||||
mask_pixmap = XCreatePixmap(display, m_window, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT, 1);
|
||||
GC gc_icon = XCreateGC(display, icon_pixmap, 0, NULL);
|
||||
GC gc_mask = XCreateGC(display, mask_pixmap, 0, NULL);
|
||||
|
||||
x_image = XCreateImage( display, m_visual->visual, 24, ZPixmap, 0, NULL, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT, 32, 0 );
|
||||
mask_image = XCreateImage( display, m_visual->visual, 1, ZPixmap, 0, NULL, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT, 8, 0);
|
||||
|
||||
x_image->data = (char *)malloc(x_image->bytes_per_line * BLENDER_ICON_HEIGHT);
|
||||
mask_image->data = (char *)malloc( mask_image->bytes_per_line * BLENDER_ICON_HEIGHT);
|
||||
|
||||
/* copy the BLENDER_ICON_48x48x24 into the XImage */
|
||||
unsigned char *col = BLENDER_ICON_48x48x24;
|
||||
int px, py;
|
||||
for (px=0; px<BLENDER_ICON_WIDTH; px++) {
|
||||
for (py=0; py<BLENDER_ICON_HEIGHT; py++, col+=3) {
|
||||
/* mask out pink */
|
||||
if (col[0]==255 && col[1] == 0 && col[2]== 255) {
|
||||
XPutPixel(mask_image, px, py, 0 );
|
||||
} else {
|
||||
XPutPixel(x_image, px, py, (col[0]<<16)+(col[1]<<8)+col[2] );
|
||||
XPutPixel(mask_image, px, py, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
XPutImage(display, icon_pixmap, gc_icon, x_image, 0, 0, 0, 0, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT);
|
||||
XPutImage(display, mask_pixmap, gc_mask, mask_image, 0, 0, 0, 0, BLENDER_ICON_WIDTH, BLENDER_ICON_HEIGHT);
|
||||
|
||||
// Now the pixmap is ok to assign to the window as a hint
|
||||
xwmhints->icon_pixmap = icon_pixmap;
|
||||
xwmhints->icon_mask = mask_pixmap;
|
||||
XFreeGC (display, gc_icon);
|
||||
XFreeGC (display, gc_mask);
|
||||
XDestroyImage( x_image ); /* frees x_image->data too */
|
||||
XDestroyImage( mask_image );
|
||||
|
||||
xwmhints->initial_state = NormalState;
|
||||
xwmhints->input= True;
|
||||
xwmhints->flags= InputHint|IconPixmapHint|IconMaskHint|StateHint;
|
||||
XSetWMHints(display, m_window, xwmhints );
|
||||
XFree(xwmhints);
|
||||
// done setting the icon
|
||||
|
||||
setTitle(title);
|
||||
|
||||
#ifdef WITH_X11_XINPUT
|
||||
initXInputDevices();
|
||||
#endif
|
||||
|
||||
// now set up the rendering context.
|
||||
if (installDrawingContext(type) == GHOST_kSuccess) {
|
||||
m_valid_setup = true;
|
||||
GHOST_PRINT("Created window\n");
|
||||
}
|
||||
|
||||
XMapWindow(m_display, m_window);
|
||||
GHOST_PRINT("Mapped window\n");
|
||||
|
||||
XFlush(m_display);
|
||||
}
|
||||
|
||||
#ifdef WITH_X11_XINPUT
|
||||
/*
|
||||
Dummy function to get around IO Handler exiting if device invalid
|
||||
Basically it will not crash blender now if you have a X device that
|
||||
is configured but not plugged in.
|
||||
|
||||
*/
|
||||
static int ApplicationErrorHandler(Display *display, XErrorEvent *theEvent) {
|
||||
fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n",
|
||||
theEvent->error_code, theEvent->request_code) ;
|
||||
|
||||
/* No exit! - but keep lint happy */
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
/* These C functions are copied from Wine 1.1.13's wintab.c */
|
||||
#define BOOL int
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
static bool match_token(const char *haystack, const char *needle)
|
||||
{
|
||||
const char *p, *q;
|
||||
for (p = haystack; *p; )
|
||||
{
|
||||
while (*p && isspace(*p))
|
||||
p++;
|
||||
if (! *p)
|
||||
break;
|
||||
|
||||
for (q = needle; *q && *p && tolower(*p) == tolower(*q); q++)
|
||||
p++;
|
||||
if (! *q && (isspace(*p) || !*p))
|
||||
return TRUE;
|
||||
|
||||
while (*p && ! isspace(*p))
|
||||
p++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Determining if an X device is a Tablet style device is an imperfect science.
|
||||
** We rely on common conventions around device names as well as the type reported
|
||||
** by Wacom tablets. This code will likely need to be expanded for alternate tablet types
|
||||
**
|
||||
** Wintab refers to any device that interacts with the tablet as a cursor,
|
||||
** (stylus, eraser, tablet mouse, airbrush, etc)
|
||||
** this is not to be confused with wacom x11 configuration "cursor" device.
|
||||
** Wacoms x11 config "cursor" refers to its device slot (which we mirror with
|
||||
** our gSysCursors) for puck like devices (tablet mice essentially).
|
||||
*/
|
||||
#if 0 // unused
|
||||
static BOOL is_tablet_cursor(const char *name, const char *type)
|
||||
{
|
||||
int i;
|
||||
static const char *tablet_cursor_whitelist[] = {
|
||||
"wacom",
|
||||
"wizardpen",
|
||||
"acecad",
|
||||
"tablet",
|
||||
"cursor",
|
||||
"stylus",
|
||||
"eraser",
|
||||
"pad",
|
||||
NULL
|
||||
};
|
||||
|
||||
for (i=0; tablet_cursor_whitelist[i] != NULL; i++) {
|
||||
if (name && match_token(name, tablet_cursor_whitelist[i]))
|
||||
return TRUE;
|
||||
if (type && match_token(type, tablet_cursor_whitelist[i]))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
static BOOL is_stylus(const char *name, const char *type)
|
||||
{
|
||||
int i;
|
||||
static const char* tablet_stylus_whitelist[] = {
|
||||
"stylus",
|
||||
"wizardpen",
|
||||
"acecad",
|
||||
NULL
|
||||
};
|
||||
|
||||
for (i=0; tablet_stylus_whitelist[i] != NULL; i++) {
|
||||
if (name && match_token(name, tablet_stylus_whitelist[i]))
|
||||
return TRUE;
|
||||
if (type && match_token(type, tablet_stylus_whitelist[i]))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL is_eraser(const char *name, const char *type)
|
||||
{
|
||||
if (name && match_token(name, "eraser"))
|
||||
return TRUE;
|
||||
if (type && match_token(type, "eraser"))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
#undef BOOL
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
/* end code copied from wine */
|
||||
|
||||
void GHOST_WindowX11::initXInputDevices()
|
||||
{
|
||||
static XErrorHandler old_handler = (XErrorHandler) 0 ;
|
||||
XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
|
||||
|
||||
if(version && (version != (XExtensionVersion*)NoSuchExtension)) {
|
||||
if(version->present) {
|
||||
int device_count;
|
||||
XDeviceInfo* device_info = XListInputDevices(m_display, &device_count);
|
||||
m_xtablet.StylusDevice = NULL;
|
||||
m_xtablet.EraserDevice = NULL;
|
||||
m_xtablet.CommonData.Active= GHOST_kTabletModeNone;
|
||||
|
||||
/* Install our error handler to override Xlib's termination behavior */
|
||||
old_handler = XSetErrorHandler(ApplicationErrorHandler) ;
|
||||
|
||||
for(int i=0; i<device_count; ++i) {
|
||||
char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) : NULL;
|
||||
|
||||
// printf("Tablet type:'%s', name:'%s', index:%d\n", device_type, device_info[i].name, i);
|
||||
|
||||
|
||||
if(m_xtablet.StylusDevice==NULL && is_stylus(device_info[i].name, device_type)) {
|
||||
// printf("\tfound stylus\n");
|
||||
m_xtablet.StylusID= device_info[i].id;
|
||||
m_xtablet.StylusDevice = XOpenDevice(m_display, m_xtablet.StylusID);
|
||||
|
||||
if (m_xtablet.StylusDevice != NULL) {
|
||||
/* Find how many pressure levels tablet has */
|
||||
XAnyClassPtr ici = device_info[i].inputclassinfo;
|
||||
for(int j=0; j<m_xtablet.StylusDevice->num_classes; ++j) {
|
||||
if(ici->c_class==ValuatorClass) {
|
||||
// printf("\t\tfound ValuatorClass\n");
|
||||
XValuatorInfo* xvi = (XValuatorInfo*)ici;
|
||||
m_xtablet.PressureLevels = xvi->axes[2].max_value;
|
||||
|
||||
/* this is assuming that the tablet has the same tilt resolution in both
|
||||
* positive and negative directions. It would be rather weird if it didn't.. */
|
||||
m_xtablet.XtiltLevels = xvi->axes[3].max_value;
|
||||
m_xtablet.YtiltLevels = xvi->axes[4].max_value;
|
||||
break;
|
||||
}
|
||||
|
||||
ici = (XAnyClassPtr)(((char *)ici) + ici->length);
|
||||
}
|
||||
} else {
|
||||
m_xtablet.StylusID= 0;
|
||||
}
|
||||
}
|
||||
else if(m_xtablet.EraserDevice==NULL && is_eraser(device_info[i].name, device_type)) {
|
||||
// printf("\tfound eraser\n");
|
||||
m_xtablet.EraserID= device_info[i].id;
|
||||
m_xtablet.EraserDevice = XOpenDevice(m_display, m_xtablet.EraserID);
|
||||
if (m_xtablet.EraserDevice == NULL) m_xtablet.EraserID= 0;
|
||||
}
|
||||
|
||||
if(device_type) {
|
||||
XFree((void*)device_type);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore handler */
|
||||
(void) XSetErrorHandler(old_handler) ;
|
||||
|
||||
XFreeDeviceList(device_info);
|
||||
|
||||
|
||||
XEventClass xevents[10], ev;
|
||||
int dcount = 0;
|
||||
|
||||
if(m_xtablet.StylusDevice) {
|
||||
DeviceMotionNotify(m_xtablet.StylusDevice, m_xtablet.MotionEvent, ev);
|
||||
if(ev) xevents[dcount++] = ev;
|
||||
ProximityIn(m_xtablet.StylusDevice, m_xtablet.ProxInEvent, ev);
|
||||
if(ev) xevents[dcount++] = ev;
|
||||
ProximityOut(m_xtablet.StylusDevice, m_xtablet.ProxOutEvent, ev);
|
||||
if(ev) xevents[dcount++] = ev;
|
||||
}
|
||||
if(m_xtablet.EraserDevice) {
|
||||
DeviceMotionNotify(m_xtablet.EraserDevice, m_xtablet.MotionEvent, ev);
|
||||
if(ev) xevents[dcount++] = ev;
|
||||
ProximityIn(m_xtablet.EraserDevice, m_xtablet.ProxInEvent, ev);
|
||||
if(ev) xevents[dcount++] = ev;
|
||||
ProximityOut(m_xtablet.EraserDevice, m_xtablet.ProxOutEvent, ev);
|
||||
if(ev) xevents[dcount++] = ev;
|
||||
}
|
||||
|
||||
XSelectExtensionEvent(m_display, m_window, xevents, dcount);
|
||||
}
|
||||
XFree(version);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WITH_X11_XINPUT */
|
||||
|
||||
Window
|
||||
GHOST_WindowX11::
|
||||
getXWindow(
|
||||
){
|
||||
return m_window;
|
||||
}
|
||||
|
||||
bool
|
||||
GHOST_WindowX11::
|
||||
getValid(
|
||||
) const {
|
||||
return m_valid_setup;
|
||||
}
|
||||
|
||||
void
|
||||
GHOST_WindowX11::
|
||||
setTitle(
|
||||
const STR_String& title
|
||||
){
|
||||
Atom name = XInternAtom(m_display, "_NET_WM_NAME", 0);
|
||||
Atom utf8str = XInternAtom(m_display, "UTF8_STRING", 0);
|
||||
XChangeProperty(m_display, m_window,
|
||||
name, utf8str, 8, PropModeReplace,
|
||||
(const unsigned char*) title.ReadPtr(),
|
||||
title.Length());
|
||||
|
||||
// This should convert to valid x11 string
|
||||
// and getTitle would need matching change
|
||||
XStoreName(m_display,m_window,title);
|
||||
|
||||
XFlush(m_display);
|
||||
}
|
||||
|
||||
void
|
||||
GHOST_WindowX11::
|
||||
getTitle(
|
||||
STR_String& title
|
||||
) const {
|
||||
char *name = NULL;
|
||||
|
||||
XFetchName(m_display,m_window,&name);
|
||||
title= name?name:"untitled";
|
||||
XFree(name);
|
||||
}
|
||||
|
||||
void
|
||||
GHOST_WindowX11::
|
||||
getWindowBounds(
|
||||
GHOST_Rect& bounds
|
||||
) const {
|
||||
// Getting the window bounds under X11 is not
|
||||
// really supported (nor should it be desired).
|
||||
getClientBounds(bounds);
|
||||
}
|
||||
|
||||
void
|
||||
GHOST_WindowX11::
|
||||
getClientBounds(
|
||||
GHOST_Rect& bounds
|
||||
) const {
|
||||
Window root_return;
|
||||
int x_return,y_return;
|
||||
unsigned int w_return,h_return,border_w_return,depth_return;
|
||||
GHOST_TInt32 screen_x, screen_y;
|
||||
|
||||
XGetGeometry(m_display,m_window,&root_return,&x_return,&y_return,
|
||||
&w_return,&h_return,&border_w_return,&depth_return);
|
||||
|
||||
clientToScreen(0, 0, screen_x, screen_y);
|
||||
|
||||
bounds.m_l = screen_x;
|
||||
bounds.m_r = bounds.m_l + w_return;
|
||||
bounds.m_t = screen_y;
|
||||
bounds.m_b = bounds.m_t + h_return;
|
||||
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
setClientWidth(
|
||||
GHOST_TUns32 width
|
||||
){
|
||||
XWindowChanges values;
|
||||
unsigned int value_mask= CWWidth;
|
||||
values.width = width;
|
||||
XConfigureWindow(m_display,m_window,value_mask,&values);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
setClientHeight(
|
||||
GHOST_TUns32 height
|
||||
){
|
||||
XWindowChanges values;
|
||||
unsigned int value_mask= CWHeight;
|
||||
values.height = height;
|
||||
XConfigureWindow(m_display,m_window,value_mask,&values);
|
||||
return GHOST_kSuccess;
|
||||
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
setClientSize(
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height
|
||||
){
|
||||
XWindowChanges values;
|
||||
unsigned int value_mask= CWWidth | CWHeight;
|
||||
values.width = width;
|
||||
values.height = height;
|
||||
XConfigureWindow(m_display,m_window,value_mask,&values);
|
||||
return GHOST_kSuccess;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
GHOST_WindowX11::
|
||||
screenToClient(
|
||||
GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32& outX,
|
||||
GHOST_TInt32& outY
|
||||
) const {
|
||||
// This is correct!
|
||||
|
||||
int ax,ay;
|
||||
Window temp;
|
||||
|
||||
XTranslateCoordinates(
|
||||
m_display,
|
||||
RootWindow(m_display, m_visual->screen),
|
||||
m_window,
|
||||
inX,
|
||||
inY,
|
||||
&ax,
|
||||
&ay,
|
||||
&temp
|
||||
);
|
||||
outX = ax;
|
||||
outY = ay;
|
||||
}
|
||||
|
||||
void
|
||||
GHOST_WindowX11::
|
||||
clientToScreen(
|
||||
GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32& outX,
|
||||
GHOST_TInt32& outY
|
||||
) const {
|
||||
int ax,ay;
|
||||
Window temp;
|
||||
|
||||
XTranslateCoordinates(
|
||||
m_display,
|
||||
m_window,
|
||||
RootWindow(m_display, m_visual->screen),
|
||||
inX,
|
||||
inY,
|
||||
&ax,
|
||||
&ay,
|
||||
&temp
|
||||
);
|
||||
outX = ax;
|
||||
outY = ay;
|
||||
}
|
||||
|
||||
void GHOST_WindowX11::icccmSetState(int state)
|
||||
{
|
||||
XEvent xev;
|
||||
|
||||
if (state != IconicState)
|
||||
return;
|
||||
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.serial = 0;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.display = m_display;
|
||||
xev.xclient.window = m_window;
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.message_type = m_system->m_wm_change_state;
|
||||
xev.xclient.data.l[0] = state;
|
||||
XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)),
|
||||
False, SubstructureNotifyMask | SubstructureRedirectMask, &xev);
|
||||
}
|
||||
|
||||
int GHOST_WindowX11::icccmGetState(void) const
|
||||
{
|
||||
unsigned char *prop_ret;
|
||||
unsigned long bytes_after, num_ret;
|
||||
Atom type_ret;
|
||||
int format_ret, st;
|
||||
|
||||
prop_ret = NULL;
|
||||
st = XGetWindowProperty(m_display, m_window, m_system->m_wm_state, 0,
|
||||
0x7fffffff, False, m_system->m_wm_state, &type_ret,
|
||||
&format_ret, &num_ret, &bytes_after, &prop_ret);
|
||||
|
||||
if ((st == Success) && (prop_ret) && (num_ret == 2))
|
||||
st = prop_ret[0];
|
||||
else
|
||||
st = NormalState;
|
||||
|
||||
if (prop_ret)
|
||||
XFree(prop_ret);
|
||||
return (st);
|
||||
}
|
||||
|
||||
void GHOST_WindowX11::netwmMaximized(bool set)
|
||||
{
|
||||
XEvent xev;
|
||||
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.serial = 0;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.window = m_window;
|
||||
xev.xclient.message_type = m_system->m_net_state;
|
||||
xev.xclient.format = 32;
|
||||
|
||||
if (set == True)
|
||||
xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
|
||||
else
|
||||
xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
|
||||
|
||||
xev.xclient.data.l[1] = m_system->m_net_max_horz;
|
||||
xev.xclient.data.l[2] = m_system->m_net_max_vert;
|
||||
xev.xclient.data.l[3] = 0;
|
||||
xev.xclient.data.l[4] = 0;
|
||||
XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
|
||||
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
||||
}
|
||||
|
||||
bool GHOST_WindowX11::netwmIsMaximized(void) const
|
||||
{
|
||||
unsigned char *prop_ret;
|
||||
unsigned long bytes_after, num_ret, i;
|
||||
Atom type_ret;
|
||||
bool st;
|
||||
int format_ret, ret, count;
|
||||
|
||||
prop_ret = NULL;
|
||||
st = False;
|
||||
ret = XGetWindowProperty(m_display, m_window, m_system->m_net_state, 0,
|
||||
0x7fffffff, False, XA_ATOM, &type_ret, &format_ret,
|
||||
&num_ret, &bytes_after, &prop_ret);
|
||||
if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
|
||||
count = 0;
|
||||
for (i = 0; i < num_ret; i++) {
|
||||
if (((unsigned long *) prop_ret)[i] == m_system->m_net_max_horz)
|
||||
count++;
|
||||
if (((unsigned long *) prop_ret)[i] == m_system->m_net_max_vert)
|
||||
count++;
|
||||
if (count == 2) {
|
||||
st = True;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prop_ret)
|
||||
XFree(prop_ret);
|
||||
return (st);
|
||||
}
|
||||
|
||||
void GHOST_WindowX11::netwmFullScreen(bool set)
|
||||
{
|
||||
XEvent xev;
|
||||
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.serial = 0;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.window = m_window;
|
||||
xev.xclient.message_type = m_system->m_net_state;
|
||||
xev.xclient.format = 32;
|
||||
|
||||
if (set == True)
|
||||
xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
|
||||
else
|
||||
xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
|
||||
|
||||
xev.xclient.data.l[1] = m_system->m_net_fullscreen;
|
||||
xev.xclient.data.l[2] = 0;
|
||||
xev.xclient.data.l[3] = 0;
|
||||
xev.xclient.data.l[4] = 0;
|
||||
XSendEvent(m_display, RootWindow(m_display, DefaultScreen(m_display)),
|
||||
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
|
||||
}
|
||||
|
||||
bool GHOST_WindowX11::netwmIsFullScreen(void) const
|
||||
{
|
||||
unsigned char *prop_ret;
|
||||
unsigned long bytes_after, num_ret, i;
|
||||
Atom type_ret;
|
||||
bool st;
|
||||
int format_ret, ret;
|
||||
|
||||
prop_ret = NULL;
|
||||
st = False;
|
||||
ret = XGetWindowProperty(m_display, m_window, m_system->m_net_state, 0,
|
||||
0x7fffffff, False, XA_ATOM, &type_ret, &format_ret,
|
||||
&num_ret, &bytes_after, &prop_ret);
|
||||
if ((ret == Success) && (prop_ret) && (format_ret == 32)) {
|
||||
for (i = 0; i < num_ret; i++) {
|
||||
if (((unsigned long *) prop_ret)[i] == m_system->m_net_fullscreen) {
|
||||
st = True;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prop_ret)
|
||||
XFree(prop_ret);
|
||||
return (st);
|
||||
}
|
||||
|
||||
void GHOST_WindowX11::motifFullScreen(bool set)
|
||||
{
|
||||
MotifWmHints hints;
|
||||
|
||||
hints.flags = MWM_HINTS_DECORATIONS;
|
||||
if (set == True)
|
||||
hints.decorations = 0;
|
||||
else
|
||||
hints.decorations = 1;
|
||||
|
||||
XChangeProperty(m_display, m_window, m_system->m_motif,
|
||||
m_system->m_motif, 32, PropModeReplace,
|
||||
(unsigned char *) &hints, 4);
|
||||
}
|
||||
|
||||
bool GHOST_WindowX11::motifIsFullScreen(void) const
|
||||
{
|
||||
unsigned char *prop_ret;
|
||||
unsigned long bytes_after, num_ret;
|
||||
MotifWmHints *hints;
|
||||
Atom type_ret;
|
||||
bool state;
|
||||
int format_ret, st;
|
||||
|
||||
prop_ret = NULL;
|
||||
state = False;
|
||||
st = XGetWindowProperty(m_display, m_window, m_system->m_motif, 0,
|
||||
0x7fffffff, False, m_system->m_motif,
|
||||
&type_ret, &format_ret, &num_ret,
|
||||
&bytes_after, &prop_ret);
|
||||
if ((st == Success) && (prop_ret)) {
|
||||
hints = (MotifWmHints *) prop_ret;
|
||||
if (hints->flags & MWM_HINTS_DECORATIONS) {
|
||||
if (!hints->decorations)
|
||||
state = True;
|
||||
}
|
||||
}
|
||||
|
||||
if (prop_ret)
|
||||
XFree(prop_ret);
|
||||
return (state);
|
||||
}
|
||||
|
||||
GHOST_TWindowState GHOST_WindowX11::getState() const
|
||||
{
|
||||
GHOST_TWindowState state_ret;
|
||||
int state;
|
||||
|
||||
state_ret = GHOST_kWindowStateNormal;
|
||||
state = icccmGetState();
|
||||
/*
|
||||
* In the Iconic and Withdrawn state, the window
|
||||
* is unmaped, so only need return a Minimized state.
|
||||
*/
|
||||
if ((state == IconicState) || (state == WithdrawnState))
|
||||
state_ret = GHOST_kWindowStateMinimized;
|
||||
else if (netwmIsMaximized() == True)
|
||||
state_ret = GHOST_kWindowStateMaximized;
|
||||
else if (netwmIsFullScreen() == True)
|
||||
state_ret = GHOST_kWindowStateFullScreen;
|
||||
else if (motifIsFullScreen() == True)
|
||||
state_ret = GHOST_kWindowStateFullScreen;
|
||||
return (state_ret);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_WindowX11::setState(GHOST_TWindowState state)
|
||||
{
|
||||
GHOST_TWindowState cur_state;
|
||||
bool is_max, is_full, is_motif_full;
|
||||
|
||||
cur_state = getState();
|
||||
if (state == (int)cur_state)
|
||||
return GHOST_kSuccess;
|
||||
|
||||
if (cur_state != GHOST_kWindowStateMinimized) {
|
||||
/*
|
||||
* The window don't have this property's
|
||||
* if it's not mapped.
|
||||
*/
|
||||
is_max = netwmIsMaximized();
|
||||
is_full = netwmIsFullScreen();
|
||||
}
|
||||
else {
|
||||
is_max = False;
|
||||
is_full = False;
|
||||
}
|
||||
|
||||
is_motif_full = motifIsFullScreen();
|
||||
|
||||
if (state == GHOST_kWindowStateNormal)
|
||||
state = m_normal_state;
|
||||
|
||||
if (state == GHOST_kWindowStateNormal) {
|
||||
if (is_max == True)
|
||||
netwmMaximized(False);
|
||||
if (is_full == True)
|
||||
netwmFullScreen(False);
|
||||
if (is_motif_full == True)
|
||||
motifFullScreen(False);
|
||||
icccmSetState(NormalState);
|
||||
return (GHOST_kSuccess);
|
||||
}
|
||||
|
||||
if (state == GHOST_kWindowStateFullScreen) {
|
||||
/*
|
||||
* We can't change to full screen if the window
|
||||
* isn't mapped.
|
||||
*/
|
||||
if (cur_state == GHOST_kWindowStateMinimized)
|
||||
return (GHOST_kFailure);
|
||||
|
||||
m_normal_state = cur_state;
|
||||
|
||||
if (is_max == True)
|
||||
netwmMaximized(False);
|
||||
if (is_full == False)
|
||||
netwmFullScreen(True);
|
||||
if (is_motif_full == False)
|
||||
motifFullScreen(True);
|
||||
return (GHOST_kSuccess);
|
||||
}
|
||||
|
||||
if (state == GHOST_kWindowStateMaximized) {
|
||||
/*
|
||||
* We can't change to Maximized if the window
|
||||
* isn't mapped.
|
||||
*/
|
||||
if (cur_state == GHOST_kWindowStateMinimized)
|
||||
return (GHOST_kFailure);
|
||||
|
||||
if (is_full == True)
|
||||
netwmFullScreen(False);
|
||||
if (is_motif_full == True)
|
||||
motifFullScreen(False);
|
||||
if (is_max == False)
|
||||
netwmMaximized(True);
|
||||
return (GHOST_kSuccess);
|
||||
}
|
||||
|
||||
if (state == GHOST_kWindowStateMinimized) {
|
||||
/*
|
||||
* The window manager need save the current state of
|
||||
* the window (maximized, full screen, etc).
|
||||
*/
|
||||
icccmSetState(IconicState);
|
||||
return (GHOST_kSuccess);
|
||||
}
|
||||
|
||||
return (GHOST_kFailure);
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
setOrder(
|
||||
GHOST_TWindowOrder order
|
||||
){
|
||||
if (order == GHOST_kWindowOrderTop) {
|
||||
XWindowAttributes attr;
|
||||
Atom atom;
|
||||
|
||||
/* We use both XRaiseWindow and _NET_ACTIVE_WINDOW, since some
|
||||
window managers ignore the former (e.g. kwin from kde) and others
|
||||
don't implement the latter (e.g. fluxbox pre 0.9.9) */
|
||||
|
||||
XRaiseWindow(m_display, m_window);
|
||||
|
||||
atom = XInternAtom(m_display, "_NET_ACTIVE_WINDOW", True);
|
||||
|
||||
if (atom != None) {
|
||||
Window root;
|
||||
XEvent xev;
|
||||
long eventmask;
|
||||
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.serial = 0;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.window = m_window;
|
||||
xev.xclient.message_type = atom;
|
||||
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = 1;
|
||||
xev.xclient.data.l[1] = CurrentTime;
|
||||
xev.xclient.data.l[2] = m_window;
|
||||
xev.xclient.data.l[3] = 0;
|
||||
xev.xclient.data.l[4] = 0;
|
||||
|
||||
root = RootWindow(m_display, m_visual->screen),
|
||||
eventmask = SubstructureRedirectMask | SubstructureNotifyMask;
|
||||
|
||||
XSendEvent(m_display, root, False, eventmask, &xev);
|
||||
}
|
||||
|
||||
XGetWindowAttributes(m_display, m_window, &attr);
|
||||
|
||||
/* iconized windows give bad match error */
|
||||
if (attr.map_state == IsViewable)
|
||||
XSetInputFocus(m_display, m_window, RevertToPointerRoot,
|
||||
CurrentTime);
|
||||
XFlush(m_display);
|
||||
} else if (order == GHOST_kWindowOrderBottom) {
|
||||
XLowerWindow(m_display,m_window);
|
||||
XFlush(m_display);
|
||||
} else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
swapBuffers(
|
||||
){
|
||||
if (getDrawingContextType() == GHOST_kDrawingContextTypeOpenGL) {
|
||||
glXSwapBuffers(m_display,m_window);
|
||||
return GHOST_kSuccess;
|
||||
} else {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
activateDrawingContext(
|
||||
){
|
||||
if (m_context !=NULL) {
|
||||
glXMakeCurrent(m_display, m_window,m_context);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
invalidate(
|
||||
){
|
||||
|
||||
// So the idea of this function is to generate an expose event
|
||||
// for the window.
|
||||
// Unfortunately X does not handle expose events for you and
|
||||
// it is the client's job to refresh the dirty part of the window.
|
||||
// We need to queue up invalidate calls and generate GHOST events
|
||||
// for them in the system.
|
||||
|
||||
// We implement this by setting a boolean in this class to concatenate
|
||||
// all such calls into a single event for this window.
|
||||
|
||||
// At the same time we queue the dirty windows in the system class
|
||||
// and generate events for them at the next processEvents call.
|
||||
|
||||
if (m_invalid_window == false) {
|
||||
m_system->addDirtyWindow(this);
|
||||
m_invalid_window = true;
|
||||
}
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* called by the X11 system implementation when expose events
|
||||
* for the window have been pushed onto the GHOST queue
|
||||
*/
|
||||
|
||||
void
|
||||
GHOST_WindowX11::
|
||||
validate(
|
||||
){
|
||||
m_invalid_window = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* Closes the window and disposes resources allocated.
|
||||
*/
|
||||
|
||||
GHOST_WindowX11::
|
||||
~GHOST_WindowX11(
|
||||
){
|
||||
static Atom Primary_atom, Clipboard_atom;
|
||||
Window p_owner, c_owner;
|
||||
/*Change the owner of the Atoms to None if we are the owner*/
|
||||
Primary_atom = XInternAtom(m_display, "PRIMARY", False);
|
||||
Clipboard_atom = XInternAtom(m_display, "CLIPBOARD", False);
|
||||
|
||||
p_owner = XGetSelectionOwner(m_display, Primary_atom);
|
||||
c_owner = XGetSelectionOwner(m_display, Clipboard_atom);
|
||||
|
||||
std::map<unsigned int, Cursor>::iterator it = m_standard_cursors.begin();
|
||||
for (; it != m_standard_cursors.end(); it++) {
|
||||
XFreeCursor(m_display, it->second);
|
||||
}
|
||||
|
||||
if (m_empty_cursor) {
|
||||
XFreeCursor(m_display, m_empty_cursor);
|
||||
}
|
||||
if (m_custom_cursor) {
|
||||
XFreeCursor(m_display, m_custom_cursor);
|
||||
}
|
||||
|
||||
#ifdef WITH_X11_XINPUT
|
||||
/* close tablet devices */
|
||||
if(m_xtablet.StylusDevice)
|
||||
XCloseDevice(m_display, m_xtablet.StylusDevice);
|
||||
|
||||
if(m_xtablet.EraserDevice)
|
||||
XCloseDevice(m_display, m_xtablet.EraserDevice);
|
||||
#endif /* WITH_X11_XINPUT */
|
||||
|
||||
if (m_context != s_firstContext) {
|
||||
glXDestroyContext(m_display, m_context);
|
||||
}
|
||||
|
||||
if (p_owner == m_window) {
|
||||
XSetSelectionOwner(m_display, Primary_atom, None, CurrentTime);
|
||||
}
|
||||
if (c_owner == m_window) {
|
||||
XSetSelectionOwner(m_display, Clipboard_atom, None, CurrentTime);
|
||||
}
|
||||
|
||||
XDestroyWindow(m_display, m_window);
|
||||
XFree(m_visual);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
installDrawingContext(
|
||||
GHOST_TDrawingContextType type
|
||||
){
|
||||
// only support openGL for now.
|
||||
GHOST_TSuccess success;
|
||||
switch (type) {
|
||||
case GHOST_kDrawingContextTypeOpenGL:
|
||||
m_context = glXCreateContext(m_display, m_visual, s_firstContext, True);
|
||||
if (m_context !=NULL) {
|
||||
if (!s_firstContext) {
|
||||
s_firstContext = m_context;
|
||||
}
|
||||
glXMakeCurrent(m_display, m_window,m_context);
|
||||
success = GHOST_kSuccess;
|
||||
} else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GHOST_kDrawingContextTypeNone:
|
||||
success = GHOST_kSuccess;
|
||||
break;
|
||||
|
||||
default:
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Removes the current drawing context.
|
||||
* @return Indication as to whether removal has succeeded.
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
removeDrawingContext(
|
||||
){
|
||||
GHOST_TSuccess success;
|
||||
|
||||
if (m_context != NULL) {
|
||||
glXDestroyContext(m_display, m_context);
|
||||
success = GHOST_kSuccess;
|
||||
} else {
|
||||
success = GHOST_kFailure;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
Cursor
|
||||
GHOST_WindowX11::
|
||||
getStandardCursor(
|
||||
GHOST_TStandardCursor g_cursor
|
||||
){
|
||||
unsigned int xcursor_id;
|
||||
|
||||
#define GtoX(gcurs, xcurs) case gcurs: xcursor_id = xcurs
|
||||
switch (g_cursor) {
|
||||
GtoX(GHOST_kStandardCursorRightArrow, XC_arrow); break;
|
||||
GtoX(GHOST_kStandardCursorLeftArrow, XC_top_left_arrow); break;
|
||||
GtoX(GHOST_kStandardCursorInfo, XC_hand1); break;
|
||||
GtoX(GHOST_kStandardCursorDestroy, XC_pirate); break;
|
||||
GtoX(GHOST_kStandardCursorHelp, XC_question_arrow); break;
|
||||
GtoX(GHOST_kStandardCursorCycle, XC_exchange); break;
|
||||
GtoX(GHOST_kStandardCursorSpray, XC_spraycan); break;
|
||||
GtoX(GHOST_kStandardCursorWait, XC_watch); break;
|
||||
GtoX(GHOST_kStandardCursorText, XC_xterm); break;
|
||||
GtoX(GHOST_kStandardCursorCrosshair, XC_crosshair); break;
|
||||
GtoX(GHOST_kStandardCursorUpDown, XC_sb_v_double_arrow); break;
|
||||
GtoX(GHOST_kStandardCursorLeftRight, XC_sb_h_double_arrow); break;
|
||||
GtoX(GHOST_kStandardCursorTopSide, XC_top_side); break;
|
||||
GtoX(GHOST_kStandardCursorBottomSide, XC_bottom_side); break;
|
||||
GtoX(GHOST_kStandardCursorLeftSide, XC_left_side); break;
|
||||
GtoX(GHOST_kStandardCursorRightSide, XC_right_side); break;
|
||||
GtoX(GHOST_kStandardCursorTopLeftCorner, XC_top_left_corner); break;
|
||||
GtoX(GHOST_kStandardCursorTopRightCorner, XC_top_right_corner); break;
|
||||
GtoX(GHOST_kStandardCursorBottomRightCorner, XC_bottom_right_corner); break;
|
||||
GtoX(GHOST_kStandardCursorBottomLeftCorner, XC_bottom_left_corner); break;
|
||||
GtoX(GHOST_kStandardCursorPencil, XC_pencil); break;
|
||||
GtoX(GHOST_kStandardCursorCopy, XC_arrow); break;
|
||||
default:
|
||||
xcursor_id = 0;
|
||||
}
|
||||
#undef GtoX
|
||||
|
||||
if (xcursor_id) {
|
||||
Cursor xcursor = m_standard_cursors[xcursor_id];
|
||||
|
||||
if (!xcursor) {
|
||||
xcursor = XCreateFontCursor(m_display, xcursor_id);
|
||||
|
||||
m_standard_cursors[xcursor_id] = xcursor;
|
||||
}
|
||||
|
||||
return xcursor;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
Cursor
|
||||
GHOST_WindowX11::
|
||||
getEmptyCursor(
|
||||
) {
|
||||
if (!m_empty_cursor) {
|
||||
Pixmap blank;
|
||||
XColor dummy;
|
||||
char data[1] = {0};
|
||||
|
||||
/* make a blank cursor */
|
||||
blank = XCreateBitmapFromData (
|
||||
m_display,
|
||||
RootWindow(m_display,DefaultScreen(m_display)),
|
||||
data, 1, 1
|
||||
);
|
||||
|
||||
m_empty_cursor = XCreatePixmapCursor(m_display, blank, blank, &dummy, &dummy, 0, 0);
|
||||
XFreePixmap(m_display, blank);
|
||||
}
|
||||
|
||||
return m_empty_cursor;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
setWindowCursorVisibility(
|
||||
bool visible
|
||||
){
|
||||
Cursor xcursor;
|
||||
|
||||
if (visible) {
|
||||
xcursor = getStandardCursor( getCursorShape() );
|
||||
} else {
|
||||
xcursor = getEmptyCursor();
|
||||
}
|
||||
|
||||
XDefineCursor(m_display, m_window, xcursor);
|
||||
XFlush(m_display);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
setWindowCursorGrab(
|
||||
GHOST_TGrabCursorMode mode
|
||||
){
|
||||
if(mode != GHOST_kGrabDisable) {
|
||||
if(mode != GHOST_kGrabNormal) {
|
||||
m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
|
||||
setCursorGrabAccum(0, 0);
|
||||
|
||||
if(mode == GHOST_kGrabHide)
|
||||
setWindowCursorVisibility(false);
|
||||
|
||||
}
|
||||
#ifdef GHOST_X11_GRAB
|
||||
XGrabPointer(m_display, m_window, False, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (m_cursorGrab==GHOST_kGrabHide) {
|
||||
m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
|
||||
setWindowCursorVisibility(true);
|
||||
}
|
||||
|
||||
if(m_cursorGrab != GHOST_kGrabNormal) {
|
||||
/* use to generate a mouse move event, otherwise the last event
|
||||
* blender gets can be outside the screen causing menus not to show
|
||||
* properly unless the user moves the mouse */
|
||||
XWarpPointer(m_display,None,None,0,0,0,0,0,0);
|
||||
}
|
||||
|
||||
/* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
|
||||
setCursorGrabAccum(0, 0);
|
||||
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */
|
||||
#ifdef GHOST_X11_GRAB
|
||||
XUngrabPointer(m_display, CurrentTime);
|
||||
#endif
|
||||
}
|
||||
|
||||
XFlush(m_display);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
setWindowCursorShape(
|
||||
GHOST_TStandardCursor shape
|
||||
){
|
||||
Cursor xcursor = getStandardCursor( shape );
|
||||
|
||||
XDefineCursor(m_display, m_window, xcursor);
|
||||
XFlush(m_display);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
setWindowCustomCursorShape(
|
||||
GHOST_TUns8 bitmap[16][2],
|
||||
GHOST_TUns8 mask[16][2],
|
||||
int hotX,
|
||||
int hotY
|
||||
){
|
||||
|
||||
setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*)mask,
|
||||
16, 16, hotX, hotY, 0, 1);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess
|
||||
GHOST_WindowX11::
|
||||
setWindowCustomCursorShape(
|
||||
GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask,
|
||||
int sizex,
|
||||
int sizey,
|
||||
int hotX,
|
||||
int hotY,
|
||||
int fg_color,
|
||||
int bg_color
|
||||
){
|
||||
Colormap colormap= DefaultColormap(m_display, DefaultScreen(m_display));
|
||||
Pixmap bitmap_pix, mask_pix;
|
||||
XColor fg, bg;
|
||||
|
||||
if(XAllocNamedColor(m_display, colormap, "White", &fg, &fg) == 0) return GHOST_kFailure;
|
||||
if(XAllocNamedColor(m_display, colormap, "Black", &bg, &bg) == 0) return GHOST_kFailure;
|
||||
|
||||
if (m_custom_cursor) {
|
||||
XFreeCursor(m_display, m_custom_cursor);
|
||||
}
|
||||
|
||||
bitmap_pix = XCreateBitmapFromData(m_display, m_window, (char*) bitmap, sizex, sizey);
|
||||
mask_pix = XCreateBitmapFromData(m_display, m_window, (char*) mask, sizex, sizey);
|
||||
|
||||
m_custom_cursor = XCreatePixmapCursor(m_display, bitmap_pix, mask_pix, &fg, &bg, hotX, hotY);
|
||||
XDefineCursor(m_display, m_window, m_custom_cursor);
|
||||
XFlush(m_display);
|
||||
|
||||
XFreePixmap(m_display, bitmap_pix);
|
||||
XFreePixmap(m_display, mask_pix);
|
||||
|
||||
XFreeColors(m_display, colormap, &fg.pixel, 1, 0L);
|
||||
XFreeColors(m_display, colormap, &bg.pixel, 1, 0L);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
void glutCustomCursor(char *data1, char *data2, int size)
|
||||
{
|
||||
Pixmap source, mask;
|
||||
Cursor cursor;
|
||||
XColor fg, bg;
|
||||
|
||||
if(XAllocNamedColor(__glutDisplay, DefaultColormap(__glutDisplay, __glutScreen),
|
||||
"White", &fg, &fg) == 0) return;
|
||||
if(XAllocNamedColor(__glutDisplay, DefaultColormap(__glutDisplay, __glutScreen),
|
||||
"Red", &bg, &bg) == 0) return;
|
||||
|
||||
|
||||
source= XCreateBitmapFromData(__glutDisplay, xdraw, data2, size, size);
|
||||
mask= XCreateBitmapFromData(__glutDisplay, xdraw, data1, size, size);
|
||||
|
||||
cursor= XCreatePixmapCursor(__glutDisplay, source, mask, &fg, &bg, 7, 7);
|
||||
|
||||
XFreePixmap(__glutDisplay, source);
|
||||
XFreePixmap(__glutDisplay, mask);
|
||||
|
||||
XDefineCursor(__glutDisplay, xdraw, cursor);
|
||||
}
|
||||
|
||||
*/
|
||||
370
intern/ghost/intern/GHOST_WindowX11.h
Normal file
370
intern/ghost/intern/GHOST_WindowX11.h
Normal file
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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/intern/GHOST_WindowX11.h
|
||||
* \ingroup GHOST
|
||||
* Declaration of GHOST_WindowX11 class.
|
||||
*/
|
||||
|
||||
#ifndef _GHOST_WINDOWX11_H_
|
||||
#define _GHOST_WINDOWX11_H_
|
||||
|
||||
#include "GHOST_Window.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <GL/glx.h>
|
||||
// For tablets
|
||||
#include <X11/extensions/XInput.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
class STR_String;
|
||||
class GHOST_SystemX11;
|
||||
|
||||
/**
|
||||
* X11 implementation of GHOST_IWindow.
|
||||
* Dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
|
||||
* @author Laurence Bourn
|
||||
* @date October 26, 2001
|
||||
*/
|
||||
|
||||
class GHOST_WindowX11 : 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 parentWindow Parent (embedder) window
|
||||
* @param type The type of drawing context installed in this window.
|
||||
* @param stereoVisual Stereo visual for quad buffered stereo.
|
||||
* @param numOfAASamples Number of samples used for AA (zero if no AA)
|
||||
*/
|
||||
GHOST_WindowX11(
|
||||
GHOST_SystemX11 *system,
|
||||
Display * display,
|
||||
const STR_String& title,
|
||||
GHOST_TInt32 left,
|
||||
GHOST_TInt32 top,
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height,
|
||||
GHOST_TWindowState state,
|
||||
const GHOST_TEmbedderWindowID parentWindow,
|
||||
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
|
||||
const bool stereoVisual = false,
|
||||
const GHOST_TUns16 numOfAASamples = 0
|
||||
);
|
||||
|
||||
bool
|
||||
getValid(
|
||||
) const;
|
||||
|
||||
void
|
||||
setTitle(const STR_String& title);
|
||||
|
||||
void
|
||||
getTitle(
|
||||
STR_String& title
|
||||
) const;
|
||||
|
||||
void
|
||||
getWindowBounds(
|
||||
GHOST_Rect& bounds
|
||||
) const;
|
||||
|
||||
void
|
||||
getClientBounds(
|
||||
GHOST_Rect& bounds
|
||||
) const;
|
||||
|
||||
GHOST_TSuccess
|
||||
setClientWidth(
|
||||
GHOST_TUns32 width
|
||||
);
|
||||
|
||||
GHOST_TSuccess
|
||||
setClientHeight(
|
||||
GHOST_TUns32 height
|
||||
);
|
||||
|
||||
GHOST_TSuccess
|
||||
setClientSize(
|
||||
GHOST_TUns32 width,
|
||||
GHOST_TUns32 height
|
||||
);
|
||||
|
||||
void
|
||||
screenToClient(
|
||||
GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32& outX,
|
||||
GHOST_TInt32& outY
|
||||
) const;
|
||||
|
||||
void
|
||||
clientToScreen(
|
||||
GHOST_TInt32 inX,
|
||||
GHOST_TInt32 inY,
|
||||
GHOST_TInt32& outX,
|
||||
GHOST_TInt32& outY
|
||||
) const;
|
||||
|
||||
GHOST_TWindowState
|
||||
getState(
|
||||
) const ;
|
||||
|
||||
GHOST_TSuccess
|
||||
setState(
|
||||
GHOST_TWindowState state
|
||||
);
|
||||
|
||||
GHOST_TSuccess
|
||||
setOrder(
|
||||
GHOST_TWindowOrder order
|
||||
);
|
||||
|
||||
GHOST_TSuccess
|
||||
swapBuffers(
|
||||
);
|
||||
|
||||
GHOST_TSuccess
|
||||
activateDrawingContext(
|
||||
);
|
||||
GHOST_TSuccess
|
||||
invalidate(
|
||||
);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
* Closes the window and disposes resources allocated.
|
||||
*/
|
||||
~GHOST_WindowX11();
|
||||
|
||||
/**
|
||||
* @section x11specific X11 system specific calls
|
||||
*/
|
||||
|
||||
/**
|
||||
* The reverse of invalidate! Tells this window
|
||||
* that all events for it have been pushed into
|
||||
* the GHOST event queue.
|
||||
*/
|
||||
|
||||
void
|
||||
validate(
|
||||
);
|
||||
|
||||
/**
|
||||
* Return a handle to the x11 window type.
|
||||
*/
|
||||
Window
|
||||
getXWindow(
|
||||
);
|
||||
|
||||
class XTablet
|
||||
{
|
||||
public:
|
||||
GHOST_TabletData CommonData;
|
||||
|
||||
XDevice* StylusDevice;
|
||||
XDevice* EraserDevice;
|
||||
|
||||
XID StylusID, EraserID;
|
||||
|
||||
int MotionEvent;
|
||||
int ProxInEvent;
|
||||
int ProxOutEvent;
|
||||
|
||||
int PressureLevels;
|
||||
int XtiltLevels, YtiltLevels;
|
||||
};
|
||||
|
||||
XTablet& GetXTablet()
|
||||
{ return m_xtablet; }
|
||||
|
||||
const GHOST_TabletData* GetTabletData()
|
||||
{ return &m_xtablet.CommonData; }
|
||||
|
||||
/*
|
||||
* Need this in case that we want start the window
|
||||
* in FullScree or Maximized state.
|
||||
* Check GHOST_WindowX11.cpp
|
||||
*/
|
||||
bool m_post_init;
|
||||
GHOST_TWindowState m_post_state;
|
||||
|
||||
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.
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
installDrawingContext(
|
||||
GHOST_TDrawingContextType type
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes the current drawing context.
|
||||
* @return Indication as to whether removal has succeeded.
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
removeDrawingContext(
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the cursor visibility on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
setWindowCursorVisibility(
|
||||
bool visible
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the cursor grab on the window using
|
||||
* native window system calls.
|
||||
* @param warp Only used when grab is enabled, hides the mouse and allows gragging outside the screen.
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
setWindowCursorGrab(
|
||||
GHOST_TGrabCursorMode mode
|
||||
);
|
||||
|
||||
GHOST_TGrabCursorMode
|
||||
getWindowCursorGrab() const;
|
||||
|
||||
/**
|
||||
* Sets the cursor shape on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
setWindowCursorShape(
|
||||
GHOST_TStandardCursor shape
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the cursor shape on the window using
|
||||
* native window system calls.
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
setWindowCustomCursorShape(
|
||||
GHOST_TUns8 bitmap[16][2],
|
||||
GHOST_TUns8 mask[16][2],
|
||||
int hotX,
|
||||
int hotY
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the cursor shape on the window using
|
||||
* native window system calls (Arbitrary size/color).
|
||||
*/
|
||||
GHOST_TSuccess
|
||||
setWindowCustomCursorShape(
|
||||
GHOST_TUns8 *bitmap,
|
||||
GHOST_TUns8 *mask,
|
||||
int sizex,
|
||||
int sizey,
|
||||
int hotX,
|
||||
int hotY,
|
||||
int fg_color,
|
||||
int bg_color
|
||||
);
|
||||
|
||||
private :
|
||||
|
||||
/// Force use of public constructor.
|
||||
|
||||
GHOST_WindowX11(
|
||||
);
|
||||
|
||||
GHOST_WindowX11(
|
||||
const GHOST_WindowX11 &
|
||||
);
|
||||
|
||||
Cursor
|
||||
getStandardCursor(
|
||||
GHOST_TStandardCursor g_cursor
|
||||
);
|
||||
|
||||
Cursor
|
||||
getEmptyCursor(
|
||||
);
|
||||
|
||||
void initXInputDevices();
|
||||
|
||||
GLXContext m_context;
|
||||
Window m_window;
|
||||
Display *m_display;
|
||||
XVisualInfo *m_visual;
|
||||
GHOST_TWindowState m_normal_state;
|
||||
|
||||
/** The first created OpenGL context (for sharing display lists) */
|
||||
static GLXContext s_firstContext;
|
||||
|
||||
/// A pointer to the typed system class.
|
||||
|
||||
GHOST_SystemX11 * m_system;
|
||||
|
||||
bool m_valid_setup;
|
||||
|
||||
/** Used to concatenate calls to invalidate() on this window. */
|
||||
bool m_invalid_window;
|
||||
|
||||
/** XCursor structure of an empty (blank) cursor */
|
||||
Cursor m_empty_cursor;
|
||||
|
||||
/** XCursor structure of the custom cursor */
|
||||
Cursor m_custom_cursor;
|
||||
|
||||
/** Cache of XC_* ID's to XCursor structures */
|
||||
std::map<unsigned int, Cursor> m_standard_cursors;
|
||||
|
||||
/* Tablet devices */
|
||||
XTablet m_xtablet;
|
||||
|
||||
void icccmSetState(int state);
|
||||
int icccmGetState() const;
|
||||
|
||||
void netwmMaximized(bool set);
|
||||
bool netwmIsMaximized() const;
|
||||
|
||||
void netwmFullScreen(bool set);
|
||||
bool netwmIsFullScreen() const;
|
||||
|
||||
void motifFullScreen(bool set);
|
||||
bool motifIsFullScreen() const;
|
||||
};
|
||||
|
||||
|
||||
#endif // _GHOST_WINDOWX11_H_
|
||||
557
intern/ghost/test/gears/GHOST_C-Test.c
Normal file
557
intern/ghost/test/gears/GHOST_C-Test.c
Normal file
@@ -0,0 +1,557 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
*
|
||||
* Simple test file for the GHOST library.
|
||||
* The OpenGL gear code is taken from the Qt sample code which,
|
||||
* in turn, is probably taken from somewhere as well.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 31, 2001
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define FALSE 0
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
|
||||
#if defined(WIN32) || defined(__APPLE__)
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#else /* WIN32 */
|
||||
/* __APPLE__ is defined */
|
||||
#include <AGL/gl.h>
|
||||
#endif /* WIN32 */
|
||||
#else /* defined(WIN32) || defined(__APPLE__) */
|
||||
#include <GL/gl.h>
|
||||
#endif /* defined(WIN32) || defined(__APPLE__) */
|
||||
|
||||
|
||||
static void gearsTimerProc(GHOST_TimerTaskHandle task, GHOST_TUns64 time);
|
||||
int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData);
|
||||
|
||||
static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0;
|
||||
static GLfloat fAngle = 0.0;
|
||||
static int sExitRequested = 0;
|
||||
static GHOST_SystemHandle shSystem = NULL;
|
||||
static GHOST_WindowHandle sMainWindow = NULL;
|
||||
static GHOST_WindowHandle sSecondaryWindow = NULL;
|
||||
static GHOST_TStandardCursor sCursor = GHOST_kStandardCursorFirstCursor;
|
||||
static GHOST_WindowHandle sFullScreenWindow = NULL;
|
||||
static GHOST_TimerTaskHandle sTestTimer;
|
||||
static GHOST_TimerTaskHandle sGearsTimer;
|
||||
|
||||
static void testTimerProc(GHOST_TimerTaskHandle task, GHOST_TUns64 time)
|
||||
{
|
||||
printf("timer1, time=%d\n", (int)time);
|
||||
}
|
||||
|
||||
|
||||
static void gearGL(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth)
|
||||
{
|
||||
GLint i;
|
||||
GLfloat r0, r1, r2;
|
||||
GLfloat angle, da;
|
||||
GLfloat u, v, len;
|
||||
const double pi = 3.14159264;
|
||||
|
||||
r0 = inner_radius;
|
||||
r1 = (float)(outer_radius - tooth_depth/2.0);
|
||||
r2 = (float)(outer_radius + tooth_depth/2.0);
|
||||
|
||||
da = (float)(2.0*pi / teeth / 4.0);
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
glNormal3f(0.0, 0.0, 1.0);
|
||||
|
||||
/* draw front face */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i=0;i<=teeth;i++) {
|
||||
angle = (float)(i * 2.0*pi / teeth);
|
||||
glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(width*0.5));
|
||||
glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(width*0.5));
|
||||
glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(width*0.5));
|
||||
glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(width*0.5));
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw front sides of teeth */
|
||||
glBegin(GL_QUADS);
|
||||
da = (float)(2.0*pi / teeth / 4.0);
|
||||
for (i=0;i<teeth;i++) {
|
||||
angle = (float)(i * 2.0*pi / teeth);
|
||||
glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(width*0.5));
|
||||
glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(width*0.5));
|
||||
glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(width*0.5));
|
||||
glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(width*0.5));
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glNormal3f(0.0, 0.0, -1.0);
|
||||
|
||||
/* draw back face */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i=0;i<=teeth;i++) {
|
||||
angle = (float)(i * 2.0*pi / teeth);
|
||||
glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(-width*0.5));
|
||||
glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(-width*0.5));
|
||||
glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(-width*0.5));
|
||||
glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(-width*0.5));
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw back sides of teeth */
|
||||
glBegin(GL_QUADS);
|
||||
da = (float)(2.0*pi / teeth / 4.0);
|
||||
for (i=0;i<teeth;i++) {
|
||||
angle = (float)(i * 2.0*pi / teeth);
|
||||
glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(-width*0.5));
|
||||
glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(-width*0.5));
|
||||
glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(-width*0.5));
|
||||
glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(-width*0.5));
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw outward faces of teeth */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i=0;i<teeth;i++) {
|
||||
angle = (float)(i * 2.0*pi / teeth);
|
||||
glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(width*0.5));
|
||||
glVertex3f((float)(r1*cos(angle)), (float)(r1*sin(angle)), (float)(-width*0.5));
|
||||
u = (float)(r2*cos(angle+da) - r1*cos(angle));
|
||||
v = (float)(r2*sin(angle+da) - r1*sin(angle));
|
||||
len = (float)(sqrt(u*u + v*v));
|
||||
u /= len;
|
||||
v /= len;
|
||||
glNormal3f(v, -u, 0.0);
|
||||
glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(width*0.5));
|
||||
glVertex3f((float)(r2*cos(angle+da)), (float)(r2*sin(angle+da)), (float)(-width*0.5));
|
||||
glNormal3f((float)(cos(angle)), (float)(sin(angle)), 0.0);
|
||||
glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(width*0.5));
|
||||
glVertex3f((float)(r2*cos(angle+2*da)), (float)(r2*sin(angle+2*da)), (float)(-width*0.5));
|
||||
u = (float)(r1*cos(angle+3*da) - r2*cos(angle+2*da));
|
||||
v = (float)(r1*sin(angle+3*da) - r2*sin(angle+2*da));
|
||||
glNormal3f(v, -u, 0.0);
|
||||
glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(width*0.5));
|
||||
glVertex3f((float)(r1*cos(angle+3*da)), (float)(r1*sin(angle+3*da)), (float)(-width*0.5));
|
||||
glNormal3f((float)(cos(angle)), (float)(sin(angle)), 0.0);
|
||||
}
|
||||
glVertex3f((float)(r1*cos(0.0)), (float)(r1*sin(0.0)), (float)(width*0.5));
|
||||
glVertex3f((float)(r1*cos(0.0)), (float)(r1*sin(0.0)), (float)(-width*0.5));
|
||||
glEnd();
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
/* draw inside radius cylinder */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i=0;i<=teeth;i++) {
|
||||
angle = (float)(i * 2.0*pi / teeth);
|
||||
glNormal3f((float)(-cos(angle)), (float)(-sin(angle)), 0.0);
|
||||
glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(-width*0.5));
|
||||
glVertex3f((float)(r0*cos(angle)), (float)(r0*sin(angle)), (float)(width*0.5));
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void drawGearGL(int id)
|
||||
{
|
||||
static GLfloat pos[4] = { 5.0f, 5.0f, 10.0f, 1.0f };
|
||||
static GLfloat ared[4] = { 0.8f, 0.1f, 0.0f, 1.0f };
|
||||
static GLfloat agreen[4] = { 0.0f, 0.8f, 0.2f, 1.0f };
|
||||
static GLfloat ablue[4] = { 0.2f, 0.2f, 1.0f, 1.0f };
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case 1:
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared);
|
||||
gearGL(1.0f, 4.0f, 1.0f, 20, 0.7f);
|
||||
break;
|
||||
case 2:
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen);
|
||||
gearGL(0.5f, 2.0f, 2.0f, 10, 0.7f);
|
||||
break;
|
||||
case 3:
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue);
|
||||
gearGL(1.3f, 2.0f, 0.5f, 10, 0.7f);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
glEnable(GL_NORMALIZE);
|
||||
}
|
||||
|
||||
|
||||
static void drawGL(void)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
glRotatef(view_rotx, 1.0, 0.0, 0.0);
|
||||
glRotatef(view_roty, 0.0, 1.0, 0.0);
|
||||
glRotatef(view_rotz, 0.0, 0.0, 1.0);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.0, -2.0, 0.0);
|
||||
glRotatef(fAngle, 0.0, 0.0, 1.0);
|
||||
drawGearGL(1);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(3.1f, -2.0f, 0.0f);
|
||||
glRotatef((float)(-2.0*fAngle-9.0), 0.0, 0.0, 1.0);
|
||||
drawGearGL(2);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.1f, 2.2f, -1.8f);
|
||||
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
|
||||
glRotatef((float)(2.0*fAngle-2.0), 0.0, 0.0, 1.0);
|
||||
drawGearGL(3);
|
||||
glPopMatrix();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
static void setViewPortGL(GHOST_WindowHandle hWindow)
|
||||
{
|
||||
GHOST_RectangleHandle hRect = NULL;
|
||||
GLfloat w, h;
|
||||
|
||||
GHOST_ActivateWindowDrawingContext(hWindow);
|
||||
hRect = GHOST_GetClientBounds(hWindow);
|
||||
|
||||
w = (float)GHOST_GetWidthRectangle(hRect) / (float)GHOST_GetHeightRectangle(hRect);
|
||||
h = 1.0;
|
||||
|
||||
glViewport(0, 0, GHOST_GetWidthRectangle(hRect), GHOST_GetHeightRectangle(hRect));
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum(-w, w, -h, h, 5.0, 60.0);
|
||||
/* glOrtho(0, bnds.getWidth(), 0, bnds.getHeight(), -10, 10); */
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -40.0);
|
||||
|
||||
glClearColor(.2f,0.0f,0.0f,0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
GHOST_DisposeRectangle(hRect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int processEvent(GHOST_EventHandle hEvent, GHOST_TUserDataPtr userData)
|
||||
{
|
||||
int handled = 1;
|
||||
int cursor;
|
||||
int visibility;
|
||||
GHOST_TEventKeyData* keyData = NULL;
|
||||
GHOST_TEventWheelData* wheelData = NULL;
|
||||
GHOST_DisplaySetting setting;
|
||||
GHOST_WindowHandle window = GHOST_GetEventWindow(hEvent);
|
||||
|
||||
switch (GHOST_GetEventType(hEvent))
|
||||
{
|
||||
/*
|
||||
case GHOST_kEventUnknown:
|
||||
break;
|
||||
case GHOST_kEventCursorButton:
|
||||
break;
|
||||
case GHOST_kEventCursorMove:
|
||||
break;
|
||||
*/
|
||||
case GHOST_kEventWheel:
|
||||
{
|
||||
wheelData = (GHOST_TEventWheelData*)GHOST_GetEventData(hEvent);
|
||||
if (wheelData->z > 0)
|
||||
{
|
||||
view_rotz += 5.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
view_rotz -= 5.f;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventKeyUp:
|
||||
break;
|
||||
|
||||
case GHOST_kEventKeyDown:
|
||||
{
|
||||
keyData = (GHOST_TEventKeyData*)GHOST_GetEventData(hEvent);
|
||||
switch (keyData->key)
|
||||
{
|
||||
case GHOST_kKeyC:
|
||||
{
|
||||
cursor = sCursor;
|
||||
cursor++;
|
||||
if (cursor >= GHOST_kStandardCursorNumCursors)
|
||||
{
|
||||
cursor = GHOST_kStandardCursorFirstCursor;
|
||||
}
|
||||
sCursor = (GHOST_TStandardCursor)cursor;
|
||||
GHOST_SetCursorShape(window, sCursor);
|
||||
}
|
||||
break;
|
||||
case GHOST_kKeyF:
|
||||
if (!GHOST_GetFullScreen(shSystem))
|
||||
{
|
||||
/* Begin fullscreen mode */
|
||||
setting.bpp = 24;
|
||||
setting.frequency = 85;
|
||||
setting.xPixels = 640;
|
||||
setting.yPixels = 480;
|
||||
|
||||
/*
|
||||
setting.bpp = 16;
|
||||
setting.frequency = 75;
|
||||
setting.xPixels = 640;
|
||||
setting.yPixels = 480;
|
||||
*/
|
||||
|
||||
sFullScreenWindow = GHOST_BeginFullScreen(shSystem, &setting,
|
||||
|
||||
FALSE /* stereo flag */);
|
||||
}
|
||||
else
|
||||
{
|
||||
GHOST_EndFullScreen(shSystem);
|
||||
sFullScreenWindow = 0;
|
||||
}
|
||||
break;
|
||||
case GHOST_kKeyH:
|
||||
{
|
||||
visibility = GHOST_GetCursorVisibility(window);
|
||||
GHOST_SetCursorVisibility(window, !visibility);
|
||||
}
|
||||
break;
|
||||
case GHOST_kKeyQ:
|
||||
if (GHOST_GetFullScreen(shSystem))
|
||||
{
|
||||
GHOST_EndFullScreen(shSystem);
|
||||
sFullScreenWindow = 0;
|
||||
}
|
||||
sExitRequested = 1;
|
||||
case GHOST_kKeyT:
|
||||
if (!sTestTimer)
|
||||
{
|
||||
sTestTimer = GHOST_InstallTimer(shSystem, 0, 1000, testTimerProc, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
GHOST_RemoveTimer(shSystem, sTestTimer);
|
||||
sTestTimer = 0;
|
||||
}
|
||||
break;
|
||||
case GHOST_kKeyW:
|
||||
{
|
||||
if (sMainWindow)
|
||||
{
|
||||
char *title = GHOST_GetTitle(sMainWindow);
|
||||
char *ntitle = malloc(strlen(title)+2);
|
||||
|
||||
sprintf(ntitle, "%s-", title);
|
||||
GHOST_SetTitle(sMainWindow, ntitle);
|
||||
|
||||
free(ntitle);
|
||||
free(title);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventWindowClose:
|
||||
{
|
||||
GHOST_WindowHandle window2 = GHOST_GetEventWindow(hEvent);
|
||||
if (window2 == sMainWindow)
|
||||
{
|
||||
sExitRequested = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sGearsTimer)
|
||||
{
|
||||
GHOST_RemoveTimer(shSystem, sGearsTimer);
|
||||
sGearsTimer = 0;
|
||||
}
|
||||
GHOST_DisposeWindow(shSystem, window2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventWindowActivate:
|
||||
handled = 0;
|
||||
break;
|
||||
case GHOST_kEventWindowDeactivate:
|
||||
handled = 0;
|
||||
break;
|
||||
case GHOST_kEventWindowUpdate:
|
||||
{
|
||||
GHOST_WindowHandle window2 = GHOST_GetEventWindow(hEvent);
|
||||
if (!GHOST_ValidWindow(shSystem, window2))
|
||||
break;
|
||||
setViewPortGL(window2);
|
||||
drawGL();
|
||||
GHOST_SwapWindowBuffers(window2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
handled = 0;
|
||||
break;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
char* title1 = "gears - main window";
|
||||
char* title2 = "gears - secondary window";
|
||||
GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(processEvent, NULL);
|
||||
|
||||
/* Create the system */
|
||||
shSystem = GHOST_CreateSystem();
|
||||
GHOST_AddEventConsumer(shSystem, consumer);
|
||||
|
||||
if (shSystem)
|
||||
{
|
||||
/* Create the main window */
|
||||
sMainWindow = GHOST_CreateWindow(shSystem,
|
||||
title1,
|
||||
10,
|
||||
64,
|
||||
320,
|
||||
200,
|
||||
GHOST_kWindowStateNormal,
|
||||
GHOST_kDrawingContextTypeOpenGL,
|
||||
FALSE);
|
||||
if (!sMainWindow)
|
||||
{
|
||||
printf("could not create main window\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Create a secondary window */
|
||||
sSecondaryWindow = GHOST_CreateWindow(shSystem,
|
||||
title2,
|
||||
340,
|
||||
64,
|
||||
320,
|
||||
200,
|
||||
GHOST_kWindowStateNormal,
|
||||
GHOST_kDrawingContextTypeOpenGL,
|
||||
FALSE);
|
||||
if (!sSecondaryWindow)
|
||||
{
|
||||
printf("could not create secondary window\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Install a timer to have the gears running */
|
||||
sGearsTimer = GHOST_InstallTimer(shSystem,
|
||||
0,
|
||||
10,
|
||||
gearsTimerProc,
|
||||
sMainWindow);
|
||||
|
||||
/* Enter main loop */
|
||||
while (!sExitRequested)
|
||||
{
|
||||
if (!GHOST_ProcessEvents(shSystem, 0))
|
||||
{
|
||||
#ifdef WIN32
|
||||
/* If there were no events, be nice to other applications */
|
||||
Sleep(10);
|
||||
#endif
|
||||
}
|
||||
GHOST_DispatchEvents(shSystem);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dispose windows */
|
||||
if (GHOST_ValidWindow(shSystem, sMainWindow))
|
||||
{
|
||||
GHOST_DisposeWindow(shSystem, sMainWindow);
|
||||
}
|
||||
if (GHOST_ValidWindow(shSystem, sSecondaryWindow))
|
||||
{
|
||||
GHOST_DisposeWindow(shSystem, sSecondaryWindow);
|
||||
}
|
||||
|
||||
/* Dispose the system */
|
||||
GHOST_DisposeSystem(shSystem);
|
||||
GHOST_DisposeEventConsumer(consumer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void gearsTimerProc(GHOST_TimerTaskHandle hTask, GHOST_TUns64 time)
|
||||
{
|
||||
GHOST_WindowHandle hWindow = NULL;
|
||||
fAngle += 2.0;
|
||||
view_roty += 1.0;
|
||||
hWindow = (GHOST_WindowHandle)GHOST_GetTimerTaskUserData(hTask);
|
||||
if (GHOST_GetFullScreen(shSystem))
|
||||
{
|
||||
/* Running full screen */
|
||||
GHOST_InvalidateWindow(sFullScreenWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GHOST_ValidWindow(shSystem, hWindow))
|
||||
{
|
||||
GHOST_InvalidateWindow(hWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
754
intern/ghost/test/gears/GHOST_Test.cpp
Normal file
754
intern/ghost/test/gears/GHOST_Test.cpp
Normal file
@@ -0,0 +1,754 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* Simple test file for the GHOST library.
|
||||
* The OpenGL gear code is taken from the Qt sample code which,
|
||||
* in turn, is probably taken from somewhere as well.
|
||||
* @author Maarten Gribnau
|
||||
* @date May 31, 2001
|
||||
* Stereo code by Raymond de Vries, januari 2002
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
#if defined(WIN32) || defined(__APPLE__)
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <atlbase.h>
|
||||
|
||||
#include <GL/gl.h>
|
||||
#else // WIN32
|
||||
// __APPLE__ is defined
|
||||
#include <AGL/gl.h>
|
||||
#endif // WIN32
|
||||
#else // defined(WIN32) || defined(__APPLE__)
|
||||
#include <GL/gl.h>
|
||||
#endif // defined(WIN32) || defined(__APPLE__)
|
||||
|
||||
#include "STR_String.h"
|
||||
#include "GHOST_Rect.h"
|
||||
|
||||
#include "GHOST_ISystem.h"
|
||||
#include "GHOST_IEvent.h"
|
||||
#include "GHOST_IEventConsumer.h"
|
||||
|
||||
|
||||
#define LEFT_EYE 0
|
||||
#define RIGHT_EYE 1
|
||||
|
||||
static bool nVidiaWindows; // very dirty but hey, it's for testing only
|
||||
|
||||
static void gearsTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time);
|
||||
|
||||
static class Application* fApp;
|
||||
static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0;
|
||||
static GLfloat fAngle = 0.0;
|
||||
static GHOST_ISystem* fSystem = 0;
|
||||
|
||||
|
||||
void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane,
|
||||
float zero_plane, float dist,
|
||||
float eye);
|
||||
|
||||
|
||||
static void testTimerProc(GHOST_ITimerTask* /*task*/, GHOST_TUns64 time)
|
||||
{
|
||||
std::cout << "timer1, time=" << (int)time << "\n";
|
||||
}
|
||||
|
||||
|
||||
static void gearGL(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, GLint teeth, GLfloat tooth_depth)
|
||||
{
|
||||
GLint i;
|
||||
GLfloat r0, r1, r2;
|
||||
GLfloat angle, da;
|
||||
GLfloat u, v, len;
|
||||
|
||||
r0 = inner_radius;
|
||||
r1 = outer_radius - tooth_depth/2.0;
|
||||
r2 = outer_radius + tooth_depth/2.0;
|
||||
|
||||
const double pi = 3.14159264;
|
||||
da = 2.0*pi / teeth / 4.0;
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
glNormal3f(0.0, 0.0, 1.0);
|
||||
|
||||
/* draw front face */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i=0;i<=teeth;i++) {
|
||||
angle = i * 2.0*pi / teeth;
|
||||
glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5);
|
||||
glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5);
|
||||
glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5);
|
||||
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw front sides of teeth */
|
||||
glBegin(GL_QUADS);
|
||||
da = 2.0*pi / teeth / 4.0;
|
||||
for (i=0;i<teeth;i++) {
|
||||
angle = i * 2.0*pi / teeth;
|
||||
glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5);
|
||||
glVertex3f(r2*cos(angle+da), r2*sin(angle+da), width*0.5);
|
||||
glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5);
|
||||
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glNormal3f(0.0, 0.0, -1.0);
|
||||
|
||||
/* draw back face */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i=0;i<=teeth;i++) {
|
||||
angle = i * 2.0*pi / teeth;
|
||||
glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5);
|
||||
glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5);
|
||||
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5);
|
||||
glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw back sides of teeth */
|
||||
glBegin(GL_QUADS);
|
||||
da = 2.0*pi / teeth / 4.0;
|
||||
for (i=0;i<teeth;i++) {
|
||||
angle = i * 2.0*pi / teeth;
|
||||
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5);
|
||||
glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5);
|
||||
glVertex3f(r2*cos(angle+da), r2*sin(angle+da), -width*0.5);
|
||||
glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
/* draw outward faces of teeth */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i=0;i<teeth;i++) {
|
||||
angle = i * 2.0*pi / teeth;
|
||||
glVertex3f(r1*cos(angle), r1*sin(angle), width*0.5);
|
||||
glVertex3f(r1*cos(angle), r1*sin(angle), -width*0.5);
|
||||
u = r2*cos(angle+da) - r1*cos(angle);
|
||||
v = r2*sin(angle+da) - r1*sin(angle);
|
||||
len = sqrt(u*u + v*v);
|
||||
u /= len;
|
||||
v /= len;
|
||||
glNormal3f(v, -u, 0.0);
|
||||
glVertex3f(r2*cos(angle+da), r2*sin(angle+da), width*0.5);
|
||||
glVertex3f(r2*cos(angle+da), r2*sin(angle+da), -width*0.5);
|
||||
glNormal3f(cos(angle), sin(angle), 0.0);
|
||||
glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5);
|
||||
glVertex3f(r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5);
|
||||
u = r1*cos(angle+3*da) - r2*cos(angle+2*da);
|
||||
v = r1*sin(angle+3*da) - r2*sin(angle+2*da);
|
||||
glNormal3f(v, -u, 0.0);
|
||||
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5);
|
||||
glVertex3f(r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5);
|
||||
glNormal3f(cos(angle), sin(angle), 0.0);
|
||||
}
|
||||
glVertex3f(r1*cos(0.0), r1*sin(0.0), width*0.5);
|
||||
glVertex3f(r1*cos(0.0), r1*sin(0.0), -width*0.5);
|
||||
glEnd();
|
||||
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
/* draw inside radius cylinder */
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
for (i=0;i<=teeth;i++) {
|
||||
angle = i * 2.0*pi / teeth;
|
||||
glNormal3f(-cos(angle), -sin(angle), 0.0);
|
||||
glVertex3f(r0*cos(angle), r0*sin(angle), -width*0.5);
|
||||
glVertex3f(r0*cos(angle), r0*sin(angle), width*0.5);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void drawGearGL(int id)
|
||||
{
|
||||
static GLfloat pos[4] = { 5.0f, 5.0f, 10.0f, 1.0f };
|
||||
static GLfloat ared[4] = { 0.8f, 0.1f, 0.0f, 1.0f };
|
||||
static GLfloat agreen[4] = { 0.0f, 0.8f, 0.2f, 1.0f };
|
||||
static GLfloat ablue[4] = { 0.2f, 0.2f, 1.0f, 1.0f };
|
||||
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, pos);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case 1:
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared);
|
||||
gearGL(1.0f, 4.0f, 1.0f, 20, 0.7f);
|
||||
break;
|
||||
case 2:
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen);
|
||||
gearGL(0.5f, 2.0f, 2.0f, 10, 0.7f);
|
||||
break;
|
||||
case 3:
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue);
|
||||
gearGL(1.3f, 2.0f, 0.5f, 10, 0.7f);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
glEnable(GL_NORMALIZE);
|
||||
}
|
||||
|
||||
|
||||
void RenderCamera()
|
||||
{
|
||||
glRotatef(view_rotx, 1.0, 0.0, 0.0);
|
||||
glRotatef(view_roty, 0.0, 1.0, 0.0);
|
||||
glRotatef(view_rotz, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
void RenderScene()
|
||||
{
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.0, -2.0, 0.0);
|
||||
glRotatef(fAngle, 0.0, 0.0, 1.0);
|
||||
drawGearGL(1);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(3.1f, -2.0f, 0.0f);
|
||||
glRotatef(-2.0 * fAngle - 9.0, 0.0, 0.0, 1.0);
|
||||
drawGearGL(2);
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.1f, 2.2f, -1.8f);
|
||||
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
|
||||
glRotatef(2.0 * fAngle - 2.0, 0.0, 0.0, 1.0);
|
||||
drawGearGL(3);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
static void View(GHOST_IWindow* window, bool stereo, int eye = 0)
|
||||
{
|
||||
window->activateDrawingContext();
|
||||
GHOST_Rect bnds;
|
||||
int noOfScanlines = 0, lowerScanline = 0;
|
||||
int verticalBlankingInterval = 32; // hard coded for testing purposes, display device dependant
|
||||
float left, right, bottom, top;
|
||||
float nearplane, farplane, zeroPlane, distance;
|
||||
float eyeSeparation = 0.62f;
|
||||
window->getClientBounds(bnds);
|
||||
|
||||
// viewport
|
||||
if(stereo)
|
||||
{
|
||||
if(nVidiaWindows)
|
||||
{
|
||||
// handled by nVidia driver so act as normal (explicitly put here since
|
||||
// it -is- stereo)
|
||||
glViewport(0, 0, bnds.getWidth(), bnds.getHeight());
|
||||
}
|
||||
else
|
||||
{ // generic cross platform above-below stereo
|
||||
noOfScanlines = (bnds.getHeight() - verticalBlankingInterval) / 2;
|
||||
switch(eye)
|
||||
{
|
||||
case LEFT_EYE:
|
||||
// upper half of window
|
||||
lowerScanline = bnds.getHeight() - noOfScanlines;
|
||||
break;
|
||||
case RIGHT_EYE:
|
||||
// lower half of window
|
||||
lowerScanline = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
noOfScanlines = bnds.getHeight();
|
||||
lowerScanline = 0;
|
||||
}
|
||||
|
||||
glViewport(0, lowerScanline, bnds.getWidth(), noOfScanlines);
|
||||
|
||||
// projection
|
||||
left = -6.0;
|
||||
right = 6.0;
|
||||
bottom = -4.8f;
|
||||
top = 4.8f;
|
||||
nearplane = 5.0;
|
||||
farplane = 60.0;
|
||||
|
||||
if(stereo)
|
||||
{
|
||||
zeroPlane = 0.0;
|
||||
distance = 14.5;
|
||||
switch(eye)
|
||||
{
|
||||
case LEFT_EYE:
|
||||
StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, -eyeSeparation / 2.0);
|
||||
break;
|
||||
case RIGHT_EYE:
|
||||
StereoProjection(left, right, bottom, top, nearplane, farplane, zeroPlane, distance, eyeSeparation / 2.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// left = -w;
|
||||
// right = w;
|
||||
// bottom = -h;
|
||||
// top = h;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glFrustum(left, right, bottom, top, 5.0, 60.0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0, 0.0, -40.0);
|
||||
|
||||
}
|
||||
|
||||
glClearColor(.2f,0.0f,0.0f,0.0f);
|
||||
}
|
||||
|
||||
|
||||
void StereoProjection(float left, float right, float bottom, float top, float nearplane, float farplane,
|
||||
float zero_plane, float dist,
|
||||
float eye)
|
||||
/* Perform the perspective projection for one eye's subfield.
|
||||
The projection is in the direction of the negative z axis.
|
||||
|
||||
-6.0, 6.0, -4.8, 4.8,
|
||||
left, right, bottom, top = the coordinate range, in the plane of zero
|
||||
parallax setting, which will be displayed on the screen. The
|
||||
ratio between (right-left) and (top-bottom) should equal the aspect
|
||||
ratio of the display.
|
||||
|
||||
6.0, -6.0,
|
||||
near, far = the z-coordinate values of the clipping planes.
|
||||
|
||||
0.0,
|
||||
zero_plane = the z-coordinate of the plane of zero parallax setting.
|
||||
|
||||
14.5,
|
||||
dist = the distance from the center of projection to the plane
|
||||
of zero parallax.
|
||||
|
||||
-0.31
|
||||
eye = half the eye separation; positive for the right eye subfield,
|
||||
negative for the left eye subfield.
|
||||
*/
|
||||
{
|
||||
float xmid, ymid, clip_near, clip_far, topw, bottomw, leftw, rightw,
|
||||
dx, dy, n_over_d;
|
||||
|
||||
dx = right - left;
|
||||
dy = top - bottom;
|
||||
|
||||
xmid = (right + left) / 2.0;
|
||||
ymid = (top + bottom) / 2.0;
|
||||
|
||||
clip_near = dist + zero_plane - nearplane;
|
||||
clip_far = dist + zero_plane - farplane;
|
||||
|
||||
n_over_d = clip_near / dist;
|
||||
|
||||
topw = n_over_d * dy / 2.0;
|
||||
bottomw = -topw;
|
||||
rightw = n_over_d * (dx / 2.0 - eye);
|
||||
leftw = n_over_d *(-dx / 2.0 - eye);
|
||||
|
||||
/* Need to be in projection mode for this. */
|
||||
glLoadIdentity();
|
||||
glFrustum(leftw, rightw, bottomw, topw, clip_near, clip_far);
|
||||
|
||||
glTranslatef(-xmid - eye, -ymid, -zero_plane - dist);
|
||||
return;
|
||||
} /* stereoproj */
|
||||
|
||||
|
||||
class Application : public GHOST_IEventConsumer {
|
||||
public:
|
||||
Application(GHOST_ISystem* system);
|
||||
~Application(void);
|
||||
virtual bool processEvent(GHOST_IEvent* event);
|
||||
|
||||
GHOST_ISystem* m_system;
|
||||
GHOST_IWindow* m_mainWindow;
|
||||
GHOST_IWindow* m_secondaryWindow;
|
||||
GHOST_IWindow* m_fullScreenWindow;
|
||||
GHOST_ITimerTask* m_gearsTimer, *m_testTimer;
|
||||
GHOST_TStandardCursor m_cursor;
|
||||
bool m_exitRequested;
|
||||
|
||||
bool stereo;
|
||||
};
|
||||
|
||||
|
||||
Application::Application(GHOST_ISystem* system)
|
||||
: m_system(system), m_mainWindow(0), m_secondaryWindow(0), m_fullScreenWindow(0),
|
||||
m_gearsTimer(0), m_testTimer(0), m_cursor(GHOST_kStandardCursorFirstCursor),
|
||||
m_exitRequested(false), stereo(false)
|
||||
{
|
||||
fApp = this;
|
||||
|
||||
// Create the main window
|
||||
STR_String title1 ("gears - main window");
|
||||
m_mainWindow = system->createWindow(title1, 10, 64, 320, 200, GHOST_kWindowStateNormal,
|
||||
GHOST_kDrawingContextTypeOpenGL, true /* stereo flag */);
|
||||
|
||||
if (!m_mainWindow) {
|
||||
std::cout << "could not create main window\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Create a secondary window
|
||||
STR_String title2 ("gears - secondary window");
|
||||
m_secondaryWindow = system->createWindow(title2, 340, 64, 320, 200, GHOST_kWindowStateNormal,
|
||||
GHOST_kDrawingContextTypeOpenGL, false /* stereo flag */);
|
||||
if (!m_secondaryWindow) {
|
||||
cout << "could not create secondary window\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Install a timer to have the gears running
|
||||
m_gearsTimer = system->installTimer(0 /*delay*/, 20/*interval*/, gearsTimerProc, m_mainWindow);
|
||||
}
|
||||
|
||||
|
||||
Application::~Application(void)
|
||||
{
|
||||
// Dispose windows
|
||||
if (m_system->validWindow(m_mainWindow)) {
|
||||
m_system->disposeWindow(m_mainWindow);
|
||||
}
|
||||
if (m_system->validWindow(m_secondaryWindow)) {
|
||||
m_system->disposeWindow(m_secondaryWindow);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Application::processEvent(GHOST_IEvent* event)
|
||||
{
|
||||
GHOST_IWindow* window = event->getWindow();
|
||||
bool handled = true;
|
||||
|
||||
switch (event->getType()) {
|
||||
/* case GHOST_kEventUnknown:
|
||||
break;
|
||||
case GHOST_kEventCursorButton:
|
||||
std::cout << "GHOST_kEventCursorButton"; break;
|
||||
case GHOST_kEventCursorMove:
|
||||
std::cout << "GHOST_kEventCursorMove"; break;
|
||||
*/
|
||||
case GHOST_kEventWheel:
|
||||
{
|
||||
GHOST_TEventWheelData* wheelData = (GHOST_TEventWheelData*) event->getData();
|
||||
if (wheelData->z > 0)
|
||||
{
|
||||
view_rotz += 5.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
view_rotz -= 5.f;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventKeyUp:
|
||||
break;
|
||||
|
||||
case GHOST_kEventKeyDown:
|
||||
{
|
||||
GHOST_TEventKeyData* keyData = (GHOST_TEventKeyData*) event->getData();
|
||||
switch (keyData->key) {
|
||||
case GHOST_kKeyC:
|
||||
{
|
||||
int cursor = m_cursor;
|
||||
cursor++;
|
||||
if (cursor >= GHOST_kStandardCursorNumCursors) {
|
||||
cursor = GHOST_kStandardCursorFirstCursor;
|
||||
}
|
||||
m_cursor = (GHOST_TStandardCursor)cursor;
|
||||
window->setCursorShape(m_cursor);
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kKeyE:
|
||||
{
|
||||
int x = 200, y= 200;
|
||||
m_system->setCursorPosition(x,y);
|
||||
break;
|
||||
}
|
||||
|
||||
case GHOST_kKeyF:
|
||||
if (!m_system->getFullScreen()) {
|
||||
// Begin fullscreen mode
|
||||
GHOST_DisplaySetting setting;
|
||||
|
||||
setting.bpp = 16;
|
||||
setting.frequency = 50;
|
||||
setting.xPixels = 640;
|
||||
setting.yPixels = 480;
|
||||
m_system->beginFullScreen(setting, &m_fullScreenWindow, false /* stereo flag */);
|
||||
}
|
||||
else {
|
||||
m_system->endFullScreen();
|
||||
m_fullScreenWindow = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kKeyH:
|
||||
window->setCursorVisibility(!window->getCursorVisibility());
|
||||
break;
|
||||
|
||||
case GHOST_kKeyM:
|
||||
{
|
||||
bool down = false;
|
||||
m_system->getModifierKeyState(GHOST_kModifierKeyLeftShift,down);
|
||||
if (down) {
|
||||
std::cout << "left shift down\n";
|
||||
}
|
||||
m_system->getModifierKeyState(GHOST_kModifierKeyRightShift,down);
|
||||
if (down) {
|
||||
std::cout << "right shift down\n"; }
|
||||
m_system->getModifierKeyState(GHOST_kModifierKeyLeftAlt,down);
|
||||
if (down) {
|
||||
std::cout << "left Alt down\n";
|
||||
}
|
||||
m_system->getModifierKeyState(GHOST_kModifierKeyRightAlt,down);
|
||||
if (down) {
|
||||
std::cout << "right Alt down\n";
|
||||
}
|
||||
m_system->getModifierKeyState(GHOST_kModifierKeyLeftControl,down);
|
||||
if (down) {
|
||||
std::cout << "left control down\n";
|
||||
}
|
||||
m_system->getModifierKeyState(GHOST_kModifierKeyRightControl,down);
|
||||
if (down) {
|
||||
std::cout << "right control down\n";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kKeyQ:
|
||||
if (m_system->getFullScreen())
|
||||
{
|
||||
m_system->endFullScreen();
|
||||
m_fullScreenWindow = 0;
|
||||
}
|
||||
m_exitRequested = true;
|
||||
break;
|
||||
|
||||
case GHOST_kKeyS: // toggle mono and stereo
|
||||
if(stereo)
|
||||
stereo = false;
|
||||
else
|
||||
stereo = true;
|
||||
break;
|
||||
|
||||
case GHOST_kKeyT:
|
||||
if (!m_testTimer) {
|
||||
m_testTimer = m_system->installTimer(0, 1000, testTimerProc);
|
||||
}
|
||||
|
||||
else {
|
||||
m_system->removeTimer(m_testTimer);
|
||||
m_testTimer = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GHOST_kKeyW:
|
||||
if (m_mainWindow)
|
||||
{
|
||||
STR_String title;
|
||||
m_mainWindow->getTitle(title);
|
||||
title += "-";
|
||||
m_mainWindow->setTitle(title);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventWindowClose:
|
||||
{
|
||||
GHOST_IWindow* window2 = event->getWindow();
|
||||
if (window2 == m_mainWindow) {
|
||||
m_exitRequested = true;
|
||||
}
|
||||
else {
|
||||
m_system->disposeWindow(window2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GHOST_kEventWindowActivate:
|
||||
handled = false;
|
||||
break;
|
||||
|
||||
case GHOST_kEventWindowDeactivate:
|
||||
handled = false;
|
||||
break;
|
||||
|
||||
case GHOST_kEventWindowUpdate:
|
||||
{
|
||||
GHOST_IWindow* window2 = event->getWindow();
|
||||
if(!m_system->validWindow(window2))
|
||||
break;
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
if(stereo)
|
||||
{
|
||||
View(window2, stereo, LEFT_EYE);
|
||||
glPushMatrix();
|
||||
RenderCamera();
|
||||
RenderScene();
|
||||
glPopMatrix();
|
||||
|
||||
View(window2, stereo, RIGHT_EYE);
|
||||
glPushMatrix();
|
||||
RenderCamera();
|
||||
RenderScene();
|
||||
glPopMatrix();
|
||||
}
|
||||
else
|
||||
{
|
||||
View(window2, stereo);
|
||||
glPushMatrix();
|
||||
RenderCamera();
|
||||
RenderScene();
|
||||
glPopMatrix();
|
||||
}
|
||||
window2->swapBuffers();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
int main(int /*argc*/, char** /*argv*/)
|
||||
{
|
||||
nVidiaWindows = false;
|
||||
// nVidiaWindows = true;
|
||||
|
||||
#ifdef WIN32
|
||||
/* Set a couple of settings in the registry for the nVidia detonator driver.
|
||||
* So this is very specific...
|
||||
*/
|
||||
if(nVidiaWindows)
|
||||
{
|
||||
LONG lresult;
|
||||
HKEY hkey = 0;
|
||||
DWORD dwd = 0;
|
||||
//unsigned char buffer[128];
|
||||
|
||||
CRegKey regkey;
|
||||
//DWORD keyValue;
|
||||
// lresult = regkey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable");
|
||||
lresult = regkey.Open(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable",
|
||||
KEY_ALL_ACCESS );
|
||||
|
||||
if(lresult == ERROR_SUCCESS)
|
||||
printf("Succesfully opened key\n");
|
||||
#if 0
|
||||
lresult = regkey.QueryValue(&keyValue, "StereoEnable");
|
||||
if(lresult == ERROR_SUCCESS)
|
||||
printf("Succesfully queried key\n");
|
||||
#endif
|
||||
lresult = regkey.SetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\NVIDIA Corporation\\Global\\Stereo3D\\StereoEnable",
|
||||
"1");
|
||||
if(lresult == ERROR_SUCCESS)
|
||||
printf("Succesfully set value for key\n");
|
||||
regkey.Close();
|
||||
if(lresult == ERROR_SUCCESS)
|
||||
printf("Succesfully closed key\n");
|
||||
// regkey.Write("2");
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
// Create the system
|
||||
GHOST_ISystem::createSystem();
|
||||
fSystem = GHOST_ISystem::getSystem();
|
||||
|
||||
if (fSystem) {
|
||||
// Create an application object
|
||||
Application app (fSystem);
|
||||
|
||||
// Add the application as event consumer
|
||||
fSystem->addEventConsumer(&app);
|
||||
|
||||
// Enter main loop
|
||||
while (!app.m_exitRequested) {
|
||||
//printf("main: loop\n");
|
||||
fSystem->processEvents(true);
|
||||
fSystem->dispatchEvents();
|
||||
}
|
||||
}
|
||||
|
||||
// Dispose the system
|
||||
GHOST_ISystem::disposeSystem();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void gearsTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 /*time*/)
|
||||
{
|
||||
fAngle += 2.0;
|
||||
view_roty += 1.0;
|
||||
GHOST_IWindow* window = (GHOST_IWindow*)task->getUserData();
|
||||
if (fApp->m_fullScreenWindow) {
|
||||
// Running full screen
|
||||
fApp->m_fullScreenWindow->invalidate();
|
||||
}
|
||||
else {
|
||||
if (fSystem->validWindow(window)) {
|
||||
window->invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
64
intern/ghost/test/multitest/Basic.c
Normal file
64
intern/ghost/test/multitest/Basic.c
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
#include "Basic.h"
|
||||
|
||||
int min_i(int a, int b) {
|
||||
return (a<b)?a:b;
|
||||
}
|
||||
int max_i(int a, int b) {
|
||||
return (b<a)?a:b;
|
||||
}
|
||||
int clamp_i(int val, int min, int max) {
|
||||
return min_i(max_i(val, min), max);
|
||||
}
|
||||
|
||||
float min_f(float a, float b) {
|
||||
return (a<b)?a:b;
|
||||
}
|
||||
float max_f(float a, float b) {
|
||||
return (b<a)?a:b;
|
||||
}
|
||||
float clamp_f(float val, float min, float max) {
|
||||
return min_f(max_f(val, min), max);
|
||||
}
|
||||
|
||||
void rect_copy(int dst[2][2], int src[2][2]) {
|
||||
dst[0][0]= src[0][0], dst[0][1]= src[0][1];
|
||||
dst[1][0]= src[1][0], dst[1][1]= src[1][1];
|
||||
}
|
||||
int rect_contains_pt(int rect[2][2], int pt[2]){
|
||||
return ((rect[0][0] <= pt[0] && pt[0] <= rect[1][0]) &&
|
||||
(rect[0][1] <= pt[1] && pt[1] <= rect[1][1]));
|
||||
}
|
||||
int rect_width(int rect[2][2]) {
|
||||
return (rect[1][0]-rect[0][0]);
|
||||
}
|
||||
int rect_height(int rect[2][2]) {
|
||||
return (rect[1][1]-rect[0][1]);
|
||||
}
|
||||
42
intern/ghost/test/multitest/Basic.h
Normal file
42
intern/ghost/test/multitest/Basic.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
int min_i (int a, int b);
|
||||
|
||||
int max_i (int a, int b);
|
||||
int clamp_i (int val, int min, int max);
|
||||
|
||||
float min_f (float a, float b);
|
||||
float max_f (float a, float b);
|
||||
float clamp_f (float val, float min, float max);
|
||||
|
||||
void rect_copy (int dst[2][2], int src[2][2]);
|
||||
int rect_contains_pt (int rect[2][2], int pt[2]);
|
||||
int rect_width (int rect[2][2]);
|
||||
int rect_height (int rect[2][2]);
|
||||
|
||||
233
intern/ghost/test/multitest/EventToBuf.c
Normal file
233
intern/ghost/test/multitest/EventToBuf.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
#include "EventToBuf.h"
|
||||
|
||||
char *eventtype_to_string(GHOST_TEventType type) {
|
||||
switch(type) {
|
||||
case GHOST_kEventCursorMove: return "CursorMove";
|
||||
case GHOST_kEventButtonDown: return "ButtonDown";
|
||||
case GHOST_kEventButtonUp: return "ButtonUp";
|
||||
|
||||
case GHOST_kEventKeyDown: return "KeyDown";
|
||||
case GHOST_kEventKeyUp: return "KeyUp";
|
||||
|
||||
case GHOST_kEventQuit: return "Quit";
|
||||
|
||||
case GHOST_kEventWindowClose: return "WindowClose";
|
||||
case GHOST_kEventWindowActivate: return "WindowActivate";
|
||||
case GHOST_kEventWindowDeactivate: return "WindowDeactivate";
|
||||
case GHOST_kEventWindowUpdate: return "WindowUpdate";
|
||||
case GHOST_kEventWindowSize: return "WindowSize";
|
||||
default:
|
||||
return "<invalid>";
|
||||
}
|
||||
}
|
||||
|
||||
static char *keytype_to_string(GHOST_TKey key) {
|
||||
#define K(key) case GHOST_k##key: return #key;
|
||||
switch (key) {
|
||||
K(KeyBackSpace);
|
||||
K(KeyTab);
|
||||
K(KeyLinefeed);
|
||||
K(KeyClear);
|
||||
K(KeyEnter);
|
||||
|
||||
K(KeyEsc);
|
||||
K(KeySpace);
|
||||
K(KeyQuote);
|
||||
K(KeyComma);
|
||||
K(KeyMinus);
|
||||
K(KeyPeriod);
|
||||
K(KeySlash);
|
||||
|
||||
K(Key0);
|
||||
K(Key1);
|
||||
K(Key2);
|
||||
K(Key3);
|
||||
K(Key4);
|
||||
K(Key5);
|
||||
K(Key6);
|
||||
K(Key7);
|
||||
K(Key8);
|
||||
K(Key9);
|
||||
|
||||
K(KeySemicolon);
|
||||
K(KeyEqual);
|
||||
|
||||
K(KeyA);
|
||||
K(KeyB);
|
||||
K(KeyC);
|
||||
K(KeyD);
|
||||
K(KeyE);
|
||||
K(KeyF);
|
||||
K(KeyG);
|
||||
K(KeyH);
|
||||
K(KeyI);
|
||||
K(KeyJ);
|
||||
K(KeyK);
|
||||
K(KeyL);
|
||||
K(KeyM);
|
||||
K(KeyN);
|
||||
K(KeyO);
|
||||
K(KeyP);
|
||||
K(KeyQ);
|
||||
K(KeyR);
|
||||
K(KeyS);
|
||||
K(KeyT);
|
||||
K(KeyU);
|
||||
K(KeyV);
|
||||
K(KeyW);
|
||||
K(KeyX);
|
||||
K(KeyY);
|
||||
K(KeyZ);
|
||||
|
||||
K(KeyLeftBracket);
|
||||
K(KeyRightBracket);
|
||||
K(KeyBackslash);
|
||||
K(KeyAccentGrave);
|
||||
|
||||
K(KeyLeftShift);
|
||||
K(KeyRightShift);
|
||||
K(KeyLeftControl);
|
||||
K(KeyRightControl);
|
||||
K(KeyLeftAlt);
|
||||
K(KeyRightAlt);
|
||||
K(KeyOS);
|
||||
|
||||
K(KeyCapsLock);
|
||||
K(KeyNumLock);
|
||||
K(KeyScrollLock);
|
||||
|
||||
K(KeyLeftArrow);
|
||||
K(KeyRightArrow);
|
||||
K(KeyUpArrow);
|
||||
K(KeyDownArrow);
|
||||
|
||||
K(KeyPrintScreen);
|
||||
K(KeyPause);
|
||||
|
||||
K(KeyInsert);
|
||||
K(KeyDelete);
|
||||
K(KeyHome);
|
||||
K(KeyEnd);
|
||||
K(KeyUpPage);
|
||||
K(KeyDownPage);
|
||||
|
||||
K(KeyNumpad0);
|
||||
K(KeyNumpad1);
|
||||
K(KeyNumpad2);
|
||||
K(KeyNumpad3);
|
||||
K(KeyNumpad4);
|
||||
K(KeyNumpad5);
|
||||
K(KeyNumpad6);
|
||||
K(KeyNumpad7);
|
||||
K(KeyNumpad8);
|
||||
K(KeyNumpad9);
|
||||
K(KeyNumpadPeriod);
|
||||
K(KeyNumpadEnter);
|
||||
K(KeyNumpadPlus);
|
||||
K(KeyNumpadMinus);
|
||||
K(KeyNumpadAsterisk);
|
||||
K(KeyNumpadSlash);
|
||||
|
||||
K(KeyF1);
|
||||
K(KeyF2);
|
||||
K(KeyF3);
|
||||
K(KeyF4);
|
||||
K(KeyF5);
|
||||
K(KeyF6);
|
||||
K(KeyF7);
|
||||
K(KeyF8);
|
||||
K(KeyF9);
|
||||
K(KeyF10);
|
||||
K(KeyF11);
|
||||
K(KeyF12);
|
||||
K(KeyF13);
|
||||
K(KeyF14);
|
||||
K(KeyF15);
|
||||
K(KeyF16);
|
||||
K(KeyF17);
|
||||
K(KeyF18);
|
||||
K(KeyF19);
|
||||
K(KeyF20);
|
||||
K(KeyF21);
|
||||
K(KeyF22);
|
||||
K(KeyF23);
|
||||
K(KeyF24);
|
||||
|
||||
default:
|
||||
return "KeyUnknown";
|
||||
}
|
||||
#undef K
|
||||
}
|
||||
|
||||
void event_to_buf(GHOST_EventHandle evt, char buf[128]) {
|
||||
GHOST_TEventType type= GHOST_GetEventType(evt);
|
||||
double time= (double) ((GHOST_TInt64) GHOST_GetEventTime(evt))/1000;
|
||||
GHOST_WindowHandle win= GHOST_GetEventWindow(evt);
|
||||
void *data= GHOST_GetEventData(evt);
|
||||
char *pos= buf;
|
||||
|
||||
pos+= sprintf(pos, "event: %6.2f, %16s", time, eventtype_to_string(type));
|
||||
if (win) {
|
||||
char *s= GHOST_GetTitle(win);
|
||||
pos+= sprintf(pos, " - win: %s", s);
|
||||
free(s);
|
||||
} else {
|
||||
pos+= sprintf(pos, " - sys evt");
|
||||
}
|
||||
switch (type) {
|
||||
case GHOST_kEventCursorMove: {
|
||||
GHOST_TEventCursorData *cd= data;
|
||||
pos+= sprintf(pos, " - pos: (%d, %d)", cd->x, cd->y);
|
||||
break;
|
||||
}
|
||||
case GHOST_kEventButtonDown:
|
||||
case GHOST_kEventButtonUp: {
|
||||
GHOST_TEventButtonData *bd= data;
|
||||
pos+= sprintf(pos, " - but: %d", bd->button);
|
||||
break;
|
||||
}
|
||||
|
||||
case GHOST_kEventKeyDown:
|
||||
case GHOST_kEventKeyUp: {
|
||||
GHOST_TEventKeyData *kd= data;
|
||||
pos+= sprintf(pos, " - key: %s (%d)", keytype_to_string(kd->key), kd->key);
|
||||
if (kd->ascii) pos+= sprintf(pos, " ascii: '%c' (%d)", kd->ascii, kd->ascii);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
31
intern/ghost/test/multitest/EventToBuf.h
Normal file
31
intern/ghost/test/multitest/EventToBuf.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
char *eventtype_to_string(GHOST_TEventType type);
|
||||
void event_to_buf(GHOST_EventHandle evt, char buf[128]);
|
||||
|
||||
41
intern/ghost/test/multitest/GL.h
Normal file
41
intern/ghost/test/multitest/GL.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
#if defined(WIN32) || defined(__APPLE__)
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <GL/gl.h>
|
||||
#else // WIN32
|
||||
// __APPLE__ is defined
|
||||
#include <AGL/gl.h>
|
||||
#endif // WIN32
|
||||
#else // defined(WIN32) || defined(__APPLE__)
|
||||
#include <GL/gl.h>
|
||||
#endif // defined(WIN32) || defined(__APPLE__)
|
||||
|
||||
859
intern/ghost/test/multitest/MultiTest.c
Normal file
859
intern/ghost/test/multitest/MultiTest.c
Normal file
@@ -0,0 +1,859 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
#define FALSE 0
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#pragma warning(disable: 4244 4305)
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "GL.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
#include "BMF_Api.h"
|
||||
|
||||
#include "Util.h"
|
||||
#include "Basic.h"
|
||||
#include "ScrollBar.h"
|
||||
#include "EventToBuf.h"
|
||||
|
||||
#include "WindowData.h"
|
||||
|
||||
/***/
|
||||
|
||||
typedef struct _MultiTestApp MultiTestApp;
|
||||
typedef struct _LoggerWindow LoggerWindow;
|
||||
|
||||
void loggerwindow_log(LoggerWindow *lw, char *line);
|
||||
|
||||
void multitestapp_toggle_extra_window(MultiTestApp *app);
|
||||
void multitestapp_free_extrawindow(MultiTestApp *app);
|
||||
LoggerWindow *multitestapp_get_logger(MultiTestApp *app);
|
||||
GHOST_SystemHandle multitestapp_get_system(MultiTestApp *app);
|
||||
void multitestapp_exit(MultiTestApp *app);
|
||||
|
||||
/**/
|
||||
|
||||
void rect_bevel_side(int rect[2][2], int side, float *lt, float *dk, float *col, int width) {
|
||||
int ltidx= (side/2)%4;
|
||||
int dkidx= (ltidx + 1 + (side&1))%4;
|
||||
int i, corner;
|
||||
|
||||
glBegin(GL_LINES);
|
||||
for (i=0; i<width; i++) {
|
||||
float ltf= pow(lt[i], 1.0/2.2), dkf= pow(dk[i], 1.0/2.2);
|
||||
float stf= (dkidx>ltidx)?dkf:ltf;
|
||||
int lx= rect[1][0]-i-1;
|
||||
int ly= rect[0][1]+i;
|
||||
|
||||
glColor3f(col[0]*stf, col[1]*stf, col[2]*stf);
|
||||
for (corner=0; corner<4; corner++) {
|
||||
int x= (corner==0 || corner==1)?(rect[0][0]+i):(rect[1][0]-i-1);
|
||||
int y= (corner==0 || corner==3)?(rect[0][1]+i):(rect[1][1]-i-1);
|
||||
|
||||
if (ltidx==corner)
|
||||
glColor3f(col[0]*ltf, col[1]*ltf, col[2]*ltf);
|
||||
if (dkidx==corner)
|
||||
glColor3f(col[0]*dkf, col[1]*dkf, col[2]*dkf);
|
||||
|
||||
glVertex2i(lx, ly);
|
||||
glVertex2i(lx= x, ly= y);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glColor3fv(col);
|
||||
glRecti(rect[0][0]+width, rect[0][1]+width, rect[1][0]-width, rect[1][1]-width);
|
||||
}
|
||||
|
||||
void rect_bevel_smooth(int rect[2][2], int width) {
|
||||
float *lt= malloc(sizeof(*lt)*width);
|
||||
float *dk= malloc(sizeof(*dk)*width);
|
||||
float col[4];
|
||||
int i;
|
||||
|
||||
for (i=0; i<width; i++) {
|
||||
float v= width-1?((float) i/(width-1)):0;
|
||||
lt[i]= 1.2 + (1.0-1.2)*v;
|
||||
dk[i]= 0.2 + (1.0-0.2)*v;
|
||||
}
|
||||
|
||||
glGetFloatv(GL_CURRENT_COLOR, col);
|
||||
|
||||
rect_bevel_side(rect, 3, lt, dk, col, width);
|
||||
|
||||
free(lt);
|
||||
free(dk);
|
||||
}
|
||||
|
||||
/*
|
||||
* MainWindow
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
MultiTestApp *app;
|
||||
|
||||
GHOST_WindowHandle win;
|
||||
|
||||
int size[2];
|
||||
|
||||
int lmouse[2], lmbut[3];
|
||||
|
||||
int tmouse[2];
|
||||
} MainWindow;
|
||||
|
||||
static void mainwindow_log(MainWindow *mw, char *str) {
|
||||
loggerwindow_log(multitestapp_get_logger(mw->app), str);
|
||||
}
|
||||
|
||||
static void mainwindow_do_draw(MainWindow *mw) {
|
||||
GHOST_ActivateWindowDrawingContext(mw->win);
|
||||
|
||||
if (mw->lmbut[0]) {
|
||||
glClearColor(0.5, 0.5, 0.5, 1);
|
||||
} else {
|
||||
glClearColor(1, 1, 1, 1);
|
||||
}
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glColor3f(0.5, 0.6, 0.8);
|
||||
glRecti(mw->tmouse[0]-5, mw->tmouse[1]-5, mw->tmouse[0]+5, mw->tmouse[1]+5);
|
||||
|
||||
GHOST_SwapWindowBuffers(mw->win);
|
||||
}
|
||||
|
||||
static void mainwindow_do_reshape(MainWindow *mw) {
|
||||
GHOST_RectangleHandle bounds= GHOST_GetClientBounds(mw->win);
|
||||
|
||||
GHOST_ActivateWindowDrawingContext(mw->win);
|
||||
|
||||
mw->size[0]= GHOST_GetWidthRectangle(bounds);
|
||||
mw->size[1]= GHOST_GetHeightRectangle(bounds);
|
||||
|
||||
glViewport(0, 0, mw->size[0], mw->size[1]);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, mw->size[0], 0, mw->size[1], -1, 1);
|
||||
glTranslatef(0.375, 0.375, 0.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
static void mainwindow_do_key(MainWindow *mw, GHOST_TKey key, int press) {
|
||||
switch(key) {
|
||||
case GHOST_kKeyC:
|
||||
if (press)
|
||||
GHOST_SetCursorShape(mw->win, (GHOST_TStandardCursor) (rand()%(GHOST_kStandardCursorNumCursors)));
|
||||
break;
|
||||
case GHOST_kKeyLeftBracket:
|
||||
if (press)
|
||||
GHOST_SetCursorVisibility(mw->win, 0);
|
||||
break;
|
||||
case GHOST_kKeyRightBracket:
|
||||
if (press)
|
||||
GHOST_SetCursorVisibility(mw->win, 1);
|
||||
break;
|
||||
case GHOST_kKeyE:
|
||||
if (press)
|
||||
multitestapp_toggle_extra_window(mw->app);
|
||||
break;
|
||||
case GHOST_kKeyQ:
|
||||
if (press)
|
||||
multitestapp_exit(mw->app);
|
||||
break;
|
||||
case GHOST_kKeyT:
|
||||
if (press)
|
||||
mainwindow_log(mw, "TextTest~|`hello`\"world\",<>/");
|
||||
break;
|
||||
case GHOST_kKeyR:
|
||||
if (press) {
|
||||
int i;
|
||||
|
||||
mainwindow_log(mw, "Invalidating window 10 times");
|
||||
for (i=0; i<10; i++)
|
||||
GHOST_InvalidateWindow(mw->win);
|
||||
}
|
||||
break;
|
||||
case GHOST_kKeyF11:
|
||||
if (press) {
|
||||
GHOST_SetWindowOrder(mw->win, GHOST_kWindowOrderBottom);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void mainwindow_do_move(MainWindow *mw, int x, int y) {
|
||||
mw->lmouse[0]= x, mw->lmouse[1]= y;
|
||||
|
||||
if (mw->lmbut[0]) {
|
||||
mw->tmouse[0]= x, mw->tmouse[1]= y;
|
||||
GHOST_InvalidateWindow(mw->win);
|
||||
}
|
||||
}
|
||||
|
||||
static void mainwindow_do_button(MainWindow *mw, int which, int press) {
|
||||
if (which==GHOST_kButtonMaskLeft) {
|
||||
mw->lmbut[0]= press;
|
||||
mw->tmouse[0]= mw->lmouse[0], mw->tmouse[1]= mw->lmouse[1];
|
||||
GHOST_InvalidateWindow(mw->win);
|
||||
} else if (which==GHOST_kButtonMaskLeft) {
|
||||
mw->lmbut[1]= press;
|
||||
} else if (which==GHOST_kButtonMaskLeft) {
|
||||
mw->lmbut[2]= press;
|
||||
}
|
||||
}
|
||||
|
||||
static void mainwindow_handle(void *priv, GHOST_EventHandle evt) {
|
||||
MainWindow *mw= priv;
|
||||
GHOST_TEventType type= GHOST_GetEventType(evt);
|
||||
char buf[256];
|
||||
|
||||
event_to_buf(evt, buf);
|
||||
mainwindow_log(mw, buf);
|
||||
|
||||
switch (type) {
|
||||
case GHOST_kEventCursorMove: {
|
||||
GHOST_TEventCursorData *cd= GHOST_GetEventData(evt);
|
||||
int x, y;
|
||||
GHOST_ScreenToClient(mw->win, cd->x, cd->y, &x, &y);
|
||||
mainwindow_do_move(mw, x, mw->size[1]-y-1);
|
||||
break;
|
||||
}
|
||||
case GHOST_kEventButtonDown:
|
||||
case GHOST_kEventButtonUp: {
|
||||
GHOST_TEventButtonData *bd= GHOST_GetEventData(evt);
|
||||
mainwindow_do_button(mw, bd->button, (type == GHOST_kEventButtonDown));
|
||||
break;
|
||||
}
|
||||
case GHOST_kEventKeyDown:
|
||||
case GHOST_kEventKeyUp: {
|
||||
GHOST_TEventKeyData *kd= GHOST_GetEventData(evt);
|
||||
mainwindow_do_key(mw, kd->key, (type == GHOST_kEventKeyDown));
|
||||
break;
|
||||
}
|
||||
|
||||
case GHOST_kEventWindowUpdate:
|
||||
mainwindow_do_draw(mw);
|
||||
break;
|
||||
case GHOST_kEventWindowSize:
|
||||
mainwindow_do_reshape(mw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
static void mainwindow_timer_proc(GHOST_TimerTaskHandle task, GHOST_TUns64 time) {
|
||||
MainWindow *mw= GHOST_GetTimerTaskUserData(task);
|
||||
char buf[64];
|
||||
|
||||
sprintf(buf, "timer: %6.2f", (double) ((GHOST_TInt64) time)/1000);
|
||||
mainwindow_log(mw, buf);
|
||||
}
|
||||
|
||||
MainWindow *mainwindow_new(MultiTestApp *app) {
|
||||
GHOST_SystemHandle sys= multitestapp_get_system(app);
|
||||
GHOST_WindowHandle win;
|
||||
|
||||
win= GHOST_CreateWindow(sys, "MultiTest:Main", 40, 40, 400, 400,
|
||||
GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL,
|
||||
FALSE);
|
||||
|
||||
if (win) {
|
||||
MainWindow *mw= MEM_callocN(sizeof(*mw), "mainwindow_new");
|
||||
mw->app= app;
|
||||
mw->win= win;
|
||||
|
||||
GHOST_SetWindowUserData(mw->win, windowdata_new(mw, mainwindow_handle));
|
||||
|
||||
GHOST_InstallTimer(sys, 1000, 10000, mainwindow_timer_proc, mw);
|
||||
|
||||
return mw;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void mainwindow_free(MainWindow *mw) {
|
||||
GHOST_SystemHandle sys= multitestapp_get_system(mw->app);
|
||||
|
||||
windowdata_free(GHOST_GetWindowUserData(mw->win));
|
||||
GHOST_DisposeWindow(sys, mw->win);
|
||||
MEM_freeN(mw);
|
||||
}
|
||||
|
||||
/*
|
||||
* LoggerWindow
|
||||
*/
|
||||
|
||||
struct _LoggerWindow {
|
||||
MultiTestApp *app;
|
||||
|
||||
GHOST_WindowHandle win;
|
||||
|
||||
BMF_Font *font;
|
||||
int fonttexid;
|
||||
int fontheight;
|
||||
|
||||
int size[2];
|
||||
|
||||
int ndisplines;
|
||||
int textarea[2][2];
|
||||
ScrollBar *scroll;
|
||||
|
||||
char **loglines;
|
||||
int nloglines, logsize;
|
||||
|
||||
int lmbut[3];
|
||||
int lmouse[2];
|
||||
};
|
||||
|
||||
#define SCROLLBAR_PAD 2
|
||||
#define SCROLLBAR_WIDTH 14
|
||||
#define TEXTAREA_PAD 2
|
||||
static void loggerwindow_recalc_regions(LoggerWindow *lw) {
|
||||
int nscroll[2][2];
|
||||
|
||||
nscroll[0][0]= SCROLLBAR_PAD;
|
||||
nscroll[0][1]= SCROLLBAR_PAD;
|
||||
nscroll[1][0]= nscroll[0][0] + SCROLLBAR_WIDTH;
|
||||
nscroll[1][1]= lw->size[1] - SCROLLBAR_PAD - 1;
|
||||
|
||||
lw->textarea[0][0]= nscroll[1][0] + TEXTAREA_PAD;
|
||||
lw->textarea[0][1]= TEXTAREA_PAD;
|
||||
lw->textarea[1][0]= lw->size[0] - TEXTAREA_PAD - 1;
|
||||
lw->textarea[1][1]= lw->size[1] - TEXTAREA_PAD - 1;
|
||||
|
||||
lw->ndisplines= (lw->textarea[1][1]-lw->textarea[0][1])/lw->fontheight;
|
||||
|
||||
scrollbar_set_thumbpct(lw->scroll, (float) lw->ndisplines/lw->nloglines);
|
||||
scrollbar_set_rect(lw->scroll, nscroll);
|
||||
}
|
||||
|
||||
static void loggerwindow_setup_window_gl(LoggerWindow *lw) {
|
||||
glViewport(0, 0, lw->size[0], lw->size[1]);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, lw->size[0], 0, lw->size[1], -1, 1);
|
||||
glTranslatef(0.375, 0.375, 0.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
static void loggerwindow_do_reshape(LoggerWindow *lw) {
|
||||
GHOST_RectangleHandle bounds= GHOST_GetClientBounds(lw->win);
|
||||
|
||||
GHOST_ActivateWindowDrawingContext(lw->win);
|
||||
|
||||
lw->size[0]= GHOST_GetWidthRectangle(bounds);
|
||||
lw->size[1]= GHOST_GetHeightRectangle(bounds);
|
||||
|
||||
loggerwindow_recalc_regions(lw);
|
||||
loggerwindow_setup_window_gl(lw);
|
||||
}
|
||||
|
||||
static void loggerwindow_do_draw(LoggerWindow *lw) {
|
||||
int i, ndisplines, startline;
|
||||
int sb_rect[2][2], sb_thumb[2][2];
|
||||
|
||||
GHOST_ActivateWindowDrawingContext(lw->win);
|
||||
|
||||
glClearColor(1, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glColor3f(0.8, 0.8, 0.8);
|
||||
rect_bevel_smooth(lw->textarea, 4);
|
||||
|
||||
scrollbar_get_rect(lw->scroll, sb_rect);
|
||||
scrollbar_get_thumb(lw->scroll, sb_thumb);
|
||||
|
||||
glColor3f(0.6, 0.6, 0.6);
|
||||
rect_bevel_smooth(sb_rect, 1);
|
||||
|
||||
if (scrollbar_is_scrolling(lw->scroll)) {
|
||||
glColor3f(0.6, 0.7, 0.5);
|
||||
} else {
|
||||
glColor3f(0.9, 0.9, 0.92);
|
||||
}
|
||||
rect_bevel_smooth(sb_thumb, 1);
|
||||
|
||||
startline= scrollbar_get_thumbpos(lw->scroll)*(lw->nloglines-1);
|
||||
ndisplines= min_i(lw->ndisplines, lw->nloglines-startline);
|
||||
|
||||
if (lw->fonttexid!=-1) {
|
||||
glBindTexture(GL_TEXTURE_2D, lw->fonttexid);
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
glColor3f(0, 0, 0);
|
||||
for (i=0; i<ndisplines; i++) {
|
||||
/* stored in reverse order */
|
||||
char *line= lw->loglines[(lw->nloglines-1)-(i+startline)];
|
||||
int x_pos= lw->textarea[0][0] + 4;
|
||||
int y_pos= lw->textarea[0][1] + 4 + i*lw->fontheight;
|
||||
|
||||
if (lw->fonttexid==-1) {
|
||||
glRasterPos2i(x_pos, y_pos);
|
||||
BMF_DrawString(lw->font, line);
|
||||
} else {
|
||||
BMF_DrawStringTexture(lw->font, line, x_pos, y_pos, 0.0);
|
||||
}
|
||||
}
|
||||
if (lw->fonttexid!=-1) {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
GHOST_SwapWindowBuffers(lw->win);
|
||||
}
|
||||
|
||||
static void loggerwindow_do_move(LoggerWindow *lw, int x, int y) {
|
||||
lw->lmouse[0]= x, lw->lmouse[1]= y;
|
||||
|
||||
if (scrollbar_is_scrolling(lw->scroll)) {
|
||||
scrollbar_keep_scrolling(lw->scroll, y);
|
||||
GHOST_InvalidateWindow(lw->win);
|
||||
}
|
||||
}
|
||||
|
||||
static void loggerwindow_do_button(LoggerWindow *lw, int which, int press) {
|
||||
if (which==GHOST_kButtonMaskLeft) {
|
||||
lw->lmbut[0]= press;
|
||||
|
||||
if (press) {
|
||||
if (scrollbar_contains_pt(lw->scroll, lw->lmouse)) {
|
||||
scrollbar_start_scrolling(lw->scroll, lw->lmouse[1]);
|
||||
GHOST_SetCursorShape(lw->win, GHOST_kStandardCursorUpDown);
|
||||
GHOST_InvalidateWindow(lw->win);
|
||||
}
|
||||
} else {
|
||||
if (scrollbar_is_scrolling(lw->scroll)) {
|
||||
scrollbar_stop_scrolling(lw->scroll);
|
||||
GHOST_SetCursorShape(lw->win, GHOST_kStandardCursorDefault);
|
||||
GHOST_InvalidateWindow(lw->win);
|
||||
}
|
||||
}
|
||||
} else if (which==GHOST_kButtonMaskMiddle) {
|
||||
lw->lmbut[1]= press;
|
||||
} else if (which==GHOST_kButtonMaskRight) {
|
||||
lw->lmbut[2]= press;
|
||||
}
|
||||
}
|
||||
|
||||
static void loggerwindow_do_key(LoggerWindow *lw, GHOST_TKey key, int press) {
|
||||
switch (key) {
|
||||
case GHOST_kKeyQ:
|
||||
if (press)
|
||||
multitestapp_exit(lw->app);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void loggerwindow_handle(void *priv, GHOST_EventHandle evt) {
|
||||
LoggerWindow *lw= priv;
|
||||
GHOST_TEventType type= GHOST_GetEventType(evt);
|
||||
|
||||
switch(type) {
|
||||
case GHOST_kEventCursorMove: {
|
||||
GHOST_TEventCursorData *cd= GHOST_GetEventData(evt);
|
||||
int x, y;
|
||||
GHOST_ScreenToClient(lw->win, cd->x, cd->y, &x, &y);
|
||||
loggerwindow_do_move(lw, x, lw->size[1]-y-1);
|
||||
break;
|
||||
}
|
||||
case GHOST_kEventButtonDown:
|
||||
case GHOST_kEventButtonUp: {
|
||||
GHOST_TEventButtonData *bd= GHOST_GetEventData(evt);
|
||||
loggerwindow_do_button(lw, bd->button, (type == GHOST_kEventButtonDown));
|
||||
break;
|
||||
}
|
||||
case GHOST_kEventKeyDown:
|
||||
case GHOST_kEventKeyUp: {
|
||||
GHOST_TEventKeyData *kd= GHOST_GetEventData(evt);
|
||||
loggerwindow_do_key(lw, kd->key, (type == GHOST_kEventKeyDown));
|
||||
break;
|
||||
}
|
||||
|
||||
case GHOST_kEventWindowUpdate:
|
||||
loggerwindow_do_draw(lw);
|
||||
break;
|
||||
case GHOST_kEventWindowSize:
|
||||
loggerwindow_do_reshape(lw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
LoggerWindow *loggerwindow_new(MultiTestApp *app) {
|
||||
GHOST_SystemHandle sys= multitestapp_get_system(app);
|
||||
GHOST_TUns32 screensize[2];
|
||||
GHOST_WindowHandle win;
|
||||
|
||||
GHOST_GetMainDisplayDimensions(sys, &screensize[0], &screensize[1]);
|
||||
win= GHOST_CreateWindow(sys, "MultiTest:Logger", 40, screensize[1]-432,
|
||||
800, 300, GHOST_kWindowStateNormal,
|
||||
GHOST_kDrawingContextTypeOpenGL, FALSE);
|
||||
|
||||
if (win) {
|
||||
LoggerWindow *lw= MEM_callocN(sizeof(*lw), "loggerwindow_new");
|
||||
int bbox[2][2];
|
||||
lw->app= app;
|
||||
lw->win= win;
|
||||
|
||||
lw->font= BMF_GetFont(BMF_kScreen12);
|
||||
lw->fonttexid= BMF_GetFontTexture(lw->font);
|
||||
|
||||
BMF_GetBoundingBox(lw->font, &bbox[0][0], &bbox[0][1], &bbox[1][0], &bbox[1][1]);
|
||||
lw->fontheight= rect_height(bbox);
|
||||
|
||||
lw->nloglines= lw->logsize= 0;
|
||||
lw->loglines= MEM_mallocN(sizeof(*lw->loglines)*lw->nloglines, "loglines");
|
||||
|
||||
lw->scroll= scrollbar_new(2, 40);
|
||||
|
||||
GHOST_SetWindowUserData(lw->win, windowdata_new(lw, loggerwindow_handle));
|
||||
|
||||
loggerwindow_do_reshape(lw);
|
||||
|
||||
return lw;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void loggerwindow_log(LoggerWindow *lw, char *line) {
|
||||
if (lw->nloglines==lw->logsize) {
|
||||
lw->loglines= memdbl(lw->loglines, &lw->logsize, sizeof(*lw->loglines));
|
||||
}
|
||||
|
||||
lw->loglines[lw->nloglines++]= string_dup(line);
|
||||
scrollbar_set_thumbpct(lw->scroll, (float) lw->ndisplines/lw->nloglines);
|
||||
|
||||
GHOST_InvalidateWindow(lw->win);
|
||||
}
|
||||
|
||||
void loggerwindow_free(LoggerWindow *lw) {
|
||||
GHOST_SystemHandle sys= multitestapp_get_system(lw->app);
|
||||
int i;
|
||||
|
||||
for (i=0; i<lw->nloglines; i++) {
|
||||
MEM_freeN(lw->loglines[i]);
|
||||
}
|
||||
MEM_freeN(lw->loglines);
|
||||
|
||||
windowdata_free(GHOST_GetWindowUserData(lw->win));
|
||||
GHOST_DisposeWindow(sys, lw->win);
|
||||
MEM_freeN(lw);
|
||||
}
|
||||
|
||||
/*
|
||||
* ExtraWindow
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
MultiTestApp *app;
|
||||
|
||||
GHOST_WindowHandle win;
|
||||
|
||||
int size[2];
|
||||
} ExtraWindow;
|
||||
|
||||
static void extrawindow_do_draw(ExtraWindow *ew) {
|
||||
GHOST_ActivateWindowDrawingContext(ew->win);
|
||||
|
||||
glClearColor(1, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glColor3f(0.8, 0.8, 0.8);
|
||||
glRecti(10, 10, ew->size[0]-10, ew->size[1]-10);
|
||||
|
||||
GHOST_SwapWindowBuffers(ew->win);
|
||||
}
|
||||
|
||||
static void extrawindow_do_reshape(ExtraWindow *ew) {
|
||||
GHOST_RectangleHandle bounds= GHOST_GetClientBounds(ew->win);
|
||||
|
||||
GHOST_ActivateWindowDrawingContext(ew->win);
|
||||
|
||||
ew->size[0]= GHOST_GetWidthRectangle(bounds);
|
||||
ew->size[1]= GHOST_GetHeightRectangle(bounds);
|
||||
|
||||
glViewport(0, 0, ew->size[0], ew->size[1]);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, ew->size[0], 0, ew->size[1], -1, 1);
|
||||
glTranslatef(0.375, 0.375, 0.0);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
}
|
||||
|
||||
static void extrawindow_do_key(ExtraWindow *ew, GHOST_TKey key, int press) {
|
||||
switch (key) {
|
||||
case GHOST_kKeyE:
|
||||
if (press)
|
||||
multitestapp_toggle_extra_window(ew->app);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void extrawindow_spin_cursor(ExtraWindow *ew, GHOST_TUns64 time) {
|
||||
GHOST_TUns8 bitmap[16][2];
|
||||
GHOST_TUns8 mask[16][2];
|
||||
double ftime= (double) ((GHOST_TInt64) time)/1000;
|
||||
float angle= fmod(ftime, 1.0) * 3.1415*2;
|
||||
int i;
|
||||
|
||||
memset(&bitmap, 0, sizeof(bitmap));
|
||||
memset(&mask, 0, sizeof(mask));
|
||||
|
||||
bitmap[0][0] |= mask[0][0] |= 0xF;
|
||||
bitmap[1][0] |= mask[1][0] |= 0xF;
|
||||
bitmap[2][0] |= mask[2][0] |= 0xF;
|
||||
bitmap[3][0] |= mask[3][0] |= 0xF;
|
||||
|
||||
for (i=0; i<7; i++) {
|
||||
int x = 7 + cos(angle)*i;
|
||||
int y = 7 + sin(angle)*i;
|
||||
|
||||
mask[y][x/8] |= (1 << (x%8));
|
||||
}
|
||||
for (i=0; i<64; i++) {
|
||||
float v= (i/63.0) * 3.1415*2;
|
||||
int x = 7 + cos(v)*7;
|
||||
int y = 7 + sin(v)*7;
|
||||
|
||||
mask[y][x/8] |= (1 << (x%8));
|
||||
}
|
||||
|
||||
GHOST_SetCustomCursorShape(ew->win, bitmap, mask, 0, 0);
|
||||
}
|
||||
|
||||
static void extrawindow_handle(void *priv, GHOST_EventHandle evt) {
|
||||
ExtraWindow *ew= priv;
|
||||
GHOST_TEventType type= GHOST_GetEventType(evt);
|
||||
char buf[256];
|
||||
|
||||
event_to_buf(evt, buf);
|
||||
loggerwindow_log(multitestapp_get_logger(ew->app), buf);
|
||||
|
||||
switch (type) {
|
||||
case GHOST_kEventKeyDown:
|
||||
case GHOST_kEventKeyUp: {
|
||||
GHOST_TEventKeyData *kd= GHOST_GetEventData(evt);
|
||||
extrawindow_do_key(ew, kd->key, (type == GHOST_kEventKeyDown));
|
||||
break;
|
||||
}
|
||||
|
||||
case GHOST_kEventCursorMove: {
|
||||
extrawindow_spin_cursor(ew, GHOST_GetEventTime(evt));
|
||||
break;
|
||||
}
|
||||
|
||||
case GHOST_kEventWindowClose:
|
||||
multitestapp_free_extrawindow(ew->app);
|
||||
break;
|
||||
case GHOST_kEventWindowUpdate:
|
||||
extrawindow_do_draw(ew);
|
||||
break;
|
||||
case GHOST_kEventWindowSize:
|
||||
extrawindow_do_reshape(ew);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
ExtraWindow *extrawindow_new(MultiTestApp *app) {
|
||||
GHOST_SystemHandle sys= multitestapp_get_system(app);
|
||||
GHOST_WindowHandle win;
|
||||
|
||||
win= GHOST_CreateWindow(sys, "MultiTest:Extra", 500, 40, 400, 400,
|
||||
GHOST_kWindowStateNormal, GHOST_kDrawingContextTypeOpenGL,
|
||||
FALSE);
|
||||
|
||||
if (win) {
|
||||
ExtraWindow *ew= MEM_callocN(sizeof(*ew), "mainwindow_new");
|
||||
ew->app= app;
|
||||
ew->win= win;
|
||||
|
||||
GHOST_SetWindowUserData(ew->win, windowdata_new(ew, extrawindow_handle));
|
||||
|
||||
return ew;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void extrawindow_free(ExtraWindow *ew) {
|
||||
GHOST_SystemHandle sys= multitestapp_get_system(ew->app);
|
||||
|
||||
windowdata_free(GHOST_GetWindowUserData(ew->win));
|
||||
GHOST_DisposeWindow(sys, ew->win);
|
||||
MEM_freeN(ew);
|
||||
}
|
||||
|
||||
/*
|
||||
* MultiTestApp
|
||||
*/
|
||||
|
||||
struct _MultiTestApp {
|
||||
GHOST_SystemHandle sys;
|
||||
MainWindow *main;
|
||||
LoggerWindow *logger;
|
||||
ExtraWindow *extra;
|
||||
|
||||
int exit;
|
||||
};
|
||||
|
||||
static int multitest_event_handler(GHOST_EventHandle evt, GHOST_TUserDataPtr data) {
|
||||
MultiTestApp *app= data;
|
||||
GHOST_WindowHandle win;
|
||||
|
||||
win= GHOST_GetEventWindow(evt);
|
||||
if (win && !GHOST_ValidWindow(app->sys, win)) {
|
||||
loggerwindow_log(app->logger, "WARNING: bad event, non-valid window\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (win) {
|
||||
WindowData *wb= GHOST_GetWindowUserData(win);
|
||||
|
||||
windowdata_handle(wb, evt);
|
||||
} else {
|
||||
GHOST_TEventType type= GHOST_GetEventType(evt);
|
||||
|
||||
/* GHOST_kEventQuit are the only 'system' events,
|
||||
* that is, events without a window.
|
||||
*/
|
||||
switch(type) {
|
||||
case GHOST_kEventQuit:
|
||||
app->exit= 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("Unhandled system event: %d (%s)\n", type, eventtype_to_string(type));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
MultiTestApp *multitestapp_new(void) {
|
||||
MultiTestApp *app= MEM_mallocN(sizeof(*app), "multitestapp_new");
|
||||
GHOST_EventConsumerHandle consumer= GHOST_CreateEventConsumer(multitest_event_handler, app);
|
||||
|
||||
app->sys= GHOST_CreateSystem();
|
||||
if (!app->sys)
|
||||
fatal("Unable to create ghost system");
|
||||
|
||||
if (!GHOST_AddEventConsumer(app->sys, consumer))
|
||||
fatal("Unable to add multitest event consumer ");
|
||||
|
||||
app->main= mainwindow_new(app);
|
||||
if (!app->main)
|
||||
fatal("Unable to create main window");
|
||||
|
||||
app->logger= loggerwindow_new(app);
|
||||
if (!app->logger)
|
||||
fatal("Unable to create logger window");
|
||||
|
||||
app->extra= NULL;
|
||||
app->exit= 0;
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
LoggerWindow *multitestapp_get_logger(MultiTestApp *app) {
|
||||
return app->logger;
|
||||
}
|
||||
|
||||
GHOST_SystemHandle multitestapp_get_system(MultiTestApp *app) {
|
||||
return app->sys;
|
||||
}
|
||||
|
||||
void multitestapp_free_extrawindow(MultiTestApp *app) {
|
||||
extrawindow_free(app->extra);
|
||||
app->extra= NULL;
|
||||
}
|
||||
|
||||
void multitestapp_toggle_extra_window(MultiTestApp *app) {
|
||||
if (app->extra) {
|
||||
multitestapp_free_extrawindow(app);
|
||||
} else {
|
||||
app->extra= extrawindow_new(app);
|
||||
}
|
||||
}
|
||||
|
||||
void multitestapp_exit(MultiTestApp *app) {
|
||||
app->exit= 1;
|
||||
}
|
||||
|
||||
void multitestapp_run(MultiTestApp *app) {
|
||||
while (!app->exit) {
|
||||
GHOST_ProcessEvents(app->sys, 1);
|
||||
GHOST_DispatchEvents(app->sys);
|
||||
}
|
||||
}
|
||||
|
||||
void multitestapp_free(MultiTestApp *app) {
|
||||
mainwindow_free(app->main);
|
||||
loggerwindow_free(app->logger);
|
||||
GHOST_DisposeSystem(app->sys);
|
||||
MEM_freeN(app);
|
||||
}
|
||||
|
||||
/***/
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
MultiTestApp *app= multitestapp_new();
|
||||
|
||||
multitestapp_run(app);
|
||||
multitestapp_free(app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
142
intern/ghost/test/multitest/ScrollBar.c
Normal file
142
intern/ghost/test/multitest/ScrollBar.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "Basic.h"
|
||||
#include "ScrollBar.h"
|
||||
|
||||
struct _ScrollBar {
|
||||
int rect[2][2];
|
||||
float thumbpos, thumbpct;
|
||||
|
||||
int inset;
|
||||
int minthumb;
|
||||
|
||||
int scrolling;
|
||||
float scrolloffs;
|
||||
};
|
||||
|
||||
static int scrollbar_get_thumbH(ScrollBar *sb) {
|
||||
int scrollable_h= rect_height(sb->rect) - 2*sb->inset;
|
||||
|
||||
return clamp_i(sb->thumbpct*scrollable_h, sb->minthumb, scrollable_h);
|
||||
}
|
||||
static int scrollbar_get_thumbableH(ScrollBar *sb) {
|
||||
int scrollable_h= rect_height(sb->rect) - 2*sb->inset;
|
||||
int thumb_h= scrollbar_get_thumbH(sb);
|
||||
|
||||
return scrollable_h - thumb_h;
|
||||
}
|
||||
|
||||
static float scrollbar_co_to_pos(ScrollBar *sb, int yco) {
|
||||
int thumb_h= scrollbar_get_thumbH(sb);
|
||||
int thumbable_h= scrollbar_get_thumbableH(sb);
|
||||
int thumbable_y= (sb->rect[0][1]+sb->inset) + thumb_h/2;
|
||||
|
||||
return (float) (yco-thumbable_y)/thumbable_h;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
ScrollBar *scrollbar_new(int inset, int minthumb) {
|
||||
ScrollBar *sb= MEM_callocN(sizeof(*sb), "scrollbar_new");
|
||||
sb->inset= inset;
|
||||
sb->minthumb= minthumb;
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
void scrollbar_get_thumb(ScrollBar *sb, int thumb_r[2][2]) {
|
||||
int thumb_h= scrollbar_get_thumbH(sb);
|
||||
int thumbable_h= scrollbar_get_thumbableH(sb);
|
||||
|
||||
thumb_r[0][0]= sb->rect[0][0]+sb->inset;
|
||||
thumb_r[1][0]= sb->rect[1][0]-sb->inset;
|
||||
|
||||
thumb_r[0][1]= sb->rect[0][1]+sb->inset + sb->thumbpos*thumbable_h;
|
||||
thumb_r[1][1]= thumb_r[0][1] + thumb_h;
|
||||
}
|
||||
|
||||
int scrollbar_is_scrolling(ScrollBar *sb) {
|
||||
return sb->scrolling;
|
||||
}
|
||||
int scrollbar_contains_pt(ScrollBar *sb, int pt[2]) {
|
||||
return rect_contains_pt(sb->rect, pt);
|
||||
}
|
||||
|
||||
void scrollbar_start_scrolling(ScrollBar *sb, int yco) {
|
||||
int thumb_h_2= scrollbar_get_thumbH(sb)/2;
|
||||
int thumbable_h= scrollbar_get_thumbableH(sb);
|
||||
float npos= scrollbar_co_to_pos(sb, yco);
|
||||
|
||||
sb->scrolloffs= sb->thumbpos - npos;
|
||||
if (fabs(sb->scrolloffs) >= (float) thumb_h_2/thumbable_h) {
|
||||
sb->scrolloffs= 0.0;
|
||||
}
|
||||
|
||||
sb->scrolling= 1;
|
||||
sb->thumbpos= clamp_f(npos + sb->scrolloffs, 0.0, 1.0);
|
||||
}
|
||||
void scrollbar_keep_scrolling(ScrollBar *sb, int yco) {
|
||||
float npos= scrollbar_co_to_pos(sb, yco);
|
||||
|
||||
sb->thumbpos= clamp_f(npos + sb->scrolloffs, 0.0, 1.0);
|
||||
}
|
||||
void scrollbar_stop_scrolling(ScrollBar *sb) {
|
||||
sb->scrolling= 0;
|
||||
sb->scrolloffs= 0.0;
|
||||
}
|
||||
|
||||
void scrollbar_set_thumbpct(ScrollBar *sb, float pct) {
|
||||
sb->thumbpct= pct;
|
||||
}
|
||||
void scrollbar_set_thumbpos(ScrollBar *sb, float pos) {
|
||||
sb->thumbpos= clamp_f(pos, 0.0, 1.0);
|
||||
}
|
||||
void scrollbar_set_rect(ScrollBar *sb, int rect[2][2]) {
|
||||
rect_copy(sb->rect, rect);
|
||||
}
|
||||
|
||||
float scrollbar_get_thumbpct(ScrollBar *sb) {
|
||||
return sb->thumbpct;
|
||||
}
|
||||
float scrollbar_get_thumbpos(ScrollBar *sb) {
|
||||
return sb->thumbpos;
|
||||
}
|
||||
void scrollbar_get_rect(ScrollBar *sb, int rect_r[2][2]) {
|
||||
rect_copy(rect_r, sb->rect);
|
||||
}
|
||||
|
||||
void scrollbar_free(ScrollBar *sb) {
|
||||
MEM_freeN(sb);
|
||||
}
|
||||
54
intern/ghost/test/multitest/ScrollBar.h
Normal file
54
intern/ghost/test/multitest/ScrollBar.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
typedef struct _ScrollBar ScrollBar;
|
||||
|
||||
|
||||
/***/
|
||||
|
||||
ScrollBar* scrollbar_new (int inset, int minthumb);
|
||||
|
||||
int scrollbar_is_scrolling (ScrollBar *sb);
|
||||
int scrollbar_contains_pt (ScrollBar *sb, int pt[2]);
|
||||
|
||||
void scrollbar_start_scrolling (ScrollBar *sb, int yco);
|
||||
void scrollbar_keep_scrolling (ScrollBar *sb, int yco);
|
||||
void scrollbar_stop_scrolling (ScrollBar *sb);
|
||||
|
||||
void scrollbar_set_thumbpct (ScrollBar *sb, float pct);
|
||||
void scrollbar_set_thumbpos (ScrollBar *sb, float pos);
|
||||
void scrollbar_set_rect (ScrollBar *sb, int rect[2][2]);
|
||||
|
||||
float scrollbar_get_thumbpct (ScrollBar *sb);
|
||||
float scrollbar_get_thumbpos (ScrollBar *sb);
|
||||
void scrollbar_get_rect (ScrollBar *sb, int rect_r[2][2]);
|
||||
|
||||
void scrollbar_get_thumb (ScrollBar *sb, int thumb_r[2][2]);
|
||||
|
||||
void scrollbar_free (ScrollBar *sb);
|
||||
|
||||
70
intern/ghost/test/multitest/Util.c
Normal file
70
intern/ghost/test/multitest/Util.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
void* memdbl(void *mem, int *size_pr, int item_size) {
|
||||
int cur_size= *size_pr;
|
||||
int new_size= cur_size?(cur_size*2):1;
|
||||
void *nmem= MEM_mallocN(new_size*item_size, "memdbl");
|
||||
|
||||
memcpy(nmem, mem, cur_size*item_size);
|
||||
MEM_freeN(mem);
|
||||
|
||||
*size_pr= new_size;
|
||||
return nmem;
|
||||
}
|
||||
|
||||
char* string_dup(char *str) {
|
||||
int len= strlen(str);
|
||||
char *nstr= MEM_mallocN(len + 1, "string_dup");
|
||||
|
||||
memcpy(nstr, str, len+1);
|
||||
|
||||
return nstr;
|
||||
}
|
||||
|
||||
void fatal(char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "FATAL: ");
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
33
intern/ghost/test/multitest/Util.h
Normal file
33
intern/ghost/test/multitest/Util.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
void* memdbl (void *mem, int *size_pr, int item_size);
|
||||
|
||||
char* string_dup (char *str);
|
||||
void fatal (char *fmt, ...);
|
||||
|
||||
56
intern/ghost/test/multitest/WindowData.c
Normal file
56
intern/ghost/test/multitest/WindowData.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
|
||||
#include "WindowData.h"
|
||||
|
||||
struct _WindowData {
|
||||
void *data;
|
||||
WindowDataHandler handler;
|
||||
};
|
||||
|
||||
WindowData *windowdata_new(void *data, WindowDataHandler handler) {
|
||||
WindowData *wb= MEM_mallocN(sizeof(*wb), "windowdata_new");
|
||||
wb->data= data;
|
||||
wb->handler= handler;
|
||||
|
||||
return wb;
|
||||
}
|
||||
|
||||
void windowdata_handle(WindowData *wb, GHOST_EventHandle evt) {
|
||||
wb->handler(wb->data, evt);
|
||||
}
|
||||
|
||||
void windowdata_free(WindowData *wb) {
|
||||
MEM_freeN(wb);
|
||||
}
|
||||
37
intern/ghost/test/multitest/WindowData.h
Normal file
37
intern/ghost/test/multitest/WindowData.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
*/
|
||||
|
||||
typedef void (*WindowDataHandler)(void *priv, GHOST_EventHandle evt);
|
||||
typedef struct _WindowData WindowData;
|
||||
|
||||
/***/
|
||||
|
||||
WindowData* windowdata_new (void *data, WindowDataHandler handler);
|
||||
void windowdata_handle (WindowData *wb, GHOST_EventHandle evt);
|
||||
void windowdata_free (WindowData *wb);
|
||||
|
||||
52
intern/guardedalloc/CMakeLists.txt
Normal file
52
intern/guardedalloc/CMakeLists.txt
Normal file
@@ -0,0 +1,52 @@
|
||||
# $Id$
|
||||
# ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2006, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# Contributor(s): Jacques Beaurain.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(INC .)
|
||||
|
||||
set(SRC
|
||||
./intern/mallocn.c
|
||||
|
||||
MEM_guardedalloc.h
|
||||
MEM_sys_types.h
|
||||
)
|
||||
|
||||
if(WIN32 AND NOT UNIX)
|
||||
list(APPEND SRC
|
||||
intern/mmap_win.c
|
||||
|
||||
mmap_win.h
|
||||
)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_intern_guardedalloc "${SRC}" "${INC}")
|
||||
|
||||
# Override C++ alloc, optional.
|
||||
if(WITH_CXX_GUARDEDALLOC)
|
||||
set(SRC
|
||||
cpp/mallocn.cpp
|
||||
)
|
||||
blender_add_lib(bf_intern_guardedalloc_cpp "${SRC}" "${INC}")
|
||||
endif()
|
||||
177
intern/guardedalloc/MEM_guardedalloc.h
Normal file
177
intern/guardedalloc/MEM_guardedalloc.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 MEM_guardedalloc.h
|
||||
* \ingroup MEM
|
||||
*
|
||||
* \author Copyright (C) 2001 NaN Technologies B.V.
|
||||
* \brief Read \ref MEMPage
|
||||
*/
|
||||
|
||||
/**
|
||||
* \page MEMPage Guarded memory(de)allocation
|
||||
*
|
||||
* \section aboutmem c-style guarded memory allocation
|
||||
*
|
||||
* \subsection memabout About the MEM module
|
||||
*
|
||||
* MEM provides guarded malloc/calloc calls. All memory is enclosed by
|
||||
* pads, to detect out-of-bound writes. All blocks are placed in a
|
||||
* linked list, so they remain reachable at all times. There is no
|
||||
* back-up in case the linked-list related data is lost.
|
||||
*
|
||||
* \subsection memissues Known issues with MEM
|
||||
*
|
||||
* There are currently no known issues with MEM. Note that there is a
|
||||
* second intern/ module with MEM_ prefix, for use in c++.
|
||||
*
|
||||
* \subsection memdependencies Dependencies
|
||||
* - stdlib
|
||||
* - stdio
|
||||
*
|
||||
* \subsection memdocs API Documentation
|
||||
* See \ref MEM_guardedalloc.h
|
||||
*/
|
||||
|
||||
#ifndef MEM_MALLOCN_H
|
||||
#define MEM_MALLOCN_H
|
||||
|
||||
#include <stdio.h> /* needed for FILE* */
|
||||
#include "MEM_sys_types.h" /* needed for uintptr_t */
|
||||
|
||||
#ifndef WARN_UNUSED
|
||||
# ifdef __GNUC__
|
||||
# define WARN_UNUSED __attribute__((warn_unused_result))
|
||||
# else
|
||||
# define WARN_UNUSED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Returns the length of the allocated memory segment pointed at
|
||||
* by vmemh. If the pointer was not previously allocated by this
|
||||
* module, the result is undefined.*/
|
||||
size_t MEM_allocN_len(void *vmemh) WARN_UNUSED;
|
||||
|
||||
/**
|
||||
* Release memory previously allocatred by this module.
|
||||
*/
|
||||
short MEM_freeN(void *vmemh);
|
||||
|
||||
|
||||
/**
|
||||
* Return zero if memory is not in allocated list
|
||||
*/
|
||||
short MEM_testN(void *vmemh);
|
||||
|
||||
/**
|
||||
* Duplicates a block of memory, and returns a pointer to the
|
||||
* newly allocated block. */
|
||||
void *MEM_dupallocN(void *vmemh) WARN_UNUSED;
|
||||
|
||||
/**
|
||||
* Reallocates a block of memory, and returns pointer to the newly
|
||||
* allocated block, the old one is freed. this is not as optimized
|
||||
* as a system realloc but just makes a new allocation and copies
|
||||
* over from existing memory. */
|
||||
void *MEM_reallocN(void *vmemh, size_t len) WARN_UNUSED;
|
||||
|
||||
/**
|
||||
* Allocate a block of memory of size len, with tag name str. The
|
||||
* memory is cleared. The name must be static, because only a
|
||||
* pointer to it is stored ! */
|
||||
void *MEM_callocN(size_t len, const char * str) WARN_UNUSED;
|
||||
|
||||
/** Allocate a block of memory of size len, with tag name str. The
|
||||
* name must be a static, because only a pointer to it is stored !
|
||||
* */
|
||||
void *MEM_mallocN(size_t len, const char * str) WARN_UNUSED;
|
||||
|
||||
/** Same as callocN, clears memory and uses mmap (disk cached) if supported.
|
||||
Can be free'd with MEM_freeN as usual.
|
||||
* */
|
||||
void *MEM_mapallocN(size_t len, const char * str) WARN_UNUSED;
|
||||
|
||||
/** Print a list of the names and sizes of all allocated memory
|
||||
* blocks. as a python dict for easy investigation */
|
||||
void MEM_printmemlist_pydict(void);
|
||||
|
||||
/** Print a list of the names and sizes of all allocated memory
|
||||
* blocks. */
|
||||
void MEM_printmemlist(void);
|
||||
|
||||
/** calls the function on all allocated memory blocks. */
|
||||
void MEM_callbackmemlist(void (*func)(void*));
|
||||
|
||||
/** Print statistics about memory usage */
|
||||
void MEM_printmemlist_stats(void);
|
||||
|
||||
/** Set the callback function for error output. */
|
||||
void MEM_set_error_callback(void (*func)(const char *));
|
||||
|
||||
/**
|
||||
* Are the start/end block markers still correct ?
|
||||
*
|
||||
* @retval 0 for correct memory, 1 for corrupted memory. */
|
||||
int MEM_check_memory_integrity(void);
|
||||
|
||||
/** Set thread locking functions for safe memory allocation from multiple
|
||||
threads, pass NULL pointers to disable thread locking again. */
|
||||
void MEM_set_lock_callback(void (*lock)(void), void (*unlock)(void));
|
||||
|
||||
/** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */
|
||||
void MEM_set_memory_debug(void);
|
||||
|
||||
/** Memory usage stats
|
||||
* - MEM_get_memory_in_use is all memory
|
||||
* - MEM_get_mapped_memory_in_use is a subset of all memory */
|
||||
uintptr_t MEM_get_memory_in_use(void);
|
||||
/** Get mapped memory usage. */
|
||||
uintptr_t MEM_get_mapped_memory_in_use(void);
|
||||
/** Get amount of memory blocks in use. */
|
||||
int MEM_get_memory_blocks_in_use(void);
|
||||
|
||||
/** Reset the peak memory statistic to zero. */
|
||||
void MEM_reset_peak_memory(void);
|
||||
|
||||
/** Get the peak memory usage in bytes, including mmap allocations. */
|
||||
uintptr_t MEM_get_peak_memory(void) WARN_UNUSED;
|
||||
|
||||
#ifndef NDEBUG
|
||||
const char *MEM_name_ptr(void *vmemh);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
131
intern/guardedalloc/MEM_sys_types.h
Normal file
131
intern/guardedalloc/MEM_sys_types.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
|
||||
* A platform-independent definition of [u]intXX_t
|
||||
* Plus the accompanying header include for htonl/ntohl
|
||||
*
|
||||
* This file includes <sys/types.h> to define [u]intXX_t types, where
|
||||
* XX can be 8, 16, 32 or 64. Unfortunately, not all systems have this
|
||||
* file.
|
||||
* - Windows uses __intXX compiler-builtin types. These are signed,
|
||||
* so we have to flip the signs.
|
||||
* For these rogue platforms, we make the typedefs ourselves.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
// DG: original BLO_sys_types.h is in source/blender/blenkernel
|
||||
// but is not allowed be accessed here because of bad-level-call
|
||||
// jesterKing: I've renamed this to MEM_sys_types.h, because otherwise
|
||||
// doxygen would get a conflict
|
||||
*/
|
||||
|
||||
/** \file MEM_sys_types.h
|
||||
* \ingroup MEM
|
||||
*/
|
||||
|
||||
#ifndef MEM_SYS_TYPES_H
|
||||
#define MEM_SYS_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(FREE_WINDOWS)
|
||||
|
||||
/* The __intXX are built-in types of the visual complier! So we don't
|
||||
* need to include anything else here. */
|
||||
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
#ifndef _INTPTR_T_DEFINED
|
||||
#ifdef _WIN64
|
||||
typedef __int64 intptr_t;
|
||||
#else
|
||||
typedef long intptr_t;
|
||||
#endif
|
||||
#define _INTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
#ifndef _UINTPTR_T_DEFINED
|
||||
#ifdef _WIN64
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else
|
||||
typedef unsigned long uintptr_t;
|
||||
#endif
|
||||
#define _UINTPTR_T_DEFINED
|
||||
#endif
|
||||
|
||||
#elif defined(__linux__) || defined(__NetBSD__)
|
||||
|
||||
/* Linux-i386, Linux-Alpha, Linux-ppc */
|
||||
#include <stdint.h>
|
||||
|
||||
#elif defined (__APPLE__)
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#elif defined(FREE_WINDOWS)
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#else
|
||||
|
||||
/* FreeBSD, Irix, Solaris */
|
||||
#include <sys/types.h>
|
||||
|
||||
#endif /* ifdef platform for types */
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef htonl
|
||||
#define htonl(x) correctByteOrder(x)
|
||||
#endif
|
||||
#ifndef ntohl
|
||||
#define ntohl(x) correctByteOrder(x)
|
||||
#endif
|
||||
#elif defined (__FreeBSD__) || defined (__OpenBSD__)
|
||||
#include <sys/param.h>
|
||||
#elif defined (__APPLE__)
|
||||
#include <sys/types.h>
|
||||
#else /* irix sun linux */
|
||||
#include <netinet/in.h>
|
||||
#endif /* ifdef platform for htonl/ntohl */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MEM_SYS_TYPES_H */
|
||||
|
||||
15
intern/guardedalloc/SConscript
Normal file
15
intern/guardedalloc/SConscript
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
Import('env')
|
||||
|
||||
defs = []
|
||||
|
||||
sources = ['intern/mallocn.c', 'intern/mmap_win.c']
|
||||
|
||||
if env['WITH_BF_CXX_GUARDEDALLOC']:
|
||||
sources.append('cpp/mallocn.cpp')
|
||||
defs.append('WITH_CXX_GUARDEDALLOC')
|
||||
|
||||
incs = '.'
|
||||
|
||||
env.BlenderLib ('bf_intern_guardedalloc', sources, Split(incs), defs, libtype=['intern','player'], priority = [5,150] )
|
||||
46
intern/guardedalloc/cpp/mallocn.cpp
Normal file
46
intern/guardedalloc/cpp/mallocn.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Contributor(s): Campbell Barton
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file guardedalloc/cpp/mallocn.cpp
|
||||
* \ingroup MEM
|
||||
*/
|
||||
|
||||
|
||||
#include <new>
|
||||
#include "../MEM_guardedalloc.h"
|
||||
|
||||
void* operator new (size_t size)
|
||||
{
|
||||
return MEM_mallocN(size, "C++/anonymous");
|
||||
}
|
||||
|
||||
/* not default but can be used when needing to set a string */
|
||||
void* operator new (size_t size, const char *str)
|
||||
{
|
||||
return MEM_mallocN(size, str);
|
||||
}
|
||||
|
||||
void operator delete (void *p)
|
||||
{
|
||||
MEM_freeN(p);
|
||||
}
|
||||
879
intern/guardedalloc/intern/mallocn.c
Normal file
879
intern/guardedalloc/intern/mallocn.c
Normal file
@@ -0,0 +1,879 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 guardedalloc/intern/mallocn.c
|
||||
* \ingroup MEM
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* $Id$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* Guarded memory allocation, and boundary-write detection.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h> /* memcpy */
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
/* Blame Microsoft for LLP64 and no inttypes.h, quick workaround needed: */
|
||||
#if defined(WIN64)
|
||||
#define SIZET_FORMAT "%I64u"
|
||||
#define SIZET_ARG(a) ((unsigned long long)(a))
|
||||
#else
|
||||
#define SIZET_FORMAT "%lu"
|
||||
#define SIZET_ARG(a) ((unsigned long)(a))
|
||||
#endif
|
||||
|
||||
/* mmap exception */
|
||||
#if defined(WIN32)
|
||||
#include "mmap_win.h"
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
/* Only for debugging:
|
||||
* lets you count the allocations so as to find the allocator of unfreed memory
|
||||
* in situations where the leak is predictable */
|
||||
|
||||
// #define DEBUG_MEMCOUNTER
|
||||
|
||||
#ifdef DEBUG_MEMCOUNTER
|
||||
#define DEBUG_MEMCOUNTER_ERROR_VAL 0 /* set this to the value that isnt being freed */
|
||||
static int _mallocn_count = 0;
|
||||
|
||||
/* breakpoint here */
|
||||
static void memcount_raise(const char *name)
|
||||
{
|
||||
fprintf(stderr, "%s: memcount-leak, %d\n", name, _mallocn_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* Data definition */
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* all memory chunks are put in linked lists */
|
||||
typedef struct localLink
|
||||
{
|
||||
struct localLink *next,*prev;
|
||||
} localLink;
|
||||
|
||||
typedef struct localListBase
|
||||
{
|
||||
void *first, *last;
|
||||
} localListBase;
|
||||
|
||||
/* note: keep this struct aligned (e.g., irix/gcc) - Hos */
|
||||
typedef struct MemHead {
|
||||
int tag1;
|
||||
size_t len;
|
||||
struct MemHead *next,*prev;
|
||||
const char * name;
|
||||
const char * nextname;
|
||||
int tag2;
|
||||
int mmap; /* if true, memory was mmapped */
|
||||
#ifdef DEBUG_MEMCOUNTER
|
||||
int _count;
|
||||
#endif
|
||||
} MemHead;
|
||||
|
||||
typedef struct MemTail {
|
||||
int tag3, pad;
|
||||
} MemTail;
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void addtail(volatile localListBase *listbase, void *vlink);
|
||||
static void remlink(volatile localListBase *listbase, void *vlink);
|
||||
static void rem_memblock(MemHead *memh);
|
||||
static void MemorY_ErroR(const char *block, const char *error);
|
||||
static const char *check_memlist(MemHead *memh);
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* locally used defines */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#if defined( __sgi) || defined (__sun) || defined (__sun__) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || (defined (__APPLE__) && !defined(__LITTLE_ENDIAN__))
|
||||
#define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
|
||||
#else
|
||||
#define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
|
||||
#endif
|
||||
|
||||
#define MEMTAG1 MAKE_ID('M', 'E', 'M', 'O')
|
||||
#define MEMTAG2 MAKE_ID('R', 'Y', 'B', 'L')
|
||||
#define MEMTAG3 MAKE_ID('O', 'C', 'K', '!')
|
||||
#define MEMFREE MAKE_ID('F', 'R', 'E', 'E')
|
||||
|
||||
#define MEMNEXT(x) ((MemHead *)(((char *) x) - ((char *) & (((MemHead *)0)->next))))
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* vars */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
|
||||
static volatile int totblock= 0;
|
||||
static volatile uintptr_t mem_in_use= 0, mmap_in_use= 0, peak_mem = 0;
|
||||
|
||||
static volatile struct localListBase _membase;
|
||||
static volatile struct localListBase *membase = &_membase;
|
||||
static void (*error_callback)(const char *) = NULL;
|
||||
static void (*thread_lock_callback)(void) = NULL;
|
||||
static void (*thread_unlock_callback)(void) = NULL;
|
||||
|
||||
static int malloc_debug_memset= 0;
|
||||
|
||||
#ifdef malloc
|
||||
#undef malloc
|
||||
#endif
|
||||
|
||||
#ifdef calloc
|
||||
#undef calloc
|
||||
#endif
|
||||
|
||||
#ifdef free
|
||||
#undef free
|
||||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* implementation */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void print_error(const char *str, ...)
|
||||
{
|
||||
char buf[512];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, str);
|
||||
vsnprintf(buf, sizeof(buf), str, ap);
|
||||
va_end(ap);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
|
||||
if (error_callback) error_callback(buf);
|
||||
}
|
||||
|
||||
static void mem_lock_thread(void)
|
||||
{
|
||||
if (thread_lock_callback)
|
||||
thread_lock_callback();
|
||||
}
|
||||
|
||||
static void mem_unlock_thread(void)
|
||||
{
|
||||
if (thread_unlock_callback)
|
||||
thread_unlock_callback();
|
||||
}
|
||||
|
||||
int MEM_check_memory_integrity(void)
|
||||
{
|
||||
const char* err_val = NULL;
|
||||
MemHead* listend;
|
||||
/* check_memlist starts from the front, and runs until it finds
|
||||
* the requested chunk. For this test, that's the last one. */
|
||||
listend = membase->last;
|
||||
|
||||
err_val = check_memlist(listend);
|
||||
|
||||
if (err_val == NULL) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void MEM_set_error_callback(void (*func)(const char *))
|
||||
{
|
||||
error_callback = func;
|
||||
}
|
||||
|
||||
void MEM_set_lock_callback(void (*lock)(void), void (*unlock)(void))
|
||||
{
|
||||
thread_lock_callback = lock;
|
||||
thread_unlock_callback = unlock;
|
||||
}
|
||||
|
||||
void MEM_set_memory_debug(void)
|
||||
{
|
||||
malloc_debug_memset= 1;
|
||||
}
|
||||
|
||||
size_t MEM_allocN_len(void *vmemh)
|
||||
{
|
||||
if (vmemh) {
|
||||
MemHead *memh= vmemh;
|
||||
|
||||
memh--;
|
||||
return memh->len;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *MEM_dupallocN(void *vmemh)
|
||||
{
|
||||
void *newp= NULL;
|
||||
|
||||
if (vmemh) {
|
||||
MemHead *memh= vmemh;
|
||||
memh--;
|
||||
|
||||
if(memh->mmap)
|
||||
newp= MEM_mapallocN(memh->len, "dupli_mapalloc");
|
||||
else
|
||||
newp= MEM_mallocN(memh->len, "dupli_alloc");
|
||||
|
||||
if (newp == NULL) return NULL;
|
||||
|
||||
memcpy(newp, vmemh, memh->len);
|
||||
}
|
||||
|
||||
return newp;
|
||||
}
|
||||
|
||||
void *MEM_reallocN(void *vmemh, size_t len)
|
||||
{
|
||||
void *newp= NULL;
|
||||
|
||||
if (vmemh) {
|
||||
MemHead *memh= vmemh;
|
||||
memh--;
|
||||
|
||||
newp= MEM_mallocN(len, memh->name);
|
||||
if(newp) {
|
||||
if(len < memh->len)
|
||||
memcpy(newp, vmemh, len);
|
||||
else
|
||||
memcpy(newp, vmemh, memh->len);
|
||||
}
|
||||
|
||||
MEM_freeN(vmemh);
|
||||
}
|
||||
|
||||
return newp;
|
||||
}
|
||||
|
||||
static void make_memhead_header(MemHead *memh, size_t len, const char *str)
|
||||
{
|
||||
MemTail *memt;
|
||||
|
||||
memh->tag1 = MEMTAG1;
|
||||
memh->name = str;
|
||||
memh->nextname = NULL;
|
||||
memh->len = len;
|
||||
memh->mmap = 0;
|
||||
memh->tag2 = MEMTAG2;
|
||||
|
||||
memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + len);
|
||||
memt->tag3 = MEMTAG3;
|
||||
|
||||
addtail(membase,&memh->next);
|
||||
if (memh->next) memh->nextname = MEMNEXT(memh->next)->name;
|
||||
|
||||
totblock++;
|
||||
mem_in_use += len;
|
||||
|
||||
peak_mem = mem_in_use > peak_mem ? mem_in_use : peak_mem;
|
||||
}
|
||||
|
||||
void *MEM_mallocN(size_t len, const char *str)
|
||||
{
|
||||
MemHead *memh;
|
||||
|
||||
mem_lock_thread();
|
||||
|
||||
len = (len + 3 ) & ~3; /* allocate in units of 4 */
|
||||
|
||||
memh= (MemHead *)malloc(len+sizeof(MemHead)+sizeof(MemTail));
|
||||
|
||||
if(memh) {
|
||||
make_memhead_header(memh, len, str);
|
||||
mem_unlock_thread();
|
||||
if(malloc_debug_memset && len)
|
||||
memset(memh+1, 255, len);
|
||||
|
||||
#ifdef DEBUG_MEMCOUNTER
|
||||
if(_mallocn_count==DEBUG_MEMCOUNTER_ERROR_VAL)
|
||||
memcount_raise("MEM_mallocN");
|
||||
memh->_count= _mallocn_count++;
|
||||
#endif
|
||||
return (++memh);
|
||||
}
|
||||
mem_unlock_thread();
|
||||
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n", SIZET_ARG(len), str, mem_in_use);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *MEM_callocN(size_t len, const char *str)
|
||||
{
|
||||
MemHead *memh;
|
||||
|
||||
mem_lock_thread();
|
||||
|
||||
len = (len + 3 ) & ~3; /* allocate in units of 4 */
|
||||
|
||||
memh= (MemHead *)calloc(len+sizeof(MemHead)+sizeof(MemTail),1);
|
||||
|
||||
if(memh) {
|
||||
make_memhead_header(memh, len, str);
|
||||
mem_unlock_thread();
|
||||
#ifdef DEBUG_MEMCOUNTER
|
||||
if(_mallocn_count==DEBUG_MEMCOUNTER_ERROR_VAL)
|
||||
memcount_raise("MEM_callocN");
|
||||
memh->_count= _mallocn_count++;
|
||||
#endif
|
||||
return (++memh);
|
||||
}
|
||||
mem_unlock_thread();
|
||||
print_error("Calloc returns null: len=" SIZET_FORMAT " in %s, total %u\n", SIZET_ARG(len), str, mem_in_use);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* note; mmap returns zero'd memory */
|
||||
void *MEM_mapallocN(size_t len, const char *str)
|
||||
{
|
||||
MemHead *memh;
|
||||
|
||||
mem_lock_thread();
|
||||
|
||||
len = (len + 3 ) & ~3; /* allocate in units of 4 */
|
||||
|
||||
#ifdef __sgi
|
||||
{
|
||||
#include <fcntl.h>
|
||||
|
||||
int fd;
|
||||
fd = open("/dev/zero", O_RDWR);
|
||||
|
||||
memh= mmap(0, len+sizeof(MemHead)+sizeof(MemTail),
|
||||
PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
close(fd);
|
||||
}
|
||||
#else
|
||||
memh= mmap(NULL, len+sizeof(MemHead)+sizeof(MemTail),
|
||||
PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);
|
||||
#endif
|
||||
|
||||
if(memh!=(MemHead *)-1) {
|
||||
make_memhead_header(memh, len, str);
|
||||
memh->mmap= 1;
|
||||
mmap_in_use += len;
|
||||
peak_mem = mmap_in_use > peak_mem ? mmap_in_use : peak_mem;
|
||||
mem_unlock_thread();
|
||||
#ifdef DEBUG_MEMCOUNTER
|
||||
if(_mallocn_count==DEBUG_MEMCOUNTER_ERROR_VAL)
|
||||
memcount_raise("MEM_mapallocN");
|
||||
memh->_count= _mallocn_count++;
|
||||
#endif
|
||||
return (++memh);
|
||||
}
|
||||
else {
|
||||
mem_unlock_thread();
|
||||
print_error("Mapalloc returns null, fallback to regular malloc: len=" SIZET_FORMAT " in %s, total %u\n", SIZET_ARG(len), str, mmap_in_use);
|
||||
return MEM_callocN(len, str);
|
||||
}
|
||||
}
|
||||
|
||||
/* Memory statistics print */
|
||||
typedef struct MemPrintBlock {
|
||||
const char *name;
|
||||
uintptr_t len;
|
||||
int items;
|
||||
} MemPrintBlock;
|
||||
|
||||
static int compare_name(const void *p1, const void *p2)
|
||||
{
|
||||
const MemPrintBlock *pb1= (const MemPrintBlock*)p1;
|
||||
const MemPrintBlock *pb2= (const MemPrintBlock*)p2;
|
||||
|
||||
return strcmp(pb1->name, pb2->name);
|
||||
}
|
||||
|
||||
static int compare_len(const void *p1, const void *p2)
|
||||
{
|
||||
const MemPrintBlock *pb1= (const MemPrintBlock*)p1;
|
||||
const MemPrintBlock *pb2= (const MemPrintBlock*)p2;
|
||||
|
||||
if(pb1->len < pb2->len)
|
||||
return 1;
|
||||
else if(pb1->len == pb2->len)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MEM_printmemlist_stats()
|
||||
{
|
||||
MemHead *membl;
|
||||
MemPrintBlock *pb, *printblock;
|
||||
int totpb, a, b;
|
||||
|
||||
mem_lock_thread();
|
||||
|
||||
/* put memory blocks into array */
|
||||
printblock= malloc(sizeof(MemPrintBlock)*totblock);
|
||||
|
||||
pb= printblock;
|
||||
totpb= 0;
|
||||
|
||||
membl = membase->first;
|
||||
if (membl) membl = MEMNEXT(membl);
|
||||
|
||||
while(membl) {
|
||||
pb->name= membl->name;
|
||||
pb->len= membl->len;
|
||||
pb->items= 1;
|
||||
|
||||
totpb++;
|
||||
pb++;
|
||||
|
||||
if(membl->next)
|
||||
membl= MEMNEXT(membl->next);
|
||||
else break;
|
||||
}
|
||||
|
||||
/* sort by name and add together blocks with the same name */
|
||||
qsort(printblock, totpb, sizeof(MemPrintBlock), compare_name);
|
||||
for(a=0, b=0; a<totpb; a++) {
|
||||
if(a == b) {
|
||||
continue;
|
||||
}
|
||||
else if(strcmp(printblock[a].name, printblock[b].name) == 0) {
|
||||
printblock[b].len += printblock[a].len;
|
||||
printblock[b].items++;
|
||||
}
|
||||
else {
|
||||
b++;
|
||||
memcpy(&printblock[b], &printblock[a], sizeof(MemPrintBlock));
|
||||
}
|
||||
}
|
||||
totpb= b+1;
|
||||
|
||||
/* sort by length and print */
|
||||
qsort(printblock, totpb, sizeof(MemPrintBlock), compare_len);
|
||||
printf("\ntotal memory len: %.3f MB\n", (double)mem_in_use/(double)(1024*1024));
|
||||
printf(" ITEMS TOTAL-MiB AVERAGE-KiB TYPE\n");
|
||||
for(a=0, pb=printblock; a<totpb; a++, pb++)
|
||||
printf("%6d (%8.3f %8.3f) %s\n", pb->items, (double)pb->len/(double)(1024*1024), (double)pb->len/1024.0/(double)pb->items, pb->name);
|
||||
|
||||
free(printblock);
|
||||
|
||||
mem_unlock_thread();
|
||||
|
||||
#if 0 /* GLIBC only */
|
||||
malloc_stats();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Prints in python syntax for easy */
|
||||
static void MEM_printmemlist_internal( int pydict )
|
||||
{
|
||||
MemHead *membl;
|
||||
|
||||
mem_lock_thread();
|
||||
|
||||
membl = membase->first;
|
||||
if (membl) membl = MEMNEXT(membl);
|
||||
|
||||
if (pydict) {
|
||||
print_error("# membase_debug.py\n");
|
||||
print_error("membase = [\\\n");
|
||||
}
|
||||
while(membl) {
|
||||
if (pydict) {
|
||||
fprintf(stderr, "{'len':" SIZET_FORMAT ", 'name':'''%s''', 'pointer':'%p'},\\\n", SIZET_ARG(membl->len), membl->name, (void *)(membl+1));
|
||||
} else {
|
||||
#ifdef DEBUG_MEMCOUNTER
|
||||
print_error("%s len: " SIZET_FORMAT " %p, count: %d\n", membl->name, SIZET_ARG(membl->len), membl+1, membl->_count);
|
||||
#else
|
||||
print_error("%s len: " SIZET_FORMAT " %p\n", membl->name, SIZET_ARG(membl->len), membl+1);
|
||||
#endif
|
||||
}
|
||||
if(membl->next)
|
||||
membl= MEMNEXT(membl->next);
|
||||
else break;
|
||||
}
|
||||
if (pydict) {
|
||||
fprintf(stderr, "]\n\n");
|
||||
fprintf(stderr,
|
||||
"mb_userinfo = {}\n"
|
||||
"totmem = 0\n"
|
||||
"for mb_item in membase:\n"
|
||||
"\tmb_item_user_size = mb_userinfo.setdefault(mb_item['name'], [0,0])\n"
|
||||
"\tmb_item_user_size[0] += 1 # Add a user\n"
|
||||
"\tmb_item_user_size[1] += mb_item['len'] # Increment the size\n"
|
||||
"\ttotmem += mb_item['len']\n"
|
||||
"print '(membase) items:', len(membase), '| unique-names:', len(mb_userinfo), '| total-mem:', totmem\n"
|
||||
"mb_userinfo_sort = mb_userinfo.items()\n"
|
||||
"for sort_name, sort_func in (('size', lambda a: -a[1][1]), ('users', lambda a: -a[1][0]), ('name', lambda a: a[0])):\n"
|
||||
"\tprint '\\nSorting by:', sort_name\n"
|
||||
"\tmb_userinfo_sort.sort(key = sort_func)\n"
|
||||
"\tfor item in mb_userinfo_sort:\n"
|
||||
"\t\tprint 'name:%%s, users:%%i, len:%%i' %% (item[0], item[1][0], item[1][1])\n"
|
||||
);
|
||||
}
|
||||
|
||||
mem_unlock_thread();
|
||||
}
|
||||
|
||||
void MEM_callbackmemlist(void (*func)(void*)) {
|
||||
MemHead *membl;
|
||||
|
||||
mem_lock_thread();
|
||||
|
||||
membl = membase->first;
|
||||
if (membl) membl = MEMNEXT(membl);
|
||||
|
||||
while(membl) {
|
||||
func(membl+1);
|
||||
if(membl->next)
|
||||
membl= MEMNEXT(membl->next);
|
||||
else break;
|
||||
}
|
||||
|
||||
mem_unlock_thread();
|
||||
}
|
||||
|
||||
short MEM_testN(void *vmemh) {
|
||||
MemHead *membl;
|
||||
|
||||
mem_lock_thread();
|
||||
|
||||
membl = membase->first;
|
||||
if (membl) membl = MEMNEXT(membl);
|
||||
|
||||
while(membl) {
|
||||
if (vmemh == membl+1) {
|
||||
mem_unlock_thread();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(membl->next)
|
||||
membl= MEMNEXT(membl->next);
|
||||
else break;
|
||||
}
|
||||
|
||||
mem_unlock_thread();
|
||||
|
||||
print_error("Memoryblock %p: pointer not in memlist\n", vmemh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MEM_printmemlist( void ) {
|
||||
MEM_printmemlist_internal(0);
|
||||
}
|
||||
void MEM_printmemlist_pydict( void ) {
|
||||
MEM_printmemlist_internal(1);
|
||||
}
|
||||
|
||||
short MEM_freeN(void *vmemh) /* anders compileertie niet meer */
|
||||
{
|
||||
short error = 0;
|
||||
MemTail *memt;
|
||||
MemHead *memh= vmemh;
|
||||
const char *name;
|
||||
|
||||
if (memh == NULL){
|
||||
MemorY_ErroR("free","attempt to free NULL pointer");
|
||||
/* print_error(err_stream, "%d\n", (memh+4000)->tag1); */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if(sizeof(intptr_t)==8) {
|
||||
if (((intptr_t) memh) & 0x7) {
|
||||
MemorY_ErroR("free","attempt to free illegal pointer");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (((intptr_t) memh) & 0x3) {
|
||||
MemorY_ErroR("free","attempt to free illegal pointer");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
memh--;
|
||||
if(memh->tag1 == MEMFREE && memh->tag2 == MEMFREE) {
|
||||
MemorY_ErroR(memh->name,"double free");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
mem_lock_thread();
|
||||
if ((memh->tag1 == MEMTAG1) && (memh->tag2 == MEMTAG2) && ((memh->len & 0x3) == 0)) {
|
||||
memt = (MemTail *)(((char *) memh) + sizeof(MemHead) + memh->len);
|
||||
if (memt->tag3 == MEMTAG3){
|
||||
|
||||
memh->tag1 = MEMFREE;
|
||||
memh->tag2 = MEMFREE;
|
||||
memt->tag3 = MEMFREE;
|
||||
/* after tags !!! */
|
||||
rem_memblock(memh);
|
||||
|
||||
mem_unlock_thread();
|
||||
|
||||
return(0);
|
||||
}
|
||||
error = 2;
|
||||
MemorY_ErroR(memh->name,"end corrupt");
|
||||
name = check_memlist(memh);
|
||||
if (name != NULL){
|
||||
if (name != memh->name) MemorY_ErroR(name,"is also corrupt");
|
||||
}
|
||||
} else{
|
||||
error = -1;
|
||||
name = check_memlist(memh);
|
||||
if (name == NULL)
|
||||
MemorY_ErroR("free","pointer not in memlist");
|
||||
else
|
||||
MemorY_ErroR(name,"error in header");
|
||||
}
|
||||
|
||||
totblock--;
|
||||
/* here a DUMP should happen */
|
||||
|
||||
mem_unlock_thread();
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void addtail(volatile localListBase *listbase, void *vlink)
|
||||
{
|
||||
struct localLink *link= vlink;
|
||||
|
||||
if (link == NULL) return;
|
||||
if (listbase == NULL) return;
|
||||
|
||||
link->next = NULL;
|
||||
link->prev = listbase->last;
|
||||
|
||||
if (listbase->last) ((struct localLink *)listbase->last)->next = link;
|
||||
if (listbase->first == NULL) listbase->first = link;
|
||||
listbase->last = link;
|
||||
}
|
||||
|
||||
static void remlink(volatile localListBase *listbase, void *vlink)
|
||||
{
|
||||
struct localLink *link= vlink;
|
||||
|
||||
if (link == NULL) return;
|
||||
if (listbase == NULL) return;
|
||||
|
||||
if (link->next) link->next->prev = link->prev;
|
||||
if (link->prev) link->prev->next = link->next;
|
||||
|
||||
if (listbase->last == link) listbase->last = link->prev;
|
||||
if (listbase->first == link) listbase->first = link->next;
|
||||
}
|
||||
|
||||
static void rem_memblock(MemHead *memh)
|
||||
{
|
||||
remlink(membase,&memh->next);
|
||||
if (memh->prev) {
|
||||
if (memh->next)
|
||||
MEMNEXT(memh->prev)->nextname = MEMNEXT(memh->next)->name;
|
||||
else
|
||||
MEMNEXT(memh->prev)->nextname = NULL;
|
||||
}
|
||||
|
||||
totblock--;
|
||||
mem_in_use -= memh->len;
|
||||
|
||||
if(memh->mmap) {
|
||||
mmap_in_use -= memh->len;
|
||||
if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail)))
|
||||
printf("Couldn't unmap memory %s\n", memh->name);
|
||||
}
|
||||
else {
|
||||
if(malloc_debug_memset && memh->len)
|
||||
memset(memh+1, 255, memh->len);
|
||||
free(memh);
|
||||
}
|
||||
}
|
||||
|
||||
static void MemorY_ErroR(const char *block, const char *error)
|
||||
{
|
||||
print_error("Memoryblock %s: %s\n",block, error);
|
||||
}
|
||||
|
||||
static const char *check_memlist(MemHead *memh)
|
||||
{
|
||||
MemHead *forw,*back,*forwok,*backok;
|
||||
const char *name;
|
||||
|
||||
forw = membase->first;
|
||||
if (forw) forw = MEMNEXT(forw);
|
||||
forwok = NULL;
|
||||
while(forw){
|
||||
if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break;
|
||||
forwok = forw;
|
||||
if (forw->next) forw = MEMNEXT(forw->next);
|
||||
else forw = NULL;
|
||||
}
|
||||
|
||||
back = (MemHead *) membase->last;
|
||||
if (back) back = MEMNEXT(back);
|
||||
backok = NULL;
|
||||
while(back){
|
||||
if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break;
|
||||
backok = back;
|
||||
if (back->prev) back = MEMNEXT(back->prev);
|
||||
else back = NULL;
|
||||
}
|
||||
|
||||
if (forw != back) return ("MORE THAN 1 MEMORYBLOCK CORRUPT");
|
||||
|
||||
if (forw == NULL && back == NULL){
|
||||
/* geen foute headers gevonden dan maar op zoek naar memblock*/
|
||||
|
||||
forw = membase->first;
|
||||
if (forw) forw = MEMNEXT(forw);
|
||||
forwok = NULL;
|
||||
while(forw){
|
||||
if (forw == memh) break;
|
||||
if (forw->tag1 != MEMTAG1 || forw->tag2 != MEMTAG2) break;
|
||||
forwok = forw;
|
||||
if (forw->next) forw = MEMNEXT(forw->next);
|
||||
else forw = NULL;
|
||||
}
|
||||
if (forw == NULL) return NULL;
|
||||
|
||||
back = (MemHead *) membase->last;
|
||||
if (back) back = MEMNEXT(back);
|
||||
backok = NULL;
|
||||
while(back){
|
||||
if (back == memh) break;
|
||||
if (back->tag1 != MEMTAG1 || back->tag2 != MEMTAG2) break;
|
||||
backok = back;
|
||||
if (back->prev) back = MEMNEXT(back->prev);
|
||||
else back = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (forwok) name = forwok->nextname;
|
||||
else name = "No name found";
|
||||
|
||||
if (forw == memh){
|
||||
/* voor alle zekerheid wordt dit block maar uit de lijst gehaald */
|
||||
if (forwok){
|
||||
if (backok){
|
||||
forwok->next = (MemHead *)&backok->next;
|
||||
backok->prev = (MemHead *)&forwok->next;
|
||||
forwok->nextname = backok->name;
|
||||
} else{
|
||||
forwok->next = NULL;
|
||||
membase->last = (struct localLink *) &forwok->next;
|
||||
/* membase->last = (struct Link *) &forwok->next; */
|
||||
}
|
||||
} else{
|
||||
if (backok){
|
||||
backok->prev = NULL;
|
||||
membase->first = &backok->next;
|
||||
} else{
|
||||
membase->first = membase->last = NULL;
|
||||
}
|
||||
}
|
||||
} else{
|
||||
MemorY_ErroR(name,"Additional error in header");
|
||||
return("Additional error in header");
|
||||
}
|
||||
|
||||
return(name);
|
||||
}
|
||||
|
||||
uintptr_t MEM_get_peak_memory(void)
|
||||
{
|
||||
uintptr_t _peak_mem;
|
||||
|
||||
mem_lock_thread();
|
||||
_peak_mem = peak_mem;
|
||||
mem_unlock_thread();
|
||||
|
||||
return _peak_mem;
|
||||
}
|
||||
|
||||
void MEM_reset_peak_memory(void)
|
||||
{
|
||||
mem_lock_thread();
|
||||
peak_mem = 0;
|
||||
mem_unlock_thread();
|
||||
}
|
||||
|
||||
uintptr_t MEM_get_memory_in_use(void)
|
||||
{
|
||||
uintptr_t _mem_in_use;
|
||||
|
||||
mem_lock_thread();
|
||||
_mem_in_use= mem_in_use;
|
||||
mem_unlock_thread();
|
||||
|
||||
return _mem_in_use;
|
||||
}
|
||||
|
||||
uintptr_t MEM_get_mapped_memory_in_use(void)
|
||||
{
|
||||
uintptr_t _mmap_in_use;
|
||||
|
||||
mem_lock_thread();
|
||||
_mmap_in_use= mmap_in_use;
|
||||
mem_unlock_thread();
|
||||
|
||||
return _mmap_in_use;
|
||||
}
|
||||
|
||||
int MEM_get_memory_blocks_in_use(void)
|
||||
{
|
||||
int _totblock;
|
||||
|
||||
mem_lock_thread();
|
||||
_totblock= totblock;
|
||||
mem_unlock_thread();
|
||||
|
||||
return _totblock;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
const char *MEM_name_ptr(void *vmemh)
|
||||
{
|
||||
if (vmemh) {
|
||||
MemHead *memh= vmemh;
|
||||
memh--;
|
||||
return memh->name;
|
||||
}
|
||||
else {
|
||||
return "MEM_name_ptr(NULL)";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* eof */
|
||||
273
intern/guardedalloc/intern/mmap_win.c
Normal file
273
intern/guardedalloc/intern/mmap_win.c
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Andrea Weikert.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file guardedalloc/intern/mmap_win.c
|
||||
* \ingroup MEM
|
||||
*/
|
||||
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
#include <errno.h>
|
||||
#include <io.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mmap_win.h"
|
||||
|
||||
#ifndef FILE_MAP_EXECUTE
|
||||
//not defined in earlier versions of the Platform SDK (before February 2003)
|
||||
#define FILE_MAP_EXECUTE 0x0020
|
||||
#endif
|
||||
|
||||
/* copied from BKE_utildefines.h ugh */
|
||||
#ifdef __GNUC__
|
||||
# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
|
||||
#else
|
||||
# define UNUSED(x) x
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local storage definitions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* all memory mapped chunks are put in linked lists */
|
||||
typedef struct mmapLink
|
||||
{
|
||||
struct mmapLink *next,*prev;
|
||||
} mmapLink;
|
||||
|
||||
typedef struct mmapListBase
|
||||
{
|
||||
void *first, *last;
|
||||
} mmapListBase;
|
||||
|
||||
typedef struct MemMap {
|
||||
struct MemMap *next,*prev;
|
||||
void *mmap;
|
||||
HANDLE fhandle;
|
||||
HANDLE maphandle;
|
||||
} MemMap;
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void mmap_addtail(volatile mmapListBase *listbase, void *vlink);
|
||||
static void mmap_remlink(volatile mmapListBase *listbase, void *vlink);
|
||||
static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr);
|
||||
|
||||
static int mmap_get_prot_flags (int flags);
|
||||
static int mmap_get_access_flags (int flags);
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* vars */
|
||||
/* --------------------------------------------------------------------- */
|
||||
volatile static struct mmapListBase _mmapbase;
|
||||
volatile static struct mmapListBase *mmapbase = &_mmapbase;
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* implementation */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* mmap for windows */
|
||||
void *mmap(void *UNUSED(start), size_t len, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
HANDLE fhandle = INVALID_HANDLE_VALUE;
|
||||
HANDLE maphandle;
|
||||
int prot_flags = mmap_get_prot_flags(prot);
|
||||
int access_flags = mmap_get_access_flags(prot);
|
||||
MemMap *mm = NULL;
|
||||
void *ptr = NULL;
|
||||
|
||||
if ( flags & MAP_FIXED ) {
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
if ( fd == -1 ) {
|
||||
_set_errno( EBADF );
|
||||
return MAP_FAILED;
|
||||
}
|
||||
*/
|
||||
|
||||
if ( fd != -1 ) {
|
||||
fhandle = (HANDLE) _get_osfhandle (fd);
|
||||
}
|
||||
if ( fhandle == INVALID_HANDLE_VALUE ) {
|
||||
if (!(flags & MAP_ANONYMOUS)) {
|
||||
errno = EBADF;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
} else {
|
||||
if ( !DuplicateHandle( GetCurrentProcess(), fhandle, GetCurrentProcess(),
|
||||
&fhandle, 0, FALSE, DUPLICATE_SAME_ACCESS ) ) {
|
||||
return MAP_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
maphandle = CreateFileMapping(fhandle, NULL, prot_flags, 0, len, NULL);
|
||||
if ( maphandle == 0 ) {
|
||||
errno = EBADF;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0);
|
||||
if ( ptr == NULL ) {
|
||||
DWORD dwLastErr = GetLastError();
|
||||
if ( dwLastErr == ERROR_MAPPED_ALIGNMENT )
|
||||
errno=EINVAL;
|
||||
else
|
||||
errno=EACCES;
|
||||
CloseHandle(maphandle);
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
mm= (MemMap *)malloc(sizeof(MemMap));
|
||||
if (!mm) {
|
||||
errno=ENOMEM;
|
||||
}
|
||||
mm->fhandle = fhandle;
|
||||
mm->maphandle = maphandle;
|
||||
mm->mmap = ptr;
|
||||
mmap_addtail(mmapbase, mm);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* munmap for windows */
|
||||
intptr_t munmap(void *ptr, intptr_t UNUSED(size))
|
||||
{
|
||||
MemMap *mm = mmap_findlink(mmapbase, ptr);
|
||||
if (!mm) {
|
||||
errno=EINVAL;
|
||||
return -1;
|
||||
}
|
||||
UnmapViewOfFile( mm->mmap );
|
||||
CloseHandle( mm->maphandle );
|
||||
CloseHandle( mm->fhandle);
|
||||
mmap_remlink(mmapbase, mm);
|
||||
free(mm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/* local functions */
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static void mmap_addtail(volatile mmapListBase *listbase, void *vlink)
|
||||
{
|
||||
struct mmapLink *link= vlink;
|
||||
|
||||
if (link == 0) return;
|
||||
if (listbase == 0) return;
|
||||
|
||||
link->next = 0;
|
||||
link->prev = listbase->last;
|
||||
|
||||
if (listbase->last) ((struct mmapLink *)listbase->last)->next = link;
|
||||
if (listbase->first == 0) listbase->first = link;
|
||||
listbase->last = link;
|
||||
}
|
||||
|
||||
static void mmap_remlink(volatile mmapListBase *listbase, void *vlink)
|
||||
{
|
||||
struct mmapLink *link= vlink;
|
||||
|
||||
if (link == 0) return;
|
||||
if (listbase == 0) return;
|
||||
|
||||
if (link->next) link->next->prev = link->prev;
|
||||
if (link->prev) link->prev->next = link->next;
|
||||
|
||||
if (listbase->last == link) listbase->last = link->prev;
|
||||
if (listbase->first == link) listbase->first = link->next;
|
||||
}
|
||||
|
||||
static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr)
|
||||
{
|
||||
MemMap *mm;
|
||||
|
||||
if (ptr == 0) return NULL;
|
||||
if (listbase == 0) return NULL;
|
||||
|
||||
mm = (MemMap *)listbase->first;
|
||||
while (mm) {
|
||||
if (mm->mmap == ptr) {
|
||||
return mm;
|
||||
}
|
||||
mm = mm->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int mmap_get_prot_flags (int flags)
|
||||
{
|
||||
int prot = PAGE_NOACCESS;
|
||||
|
||||
if ( ( flags & PROT_READ ) == PROT_READ ) {
|
||||
if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
|
||||
prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
||||
} else {
|
||||
prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_READONLY;
|
||||
}
|
||||
} else if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
|
||||
prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_WRITECOPY;
|
||||
} else if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
|
||||
prot = PAGE_EXECUTE_READ;
|
||||
}
|
||||
return prot;
|
||||
}
|
||||
|
||||
static int mmap_get_access_flags (int flags)
|
||||
{
|
||||
int access = 0;
|
||||
|
||||
if ( ( flags & PROT_READ ) == PROT_READ ) {
|
||||
if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
|
||||
access = FILE_MAP_WRITE;
|
||||
} else {
|
||||
access = (flags & PROT_EXEC) ? FILE_MAP_EXECUTE : FILE_MAP_READ;
|
||||
}
|
||||
} else if ( ( flags & PROT_WRITE ) == PROT_WRITE ) {
|
||||
access = FILE_MAP_COPY;
|
||||
} else if ( ( flags & PROT_EXEC ) == PROT_EXEC ) {
|
||||
access = FILE_MAP_EXECUTE;
|
||||
}
|
||||
return access;
|
||||
}
|
||||
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
59
intern/guardedalloc/mmap_win.h
Normal file
59
intern/guardedalloc/mmap_win.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): Andrea Weikert.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file mmap_win.h
|
||||
* \ingroup MEM
|
||||
* \author Andrea Weikert
|
||||
*/
|
||||
|
||||
#ifndef MMAP_WIN_H
|
||||
#define MMAP_WIN_H
|
||||
|
||||
#define PROT_NONE 0
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define PROT_EXEC 4
|
||||
|
||||
#define MAP_FILE 0
|
||||
#define MAP_SHARED 1
|
||||
#define MAP_PRIVATE 2
|
||||
#define MAP_TYPE 0xF
|
||||
#define MAP_FIXED 0x10
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
|
||||
#define MAP_FAILED ((void *)-1)
|
||||
|
||||
#include "MEM_sys_types.h" // needed for intptr_t
|
||||
|
||||
void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset);
|
||||
intptr_t munmap(void *ptr, intptr_t size);
|
||||
|
||||
#endif
|
||||
|
||||
161
intern/guardedalloc/test/simpletest/memtest.c
Normal file
161
intern/guardedalloc/test/simpletest/memtest.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* $Id$
|
||||
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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$
|
||||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
* Simple test of memory.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Number of chunks to test with */
|
||||
#define NUM_BLOCKS 10
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
static void mem_error_cb(const char *errorStr)
|
||||
{
|
||||
fprintf(stderr, "%s", errorStr);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int verbose = 0;
|
||||
int error_status = 0;
|
||||
int retval = 0;
|
||||
int *ip;
|
||||
|
||||
void *p[NUM_BLOCKS];
|
||||
int i = 0;
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
switch (argc) {
|
||||
case 2:
|
||||
verbose = atoi(argv[1]);
|
||||
if (verbose < 0) verbose = 0;
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
verbose = 0;
|
||||
}
|
||||
if (verbose) {
|
||||
fprintf(stderr,"\n*** Simple memory test\n|\n");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* Round one, do a normal allocation, and free the blocks again. */
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* flush mem lib output to stderr */
|
||||
MEM_set_error_callback(mem_error_cb);
|
||||
|
||||
for (i = 0; i < NUM_BLOCKS; i++) {
|
||||
int blocksize = 10000;
|
||||
char tagstring[1000];
|
||||
if (verbose >1) printf("|--* Allocating block %d\n", i);
|
||||
sprintf(tagstring,"Memblock no. %d : ", i);
|
||||
p[i]= MEM_callocN(blocksize, strdup(tagstring));
|
||||
}
|
||||
|
||||
/* report on that */
|
||||
if (verbose > 1) MEM_printmemlist();
|
||||
|
||||
/* memory is there: test it */
|
||||
error_status = MEM_check_memory_integrity();
|
||||
|
||||
if (verbose) {
|
||||
if (error_status) {
|
||||
fprintf(stderr, "|--* Memory test FAILED\n|\n");
|
||||
} else {
|
||||
fprintf(stderr, "|--* Memory tested as good (as it should be)\n|\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_BLOCKS; i++) {
|
||||
MEM_freeN(p[i]);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* Round two, do a normal allocation, and corrupt some blocks. */
|
||||
/* ----------------------------------------------------------------- */
|
||||
/* switch off, because it will complain about some things. */
|
||||
MEM_set_error_callback(NULL);
|
||||
|
||||
for (i = 0; i < NUM_BLOCKS; i++) {
|
||||
int blocksize = 10000;
|
||||
char tagstring[1000];
|
||||
if (verbose >1) printf("|--* Allocating block %d\n", i);
|
||||
sprintf(tagstring,"Memblock no. %d : ", i);
|
||||
p[i]= MEM_callocN(blocksize, strdup(tagstring));
|
||||
}
|
||||
|
||||
/* now corrupt a few blocks...*/
|
||||
ip = (int*) p[5] - 50 ;
|
||||
for (i = 0; i< 1000; i++,ip++) *ip = i+1;
|
||||
ip = (int*) p[6];
|
||||
*(ip+10005) = 0;
|
||||
|
||||
retval = MEM_check_memory_integrity();
|
||||
|
||||
/* the test should have failed */
|
||||
error_status |= !retval;
|
||||
if (verbose) {
|
||||
if (retval) {
|
||||
fprintf(stderr, "|--* Memory test failed (as it should be)\n");
|
||||
} else {
|
||||
fprintf(stderr, "|--* Memory test FAILED to find corrupted blocks \n");
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_BLOCKS; i++) {
|
||||
MEM_freeN(p[i]);
|
||||
}
|
||||
|
||||
|
||||
if (verbose && error_status) {
|
||||
fprintf(stderr,"|--* Memory was corrupted\n");
|
||||
}
|
||||
/* ----------------------------------------------------------------- */
|
||||
if (verbose) {
|
||||
if (error_status) {
|
||||
fprintf(stderr,"|\n|--* Errors were detected\n");
|
||||
} else {
|
||||
fprintf(stderr,"|\n|--* Test exited succesfully\n");
|
||||
}
|
||||
|
||||
fprintf(stderr,"|\n*** Finished test\n\n");
|
||||
}
|
||||
return error_status;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user