compile fixes for MSVC!
[blender.git] / intern / ghost / intern / GHOST_SystemWin32.cpp
index 8513d056795bed2cbc96eb70a2c88f5e4d0fc942..0cbd3e99c73c8b2a36e373659d13fbe572340019 100644 (file)
@@ -14,7 +14,7 @@
  *
  * 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.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
@@ -39,7 +39,7 @@
 #endif
 
 #include "GHOST_SystemWin32.h"
-//#include <stdio.h> //for printf()
+#include "GHOST_EventDragnDrop.h"
 
 // win64 doesn't define GWL_USERDATA
 #ifdef WIN32
 #define WHEEL_DELTA 120        /* Value for rolling one detent, (old convention! MS changed it) */
 #endif // WHEEL_DELTA
 
+/* 
+ * Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2.
+ * MSDN: Declared in Winuser.h, include Windows.h 
+ * This does not seem to work with MinGW so we define our own here.
+ */
+#ifndef XBUTTON1
+#define XBUTTON1 0x0001
+#endif // XBUTTON1
+#ifndef XBUTTON2
+#define XBUTTON2 0x0002
+#endif // XBUTTON2
+#ifndef WM_XBUTTONUP
+#define WM_XBUTTONUP 524
+#endif // WM_XBUTTONUP
+#ifndef WM_XBUTTONDOWN
+#define WM_XBUTTONDOWN 523
+#endif // WM_XBUTTONDOWN
 
 #include "GHOST_Debug.h"
 #include "GHOST_DisplayManagerWin32.h"
 
 GHOST_SystemWin32::GHOST_SystemWin32()
 : m_hasPerformanceCounter(false), m_freq(0), m_start(0),
-  m_seperateLeftRight(false),
-  m_seperateLeftRightInitialized(false)
+  m_separateLeftRight(false),
+  m_separateLeftRightInitialized(false)
 {
        m_displayManager = new GHOST_DisplayManagerWin32 ();
        GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n");
        m_displayManager->initialize();
+       
+       // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32.
+       OleInitialize(0);
 }
 
 GHOST_SystemWin32::~GHOST_SystemWin32()
 {
+       // Shutdown COM
+       OleUninitialize();
 }
 
 
@@ -168,10 +190,10 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow(
        const STR_String& title, 
        GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
        GHOST_TWindowState state, GHOST_TDrawingContextType type,
-       bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow )
+       bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow )
 {
        GHOST_Window* window = 0;
-       window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual);
+       window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples);
        if (window) {
                if (window->getValid()) {
                        // Store the pointer to the window
@@ -180,8 +202,18 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow(
 //                     }
                }
                else {
+                       // An invalid window could be one that was used to test for AA
+                       GHOST_Window *other_window = ((GHOST_WindowWin32*)window)->getNextWindow();
+
                        delete window;
                        window = 0;
+                       
+                       // If another window is found, let the wm know about that one, but not the old one
+                       if (other_window)
+                       {
+                               m_windowManager->addWindow(other_window);
+                               window = other_window;
+                       }
                }
        }
        return window;
@@ -232,10 +264,12 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
 GHOST_TSuccess GHOST_SystemWin32::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
 {
        POINT point;
-       ::GetCursorPos(&point);
-       x = point.x;
-       y = point.y;
-       return GHOST_kSuccess;
+       if(::GetCursorPos(&point)){
+               x = point.x;
+               y = point.y;
+               return GHOST_kSuccess;
+       }
+       return GHOST_kFailure;
 }
 
 
@@ -258,7 +292,7 @@ GHOST_TSuccess GHOST_SystemWin32::getModifierKeys(GHOST_ModifierKeys& keys) cons
        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) {
+       if (m_separateLeftRight && m_separateLeftRightInitialized) {
                bool down = HIBYTE(::GetKeyState(VK_LSHIFT)) != 0;
                keys.set(GHOST_kModifierKeyLeftShift, down);
                down = HIBYTE(::GetKeyState(VK_RSHIFT)) != 0;
@@ -483,11 +517,56 @@ GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
 }
 
 
-GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *window)
+GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow)
 {
-       GHOST_TInt32 x, y;
-       getSystem()->getCursorPosition(x, y);
-       return new GHOST_EventCursor (getSystem()->getMilliSeconds(), type, window, x, y);
+       GHOST_TInt32 x_screen, y_screen;
+       GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem());
+       GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow;
+       
+       system->getCursorPosition(x_screen, y_screen);
+
+       if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal)
+       {
+               GHOST_TInt32 x_new= x_screen;
+               GHOST_TInt32 y_new= y_screen;
+               GHOST_TInt32 x_accum, y_accum;
+               GHOST_Rect bounds;
+
+               /* fallback to window bounds */
+               if(window->getCursorGrabBounds(bounds)==GHOST_kFailure){
+                       window->getClientBounds(bounds);
+               }
+
+               /* could also clamp to screen bounds
+                * wrap with a window outside the view will fail atm  */
+
+               bounds.wrapPoint(x_new, y_new, 2); /* offset of one incase blender is at screen bounds */
+
+               window->getCursorGrabAccum(x_accum, y_accum);
+               if(x_new != x_screen|| y_new != y_screen) {
+                       /* when wrapping we don't need to add an event because the
+                        * setCursorPosition call will cause a new event after */
+                       system->setCursorPosition(x_new, y_new); /* wrap */
+                       window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
+               }else{
+                       return new GHOST_EventCursor(system->getMilliSeconds(),
+                                                                                GHOST_kEventCursorMove,
+                                                                                window,
+                                                                                x_screen + x_accum,
+                                                                                y_screen + y_accum
+                       );
+               }
+
+       }
+       else {
+               return new GHOST_EventCursor(system->getMilliSeconds(),
+                                                                        GHOST_kEventCursorMove,
+                                                                        window,
+                                                                        x_screen,
+                                                                        y_screen
+               );
+       }
+       return NULL;
 }
 
 
