Fix some window messaging bugs for dx.

This commit is contained in:
jmsgrogan 2023-01-08 12:41:09 +00:00
parent 55ed0e9299
commit 39422838b7
13 changed files with 237 additions and 68 deletions

View file

@ -15,7 +15,7 @@ std::unique_ptr<DrawingSurface> DrawingSurface::Create()
return std::make_unique<DrawingSurface>(); return std::make_unique<DrawingSurface>();
} }
void DrawingSurface::setSize(unsigned width, unsigned height) void DrawingSurface::setSize(unsigned width, unsigned height, bool triggerResize)
{ {
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;

View file

@ -15,7 +15,7 @@ public:
static std::unique_ptr<DrawingSurface> Create(); static std::unique_ptr<DrawingSurface> Create();
virtual void setSize(unsigned width, unsigned height); virtual void setSize(unsigned width, unsigned height, bool triggerResize = true);
unsigned getWidth() const; unsigned getWidth() const;

View file

@ -1,19 +1,23 @@
list(APPEND ui_elements_LIB_INCLUDES list(APPEND ui_elements_LIB_INCLUDES
desktop_elements/Keyboard.h
desktop_elements/Keyboard.cpp desktop_elements/Keyboard.cpp
desktop_elements/IPlatformScreen.h desktop_elements/IPlatformScreen.h
desktop_elements/Screen.h
desktop_elements/Screen.cpp desktop_elements/Screen.cpp
desktop_elements/IPlatformWindow.h desktop_elements/IPlatformWindow.h
desktop_elements/Window.h
desktop_elements/Window.cpp desktop_elements/Window.cpp
ui_events/KeyboardEvent.cpp
ui_events/MouseEvent.cpp
ui_events/UiEvent.cpp
ui_events/PaintEvent.cpp
ui_events/KeyboardEvent.h ui_events/KeyboardEvent.h
ui_events/KeyboardEvent.cpp
ui_events/MouseEvent.h ui_events/MouseEvent.h
ui_events/MouseEvent.cpp
ui_events/UiEvent.h ui_events/UiEvent.h
ui_events/UiEvent.cpp
ui_events/PaintEvent.h ui_events/PaintEvent.h
ui_events/PaintEvent.cpp
ui_events/ResizeEvent.h ui_events/ResizeEvent.h
ui_events/ResizeEvent.cpp ui_events/ResizeEvent.cpp
widgets/Widget.h
widgets/Widget.cpp widgets/Widget.cpp
widgets/Button.cpp widgets/Button.cpp
widgets/ButtonGroup.cpp widgets/ButtonGroup.cpp

View file

@ -0,0 +1,12 @@
#pragma once
namespace WindowState
{
enum class Display
{
NORMAL,
MINIMIZED,
MAXIMIZED,
FULL_SCREEN
};
}

View file

@ -43,14 +43,37 @@ std::unique_ptr<Window> Window::Create()
return std::make_unique<Window>(); return std::make_unique<Window>();
} }
void Window::setSize(unsigned width, unsigned height) void Window::setIsSizingOnGoing(bool sizingOngoing)
{ {
mSizingOngoing = sizingOngoing;
}
bool Window::getIsSizingOnGoing() const
{
return mSizingOngoing;
}
void Window::setSize(unsigned width, unsigned height, bool triggerResize)
{
if (width == mWidth && height == mHeight)
{
return;
}
DrawingSurface::setSize(width, height); DrawingSurface::setSize(width, height);
mWidget->setBounds(width, height); if (triggerResize && !mSizingOngoing)
{
onResize();
}
}
void Window::onResize()
{
mWidget->setBounds(mWidth, mHeight);
if (mPlatformWindow) if (mPlatformWindow)
{ {
mPlatformWindow->onResize(width, height); mPlatformWindow->onResize(mWidth, mHeight);
} }
} }
@ -151,4 +174,47 @@ bool Window::isDirty() const
return mWidget->needsUpdate(); return mWidget->needsUpdate();
} }
void Window::setDisplayState(WindowState::Display state)
{
mDisplayState = state;
}
WindowState::Display Window::getDisplayState() const
{
return mDisplayState;
}
void Window::setTitle(const std::string& title)
{
mTitle = title;
}
const std::string& Window::getTitle() const
{
return mTitle;
}
void Window::addPopup(std::unique_ptr<Widget> popupWidget)
{
if (mPopupFunc)
{
mPopupFunc(this, std::move(popupWidget));
}
}
void Window::setPopupHandler(onPopupFunc func)
{
mPopupFunc = func;
}
void Window::setParent(Window* parent)
{
mParent = parent;
}
Window* Window::getParent() const
{
return mParent;
}
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "DrawingSurface.h" #include "DrawingSurface.h"
#include "DisplayState.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -30,7 +31,6 @@ class Window : public DrawingSurface
{ {
public: public:
using onPopupFunc = std::function<void(mt::Window* parent, std::unique_ptr<Widget> popup)>; using onPopupFunc = std::function<void(mt::Window* parent, std::unique_ptr<Widget> popup)>;
Window(); Window();
@ -39,66 +39,55 @@ public:
static std::unique_ptr<Window> Create(); static std::unique_ptr<Window> Create();
void setWidget(WidgetPtr widget); void addPopup(std::unique_ptr<Widget> popupWidget);
void onPaint(const PaintEvent* event);
void onMouseEvent(const MouseEvent* event);
void onKeyboardEvent(const KeyboardEvent* event);
IPlatformWindow* getPlatformWindow() const;
void setPlatformWindow(IPlatformWindowPtr window, FontsManager* fontsManager, DrawingMode drawingMode);
void map();
void show();
void doPaint(mt::Screen* screen);
void clear(); void clear();
void clearPlatformWindow(); void clearPlatformWindow();
void setSize(unsigned width, unsigned height) override; void doPaint(mt::Screen* screen);
IPlatformWindow* getPlatformWindow() const;
const std::string& getTitle() const;
Window* getParent() const;
DrawingContext* getDrawingContent() const;
WindowState::Display getDisplayState() const;
bool getIsSizingOnGoing() const;
bool isDirty() const; bool isDirty() const;
void setTitle(const std::string& title) void map();
{
mTitle = title;
}
const std::string& getTitle() const void onPaint(const PaintEvent* event);
{
return mTitle;
}
void addPopup(std::unique_ptr<Widget> popupWidget) void onMouseEvent(const MouseEvent* event);
{
if (mPopupFunc)
{
mPopupFunc(this, std::move(popupWidget));
}
}
void setPopupHandler(onPopupFunc func) void onResize();
{
mPopupFunc = func;
}
void setParent(Window* parent) void onKeyboardEvent(const KeyboardEvent* event);
{
mParent = parent;
}
Window* getParent() const void setPlatformWindow(IPlatformWindowPtr window, FontsManager* fontsManager, DrawingMode drawingMode);
{
return mParent;
}
DrawingContext* getDrawingContent() const; void setPopupHandler(onPopupFunc func);
void setParent(Window* parent);
void show();
void setIsSizingOnGoing(bool sizingOngoing);
void setSize(unsigned width, unsigned height, bool triggerResize = true) override;
void setTitle(const std::string& title);
void setWidget(WidgetPtr widget);
void setDisplayState(WindowState::Display state);
private: private:
WidgetPtr mWidget {nullptr}; WidgetPtr mWidget {nullptr};
@ -108,6 +97,9 @@ private:
onPopupFunc mPopupFunc; onPopupFunc mPopupFunc;
Window* mParent{nullptr}; Window* mParent{nullptr};
bool mSizingOngoing{ false };
WindowState::Display mDisplayState{ WindowState::Display::NORMAL };
}; };
} }

