summaryrefslogtreecommitdiff
path: root/src/SFML/Window/Win32/WindowImplWin32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/SFML/Window/Win32/WindowImplWin32.cpp')
-rw-r--r--[-rwxr-xr-x]src/SFML/Window/Win32/WindowImplWin32.cpp1259
1 files changed, 534 insertions, 725 deletions
diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp
index 506cb73..4c83cae 100755..100644
--- a/src/SFML/Window/Win32/WindowImplWin32.cpp
+++ b/src/SFML/Window/Win32/WindowImplWin32.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
+// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -25,15 +25,19 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
+#ifdef _WIN32_WINDOWS
+ #undef _WIN32_WINDOWS
+#endif
+#ifdef _WIN32_WINNT
+ #undef _WIN32_WINNT
+#endif
#define _WIN32_WINDOWS 0x0501
#define _WIN32_WINNT 0x0501
#include <SFML/Window/Win32/WindowImplWin32.hpp>
-#include <SFML/Window/WindowSettings.hpp>
#include <SFML/Window/WindowStyle.hpp>
#include <GL/gl.h>
-#include <SFML/Window/glext/wglext.h>
-#include <SFML/Window/glext/glext.h>
-#include <iostream>
+#include <SFML/System/Err.hpp>
+#include <SFML/System/Utf.hpp>
#include <vector>
// MinGW lacks the definition of some Win32 constants
@@ -48,653 +52,376 @@
#endif
+namespace
+{
+ unsigned int windowCount = 0;
+ const char* classNameA = "SFML_Window";
+ const wchar_t* classNameW = L"SFML_Window";
+ sf::priv::WindowImplWin32* fullscreenWindow = NULL;
+}
+
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
-// Static member data
-////////////////////////////////////////////////////////////
-unsigned int WindowImplWin32::ourWindowCount = 0;
-const char* WindowImplWin32::ourClassNameA = "SFML_Window";
-const wchar_t* WindowImplWin32::ourClassNameW = L"SFML_Window";
-WindowImplWin32* WindowImplWin32::ourFullscreenWindow = NULL;
-
-
-////////////////////////////////////////////////////////////
-/// Default constructor
-/// (creates a dummy window to provide a valid OpenGL context)
-////////////////////////////////////////////////////////////
-WindowImplWin32::WindowImplWin32() :
-myHandle (NULL),
-myCallback (0),
-myCursor (NULL),
-myIcon (NULL),
-myKeyRepeatEnabled(true),
-myIsCursorIn (false)
-{
- // Register the window class at first call
- if (ourWindowCount == 0)
- RegisterWindowClass();
-
- // Use small dimensions
- myWidth = 1;
- myHeight = 1;
-
- // Create a dummy window (disabled and hidden)
- if (HasUnicodeSupport())
- {
- myHandle = CreateWindowW(ourClassNameW, L"", WS_POPUP | WS_DISABLED, 0, 0, myWidth, myHeight, NULL, NULL, GetModuleHandle(NULL), NULL);
- }
- else
- {
- myHandle = CreateWindowA(ourClassNameA, "", WS_POPUP | WS_DISABLED, 0, 0, myWidth, myHeight, NULL, NULL, GetModuleHandle(NULL), NULL);
- }
- ShowWindow(myHandle, SW_HIDE);
-
- // Create the rendering context
- if (myHandle)
- {
- WindowSettings Params(0, 0, 0);
- CreateContext(VideoMode(myWidth, myHeight, 32), Params);
-
- // Don't activate by default
- SetActive(false);
- }
-}
-
-
-////////////////////////////////////////////////////////////
-/// Create the window implementation from an existing control
-////////////////////////////////////////////////////////////
-WindowImplWin32::WindowImplWin32(WindowHandle Handle, WindowSettings& Params) :
-myHandle (NULL),
-myCallback (0),
-myCursor (NULL),
-myIcon (NULL),
-myKeyRepeatEnabled(true),
-myIsCursorIn (false)
+WindowImplWin32::WindowImplWin32(WindowHandle handle) :
+m_handle (handle),
+m_callback (0),
+m_cursor (NULL),
+m_icon (NULL),
+m_keyRepeatEnabled(true),
+m_lastSize (0, 0),
+m_resizing (false),
+m_surrogate (0)
{
- // Save window handle
- myHandle = static_cast<HWND>(Handle);
-
- if (myHandle)
+ if (m_handle)
{
- // Get window client size
- RECT Rect;
- GetClientRect(myHandle, &Rect);
- myWidth = Rect.right - Rect.left;
- myHeight = Rect.bottom - Rect.top;
-
- // Create the rendering context
- VideoMode Mode(myWidth, myHeight, VideoMode::GetDesktopMode().BitsPerPixel);
- CreateContext(Mode, Params);
-
// We change the event procedure of the control (it is important to save the old one)
- SetWindowLongPtr(myHandle, GWLP_USERDATA, reinterpret_cast<long>(this));
- myCallback = SetWindowLongPtr(myHandle, GWLP_WNDPROC, reinterpret_cast<long>(&WindowImplWin32::GlobalOnEvent));
+ SetWindowLongPtr(m_handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
+ m_callback = SetWindowLongPtr(m_handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&WindowImplWin32::globalOnEvent));
}
}
////////////////////////////////////////////////////////////
-/// Create the window implementation
-////////////////////////////////////////////////////////////
-WindowImplWin32::WindowImplWin32(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params) :
-myHandle (NULL),
-myCallback (0),
-myCursor (NULL),
-myIcon (NULL),
-myKeyRepeatEnabled(true),
-myIsCursorIn (false)
+WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& /*settings*/) :
+m_handle (NULL),
+m_callback (0),
+m_cursor (NULL),
+m_icon (NULL),
+m_keyRepeatEnabled(true),
+m_lastSize (mode.width, mode.height),
+m_resizing (false),
+m_surrogate (0)
{
// Register the window class at first call
- if (ourWindowCount == 0)
- RegisterWindowClass();
+ if (windowCount == 0)
+ registerWindowClass();
// Compute position and size
- HDC ScreenDC = GetDC(NULL);
- int Left = (GetDeviceCaps(ScreenDC, HORZRES) - Mode.Width) / 2;
- int Top = (GetDeviceCaps(ScreenDC, VERTRES) - Mode.Height) / 2;
- int Width = myWidth = Mode.Width;
- int Height = myHeight = Mode.Height;
- ReleaseDC(NULL, ScreenDC);
+ HDC screenDC = GetDC(NULL);
+ int left = (GetDeviceCaps(screenDC, HORZRES) - static_cast<int>(mode.width)) / 2;
+ int top = (GetDeviceCaps(screenDC, VERTRES) - static_cast<int>(mode.height)) / 2;
+ int width = mode.width;
+ int height = mode.height;
+ ReleaseDC(NULL, screenDC);
// Choose the window style according to the Style parameter
- DWORD Win32Style = WS_VISIBLE;
- if (WindowStyle == Style::None)
+ DWORD win32Style = WS_VISIBLE;
+ if (style == Style::None)
{
- Win32Style |= WS_POPUP;
+ win32Style |= WS_POPUP;
}
else
{
- if (WindowStyle & Style::Titlebar) Win32Style |= WS_CAPTION | WS_MINIMIZEBOX;
- if (WindowStyle & Style::Resize) Win32Style |= WS_THICKFRAME | WS_MAXIMIZEBOX;
- if (WindowStyle & Style::Close) Win32Style |= WS_SYSMENU;
+ if (style & Style::Titlebar) win32Style |= WS_CAPTION | WS_MINIMIZEBOX;
+ if (style & Style::Resize) win32Style |= WS_THICKFRAME | WS_MAXIMIZEBOX;
+ if (style & Style::Close) win32Style |= WS_SYSMENU;
}
// In windowed mode, adjust width and height so that window will have the requested client area
- bool Fullscreen = (WindowStyle & Style::Fullscreen) != 0;
- if (!Fullscreen)
+ bool fullscreen = (style & Style::Fullscreen) != 0;
+ if (!fullscreen)
{
- RECT Rect = {0, 0, Width, Height};
- AdjustWindowRect(&Rect, Win32Style, false);
- Width = Rect.right - Rect.left;
- Height = Rect.bottom - Rect.top;
+ RECT rectangle = {0, 0, width, height};
+ AdjustWindowRect(&rectangle, win32Style, false);
+ width = rectangle.right - rectangle.left;
+ height = rectangle.bottom - rectangle.top;
}
// Create the window
- if (HasUnicodeSupport())
+ if (hasUnicodeSupport())
{
- wchar_t WTitle[256];
- int NbChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, Title.c_str(), static_cast<int>(Title.size()), WTitle, sizeof(WTitle) / sizeof(*WTitle));
- WTitle[NbChars] = L'\0';
- myHandle = CreateWindowW(ourClassNameW, WTitle, Win32Style, Left, Top, Width, Height, NULL, NULL, GetModuleHandle(NULL), this);
+ m_handle = CreateWindowW(classNameW, title.toWideString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
}
else
{
- myHandle = CreateWindowA(ourClassNameA, Title.c_str(), Win32Style, Left, Top, Width, Height, NULL, NULL, GetModuleHandle(NULL), this);
+ m_handle = CreateWindowA(classNameA, title.toAnsiString().c_str(), win32Style, left, top, width, height, NULL, NULL, GetModuleHandle(NULL), this);
}
- // Switch to fullscreen if requested
- if (Fullscreen)
- SwitchToFullscreen(Mode);
+ // By default, the OS limits the size of the window the the desktop size,
+ // we have to resize it after creation to apply the real size
+ setSize(Vector2u(mode.width, mode.height));
- // Create the rendering context
- if (myHandle)
- CreateContext(Mode, Params);
+ // Switch to fullscreen if requested
+ if (fullscreen)
+ switchToFullscreen(mode);
// Increment window count
- ourWindowCount++;
-
- // Get the actual size of the window, which can be smaller even after the call to AdjustWindowRect
- // This happens when the window is bigger than the desktop
- RECT ActualRect;
- GetClientRect(myHandle, &ActualRect);
- myWidth = ActualRect.right - ActualRect.left;
- myHeight = ActualRect.bottom - ActualRect.top;
+ windowCount++;
}
////////////////////////////////////////////////////////////
-/// Destructor
-////////////////////////////////////////////////////////////
WindowImplWin32::~WindowImplWin32()
{
// Destroy the custom icon, if any
- if (myIcon)
- DestroyIcon(myIcon);
+ if (m_icon)
+ DestroyIcon(m_icon);
- if (!myCallback)
+ if (!m_callback)
{
// Destroy the window
- if (myHandle)
- DestroyWindow(myHandle);
+ if (m_handle)
+ DestroyWindow(m_handle);
// Decrement the window count
- ourWindowCount--;
+ windowCount--;
// Unregister window class if we were the last window
- if (ourWindowCount == 0)
+ if (windowCount == 0)
{
- if (HasUnicodeSupport())
+ if (hasUnicodeSupport())
{
- UnregisterClassW(ourClassNameW, GetModuleHandle(NULL));
+ UnregisterClassW(classNameW, GetModuleHandle(NULL));
}
else
{
- UnregisterClassA(ourClassNameA, GetModuleHandle(NULL));
+ UnregisterClassA(classNameA, GetModuleHandle(NULL));
}
}
}
else
{
// The window is external : remove the hook on its message callback
- SetWindowLongPtr(myHandle, GWLP_WNDPROC, myCallback);
+ SetWindowLongPtr(m_handle, GWLP_WNDPROC, m_callback);
}
}
////////////////////////////////////////////////////////////
-/// Check if there's an active context on the current thread
-////////////////////////////////////////////////////////////
-bool WindowImplWin32::IsContextActive()
+WindowHandle WindowImplWin32::getSystemHandle() const
{
- return wglGetCurrentContext() != NULL;
+ return m_handle;
}
////////////////////////////////////////////////////////////
-/// /see WindowImpl::ProcessEvents
-////////////////////////////////////////////////////////////
-void WindowImplWin32::ProcessEvents()
+void WindowImplWin32::processEvents()
{
- // We update the window only if we own it
- if (!myCallback)
+ // We process the window events only if we own it
+ if (!m_callback)
{
- MSG Message;
- while (PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
+ MSG message;
+ while (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
- TranslateMessage(&Message);
- DispatchMessage(&Message);
+ TranslateMessage(&message);
+ DispatchMessage(&message);
}
}
}
////////////////////////////////////////////////////////////
-/// /see WindowImpl::Display
-////////////////////////////////////////////////////////////
-void WindowImplWin32::Display()
+Vector2i WindowImplWin32::getPosition() const
{
- if (myDeviceContext && myGLContext)
- SwapBuffers(myDeviceContext);
-}
+ RECT rect;
+ GetWindowRect(m_handle, &rect);
-
-////////////////////////////////////////////////////////////
-/// /see WindowImpl::SetActive
-////////////////////////////////////////////////////////////
-void WindowImplWin32::SetActive(bool Active) const
-{
- if (Active)
- {
- if (myDeviceContext && myGLContext && (wglGetCurrentContext() != myGLContext))
- wglMakeCurrent(myDeviceContext, myGLContext);
- }
- else
- {
- if (wglGetCurrentContext() == myGLContext)
- wglMakeCurrent(NULL, NULL);
- }
+ return Vector2i(rect.left, rect.top);
}
////////////////////////////////////////////////////////////
-/// /see WindowImpl::UseVerticalSync
-////////////////////////////////////////////////////////////
-void WindowImplWin32::UseVerticalSync(bool Enabled)
-{
- PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(wglGetProcAddress("wglSwapIntervalEXT"));
- if (wglSwapIntervalEXT)
- wglSwapIntervalEXT(Enabled ? 1 : 0);
-}
-
-
-////////////////////////////////////////////////////////////
-/// /see WindowImpl::ShowMouseCursor
-////////////////////////////////////////////////////////////
-void WindowImplWin32::ShowMouseCursor(bool Show)
+void WindowImplWin32::setPosition(const Vector2i& position)
{
- if (Show)
- myCursor = LoadCursor(NULL, IDC_ARROW);
- else
- myCursor = NULL;
-
- SetCursor(myCursor);
+ SetWindowPos(m_handle, NULL, position.x, position.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
////////////////////////////////////////////////////////////
-/// /see WindowImpl::SetCursorPosition
-////////////////////////////////////////////////////////////
-void WindowImplWin32::SetCursorPosition(unsigned int Left, unsigned int Top)
+Vector2u WindowImplWin32::getSize() const
{
- POINT Pos = {Left, Top};
- ClientToScreen(myHandle, &Pos);
- SetCursorPos(Pos.x, Pos.y);
-}
-
+ RECT rect;
+ GetClientRect(m_handle, &rect);
-////////////////////////////////////////////////////////////
-/// /see WindowImpl::SetPosition
-////////////////////////////////////////////////////////////
-void WindowImplWin32::SetPosition(int Left, int Top)
-{
- SetWindowPos(myHandle, NULL, Left, Top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+ return Vector2u(rect.right - rect.left, rect.bottom - rect.top);
}
////////////////////////////////////////////////////////////
-/// /see WindowImpl::SetSize
-////////////////////////////////////////////////////////////
-void WindowImplWin32::SetSize(unsigned int Width, unsigned int Height)
+void WindowImplWin32::setSize(const Vector2u& size)
{
// SetWindowPos wants the total size of the window (including title bar and borders),
// so we have to compute it
- RECT Rect = {0, 0, Width, Height};
- AdjustWindowRect(&Rect, GetWindowLong(myHandle, GWL_STYLE), false);
- Width = Rect.right - Rect.left;
- Height = Rect.bottom - Rect.top;
-
- SetWindowPos(myHandle, NULL, 0, 0, Width, Height, SWP_NOMOVE | SWP_NOZORDER);
-}
+ RECT rectangle = {0, 0, static_cast<long>(size.x), static_cast<long>(size.y)};
+ AdjustWindowRect(&rectangle, GetWindowLong(m_handle, GWL_STYLE), false);
+ int width = rectangle.right - rectangle.left;
+ int height = rectangle.bottom - rectangle.top;
-
-////////////////////////////////////////////////////////////
-/// /see WindowImpl::Show
-////////////////////////////////////////////////////////////
-void WindowImplWin32::Show(bool State)
-{
- ShowWindow(myHandle, State ? SW_SHOW : SW_HIDE);
+ SetWindowPos(m_handle, NULL, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER);
}
////////////////////////////////////////////////////////////
-/// /see WindowImpl::EnableKeyRepeat
-////////////////////////////////////////////////////////////
-void WindowImplWin32::EnableKeyRepeat(bool Enabled)
+void WindowImplWin32::setTitle(const String& title)
{
- myKeyRepeatEnabled = Enabled;
+ if (hasUnicodeSupport())
+ {
+ SetWindowTextW(m_handle, title.toWideString().c_str());
+ }
+ else
+ {
+ SetWindowTextA(m_handle, title.toAnsiString().c_str());
+ }
}
////////////////////////////////////////////////////////////
-/// /see WindowImpl::SetIcon
-////////////////////////////////////////////////////////////
-void WindowImplWin32::SetIcon(unsigned int Width, unsigned int Height, const Uint8* Pixels)
+void WindowImplWin32::setIcon(unsigned int width, unsigned int height, const Uint8* pixels)
{
// First destroy the previous one
- if (myIcon)
- DestroyIcon(myIcon);
+ if (m_icon)
+ DestroyIcon(m_icon);
- // Windows wants BGRA pixels : swap red and blue channels
- std::vector<Uint8> IconPixels(Width * Height * 4);
- for (std::size_t i = 0; i < IconPixels.size() / 4; ++i)
+ // Windows wants BGRA pixels: swap red and blue channels
+ std::vector<Uint8> iconPixels(width * height * 4);
+ for (std::size_t i = 0; i < iconPixels.size() / 4; ++i)
{
- IconPixels[i * 4 + 0] = Pixels[i * 4 + 2];
- IconPixels[i * 4 + 1] = Pixels[i * 4 + 1];
- IconPixels[i * 4 + 2] = Pixels[i * 4 + 0];
- IconPixels[i * 4 + 3] = Pixels[i * 4 + 3];
+ iconPixels[i * 4 + 0] = pixels[i * 4 + 2];
+ iconPixels[i * 4 + 1] = pixels[i * 4 + 1];
+ iconPixels[i * 4 + 2] = pixels[i * 4 + 0];
+ iconPixels[i * 4 + 3] = pixels[i * 4 + 3];
}
- // Create the icon from the pixels array
- myIcon = CreateIcon(GetModuleHandle(NULL), Width, Height, 1, 32, NULL, &IconPixels[0]);
+ // Create the icon from the pixel array
+ m_icon = CreateIcon(GetModuleHandle(NULL), width, height, 1, 32, NULL, &iconPixels[0]);
// Set it as both big and small icon of the window
- if (myIcon)
+ if (m_icon)
{
- SendMessage(myHandle, WM_SETICON, ICON_BIG, (LPARAM)myIcon);
- SendMessage(myHandle, WM_SETICON, ICON_SMALL, (LPARAM)myIcon);
+ SendMessage(m_handle, WM_SETICON, ICON_BIG, (LPARAM)m_icon);
+ SendMessage(m_handle, WM_SETICON, ICON_SMALL, (LPARAM)m_icon);
}
else
{
- std::cerr << "Failed to set the window's icon" << std::endl;
+ err() << "Failed to set the window's icon" << std::endl;
}
}
////////////////////////////////////////////////////////////
-/// Register the window class
-////////////////////////////////////////////////////////////
-void WindowImplWin32::RegisterWindowClass()
+void WindowImplWin32::setVisible(bool visible)
{
- if (HasUnicodeSupport())
- {
- WNDCLASSW WindowClass;
- WindowClass.style = 0;
- WindowClass.lpfnWndProc = &WindowImplWin32::GlobalOnEvent;
- WindowClass.cbClsExtra = 0;
- WindowClass.cbWndExtra = 0;
- WindowClass.hInstance = GetModuleHandle(NULL);
- WindowClass.hIcon = NULL;
- WindowClass.hCursor = 0;
- WindowClass.hbrBackground = 0;
- WindowClass.lpszMenuName = NULL;
- WindowClass.lpszClassName = ourClassNameW;
- RegisterClassW(&WindowClass);
- }
- else
- {
- WNDCLASSA WindowClass;
- WindowClass.style = 0;
- WindowClass.lpfnWndProc = &WindowImplWin32::GlobalOnEvent;
- WindowClass.cbClsExtra = 0;
- WindowClass.cbWndExtra = 0;
- WindowClass.hInstance = GetModuleHandle(NULL);
- WindowClass.hIcon = NULL;
- WindowClass.hCursor = 0;
- WindowClass.hbrBackground = 0;
- WindowClass.lpszMenuName = NULL;
- WindowClass.lpszClassName = ourClassNameA;
- RegisterClassA(&WindowClass);
- }
+ ShowWindow(m_handle, visible ? SW_SHOW : SW_HIDE);
}
////////////////////////////////////////////////////////////
-/// Switch to fullscreen mode
-////////////////////////////////////////////////////////////
-void WindowImplWin32::SwitchToFullscreen(const VideoMode& Mode)
+void WindowImplWin32::setMouseCursorVisible(bool visible)
{
- DEVMODE DevMode;
- DevMode.dmSize = sizeof(DEVMODE);
- DevMode.dmPelsWidth = Mode.Width;
- DevMode.dmPelsHeight = Mode.Height;
- DevMode.dmBitsPerPel = Mode.BitsPerPixel;
- DevMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
-
- // Apply fullscreen mode
- if (ChangeDisplaySettings(&DevMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
- {
- std::cerr << "Failed to change display mode for fullscreen" << std::endl;
- return;
- }
-
- // Make the window flags compatible with fullscreen mode
- SetWindowLong(myHandle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
- SetWindowLong(myHandle, GWL_EXSTYLE, WS_EX_APPWINDOW);
-
- // Resize the window so that it fits the entire screen
- SetWindowPos(myHandle, HWND_TOP, 0, 0, Mode.Width, Mode.Height, SWP_FRAMECHANGED);
- ShowWindow(myHandle, SW_SHOW);
+ if (visible)
+ m_cursor = LoadCursor(NULL, IDC_ARROW);
+ else
+ m_cursor = NULL;
- // Set "this" as the current fullscreen window
- ourFullscreenWindow = this;
+ SetCursor(m_cursor);
}
////////////////////////////////////////////////////////////
-/// Construct the context from graphics settings
-////////////////////////////////////////////////////////////
-void WindowImplWin32::CreateContext(const VideoMode& Mode, WindowSettings& Params)
+void WindowImplWin32::setKeyRepeatEnabled(bool enabled)
{
- // Get the device context attached to the window
- myDeviceContext = GetDC(myHandle);
- if (myDeviceContext == NULL)
- {
- std::cerr << "Failed to get device context of window -- cannot create OpenGL context" << std::endl;
- return;
- }
-
- // Let's find a suitable pixel format -- first try with antialiasing
- int BestFormat = 0;
- if (Params.AntialiasingLevel > 0)
- {
- // Get the wglChoosePixelFormatARB function (it is an extension)
- PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(wglGetProcAddress("wglChoosePixelFormatARB"));
- if (wglChoosePixelFormatARB)
- {
- // Define the basic attributes we want for our window
- int IntAttributes[] =
- {
- WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
- WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
- WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
- WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
- WGL_SAMPLE_BUFFERS_ARB, (Params.AntialiasingLevel ? GL_TRUE : GL_FALSE),
- WGL_SAMPLES_ARB, Params.AntialiasingLevel,
- 0, 0
- };
-
- // Let's check how many formats are supporting our requirements
- int Formats[128];
- UINT NbFormats;
- float FloatAttributes[] = {0, 0};
- bool IsValid = wglChoosePixelFormatARB(myDeviceContext, IntAttributes, FloatAttributes, sizeof(Formats) / sizeof(*Formats), Formats, &NbFormats) != 0;
- if (!IsValid || (NbFormats == 0))
- {
- if (Params.AntialiasingLevel > 2)
- {
- // No format matching our needs : reduce the multisampling level
- std::cerr << "Failed to find a pixel format supporting "
- << Params.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl;
-
- Params.AntialiasingLevel = IntAttributes[11] = 2;
- IsValid = wglChoosePixelFormatARB(myDeviceContext, IntAttributes, FloatAttributes, sizeof(Formats) / sizeof(*Formats), Formats, &NbFormats) != 0;
- }
+ m_keyRepeatEnabled = enabled;
+}
- if (!IsValid || (NbFormats == 0))
- {
- // Cannot find any pixel format supporting multisampling ; disabling antialiasing
- std::cerr << "Failed to find a pixel format supporting antialiasing ; antialiasing will be disabled" << std::endl;
- Params.AntialiasingLevel = 0;
- }
- }
- // Get the best format among the returned ones
- if (IsValid && (NbFormats > 0))
- {
- int BestScore = 0xFFFF;
- for (UINT i = 0; i < NbFormats; ++i)
- {
- // Get the current format's attributes
- PIXELFORMATDESCRIPTOR Attribs;
- Attribs.nSize = sizeof(PIXELFORMATDESCRIPTOR);
- Attribs.nVersion = 1;
- DescribePixelFormat(myDeviceContext, Formats[i], sizeof(PIXELFORMATDESCRIPTOR), &Attribs);
-
- // Evaluate the current configuration
- int Color = Attribs.cRedBits + Attribs.cGreenBits + Attribs.cBlueBits + Attribs.cAlphaBits;
- int Score = EvaluateConfig(Mode, Params, Color, Attribs.cDepthBits, Attribs.cStencilBits, Params.AntialiasingLevel);
-
- // Keep it if it's better than the current best
- if (Score < BestScore)
- {
- BestScore = Score;
- BestFormat = Formats[i];
- }
- }
- }
- }
- else
- {
- // wglChoosePixelFormatARB not supported ; disabling antialiasing
- std::cerr << "Antialiasing is not supported ; it will be disabled" << std::endl;
- Params.AntialiasingLevel = 0;
- }
+////////////////////////////////////////////////////////////
+void WindowImplWin32::registerWindowClass()
+{
+ if (hasUnicodeSupport())
+ {
+ WNDCLASSW windowClass;
+ windowClass.style = 0;
+ windowClass.lpfnWndProc = &WindowImplWin32::globalOnEvent;
+ windowClass.cbClsExtra = 0;
+ windowClass.cbWndExtra = 0;
+ windowClass.hInstance = GetModuleHandle(NULL);
+ windowClass.hIcon = NULL;
+ windowClass.hCursor = 0;
+ windowClass.hbrBackground = 0;
+ windowClass.lpszMenuName = NULL;
+ windowClass.lpszClassName = classNameW;
+ RegisterClassW(&windowClass);
}
-
- // Find a pixel format with no antialiasing, if not needed or not supported
- if (BestFormat == 0)
+ else
{
- // Setup a pixel format descriptor from the rendering settings
- PIXELFORMATDESCRIPTOR PixelDescriptor;
- ZeroMemory(&PixelDescriptor, sizeof(PIXELFORMATDESCRIPTOR));
- PixelDescriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
- PixelDescriptor.nVersion = 1;
- PixelDescriptor.iLayerType = PFD_MAIN_PLANE;
- PixelDescriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
- PixelDescriptor.iPixelType = PFD_TYPE_RGBA;
- PixelDescriptor.cColorBits = static_cast<BYTE>(Mode.BitsPerPixel);
- PixelDescriptor.cDepthBits = static_cast<BYTE>(Params.DepthBits);
- PixelDescriptor.cStencilBits = static_cast<BYTE>(Params.StencilBits);
- PixelDescriptor.cAlphaBits = Mode.BitsPerPixel == 32 ? 8 : 0;
-
- // Get the pixel format that best matches our requirements
- BestFormat = ChoosePixelFormat(myDeviceContext, &PixelDescriptor);
- if (BestFormat == 0)
- {
- std::cerr << "Failed to find a suitable pixel format for device context -- cannot create OpenGL context" << std::endl;
- return;
- }
+ WNDCLASSA windowClass;
+ windowClass.style = 0;
+ windowClass.lpfnWndProc = &WindowImplWin32::globalOnEvent;
+ windowClass.cbClsExtra = 0;
+ windowClass.cbWndExtra = 0;
+ windowClass.hInstance = GetModuleHandle(NULL);
+ windowClass.hIcon = NULL;
+ windowClass.hCursor = 0;
+ windowClass.hbrBackground = 0;
+ windowClass.lpszMenuName = NULL;
+ windowClass.lpszClassName = classNameA;
+ RegisterClassA(&windowClass);
}
+}
- // Extract the depth and stencil bits from the chosen format
- PIXELFORMATDESCRIPTOR ActualFormat;
- ActualFormat.nSize = sizeof(PIXELFORMATDESCRIPTOR);
- ActualFormat.nVersion = 1;
- DescribePixelFormat(myDeviceContext, BestFormat, sizeof(PIXELFORMATDESCRIPTOR), &ActualFormat);
- Params.DepthBits = ActualFormat.cDepthBits;
- Params.StencilBits = ActualFormat.cStencilBits;
- // Set the chosen pixel format
- if (!SetPixelFormat(myDeviceContext, BestFormat, &ActualFormat))
- {
- std::cerr << "Failed to set pixel format for device context -- cannot create OpenGL context" << std::endl;
- return;
- }
+////////////////////////////////////////////////////////////
+void WindowImplWin32::switchToFullscreen(const VideoMode& mode)
+{
+ DEVMODE devMode;
+ devMode.dmSize = sizeof(devMode);
+ devMode.dmPelsWidth = mode.width;
+ devMode.dmPelsHeight = mode.height;
+ devMode.dmBitsPerPel = mode.bitsPerPixel;
+ devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
- // Create the OpenGL context from the device context
- myGLContext = wglCreateContext(myDeviceContext);
- if (myGLContext == NULL)
+ // Apply fullscreen mode
+ if (ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
- std::cerr << "Failed to create an OpenGL context for this window" << std::endl;
+ err() << "Failed to change display mode for fullscreen" << std::endl;
return;
}
- // Share display lists with other contexts
- HGLRC CurrentContext = wglGetCurrentContext();
- if (CurrentContext)
- wglShareLists(CurrentContext, myGLContext);
+ // Make the window flags compatible with fullscreen mode
+ SetWindowLong(m_handle, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
+ SetWindowLong(m_handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
- // Activate the context
- SetActive(true);
+ // Resize the window so that it fits the entire screen
+ SetWindowPos(m_handle, HWND_TOP, 0, 0, mode.width, mode.height, SWP_FRAMECHANGED);
+ ShowWindow(m_handle, SW_SHOW);
- // Enable multisampling
- if (Params.AntialiasingLevel > 0)
- glEnable(GL_MULTISAMPLE_ARB);
+ // Set "this" as the current fullscreen window
+ fullscreenWindow = this;
}
////////////////////////////////////////////////////////////
-/// Free all the graphical resources attached to the window
-////////////////////////////////////////////////////////////
-void WindowImplWin32::Cleanup()
+void WindowImplWin32::cleanup()
{
// Restore the previous video mode (in case we were running in fullscreen)
- if (ourFullscreenWindow == this)
+ if (fullscreenWindow == this)
{
ChangeDisplaySettings(NULL, 0);
- ourFullscreenWindow = NULL;
+ fullscreenWindow = NULL;
}
// Unhide the mouse cursor (in case it was hidden)
- ShowMouseCursor(true);
-
- // Destroy the OpenGL context
- if (myGLContext)
- {
- // Unbind the context before destroying it
- SetActive(false);
-
- wglDeleteContext(myGLContext);
- myGLContext = NULL;
- }
- if (myDeviceContext)
- {
- ReleaseDC(myHandle, myDeviceContext);
- myDeviceContext = NULL;
- }
+ setMouseCursorVisible(true);
}
////////////////////////////////////////////////////////////
-/// Process a Win32 event
-////////////////////////////////////////////////////////////
-void WindowImplWin32::ProcessEvent(UINT Message, WPARAM WParam, LPARAM LParam)
+void WindowImplWin32::processEvent(UINT message, WPARAM wParam, LPARAM lParam)
{
// Don't process any message until window is created
- if (myHandle == NULL)
+ if (m_handle == NULL)
return;
- switch (Message)
+ switch (message)
{
// Destroy event
case WM_DESTROY :
{
// Here we must cleanup resources !
- Cleanup();
+ cleanup();
break;
}
@@ -702,8 +429,8 @@ void WindowImplWin32::ProcessEvent(UINT Message, WPARAM WParam, LPARAM LParam)
case WM_SETCURSOR :
{
// The mouse has moved, if the cursor is in our window we must refresh the cursor
- if (LOWORD(LParam) == HTCLIENT)
- SetCursor(myCursor);
+ if (LOWORD(lParam) == HTCLIENT)
+ SetCursor(m_cursor);
break;
}
@@ -711,56 +438,120 @@ void WindowImplWin32::ProcessEvent(UINT Message, WPARAM WParam, LPARAM LParam)
// Close event
case WM_CLOSE :
{
- Event Evt;
- Evt.Type = Event::Closed;
- SendEvent(Evt);
+ Event event;
+ event.type = Event::Closed;
+ pushEvent(event);
break;
}
// Resize event
case WM_SIZE :
{
- // Update window size
- RECT Rect;
- GetClientRect(myHandle, &Rect);
- myWidth = Rect.right - Rect.left;
- myHeight = Rect.bottom - Rect.top;
-
- Event Evt;
- Evt.Type = Event::Resized;
- Evt.Size.Width = myWidth;
- Evt.Size.Height = myHeight;
- SendEvent(Evt);
+ // Consider only events triggered by a maximize or a un-maximize
+ if (wParam != SIZE_MINIMIZED && !m_resizing && m_lastSize != getSize())
+ {
+ // Update the last handled size
+ m_lastSize = getSize();
+
+ // Push a resize event
+ Event event;
+ event.type = Event::Resized;
+ event.size.width = m_lastSize.x;
+ event.size.height = m_lastSize.y;
+ pushEvent(event);
+ }
+ break;
+ }
+
+ // Start resizing
+ case WM_ENTERSIZEMOVE:
+ {
+ m_resizing = true;
+ break;
+ }
+
+ // Stop resizing
+ case WM_EXITSIZEMOVE:
+ {
+ m_resizing = false;
+
+ // Ignore cases where the window has only been moved
+ if(m_lastSize != getSize())
+ {
+ // Update the last handled size
+ m_lastSize = getSize();
+
+ // Push a resize event
+ Event event;
+ event.type = Event::Resized;
+ event.size.width = m_lastSize.x;
+ event.size.height = m_lastSize.y;
+ pushEvent(event);
+ }
+ break;
+ }
+
+ // The system request the min/max window size and position
+ case WM_GETMINMAXINFO :
+ {
+ // We override the returned information to remove the default limit
+ // (the OS doesn't allow windows bigger than the desktop by default)
+ MINMAXINFO* info = reinterpret_cast<MINMAXINFO*>(lParam);
+ info->ptMaxTrackSize.x = 50000;
+ info->ptMaxTrackSize.y = 50000;
break;
}
// Gain focus event
case WM_SETFOCUS :
{
- Event Evt;
- Evt.Type = Event::GainedFocus;
- SendEvent(Evt);
+ Event event;
+ event.type = Event::GainedFocus;
+ pushEvent(event);
break;
}
// Lost focus event
case WM_KILLFOCUS :
{
- Event Evt;
- Evt.Type = Event::LostFocus;
- SendEvent(Evt);
+ Event event;
+ event.type = Event::LostFocus;
+ pushEvent(event);
break;
}
// Text event
case WM_CHAR :
{
- if (myKeyRepeatEnabled || ((LParam & (1 << 30)) == 0))
+ if (m_keyRepeatEnabled || ((lParam & (1 << 30)) == 0))
{
- Event Evt;
- Evt.Type = Event::TextEntered;
- Evt.Text.Unicode = static_cast<Uint32>(WParam);
- SendEvent(Evt);
+ // Get the code of the typed character
+ Uint32 character = static_cast<Uint32>(wParam);
+
+ // Check if it is the first part of a surrogate pair, or a regular character
+ if ((character >= 0xD800) && (character <= 0xDBFF))
+ {
+ // First part of a surrogate pair: store it and wait for the second one
+ m_surrogate = static_cast<Uint16>(character);
+ }
+ else
+ {
+
+ // Check if it is the second part of a surrogate pair, or a regular character
+ if ((character >= 0xDC00) && (character <= 0xDFFF))
+ {
+ // Convert the UTF-16 surrogate pair to a single UTF-32 value
+ Uint16 utf16[] = {m_surrogate, static_cast<Uint16>(character)};
+ sf::Utf16::toUtf32(utf16, utf16 + 2, &character);
+ m_surrogate = 0;
+ }
+
+ // Send a TextEntered event
+ Event event;
+ event.type = Event::TextEntered;
+ event.text.unicode = character;
+ pushEvent(event);
+ }
}
break;
}
@@ -769,15 +560,16 @@ void WindowImplWin32::ProcessEvent(UINT Message, WPARAM WParam, LPARAM LParam)
case WM_KEYDOWN :
case WM_SYSKEYDOWN :
{
- if (myKeyRepeatEnabled || ((HIWORD(LParam) & KF_REPEAT) == 0))
+ if (m_keyRepeatEnabled || ((HIWORD(lParam) & KF_REPEAT) == 0))
{
- Event Evt;
- Evt.Type = Event::KeyPressed;
- Evt.Key.Alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
- Evt.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
- Evt.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
- Evt.Key.Code = VirtualKeyCodeToSF(WParam, LParam);
- SendEvent(Evt);
+ Event event;
+ event.type = Event::KeyPressed;
+ event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
+ event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
+ event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
+ event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
+ event.key.code = virtualKeyCodeToSF(wParam, lParam);
+ pushEvent(event);
}
break;
}
@@ -786,301 +578,315 @@ void WindowImplWin32::ProcessEvent(UINT Message, WPARAM WParam, LPARAM LParam)
case WM_KEYUP :
case WM_SYSKEYUP :
{
- Event Evt;
- Evt.Type = Event::KeyReleased;
- Evt.Key.Alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
- Evt.Key.Control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
- Evt.Key.Shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
- Evt.Key.Code = VirtualKeyCodeToSF(WParam, LParam);
- SendEvent(Evt);
-
+ Event event;
+ event.type = Event::KeyReleased;
+ event.key.alt = HIWORD(GetAsyncKeyState(VK_MENU)) != 0;
+ event.key.control = HIWORD(GetAsyncKeyState(VK_CONTROL)) != 0;
+ event.key.shift = HIWORD(GetAsyncKeyState(VK_SHIFT)) != 0;
+ event.key.system = HIWORD(GetAsyncKeyState(VK_LWIN)) || HIWORD(GetAsyncKeyState(VK_RWIN));
+ event.key.code = virtualKeyCodeToSF(wParam, lParam);
+ pushEvent(event);
break;
}
// Mouse wheel event
case WM_MOUSEWHEEL :
{
- Event Evt;
- Evt.Type = Event::MouseWheelMoved;
- Evt.MouseWheel.Delta = static_cast<Int16>(HIWORD(WParam)) / 120;
- SendEvent(Evt);
+ // Mouse position is in screen coordinates, convert it to window coordinates
+ POINT position;
+ position.x = static_cast<Int16>(LOWORD(lParam));
+ position.y = static_cast<Int16>(HIWORD(lParam));
+ ScreenToClient(m_handle, &position);
+
+ Event event;
+ event.type = Event::MouseWheelMoved;
+ event.mouseWheel.delta = static_cast<Int16>(HIWORD(wParam)) / 120;
+ event.mouseWheel.x = position.x;
+ event.mouseWheel.y = position.y;
+ pushEvent(event);
break;
}
// Mouse left button down event
case WM_LBUTTONDOWN :
{
- Event Evt;
- Evt.Type = Event::MouseButtonPressed;
- Evt.MouseButton.Button = Mouse::Left;
- Evt.MouseButton.X = LOWORD(LParam);
- Evt.MouseButton.Y = HIWORD(LParam);
- SendEvent(Evt);
+ Event event;
+ event.type = Event::MouseButtonPressed;
+ event.mouseButton.button = Mouse::Left;
+ event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
+ event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
+ pushEvent(event);
break;
}
// Mouse left button up event
case WM_LBUTTONUP :
{
- Event Evt;
- Evt.Type = Event::MouseButtonReleased;
- Evt.MouseButton.Button = Mouse::Left;
- Evt.MouseButton.X = LOWORD(LParam);
- Evt.MouseButton.Y = HIWORD(LParam);
- SendEvent(Evt);
+ Event event;
+ event.type = Event::MouseButtonReleased;
+ event.mouseButton.button = Mouse::Left;
+ event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
+ event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
+ pushEvent(event);
break;
}
// Mouse right button down event
case WM_RBUTTONDOWN :
{
- Event Evt;
- Evt.Type = Event::MouseButtonPressed;
- Evt.MouseButton.Button = Mouse::Right;
- Evt.MouseButton.X = LOWORD(LParam);
- Evt.MouseButton.Y = HIWORD(LParam);
- SendEvent(Evt);
+ Event event;
+ event.type = Event::MouseButtonPressed;
+ event.mouseButton.button = Mouse::Right;
+ event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
+ event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
+ pushEvent(event);
break;
}
// Mouse right button up event
case WM_RBUTTONUP :
{
- Event Evt;
- Evt.Type = Event::MouseButtonReleased;
- Evt.MouseButton.Button = Mouse::Right;
- Evt.MouseButton.X = LOWORD(LParam);
- Evt.MouseButton.Y = HIWORD(LParam);
- SendEvent(Evt);
+ Event event;
+ event.type = Event::MouseButtonReleased;
+ event.mouseButton.button = Mouse::Right;
+ event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
+ event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
+ pushEvent(event);
break;
}
// Mouse wheel button down event
case WM_MBUTTONDOWN :
{
- Event Evt;
- Evt.Type = Event::MouseButtonPressed;
- Evt.MouseButton.Button = Mouse::Middle;
- Evt.MouseButton.X = LOWORD(LParam);
- Evt.MouseButton.Y = HIWORD(LParam);
- SendEvent(Evt);
+ Event event;
+ event.type = Event::MouseButtonPressed;
+ event.mouseButton.button = Mouse::Middle;
+ event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
+ event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
+ pushEvent(event);
break;
}
// Mouse wheel button up event
case WM_MBUTTONUP :
{
- Event Evt;
- Evt.Type = Event::MouseButtonReleased;
- Evt.MouseButton.Button = Mouse::Middle;
- Evt.MouseButton.X = LOWORD(LParam);
- Evt.MouseButton.Y = HIWORD(LParam);
- SendEvent(Evt);
+ Event event;
+ event.type = Event::MouseButtonReleased;
+ event.mouseButton.button = Mouse::Middle;
+ event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
+ event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
+ pushEvent(event);
break;
}
// Mouse X button down event
case WM_XBUTTONDOWN :
{
- Event Evt;
- Evt.Type = Event::MouseButtonPressed;
- Evt.MouseButton.Button = HIWORD(WParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2;
- Evt.MouseButton.X = LOWORD(LParam);
- Evt.MouseButton.Y = HIWORD(LParam);
- SendEvent(Evt);
+ Event event;
+ event.type = Event::MouseButtonPressed;
+ event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2;
+ event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
+ event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
+ pushEvent(event);
break;
}
// Mouse X button up event
case WM_XBUTTONUP :
{
- Event Evt;
- Evt.Type = Event::MouseButtonReleased;
- Evt.MouseButton.Button = HIWORD(WParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2;
- Evt.MouseButton.X = LOWORD(LParam);
- Evt.MouseButton.Y = HIWORD(LParam);
- SendEvent(Evt);
+ Event event;
+ event.type = Event::MouseButtonReleased;
+ event.mouseButton.button = HIWORD(wParam) == XBUTTON1 ? Mouse::XButton1 : Mouse::XButton2;
+ event.mouseButton.x = static_cast<Int16>(LOWORD(lParam));
+ event.mouseButton.y = static_cast<Int16>(HIWORD(lParam));
+ pushEvent(event);
break;
}
// Mouse move event
case WM_MOUSEMOVE :
{
- // Check if we need to generate a MouseEntered event
- if (!myIsCursorIn)
+ // Extract the mouse local coordinates
+ int x = static_cast<Int16>(LOWORD(lParam));
+ int y = static_cast<Int16>(HIWORD(lParam));
+
+ // Get the client area of the window
+ RECT area;
+ GetClientRect(m_handle, &area);
+
+ // Check the mouse position against the window
+ if ((x < area.left) || (x > area.right) || (y < area.top) || (y > area.bottom))
{
- TRACKMOUSEEVENT MouseEvent;
- MouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
- MouseEvent.hwndTrack = myHandle;
- MouseEvent.dwFlags = TME_LEAVE;
- TrackMouseEvent(&MouseEvent);
+ // Mouse is outside
- myIsCursorIn = true;
+ // Release the mouse capture
+ ReleaseCapture();
- Event Evt;
- Evt.Type = Event::MouseEntered;
- SendEvent(Evt);
+ // Generate a MouseLeft event
+ Event event;
+ event.type = Event::MouseLeft;
+ pushEvent(event);
}
+ else
+ {
+ // Mouse is inside
+ if (GetCapture() != m_handle)
+ {
+ // Mouse was previously outside the window
- Event Evt;
- Evt.Type = Event::MouseMoved;
- Evt.MouseMove.X = LOWORD(LParam);
- Evt.MouseMove.Y = HIWORD(LParam);
- SendEvent(Evt);
- break;
- }
+ // Capture the mouse
+ SetCapture(m_handle);
- // Mouse leave event
- case WM_MOUSELEAVE :
- {
- myIsCursorIn = false;
+ // Generate a MouseEntered event
+ Event event;
+ event.type = Event::MouseEntered;
+ pushEvent(event);
+ }
- Event Evt;
- Evt.Type = Event::MouseLeft;
- SendEvent(Evt);
- break;
+ // Generate a MouseMove event
+ Event event;
+ event.type = Event::MouseMoved;
+ event.mouseMove.x = x;
+ event.mouseMove.y = y;
+ pushEvent(event);
+ break;
+ }
}
}
}
////////////////////////////////////////////////////////////
-/// Convert a Win32 virtual key code to a SFML key code
-////////////////////////////////////////////////////////////
-Key::Code WindowImplWin32::VirtualKeyCodeToSF(WPARAM VirtualKey, LPARAM Flags)
+Keyboard::Key WindowImplWin32::virtualKeyCodeToSF(WPARAM key, LPARAM flags)
{
- switch (VirtualKey)
+ switch (key)
{
// Check the scancode to distinguish between left and right shift
case VK_SHIFT :
{
- static UINT LShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC);
- UINT scancode = (Flags & (0xFF << 16)) >> 16;
- return scancode == LShift ? Key::LShift : Key::RShift;
+ static UINT lShift = MapVirtualKey(VK_LSHIFT, MAPVK_VK_TO_VSC);
+ UINT scancode = static_cast<UINT>((flags & (0xFF << 16)) >> 16);
+ return scancode == lShift ? Keyboard::LShift : Keyboard::RShift;
}
// Check the "extended" flag to distinguish between left and right alt
- case VK_MENU : return (HIWORD(Flags) & KF_EXTENDED) ? Key::RAlt : Key::LAlt;
+ case VK_MENU : return (HIWORD(flags) & KF_EXTENDED) ? Keyboard::RAlt : Keyboard::LAlt;
// Check the "extended" flag to distinguish between left and right control
- case VK_CONTROL : return (HIWORD(Flags) & KF_EXTENDED) ? Key::RControl : Key::LControl;
+ case VK_CONTROL : return (HIWORD(flags) & KF_EXTENDED) ? Keyboard::RControl : Keyboard::LControl;
// Other keys are reported properly
- case VK_LWIN : return Key::LSystem;
- case VK_RWIN : return Key::RSystem;
- case VK_APPS : return Key::Menu;
- case VK_OEM_1 : return Key::SemiColon;
- case VK_OEM_2 : return Key::Slash;
- case VK_OEM_PLUS : return Key::Equal;
- case VK_OEM_MINUS : return Key::Dash;
- case VK_OEM_4 : return Key::LBracket;
- case VK_OEM_6 : return Key::RBracket;
- case VK_OEM_COMMA : return Key::Comma;
- case VK_OEM_PERIOD : return Key::Period;
- case VK_OEM_7 : return Key::Quote;
- case VK_OEM_5 : return Key::BackSlash;
- case VK_OEM_3 : return Key::Tilde;
- case VK_ESCAPE : return Key::Escape;
- case VK_SPACE : return Key::Space;
- case VK_RETURN : return Key::Return;
- case VK_BACK : return Key::Back;
- case VK_TAB : return Key::Tab;
- case VK_PRIOR : return Key::PageUp;
- case VK_NEXT : return Key::PageDown;
- case VK_END : return Key::End;
- case VK_HOME : return Key::Home;
- case VK_INSERT : return Key::Insert;
- case VK_DELETE : return Key::Delete;
- case VK_ADD : return Key::Add;
- case VK_SUBTRACT : return Key::Subtract;
- case VK_MULTIPLY : return Key::Multiply;
- case VK_DIVIDE : return Key::Divide;
- case VK_PAUSE : return Key::Pause;
- case VK_F1 : return Key::F1;
- case VK_F2 : return Key::F2;
- case VK_F3 : return Key::F3;
- case VK_F4 : return Key::F4;
- case VK_F5 : return Key::F5;
- case VK_F6 : return Key::F6;
- case VK_F7 : return Key::F7;
- case VK_F8 : return Key::F8;
- case VK_F9 : return Key::F9;
- case VK_F10 : return Key::F10;
- case VK_F11 : return Key::F11;
- case VK_F12 : return Key::F12;
- case VK_F13 : return Key::F13;
- case VK_F14 : return Key::F14;
- case VK_F15 : return Key::F15;
- case VK_LEFT : return Key::Left;
- case VK_RIGHT : return Key::Right;
- case VK_UP : return Key::Up;
- case VK_DOWN : return Key::Down;
- case VK_NUMPAD0 : return Key::Numpad0;
- case VK_NUMPAD1 : return Key::Numpad1;
- case VK_NUMPAD2 : return Key::Numpad2;
- case VK_NUMPAD3 : return Key::Numpad3;
- case VK_NUMPAD4 : return Key::Numpad4;
- case VK_NUMPAD5 : return Key::Numpad5;
- case VK_NUMPAD6 : return Key::Numpad6;
- case VK_NUMPAD7 : return Key::Numpad7;
- case VK_NUMPAD8 : return Key::Numpad8;
- case VK_NUMPAD9 : return Key::Numpad9;
- case 'A' : return Key::A;
- case 'Z' : return Key::Z;
- case 'E' : return Key::E;
- case 'R' : return Key::R;
- case 'T' : return Key::T;
- case 'Y' : return Key::Y;
- case 'U' : return Key::U;
- case 'I' : return Key::I;
- case 'O' : return Key::O;
- case 'P' : return Key::P;
- case 'Q' : return Key::Q;
- case 'S' : return Key::S;
- case 'D' : return Key::D;
- case 'F' : return Key::F;
- case 'G' : return Key::G;
- case 'H' : return Key::H;
- case 'J' : return Key::J;
- case 'K' : return Key::K;
- case 'L' : return Key::L;
- case 'M' : return Key::M;
- case 'W' : return Key::W;
- case 'X' : return Key::X;
- case 'C' : return Key::C;
- case 'V' : return Key::V;
- case 'B' : return Key::B;
- case 'N' : return Key::N;
- case '0' : return Key::Num0;
- case '1' : return Key::Num1;
- case '2' : return Key::Num2;
- case '3' : return Key::Num3;
- case '4' : return Key::Num4;
- case '5' : return Key::Num5;
- case '6' : return Key::Num6;
- case '7' : return Key::Num7;
- case '8' : return Key::Num8;
- case '9' : return Key::Num9;
- }
-
- return Key::Code(0);
+ case VK_LWIN : return Keyboard::LSystem;
+ case VK_RWIN : return Keyboard::RSystem;
+ case VK_APPS : return Keyboard::Menu;
+ case VK_OEM_1 : return Keyboard::SemiColon;
+ case VK_OEM_2 : return Keyboard::Slash;
+ case VK_OEM_PLUS : return Keyboard::Equal;
+ case VK_OEM_MINUS : return Keyboard::Dash;
+ case VK_OEM_4 : return Keyboard::LBracket;
+ case VK_OEM_6 : return Keyboard::RBracket;
+ case VK_OEM_COMMA : return Keyboard::Comma;
+ case VK_OEM_PERIOD : return Keyboard::Period;
+ case VK_OEM_7 : return Keyboard::Quote;
+ case VK_OEM_5 : return Keyboard::BackSlash;
+ case VK_OEM_3 : return Keyboard::Tilde;
+ case VK_ESCAPE : return Keyboard::Escape;
+ case VK_SPACE : return Keyboard::Space;
+ case VK_RETURN : return Keyboard::Return;
+ case VK_BACK : return Keyboard::BackSpace;
+ case VK_TAB : return Keyboard::Tab;
+ case VK_PRIOR : return Keyboard::PageUp;
+ case VK_NEXT : return Keyboard::PageDown;
+ case VK_END : return Keyboard::End;
+ case VK_HOME : return Keyboard::Home;
+ case VK_INSERT : return Keyboard::Insert;
+ case VK_DELETE : return Keyboard::Delete;
+ case VK_ADD : return Keyboard::Add;
+ case VK_SUBTRACT : return Keyboard::Subtract;
+ case VK_MULTIPLY : return Keyboard::Multiply;
+ case VK_DIVIDE : return Keyboard::Divide;
+ case VK_PAUSE : return Keyboard::Pause;
+ case VK_F1 : return Keyboard::F1;
+ case VK_F2 : return Keyboard::F2;
+ case VK_F3 : return Keyboard::F3;
+ case VK_F4 : return Keyboard::F4;
+ case VK_F5 : return Keyboard::F5;
+ case VK_F6 : return Keyboard::F6;
+ case VK_F7 : return Keyboard::F7;
+ case VK_F8 : return Keyboard::F8;
+ case VK_F9 : return Keyboard::F9;
+ case VK_F10 : return Keyboard::F10;
+ case VK_F11 : return Keyboard::F11;
+ case VK_F12 : return Keyboard::F12;
+ case VK_F13 : return Keyboard::F13;
+ case VK_F14 : return Keyboard::F14;
+ case VK_F15 : return Keyboard::F15;
+ case VK_LEFT : return Keyboard::Left;
+ case VK_RIGHT : return Keyboard::Right;
+ case VK_UP : return Keyboard::Up;
+ case VK_DOWN : return Keyboard::Down;
+ case VK_NUMPAD0 : return Keyboard::Numpad0;
+ case VK_NUMPAD1 : return Keyboard::Numpad1;
+ case VK_NUMPAD2 : return Keyboard::Numpad2;
+ case VK_NUMPAD3 : return Keyboard::Numpad3;
+ case VK_NUMPAD4 : return Keyboard::Numpad4;
+ case VK_NUMPAD5 : return Keyboard::Numpad5;
+ case VK_NUMPAD6 : return Keyboard::Numpad6;
+ case VK_NUMPAD7 : return Keyboard::Numpad7;
+ case VK_NUMPAD8 : return Keyboard::Numpad8;
+ case VK_NUMPAD9 : return Keyboard::Numpad9;
+ case 'A' : return Keyboard::A;
+ case 'Z' : return Keyboard::Z;
+ case 'E' : return Keyboard::E;
+ case 'R' : return Keyboard::R;
+ case 'T' : return Keyboard::T;
+ case 'Y' : return Keyboard::Y;
+ case 'U' : return Keyboard::U;
+ case 'I' : return Keyboard::I;
+ case 'O' : return Keyboard::O;
+ case 'P' : return Keyboard::P;
+ case 'Q' : return Keyboard::Q;
+ case 'S' : return Keyboard::S;
+ case 'D' : return Keyboard::D;
+ case 'F' : return Keyboard::F;
+ case 'G' : return Keyboard::G;
+ case 'H' : return Keyboard::H;
+ case 'J' : return Keyboard::J;
+ case 'K' : return Keyboard::K;
+ case 'L' : return Keyboard::L;
+ case 'M' : return Keyboard::M;
+ case 'W' : return Keyboard::W;
+ case 'X' : return Keyboard::X;
+ case 'C' : return Keyboard::C;
+ case 'V' : return Keyboard::V;
+ case 'B' : return Keyboard::B;
+ case 'N' : return Keyboard::N;
+ case '0' : return Keyboard::Num0;
+ case '1' : return Keyboard::Num1;
+ case '2' : return Keyboard::Num2;
+ case '3' : return Keyboard::Num3;
+ case '4' : return Keyboard::Num4;
+ case '5' : return Keyboard::Num5;
+ case '6' : return Keyboard::Num6;
+ case '7' : return Keyboard::Num7;
+ case '8' : return Keyboard::Num8;
+ case '9' : return Keyboard::Num9;
+ }
+
+ return Keyboard::Unknown;
}
////////////////////////////////////////////////////////////
-/// Check if the current version of the OS supports unicode
-/// messages and functions ; Windows 95/98/Me may not support
-/// it, whereas Windows NT/2000/XP/Vista will
-////////////////////////////////////////////////////////////
-bool WindowImplWin32::HasUnicodeSupport()
+bool WindowImplWin32::hasUnicodeSupport()
{
- OSVERSIONINFO VersionInfo;
- ZeroMemory(&VersionInfo, sizeof(VersionInfo));
- VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
+ OSVERSIONINFO version;
+ ZeroMemory(&version, sizeof(version));
+ version.dwOSVersionInfoSize = sizeof(version);
- if (GetVersionEx(&VersionInfo))
+ if (GetVersionEx(&version))
{
- return VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT;
+ return version.dwPlatformId == VER_PLATFORM_WIN32_NT;
}
else
{
@@ -1090,41 +896,44 @@ bool WindowImplWin32::HasUnicodeSupport()
////////////////////////////////////////////////////////////
-/// Function called whenever one of our windows receives a message
-////////////////////////////////////////////////////////////
-LRESULT CALLBACK WindowImplWin32::GlobalOnEvent(HWND Handle, UINT Message, WPARAM WParam, LPARAM LParam)
+LRESULT CALLBACK WindowImplWin32::globalOnEvent(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
// Associate handle and Window instance when the creation message is received
- if (Message == WM_CREATE)
+ if (message == WM_CREATE)
{
// Get WindowImplWin32 instance (it was passed as the last argument of CreateWindow)
- long This = reinterpret_cast<long>(reinterpret_cast<CREATESTRUCT*>(LParam)->lpCreateParams);
+ LONG_PTR window = (LONG_PTR)reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams;
// Set as the "user data" parameter of the window
- SetWindowLongPtr(Handle, GWLP_USERDATA, This);
+ SetWindowLongPtr(handle, GWLP_USERDATA, window);
}
// Get the WindowImpl instance corresponding to the window handle
- WindowImplWin32* Window = reinterpret_cast<WindowImplWin32*>(GetWindowLongPtr(Handle, GWLP_USERDATA));
+ WindowImplWin32* window = handle ? reinterpret_cast<WindowImplWin32*>(GetWindowLongPtr(handle, GWLP_USERDATA)) : NULL;
// Forward the event to the appropriate function
- if (Window)
+ if (window)
{
- Window->ProcessEvent(Message, WParam, LParam);
+ window->processEvent(message, wParam, lParam);
- if (Window->myCallback)
- return CallWindowProc(reinterpret_cast<WNDPROC>(Window->myCallback), Handle, Message, WParam, LParam);
+ if (window->m_callback)
+ return CallWindowProc(reinterpret_cast<WNDPROC>(window->m_callback), handle, message, wParam, lParam);
}
// We don't forward the WM_CLOSE message to prevent the OS from automatically destroying the window
- if (Message == WM_CLOSE)
+ if (message == WM_CLOSE)
return 0;
- static const bool HasUnicode = HasUnicodeSupport();
- return HasUnicode ? DefWindowProcW(Handle, Message, WParam, LParam) :
- DefWindowProcA(Handle, Message, WParam, LParam);
+ // Don't forward the menu system command, so that pressing ALT or F10 doesn't steal the focus
+ if ((message == WM_SYSCOMMAND) && (wParam == SC_KEYMENU))
+ return 0;
+
+ static const bool hasUnicode = hasUnicodeSupport();
+ return hasUnicode ? DefWindowProcW(handle, message, wParam, lParam) :
+ DefWindowProcA(handle, message, wParam, lParam);
}
} // namespace priv
} // namespace sf
+