|
|
@@ -18,6 +18,7 @@
|
|
|
|
|
|
#include <tinystl/allocator.h>
|
|
|
#include <tinystl/string.h>
|
|
|
+#include <tinystl/vector.h>
|
|
|
|
|
|
#include <windows.h>
|
|
|
#include <windowsx.h>
|
|
|
@@ -33,6 +34,16 @@
|
|
|
|
|
|
namespace entry
|
|
|
{
|
|
|
+ typedef tinystl::vector<WCHAR> WSTRING;
|
|
|
+
|
|
|
+ inline WSTRING UTF8ToUTF16(const char *utf8_str)
|
|
|
+ {
|
|
|
+ int len = MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, NULL, 0);
|
|
|
+ WSTRING utf16(len);
|
|
|
+ MultiByteToWideChar(CP_UTF8, 0, utf8_str, -1, utf16.data(), len);
|
|
|
+ return utf16;
|
|
|
+ }
|
|
|
+
|
|
|
///
|
|
|
inline void winSetHwnd(::HWND _window)
|
|
|
{
|
|
|
@@ -359,6 +370,7 @@ namespace entry
|
|
|
, m_init(false)
|
|
|
, m_exit(false)
|
|
|
{
|
|
|
+ m_surrogate = 0;
|
|
|
bx::memSet(s_translateKey, 0, sizeof(s_translateKey) );
|
|
|
s_translateKey[VK_ESCAPE] = Key::Esc;
|
|
|
s_translateKey[VK_RETURN] = Key::Return;
|
|
|
@@ -450,29 +462,29 @@ namespace entry
|
|
|
|
|
|
int32_t run(int _argc, const char* const* _argv)
|
|
|
{
|
|
|
- SetDllDirectoryA(".");
|
|
|
+ SetDllDirectoryW(L".");
|
|
|
|
|
|
s_xinput.init();
|
|
|
|
|
|
- HINSTANCE instance = (HINSTANCE)GetModuleHandle(NULL);
|
|
|
+ HINSTANCE instance = (HINSTANCE)GetModuleHandleW(NULL);
|
|
|
|
|
|
- WNDCLASSEXA wnd;
|
|
|
+ WNDCLASSEXW wnd;
|
|
|
bx::memSet(&wnd, 0, sizeof(wnd) );
|
|
|
wnd.cbSize = sizeof(wnd);
|
|
|
wnd.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
wnd.lpfnWndProc = wndProc;
|
|
|
wnd.hInstance = instance;
|
|
|
- wnd.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
|
|
- wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
- wnd.lpszClassName = "bgfx";
|
|
|
- wnd.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
|
|
- RegisterClassExA(&wnd);
|
|
|
+ wnd.hIcon = LoadIconW(NULL, (LPWSTR)IDI_APPLICATION);
|
|
|
+ wnd.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
|
|
|
+ wnd.lpszClassName = L"bgfx";
|
|
|
+ wnd.hIconSm = LoadIconW(NULL, (LPWSTR)IDI_APPLICATION);
|
|
|
+ RegisterClassExW(&wnd);
|
|
|
|
|
|
m_windowAlloc.alloc();
|
|
|
- m_hwnd[0] = CreateWindowExA(
|
|
|
+ m_hwnd[0] = CreateWindowExW(
|
|
|
WS_EX_ACCEPTFILES
|
|
|
- , "bgfx"
|
|
|
- , "BGFX"
|
|
|
+ , L"bgfx"
|
|
|
+ , L"BGFX"
|
|
|
, WS_OVERLAPPEDWINDOW|WS_VISIBLE
|
|
|
, 0
|
|
|
, 0
|
|
|
@@ -521,10 +533,10 @@ namespace entry
|
|
|
s_xinput.update(m_eventQueue);
|
|
|
WaitForInputIdle(GetCurrentProcess(), 16);
|
|
|
|
|
|
- while (0 != PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) )
|
|
|
+ while (0 != PeekMessageW(&msg, NULL, 0U, 0U, PM_REMOVE) )
|
|
|
{
|
|
|
TranslateMessage(&msg);
|
|
|
- DispatchMessage(&msg);
|
|
|
+ DispatchMessageW(&msg);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -548,8 +560,8 @@ namespace entry
|
|
|
case WM_USER_WINDOW_CREATE:
|
|
|
{
|
|
|
Msg* msg = (Msg*)_lparam;
|
|
|
- HWND hwnd = CreateWindowA("bgfx"
|
|
|
- , msg->m_title.c_str()
|
|
|
+ HWND hwnd = CreateWindowW(L"bgfx"
|
|
|
+ , UTF8ToUTF16(msg->m_title.c_str()).data()
|
|
|
, WS_OVERLAPPEDWINDOW|WS_VISIBLE
|
|
|
, msg->m_x
|
|
|
, msg->m_y
|
|
|
@@ -557,7 +569,7 @@ namespace entry
|
|
|
, msg->m_height
|
|
|
, NULL
|
|
|
, NULL
|
|
|
- , (HINSTANCE)GetModuleHandle(NULL)
|
|
|
+ , (HINSTANCE)GetModuleHandleW(NULL)
|
|
|
, 0
|
|
|
);
|
|
|
clear(hwnd);
|
|
|
@@ -590,7 +602,7 @@ namespace entry
|
|
|
case WM_USER_WINDOW_SET_TITLE:
|
|
|
{
|
|
|
Msg* msg = (Msg*)_lparam;
|
|
|
- SetWindowTextA(m_hwnd[_wparam], msg->m_title.c_str() );
|
|
|
+ SetWindowTextW(m_hwnd[_wparam], UTF8ToUTF16(msg->m_title.c_str()).data() );
|
|
|
delete msg;
|
|
|
}
|
|
|
break;
|
|
|
@@ -743,7 +755,7 @@ namespace entry
|
|
|
HWND parent = GetWindow(_hwnd, GW_OWNER);
|
|
|
if (NULL != parent)
|
|
|
{
|
|
|
- PostMessage(parent, _id, _wparam, _lparam);
|
|
|
+ PostMessageW(parent, _id, _wparam, _lparam);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -842,20 +854,36 @@ namespace entry
|
|
|
|
|
|
case WM_CHAR:
|
|
|
{
|
|
|
+ WCHAR utf16[2] = { (WCHAR)_wparam };
|
|
|
uint8_t utf8[4] = {};
|
|
|
- uint8_t len = (uint8_t)WideCharToMultiByte(CP_UTF8
|
|
|
- , 0
|
|
|
- , (LPCWSTR)&_wparam
|
|
|
- , 1
|
|
|
- , (LPSTR)utf8
|
|
|
- , BX_COUNTOF(utf8)
|
|
|
- , NULL
|
|
|
- , NULL
|
|
|
- );
|
|
|
- if (0 != len)
|
|
|
- {
|
|
|
- WindowHandle handle = findHandle(_hwnd);
|
|
|
- m_eventQueue.postCharEvent(handle, len, utf8);
|
|
|
+
|
|
|
+ if (utf16[0] >= 0xD800 && utf16[0] <= 0xDBFF) {
|
|
|
+ m_surrogate = utf16[0];
|
|
|
+ } else {
|
|
|
+ int utf16_len;
|
|
|
+ if (utf16[0] >= 0xDC00 && utf16[0] <= 0xDFFF) {
|
|
|
+ utf16[1] = utf16[0];
|
|
|
+ utf16[0] = m_surrogate;
|
|
|
+ m_surrogate = 0;
|
|
|
+ utf16_len = 2;
|
|
|
+ } else {
|
|
|
+ utf16_len = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ uint8_t len = (uint8_t)WideCharToMultiByte(CP_UTF8
|
|
|
+ , 0
|
|
|
+ , utf16
|
|
|
+ , utf16_len
|
|
|
+ , (LPSTR)utf8
|
|
|
+ , BX_COUNTOF(utf8)
|
|
|
+ , NULL
|
|
|
+ , NULL
|
|
|
+ );
|
|
|
+ if (0 != len)
|
|
|
+ {
|
|
|
+ WindowHandle handle = findHandle(_hwnd);
|
|
|
+ m_eventQueue.postCharEvent(handle, len, utf8);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
@@ -864,8 +892,10 @@ namespace entry
|
|
|
{
|
|
|
HDROP drop = (HDROP)_wparam;
|
|
|
char tmp[bx::kMaxFilePath];
|
|
|
- uint32_t result = DragQueryFileA(drop, 0, tmp, sizeof(tmp) );
|
|
|
+ WCHAR utf16[bx::kMaxFilePath];
|
|
|
+ uint32_t result = DragQueryFileW(drop, 0, utf16, bx::kMaxFilePath);
|
|
|
BX_UNUSED(result);
|
|
|
+ WideCharToMultiByte(CP_UTF8, 0, utf16, -1, tmp, bx::kMaxFilePath, NULL, NULL);
|
|
|
WindowHandle handle = findHandle(_hwnd);
|
|
|
m_eventQueue.postDropFileEvent(handle, tmp);
|
|
|
}
|
|
|
@@ -876,7 +906,7 @@ namespace entry
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return DefWindowProc(_hwnd, _id, _wparam, _lparam);
|
|
|
+ return DefWindowProcW(_hwnd, _id, _wparam, _lparam);
|
|
|
}
|
|
|
|
|
|
WindowHandle findHandle(HWND _hwnd)
|
|
|
@@ -921,7 +951,7 @@ namespace entry
|
|
|
if (m_frame)
|
|
|
{
|
|
|
GetWindowRect(_hwnd, &m_rect);
|
|
|
- m_style = GetWindowLong(_hwnd, GWL_STYLE);
|
|
|
+ m_style = GetWindowLongW(_hwnd, GWL_STYLE);
|
|
|
}
|
|
|
|
|
|
if (_windowFrame)
|
|
|
@@ -934,13 +964,13 @@ namespace entry
|
|
|
HMONITOR monitor = MonitorFromWindow(_hwnd, MONITOR_DEFAULTTONEAREST);
|
|
|
MONITORINFO mi;
|
|
|
mi.cbSize = sizeof(mi);
|
|
|
- GetMonitorInfo(monitor, &mi);
|
|
|
+ GetMonitorInfoW(monitor, &mi);
|
|
|
newrect = mi.rcMonitor;
|
|
|
rect = mi.rcMonitor;
|
|
|
m_aspectRatio = float(newrect.right - newrect.left)/float(newrect.bottom - newrect.top);
|
|
|
}
|
|
|
|
|
|
- SetWindowLong(_hwnd, GWL_STYLE, style);
|
|
|
+ SetWindowLongW(_hwnd, GWL_STYLE, style);
|
|
|
uint32_t prewidth = newrect.right - newrect.left;
|
|
|
uint32_t preheight = newrect.bottom - newrect.top;
|
|
|
AdjustWindowRect(&newrect, style, FALSE);
|
|
|
@@ -1015,6 +1045,7 @@ namespace entry
|
|
|
static LRESULT CALLBACK wndProc(HWND _hwnd, UINT _id, WPARAM _wparam, LPARAM _lparam);
|
|
|
|
|
|
EventQueue m_eventQueue;
|
|
|
+ WCHAR m_surrogate;
|
|
|
bx::Mutex m_lock;
|
|
|
|
|
|
bx::HandleAllocT<ENTRY_CONFIG_MAX_WINDOWS> m_windowAlloc;
|
|
|
@@ -1078,7 +1109,7 @@ namespace entry
|
|
|
msg->m_height = _height;
|
|
|
msg->m_title = _title;
|
|
|
msg->m_flags = _flags;
|
|
|
- PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_CREATE, handle.idx, (LPARAM)msg);
|
|
|
+ PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_CREATE, handle.idx, (LPARAM)msg);
|
|
|
}
|
|
|
|
|
|
return handle;
|
|
|
@@ -1088,7 +1119,7 @@ namespace entry
|
|
|
{
|
|
|
if (UINT16_MAX != _handle.idx)
|
|
|
{
|
|
|
- PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_DESTROY, _handle.idx, 0);
|
|
|
+ PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_DESTROY, _handle.idx, 0);
|
|
|
|
|
|
bx::MutexScope scope(s_ctx.m_lock);
|
|
|
s_ctx.m_windowAlloc.free(_handle.idx);
|
|
|
@@ -1100,19 +1131,19 @@ namespace entry
|
|
|
Msg* msg = new Msg;
|
|
|
msg->m_x = _x;
|
|
|
msg->m_y = _y;
|
|
|
- PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_POS, _handle.idx, (LPARAM)msg);
|
|
|
+ PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_POS, _handle.idx, (LPARAM)msg);
|
|
|
}
|
|
|
|
|
|
void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height)
|
|
|
{
|
|
|
- PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_SIZE, _handle.idx, (_height<<16) | (_width&0xffff) );
|
|
|
+ PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_SIZE, _handle.idx, (_height<<16) | (_width&0xffff) );
|
|
|
}
|
|
|
|
|
|
void setWindowTitle(WindowHandle _handle, const char* _title)
|
|
|
{
|
|
|
Msg* msg = new Msg;
|
|
|
msg->m_title = _title;
|
|
|
- PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_TITLE, _handle.idx, (LPARAM)msg);
|
|
|
+ PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_TITLE, _handle.idx, (LPARAM)msg);
|
|
|
}
|
|
|
|
|
|
void setWindowFlags(WindowHandle _handle, uint32_t _flags, bool _enabled)
|
|
|
@@ -1120,24 +1151,24 @@ namespace entry
|
|
|
Msg* msg = new Msg;
|
|
|
msg->m_flags = _flags;
|
|
|
msg->m_flagsEnabled = _enabled;
|
|
|
- PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_FLAGS, _handle.idx, (LPARAM)msg);
|
|
|
+ PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_FLAGS, _handle.idx, (LPARAM)msg);
|
|
|
}
|
|
|
|
|
|
void toggleFullscreen(WindowHandle _handle)
|
|
|
{
|
|
|
- PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_TOGGLE_FRAME, _handle.idx, 0);
|
|
|
+ PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_TOGGLE_FRAME, _handle.idx, 0);
|
|
|
}
|
|
|
|
|
|
void setMouseLock(WindowHandle _handle, bool _lock)
|
|
|
{
|
|
|
- PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_MOUSE_LOCK, _handle.idx, _lock);
|
|
|
+ PostMessageW(s_ctx.m_hwnd[0], WM_USER_WINDOW_MOUSE_LOCK, _handle.idx, _lock);
|
|
|
}
|
|
|
|
|
|
int32_t MainThreadEntry::threadFunc(bx::Thread* /*_thread*/, void* _userData)
|
|
|
{
|
|
|
MainThreadEntry* self = (MainThreadEntry*)_userData;
|
|
|
int32_t result = main(self->m_argc, self->m_argv);
|
|
|
- PostMessage(s_ctx.m_hwnd[0], WM_QUIT, 0, 0);
|
|
|
+ PostMessageW(s_ctx.m_hwnd[0], WM_QUIT, 0, 0);
|
|
|
return result;
|
|
|
}
|
|
|
|