diff options
author | Hans Lambermont <hans@lambermont.dyndns.org> | 2002-10-12 15:37:38 +0400 |
---|---|---|
committer | Hans Lambermont <hans@lambermont.dyndns.org> | 2002-10-12 15:37:38 +0400 |
commit | 12315f4d0e0ae993805f141f64cb8c73c5297311 (patch) | |
tree | 59b45827cd8293cfb727758989c7a74b40183974 /intern/ghost |
Initial revisionv2.25
Diffstat (limited to 'intern/ghost')
81 files changed, 18697 insertions, 0 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h new file mode 100644 index 00000000000..10b986a55b0 --- /dev/null +++ b/intern/ghost/GHOST_C-api.h @@ -0,0 +1,733 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef GHOST_C_API_H + +#define GHOST_C_API_H + +#include "GHOST_Types.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +#define GHOST_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +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. + * @return A handle to the new window ( == NULL if creation failed). + */ +extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, + char* title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const int stereoVisual); + +/** + * 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); + + + +/*************************************************************************************** + ** 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); + +/** + * 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); + +/*************************************************************************************** + ** 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); + +/** + * 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, + 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 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); + +/** + * 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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/intern/ghost/GHOST_IEvent.h b/intern/ghost/GHOST_IEvent.h new file mode 100644 index 00000000000..ba901708e84 --- /dev/null +++ b/intern/ghost/GHOST_IEvent.h @@ -0,0 +1,88 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#ifndef _GHOST_IEVENT_H_ +#define _GHOST_IEVENT_H_ + +#include "GHOST_Types.h" + +class GHOST_IWindow; + +/** + * Interface class for events received the operating system. + * @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; +}; + +#endif // _GHOST_IEVENT_H_ diff --git a/intern/ghost/GHOST_IEventConsumer.h b/intern/ghost/GHOST_IEventConsumer.h new file mode 100644 index 00000000000..7234beff777 --- /dev/null +++ b/intern/ghost/GHOST_IEventConsumer.h @@ -0,0 +1,66 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 14, 2001 + */ + +#ifndef _GHOST_IEVENT_CONSUMER_H_ +#define _GHOST_IEVENT_CONSUMER_H_ + +#include "GHOST_IEvent.h" + +/** + * Interface class for objects interested in receiving events. + */ +class GHOST_IEventConsumer +{ +public: + /** + * Destructor. + */ + virtual ~GHOST_IEventConsumer() + { + } + + /** + * 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) = 0; +}; + +#endif // _GHOST_EVENT_CONSUMER_H_ diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h new file mode 100644 index 00000000000..3c3398408f0 --- /dev/null +++ b/intern/ghost/GHOST_ISystem.h @@ -0,0 +1,282 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 30, 2001 + */ + +#ifndef _GHOST_ISYSTEM_H_ +#define _GHOST_ISYSTEM_H_ + +#include "GHOST_Types.h" +#include "GHOST_ITimerTask.h" +#include "GHOST_IWindow.h" + +class GHOST_IEventConsumer; + +/** + * 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: + * 1. Time(r) management. + * 2. Display/window management (windows are only created on the main display for now). + * 3. Event management. + * 4. Access to the state of the mouse buttons and the keyboard. + * @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. + * @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) = 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; + + /*************************************************************************************** + ** 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) const = 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; + +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; +}; + +#endif // _GHOST_ISYSTEM_H_ diff --git a/intern/ghost/GHOST_ITimerTask.h b/intern/ghost/GHOST_ITimerTask.h new file mode 100644 index 00000000000..354652017d9 --- /dev/null +++ b/intern/ghost/GHOST_ITimerTask.h @@ -0,0 +1,88 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#ifndef _GHOST_ITIMER_TASK_H_ +#define _GHOST_ITIMER_TASK_H_ + + +#include "GHOST_Types.h" + + +/** + * Interface for a timer task. + * @author Maarten Gribnau + * @date May 31, 2001 + */ +class GHOST_ITimerTask +{ +public: + /** + * Destructor. + */ + virtual ~GHOST_ITimerTask() + { + } + + /** + * Returns the timer callback. + * @return The timer callback. + */ + inline virtual GHOST_TimerProcPtr getTimerProc() const = 0; + + /** + * Changes the timer callback. + * @param timerProc The timer callback. + */ + inline virtual void setTimerProc(const GHOST_TimerProcPtr timerProc) = 0; + + /** + * Returns the timer user data. + * @return The timer user data. + */ + inline 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; +}; + + +#endif // _GHOST_ITIMER_TASK_H_ diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h new file mode 100644 index 00000000000..8f41345ec5f --- /dev/null +++ b/intern/ghost/GHOST_IWindow.h @@ -0,0 +1,241 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#ifndef _GHOST_IWINDOW_H_ +#define _GHOST_IWINDOW_H_ + +#include "STR_String.h" +#include "GHOST_Rect.h" +#include "GHOST_Types.h" + + +/** + * Interface for GHOST windows. + * Dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. + * @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 type of drawing context used in this window. + * @return The current type of drawing context. + */ + inline 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; + + /** + * 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 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. + */ + inline 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; + + /*************************************************************************************** + ** 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; + + /** + * 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; +}; + +#endif // _GHOST_IWINDOW_H_ diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h new file mode 100644 index 00000000000..c8cfc79ea9d --- /dev/null +++ b/intern/ghost/GHOST_Rect.h @@ -0,0 +1,237 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#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); + + /** + * 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; +}; + + +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; +} + +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 diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h new file mode 100644 index 00000000000..c7b8f3b19e0 --- /dev/null +++ b/intern/ghost/GHOST_Types.h @@ -0,0 +1,354 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#ifndef _GHOST_TYPES_H_ +#define _GHOST_TYPES_H_ + +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 +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; + + +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_kModifierKeyCommand, // APPLE only + GHOST_kModifierKeyNumMasks +} GHOST_TModifierKeyMask; + + +typedef enum { + GHOST_kWindowStateNormal = 0, + GHOST_kWindowStateMaximized, + GHOST_kWindowStateMinimized, + GHOST_kWindowStateFullScreen +} GHOST_TWindowState; + + +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_kButtonNumMasks +} GHOST_TButtonMask; + + +typedef enum { + GHOST_kEventUnknown = 0, + + GHOST_kEventCursorMove, + GHOST_kEventButtonDown, + GHOST_kEventButtonUp, + + GHOST_kEventKeyDown, + GHOST_kEventKeyUp, +// GHOST_kEventKeyAuto, + + GHOST_kEventQuit, + + GHOST_kEventWindowClose, + GHOST_kEventWindowActivate, + GHOST_kEventWindowDeactivate, + GHOST_kEventWindowUpdate, + GHOST_kEventWindowSize, + + 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_kStandardCursorCustom, + GHOST_kStandardCursorNumCursors +} 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_kKeyCommand, // APPLE 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 +} GHOST_TKey; + + +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 { + /** 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; + + +/** + * 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_ diff --git a/intern/ghost/Makefile b/intern/ghost/Makefile new file mode 100644 index 00000000000..5c78bea192c --- /dev/null +++ b/intern/ghost/Makefile @@ -0,0 +1,52 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL 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. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# ghost main makefile. +# + +include nan_definitions.mk + +LIBNAME = ghost +SOURCEDIR = intern/$(LIBNAME) +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = intern +TESTDIRS = test + +include nan_subdirs.mk + +install: all debug + @[ -d $(NAN_GHOST) ] || mkdir $(NAN_GHOST) + @[ -d $(NAN_GHOST)/include ] || mkdir $(NAN_GHOST)/include + @[ -d $(NAN_GHOST)/lib ] || mkdir $(NAN_GHOST)/lib + @[ -d $(NAN_GHOST)/lib/debug ] || mkdir $(NAN_GHOST)/lib/debug + cp -f $(DIR)/libghost.a $(NAN_GHOST)/lib/ + cp -f $(DIR)/debug/libghost.a $(NAN_GHOST)/lib/debug/ + cp -f *.h $(NAN_GHOST)/include/ + diff --git a/intern/ghost/doc/Doxyfile.win b/intern/ghost/doc/Doxyfile.win new file mode 100644 index 00000000000..463da56cc94 --- /dev/null +++ b/intern/ghost/doc/Doxyfile.win @@ -0,0 +1,747 @@ +# Doxyfile 1.2.4 + +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# 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 = doc + +# 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 = NO + +# 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. +# MAART: changed +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 = NO + +# 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 = NO + +# 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. +#MAART: changed +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 = 8 + +# The ENABLE_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# 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 = . +#C:\Documents and Settings\maarten\My Documents\develop\blender\source\blender\img + +# 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 = + +# 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 = + +# 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 = + +# 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 = NO + +# 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 = NO + +# 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 = NO + +# 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. +#MAART: changed +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. +#MAART: changed +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 +#MAART: changed +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::addtions 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 = NO + +# 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 = NO + +# 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 = c:\program files\doxygen\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 = diff --git a/intern/ghost/intern/GHOST_Buttons.cpp b/intern/ghost/intern/GHOST_Buttons.cpp new file mode 100644 index 00000000000..6e0c46e17a0 --- /dev/null +++ b/intern/ghost/intern/GHOST_Buttons.cpp @@ -0,0 +1,82 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#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; +} diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h new file mode 100644 index 00000000000..fdde52f3e8e --- /dev/null +++ b/intern/ghost/intern/GHOST_Buttons.h @@ -0,0 +1,76 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 15, 2001 + */ + +#ifndef _GHOST_BUTTONS_H_ +#define _GHOST_BUTTONS_H_ + +#include "GHOST_Types.h" + + +struct GHOST_Buttons { + /** + * Constructor. + */ + 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_ diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp new file mode 100644 index 00000000000..3ab3ce67fe8 --- /dev/null +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -0,0 +1,778 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/* + + * 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" + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + + +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, + char* title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const int stereoVisual) +{ + 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); +} + +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_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); +} + +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_GetModifierKeyState(GHOST_SystemHandle systemhandle, + GHOST_TModifierKeyMask mask, + int* isDown) +{ + GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; + GHOST_TSuccess result; + bool isdown; + + 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; + + result = system->getButtonState(mask, isdown); + *isDown = (int) isdown; + + return result; +} + + + +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, + 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); + 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_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(); +} + + + +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; +} + + + diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp b/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp new file mode 100644 index 00000000000..8099bdbd1d5 --- /dev/null +++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.cpp @@ -0,0 +1,55 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $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; +} diff --git a/intern/ghost/intern/GHOST_CallbackEventConsumer.h b/intern/ghost/intern/GHOST_CallbackEventConsumer.h new file mode 100644 index 00000000000..28326653b31 --- /dev/null +++ b/intern/ghost/intern/GHOST_CallbackEventConsumer.h @@ -0,0 +1,77 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date October 25, 2001 + */ + +#ifndef _GHOST_CALLBACK_EVENT_CONSUMER_H_ +#define _GHOST_CALLBACK_EVENT_CONSUMER_H_ + +#include "GHOST_IEventConsumer.h" +#include "GHOST_C-api.h" + +/** + * Interface class for objects interested in receiving events. + */ +class GHOST_CallbackEventConsumer : public GHOST_IEventConsumer +{ +public: + /** + * Constructor. + */ + 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: + GHOST_EventCallbackProcPtr m_eventCallback; + GHOST_TUserDataPtr m_userData; +}; + +#endif // _GHOST_CALLBACK_EVENT_CONSUMER_H_ diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h new file mode 100644 index 00000000000..18be85e08b4 --- /dev/null +++ b/intern/ghost/intern/GHOST_Debug.h @@ -0,0 +1,74 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date June 1, 2001 + */ + +#ifndef _GHOST_DEBUG_H_ +#define _GHOST_DEBUG_H_ + +#ifdef WIN32 + #ifdef _DEBUG + #pragma warning (disable:4786) // suppress stl-MSVC debug info warning + #define GHOST_DEBUG + #endif // _DEBUG +#else // WIN32 + #ifndef NDEBUG + #define GHOST_DEBUG + #endif // DEBUG +#endif // WIN32 + +#ifdef GHOST_DEBUG + #include <iostream> +#endif // GHOST_DEBUG + + +#ifdef GHOST_DEBUG + #define GHOST_PRINT(x) { std::cout << x; } + //#define GHOST_PRINTF(x) { printf(x); } +#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_ diff --git a/intern/ghost/intern/GHOST_DisplayManager.cpp b/intern/ghost/intern/GHOST_DisplayManager.cpp new file mode 100644 index 00000000000..dc662634434 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManager.cpp @@ -0,0 +1,219 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * 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 && 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; +} diff --git a/intern/ghost/intern/GHOST_DisplayManager.h b/intern/ghost/intern/GHOST_DisplayManager.h new file mode 100644 index 00000000000..efc218a4952 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManager.h @@ -0,0 +1,142 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#ifndef _GHOST_DISPLAY_MANAGER_H_ +#define _GHOST_DISPLAY_MANAGER_H_ + +#include "GHOST_Types.h" + +#ifdef WIN32 +#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#endif // WIN32 + +#include <vector> + +/** + * Manages system displays (platform independent implementation). + */ + +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_ diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp new file mode 100644 index 00000000000..3220fa1a330 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp @@ -0,0 +1,178 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $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); + GHOST_TInt32 numSettings = (GHOST_TInt32)numModes; + 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; +} + diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.h b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h new file mode 100644 index 00000000000..3374f710f47 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h @@ -0,0 +1,119 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#ifndef _GHOST_DISPLAY_MANAGER_CARBON_H_ +#define _GHOST_DISPLAY_MANAGER_CARBON_H_ + +#ifndef __APPLE__ +#error Apple only! +#endif // __APPLE__ + +#include "GHOST_DisplayManager.h" + +#include <Carbon/Carbon.h> + +/** + * Manages system displays (Mac OSX/Carbon implementation). + */ + +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_ diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp new file mode 100644 index 00000000000..60892ce094e --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp @@ -0,0 +1,186 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @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 +#include <multimon.h> + + +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; + GHOST_TSuccess success = 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; +} diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.h b/intern/ghost/intern/GHOST_DisplayManagerWin32.h new file mode 100644 index 00000000000..f44ba07ee33 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.h @@ -0,0 +1,106 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#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). + */ + +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_ diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.cpp b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp new file mode 100755 index 00000000000..1eb0e0a10ca --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.cpp @@ -0,0 +1,125 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#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; +} + + + + diff --git a/intern/ghost/intern/GHOST_DisplayManagerX11.h b/intern/ghost/intern/GHOST_DisplayManagerX11.h new file mode 100755 index 00000000000..7f4e772ce95 --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerX11.h @@ -0,0 +1,129 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date September 21, 2001 + */ + +#ifndef _GHOST_DISPLAY_MANAGER_X11_H_ +#define _GHOST_DISPLAY_MANAGER_X11_H_ + + +#include "GHOST_DisplayManager.h" + + +class GHOST_SystemX11; + +/** + * Manages system displays (X11 implementation). + */ + +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 // diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h new file mode 100644 index 00000000000..90b411febf9 --- /dev/null +++ b/intern/ghost/intern/GHOST_Event.h @@ -0,0 +1,114 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#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_ diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h new file mode 100644 index 00000000000..f0718414ced --- /dev/null +++ b/intern/ghost/intern/GHOST_EventButton.h @@ -0,0 +1,73 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#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_ diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h new file mode 100644 index 00000000000..9b7d3d3acc7 --- /dev/null +++ b/intern/ghost/intern/GHOST_EventCursor.h @@ -0,0 +1,74 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#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_ diff --git a/intern/ghost/intern/GHOST_EventKey.h b/intern/ghost/intern/GHOST_EventKey.h new file mode 100644 index 00000000000..19602736d99 --- /dev/null +++ b/intern/ghost/intern/GHOST_EventKey.h @@ -0,0 +1,87 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#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_ diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp new file mode 100644 index 00000000000..f4a8b72db25 --- /dev/null +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -0,0 +1,215 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $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(); +} + + +GHOST_TUns32 GHOST_EventManager::getNumEvents() +{ + return (GHOST_TUns32) m_events.size(); +} + + +GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type) +{ + GHOST_TUns32 numEvents = 0; + std::deque<GHOST_IEvent*>::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; + /* + for (unsigned int i = 0; i < m_consumers.size(); i++) { + if (m_consumers[i]->processEvent(event)) { + handled = false; + } + } + */ + 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; +} + + +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(); + } +} diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h new file mode 100644 index 00000000000..93c009b892d --- /dev/null +++ b/intern/ghost/intern/GHOST_EventManager.h @@ -0,0 +1,157 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 14, 2001 + */ + +#ifndef _GHOST_EVENT_MANAGER_H_ +#define _GHOST_EVENT_MANAGER_H_ + +#ifdef WIN32 +#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#endif // WIN32 + +#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); + +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(); + + /** The event stack. */ + std::deque<GHOST_IEvent*> m_events; + + typedef std::vector<GHOST_IEventConsumer*> TConsumerVector; + /** The list with event consumers. */ + TConsumerVector m_consumers; +}; + +#endif // _GHOST_EVENT_MANAGER_H_ diff --git a/intern/ghost/intern/GHOST_EventPrinter.cpp b/intern/ghost/intern/GHOST_EventPrinter.cpp new file mode 100644 index 00000000000..16576357fbc --- /dev/null +++ b/intern/ghost/intern/GHOST_EventPrinter.cpp @@ -0,0 +1,259 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 15, 2001 + */ + +#include "GHOST_EventPrinter.h" + +#include <iostream> + +#include "GHOST_EventKey.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 << "GHOST_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_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_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; + } + std::cout << "\n"; + 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; + } + 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_kKeyCommand: + // APPLE only! + str = "Command"; + 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; + default: + str = "unknown"; + break; + } + } +} + diff --git a/intern/ghost/intern/GHOST_EventPrinter.h b/intern/ghost/intern/GHOST_EventPrinter.h new file mode 100644 index 00000000000..6214e94393d --- /dev/null +++ b/intern/ghost/intern/GHOST_EventPrinter.h @@ -0,0 +1,70 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 14, 2001 + */ + +#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_ diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp new file mode 100644 index 00000000000..6505194645a --- /dev/null +++ b/intern/ghost/intern/GHOST_ISystem.cpp @@ -0,0 +1,98 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $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__ +# include "GHOST_SystemCarbon.h" +# 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__ + m_system = new GHOST_SystemCarbon (); +# 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; + if (m_system) { + delete m_system; + m_system = 0; + } + else { + success = GHOST_kFailure; + } + return success; +} + + +GHOST_ISystem* GHOST_ISystem::getSystem() +{ + return m_system; +} + diff --git a/intern/ghost/intern/GHOST_ModifierKeys.cpp b/intern/ghost/intern/GHOST_ModifierKeys.cpp new file mode 100644 index 00000000000..930ddf97f9a --- /dev/null +++ b/intern/ghost/intern/GHOST_ModifierKeys.cpp @@ -0,0 +1,136 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $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_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_kModifierKeyCommand: key = GHOST_kKeyCommand; 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_kModifierKeyCommand: + return m_Command; + 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_kModifierKeyCommand: + m_Command = 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_Command = 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_Command == keys.m_Command); +} diff --git a/intern/ghost/intern/GHOST_ModifierKeys.h b/intern/ghost/intern/GHOST_ModifierKeys.h new file mode 100644 index 00000000000..fc590b9597f --- /dev/null +++ b/intern/ghost/intern/GHOST_ModifierKeys.h @@ -0,0 +1,102 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 17, 2001 + */ + +#ifndef _GHOST_MODIFIER_KEYS_H_ +#define _GHOST_MODIFIER_KEYS_H_ + +#include "GHOST_Types.h" + +struct GHOST_ModifierKeys +{ + /** + * Constructor. + */ + 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. APPLE only! */ + GHOST_TUns8 m_Command : 1; +}; + +#endif // _GHOST_MODIFIER_KEYS_H_ diff --git a/intern/ghost/intern/GHOST_Rect.cpp b/intern/ghost/intern/GHOST_Rect.cpp new file mode 100644 index 00000000000..cb600815f69 --- /dev/null +++ b/intern/ghost/intern/GHOST_Rect.cpp @@ -0,0 +1,140 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#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; +} + diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp new file mode 100644 index 00000000000..5585be62f5a --- /dev/null +++ b/intern/ghost/intern/GHOST_System.cpp @@ -0,0 +1,320 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#include "GHOST_System.h" + +#include <time.h> + +#include "GHOST_DisplayManager.h" +#include "GHOST_EventManager.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) +{ +} + + +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; + 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, + 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::pushEvent(GHOST_IEvent* event) +{ + GHOST_TSuccess success; + if (m_eventManager) { + success = m_eventManager->pushEvent(event); + } + else { + success = GHOST_kFailure; + } + return success; +} + + +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 (); +#ifdef GHOST_DEBUG + if (m_eventManager) { + //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; + } + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, 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; +} diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h new file mode 100644 index 00000000000..52d90cab7a7 --- /dev/null +++ b/intern/ghost/intern/GHOST_System.h @@ -0,0 +1,328 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#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; + +/** + * Implementation of platform independent functionality of the GHOST_ISystem interface. + * GHOST_System is an abstract base class because not all methods of GHOST_ISystem are implemented. + * There should be only one system class in an application. + * Therefore, the routines to create and dispose the system are static. + * Provides: + * 1. Time(r) management. + * 2. Display/window management (windows are only created on the main display for now). + * 3. Event management. + * 4. Cursor shape management (no custom cursors for now). + * 5. Access to the state of the mouse buttons and the keyboard. + * @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); + + /*************************************************************************************** + ** 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 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; + +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; + + /** 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; +} + +#endif // _GHOST_SYSTEM_H_ diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp new file mode 100644 index 00000000000..baba1bb4e6c --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp @@ -0,0 +1,735 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#include "GHOST_SystemCarbon.h" + +#include "GHOST_DisplayManagerCarbon.h" +#include "GHOST_EventKey.h" +#include "GHOST_EventButton.h" +#include "GHOST_EventCursor.h" +#include "GHOST_TimerManager.h" +#include "GHOST_TimerTask.h" +#include "GHOST_WindowManager.h" +#include "GHOST_WindowCarbon.h" + +#define GHOST_KEY_SWITCH(mac, ghost) { case (mac): ghostKey = (ghost); break; } + +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 }, + + { kEventClassWindow, kEventWindowClose }, + { kEventClassWindow, kEventWindowActivated }, + { kEventClassWindow, kEventWindowDeactivated }, + { kEventClassWindow, kEventWindowUpdate }, + { kEventClassWindow, kEventWindowBoundsChanged } +}; + +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. + */ + UInt32 dummy= 0; + Handle transData = (Handle) GetScriptManagerVariable(smKCHRCache); + char vk = KeyTranslate(transData, rawCode, &dummy); + + /* Map numpad based on rawcodes first, otherwise they + * look like non-numpad events. + */ + switch (rawCode) { + 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; +} + +/***/ + +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); + UInt64 millis; + m_start_time = UnsignedWideToUInt64(micros)/1000; +} + +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 +) +{ + 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; +} + + +bool GHOST_SystemCarbon::processEvents(bool waitForEvent) +{ + bool anyProcessed = false; + EventRef event; + + do { + GHOST_TimerManager* timerMgr = getTimerManager(); + + if (waitForEvent) { + GHOST_TUns64 curtime = getMilliSeconds(); + GHOST_TUns64 next = timerMgr->nextFireTime(); + double timeOut; + + if (next == GHOST_kFireTimeNever) { + timeOut = kEventDurationForever; + } else { + if (next<=curtime) + timeOut = 0.0; + else + timeOut = (double) (next - getMilliSeconds())/1000.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; + } + } + + 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 ') { + //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*/) const +{ + // Not supported in Carbon! + return GHOST_kFailure; +} + + +GHOST_TSuccess GHOST_SystemCarbon::getModifierKeys(GHOST_ModifierKeys& keys) const +{ + UInt32 modifiers = ::GetCurrentKeyModifiers(); + + keys.set(GHOST_kModifierKeyCommand, (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; +} + +static bool g_hasFirstFile = false; +static char g_firstFileBuf[512]; + +extern "C" int GHOST_HACK_getFirstFile(char buf[512]) { + if (g_hasFirstFile) { + strcpy(buf, g_firstFileBuf); + 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) +{ + GHOST_WindowCarbon *window; + + if (!getFullScreen()) { + WindowRef windowref; + ::GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &windowref); + window = (GHOST_WindowCarbon*) ::GetWRefCon(windowref); + + if (validWindow(window)) { + 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: + window->updateDrawingContext(); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); + break; + } + } + } + //else { + //window = (GHOST_WindowCarbon*) m_windowManager->getFullScreenWindow(); + //GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen window event, " << window << "\n"); + //::RemoveEventFromQueue(::GetMainEventQueue(), event); + //} + + return noErr; +} + +OSStatus GHOST_SystemCarbon::handleMouseEvent(EventRef event) +{ + 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)) { + ; + } else { + GHOST_TEventType type = (kind == kEventMouseDown) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; + EventMouseButton button; + + /* Window still gets mouse up after command-H */ + if (window) { + ::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); + pushEvent(new GHOST_EventButton(getMilliSeconds(), type, window, convertButton(button))); + } + } + break; + + case kEventMouseMoved: + case kEventMouseDragged: + Point mousePos; + if (window) { + ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos); + pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, mousePos.h, mousePos.v)); + } + break; + } + + return noErr; +} + + +OSStatus GHOST_SystemCarbon::handleKeyEvent(EventRef event) +{ + GHOST_IWindow* window = m_windowManager->getActiveWindow(); + UInt32 kind = ::GetEventKind(event); + UInt32 modifiers; + UInt32 rawCode; + GHOST_TKey key; + 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 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); + 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_kKeyCommand) ); + } + + m_modifierMask = modifiers; + break; + } + + return noErr; +} + + +bool GHOST_SystemCarbon::handleMouseDown(EventRef event) +{ + WindowPtr window; + short part; + BitMap screenBits; + bool handled = true; + GHOST_IWindow* ghostWindow; + Point mousePos = {0 , 0}; + + ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos); + + part = ::FindWindow(mousePos, &window); + ghostWindow = (GHOST_IWindow*) ::GetWRefCon(window); + GHOST_ASSERT(validWindow(ghostWindow), "GHOST_SystemCarbon::handleMouseEvent: invalid window"); + + switch (part) { + case inMenuBar: + handleMenuCommand(::MenuSelect(mousePos)); + break; + + case inDrag: + ::DragWindow(window, mousePos, &GetQDGlobalsScreenBits(&screenBits)->bounds); + break; + + case inContent: + if (window != ::FrontWindow()) { + ::SelectWindow(window); + } 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)) { + ::ZoomWindow(window, part, 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; + + 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; + } + + return err; +} diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h new file mode 100644 index 00000000000..17c09e8e91f --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemCarbon.h @@ -0,0 +1,251 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#ifndef _GHOST_SYSTEM_CARBON_H_ +#define _GHOST_SYSTEM_CARBON_H_ + +#ifndef __APPLE__ +#error Apple OSX only! +#endif // __APPLE__ + +#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::GHOST_SystemCarbon(); + + /** + * Destructor. + */ + GHOST_SystemCarbon::~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. + * @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 + ); + + /*************************************************************************************** + ** Event management functionality + ***************************************************************************************/ + + /** + * Gets events from the system and stores them in the queue. + * @param waitForEvent Flag to wait for an event (or return immediately). + * @return Indication of the presence of events. + */ + virtual bool processEvents(bool waitForEvent); + + /*************************************************************************************** + ** Cursor management functionality + ***************************************************************************************/ + + /** + * Returns the current location of the cursor (location in screen coordinates) + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; + + /** + * Updates the location of the cursor (location in screen coordinates). + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const; + + /*************************************************************************************** + ** Access to mouse button and keyboard states. + ***************************************************************************************/ + + /** + * Returns the state of all modifier keys. + * @param keys The state of all modifier keys (true == pressed). + * @return Indication of success. + */ + virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; + + /** + * Returns the state of the mouse buttons (ouside the message queue). + * @param buttons The state of the buttons. + * @return Indication of success. + */ + virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; + +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 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 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; +}; + +#endif // _GHOST_SYSTEM_CARBON_H_ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h new file mode 100644 index 00000000000..099706b7e82 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -0,0 +1,65 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 22, 2001 + */ + +#ifndef _GHOST_SYSTEM_CARBON_H_ +#define _GHOST_SYSTEM_CARBON_H_ + +#ifndef __APPLE__ +#error Apple OSX only! +#endif // __APPLE__ + +#include "GHOST_System.h" +#include "GHOST_Keys.h" + +#include <Carbon/Carbon.h> + +class GHOST_EventCursor; +class GHOST_EventKey; +class GHOST_EventWindow; + +/** + * OSX/Cocoa Implementation of GHOST_System class. + * @see GHOST_System. + * @author Maarten Gribnau + * @date May 21, 2001 + */ +class GHOST_SystemCarbon : public GHOST_System { +}; + +#endif // _GHOST_SYSTEM_CARBON_H_ diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp new file mode 100644 index 00000000000..6dc00bd1847 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -0,0 +1,817 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#include "GHOST_SystemWin32.h" + + +#include "GHOST_Debug.h" +#include "GHOST_DisplayManagerWin32.h" +#include "GHOST_EventButton.h" +#include "GHOST_EventCursor.h" +#include "GHOST_EventKey.h" +#include "GHOST_TimerTask.h" +#include "GHOST_TimerManager.h" +#include "GHOST_WindowManager.h" +#include "GHOST_WindowWin32.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 + + +GHOST_SystemWin32::GHOST_SystemWin32() +: m_hasPerformanceCounter(false), m_freq(0), m_start(0), + m_seperateLeftRight(false), + m_seperateLeftRightInitialized(false) +{ + m_displayManager = new GHOST_DisplayManagerWin32 (); + GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n"); + m_displayManager->initialize(); +} + +GHOST_SystemWin32::~GHOST_SystemWin32() +{ +} + + +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) +{ + GHOST_Window* window = 0; + window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual); + if (window) { + if (window->getValid()) { + // Store the pointer to the window + if (state != GHOST_kWindowStateFullScreen) { + 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(); + + if (next == GHOST_kFireTimeNever) { + ::WaitMessage(); + } else { + ::SetTimer(NULL, 0, next - getMilliSeconds(), 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) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + anyProcessed = true; + } + } while (waitForEvent && !anyProcessed); + + return anyProcessed; +} + + +GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const +{ + POINT point; + bool success = ::GetCursorPos(&point) == TRUE; + x = point.x; + y = point.y; + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_SystemWin32::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const +{ + return ::SetCursorPos(x, y) == TRUE ? GHOST_kSuccess : GHOST_kFailure; +} + + +GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) const +{ + /* + GetKeyState and GetAsyncKeyState only work with Win95, Win98, NT4, + Terminal Server and Windows 2000. + But on WinME it always returns zero. These two functions are simply + skipped by Millenium Edition! + + Official explanation from Microsoft: + Intentionally disabled. + It didn't work all that well on some newer hardware, and worked less + well with the passage of time, so it was fully disabled in ME. + */ + if (m_seperateLeftRight && m_seperateLeftRightInitialized) { + 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); + } + else { + bool down = HIBYTE(::GetKeyState(VK_SHIFT)) != 0; + keys.set(GHOST_kModifierKeyLeftShift, down); + keys.set(GHOST_kModifierKeyRightShift, down); + down = HIBYTE(::GetKeyState(VK_MENU)) != 0; + keys.set(GHOST_kModifierKeyLeftAlt, down); + keys.set(GHOST_kModifierKeyRightAlt, down); + down = HIBYTE(::GetKeyState(VK_CONTROL)) != 0; + keys.set(GHOST_kModifierKeyLeftControl, down); + keys.set(GHOST_kModifierKeyRightControl, down); + } + 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(); + + // 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() +{ + return GHOST_System::exit(); +} + + +GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const +{ + GHOST_TKey key; + bool isExtended = (lParam&(1<<24))?true:false; + + if ((wParam >= '0') && (wParam <= '9')) { + // VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) + key = (GHOST_TKey)(wParam - '0' + GHOST_kKey0); + } + else if ((wParam >= 'A') && (wParam <= 'Z')) { + // VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) + key = (GHOST_TKey)(wParam - 'A' + GHOST_kKeyA); + } + else if ((wParam >= VK_F1) && (wParam <= VK_F24)) { + key = (GHOST_TKey)(wParam - VK_F1 + GHOST_kKeyF1); + } + else { + switch (wParam) { + case VK_RETURN: + key = isExtended?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_PRIOR: key = GHOST_kKeyUpPage; break; + case VK_NEXT: key = GHOST_kKeyDownPage; break; + case VK_END: key = GHOST_kKeyEnd; break; + case VK_HOME: key = GHOST_kKeyHome; break; + case VK_INSERT: key = GHOST_kKeyInsert; break; + case VK_DELETE: key = GHOST_kKeyDelete; break; + case VK_LEFT: key = GHOST_kKeyLeftArrow; break; + case VK_RIGHT: key = GHOST_kKeyRightArrow; break; + case VK_UP: key = GHOST_kKeyUpArrow; break; + case VK_DOWN: key = GHOST_kKeyDownArrow; break; + case VK_NUMPAD0: key = GHOST_kKeyNumpad0; break; + case VK_NUMPAD1: key = GHOST_kKeyNumpad1; break; + case VK_NUMPAD2: key = GHOST_kKeyNumpad2; break; + case VK_NUMPAD3: key = GHOST_kKeyNumpad3; break; + case VK_NUMPAD4: key = GHOST_kKeyNumpad4; break; + case VK_NUMPAD5: key = GHOST_kKeyNumpad5; break; + case VK_NUMPAD6: key = GHOST_kKeyNumpad6; break; + case VK_NUMPAD7: key = GHOST_kKeyNumpad7; break; + case VK_NUMPAD8: key = GHOST_kKeyNumpad8; break; + case VK_NUMPAD9: key = GHOST_kKeyNumpad9; 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_DECIMAL: key = GHOST_kKeyNumpadPeriod; 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; + + // Process these keys separately because we need to distinguish right from left modifier keys + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + + // Ignore these keys + case VK_NUMLOCK: + case VK_SCROLL: + case VK_CAPITAL: + default: + key = GHOST_kKeyUnknown; + break; + } + } + return key; +} + + +void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window) +{ + GHOST_ModifierKeys oldModifiers, newModifiers; + // Retrieve old state of the modifier keys + ((GHOST_SystemWin32*)getSystem())->retrieveModifierKeys(oldModifiers); + // Retrieve current state of the modifier keys + ((GHOST_SystemWin32*)getSystem())->getModifierKeys(newModifiers); + + // Compare the old and the new + if (!newModifiers.equals(oldModifiers)) { + // Create events for the masks that changed + for (int i = 0; i < GHOST_kModifierKeyNumMasks; i++) { + if (newModifiers.get((GHOST_TModifierKeyMask)i) != oldModifiers.get((GHOST_TModifierKeyMask)i)) { + // Convert the mask to a key code + GHOST_TKey key = GHOST_ModifierKeys::getModifierKeyCode((GHOST_TModifierKeyMask)i); + bool keyDown = newModifiers.get((GHOST_TModifierKeyMask)i); + GHOST_EventKey* event; + if (key != GHOST_kKeyUnknown) { + // Create an event + event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key); + pushEvent(event); + } + } + } + } + + // Store new modifier keys state + ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers); +} + + +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 *window) +{ + GHOST_TInt32 x, y; + getSystem()->getCursorPosition(x, y); + return new GHOST_EventCursor (getSystem()->getMilliSeconds(), type, window, x, y); +} + + +GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam) +{ + GHOST_TKey key = ((GHOST_SystemWin32*)getSystem())->convertKey(wParam, lParam); + GHOST_EventKey* event; + if (key != GHOST_kKeyUnknown) { + MSG keyMsg; + char ascii = '\0'; + + /* Eat any character related messages */ + if (::PeekMessage(&keyMsg, NULL, WM_CHAR, WM_SYSDEADCHAR, PM_REMOVE)) { + ascii = (char) keyMsg.wParam; + } + + event = new GHOST_EventKey(getSystem()->getMilliSeconds(), keyDown ? GHOST_kEventKeyDown: GHOST_kEventKeyUp, window, key, ascii); + } + else { + event = 0; + } + return event; +} + + +GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window) +{ + return new GHOST_Event(getSystem()->getMilliSeconds(), type, window); +} + + +LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + GHOST_Event* event = 0; + LRESULT lResult; + 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) { + //////////////////////////////////////////////////////////////////////// + // Keyboard events, processed + //////////////////////////////////////////////////////////////////////// + case WM_KEYDOWN: + /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a + * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt + * key is not pressed. + */ + case WM_SYSKEYDOWN: + /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when + * the user presses the F10 key (which activates the menu bar) or holds down the + * alt key and then presses another key. It also occurs when no window currently + * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the + * active window. The window that receives the message can distinguish between these + * two contexts by checking the context code in the lKeyData parameter. + */ + switch (wParam) { + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + if (!system->m_seperateLeftRightInitialized) { + // Check whether this system supports seperate left and right keys + switch (wParam) { + case VK_SHIFT: + system->m_seperateLeftRight = + (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) || + (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ? + true : false; + break; + case VK_CONTROL: + system->m_seperateLeftRight = + (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) || + (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ? + true : false; + break; + case VK_MENU: + system->m_seperateLeftRight = + (HIBYTE(::GetKeyState(VK_LMENU)) != 0) || + (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ? + true : false; + break; + } + system->m_seperateLeftRightInitialized = true; + } + system->processModifierKeys(window); + // Bypass call to DefWindowProc + return 0; + default: + event = processKeyEvent(window, true, wParam, lParam); + if (!event) { + GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") + GHOST_PRINT(msg) + GHOST_PRINT(" key ignored\n") + } + break; + } + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + switch (wParam) { + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + system->processModifierKeys(window); + // Bypass call to DefWindowProc + return 0; + default: + event = processKeyEvent(window, false, wParam, lParam); + if (!event) { + GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") + GHOST_PRINT(msg) + GHOST_PRINT(" key ignored\n") + } + break; + } + break; + + //////////////////////////////////////////////////////////////////////// + // Keyboard events, ignored + //////////////////////////////////////////////////////////////////////// + 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. + */ + 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. + */ + break; + + //////////////////////////////////////////////////////////////////////// + // Mouse events, processed + //////////////////////////////////////////////////////////////////////// + case WM_LBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); + break; + case WM_MBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); + break; + case WM_RBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); + break; + case WM_LBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); + break; + case WM_MBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); + break; + case WM_RBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); + break; + case WM_MOUSEMOVE: + event = processCursorEvent(GHOST_kEventCursorMove, window); + 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); + 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_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); + case WM_CAPTURECHANGED: + window->lostMouseCapture(); + 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_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. + */ + 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. + */ + case WM_KILLFOCUS: + /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */ + 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_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_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; + } + } + 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); + lResult = 0; + } + else { + lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); + } + return lResult; +} diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h new file mode 100644 index 00000000000..ac1a7eb6ac5 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -0,0 +1,278 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#ifndef _GHOST_SYSTEM_WIN32_H_ +#define _GHOST_SYSTEM_WIN32_H_ + +#ifndef WIN32 +#error WIN32 only! +#endif // WIN32 + +#include "GHOST_System.h" + +#include <windows.h> + +#if defined(__CYGWIN32__) +# define __int64 long long +#endif + + +class GHOST_EventButton; +class GHOST_EventCursor; +class GHOST_EventKey; +class GHOST_EventWindow; + +/** + * 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. + * @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); + + /*************************************************************************************** + ** Event management functionality + ***************************************************************************************/ + + /** + * Gets events from the system and stores them in the queue. + * @param waitForEvent Flag to wait for an event (or return immediately). + * @return Indication of the presence of events. + */ + virtual bool processEvents(bool waitForEvent); + + + /*************************************************************************************** + ** Cursor management functionality + ***************************************************************************************/ + + /** + * Returns the current location of the cursor (location in screen coordinates) + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; + + /** + * Updates the location of the cursor (location in screen coordinates). + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const; + + /*************************************************************************************** + ** Access to mouse button and keyboard states. + ***************************************************************************************/ + + /** + * Returns the state of all modifier keys. + * @param keys The state of all modifier keys (true == pressed). + * @return Indication of success. + */ + virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; + + /** + * Returns the state of the mouse buttons (ouside the message queue). + * @param buttons The state of the buttons. + * @return Indication of success. + */ + virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; + +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 wParam The wParam from the wndproc + * @param lParam The lParam from the wndproc + * @return The GHOST key (GHOST_kKeyUnknown if no match). + */ + virtual GHOST_TKey convertKey(WPARAM wParam, LPARAM lParam) const; + + /** + * 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. + */ + void processModifierKeys(GHOST_IWindow *window); + + /** + * Creates mouse button event. + * @param type The type of event to create. + * @param type 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. + * @return The event created. + */ + static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window); + + /** + * 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. + */ + static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, bool keyDown, WPARAM wParam, LPARAM lParam); + + /** + * Creates a window event. + * @param type The type of event to create. + * @param window The window receiving the event. + * @return The event created. + */ + static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window); + + /** + * 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); + + /** + * Windows call back routine for our window class. + */ + static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + + /** 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; + /** Stores the capability of this system to distinguish left and right modifier keys. */ + bool m_seperateLeftRight; + /** Stores the initialization state of the member m_leftRightDistinguishable. */ + bool m_seperateLeftRightInitialized; +}; + +inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const +{ + keys = m_modifierKeys; +} + +inline void GHOST_SystemWin32::storeModifierKeys(const GHOST_ModifierKeys& keys) +{ + m_modifierKeys = keys; +} + +#endif // _GHOST_SYSTEM_WIN32_H_ diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp new file mode 100755 index 00000000000..77c13d66de2 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -0,0 +1,803 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#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_DisplayManagerX11.h" + +#include "GHOST_Debug.h" + +#include <X11/Xatom.h> +#include <X11/keysym.h> + +// For timing + +#include <sys/time.h> +#include <unistd.h> + +#include <vector> + +using namespace std; + +GHOST_SystemX11:: +GHOST_SystemX11( +) : + GHOST_System(), + m_start_time(0) +{ + m_display = XOpenDisplay(NULL); + + if (!m_display) return; + + m_delete_window_atom = XInternAtom(m_display, "WM_DELETE_WINDOW", True); + + // 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); +} + + GHOST_TSuccess +GHOST_SystemX11:: +init( +){ + GHOST_TSuccess success = GHOST_System::init(); + + if (success) { + m_keyboard_vector = new char[32]; + + m_displayManager = new GHOST_DisplayManagerX11(this); + + if (m_keyboard_vector && 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. + * @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 +){ + GHOST_WindowX11 * window = 0; + + if (!m_display) return 0; + + window = new GHOST_WindowX11 ( + this,m_display,title, left, top, width, height, state, type + ); + + if (window) { + + // Install a new protocol for this window - so we can overide + // the default window closure mechanism. + + XSetWMProtocols(m_display, window->getXWindow(), &m_delete_window_atom, 1); + + 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_TUns64 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); + } +} + + 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 { + 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; + + 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; + + switch (xbe.button) { + case Button1 : gbmask = GHOST_kButtonMaskLeft; break; + case Button3 : gbmask = GHOST_kButtonMaskRight; break; + default: + case Button2 : gbmask = GHOST_kButtonMaskMiddle; break; + } + + GHOST_TEventType type = (xbe.type == ButtonPress) ? + GHOST_kEventButtonDown : GHOST_kEventButtonUp; + + 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; + + if (xcme.data.l[0] == m_delete_window_atom) { + g_event = new + GHOST_Event( + getMilliSeconds(), + GHOST_kEventWindowClose, + window + ); + } else { + /* Unknown client message, ignore */ + } + + break; + } + + // We're not interested in the following things.(yet...) + case NoExpose : + case GraphicsExpose : + + case EnterNotify: + case LeaveNotify: + // XCrossingEvents pointer leave enter window. + break; + case MapNotify: + case UnmapNotify: + break; + case MappingNotify: + case ReparentNotify: + break; + + default: + break; + } + + if (g_event) { + pushEvent(g_event); + } +} + + + GHOST_TSuccess +GHOST_SystemX11:: +getModifierKeys( + GHOST_ModifierKeys& keys +) const { + + // analyse the masks retuned from XQueryPointer. + + memset(m_keyboard_vector,32,0); + + XQueryKeymap(m_display,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); + + // 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); + } + 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 +) const { + + // 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); + XFlush(m_display); + + 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( + unsigned int 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)); + } 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_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); + + /* 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 + + diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h new file mode 100755 index 00000000000..6dedf1eb457 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -0,0 +1,252 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#ifndef _GHOST_SYSTEM_X11_H_ +#define _GHOST_SYSTEM_X11_H_ + +#include "GHOST_System.h" +#include "../GHOST_Types.h" + +#include <X11/Xlib.h> +#include <GL/glx.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( + ); + + 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. + * @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 + ); + + /** + * @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 + ) const; + + /** + * 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 + * 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; + } + + +private : + + Display * m_display; + + /** + * Atom used to detect window close events + */ + Atom m_delete_window_atom; + + /// 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; + + /** + * Return the ghost window associated with the + * X11 window xwind + */ + + GHOST_WindowX11 * + findGhostWindow( + Window xwind + ) const ; + + void + processEvent( + XEvent *xe + ); + + bool + generateWindowExposeEvents( + ); + + GHOST_TKey + convertXKey( + unsigned int key + ); + +}; + +#endif + + + + diff --git a/intern/ghost/intern/GHOST_TimerManager.cpp b/intern/ghost/intern/GHOST_TimerManager.cpp new file mode 100644 index 00000000000..e54dfce86f9 --- /dev/null +++ b/intern/ghost/intern/GHOST_TimerManager.cpp @@ -0,0 +1,163 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $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()); + } +} diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h new file mode 100644 index 00000000000..ab6d004cba8 --- /dev/null +++ b/intern/ghost/intern/GHOST_TimerManager.h @@ -0,0 +1,133 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 31, 2001 + */ + +#ifndef _GHOST_TIMER_MANAGER_H_ +#define _GHOST_TIMER_MANAGER_H_ + +#ifdef WIN32 +#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#endif // WIN32 + +#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. + */ +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_ diff --git a/intern/ghost/intern/GHOST_TimerTask.h b/intern/ghost/intern/GHOST_TimerTask.h new file mode 100644 index 00000000000..4f845a38fa1 --- /dev/null +++ b/intern/ghost/intern/GHOST_TimerTask.h @@ -0,0 +1,195 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 28, 2001 + */ + +#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_ diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp new file mode 100644 index 00000000000..daa83eedcf6 --- /dev/null +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -0,0 +1,116 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * 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) +: + m_drawingContextType(type), + m_cursorVisible(true), + m_cursorShape(GHOST_kStandardCursorDefault), + m_stereoVisual(stereoVisual) +{ + m_fullScreen = state == GHOST_kWindowStateFullScreen; + if (m_fullScreen) { + m_fullScreenWidth = width; + m_fullScreenHeight = height; + } +} + + +GHOST_Window::~GHOST_Window() +{ +} + + +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::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) +{ + if (setWindowCustomCursorShape(bitmap, mask, hotX, hotY)) { + m_cursorShape = GHOST_kStandardCursorCustom; + return GHOST_kSuccess; + } + else { + return GHOST_kFailure; + } +} + diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h new file mode 100644 index 00000000000..9bb2be7679f --- /dev/null +++ b/intern/ghost/intern/GHOST_Window.h @@ -0,0 +1,255 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#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. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +class GHOST_Window : public GHOST_IWindow +{ +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 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. + */ + 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); + + /** + * @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 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); + + /** + * Returns the visibility state of the cursor. + * @return The visibility state of the cursor. + */ + inline virtual bool getCursorVisibility() const; + + /** + * Shows or hides the cursor. + * @param visible The new visibility state of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorVisibility(bool visible); + + /** + * 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 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; + + /** 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 shape of the cursor */ + GHOST_TStandardCursor m_cursorShape; + + /** 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; + + /** 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_TStandardCursor GHOST_Window::getCursorShape() const +{ + return m_cursorShape; +} + +#endif // _GHOST_WINDOW_H diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp new file mode 100644 index 00000000000..0e894a2dd43 --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowCarbon.cpp @@ -0,0 +1,581 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $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; + +static const GLint sPreferredFormatWindow[7] = { +AGL_RGBA, GL_TRUE, +AGL_DOUBLEBUFFER, GL_TRUE, +AGL_DEPTH_SIZE, 16, +AGL_NONE, +}; + +static const GLint sPreferredFormatFullScreen[7] = { +AGL_RGBA, +AGL_DOUBLEBUFFER, +AGL_ACCELERATED, +AGL_FULLSCREEN, +AGL_DEPTH_SIZE, 16, +AGL_NONE, +}; + +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 +) : + 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; + + if (state != GHOST_kWindowStateFullScreen) { + Rect bnds = { top, left, top+height, left+width }; + Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); + gen2mac(title, title255); + + m_windowRef = ::NewCWindow( + nil, // Storage + &bnds, // Bounding rectangle of the window + title255, // Title of the window + visible, // Window initially visible + kWindowFullZoomGrowDocumentProc, //kWindowGrowDocumentProc, // procID + (WindowRef)-1L, // Put window before all other windows + true, // Window has minimize box + (SInt32)this); // Store a pointer to the class in the refCon + if (m_windowRef) { + m_grafPtr = ::GetWindowPort(m_windowRef); + setDrawingContextType(type); + updateDrawingContext(); + activateDrawingContext(); + } + } + 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); + updateDrawingContext(); + activateDrawingContext(); + } +} + + +GHOST_WindowCarbon::~GHOST_WindowCarbon() +{ + if (m_customCursor) delete m_customCursor; + + //GHOST_PRINT("GHOST_WindowCarbon::~GHOST_WindowCarbon(): removing drawing context\n"); + 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); + bounds.m_b = rect.bottom; + bounds.m_l = rect.left; + bounds.m_r = rect.right; + bounds.m_t = rect.top; +} + + +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); + if (((GHOST_TUns32)cBnds.getHeight()) != height) { + ::SizeWindow(m_windowRef, cBnds.getWidth(), height, true); + } + 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); + if ((((GHOST_TUns32)cBnds.getWidth()) != width) || + (((GHOST_TUns32)cBnds.getHeight()) != height)) { + ::SizeWindow(m_windowRef, width, height, true); + } + return GHOST_kSuccess; +} + + +GHOST_TWindowState GHOST_WindowCarbon::getState() const +{ + GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getState(): window invalid") + GHOST_TWindowState state; + if (::IsWindowVisible(m_windowRef)) { + 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_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); + } + else { + ::SendBehind(m_windowRef, nil); + } + return GHOST_kSuccess; +} + + +GHOST_TSuccess GHOST_WindowCarbon::swapBuffers() +{ + 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); + } + 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"); + pixelFormat = ::aglChoosePixelFormat(0, 0, 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, kThemeArrowCursor); + 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, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorLeftRight, kThemeResizeLeftRightCursor); + GCMAP( GHOST_kStandardCursorTopSide, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorBottomSide, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorLeftSide, kThemeResizeLeftCursor); + GCMAP( GHOST_kStandardCursorRightSide, kThemeResizeRightCursor); + GCMAP( GHOST_kStandardCursorTopLeftCorner, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorTopRightCorner, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorBottomRightCorner, kThemeArrowCursor); + GCMAP( GHOST_kStandardCursorBottomLeftCorner, kThemeArrowCursor); + }; +#undef GCMAP + + ::SetThemeCursor(carbon_cursor); + } +} + + +bool GHOST_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; +} + +/** 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[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY) +{ + 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++) { + m_customCursor->data[y] = uns16ReverseBits((bitmap[y][0]<<0) | (bitmap[y][1]<<8)); + m_customCursor->mask[y] = uns16ReverseBits((mask[y][0]<<0) | (mask[y][1]<<8)); + } + + m_customCursor->hotSpot.h = hotX; + m_customCursor->hotSpot.v = hotY; + + if (::FrontWindow() == m_windowRef) { + loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom); + } + + return GHOST_kSuccess; +} diff --git a/intern/ghost/intern/GHOST_WindowCarbon.h b/intern/ghost/intern/GHOST_WindowCarbon.h new file mode 100644 index 00000000000..694bb8e9a5d --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowCarbon.h @@ -0,0 +1,273 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#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" + +#include <Carbon/Carbon.h> +#include <AGL/agl.h> + + +/** + * Window on Mac OSX/Carbon. + * @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 + ); + + /** + * 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(); + +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[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; + + /** When running in full-screen this tells whether to refresh the window. */ + bool m_fullScreenDirty; +}; + +#endif // _GHOST_WINDOW_CARBON_H_ diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp new file mode 100644 index 00000000000..a281145ac29 --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowManager.cpp @@ -0,0 +1,190 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $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) +{ +} + + +GHOST_WindowManager::~GHOST_WindowManager() +{ +} + + +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; + 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; + } + 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; +} + diff --git a/intern/ghost/intern/GHOST_WindowManager.h b/intern/ghost/intern/GHOST_WindowManager.h new file mode 100644 index 00000000000..7af86a1113c --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowManager.h @@ -0,0 +1,165 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 11, 2001 + */ + +#ifndef _GHOST_WINDOW_MANAGER_H_ +#define _GHOST_WINDOW_MANAGER_H_ + + +#ifdef WIN32 +#pragma warning (disable:4786) // suppress stl-MSVC debug info warning +#endif // WIN32 + +#include <vector> + +#include "GHOST_Rect.h" +#include "GHOST_IWindow.h" + +//class GHOST_Window; + +/** + * Manages system windows (platform independent implementation). + */ + +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( + ); + + +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; +}; + +#endif // _GHOST_WINDOW_MANAGER_H_ diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp new file mode 100644 index 00000000000..239a020083b --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -0,0 +1,584 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#include <string.h> + +#include "GHOST_WindowWin32.h" + +#include <GL/gl.h> + +LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass"; +const int GHOST_WindowWin32::s_maxTitleLength = 128; +HGLRC GHOST_WindowWin32::s_firsthGLRc = NULL; + +/* + * 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_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 */ +}; + +GHOST_WindowWin32::GHOST_WindowWin32( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + const bool stereoVisual) +: + GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, + stereoVisual), + m_hDC(0), + m_hGlRc(0), + m_hasMouseCaptured(false), + m_nPressedButtons(0), + m_customCursor(0) +{ + if (state != GHOST_kWindowStateFullScreen) { + /* Convert client size into window size */ + width += GetSystemMetrics(SM_CXSIZEFRAME)*2; + height += GetSystemMetrics(SM_CYSIZEFRAME)*2 + GetSystemMetrics(SM_CYCAPTION); + + m_hWnd = ::CreateWindow( + s_windowClassName, // pointer to registered class name + title, // pointer to window name + WS_OVERLAPPEDWINDOW, // window style + left, // horizontal position of window + top, // vertical position of window + width, // window width + height, // window height + 0, // 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 + 0, // 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) { + // Store a pointer to this class in the window structure + LONG result = ::SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this); + + // Store the device context + m_hDC = ::GetDC(m_hWnd); + + // 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; + } + setDrawingContextType(type); + ::ShowWindow(m_hWnd, nCmdShow); + // Force an initial paint of the window + ::UpdateWindow(m_hWnd); + } +} + + +GHOST_WindowWin32::~GHOST_WindowWin32() +{ + if (m_customCursor) { + DestroyCursor(m_customCursor); + m_customCursor = NULL; + } + + setDrawingContextType(GHOST_kDrawingContextTypeNone); + if (m_hDC) { + ::ReleaseDC(m_hWnd, m_hDC); + m_hDC = 0; + } + if (m_hWnd) { + ::DestroyWindow(m_hWnd); + m_hWnd = 0; + } +} + +bool GHOST_WindowWin32::getValid() const +{ + return m_hWnd != 0; +} + + +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; + ::GetClientRect(m_hWnd, &rect); + 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() != 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() != 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() != width) || (cBnds.getHeight() != 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; + if (::IsIconic(m_hWnd)) { + state = GHOST_kWindowStateMinimized; + } + else if (::IsZoomed(m_hWnd)) { + state = GHOST_kWindowStateMaximized; + } + 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) +{ + WINDOWPLACEMENT wp; + wp.length = sizeof(WINDOWPLACEMENT); + ::GetWindowPlacement(m_hWnd, &wp); + switch (state) { + case GHOST_kWindowStateMinimized: wp.showCmd = SW_SHOWMAXIMIZED; break; + case GHOST_kWindowStateMaximized: wp.showCmd = SW_SHOWMINIMIZED; break; + case GHOST_kWindowStateNormal: default: wp.showCmd = SW_SHOWNORMAL; 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() +{ + return ::SwapBuffers(m_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::installDrawingContext(GHOST_TDrawingContextType type) +{ + GHOST_TSuccess success; + switch (type) { + case GHOST_kDrawingContextTypeOpenGL: + { + if(m_stereoVisual) + sPreferredFormat.dwFlags |= PFD_STEREO; + + // Attempt to match device context pixel format to the preferred format + int iPixelFormat = ::ChoosePixelFormat(m_hDC, &sPreferredFormat); + 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 (s_firsthGLRc) { + wglShareLists(s_firsthGLRc, m_hGlRc); + } else { + s_firsthGLRc = m_hGlRc; + } + + success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; + } + else { + success = GHOST_kFailure; + } + } + 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: + if (m_hGlRc) { + success = ::wglDeleteContext(m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; + if (m_hGlRc == s_firsthGLRc) { + s_firsthGLRc = NULL; + } + 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_hasMouseCaptured = false; + m_nPressedButtons = 0; + } +} + +void GHOST_WindowWin32::registerMouseClickEvent(bool press) +{ + if (press) { + if (!m_hasMouseCaptured) { + ::SetCapture(m_hWnd); + m_hasMouseCaptured = true; + } + m_nPressedButtons++; + } else { + if (m_nPressedButtons) { + m_nPressedButtons--; + if (!m_nPressedButtons) { + ::ReleaseCapture(); + m_hasMouseCaptured = false; + } + } + } +} + + +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; + 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; + default: + success = false; + } + + if (success) { + HCURSOR hCursor = ::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::setWindowCursorShape(GHOST_TStandardCursor cursorShape) +{ + if (m_customCursor) { + DestroyCursor(m_customCursor); + m_customCursor = NULL; + } + + if (::GetForegroundWindow() == m_hWnd) { + loadCursor(getCursorVisibility(), cursorShape); + } + + return GHOST_kSuccess; +} + +/** 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) +{ + GHOST_TUns32 andData[32]; + GHOST_TUns32 xorData[32]; + int y; + + if (m_customCursor) { + DestroyCursor(m_customCursor); + m_customCursor = NULL; + } + + memset(&andData, 0xFF, sizeof(andData)); + memset(&xorData, 0, sizeof(xorData)); + + for (y=0; y<16; y++) { + GHOST_TUns32 fullBitRow = uns16ReverseBits((bitmap[y][0]<<8) | (bitmap[y][1]<<0)); + GHOST_TUns32 fullMaskRow = uns16ReverseBits((mask[y][0]<<8) | (mask[y][1]<<0)); + + 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; +} + diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h new file mode 100644 index 00000000000..c29e61aabbb --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -0,0 +1,276 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 10, 2001 + */ + +#ifndef _GHOST_WINDOW_WIN32_H_ +#define _GHOST_WINDOW_WIN32_H_ + +#ifndef WIN32 +#error WIN32 only! +#endif // WIN32 + +#include "GHOST_Window.h" + +#include <windows.h> + + +/** + * 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. + */ + GHOST_WindowWin32( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, + const bool stereoVisual = false + ); + + /** + * Destructor. + * Closes the window and disposes resources allocated. + */ + virtual ~GHOST_WindowWin32(); + + /** + * 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 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(); + + /** + * 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 True the event was a button press. + */ + void registerMouseClickEvent(bool 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; + + +protected: + /** + * 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 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); + + /** 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; + /** Flag for if window has captured the mouse */ + bool m_hasMouseCaptured; + /** Count of number of pressed buttons */ + int m_nPressedButtons; + /** HCURSOR structure of the custom cursor */ + HCURSOR m_customCursor; + + static LPCSTR s_windowClassName; + static const int s_maxTitleLength; +}; + +#endif // _GHOST_WINDOW_WIN32_H_ diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp new file mode 100755 index 00000000000..81592c1984c --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -0,0 +1,714 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include "GHOST_WindowX11.h" + +#include "GHOST_SystemX11.h" +#include "STR_String.h" +#include "GHOST_Debug.h" + +// For standard X11 cursors +#include <X11/cursorfont.h> + +// 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) + +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, + GHOST_TDrawingContextType type, + const bool stereoVisual +) : + GHOST_Window(title,left,top,width,height,state,type), + m_display(display), + m_valid_setup (false), + m_system (system), + m_invalid_window(false), + m_context(NULL), + 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 = 0; + + 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; + attributes[i] = None; + + m_visual = glXChooseVisual(m_display, DefaultScreen(m_display), attributes); + + if (m_visual == NULL) { + // barf : no visual meeting these requirements could be found. + return; + } + + // 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; + + // create the window! + + 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 + ); + + // Are we in fullscreen mode - then include + // some obscure blut code to remove decorations. + + if (state == GHOST_kWindowStateFullScreen) { + + MotifWmHints hints; + Atom atom; + + atom = XInternAtom(m_display, "_MOTIF_WM_HINTS", False); + + if (atom == None) { + GHOST_PRINT("Could not intern X atom for _MOTIF_WM_HINTS.\n"); + } else { + hints.flags = MWM_HINTS_DECORATIONS; + hints.decorations = 0; /* Absolutely no decorations. */ + // other hints.decorations make no sense + // you can't select individual decorations + + XChangeProperty(m_display, m_window, + atom, atom, 32, + PropModeReplace, (unsigned char *) &hints, 4); + } + } + + // Create some hints for the window manager on how + // we want this window treated. + + XSizeHints * xsizehints = XAllocSizeHints(); + xsizehints->flags = USPosition | USSize; + xsizehints->x = left; + xsizehints->y = top; + xsizehints->width = width; + xsizehints->height = height; + XSetWMNormalHints(m_display, m_window, xsizehints); + XFree(xsizehints); + + setTitle(title); + + // 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); +} + + Window +GHOST_WindowX11:: +getXWindow( +){ + return m_window; +} + + bool +GHOST_WindowX11:: +getValid( +) const { + return m_valid_setup; +} + + void +GHOST_WindowX11:: +setTitle( + const STR_String& title +){ + 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 { + // not sure about this one! + + 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; +} + + + GHOST_TWindowState +GHOST_WindowX11:: +getState( +) const { + //FIXME + return GHOST_kWindowStateNormal; +} + + GHOST_TSuccess +GHOST_WindowX11:: +setState( + GHOST_TWindowState state +){ + //TODO + + if (state == getState()) { + return GHOST_kSuccess; + } else { + return GHOST_kFailure; + } + +} + + GHOST_TSuccess +GHOST_WindowX11:: +setOrder( + GHOST_TWindowOrder order +){ + if (order == GHOST_kWindowOrderTop) { + XRaiseWindow(m_display,m_window); + 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( +){ + 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); + } + + XDestroyWindow(m_display, m_window); + if (m_context) { + if (m_context == s_firstContext) { + s_firstContext = NULL; + } + glXDestroyContext(m_display, m_context); + } + 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; + 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:: +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 +){ + Pixmap bitmap_pix, mask_pix; + XColor fg, bg; + + if(XAllocNamedColor(m_display, DefaultColormap(m_display, DefaultScreen(m_display)), + "White", &fg, &fg) == 0) return GHOST_kFailure; + if(XAllocNamedColor(m_display, DefaultColormap(m_display, DefaultScreen(m_display)), + "Red", &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, 16, 16); + mask_pix = XCreateBitmapFromData(m_display, m_window, (char*) mask, 16, 16); + + 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); + + 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); +} + +*/ diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h new file mode 100755 index 00000000000..dd38496c903 --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -0,0 +1,292 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + + * $Id$ + * Copyright (C) 2001 NaN Technologies B.V. + * @author Maarten Gribnau + * @date May 7, 2001 + */ + +#ifndef _GHOST_WINDOWX11_H_ +#define _GHOST_WINDOWX11_H_ + +#include "GHOST_Window.h" +#include <X11/Xlib.h> +#include <GL/glx.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 type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + */ + 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, + GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, + const bool stereoVisual = false + ); + + 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 + * 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( + ); + +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 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 + ); + +private : + + /// Force use of public constructor. + + GHOST_WindowX11( + ); + + GHOST_WindowX11( + const GHOST_WindowX11 & + ); + + Cursor + getStandardCursor( + GHOST_TStandardCursor g_cursor + ); + + Cursor + getEmptyCursor( + ); + + GLXContext m_context; + Window m_window; + Display *m_display; + XVisualInfo *m_visual; + + /** 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; +}; + + +#endif // _GHOST_WINDOWX11_H_ diff --git a/intern/ghost/intern/Makefile b/intern/ghost/intern/Makefile new file mode 100644 index 00000000000..8107a73ce58 --- /dev/null +++ b/intern/ghost/intern/Makefile @@ -0,0 +1,65 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL 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. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# ghost intern Makefile +# + +LIBNAME = ghost +DIR = $(OCGDIR)/intern/$(LIBNAME) + +CCSRCS = GHOST_Buttons.cpp GHOST_System.cpp GHOST_Window.cpp +CCSRCS += GHOST_EventManager.cpp GHOST_EventPrinter.cpp GHOST_WindowManager.cpp +CCSRCS += GHOST_ISystem.cpp GHOST_ModifierKeys.cpp GHOST_TimerManager.cpp +CCSRCS += GHOST_Rect.cpp GHOST_DisplayManager.cpp GHOST_C-api.cpp +CCSRCS += GHOST_CallbackEventConsumer.cpp + +include nan_definitions.mk + +ifeq ($(OS),$(findstring $(OS), "darwin")) + CCSRCS += $(wildcard *Carbon.cpp) +endif + +ifeq ($(OS),$(findstring $(OS), "windows")) + CCSRCS += $(wildcard *Win32.cpp) +endif + +ifeq ($(OS),$(findstring $(OS), "freebsd irix linux openbsd solaris")) + CCSRCS += $(wildcard *X11.cpp) +endif + +include nan_compile.mk + +#CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_MEMUTIL)/include +CPPFLAGS += -I.. +CPPFLAGS += -I$(OPENGL_HEADERS) + diff --git a/intern/ghost/make/msvc/ghost.dsp b/intern/ghost/make/msvc/ghost.dsp new file mode 100644 index 00000000000..e58b4e8783e --- /dev/null +++ b/intern/ghost/make/msvc/ghost.dsp @@ -0,0 +1,576 @@ +# Microsoft Developer Studio Project File - Name="ghost" - Package Owner=<4> + +# Microsoft Developer Studio Generated Build File, Format Version 6.00 + +# ** DO NOT EDIT ** + + + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + + + +CFG=ghost - Win32 Debug + +!MESSAGE This is not a valid makefile. To build this project using NMAKE, + +!MESSAGE use the Export Makefile command and run + +!MESSAGE + +!MESSAGE NMAKE /f "ghost.mak". + +!MESSAGE + +!MESSAGE You can specify a configuration when running NMAKE + +!MESSAGE by defining the macro CFG on the command line. For example: + +!MESSAGE + +!MESSAGE NMAKE /f "ghost.mak" CFG="ghost - Win32 Debug" + +!MESSAGE + +!MESSAGE Possible choices for configuration are: + +!MESSAGE + +!MESSAGE "ghost - Win32 Release" (based on "Win32 (x86) Static Library") + +!MESSAGE "ghost - Win32 Debug" (based on "Win32 (x86) Static Library") + +!MESSAGE + + + +# Begin Project + +# PROP AllowPerConfigDependencies 0 + +# PROP Scc_ProjName "" + +# PROP Scc_LocalPath "" + +CPP=cl.exe + +RSC=rc.exe + + + +!IF "$(CFG)" == "ghost - Win32 Release" + + + +# PROP BASE Use_MFC 0 + +# PROP BASE Use_Debug_Libraries 0 + +# PROP BASE Output_Dir "Release" + +# PROP BASE Intermediate_Dir "Release" + +# PROP BASE Target_Dir "" + +# PROP Use_MFC 0 + +# PROP Use_Debug_Libraries 0 + +# PROP Output_Dir "../../../../../obj/windows/intern/ghost/" + +# PROP Intermediate_Dir "../../../../../obj/windows/intern/ghost/" + +# PROP Target_Dir "" + +LINK32=link.exe -lib + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c + +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../.." /I "../../../../lib/windows/string/include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c + +# ADD BASE RSC /l 0x409 /d "NDEBUG" + +# ADD RSC /l 0x409 /d "NDEBUG" + +BSC32=bscmake.exe + +# ADD BASE BSC32 /nologo + +# ADD BSC32 /nologo + +LIB32=link.exe -lib + +# ADD BASE LIB32 /nologo + +# ADD LIB32 /nologo + +# Begin Special Build Tool + +SOURCE="$(InputPath)" + +PostBuild_Desc=Copying GHOST files library (release target) to lib tree. + +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\..\develop\lib\windows\ghost\include\" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\ghost\ghost.lib" "..\..\..\..\..\develop\lib\windows\ghost\lib\libghost.a" ECHO Done + +# End Special Build Tool + + + +!ELSEIF "$(CFG)" == "ghost - Win32 Debug" + + + +# PROP BASE Use_MFC 0 + +# PROP BASE Use_Debug_Libraries 1 + +# PROP BASE Output_Dir "Debug" + +# PROP BASE Intermediate_Dir "Debug" + +# PROP BASE Target_Dir "" + +# PROP Use_MFC 0 + +# PROP Use_Debug_Libraries 1 + +# PROP Output_Dir "../../../../../obj/windows/intern/ghost/debug" + +# PROP Intermediate_Dir "../../../../../obj/windows/intern/ghost/debug" + +# PROP Target_Dir "" + +LINK32=link.exe -lib + +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c + +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../.." /I "../../../../lib/windows/string/include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /YX /FD /GZ /c + +# ADD BASE RSC /l 0x409 /d "_DEBUG" + +# ADD RSC /l 0x409 /d "_DEBUG" + +BSC32=bscmake.exe + +# ADD BASE BSC32 /nologo + +# ADD BSC32 /nologo + +LIB32=link.exe -lib + +# ADD BASE LIB32 /nologo + +# ADD LIB32 /nologo + +# Begin Special Build Tool + +SOURCE="$(InputPath)" + +PostBuild_Desc=Copying GHOST files library (debug target) to lib tree. + +PostBuild_Cmds=ECHO Copying header files COPY "..\..\*.h" "..\..\..\..\..\develop\lib\windows\ghost\include" ECHO Copying lib COPY "..\..\..\..\..\obj\windows\intern\ghost\debug\ghost.lib" "..\..\..\..\..\develop\lib\windows\ghost\lib\debug\libghost.a" ECHO Done + +# End Special Build Tool + + + +!ENDIF + + + +# Begin Target + + + +# Name "ghost - Win32 Release" + +# Name "ghost - Win32 Debug" + +# Begin Group "Header Files" + + + +# PROP Default_Filter "" + +# Begin Group "intern" + + + +# PROP Default_Filter "" + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Buttons.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Debug.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_DisplayManager.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_DisplayManagerWin32.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Event.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventButton.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventCursor.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventKey.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventManager.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventPrinter.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventWindow.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_ModifierKeys.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_System.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_SystemWin32.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_TimerManager.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_TimerTask.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Window.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_WindowManager.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_WindowWin32.h + +# End Source File + +# End Group + +# Begin Group "extern" + + + +# PROP Default_Filter "" + +# Begin Source File + + + +SOURCE="..\..\GHOST_C-api.h" + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_IEvent.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_IEventConsumer.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_ISystem.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_ITimerTask.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_IWindow.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_Rect.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\GHOST_Types.h + +# End Source File + +# End Group + +# End Group + +# Begin Group "Source Files" + + + +# PROP Default_Filter "" + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Buttons.cpp + +# End Source File + +# Begin Source File + + + +SOURCE="..\..\intern\GHOST_C-api.cpp" + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_CallbackEventConsumer.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_CallbackEventConsumer.h + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_DisplayManager.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_DisplayManagerWin32.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventManager.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_EventPrinter.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_ISystem.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_ModifierKeys.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Rect.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_System.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_SystemWin32.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_TimerManager.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_Window.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_WindowManager.cpp + +# End Source File + +# Begin Source File + + + +SOURCE=..\..\intern\GHOST_WindowWin32.cpp + +# End Source File + +# End Group + +# End Target + +# End Project + diff --git a/intern/ghost/make/msvc/ghost.dsw b/intern/ghost/make/msvc/ghost.dsw new file mode 100644 index 00000000000..7ae428a5fb5 --- /dev/null +++ b/intern/ghost/make/msvc/ghost.dsw @@ -0,0 +1,58 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 + +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + + + +############################################################################### + + + +Project: "ghost"=".\ghost.dsp" - Package Owner=<4> + + + +Package=<5> + +{{{ + +}}} + + + +Package=<4> + +{{{ + +}}} + + + +############################################################################### + + + +Global: + + + +Package=<5> + +{{{ + +}}} + + + +Package=<3> + +{{{ + +}}} + + + +############################################################################### + + + diff --git a/intern/ghost/test/Makefile b/intern/ghost/test/Makefile new file mode 100755 index 00000000000..bbd1988a778 --- /dev/null +++ b/intern/ghost/test/Makefile @@ -0,0 +1,86 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL 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. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# GHOST test applications makefile. +# This bounces to test application directories. +# + +LIBNAME = ghost +SOURCEDIR = intern/$(LIBNAME)/test +DIR = $(OCGDIR)/$(SOURCEDIR) +DIRS = gears + +include nan_subdirs.mk + +include nan_compile.mk +include nan_link.mk + +OCGGHOST = $(OCGDIR)/intern/$(LIBNAME) +GEARDIR = $(OCGGHOST)/test/$(DEBUG_DIR)gears.app + +LIBS = $(OCGGHOST)/$(DEBUG_DIR)libghost.a +SLIBS += $(LCGDIR)/string/lib/libstring.a + +all debug:: $(LIBS) + @echo "****> linking $@ in $(SOURCEDIR)" +ifeq ($(OS),darwin) + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)gears $(DIR)/$(DEBUG_DIR)GHOST_Test.o $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS) + @# set up directory structure for the OSX application bundle + @[ -d $(OCGGHOST)/test/ ] || mkdir $(OCGGHOST)/test/ + @[ -d $(OCGGHOST)/test/debug ] || mkdir $(OCGGHOST)/test/debug + @[ -d $(GEARDIR) ] || mkdir $(GEARDIR) + @[ -d $(GEARDIR)/Contents ] || mkdir $(GEARDIR)/Contents + @[ -d $(GEARDIR)/Contents/MacOS ] || mkdir $(GEARDIR)/Contents/MacOS + @[ -d $(GEARDIR)/Contents/Resources ] || mkdir $(GEARDIR)/Contents/Resources + @[ -d $(GEARDIR)/Contents/Resources/English.lproj ] || mkdir $(GEARDIR)/Contents/Resources/English.lproj + @[ -d $(GEARDIR)/Contents/Resources/English.lproj/MainMenu.nib ] || mkdir $(GEARDIR)/Contents/Resources/English.lproj/MainMenu.nib + @# copy the files into the bundle directory tree + cp -f $(DIR)/$(DEBUG_DIR)gears $(GEARDIR)/Contents/MacOS + cp -f gears/resources/osx/PkgInfo $(GEARDIR)/Contents/ + cp -f gears/resources/osx/Info.plist $(GEARDIR)/Contents/ + cp -f gears/resources/osx/English.lproj/InfoPlist.strings $(GEARDIR)/Contents/Resources/English.lproj + cp -f gears/resources/osx/English.lproj/MainMenu.nib/classes.nib $(GEARDIR)/Contents/Resources/English.lproj + cp -f gears/resources/osx/English.lproj/MainMenu.nib/info.nib $(GEARDIR)/Contents/Resources/English.lproj + cp -f gears/resources/osx/English.lproj/MainMenu.nib/objects.nib $(GEARDIR)/Contents/Resources/English.lproj +else + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)gears_cpp $(DIR)/$(DEBUG_DIR)GHOST_Test.o $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS) + $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)gears_c $(DIR)/$(DEBUG_DIR)GHOST_C-Test.o $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS) +endif + +clean:: + @# mac stuff. well ok, only the binary + @rm -f $(DIR)/gears $(DIR)/debug/gears + @# others + @rm -f $(DIR)/gears_c $(DIR)/debug/gears_c + @rm -f $(DIR)/gears_cpp $(DIR)/debug/gears_cpp + +test:: all + $(DIR)/gears_cpp + $(DIR)/gears_c diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c new file mode 100644 index 00000000000..16d8b421d5b --- /dev/null +++ b/intern/ghost/test/gears/GHOST_C-Test.c @@ -0,0 +1,543 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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> + +#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); + +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_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_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 window = GHOST_GetEventWindow(hEvent); + if (window == sMainWindow) + { + sExitRequested = 1; + } + else + { + if (sGearsTimer) + { + GHOST_RemoveTimer(shSystem, sGearsTimer); + sGearsTimer = 0; + } + GHOST_DisposeWindow(shSystem, window); + } + } + break; + + case GHOST_kEventWindowActivate: + handled = 0; + break; + case GHOST_kEventWindowDeactivate: + handled = 0; + break; + case GHOST_kEventWindowUpdate: + { + GHOST_WindowHandle window = GHOST_GetEventWindow(hEvent); + if (!GHOST_ValidWindow(shSystem, window)) + break; + //if (!m_fullScreenWindow) + { + setViewPortGL(window); + drawGL(); + GHOST_SwapWindowBuffers(window); + } + } + 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); + 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); + 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); + } + } +} diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp new file mode 100755 index 00000000000..a5459c9da9b --- /dev/null +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -0,0 +1,745 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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; + int verticalBlankingInterval = 32; // hard coded for testing purposes, display device dependant + float left, right, bottom, top; + float nearplane, farplane, zeroPlane, distance; + float eyeSeparation = 0.62; + window->getClientBounds(bnds); + GLfloat w = float(bnds.getWidth()) / float(bnds.getHeight()); + GLfloat h = 1.0; + + // 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.8; + top = 4.8; + 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_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* window = event->getWindow(); + if (window == m_mainWindow) { + m_exitRequested = true; + } + else { + m_system->disposeWindow(window); + } + } + break; + + case GHOST_kEventWindowActivate: + handled = false; + break; + + case GHOST_kEventWindowDeactivate: + handled = false; + break; + + case GHOST_kEventWindowUpdate: + { + GHOST_IWindow* window = event->getWindow(); + if(!m_system->validWindow(window)) + break; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if(stereo) + { + View(window, stereo, LEFT_EYE); + glPushMatrix(); + RenderCamera(); + RenderScene(); + glPopMatrix(); + + View(window, stereo, RIGHT_EYE); + glPushMatrix(); + RenderCamera(); + RenderScene(); + glPopMatrix(); + } + else + { + View(window, stereo); + glPushMatrix(); + RenderCamera(); + RenderScene(); + glPopMatrix(); + } + window->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(); + } + } +} diff --git a/intern/ghost/test/gears/Makefile b/intern/ghost/test/gears/Makefile new file mode 100755 index 00000000000..b7966b4d157 --- /dev/null +++ b/intern/ghost/test/gears/Makefile @@ -0,0 +1,48 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL 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. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# GHOST gears test application Makefile +# + +LIBNAME = gearstest +DIR = $(OCGDIR)/intern/ghost/test + +# we don't want a library here, only object files: +ALLTARGETS = $(OBJS) + +include nan_compile.mk + +CFLAGS += $(LEVEL_2_C_WARNINGS) +CCFLAGS += $(LEVEL_2_CPP_WARNINGS) + +CPPFLAGS += -I$(OPENGL_HEADERS) +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I../.. + diff --git a/intern/ghost/test/make/msvc_6_0/gears.dsp b/intern/ghost/test/make/msvc_6_0/gears.dsp new file mode 100644 index 00000000000..3e809a6b604 --- /dev/null +++ b/intern/ghost/test/make/msvc_6_0/gears.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="gears" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=gears - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gears.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gears.mak" CFG="gears - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gears - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "gears - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gears - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../../obj/windows/intern/ghost/test/" +# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../.." /I "../../../../string" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "gears - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../../obj/windows/intern/ghost/test/debug" +# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../../.." /I "../../../../string" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gears - Win32 Release" +# Name "gears - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gears\GHOST_Test.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/intern/ghost/test/make/msvc_6_0/gears_C.dsp b/intern/ghost/test/make/msvc_6_0/gears_C.dsp new file mode 100644 index 00000000000..5972d123268 --- /dev/null +++ b/intern/ghost/test/make/msvc_6_0/gears_C.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="gears_C" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=gears_C - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "gears_C.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "gears_C.mak" CFG="gears_C - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "gears_C - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "gears_C - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gears_C - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../../../../../../obj/windows/intern/ghost/test/" +# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../.." /I "../../../../string" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "gears_C - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../../../../../obj/windows/intern/ghost/test/debug" +# PROP Intermediate_Dir "../../../../../../obj/windows/intern/ghost/test/debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../../.." /I "../../../../string" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glu32.lib opengl32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "gears_C - Win32 Release" +# Name "gears_C - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gears\GHOST_C-Test.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/intern/ghost/test/make/msvc_6_0/ghost_test.dsw b/intern/ghost/test/make/msvc_6_0/ghost_test.dsw new file mode 100644 index 00000000000..03bf5eb5c9a --- /dev/null +++ b/intern/ghost/test/make/msvc_6_0/ghost_test.dsw @@ -0,0 +1,77 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "gears"=.\gears.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name ghost + End Project Dependency + Begin Project Dependency + Project_Dep_Name string + End Project Dependency +}}} + +############################################################################### + +Project: "gears_C"=.\gears_C.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name ghost + End Project Dependency + Begin Project Dependency + Project_Dep_Name string + End Project Dependency +}}} + +############################################################################### + +Project: "ghost"=..\..\..\make\msvc\ghost.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "string"=..\..\..\..\string\make\msvc_6_0\string.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/intern/ghost/test/multitest/Basic.c b/intern/ghost/test/multitest/Basic.c new file mode 100644 index 00000000000..c26cf7c92ca --- /dev/null +++ b/intern/ghost/test/multitest/Basic.c @@ -0,0 +1,68 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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]); +} diff --git a/intern/ghost/test/multitest/Basic.h b/intern/ghost/test/multitest/Basic.h new file mode 100644 index 00000000000..f81f4684bcc --- /dev/null +++ b/intern/ghost/test/multitest/Basic.h @@ -0,0 +1,44 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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]); diff --git a/intern/ghost/test/multitest/EventToBuf.c b/intern/ghost/test/multitest/EventToBuf.c new file mode 100644 index 00000000000..950d80a2468 --- /dev/null +++ b/intern/ghost/test/multitest/EventToBuf.c @@ -0,0 +1,236 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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(KeyCommand); + + 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; + } + } +} diff --git a/intern/ghost/test/multitest/EventToBuf.h b/intern/ghost/test/multitest/EventToBuf.h new file mode 100644 index 00000000000..be6f37d869b --- /dev/null +++ b/intern/ghost/test/multitest/EventToBuf.h @@ -0,0 +1,35 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +char *eventtype_to_string(GHOST_TEventType type); + +void event_to_buf(GHOST_EventHandle evt, char buf[128]); + diff --git a/intern/ghost/test/multitest/GL.h b/intern/ghost/test/multitest/GL.h new file mode 100644 index 00000000000..b395627d1d8 --- /dev/null +++ b/intern/ghost/test/multitest/GL.h @@ -0,0 +1,43 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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__) diff --git a/intern/ghost/test/multitest/Makefile b/intern/ghost/test/multitest/Makefile new file mode 100644 index 00000000000..a424a397502 --- /dev/null +++ b/intern/ghost/test/multitest/Makefile @@ -0,0 +1,60 @@ +# +# $Id$ +# +# ***** BEGIN GPL/BL DUAL 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. The Blender +# Foundation also sells licenses for use in proprietary software under +# the Blender License. See http://www.blender.org/BL/ for information +# about this. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# GHOST gears test application Makefile +# + +DIR = $(OCGDIR)/intern/ghost/test + +# we don't want a library here, only object files: +ALLTARGETS = $(OBJS) + +include nan_compile.mk +include nan_link.mk + +CFLAGS += $(LEVEL_1_C_WARNINGS) +CCFLAGS += $(LEVEL_1_CPP_WARNINGS) + +CPPFLAGS += -I$(OPENGL_HEADERS) +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_BMFONT)/include +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I../.. + +OCGGHOST = $(OCGDIR)/intern/ghost + +LIBS = $(OCGGHOST)/$(DEBUG_DIR)libghost.a +SLIBS += $(LCGDIR)/string/lib/libstring.a +SLIBS += $(LCGDIR)/bmfont/lib/libbmfont.a +SLIBS += $(LCGDIR)/guardedalloc/lib/libguardedalloc.a + +all:: + @echo "- link $(DIR)/$(DEBUG_DIR)multitest -" + @$(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)multitest $(OBJS) $(LIBS) $(SLIBS) $(LLIBS) $(DADD) $(LOPTS) diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c new file mode 100755 index 00000000000..c78d9045022 --- /dev/null +++ b/intern/ghost/test/multitest/MultiTest.c @@ -0,0 +1,855 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#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); + + 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); + + 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); + + 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; +} diff --git a/intern/ghost/test/multitest/ScrollBar.c b/intern/ghost/test/multitest/ScrollBar.c new file mode 100644 index 00000000000..cd690f6f14e --- /dev/null +++ b/intern/ghost/test/multitest/ScrollBar.c @@ -0,0 +1,145 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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); +} diff --git a/intern/ghost/test/multitest/ScrollBar.h b/intern/ghost/test/multitest/ScrollBar.h new file mode 100644 index 00000000000..30e49e8b531 --- /dev/null +++ b/intern/ghost/test/multitest/ScrollBar.h @@ -0,0 +1,56 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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); diff --git a/intern/ghost/test/multitest/Util.c b/intern/ghost/test/multitest/Util.c new file mode 100644 index 00000000000..31e43f6f5da --- /dev/null +++ b/intern/ghost/test/multitest/Util.c @@ -0,0 +1,73 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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); +} diff --git a/intern/ghost/test/multitest/Util.h b/intern/ghost/test/multitest/Util.h new file mode 100644 index 00000000000..1146112c9c4 --- /dev/null +++ b/intern/ghost/test/multitest/Util.h @@ -0,0 +1,35 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +void* memdbl (void *mem, int *size_pr, int item_size); + +char* string_dup (char *str); +void fatal (char *fmt, ...); diff --git a/intern/ghost/test/multitest/WindowData.c b/intern/ghost/test/multitest/WindowData.c new file mode 100644 index 00000000000..ee377c98b58 --- /dev/null +++ b/intern/ghost/test/multitest/WindowData.c @@ -0,0 +1,60 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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); +} diff --git a/intern/ghost/test/multitest/WindowData.h b/intern/ghost/test/multitest/WindowData.h new file mode 100644 index 00000000000..a046c41d90c --- /dev/null +++ b/intern/ghost/test/multitest/WindowData.h @@ -0,0 +1,40 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL 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); |