View file

@ -104,10 +104,60 @@ LRESULT CALLBACK Win32Window::WindowProc(UINT message, WPARAM wParam, LPARAM lPa
auto keyChar = (wchar_t)wParam; auto keyChar = (wchar_t)wParam;
key_event->setKeyString(StringUtils::convert(std::wstring(1, keyChar))); key_event->setKeyString(StringUtils::convert(std::wstring(1, keyChar)));
mDesktopManager->onUiEvent(std::move(key_event)); mDesktopManager->onUiEvent(std::move(key_event));
return 0;
} }
case WM_PAINT: case WM_PAINT:
{ {
onPaintMessage(); onPaintMessage();
return 0;
}
case WM_SIZE:
{
auto width = LOWORD(lParam);
auto height = HIWORD(lParam);
MLOG_INFO("WM_SIZE: " << width << " | " << height);
mWindow->setSize(width, height, false);
if (wParam == SIZE_MINIMIZED)
{
mWindow->setDisplayState(WindowState::Display::MINIMIZED);
}
else if (wParam == SIZE_MAXIMIZED)
{
mWindow->setDisplayState(WindowState::Display::MAXIMIZED);
mWindow->onResize();
}
else if (wParam == SIZE_RESTORED)
{
if (mWindow->getDisplayState() == WindowState::Display::MINIMIZED)
{
mWindow->setDisplayState(WindowState::Display::NORMAL);
mWindow->onResize();
}
else if (mWindow->getDisplayState() == WindowState::Display::MAXIMIZED)
{
mWindow->setDisplayState(WindowState::Display::NORMAL);
mWindow->onResize();
}
else if (!mWindow->getIsSizingOnGoing())
{
mWindow->onResize();
}
}
return 0;
}
case WM_ENTERSIZEMOVE:
{
MLOG_INFO("WM_ENTERSIZEMOVE");
mWindow->setIsSizingOnGoing(true);
return 0;
}
case WM_EXITSIZEMOVE:
{
MLOG_INFO("WM_EXITSIZEMOVE");
mWindow->setIsSizingOnGoing(false);
mWindow->onResize();
return 0;
} }
} }
return DefWindowProc(mHandle, message, wParam, lParam); return DefWindowProc(mHandle, message, wParam, lParam);
@ -172,3 +222,11 @@ void Win32Window::afterPaint(mt::Screen* screen)
EndPaint(mHandle, &ps); EndPaint(mHandle, &ps);
} }
} }
void Win32Window::onResize(unsigned width, unsigned height)
{
if (mDxInterface)
{
mDxInterface->onResize();
}
}

