boo/lib/win/ApplicationWin32.cpp

642 lines
23 KiB
C++
Raw Normal View History

2015-11-03 04:19:41 +00:00
#include "Win32Common.hpp"
2015-08-31 03:40:58 +00:00
#include <shellapi.h>
2015-05-06 00:50:57 +00:00
#include <initguid.h>
#include <Usbiodef.h>
2016-01-27 19:26:45 +00:00
#include <winver.h>
2016-08-17 20:04:19 +00:00
#include <Dbt.h>
2015-05-06 00:50:57 +00:00
2016-12-11 01:50:26 +00:00
#if _WIN32_WINNT_WINBLUE
PFN_GetScaleFactorForMonitor MyGetScaleFactorForMonitor = nullptr;
#endif
2015-11-03 04:19:41 +00:00
#if _DEBUG
#define D3D11_CREATE_DEVICE_FLAGS D3D11_CREATE_DEVICE_DEBUG
#else
#define D3D11_CREATE_DEVICE_FLAGS 0
#endif
#include "boo/System.hpp"
2015-08-31 03:40:58 +00:00
#include "boo/IApplication.hpp"
#include "boo/inputdev/DeviceFinder.hpp"
#include "boo/graphicsdev/D3D.hpp"
2016-03-04 23:02:18 +00:00
#include "logvisor/logvisor.hpp"
2015-05-06 00:50:57 +00:00
2016-07-17 21:15:57 +00:00
#if BOO_HAS_VULKAN
2017-11-25 02:49:20 +00:00
#include "boo/graphicsdev/Vulkan.hpp"
2016-07-17 21:15:57 +00:00
#endif
DWORD g_mainThreadId = 0;
2015-11-05 00:00:29 +00:00
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
2015-11-06 03:20:58 +00:00
#if _WIN32_WINNT_WIN10
2015-11-05 00:00:29 +00:00
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignaturePROC = nullptr;
2015-11-06 03:20:58 +00:00
#endif
pD3DCompile D3DCompilePROC = nullptr;
pD3DCreateBlob D3DCreateBlobPROC = nullptr;
static bool FindBestD3DCompile()
{
HMODULE d3dCompilelib = LoadLibraryW(L"D3DCompiler_47.dll");
if (!d3dCompilelib)
{
d3dCompilelib = LoadLibraryW(L"D3DCompiler_46.dll");
if (!d3dCompilelib)
{
d3dCompilelib = LoadLibraryW(L"D3DCompiler_45.dll");
if (!d3dCompilelib)
{
d3dCompilelib = LoadLibraryW(L"D3DCompiler_44.dll");
if (!d3dCompilelib)
{
d3dCompilelib = LoadLibraryW(L"D3DCompiler_43.dll");
}
}
}
}
if (d3dCompilelib)
{
D3DCompilePROC = (pD3DCompile)GetProcAddress(d3dCompilelib, "D3DCompile");
D3DCreateBlobPROC = (pD3DCreateBlob)GetProcAddress(d3dCompilelib, "D3DCreateBlob");
return D3DCompilePROC != nullptr && D3DCreateBlobPROC != nullptr;
}
return false;
}
2015-11-05 00:00:29 +00:00
2015-05-06 00:50:57 +00:00
namespace boo
{
2016-03-04 23:02:18 +00:00
static logvisor::Module Log("boo::ApplicationWin32");
2015-12-01 00:33:14 +00:00
Win32Cursors WIN32_CURSORS;
2016-01-19 20:30:51 +00:00
std::shared_ptr<IWindow> _WindowWin32New(SystemStringView title, Boo3DAppContextWin32& d3dCtx);
2015-05-06 00:50:57 +00:00
2015-08-31 03:40:58 +00:00
class ApplicationWin32 final : public IApplication
2015-05-06 00:50:57 +00:00
{
2015-11-03 04:19:41 +00:00
IApplicationCallback& m_callback;
2015-08-31 03:40:58 +00:00
const SystemString m_uniqueName;
const SystemString m_friendlyName;
const SystemString m_pname;
const std::vector<SystemString> m_args;
2017-07-17 04:01:13 +00:00
std::unordered_map<HWND, std::weak_ptr<IWindow>> m_allWindows;
2015-05-13 22:21:13 +00:00
bool m_singleInstance;
2015-11-03 04:19:41 +00:00
Boo3DAppContextWin32 m_3dCtx;
2016-07-24 06:33:23 +00:00
#if BOO_HAS_VULKAN
2016-07-17 21:15:57 +00:00
PFN_vkGetInstanceProcAddr m_getVkProc = nullptr;
2016-07-24 06:33:23 +00:00
#endif
2015-11-03 04:19:41 +00:00
2015-05-06 00:50:57 +00:00
void _deletedWindow(IWindow* window)
{
2015-08-31 03:40:58 +00:00
m_allWindows.erase(HWND(window->getPlatformHandle()));
2015-05-06 00:50:57 +00:00
}
2016-01-19 20:30:51 +00:00
2015-05-06 00:50:57 +00:00
public:
2016-01-19 20:30:51 +00:00
2015-11-03 04:19:41 +00:00
ApplicationWin32(IApplicationCallback& callback,
2017-11-13 06:13:32 +00:00
SystemStringView uniqueName,
SystemStringView friendlyName,
SystemStringView pname,
2015-08-31 03:40:58 +00:00
const std::vector<SystemString>& args,
std::string_view gfxApi,
uint32_t samples,
uint32_t anisotropy,
2015-08-31 03:40:58 +00:00
bool singleInstance)
2015-05-06 00:50:57 +00:00
: m_callback(callback),
2015-08-31 03:40:58 +00:00
m_uniqueName(uniqueName),
2015-05-06 00:50:57 +00:00
m_friendlyName(friendlyName),
m_pname(pname),
2015-05-13 22:21:13 +00:00
m_args(args),
m_singleInstance(singleInstance)
2015-11-03 04:19:41 +00:00
{
m_3dCtx.m_ctx11.m_sampleCount = samples;
m_3dCtx.m_ctx11.m_anisotropy = anisotropy;
m_3dCtx.m_ctx12.m_sampleCount = samples;
m_3dCtx.m_ctx12.m_anisotropy = anisotropy;
m_3dCtx.m_ctxOgl.m_glCtx.m_sampleCount = samples;
m_3dCtx.m_ctxOgl.m_glCtx.m_anisotropy = anisotropy;
2018-01-10 06:25:51 +00:00
#if BOO_HAS_VULKAN
g_VulkanContext.m_sampleCountColor = samples;
g_VulkanContext.m_sampleCountDepth = samples;
g_VulkanContext.m_anisotropy = anisotropy;
2018-01-10 06:25:51 +00:00
#endif
2015-11-03 04:19:41 +00:00
HMODULE dxgilib = LoadLibraryW(L"dxgi.dll");
if (!dxgilib)
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Fatal, "unable to load dxgi.dll");
2015-11-03 04:19:41 +00:00
2015-11-07 05:15:50 +00:00
typedef HRESULT(WINAPI*CreateDXGIFactory1PROC)(REFIID riid, _COM_Outptr_ void **ppFactory);
CreateDXGIFactory1PROC MyCreateDXGIFactory1 = (CreateDXGIFactory1PROC)GetProcAddress(dxgilib, "CreateDXGIFactory1");
if (!MyCreateDXGIFactory1)
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Fatal, "unable to find CreateDXGIFactory1 in DXGI.dll\n");
2015-11-03 04:19:41 +00:00
2017-11-25 02:49:20 +00:00
bool yes12 = false;
bool noD3d = false;
2016-07-17 21:15:57 +00:00
#if BOO_HAS_VULKAN
bool useVulkan = false;
2016-07-17 21:15:57 +00:00
#endif
if (!gfxApi.empty())
{
#if BOO_HAS_VULKAN
if (!gfxApi.compare("D3D12"))
{
useVulkan = false;
yes12 = true;
}
if (!gfxApi.compare("Vulkan"))
{
noD3d = true;
useVulkan = true;
}
if (!gfxApi.compare("OpenGL"))
{
noD3d = true;
useVulkan = false;
}
#else
2018-01-10 06:25:51 +00:00
if (!gfxApi.compare("D3D12"))
yes12 = true;
2018-01-10 06:25:51 +00:00
if (!gfxApi.compare("OpenGL"))
noD3d = true;
#endif
}
for (const SystemString& arg : args)
{
2016-07-17 21:15:57 +00:00
#if BOO_HAS_VULKAN
2017-11-25 02:49:20 +00:00
if (!arg.compare(L"--d3d12"))
{
useVulkan = false;
yes12 = true;
noD3d = false;
}
if (!arg.compare(L"--d3d11"))
{
useVulkan = false;
yes12 = false;
noD3d = false;
2017-11-25 02:49:20 +00:00
}
if (!arg.compare(L"--vulkan"))
2017-11-25 02:49:20 +00:00
{
noD3d = true;
2017-11-25 02:49:20 +00:00
}
2016-07-17 21:15:57 +00:00
if (!arg.compare(L"--gl"))
{
noD3d = true;
useVulkan = false;
}
#else
2017-11-25 02:49:20 +00:00
if (!arg.compare(L"--d3d12"))
{
2017-11-25 02:49:20 +00:00
yes12 = true;
noD3d = false;
}
if (!arg.compare(L"--d3d11"))
{
yes12 = false;
noD3d = false;
}
if (!arg.compare(L"--gl"))
noD3d = true;
2016-07-17 21:15:57 +00:00
#endif
}
2015-11-06 03:20:58 +00:00
#if _WIN32_WINNT_WIN10
2017-11-25 02:49:20 +00:00
HMODULE d3d12lib = nullptr;
if (yes12 && !noD3d)
d3d12lib = LoadLibraryW(L"D3D12.dll");
if (d3d12lib)
2016-12-11 06:18:41 +00:00
{
2015-11-05 00:00:29 +00:00
#if _DEBUG
{
2016-01-19 20:30:51 +00:00
PFN_D3D12_GET_DEBUG_INTERFACE MyD3D12GetDebugInterface =
2015-11-05 00:00:29 +00:00
(PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(d3d12lib, "D3D12GetDebugInterface");
ComPtr<ID3D12Debug> debugController;
if (SUCCEEDED(MyD3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
{
debugController->EnableDebugLayer();
}
}
#endif
if (!FindBestD3DCompile())
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Fatal, "unable to find D3DCompile_[43-47].dll");
2016-01-19 20:30:51 +00:00
D3D12SerializeRootSignaturePROC =
2015-11-05 00:00:29 +00:00
(PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)GetProcAddress(d3d12lib, "D3D12SerializeRootSignature");
2016-01-19 20:30:51 +00:00
2015-11-04 00:27:32 +00:00
/* Create device */
2015-11-03 04:19:41 +00:00
PFN_D3D12_CREATE_DEVICE MyD3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)GetProcAddress(d3d12lib, "D3D12CreateDevice");
if (!MyD3D12CreateDevice)
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Fatal, "unable to find D3D12CreateDevice in D3D12.dll");
2015-11-04 00:27:32 +00:00
2016-12-11 06:18:41 +00:00
/* Obtain DXGI Factory */
HRESULT hr = MyCreateDXGIFactory1(__uuidof(IDXGIFactory2), &m_3dCtx.m_ctx12.m_dxFactory);
if (FAILED(hr))
Log.report(logvisor::Fatal, "unable to create DXGI factory");
/* Adapter */
ComPtr<IDXGIAdapter1> ppAdapter;
for (UINT adapterIndex = 0; ; ++adapterIndex)
{
ComPtr<IDXGIAdapter1> pAdapter;
if (DXGI_ERROR_NOT_FOUND == m_3dCtx.m_ctx12.m_dxFactory->EnumAdapters1(adapterIndex, &pAdapter))
break;
// Check to see if the adapter supports Direct3D 12, but don't create the
// actual device yet.
if (SUCCEEDED(MyD3D12CreateDevice(pAdapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
{
ppAdapter = std::move(pAdapter);
break;
}
}
2015-11-04 00:27:32 +00:00
/* Create device */
2016-12-11 06:18:41 +00:00
hr = ppAdapter ? MyD3D12CreateDevice(ppAdapter.Get(), D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), &m_3dCtx.m_ctx12.m_dev) : E_FAIL;
2016-06-27 22:54:02 +00:00
if (!FAILED(hr))
{
/* Establish loader objects */
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT,
__uuidof(ID3D12CommandAllocator), &m_3dCtx.m_ctx12.m_loadqalloc)))
Log.report(logvisor::Fatal, "unable to create loader allocator");
2015-11-05 00:00:29 +00:00
2016-06-27 22:54:02 +00:00
D3D12_COMMAND_QUEUE_DESC desc =
{
D3D12_COMMAND_LIST_TYPE_DIRECT,
D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
D3D12_COMMAND_QUEUE_FLAG_NONE
};
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateCommandQueue(&desc, __uuidof(ID3D12CommandQueue), &m_3dCtx.m_ctx12.m_loadq)))
Log.report(logvisor::Fatal, "unable to create loader queue");
2015-11-05 00:00:29 +00:00
2016-06-27 22:54:02 +00:00
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), &m_3dCtx.m_ctx12.m_loadfence)))
Log.report(logvisor::Fatal, "unable to create loader fence");
2015-11-05 00:00:29 +00:00
2016-06-27 22:54:02 +00:00
m_3dCtx.m_ctx12.m_loadfencehandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
2015-11-05 00:00:29 +00:00
2016-06-27 22:54:02 +00:00
if (FAILED(m_3dCtx.m_ctx12.m_dev->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_3dCtx.m_ctx12.m_loadqalloc.Get(),
nullptr, __uuidof(ID3D12GraphicsCommandList), &m_3dCtx.m_ctx12.m_loadlist)))
Log.report(logvisor::Fatal, "unable to create loader list");
2015-11-05 00:00:29 +00:00
2016-06-27 22:54:02 +00:00
Log.report(logvisor::Info, "initialized D3D12 renderer");
return;
}
else
{
/* Some Win10 client HW doesn't support D3D12 (despite being supposedly HW-agnostic) */
m_3dCtx.m_ctx12.m_dev.Reset();
2016-12-11 06:18:41 +00:00
m_3dCtx.m_ctx12.m_dxFactory.Reset();
2016-06-27 22:54:02 +00:00
}
2015-11-03 04:19:41 +00:00
}
#endif
2017-11-25 02:49:20 +00:00
HMODULE d3d11lib = nullptr;
if (!noD3d)
d3d11lib = LoadLibraryW(L"D3D11.dll");
if (d3d11lib)
2015-11-03 04:19:41 +00:00
{
if (!FindBestD3DCompile())
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Fatal, "unable to find D3DCompile_[43-47].dll");
2015-11-03 04:19:41 +00:00
/* Create device proc */
PFN_D3D11_CREATE_DEVICE MyD3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(d3d11lib, "D3D11CreateDevice");
if (!MyD3D11CreateDevice)
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Fatal, "unable to find D3D11CreateDevice in D3D11.dll");
2015-11-03 04:19:41 +00:00
/* Create device */
D3D_FEATURE_LEVEL level = D3D_FEATURE_LEVEL_11_0;
2015-11-03 04:19:41 +00:00
ComPtr<ID3D11Device> tempDev;
ComPtr<ID3D11DeviceContext> tempCtx;
2016-01-19 20:30:51 +00:00
if (FAILED(MyD3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_FLAGS, &level,
2015-11-03 04:19:41 +00:00
1, D3D11_SDK_VERSION, &tempDev, nullptr, &tempCtx)))
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Fatal, "unable to create D3D11 device");
2015-11-03 04:19:41 +00:00
2015-11-04 00:27:32 +00:00
ComPtr<IDXGIDevice2> device;
if (FAILED(tempDev.As<ID3D11Device1>(&m_3dCtx.m_ctx11.m_dev)) || !m_3dCtx.m_ctx11.m_dev ||
FAILED(tempCtx.As<ID3D11DeviceContext1>(&m_3dCtx.m_ctx11.m_devCtx)) || !m_3dCtx.m_ctx11.m_devCtx ||
FAILED(m_3dCtx.m_ctx11.m_dev.As<IDXGIDevice2>(&device)) || !device)
{
MessageBoxW(nullptr, L"Windows 7 users should install 'Platform Update for Windows 7':\n"
L"https://www.microsoft.com/en-us/download/details.aspx?id=36805",
L"IDXGIDevice2 interface error", MB_OK | MB_ICONERROR);
exit(1);
}
/* Obtain DXGI Factory */
2015-11-04 00:27:32 +00:00
ComPtr<IDXGIAdapter> adapter;
device->GetParent(__uuidof(IDXGIAdapter), &adapter);
adapter->GetParent(__uuidof(IDXGIFactory2), &m_3dCtx.m_ctx11.m_dxFactory);
2015-11-04 00:27:32 +00:00
m_3dCtx.m_ctx11.m_anisotropy = std::min(m_3dCtx.m_ctx11.m_anisotropy, uint32_t(16));
2015-11-06 03:20:58 +00:00
/* Build default sampler here */
2016-01-19 20:30:51 +00:00
CD3D11_SAMPLER_DESC sampDesc(D3D11_DEFAULT);
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.Filter = D3D11_FILTER_ANISOTROPIC;
sampDesc.MaxAnisotropy = m_3dCtx.m_ctx11.m_anisotropy;
2017-10-01 04:23:28 +00:00
m_3dCtx.m_ctx11.m_dev->CreateSamplerState(&sampDesc, &m_3dCtx.m_ctx11.m_ss[0]);
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER;
m_3dCtx.m_ctx11.m_dev->CreateSamplerState(&sampDesc, &m_3dCtx.m_ctx11.m_ss[1]);
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
m_3dCtx.m_ctx11.m_dev->CreateSamplerState(&sampDesc, &m_3dCtx.m_ctx11.m_ss[2]);
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Info, "initialized D3D11 renderer");
return;
}
#if BOO_HAS_VULKAN
if (useVulkan)
{
HMODULE vulkanLib = LoadLibraryW(L"vulkan-1.dll");
if (vulkanLib)
{
m_getVkProc = (PFN_vkGetInstanceProcAddr)GetProcAddress(vulkanLib, "vkGetInstanceProcAddr");
if (m_getVkProc)
{
/* Check device support for vulkan */
vk::init_dispatch_table_top(PFN_vkGetInstanceProcAddr(m_getVkProc));
if (g_VulkanContext.m_instance == VK_NULL_HANDLE)
{
auto appName = getUniqueName();
if (g_VulkanContext.initVulkan(WCSTMBS(appName.data()).c_str()))
{
vk::init_dispatch_table_middle(g_VulkanContext.m_instance, false);
if (g_VulkanContext.enumerateDevices())
{
/* Obtain DXGI Factory */
HRESULT hr = MyCreateDXGIFactory1(__uuidof(IDXGIFactory1), &m_3dCtx.m_vulkanDxFactory);
if (FAILED(hr))
Log.report(logvisor::Fatal, "unable to create DXGI factory");
Log.report(logvisor::Info, "initialized Vulkan renderer");
return;
}
}
}
}
}
}
#endif
/* Finally try OpenGL */
{
/* Obtain DXGI Factory */
2015-11-07 05:15:50 +00:00
HRESULT hr = MyCreateDXGIFactory1(__uuidof(IDXGIFactory1), &m_3dCtx.m_ctxOgl.m_dxFactory);
if (FAILED(hr))
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Fatal, "unable to create DXGI factory");
2015-11-06 03:20:58 +00:00
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Info, "initialized OpenGL renderer");
2015-11-03 04:19:41 +00:00
return;
}
2017-11-25 02:49:20 +00:00
Log.report(logvisor::Fatal, "system doesn't support Vulkan, D3D11, or OpenGL");
2015-11-03 04:19:41 +00:00
}
2016-01-19 20:30:51 +00:00
2015-05-06 00:50:57 +00:00
EPlatformType getPlatformType() const
{
2015-11-21 02:58:56 +00:00
return EPlatformType::Win32;
2015-05-06 00:50:57 +00:00
}
2016-01-19 20:30:51 +00:00
2015-05-06 00:50:57 +00:00
LRESULT winHwndHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
/* Lookup boo window instance */
2017-07-17 04:01:13 +00:00
auto search = m_allWindows.find(hwnd);
if (search == m_allWindows.end())
2017-09-15 22:26:39 +00:00
return DefWindowProc(hwnd, uMsg, wParam, lParam);;
2017-07-17 04:01:13 +00:00
std::shared_ptr<IWindow> window = search->second.lock();
if (!window)
2017-09-15 22:26:39 +00:00
return DefWindowProc(hwnd, uMsg, wParam, lParam);
2017-07-17 04:01:13 +00:00
2015-05-06 00:50:57 +00:00
switch (uMsg)
{
case WM_CREATE:
return 0;
2016-01-19 20:30:51 +00:00
2015-05-06 00:50:57 +00:00
case WM_DEVICECHANGE:
2015-08-31 03:40:58 +00:00
return DeviceFinder::winDevChangedHandler(wParam, lParam);
2016-01-19 20:30:51 +00:00
case WM_CLOSE:
2015-11-07 20:12:47 +00:00
case WM_SIZE:
2015-11-07 07:49:53 +00:00
case WM_MOVING:
2015-11-06 03:20:58 +00:00
case WM_SYSKEYDOWN:
2015-11-03 04:19:41 +00:00
case WM_KEYDOWN:
2015-11-06 03:20:58 +00:00
case WM_SYSKEYUP:
2015-11-03 04:19:41 +00:00
case WM_KEYUP:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_XBUTTONDOWN:
case WM_XBUTTONUP:
case WM_MOUSEMOVE:
2015-11-07 07:49:53 +00:00
case WM_MOUSELEAVE:
case WM_NCMOUSELEAVE:
case WM_MOUSEHOVER:
case WM_NCMOUSEHOVER:
2015-12-31 06:34:26 +00:00
case WM_MOUSEWHEEL:
2016-01-15 06:46:15 +00:00
case WM_MOUSEHWHEEL:
2015-12-28 00:02:16 +00:00
case WM_CHAR:
2015-12-27 23:23:17 +00:00
case WM_UNICHAR:
2017-07-17 04:01:13 +00:00
{
HWNDEvent eventData(uMsg, wParam, lParam);
window->_incomingEvent(&eventData);
}
2015-11-03 04:19:41 +00:00
2015-05-06 00:50:57 +00:00
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
2016-01-19 20:30:51 +00:00
2015-11-03 04:19:41 +00:00
int run()
2015-05-06 00:50:57 +00:00
{
g_mainThreadId = GetCurrentThreadId();
2015-11-05 00:00:29 +00:00
2015-11-03 04:19:41 +00:00
/* Spawn client thread */
int clientReturn = 0;
std::thread clientThread([&]()
{
2017-11-14 03:32:44 +00:00
std::string thrName = WCSTMBS(getFriendlyName().data()) + " Client Thread";
2017-11-09 08:10:43 +00:00
logvisor::RegisterThreadName(thrName.c_str());
CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
clientReturn = m_callback.appMain(this);
PostThreadMessage(g_mainThreadId, WM_USER+1, 0, 0);
});
2016-01-19 20:30:51 +00:00
2015-05-06 00:50:57 +00:00
/* Pump messages */
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0))
{
2015-12-25 01:08:46 +00:00
if (!msg.hwnd)
{
2015-12-25 01:08:46 +00:00
/* PostThreadMessage events */
switch (msg.message)
{
case WM_USER:
{
/* New-window message (coalesced onto main thread) */
std::unique_lock<std::mutex> lk(m_nwmt);
SystemStringView* title = reinterpret_cast<SystemStringView*>(msg.wParam);
m_mwret = newWindow(*title);
2015-12-25 01:08:46 +00:00
lk.unlock();
m_nwcv.notify_one();
continue;
}
case WM_USER+1:
/* Quit message from client thread */
PostQuitMessage(0);
continue;
case WM_USER+2:
/* SetCursor call from client thread */
SetCursor(HCURSOR(msg.wParam));
continue;
case WM_USER+3:
/* ImmSetOpenStatus call from client thread */
ImmSetOpenStatus(HIMC(msg.wParam), BOOL(msg.lParam));
continue;
case WM_USER+4:
/* ImmSetCompositionWindow call from client thread */
ImmSetCompositionWindow(HIMC(msg.wParam), LPCOMPOSITIONFORM(msg.lParam));
continue;
default: break;
}
}
2015-12-25 01:08:46 +00:00
TranslateMessage(&msg);
DispatchMessage(&msg);
2015-05-06 00:50:57 +00:00
}
2015-11-03 04:19:41 +00:00
m_callback.appQuitting(this);
clientThread.join();
return clientReturn;
2015-05-06 00:50:57 +00:00
}
2016-01-19 20:30:51 +00:00
2017-11-13 06:13:32 +00:00
SystemStringView getUniqueName() const
2015-08-31 03:40:58 +00:00
{
return m_uniqueName;
}
2017-11-13 06:13:32 +00:00
SystemStringView getFriendlyName() const
2015-08-31 03:40:58 +00:00
{
return m_friendlyName;
}
2017-11-13 06:13:32 +00:00
SystemStringView getProcessName() const
2015-05-06 00:50:57 +00:00
{
return m_pname;
}
2016-01-19 20:30:51 +00:00
2015-08-31 03:40:58 +00:00
const std::vector<SystemString>& getArgs() const
2015-05-06 00:50:57 +00:00
{
return m_args;
}
2016-01-19 20:30:51 +00:00
2015-11-05 00:00:29 +00:00
std::mutex m_nwmt;
std::condition_variable m_nwcv;
2017-07-17 04:01:13 +00:00
std::shared_ptr<IWindow> m_mwret;
std::shared_ptr<IWindow> newWindow(SystemStringView title)
2015-05-06 00:50:57 +00:00
{
if (GetCurrentThreadId() != g_mainThreadId)
2015-11-05 00:00:29 +00:00
{
std::unique_lock<std::mutex> lk(m_nwmt);
if (!PostThreadMessage(g_mainThreadId, WM_USER, WPARAM(&title), 0))
2016-03-04 23:02:18 +00:00
Log.report(logvisor::Fatal, "PostThreadMessage error");
2015-11-05 00:00:29 +00:00
m_nwcv.wait(lk);
2017-07-17 04:01:13 +00:00
std::shared_ptr<IWindow> ret = std::move(m_mwret);
m_mwret.reset();
return ret;
2015-11-05 00:00:29 +00:00
}
2016-01-19 20:30:51 +00:00
std::shared_ptr<IWindow> window = _WindowWin32New(title, m_3dCtx);
2015-08-31 03:40:58 +00:00
HWND hwnd = HWND(window->getPlatformHandle());
2015-05-06 00:50:57 +00:00
m_allWindows[hwnd] = window;
2015-08-31 03:40:58 +00:00
return window;
2015-05-06 00:50:57 +00:00
}
};
2016-01-19 20:30:51 +00:00
2015-05-06 00:50:57 +00:00
IApplication* APP = NULL;
2015-11-03 04:19:41 +00:00
int ApplicationRun(IApplication::EPlatformType platform,
IApplicationCallback& cb,
2017-11-13 06:13:32 +00:00
SystemStringView uniqueName,
SystemStringView friendlyName,
SystemStringView pname,
2015-11-03 04:19:41 +00:00
const std::vector<SystemString>& args,
std::string_view gfxApi,
uint32_t samples,
uint32_t anisotropy,
2015-11-03 04:19:41 +00:00
bool singleInstance)
2015-05-06 00:50:57 +00:00
{
2017-11-14 03:32:44 +00:00
std::string thrName = WCSTMBS(friendlyName.data()) + " Main Thread";
2017-11-09 08:10:43 +00:00
logvisor::RegisterThreadName(thrName.c_str());
2015-11-03 04:19:41 +00:00
if (APP)
return 1;
2015-11-21 02:58:56 +00:00
if (platform != IApplication::EPlatformType::Win32 &&
platform != IApplication::EPlatformType::Auto)
2015-11-03 04:19:41 +00:00
return 1;
2015-11-05 00:00:29 +00:00
2016-12-11 01:50:26 +00:00
#if _WIN32_WINNT_WINBLUE
/* HI-DPI support */
HMODULE shcoreLib = LoadLibraryW(L"Shcore.dll");
if (shcoreLib)
MyGetScaleFactorForMonitor =
(PFN_GetScaleFactorForMonitor)GetProcAddress(shcoreLib, "GetScaleFactorForMonitor");
#endif
2016-01-28 03:39:04 +00:00
WIN32_CURSORS.m_arrow = LoadCursor(nullptr, IDC_ARROW);
WIN32_CURSORS.m_hResize = LoadCursor(nullptr, IDC_SIZEWE);
WIN32_CURSORS.m_vResize = LoadCursor(nullptr, IDC_SIZENS);
WIN32_CURSORS.m_ibeam = LoadCursor(nullptr, IDC_IBEAM);
WIN32_CURSORS.m_crosshairs = LoadCursor(nullptr, IDC_CROSS);
WIN32_CURSORS.m_wait = LoadCursor(nullptr, IDC_WAIT);
2015-11-05 00:00:29 +00:00
/* One class for *all* boo windows */
WNDCLASS wndClass =
{
0,
WindowProc,
0,
0,
GetModuleHandle(nullptr),
0,
0,
0,
0,
L"BooWindow"
};
2016-01-27 19:26:45 +00:00
wndClass.hIcon = LoadIconW(wndClass.hInstance, MAKEINTRESOURCEW(101));
2016-01-28 03:39:04 +00:00
wndClass.hCursor = WIN32_CURSORS.m_arrow;
2017-09-15 22:26:39 +00:00
ATOM a = RegisterClassW(&wndClass);
2015-11-05 00:00:29 +00:00
APP = new ApplicationWin32(cb, uniqueName, friendlyName, pname, args,
gfxApi, samples, anisotropy, singleInstance);
2015-11-03 04:19:41 +00:00
return APP->run();
2015-05-06 00:50:57 +00:00
}
}
static const DEV_BROADCAST_DEVICEINTERFACE HOTPLUG_CONF =
2015-05-06 00:50:57 +00:00
{
sizeof(DEV_BROADCAST_DEVICEINTERFACE),
2015-05-06 00:50:57 +00:00
DBT_DEVTYP_DEVICEINTERFACE,
0,
0
2015-05-06 00:50:57 +00:00
};
static bool HOTPLUG_REGISTERED = false;
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
2015-08-31 03:40:58 +00:00
if (!HOTPLUG_REGISTERED && uMsg == WM_CREATE)
2015-05-06 00:50:57 +00:00
{
/* Register hotplug notification with windows */
RegisterDeviceNotification(hwnd, (LPVOID)&HOTPLUG_CONF,
DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
2015-05-06 00:50:57 +00:00
HOTPLUG_REGISTERED = true;
}
2015-08-31 03:40:58 +00:00
return static_cast<boo::ApplicationWin32*>(boo::APP)->winHwndHandler(hwnd, uMsg, wParam, lParam);
2015-05-06 00:50:57 +00:00
}