@@ -533,6 +612,26 @@ GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_
        return new GHOST_Event(getSystem()->getMilliSeconds(), type, window);
 }
 
+GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, 
+                                                                                                       GHOST_TDragnDropTypes draggedObjectType,
+                                                                                                       GHOST_IWindow* window,
+                                                                                                       int mouseX, int mouseY,
+                                                                                                       void* data)
+{
+       GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem());
+       return system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
+                                                                                                         eventType,
+                                                                                                         draggedObjectType,
+                                                                                                         window,mouseX,mouseY,data)
+                       );
+}
+
+void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax)
+{
+       minmax->ptMinTrackSize.x=320;
+       minmax->ptMinTrackSize.y=240;
+}
+
 
 LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
@@ -565,29 +664,29 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
                                                case VK_SHIFT:
                                                case VK_CONTROL:
                                                case VK_MENU:
-                                                       if (!system->m_seperateLeftRightInitialized) {
-                                                               // Check whether this system supports seperate left and right keys
+                                                       if (!system->m_separateLeftRightInitialized) {
+                                                               // Check whether this system supports separate left and right keys
                                                                switch (wParam) {
                                                                        case VK_SHIFT:
-                                                                               system->m_seperateLeftRight = 
+                                                                               system->m_separateLeftRight = 
                                                                                        (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) ||
                                                                                        (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ?
                                                                                        true : false;
                                                                                break;
                                                                        case VK_CONTROL:
-                                                                               system->m_seperateLeftRight = 
+                                                                               system->m_separateLeftRight = 
                                                                                        (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) ||
                                                                                        (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ?
                                                                                        true : false;
                                                                                break;
                                                                        case VK_MENU:
-                                                                               system->m_seperateLeftRight = 
+                                                                               system->m_separateLeftRight = 
                                                                                        (HIBYTE(::GetKeyState(VK_LMENU)) != 0) ||
                                                                                        (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ?
                                                                                        true : false;
                                                                                break;
                                                                }
-                                                               system->m_seperateLeftRightInitialized = true;
+                                                               system->m_separateLeftRightInitialized = true;
                                                        }
                                                        system->processModifierKeys(window);
                                                        // Bypass call to DefWindowProc
@@ -672,6 +771,14 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
                                        window->registerMouseClickEvent(true);
                                        event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight);
                                        break;
+                               case WM_XBUTTONDOWN:
+                                       window->registerMouseClickEvent(true);
+                                       if ((short) HIWORD(wParam) == XBUTTON1){
+                                               event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4);
+                                       }else if((short) HIWORD(wParam) == XBUTTON2){
+                                               event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5);
+                                       }
+                                       break;
                                case WM_LBUTTONUP:
                                        window->registerMouseClickEvent(false);
                                        event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft);
@@ -684,6 +791,14 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
                                        window->registerMouseClickEvent(false);
                                        event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight);
                                        break;
+                               case WM_XBUTTONUP:
+                                       window->registerMouseClickEvent(false);
+                                       if ((short) HIWORD(wParam) == XBUTTON1){
+                                               event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4);
+                                       }else if((short) HIWORD(wParam) == XBUTTON2){
+                                               event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5);
+                                       }
+                                       break;
                                case WM_MOUSEMOVE:
                                        event = processCursorEvent(GHOST_kEventCursorMove, window);
                                        break;
@@ -761,6 +876,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
                                        event = processWindowEvent(GHOST_kEventWindowUpdate, window);
                                        ::ValidateRect(hwnd, NULL);
                                        break;
+                               case WM_GETMINMAXINFO:
+                                       /* The WM_GETMINMAXINFO message is sent to a window when the size or 
+                                        * position of the window is about to change. An application can use 
+                                        * this message to override the window's default maximized size and 
+                                        * position, or its default minimum or maximum tracking size. 
+                                        */
+                                       processMinMaxInfo((MINMAXINFO *) lParam);
+                                       /* Let DefWindowProc handle it. */
+                                       break;
                                case WM_SIZE:
                                        /* The WM_SIZE message is sent to a window after its size has changed.
                                         * The WM_SIZE and WM_MOVE messages are not sent if an application handles the 
@@ -971,3 +1095,12 @@ void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
        }
 }
 
+GHOST_TUns8* GHOST_SystemWin32::getSystemDir() const
+{
+       return NULL;
+}
+
+GHOST_TUns8* GHOST_SystemWin32::getUserDir() const
+{
+       return NULL;
+}