View file

@ -43,7 +43,7 @@ public:
void clear() {}; void clear() {};
void onResize(unsigned width, unsigned height) {}; void onResize(unsigned width, unsigned height);
void beforePaint(mt::Screen* screen); void beforePaint(mt::Screen* screen);

View file

@ -63,6 +63,9 @@ void DirectX2dIntegration::clearBuffers()
buffer.Reset(); buffer.Reset();
} }
mD2dRenderTargets.clear(); mD2dRenderTargets.clear();
mDxInterface->getD2dContext()->SetTarget(nullptr);
mDxInterface->getD3d11DeviceContext()->Flush();
} }
void DirectX2dIntegration::wrapBuffer(ID3D12Resource* renderTarget) void DirectX2dIntegration::wrapBuffer(ID3D12Resource* renderTarget)

View file

@ -2,6 +2,8 @@
#include "DirectXDescriptors.h" #include "DirectXDescriptors.h"
#include "FileLogger.h"
#include <dxgi.h> #include <dxgi.h>
#include <dxgi1_6.h> #include <dxgi1_6.h>
#include <d3d12.h> #include <d3d12.h>
@ -17,10 +19,17 @@ void DirectXBuffers::clear()
{ {
for (auto& buffer : mBackBuffers) for (auto& buffer : mBackBuffers)
{ {
buffer.Reset(); auto count = buffer.Reset();
} }
mBackBuffers.clear(); mBackBuffers.clear();
mDepthStencilBuffer.Reset(); mDepthStencilBuffer.Reset();
mInitialized = false;
}
bool DirectXBuffers::isInitialized()
{
return mInitialized;
} }
UINT DirectXBuffers::getCurrentBackBufferIndex() const UINT DirectXBuffers::getCurrentBackBufferIndex() const
@ -57,8 +66,11 @@ void DirectXBuffers::setupBackBuffers(ID3D12Device* device, IDXGISwapChain4* swa
swapChain->GetBuffer(i, IID_PPV_ARGS(&mBackBuffers[mBackBuffers.size()-1])); swapChain->GetBuffer(i, IID_PPV_ARGS(&mBackBuffers[mBackBuffers.size()-1]));
device->CreateRenderTargetView(mBackBuffers[mBackBuffers.size() - 1].Get(), nullptr, rtv_heap_handle); device->CreateRenderTargetView(mBackBuffers[mBackBuffers.size() - 1].Get(), nullptr, rtv_heap_handle);
rtv_heap_handle.Offset(1, descriptors->getRtvDescriptorSize()); rtv_heap_handle.Offset(1, descriptors->getRtvDescriptorSize());
} }
mInitialized = true;
} }
void DirectXBuffers::setupDepthStencilHeap(ID3D12Device* device, unsigned width, unsigned height) void DirectXBuffers::setupDepthStencilHeap(ID3D12Device* device, unsigned width, unsigned height)

