2011-08-28 15:17:58 +02:00
|
|
|
/*
|
2012-01-02 17:58:37 +01:00
|
|
|
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
|
2011-08-28 15:17:58 +02:00
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2012-06-12 18:50:43 +02:00
|
|
|
#ifdef WIN32
|
|
|
|
|
2011-12-03 22:41:37 +01:00
|
|
|
#include "win32window.h"
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
#include <framework/application.h>
|
2011-11-23 17:35:16 +01:00
|
|
|
#include <framework/thirdparty/apngloader.h>
|
|
|
|
#include <framework/core/resourcemanager.h>
|
|
|
|
|
2012-01-20 16:00:24 +01:00
|
|
|
#define HSB_BIT_SET(p, n) (p[(n)/8] |= (128 >>((n)%8)))
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
WIN32Window::WIN32Window()
|
|
|
|
{
|
|
|
|
m_window = 0;
|
|
|
|
m_instance = 0;
|
|
|
|
m_deviceContext = 0;
|
2012-01-20 03:48:38 +01:00
|
|
|
m_cursor = 0;
|
2012-02-04 01:43:28 +01:00
|
|
|
m_minimumSize = Size(600,480);
|
2011-12-29 19:18:12 +01:00
|
|
|
|
2012-06-10 20:52:08 +02:00
|
|
|
#ifdef OPENGL_ES
|
|
|
|
m_eglConfig = 0;
|
|
|
|
m_eglContext = 0;
|
|
|
|
m_eglDisplay = 0;
|
|
|
|
m_eglSurface = 0;
|
|
|
|
#else
|
|
|
|
m_wglContext = 0;
|
|
|
|
#endif
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap[VK_ESCAPE] = Fw::KeyEscape;
|
|
|
|
m_keyMap[VK_TAB] = Fw::KeyTab;
|
2012-02-04 03:11:18 +01:00
|
|
|
m_keyMap[VK_RETURN] = Fw::KeyEnter;
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap[VK_BACK] = Fw::KeyBackspace;
|
|
|
|
m_keyMap[VK_SPACE] = Fw::KeySpace;
|
|
|
|
|
|
|
|
m_keyMap[VK_PRIOR] = Fw::KeyPageUp;
|
|
|
|
m_keyMap[VK_NEXT] = Fw::KeyPageDown;
|
|
|
|
m_keyMap[VK_HOME] = Fw::KeyHome;
|
|
|
|
m_keyMap[VK_END] = Fw::KeyEnd;
|
|
|
|
m_keyMap[VK_INSERT] = Fw::KeyInsert;
|
|
|
|
m_keyMap[VK_DELETE] = Fw::KeyDelete;
|
|
|
|
|
|
|
|
m_keyMap[VK_UP] = Fw::KeyUp;
|
|
|
|
m_keyMap[VK_DOWN] = Fw::KeyDown;
|
|
|
|
m_keyMap[VK_LEFT] = Fw::KeyLeft;
|
|
|
|
m_keyMap[VK_RIGHT] = Fw::KeyRight;
|
|
|
|
|
|
|
|
m_keyMap[VK_NUMLOCK] = Fw::KeyNumLock;
|
|
|
|
m_keyMap[VK_SCROLL] = Fw::KeyScrollLock;
|
|
|
|
m_keyMap[VK_CAPITAL] = Fw::KeyCapsLock;
|
|
|
|
m_keyMap[VK_SNAPSHOT] = Fw::KeyPrintScreen;
|
|
|
|
m_keyMap[VK_PAUSE] = Fw::KeyPause;
|
|
|
|
|
2012-01-17 07:24:58 +01:00
|
|
|
m_keyMap[VK_CONTROL] = Fw::KeyCtrl;
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap[VK_LCONTROL] = Fw::KeyCtrl;
|
|
|
|
m_keyMap[VK_RCONTROL] = Fw::KeyCtrl;
|
2012-01-17 07:24:58 +01:00
|
|
|
m_keyMap[VK_SHIFT] = Fw::KeyShift;
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap[VK_LSHIFT] = Fw::KeyShift;
|
|
|
|
m_keyMap[VK_RSHIFT] = Fw::KeyShift;
|
2012-01-17 07:24:58 +01:00
|
|
|
m_keyMap[VK_MENU] = Fw::KeyAlt;
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap[VK_LMENU] = Fw::KeyAlt;
|
2012-02-04 03:43:43 +01:00
|
|
|
m_keyMap[VK_RMENU] = Fw::KeyAlt;
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap[VK_LWIN] = Fw::KeyMeta;
|
|
|
|
m_keyMap[VK_RWIN] = Fw::KeyMeta;
|
2012-02-04 03:43:43 +01:00
|
|
|
m_keyMap[VK_APPS] = Fw::KeyMenu;
|
2011-08-30 00:27:22 +02:00
|
|
|
|
|
|
|
// ascii characters
|
2011-11-03 11:10:39 +01:00
|
|
|
/*
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap['!'] = Fw::KeyExclamation;
|
|
|
|
m_keyMap['"'] = Fw::KeyQuote;
|
|
|
|
m_keyMap['#'] = Fw::KeyNumberSign;
|
|
|
|
m_keyMap['$'] = Fw::KeyDollar;
|
|
|
|
m_keyMap['%'] = Fw::KeyPercent;
|
|
|
|
m_keyMap['$'] = Fw::KeyAmpersand;
|
|
|
|
m_keyMap['\''] = Fw::KeyApostrophe;
|
|
|
|
m_keyMap['('] = Fw::KeyLeftParen;
|
|
|
|
m_keyMap[')'] = Fw::KeyRightParen;
|
|
|
|
m_keyMap['*'] = Fw::KeyAsterisk;
|
|
|
|
m_keyMap['+'] = Fw::KeyPlus;
|
|
|
|
m_keyMap['.'] = Fw::KeyComma;
|
|
|
|
m_keyMap['-'] = Fw::KeyMinus;
|
|
|
|
m_keyMap['.'] = Fw::KeyPeriod;
|
|
|
|
m_keyMap['/'] = Fw::KeySlash;
|
2011-11-03 11:10:39 +01:00
|
|
|
*/
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap['0'] = Fw::Key0;
|
|
|
|
m_keyMap['1'] = Fw::Key1;
|
|
|
|
m_keyMap['2'] = Fw::Key2;
|
|
|
|
m_keyMap['3'] = Fw::Key3;
|
|
|
|
m_keyMap['4'] = Fw::Key4;
|
|
|
|
m_keyMap['5'] = Fw::Key5;
|
|
|
|
m_keyMap['6'] = Fw::Key6;
|
|
|
|
m_keyMap['7'] = Fw::Key7;
|
|
|
|
m_keyMap['8'] = Fw::Key8;
|
|
|
|
m_keyMap['9'] = Fw::Key9;
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2011-11-03 11:10:39 +01:00
|
|
|
/*
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap[':'] = Fw::KeyColon;
|
|
|
|
m_keyMap[';'] = Fw::KeySemicolon;
|
|
|
|
m_keyMap['<'] = Fw::KeyLess;
|
|
|
|
m_keyMap['='] = Fw::KeyEqual;
|
|
|
|
m_keyMap['>'] = Fw::KeyGreater;
|
|
|
|
m_keyMap['?'] = Fw::KeyQuestion;
|
|
|
|
m_keyMap['@'] = Fw::KeyAtSign;
|
2011-11-03 11:10:39 +01:00
|
|
|
*/
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap['A'] = Fw::KeyA;
|
|
|
|
m_keyMap['B'] = Fw::KeyB;
|
|
|
|
m_keyMap['C'] = Fw::KeyC;
|
|
|
|
m_keyMap['D'] = Fw::KeyD;
|
|
|
|
m_keyMap['E'] = Fw::KeyE;
|
|
|
|
m_keyMap['F'] = Fw::KeyF;
|
|
|
|
m_keyMap['G'] = Fw::KeyG;
|
|
|
|
m_keyMap['H'] = Fw::KeyH;
|
|
|
|
m_keyMap['I'] = Fw::KeyI;
|
|
|
|
m_keyMap['J'] = Fw::KeyJ;
|
|
|
|
m_keyMap['K'] = Fw::KeyK;
|
|
|
|
m_keyMap['L'] = Fw::KeyL;
|
|
|
|
m_keyMap['M'] = Fw::KeyM;
|
|
|
|
m_keyMap['N'] = Fw::KeyN;
|
|
|
|
m_keyMap['O'] = Fw::KeyO;
|
|
|
|
m_keyMap['P'] = Fw::KeyP;
|
|
|
|
m_keyMap['Q'] = Fw::KeyQ;
|
|
|
|
m_keyMap['R'] = Fw::KeyR;
|
|
|
|
m_keyMap['S'] = Fw::KeyS;
|
|
|
|
m_keyMap['T'] = Fw::KeyT;
|
|
|
|
m_keyMap['U'] = Fw::KeyU;
|
|
|
|
m_keyMap['V'] = Fw::KeyV;
|
|
|
|
m_keyMap['W'] = Fw::KeyW;
|
|
|
|
m_keyMap['X'] = Fw::KeyX;
|
|
|
|
m_keyMap['Y'] = Fw::KeyY;
|
|
|
|
m_keyMap['Z'] = Fw::KeyZ;
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2011-11-03 11:10:39 +01:00
|
|
|
/*
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap['['] = Fw::KeyLeftBracket;
|
|
|
|
m_keyMap['\\'] = Fw::KeyBackslash;
|
|
|
|
m_keyMap[']'] = Fw::KeyRightBracket;
|
|
|
|
m_keyMap['^'] = Fw::KeyCaret;
|
|
|
|
m_keyMap['_'] = Fw::KeyUnderscore;
|
|
|
|
m_keyMap['`'] = Fw::KeyGrave;
|
|
|
|
m_keyMap['{'] = Fw::KeyLeftCurly;
|
|
|
|
m_keyMap['|'] = Fw::KeyBar;
|
|
|
|
m_keyMap['}'] = Fw::KeyRightCurly;
|
|
|
|
m_keyMap['~'] = Fw::KeyTilde;
|
2011-11-03 11:10:39 +01:00
|
|
|
*/
|
2011-08-30 00:27:22 +02:00
|
|
|
|
|
|
|
// keypad
|
2012-03-30 12:21:24 +02:00
|
|
|
/*
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap[VK_ADD] = Fw::KeyPlus;
|
|
|
|
m_keyMap[VK_SUBTRACT] = Fw::KeyMinus;
|
|
|
|
m_keyMap[VK_DECIMAL] = Fw::KeyPeriod;
|
|
|
|
m_keyMap[VK_DIVIDE] = Fw::KeySlash;
|
|
|
|
m_keyMap[VK_MULTIPLY] = Fw::KeyAsterisk;
|
2012-03-30 12:21:24 +02:00
|
|
|
*/
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap[VK_OEM_1] = Fw::KeySemicolon;
|
|
|
|
m_keyMap[VK_OEM_2] = Fw::KeySlash;
|
|
|
|
m_keyMap[VK_OEM_3] = Fw::KeyGrave;
|
|
|
|
m_keyMap[VK_OEM_4] = Fw::KeyLeftBracket;
|
|
|
|
m_keyMap[VK_OEM_5] = Fw::KeyBackslash;
|
|
|
|
m_keyMap[VK_OEM_6] = Fw::KeyRightBracket;
|
|
|
|
m_keyMap[VK_OEM_7] = Fw::KeyApostrophe;
|
|
|
|
m_keyMap[VK_OEM_MINUS] = Fw::KeyMinus;
|
2012-03-30 12:21:24 +02:00
|
|
|
m_keyMap[VK_OEM_PLUS] = Fw::KeyEqual;
|
2011-12-29 19:18:12 +01:00
|
|
|
m_keyMap[VK_OEM_COMMA] = Fw::KeyComma;
|
|
|
|
m_keyMap[VK_OEM_PERIOD] = Fw::KeyPeriod;
|
|
|
|
|
|
|
|
m_keyMap[VK_F1] = Fw::KeyF1;
|
|
|
|
m_keyMap[VK_F2] = Fw::KeyF2;
|
|
|
|
m_keyMap[VK_F3] = Fw::KeyF3;
|
|
|
|
m_keyMap[VK_F4] = Fw::KeyF4;
|
|
|
|
m_keyMap[VK_F5] = Fw::KeyF5;
|
|
|
|
m_keyMap[VK_F6] = Fw::KeyF6;
|
|
|
|
m_keyMap[VK_F7] = Fw::KeyF7;
|
|
|
|
m_keyMap[VK_F8] = Fw::KeyF8;
|
|
|
|
m_keyMap[VK_F9] = Fw::KeyF9;
|
|
|
|
m_keyMap[VK_F10] = Fw::KeyF10;
|
|
|
|
m_keyMap[VK_F11] = Fw::KeyF11;
|
|
|
|
m_keyMap[VK_F12] = Fw::KeyF12;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WIN32Window::init()
|
|
|
|
{
|
|
|
|
m_instance = GetModuleHandle(NULL);
|
|
|
|
|
|
|
|
internalCreateWindow();
|
|
|
|
internalCreateGLContext();
|
|
|
|
}
|
|
|
|
|
|
|
|
void WIN32Window::terminate()
|
|
|
|
{
|
2012-06-10 20:52:08 +02:00
|
|
|
internalDestroyGLContext();
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
if(m_deviceContext) {
|
|
|
|
if(!ReleaseDC(m_window, m_deviceContext))
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.error("Release device context failed.");
|
2011-12-29 19:18:12 +01:00
|
|
|
m_deviceContext = NULL;
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
|
2012-01-20 03:48:38 +01:00
|
|
|
if(m_cursor) {
|
|
|
|
DestroyCursor(m_cursor);
|
|
|
|
m_cursor = NULL;
|
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
if(m_window) {
|
|
|
|
if(!DestroyWindow(m_window))
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.error("ERROR: Destroy window failed.");
|
2011-12-29 19:18:12 +01:00
|
|
|
m_window = NULL;
|
|
|
|
}
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
if(m_instance) {
|
2012-03-16 14:28:29 +01:00
|
|
|
if(!UnregisterClassA(g_app->getName().c_str(), m_instance))
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.error("UnregisterClassA failed");
|
2011-12-29 19:18:12 +01:00
|
|
|
m_instance = NULL;
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
struct WindowProcProxy {
|
|
|
|
static LRESULT CALLBACK call(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
|
|
|
WIN32Window *window = (WIN32Window*)&g_window;
|
|
|
|
return window->windowProc(hWnd, uMsg, wParam, lParam);
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
};
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2012-06-11 01:48:53 +02:00
|
|
|
void WIN32Window::internalCreateWindow()
|
2011-08-30 00:27:22 +02:00
|
|
|
{
|
2012-01-20 03:48:38 +01:00
|
|
|
m_defaultCursor = LoadCursor(NULL, IDC_ARROW);
|
2011-12-29 19:18:12 +01:00
|
|
|
WNDCLASSA wc;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
|
|
|
wc.lpfnWndProc = (WNDPROC)WindowProcProxy::call;
|
|
|
|
wc.cbClsExtra = 0;
|
|
|
|
wc.cbWndExtra = 0;
|
|
|
|
wc.hInstance = m_instance;
|
|
|
|
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
|
2012-01-20 03:48:38 +01:00
|
|
|
wc.hCursor = m_defaultCursor;
|
2012-06-11 01:48:53 +02:00
|
|
|
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
2011-12-29 19:18:12 +01:00
|
|
|
wc.lpszMenuName = NULL;
|
2012-03-16 14:28:29 +01:00
|
|
|
wc.lpszClassName = g_app->getName().c_str();
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
if(!RegisterClassA(&wc))
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.fatal("Failed to register the window class.");
|
2011-08-30 00:27:22 +02:00
|
|
|
DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
2012-01-07 00:26:29 +01:00
|
|
|
DWORD dwStyle = WS_OVERLAPPEDWINDOW;
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2012-02-04 01:43:28 +01:00
|
|
|
// initialize in the center of the screen
|
|
|
|
m_size = m_minimumSize;
|
|
|
|
m_position = ((getDisplaySize() - m_size) / 2).toPoint();
|
|
|
|
|
2012-01-30 01:00:12 +01:00
|
|
|
RECT windowRect = {m_position.x, m_position.y, m_position.x + m_size.width(), m_position.y + m_size.height()};
|
2011-08-30 00:27:22 +02:00
|
|
|
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);
|
|
|
|
|
2012-01-07 00:26:29 +01:00
|
|
|
updateUnmaximizedCoords();
|
2011-12-29 19:18:12 +01:00
|
|
|
m_window = CreateWindowExA(dwExStyle,
|
2012-03-16 14:28:29 +01:00
|
|
|
g_app->getName().c_str(),
|
2011-12-29 19:18:12 +01:00
|
|
|
NULL,
|
|
|
|
dwStyle,
|
|
|
|
windowRect.left,
|
|
|
|
windowRect.top,
|
|
|
|
windowRect.right - windowRect.left,
|
|
|
|
windowRect.bottom - windowRect.top,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
m_instance,
|
|
|
|
NULL);
|
2011-11-23 17:35:16 +01:00
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
if(!m_window)
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.fatal("Unable to create window");
|
2011-11-23 17:35:16 +01:00
|
|
|
|
2012-03-27 23:33:58 +02:00
|
|
|
ShowWindow(m_window, SW_HIDE);
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
m_deviceContext = GetDC(m_window);
|
|
|
|
if(!m_deviceContext)
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.fatal("GetDC failed");
|
2011-11-23 17:35:16 +01:00
|
|
|
}
|
|
|
|
|
2012-06-11 01:48:53 +02:00
|
|
|
void WIN32Window::internalCreateGLContext()
|
2012-06-10 20:52:08 +02:00
|
|
|
{
|
|
|
|
#ifdef OPENGL_ES
|
2012-06-11 01:48:53 +02:00
|
|
|
m_eglDisplay = eglGetDisplay(m_deviceContext);
|
2012-06-10 20:52:08 +02:00
|
|
|
if(m_eglDisplay == EGL_NO_DISPLAY)
|
|
|
|
g_logger.fatal("EGL not supported");
|
|
|
|
|
|
|
|
if(!eglInitialize(m_eglDisplay, NULL, NULL))
|
|
|
|
g_logger.fatal("Unable to initialize EGL");
|
|
|
|
|
2012-06-11 01:48:53 +02:00
|
|
|
static int configList[] = {
|
2012-06-10 20:52:08 +02:00
|
|
|
#if OPENGL_ES==2
|
|
|
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
|
|
|
#else
|
|
|
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
|
|
|
|
#endif
|
2012-06-11 01:48:53 +02:00
|
|
|
EGL_RED_SIZE, 4,
|
|
|
|
EGL_GREEN_SIZE, 4,
|
|
|
|
EGL_BLUE_SIZE, 4,
|
|
|
|
EGL_ALPHA_SIZE, 4,
|
2012-06-10 20:52:08 +02:00
|
|
|
EGL_NONE
|
|
|
|
};
|
|
|
|
|
|
|
|
EGLint numConfig;
|
|
|
|
|
2012-06-11 01:48:53 +02:00
|
|
|
if(!eglGetConfigs(m_eglDisplay, NULL, 0, &numConfig))
|
|
|
|
g_logger.fatal("No valid GL configurations");
|
|
|
|
|
|
|
|
if(!eglChooseConfig(m_eglDisplay, configList, &m_eglConfig, 1, &numConfig))
|
2012-06-10 20:52:08 +02:00
|
|
|
g_logger.fatal("Failed to choose EGL config");
|
|
|
|
|
|
|
|
if(numConfig != 1)
|
|
|
|
g_logger.warning("Didn't got the exact EGL config");
|
2012-06-11 01:48:53 +02:00
|
|
|
|
|
|
|
EGLint contextAtrrList[] = {
|
|
|
|
#if OPENGL_ES==2
|
|
|
|
EGL_CONTEXT_CLIENT_VERSION, 2,
|
|
|
|
#else
|
|
|
|
EGL_CONTEXT_CLIENT_VERSION, 1,
|
|
|
|
#endif
|
|
|
|
EGL_NONE
|
|
|
|
};
|
|
|
|
|
|
|
|
m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_window, NULL);
|
|
|
|
if(m_eglSurface == EGL_NO_SURFACE)
|
|
|
|
g_logger.fatal(stdext::format("Unable to create EGL surface: %s", eglGetError()));
|
|
|
|
|
|
|
|
m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAtrrList);
|
|
|
|
if(m_eglContext == EGL_NO_CONTEXT )
|
|
|
|
g_logger.fatal(stdext::format("Unable to create EGL context: %s", eglGetError()));
|
|
|
|
|
|
|
|
if(!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext))
|
|
|
|
g_logger.fatal("Unable to make current EGL context");
|
2012-06-10 20:52:08 +02:00
|
|
|
#else
|
2011-12-29 19:18:12 +01:00
|
|
|
uint pixelFormat;
|
|
|
|
static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR),
|
|
|
|
1,
|
|
|
|
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
|
|
|
PFD_TYPE_RGBA,
|
2012-06-02 20:58:30 +02:00
|
|
|
32, // Select Our Color Depth
|
2012-06-02 17:54:35 +02:00
|
|
|
8, 0, 8, 0, 8, 0, // Color Bits Ignored
|
2012-06-02 01:21:45 +02:00
|
|
|
8, // Alpha Buffer Bits
|
2011-12-29 19:18:12 +01:00
|
|
|
0, // Shift Bit Ignored
|
|
|
|
0, // No Accumulation Buffer
|
2012-03-28 20:10:59 +02:00
|
|
|
0, 0, 0, 0, // Accumulation Bits Ignored
|
2012-06-02 17:54:35 +02:00
|
|
|
0, // Z-Buffer (Depth Buffer)
|
2012-04-04 22:18:24 +02:00
|
|
|
0, // No Stencil Buffer
|
2011-12-29 19:18:12 +01:00
|
|
|
0, // No Auxiliary Buffer
|
|
|
|
PFD_MAIN_PLANE, // Main Drawing Layer
|
|
|
|
0, // Reserved
|
|
|
|
0, 0, 0 }; // Layer Masks Ignored
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2012-03-27 20:14:35 +02:00
|
|
|
pixelFormat = ChoosePixelFormat(m_deviceContext, &pfd);
|
2011-12-29 19:18:12 +01:00
|
|
|
if(!pixelFormat)
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.fatal("Could not find a suitable pixel format");
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
if(!SetPixelFormat(m_deviceContext, pixelFormat, &pfd))
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.fatal("Could not set the pixel format");
|
2012-06-10 20:52:08 +02:00
|
|
|
|
|
|
|
if(!(m_wglContext = wglCreateContext(m_deviceContext)))
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.fatal("Unable to create GL context");
|
2011-08-30 00:27:22 +02:00
|
|
|
|
2012-06-10 20:52:08 +02:00
|
|
|
if(!wglMakeCurrent(m_deviceContext, m_wglContext))
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.fatal("Unable to set GLX context on WIN32 window");
|
2012-06-10 20:52:08 +02:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void WIN32Window::internalDestroyGLContext()
|
|
|
|
{
|
|
|
|
#ifdef OPENGL_ES
|
|
|
|
if(m_eglDisplay) {
|
|
|
|
if(m_eglContext) {
|
|
|
|
eglDestroyContext(m_eglDisplay, m_eglContext);
|
|
|
|
m_eglContext = 0;
|
|
|
|
}
|
|
|
|
if(m_eglSurface) {
|
|
|
|
eglDestroySurface(m_eglDisplay, m_eglSurface);
|
|
|
|
m_eglSurface = 0;
|
|
|
|
}
|
|
|
|
eglTerminate(m_eglDisplay);
|
|
|
|
m_eglDisplay = 0;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if(m_wglContext) {
|
|
|
|
if(!wglMakeCurrent(NULL, NULL))
|
|
|
|
g_logger.error("Release of dc and rc failed.");
|
|
|
|
if(!wglDeleteContext(m_wglContext))
|
|
|
|
g_logger.error("Release rendering context failed.");
|
|
|
|
m_wglContext = NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
bool WIN32Window::isExtensionSupported(const char *ext)
|
2011-08-30 00:27:22 +02:00
|
|
|
{
|
2012-06-10 20:52:08 +02:00
|
|
|
#ifdef OPENGL_ES
|
|
|
|
//TODO
|
|
|
|
return false;
|
|
|
|
#else
|
2012-01-18 00:14:10 +01:00
|
|
|
typedef const char* (WINAPI * wglGetExtensionsStringProc)();
|
2012-01-18 00:07:22 +01:00
|
|
|
wglGetExtensionsStringProc wglGetExtensionsString = (wglGetExtensionsStringProc)getExtensionProcAddress("wglGetExtensionsStringEXT");
|
|
|
|
if(!wglGetExtensionsString)
|
|
|
|
return false;
|
|
|
|
|
2012-01-18 00:14:10 +01:00
|
|
|
const char *exts = wglGetExtensionsString();
|
2012-01-18 00:07:22 +01:00
|
|
|
if(exts && strstr(exts, ext))
|
|
|
|
return true;
|
2011-08-30 00:27:22 +02:00
|
|
|
|
|
|
|
return false;
|
2012-06-10 20:52:08 +02:00
|
|
|
#endif
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
void *WIN32Window::getExtensionProcAddress(const char *ext)
|
2011-08-30 00:27:22 +02:00
|
|
|
{
|
2012-06-10 20:52:08 +02:00
|
|
|
#ifdef OPENGL_ES
|
|
|
|
//TODO
|
|
|
|
return NULL;
|
|
|
|
#else
|
2011-12-29 19:18:12 +01:00
|
|
|
return (void*)wglGetProcAddress(ext);
|
2012-06-10 20:52:08 +02:00
|
|
|
#endif
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
void WIN32Window::move(const Point& pos)
|
2011-08-30 00:27:22 +02:00
|
|
|
{
|
2012-02-04 01:43:28 +01:00
|
|
|
RECT clientRect;
|
|
|
|
GetClientRect(m_window, &clientRect);
|
|
|
|
|
|
|
|
RECT windowRect = {pos.x, pos.y, clientRect.right - clientRect.left, clientRect.bottom - clientRect.top};
|
2012-01-20 03:48:38 +01:00
|
|
|
AdjustWindowRectEx(&windowRect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
|
2012-02-04 01:43:28 +01:00
|
|
|
|
|
|
|
int x = windowRect.left;
|
|
|
|
int y = windowRect.top;
|
|
|
|
GetWindowRect(m_window, &windowRect);
|
|
|
|
int width = windowRect.right - windowRect.left;
|
|
|
|
int height = windowRect.bottom - windowRect.top;
|
|
|
|
|
|
|
|
MoveWindow(m_window, x, y, width, height, TRUE);
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
void WIN32Window::resize(const Size& size)
|
2011-08-30 00:27:22 +02:00
|
|
|
{
|
2012-02-04 01:43:28 +01:00
|
|
|
RECT windowRect;
|
|
|
|
RECT clientRect;
|
|
|
|
|
|
|
|
GetWindowRect(m_window, &windowRect);
|
|
|
|
GetClientRect(m_window, &clientRect);
|
|
|
|
|
|
|
|
int x = windowRect.left;
|
|
|
|
int y = windowRect.top;
|
|
|
|
int width = size.width() + ((windowRect.right - windowRect.left) - (clientRect.right - clientRect.left));
|
|
|
|
int height = size.height() + ((windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top));
|
|
|
|
|
|
|
|
MoveWindow(m_window, x, y, width, height, TRUE);
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
void WIN32Window::show()
|
2011-08-30 00:27:22 +02:00
|
|
|
{
|
2012-01-07 00:26:29 +01:00
|
|
|
ShowWindow(m_window, SW_SHOW);
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
void WIN32Window::hide()
|
2011-08-30 00:27:22 +02:00
|
|
|
{
|
2011-12-29 19:18:12 +01:00
|
|
|
ShowWindow(m_window, SW_HIDE);
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
void WIN32Window::maximize()
|
2011-08-30 00:27:22 +02:00
|
|
|
{
|
2012-01-07 00:26:29 +01:00
|
|
|
ShowWindow(m_window, SW_MAXIMIZE);
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
void WIN32Window::poll()
|
2011-08-30 00:27:22 +02:00
|
|
|
{
|
2012-01-17 07:24:58 +01:00
|
|
|
fireKeysPress();
|
|
|
|
|
2012-02-04 01:43:28 +01:00
|
|
|
MSG msg;
|
2012-04-04 18:21:02 +02:00
|
|
|
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
2012-02-04 01:43:28 +01:00
|
|
|
TranslateMessage(&msg);
|
|
|
|
DispatchMessage(&msg);
|
2011-12-29 19:18:12 +01:00
|
|
|
}
|
2012-02-04 01:43:28 +01:00
|
|
|
|
|
|
|
updateUnmaximizedCoords();
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
|
2012-02-04 03:11:18 +01:00
|
|
|
Fw::Key WIN32Window::retranslateVirtualKey(WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
2012-04-24 14:06:01 +02:00
|
|
|
// ignore numpad keys when numlock is on
|
|
|
|
if((wParam >= VK_NUMPAD0 && wParam <= VK_NUMPAD9) || wParam == VK_SEPARATOR)
|
|
|
|
return Fw::KeyUnknown;
|
2012-02-04 03:11:18 +01:00
|
|
|
|
2012-04-24 14:06:01 +02:00
|
|
|
// lParam will have this state when receiving insert,end,down,etc presses from numpad
|
|
|
|
if(!(((HIWORD(lParam) >> 8) & 0xFF) & 1)) {
|
2012-02-04 03:11:18 +01:00
|
|
|
// retranslate numpad keys
|
|
|
|
switch(wParam) {
|
|
|
|
case VK_INSERT:
|
2012-02-04 03:43:43 +01:00
|
|
|
return Fw::KeyNumpad0;
|
2012-02-04 03:11:18 +01:00
|
|
|
case VK_END:
|
2012-02-04 03:43:43 +01:00
|
|
|
return Fw::KeyNumpad1;
|
2012-02-04 03:11:18 +01:00
|
|
|
case VK_DOWN:
|
2012-02-04 03:43:43 +01:00
|
|
|
return Fw::KeyNumpad2;
|
2012-02-04 03:11:18 +01:00
|
|
|
case VK_NEXT:
|
2012-02-04 03:43:43 +01:00
|
|
|
return Fw::KeyNumpad3;
|
2012-02-04 03:11:18 +01:00
|
|
|
case VK_LEFT:
|
2012-02-04 03:43:43 +01:00
|
|
|
return Fw::KeyNumpad4;
|
2012-02-04 03:11:18 +01:00
|
|
|
case VK_CLEAR:
|
2012-02-04 03:43:43 +01:00
|
|
|
return Fw::KeyNumpad5;
|
2012-02-04 03:11:18 +01:00
|
|
|
case VK_RIGHT:
|
2012-02-04 03:43:43 +01:00
|
|
|
return Fw::KeyNumpad6;
|
2012-02-04 03:11:18 +01:00
|
|
|
case VK_HOME:
|
2012-02-04 03:43:43 +01:00
|
|
|
return Fw::KeyNumpad7;
|
2012-02-04 03:11:18 +01:00
|
|
|
case VK_UP:
|
2012-02-04 03:43:43 +01:00
|
|
|
return Fw::KeyNumpad8;
|
2012-02-04 03:11:18 +01:00
|
|
|
case VK_PRIOR:
|
2012-02-04 03:43:43 +01:00
|
|
|
return Fw::KeyNumpad9;
|
2012-02-04 03:11:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-05 00:35:56 +02:00
|
|
|
Fw::Key key = Fw::KeyUnknown;
|
2012-02-04 03:43:43 +01:00
|
|
|
if(m_keyMap.find(wParam) != m_keyMap.end())
|
2012-04-05 00:35:56 +02:00
|
|
|
key = m_keyMap[wParam];
|
2012-02-04 03:43:43 +01:00
|
|
|
|
2012-04-05 00:35:56 +02:00
|
|
|
// actually ignore alt/ctrl/shift keys, they is states are already stored in m_inputEvent.keyboardModifiers
|
|
|
|
if(key == Fw::KeyAlt || key == Fw::KeyCtrl || key == Fw::KeyShift)
|
|
|
|
key = Fw::KeyUnknown;
|
|
|
|
|
|
|
|
return key;
|
2012-02-04 03:11:18 +01:00
|
|
|
}
|
|
|
|
|
2012-04-05 00:35:56 +02:00
|
|
|
#define IsKeyDown(a) (GetKeyState(a) & 0x80)
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
2011-08-30 00:27:22 +02:00
|
|
|
{
|
2012-04-05 00:35:56 +02:00
|
|
|
m_inputEvent.keyboardModifiers = 0;
|
|
|
|
if(IsKeyDown(VK_CONTROL))
|
|
|
|
m_inputEvent.keyboardModifiers |= Fw::KeyboardCtrlModifier;
|
|
|
|
if(IsKeyDown(VK_SHIFT))
|
|
|
|
m_inputEvent.keyboardModifiers |= Fw::KeyboardShiftModifier;
|
|
|
|
if(IsKeyDown(VK_MENU))
|
|
|
|
m_inputEvent.keyboardModifiers |= Fw::KeyboardAltModifier;
|
|
|
|
|
2011-08-30 00:27:22 +02:00
|
|
|
switch(uMsg)
|
|
|
|
{
|
2012-01-20 03:48:38 +01:00
|
|
|
case WM_SETCURSOR: {
|
|
|
|
if(m_cursor)
|
|
|
|
SetCursor(m_cursor);
|
|
|
|
else
|
2012-04-24 14:06:01 +02:00
|
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
2012-01-20 03:48:38 +01:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_ACTIVATE: {
|
|
|
|
m_focused = !(wParam == WA_INACTIVE);
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_CHAR: {
|
2011-08-30 00:27:22 +02:00
|
|
|
if(wParam >= 32 && wParam <= 255) {
|
2012-01-17 07:24:58 +01:00
|
|
|
m_inputEvent.reset(Fw::KeyTextInputEvent);
|
2011-12-29 19:18:12 +01:00
|
|
|
m_inputEvent.keyText = wParam;
|
2012-01-19 05:12:53 +01:00
|
|
|
if(m_onInputEvent)
|
|
|
|
m_onInputEvent(m_inputEvent);
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_CLOSE: {
|
|
|
|
m_onClose();
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2012-01-17 07:24:58 +01:00
|
|
|
case WM_KEYDOWN: {
|
2012-02-04 03:11:18 +01:00
|
|
|
processKeyDown(retranslateVirtualKey(wParam, lParam));
|
2012-01-17 07:24:58 +01:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_KEYUP: {
|
2012-02-04 03:11:18 +01:00
|
|
|
processKeyUp(retranslateVirtualKey(wParam, lParam));
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2012-04-24 14:06:01 +02:00
|
|
|
case WM_SYSKEYUP:
|
|
|
|
case WM_SYSKEYDOWN: {
|
|
|
|
// F10 is the shortcut key to enter a windows menu, this is a workaround to get F10 working
|
|
|
|
if(wParam != VK_F10)
|
|
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
|
|
else {
|
|
|
|
if(uMsg == WM_SYSKEYUP)
|
|
|
|
processKeyUp(retranslateVirtualKey(wParam, lParam));
|
|
|
|
else
|
|
|
|
processKeyDown(retranslateVirtualKey(wParam, lParam));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_LBUTTONDOWN: {
|
2012-03-27 23:33:58 +02:00
|
|
|
SetCapture(m_window);
|
2012-01-17 07:24:58 +01:00
|
|
|
m_inputEvent.reset(Fw::MousePressInputEvent);
|
2011-12-29 19:18:12 +01:00
|
|
|
m_inputEvent.mouseButton = Fw::MouseLeftButton;
|
2012-03-29 15:45:40 +02:00
|
|
|
m_mouseButtonStates[Fw::MouseLeftButton] = true;
|
2012-01-19 05:12:53 +01:00
|
|
|
if(m_onInputEvent)
|
|
|
|
m_onInputEvent(m_inputEvent);
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_LBUTTONUP: {
|
2012-03-27 23:33:58 +02:00
|
|
|
SetCapture(NULL);
|
2012-01-17 07:24:58 +01:00
|
|
|
m_inputEvent.reset(Fw::MouseReleaseInputEvent);
|
2011-12-29 19:18:12 +01:00
|
|
|
m_inputEvent.mouseButton = Fw::MouseLeftButton;
|
2012-03-29 15:45:40 +02:00
|
|
|
m_mouseButtonStates[Fw::MouseLeftButton] = false;
|
2012-01-19 05:12:53 +01:00
|
|
|
if(m_onInputEvent)
|
|
|
|
m_onInputEvent(m_inputEvent);
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_MBUTTONDOWN: {
|
2012-03-27 23:33:58 +02:00
|
|
|
SetCapture(m_window);
|
2012-01-17 07:24:58 +01:00
|
|
|
m_inputEvent.reset(Fw::MousePressInputEvent);
|
2011-12-29 19:18:12 +01:00
|
|
|
m_inputEvent.mouseButton = Fw::MouseMidButton;
|
2012-03-29 15:45:40 +02:00
|
|
|
m_mouseButtonStates[Fw::MouseMidButton] = true;
|
2012-01-19 05:12:53 +01:00
|
|
|
if(m_onInputEvent)
|
|
|
|
m_onInputEvent(m_inputEvent);
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_MBUTTONUP: {
|
2012-03-27 23:33:58 +02:00
|
|
|
SetCapture(NULL);
|
2012-01-17 07:24:58 +01:00
|
|
|
m_inputEvent.reset(Fw::MouseReleaseInputEvent);
|
2011-12-29 19:18:12 +01:00
|
|
|
m_inputEvent.mouseButton = Fw::MouseMidButton;
|
2012-03-29 15:45:40 +02:00
|
|
|
m_mouseButtonStates[Fw::MouseMidButton] = false;
|
2012-01-19 05:12:53 +01:00
|
|
|
if(m_onInputEvent)
|
|
|
|
m_onInputEvent(m_inputEvent);
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_RBUTTONDOWN: {
|
2012-03-27 23:33:58 +02:00
|
|
|
SetCapture(m_window);
|
2012-01-17 07:24:58 +01:00
|
|
|
m_inputEvent.reset(Fw::MousePressInputEvent);
|
2011-12-29 19:18:12 +01:00
|
|
|
m_inputEvent.mouseButton = Fw::MouseRightButton;
|
2012-03-29 15:45:40 +02:00
|
|
|
m_mouseButtonStates[Fw::MouseRightButton] = true;
|
2012-01-19 05:12:53 +01:00
|
|
|
if(m_onInputEvent)
|
|
|
|
m_onInputEvent(m_inputEvent);
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_RBUTTONUP: {
|
2012-03-27 23:33:58 +02:00
|
|
|
SetCapture(NULL);
|
2012-01-17 07:24:58 +01:00
|
|
|
m_inputEvent.reset(Fw::MouseReleaseInputEvent);
|
2011-12-29 19:18:12 +01:00
|
|
|
m_inputEvent.mouseButton = Fw::MouseRightButton;
|
2012-03-29 15:45:40 +02:00
|
|
|
m_mouseButtonStates[Fw::MouseRightButton] = false;
|
2012-01-19 05:12:53 +01:00
|
|
|
if(m_onInputEvent)
|
|
|
|
m_onInputEvent(m_inputEvent);
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_MOUSEMOVE: {
|
2012-01-17 07:24:58 +01:00
|
|
|
m_inputEvent.reset(Fw::MouseMoveInputEvent);
|
2012-03-27 23:33:58 +02:00
|
|
|
|
2011-08-30 00:27:22 +02:00
|
|
|
Point newMousePos(LOWORD(lParam), HIWORD(lParam));
|
2012-03-27 23:33:58 +02:00
|
|
|
if(newMousePos.x >= 32767)
|
|
|
|
newMousePos.x = 0;
|
|
|
|
else
|
|
|
|
newMousePos.x = std::min(newMousePos.x, m_size.width());
|
|
|
|
|
|
|
|
if(newMousePos.y >= 32767)
|
|
|
|
newMousePos.y = 0;
|
|
|
|
else
|
|
|
|
newMousePos.y = std::min(newMousePos.y, m_size.height());
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos;
|
|
|
|
m_inputEvent.mousePos = newMousePos;
|
2012-01-19 05:12:53 +01:00
|
|
|
if(m_onInputEvent)
|
|
|
|
m_onInputEvent(m_inputEvent);
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_MOUSEWHEEL: {
|
2012-03-28 20:10:59 +02:00
|
|
|
m_inputEvent.reset(Fw::MouseWheelInputEvent);
|
2011-12-29 19:18:12 +01:00
|
|
|
m_inputEvent.mouseButton = Fw::MouseMidButton;
|
2012-03-28 20:10:59 +02:00
|
|
|
m_inputEvent.wheelDirection = ((short)HIWORD(wParam)) > 0 ? Fw::MouseWheelUp : Fw::MouseWheelDown;
|
2012-01-19 05:12:53 +01:00
|
|
|
if(m_onInputEvent)
|
|
|
|
m_onInputEvent(m_inputEvent);
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_MOVE: {
|
2012-02-04 01:43:28 +01:00
|
|
|
m_position.x = (short)LOWORD(lParam);
|
|
|
|
m_position.y = (short)HIWORD(lParam);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_GETMINMAXINFO: {
|
|
|
|
LPMINMAXINFO pMMI = (LPMINMAXINFO)lParam;
|
|
|
|
pMMI->ptMinTrackSize.x = m_minimumSize.width();
|
|
|
|
pMMI->ptMinTrackSize.y = m_minimumSize.height();
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
case WM_SIZE: {
|
|
|
|
switch(wParam) {
|
|
|
|
case SIZE_MAXIMIZED:
|
|
|
|
m_maximized = true;
|
2012-04-13 21:54:08 +02:00
|
|
|
m_visible = true;
|
2011-12-29 19:18:12 +01:00
|
|
|
break;
|
|
|
|
case SIZE_RESTORED:
|
|
|
|
m_maximized = false;
|
2012-04-13 21:54:08 +02:00
|
|
|
m_visible = true;
|
|
|
|
break;
|
|
|
|
case SIZE_MINIMIZED:
|
|
|
|
m_visible = false;
|
2011-12-29 19:18:12 +01:00
|
|
|
break;
|
2011-08-30 00:27:22 +02:00
|
|
|
}
|
|
|
|
|
2012-04-13 21:54:08 +02:00
|
|
|
Size size;
|
|
|
|
size.setWidth(std::max(std::min((int)LOWORD(lParam), 7680), m_minimumSize.width()));
|
|
|
|
size.setHeight(std::max(std::min((int)HIWORD(lParam), 4320), m_minimumSize.height()));
|
2012-01-07 00:26:29 +01:00
|
|
|
|
2012-04-13 21:54:08 +02:00
|
|
|
if(m_visible && m_size != size) {
|
|
|
|
m_size = size;
|
2012-03-27 23:33:58 +02:00
|
|
|
m_onResize(m_size);
|
|
|
|
}
|
2012-04-13 21:54:08 +02:00
|
|
|
|
2011-08-30 00:27:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
default:
|
2011-08-30 00:27:22 +02:00
|
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
|
2011-08-30 00:27:22 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2011-11-17 03:31:06 +01:00
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
void WIN32Window::swapBuffers()
|
|
|
|
{
|
2012-06-11 01:48:53 +02:00
|
|
|
#ifdef OPENGL_ES
|
|
|
|
eglSwapBuffers(m_eglDisplay, m_eglSurface);
|
|
|
|
#else
|
2011-12-29 19:18:12 +01:00
|
|
|
SwapBuffers(m_deviceContext);
|
2012-06-11 01:48:53 +02:00
|
|
|
#endif
|
2011-12-29 19:18:12 +01:00
|
|
|
}
|
|
|
|
|
2012-01-13 02:06:29 +01:00
|
|
|
void WIN32Window::restoreMouseCursor()
|
|
|
|
{
|
2012-01-20 03:48:38 +01:00
|
|
|
if(m_cursor) {
|
|
|
|
DestroyCursor(m_cursor);
|
|
|
|
m_cursor = NULL;
|
|
|
|
SetCursor(m_defaultCursor);
|
|
|
|
ShowCursor(true);
|
|
|
|
}
|
2012-01-13 02:06:29 +01:00
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
void WIN32Window::showMouse()
|
|
|
|
{
|
|
|
|
ShowCursor(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void WIN32Window::hideMouse()
|
|
|
|
{
|
|
|
|
ShowCursor(false);
|
|
|
|
}
|
|
|
|
|
2012-01-12 02:12:25 +01:00
|
|
|
void WIN32Window::displayFatalError(const std::string& message)
|
|
|
|
{
|
|
|
|
MessageBoxA(m_window, message.c_str(), "FATAL ERROR", MB_OK | MB_ICONERROR);
|
|
|
|
}
|
|
|
|
|
2012-01-20 03:48:38 +01:00
|
|
|
void WIN32Window::setMouseCursor(const std::string& file, const Point& hotSpot)
|
2012-01-12 02:12:25 +01:00
|
|
|
{
|
2012-01-20 03:48:38 +01:00
|
|
|
std::stringstream fin;
|
|
|
|
g_resources.loadFile(file, fin);
|
|
|
|
|
|
|
|
apng_data apng;
|
|
|
|
if(load_apng(fin, &apng) != 0) {
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.traceError(stdext::format("unable to load png file %s", file));
|
2012-01-20 03:48:38 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(apng.bpp != 4) {
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.error("the cursor png must have 4 channels");
|
2012-01-20 03:48:38 +01:00
|
|
|
free_apng(&apng);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(apng.width != 32|| apng.height != 32) {
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.error("the cursor png must have 32x32 dimension");
|
2012-01-20 03:48:38 +01:00
|
|
|
free_apng(&apng);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m_cursor != NULL)
|
|
|
|
DestroyCursor(m_cursor);
|
|
|
|
|
|
|
|
int width = apng.width;
|
|
|
|
int height = apng.height;
|
|
|
|
int numbits = width * height;
|
|
|
|
int numbytes = (width * height)/8;
|
|
|
|
|
|
|
|
std::vector<uchar> andMask(numbytes, 0);
|
|
|
|
std::vector<uchar> xorMask(numbytes, 0);
|
|
|
|
|
|
|
|
for(int i=0;i<numbits;++i) {
|
2012-05-28 15:06:26 +02:00
|
|
|
uint32 rgba = stdext::readLE32(apng.pdata + i*4);
|
2012-04-05 14:18:25 +02:00
|
|
|
if(rgba == 0xffffffff) { //white
|
2012-01-20 03:48:38 +01:00
|
|
|
HSB_BIT_SET(xorMask, i);
|
2012-04-05 14:18:25 +02:00
|
|
|
} else if(rgba == 0x00000000) { //alpha
|
2012-01-20 03:48:38 +01:00
|
|
|
HSB_BIT_SET(andMask, i);
|
2012-04-05 14:18:25 +02:00
|
|
|
} // otherwise 0xff000000 => black
|
2012-01-20 03:48:38 +01:00
|
|
|
}
|
|
|
|
free_apng(&apng);
|
2012-01-12 02:12:25 +01:00
|
|
|
|
2012-01-20 03:48:38 +01:00
|
|
|
m_cursor = CreateCursor(m_instance, hotSpot.x, hotSpot.y, width, height, &andMask[0], &xorMask[0]);
|
|
|
|
SetCursor(m_cursor);
|
2012-01-12 02:12:25 +01:00
|
|
|
}
|
|
|
|
|
2011-12-29 19:18:12 +01:00
|
|
|
void WIN32Window::setTitle(const std::string& title)
|
|
|
|
{
|
|
|
|
SetWindowTextA(m_window, title.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
void WIN32Window::setMinimumSize(const Size& minimumSize)
|
2011-11-17 03:31:06 +01:00
|
|
|
{
|
2012-01-07 00:26:29 +01:00
|
|
|
m_minimumSize = minimumSize;
|
2011-12-29 19:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void WIN32Window::setFullscreen(bool fullscreen)
|
|
|
|
{
|
2012-01-07 00:26:29 +01:00
|
|
|
if(m_fullscreen == fullscreen)
|
|
|
|
return;
|
|
|
|
|
|
|
|
DWORD dwStyle = GetWindowLong(m_window, GWL_STYLE);
|
2012-02-20 03:27:08 +01:00
|
|
|
static WINDOWPLACEMENT wpPrev;
|
|
|
|
wpPrev.length = sizeof(wpPrev);
|
|
|
|
|
2012-01-07 00:26:29 +01:00
|
|
|
if(fullscreen) {
|
|
|
|
GetWindowPlacement(m_window, &wpPrev);
|
|
|
|
SetWindowLong(m_window, GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW);
|
|
|
|
SetWindowPos(m_window, HWND_TOP, 0, 0, getDisplayWidth(), getDisplayHeight(),
|
|
|
|
SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
|
|
|
|
} else {
|
|
|
|
SetWindowLong(m_window, GWL_STYLE, dwStyle | WS_OVERLAPPEDWINDOW);
|
|
|
|
SetWindowPlacement(m_window, &wpPrev);
|
|
|
|
SetWindowPos(m_window, NULL, 0, 0, 0, 0,
|
|
|
|
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_fullscreen = fullscreen;
|
2011-12-29 19:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void WIN32Window::setVerticalSync(bool enable)
|
|
|
|
{
|
2012-06-10 20:52:08 +02:00
|
|
|
#ifdef OPENGL_ES
|
2012-06-11 01:48:53 +02:00
|
|
|
eglSwapInterval(m_eglDisplay, enable ? 1 : 0);
|
2012-06-10 20:52:08 +02:00
|
|
|
#else
|
2012-01-18 00:07:22 +01:00
|
|
|
if(!isExtensionSupported("WGL_EXT_swap_control"))
|
|
|
|
return;
|
2011-12-29 19:18:12 +01:00
|
|
|
|
2012-01-18 00:07:22 +01:00
|
|
|
typedef BOOL (WINAPI * wglSwapIntervalProc)(int);
|
|
|
|
wglSwapIntervalProc wglSwapInterval = (wglSwapIntervalProc)getExtensionProcAddress("wglSwapIntervalEXT");
|
|
|
|
if(!wglSwapInterval)
|
|
|
|
return;
|
2011-12-29 19:18:12 +01:00
|
|
|
|
2012-01-18 00:07:22 +01:00
|
|
|
wglSwapInterval(enable ? 1 : 0);
|
2012-06-10 20:52:08 +02:00
|
|
|
#endif
|
2011-12-29 19:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void WIN32Window::setIcon(const std::string& pngIcon)
|
|
|
|
{
|
|
|
|
apng_data apng;
|
|
|
|
std::stringstream fin;
|
|
|
|
g_resources.loadFile(pngIcon, fin);
|
|
|
|
if(load_apng(fin, &apng) == 0) {
|
|
|
|
if(apng.bpp != 4) {
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.error("could not set app icon, icon image must have 4 channels");
|
2011-12-29 19:18:12 +01:00
|
|
|
free_apng(&apng);
|
|
|
|
}
|
|
|
|
|
|
|
|
int n = apng.width * apng.height;
|
|
|
|
std::vector<uint32> iconData(n);
|
|
|
|
for(int i=0; i < n;++i) {
|
|
|
|
uint8 *pixel = (uint8*)&iconData[i];
|
|
|
|
pixel[2] = *(apng.pdata + (i * 4) + 0);
|
|
|
|
pixel[1] = *(apng.pdata + (i * 4) + 1);
|
|
|
|
pixel[0] = *(apng.pdata + (i * 4) + 2);
|
|
|
|
pixel[3] = *(apng.pdata + (i * 4) + 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
HBITMAP hbmColor = CreateBitmap(apng.width, apng.height, 1, 32, &iconData[0]);
|
|
|
|
HBITMAP hbmMask = CreateCompatibleBitmap(GetDC(NULL), apng.width, apng.height);
|
|
|
|
|
|
|
|
ICONINFO ii;
|
|
|
|
ii.fIcon = TRUE;
|
|
|
|
ii.hbmColor = hbmColor;
|
|
|
|
ii.hbmMask = hbmMask;
|
|
|
|
ii.xHotspot = 0;
|
|
|
|
ii.yHotspot = 0;
|
|
|
|
|
|
|
|
HICON icon = CreateIconIndirect(&ii);
|
|
|
|
DeleteObject(hbmMask);
|
|
|
|
DeleteObject(hbmColor);
|
|
|
|
|
|
|
|
SendMessage(m_window, WM_SETICON, ICON_SMALL, (LPARAM)icon);
|
|
|
|
SendMessage(m_window, WM_SETICON, ICON_BIG, (LPARAM)icon);
|
|
|
|
|
|
|
|
free_apng(&apng);
|
|
|
|
} else
|
2012-06-01 22:39:23 +02:00
|
|
|
g_logger.error("could not load app icon");
|
2011-12-29 19:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void WIN32Window::setClipboardText(const std::string& text)
|
|
|
|
{
|
2012-01-07 00:26:29 +01:00
|
|
|
if(!OpenClipboard(m_window))
|
|
|
|
return;
|
|
|
|
|
|
|
|
HGLOBAL hglb = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(TCHAR));
|
|
|
|
if(!hglb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
LPTSTR lptstr = (LPTSTR)GlobalLock(hglb);
|
|
|
|
memcpy(lptstr, &text[0], text.length() * sizeof(TCHAR));
|
|
|
|
lptstr[text.length()] = (TCHAR)0;
|
|
|
|
GlobalUnlock(hglb);
|
|
|
|
|
|
|
|
EmptyClipboard();
|
|
|
|
SetClipboardData(CF_TEXT, hglb);
|
|
|
|
CloseClipboard();
|
2011-12-29 19:18:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Size WIN32Window::getDisplaySize()
|
|
|
|
{
|
|
|
|
return Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string WIN32Window::getClipboardText()
|
|
|
|
{
|
|
|
|
std::string text;
|
2012-01-07 00:26:29 +01:00
|
|
|
|
|
|
|
if(!OpenClipboard(m_window))
|
|
|
|
return text;
|
|
|
|
|
|
|
|
HGLOBAL hglb = GetClipboardData(CF_TEXT);
|
|
|
|
if(hglb) {
|
|
|
|
LPTSTR lptstr = (LPTSTR)GlobalLock(hglb);
|
|
|
|
if(lptstr) {
|
2012-05-28 15:06:26 +02:00
|
|
|
text = stdext::utf8StringToLatin1((uchar*)lptstr);
|
2012-01-07 00:26:29 +01:00
|
|
|
GlobalUnlock(hglb);
|
|
|
|
}
|
2011-12-29 19:18:12 +01:00
|
|
|
}
|
2012-01-07 00:26:29 +01:00
|
|
|
CloseClipboard();
|
2011-12-29 19:18:12 +01:00
|
|
|
return text;
|
2011-11-17 03:31:06 +01:00
|
|
|
}
|
|
|
|
|
2011-12-30 05:50:19 +01:00
|
|
|
std::string WIN32Window::getPlatformType()
|
|
|
|
{
|
2012-06-10 20:52:08 +02:00
|
|
|
#ifdef OPENGL_ES
|
2011-12-30 05:50:19 +01:00
|
|
|
return "WIN32-WGL";
|
2012-06-10 20:52:08 +02:00
|
|
|
#else
|
|
|
|
return "WIN32-EGL";
|
|
|
|
#endif
|
2011-12-30 05:50:19 +01:00
|
|
|
}
|
2012-06-12 18:50:43 +02:00
|
|
|
|
|
|
|
#endif
|