View file

@ -23,6 +23,8 @@ public:
ID3D12Resource* getDepthStencilBuffer() const; ID3D12Resource* getDepthStencilBuffer() const;
bool isInitialized();
void setupBackBuffers(ID3D12Device* device, IDXGISwapChain4* swapChain, DirectXDescriptors* descriptors); void setupBackBuffers(ID3D12Device* device, IDXGISwapChain4* swapChain, DirectXDescriptors* descriptors);
void setupDepthStencilHeap(ID3D12Device* device, unsigned width, unsigned height); void setupDepthStencilHeap(ID3D12Device* device, unsigned width, unsigned height);
@ -32,6 +34,7 @@ public:
void updateBackbufferIndex(UINT index); void updateBackbufferIndex(UINT index);
private: private:
bool mInitialized{ false };
UINT mFrameCount{ 2 }; UINT mFrameCount{ 2 };
UINT mBackBufferIndex{ 0 }; UINT mBackBufferIndex{ 0 };
std::vector<Microsoft::WRL::ComPtr<ID3D12Resource> > mBackBuffers; std::vector<Microsoft::WRL::ComPtr<ID3D12Resource> > mBackBuffers;

View file

@ -32,6 +32,6 @@ void DirectXCommandList::reset(ID3D12PipelineState* pso)
void DirectXCommandList::resetAllocator() void DirectXCommandList::resetAllocator()
{ {
mCommandAllocator.Reset(); mCommandAllocator->Reset();
} }

View file

@ -46,6 +46,13 @@ void Win32DxWindowInterface::onRender()
{ {
if (!mIsValid) if (!mIsValid)
{ {
MLOG_INFO("Invalid state - returning");
return;
}
if (!mBuffers->isInitialized())
{
MLOG_INFO("Buffer not initialized - returning");
return; return;
} }
@ -89,8 +96,8 @@ void Win32DxWindowInterface::updateCommandList()
painter->paintMesh(mCommandList->get()); painter->paintMesh(mCommandList->get());
// Indicate that the back buffer will now be used to present. (Exclude as handled by D2D integration later) // Indicate that the back buffer will now be used to present. (Exclude as handled by D2D integration later)
//barrier = CD3DX12_RESOURCE_BARRIER::Transition(mRenderTargets[mFrameIndex].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT); //barrier = CD3DX12_RESOURCE_BARRIER::Transition(mBuffers->getCurrentBackBuffer(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
//mCommandList->ResourceBarrier(1, &barrier); //mCommandList->get()->ResourceBarrier(1, &barrier);
mCommandList->close(); mCommandList->close();
} }
@ -102,6 +109,10 @@ bool Win32DxWindowInterface::initialize()
return true; return true;
} }
mInitialized = true; mInitialized = true;
MLOG_INFO("D3D Win init");
mD2dIntegration = std::make_unique<DirectX2dIntegration>(mWindow, mDxInterface, FrameCount);
mBuffers = std::make_unique<DirectXBuffers>(FrameCount);
if (!createSwapChain()) if (!createSwapChain())
{ {
@ -115,8 +126,6 @@ bool Win32DxWindowInterface::initialize()
mDescriptors = std::make_unique<DirectXDescriptors>(); mDescriptors = std::make_unique<DirectXDescriptors>();
mDescriptors->setupDefaultDescriptorHeaps(mDxInterface->getD3dDevice()); mDescriptors->setupDefaultDescriptorHeaps(mDxInterface->getD3dDevice());
mD2dIntegration = std::make_unique<DirectX2dIntegration>(mWindow, mDxInterface, FrameCount);
mBuffers = std::make_unique<DirectXBuffers>(FrameCount);
onResize(); onResize();
@ -133,6 +142,9 @@ bool Win32DxWindowInterface::initialize()
void Win32DxWindowInterface::onResize() void Win32DxWindowInterface::onResize()
{ {
MLOG_INFO("On resize");
mIsValid = false;
flushCommandQueue(); flushCommandQueue();
mCommandList->reset(getPipelineState()); mCommandList->reset(getPipelineState());
@ -150,12 +162,15 @@ void Win32DxWindowInterface::onResize()
flushCommandQueue(); flushCommandQueue();
updateViewport(); updateViewport();
mIsValid = true;
} }
void Win32DxWindowInterface::resizeSwapChain() void Win32DxWindowInterface::resizeSwapChain()
{ {
const auto width = mWindow->getWidth(); const auto width = mWindow->getWidth();
const auto height = mWindow->getHeight(); const auto height = mWindow->getHeight();
MLOG_INFO("Resizing swap chain to: " << width << " | " << height);
mSwapChain->ResizeBuffers(FrameCount, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); mSwapChain->ResizeBuffers(FrameCount, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH);
updateBackbufferIndex(0); updateBackbufferIndex(0);
} }
@ -170,8 +185,8 @@ void Win32DxWindowInterface::updateViewport()
void Win32DxWindowInterface::clearBuffers() void Win32DxWindowInterface::clearBuffers()
{ {
mBuffers->clear();
mD2dIntegration->clearBuffers(); mD2dIntegration->clearBuffers();
mBuffers->clear();
} }
ID3D12PipelineState* Win32DxWindowInterface::getPipelineState() const ID3D12PipelineState* Win32DxWindowInterface::getPipelineState() const
@ -182,6 +197,7 @@ ID3D12PipelineState* Win32DxWindowInterface::getPipelineState() const
void Win32DxWindowInterface::populateBuffers() void Win32DxWindowInterface::populateBuffers()
{ {
MLOG_INFO("Populating buffers");
auto d3d_device = mDxInterface->getD3dDevice(); auto d3d_device = mDxInterface->getD3dDevice();
mBuffers->setupBackBuffers(d3d_device, mSwapChain.Get(), mDescriptors.get()); mBuffers->setupBackBuffers(d3d_device, mSwapChain.Get(), mDescriptors.get());
for (UINT idx = 0; idx < FrameCount; idx++) for (UINT idx = 0; idx < FrameCount; idx++)
@ -191,12 +207,15 @@ void Win32DxWindowInterface::populateBuffers()
const auto width = mWindow->getWidth(); const auto width = mWindow->getWidth();
const auto height = mWindow->getHeight(); const auto height = mWindow->getHeight();
if (width > 0 and height > 0)
{
mBuffers->setupDepthStencilHeap(mDxInterface->getD3dDevice(), width, height); mBuffers->setupDepthStencilHeap(mDxInterface->getD3dDevice(), width, height);
mBuffers->setupDepthStencilView(mDxInterface->getD3dDevice(), mDescriptors.get()); mBuffers->setupDepthStencilView(mDxInterface->getD3dDevice(), mDescriptors.get());
auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(mBuffers->getDepthStencilBuffer(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_DEPTH_WRITE); auto barrier = CD3DX12_RESOURCE_BARRIER::Transition(mBuffers->getDepthStencilBuffer(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_DEPTH_WRITE);
mCommandList->get()->ResourceBarrier(1, &barrier); mCommandList->get()->ResourceBarrier(1, &barrier);
} }
}
bool Win32DxWindowInterface::createSwapChain() bool Win32DxWindowInterface::createSwapChain()
{ {