diff options
Diffstat (limited to 'src/win')
-rw-r--r-- | src/win/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/win/StdOutLogger.hpp | 24 | ||||
-rw-r--r-- | src/win/graph/direct/CMakeLists.txt | 25 | ||||
-rw-r--r-- | src/win/graph/direct/Resource.cpp | 12 | ||||
-rw-r--r-- | src/win/graphics/CMakeLists.txt (renamed from src/win/graph/CMakeLists.txt) | 0 | ||||
-rw-r--r-- | src/win/graphics/direct/Brush.cpp (renamed from src/win/graph/direct/Brush.cpp) | 12 | ||||
-rw-r--r-- | src/win/graphics/direct/CMakeLists.txt | 29 | ||||
-rw-r--r-- | src/win/graphics/direct/Factory.cpp (renamed from src/win/graph/direct/Factory.cpp) | 16 | ||||
-rw-r--r-- | src/win/graphics/direct/Font.cpp (renamed from src/win/graph/direct/Font.cpp) | 10 | ||||
-rw-r--r-- | src/win/graphics/direct/Geometry.cpp (renamed from src/win/graph/direct/Geometry.cpp) | 12 | ||||
-rw-r--r-- | src/win/graphics/direct/Painter.cpp (renamed from src/win/graph/direct/Painter.cpp) | 24 | ||||
-rw-r--r-- | src/win/graphics/direct/Resource.cpp | 12 | ||||
-rw-r--r-- | src/win/graphics/direct/TextLayout.cpp (renamed from src/win/graph/direct/TextLayout.cpp) | 19 | ||||
-rw-r--r-- | src/win/graphics/direct/WindowPainter.cpp | 20 | ||||
-rw-r--r-- | src/win/graphics/direct/WindowRenderTarget.cpp (renamed from src/win/native/WindowRenderTarget.cpp) | 35 | ||||
-rw-r--r-- | src/win/gui/CMakeLists.txt | 31 | ||||
-rw-r--r-- | src/win/gui/Cursor.cpp (renamed from src/win/native/Cursor.cpp) | 13 | ||||
-rw-r--r-- | src/win/gui/GodWindow.cpp (renamed from src/win/native/GodWindow.cpp) | 61 | ||||
-rw-r--r-- | src/win/gui/InputMethod.cpp (renamed from src/win/native/InputMethod.cpp) | 102 | ||||
-rw-r--r-- | src/win/gui/Keyboard.cpp (renamed from src/win/native/Keyboard.cpp) | 6 | ||||
-rw-r--r-- | src/win/gui/TimerManager.cpp | 100 | ||||
-rw-r--r-- | src/win/gui/TimerManager.hpp | 61 | ||||
-rw-r--r-- | src/win/gui/UiApplication.cpp (renamed from src/win/native/UiApplication.cpp) | 80 | ||||
-rw-r--r-- | src/win/gui/Window.cpp (renamed from src/win/native/Window.cpp) | 128 | ||||
-rw-r--r-- | src/win/gui/WindowClass.cpp (renamed from src/win/native/WindowClass.cpp) | 8 | ||||
-rw-r--r-- | src/win/gui/WindowManager.cpp (renamed from src/win/native/WindowManager.cpp) | 10 | ||||
-rw-r--r-- | src/win/gui/WindowManager.hpp (renamed from src/win/native/WindowManager.hpp) | 4 | ||||
-rw-r--r-- | src/win/native/CMakeLists.txt | 37 | ||||
-rw-r--r-- | src/win/native/DpiUtil.hpp | 46 | ||||
-rw-r--r-- | src/win/native/GodWindowMessage.hpp | 6 | ||||
-rw-r--r-- | src/win/native/Timer.cpp | 28 | ||||
-rw-r--r-- | src/win/native/Timer.hpp | 34 | ||||
-rw-r--r-- | src/win/native/WindowD2DPainter.cpp | 22 | ||||
-rw-r--r-- | src/win/native/WindowD2DPainter.hpp | 21 |
34 files changed, 544 insertions, 509 deletions
diff --git a/src/win/CMakeLists.txt b/src/win/CMakeLists.txt index 75b0a7ca..bf8de863 100644 --- a/src/win/CMakeLists.txt +++ b/src/win/CMakeLists.txt @@ -2,6 +2,7 @@ set(CRU_WIN_BASE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/win/) add_library(cru_win_base STATIC DebugLogger.hpp + StdOutLogger.hpp Exception.cpp HeapDebug.cpp @@ -13,5 +14,5 @@ target_sources(cru_win_base PUBLIC target_compile_definitions(cru_win_base PUBLIC UNICODE _UNICODE) # use unicode target_link_libraries(cru_win_base PUBLIC cru_base) -add_subdirectory(graph) -add_subdirectory(native) +add_subdirectory(graphics) +add_subdirectory(gui) diff --git a/src/win/StdOutLogger.hpp b/src/win/StdOutLogger.hpp new file mode 100644 index 00000000..bff8b30e --- /dev/null +++ b/src/win/StdOutLogger.hpp @@ -0,0 +1,24 @@ +#include "cru/common/Base.hpp" +#include "cru/win/WinPreConfig.hpp" + +#include "cru/common/Logger.hpp" + +#include <cwchar> + +namespace cru::platform::win { +class WinStdOutLoggerSource : public ::cru::log::ILogSource { + public: + WinStdOutLoggerSource() = default; + + CRU_DELETE_COPY(WinStdOutLoggerSource) + CRU_DELETE_MOVE(WinStdOutLoggerSource) + + ~WinStdOutLoggerSource() = default; + + void Write(::cru::log::LogLevel level, const std::u16string& s) override { + CRU_UNUSED(level) + + std::fputws(reinterpret_cast<const wchar_t*>(s.c_str()), stdout); + } +}; +} // namespace cru::platform::win diff --git a/src/win/graph/direct/CMakeLists.txt b/src/win/graph/direct/CMakeLists.txt deleted file mode 100644 index 5505b0b5..00000000 --- a/src/win/graph/direct/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -set(CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/win/graph/direct) - -add_library(cru_win_graph_direct STATIC - Brush.cpp - Font.cpp - Geometry.cpp - Factory.cpp - Painter.cpp - Resource.cpp - TextLayout.cpp -) -target_sources(cru_win_graph_direct PUBLIC - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/Brush.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/ComResource.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/ConvertUtil.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/Exception.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/Font.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/Geometry.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/Factory.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/Painter.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/Resource.hpp - ${CRU_WIN_GRAPH_DIRECT_INCLUDE_DIR}/TextLayout.hpp -) -target_link_libraries(cru_win_graph_direct PUBLIC D3D11 D2d1 DWrite) -target_link_libraries(cru_win_graph_direct PUBLIC cru_win_base cru_platform_graph) diff --git a/src/win/graph/direct/Resource.cpp b/src/win/graph/direct/Resource.cpp deleted file mode 100644 index 772bb74b..00000000 --- a/src/win/graph/direct/Resource.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "cru/win/graph/direct/Resource.hpp" - -#include "cru/win/graph/direct/Factory.hpp" - -namespace cru::platform::graph::win::direct { -DirectGraphResource::DirectGraphResource(DirectGraphFactory* factory) - : factory_(factory) { - Expects(factory); -} - -IGraphFactory* DirectGraphResource::GetGraphFactory() { return factory_; } -} // namespace cru::platform::graph::win::direct diff --git a/src/win/graph/CMakeLists.txt b/src/win/graphics/CMakeLists.txt index c90537ac..c90537ac 100644 --- a/src/win/graph/CMakeLists.txt +++ b/src/win/graphics/CMakeLists.txt diff --git a/src/win/graph/direct/Brush.cpp b/src/win/graphics/direct/Brush.cpp index 2b9d4ac3..b7842b97 100644 --- a/src/win/graph/direct/Brush.cpp +++ b/src/win/graphics/direct/Brush.cpp @@ -1,10 +1,10 @@ -#include "cru/win/graph/direct/Brush.hpp" +#include "cru/win/graphics/direct/Brush.hpp" -#include "cru/win/graph/direct/ConvertUtil.hpp" -#include "cru/win/graph/direct/Exception.hpp" -#include "cru/win/graph/direct/Factory.hpp" +#include "cru/win/graphics/direct/ConvertUtil.hpp" +#include "cru/win/graphics/direct/Exception.hpp" +#include "cru/win/graphics/direct/Factory.hpp" -namespace cru::platform::graph::win::direct { +namespace cru::platform::graphics::win::direct { D2DSolidColorBrush::D2DSolidColorBrush(DirectGraphFactory* factory) : DirectGraphResource(factory) { ThrowIfFailed(factory->GetDefaultD2D1DeviceContext()->CreateSolidColorBrush( @@ -14,4 +14,4 @@ D2DSolidColorBrush::D2DSolidColorBrush(DirectGraphFactory* factory) void D2DSolidColorBrush::SetColor(const Color& color) { brush_->SetColor(Convert(color)); } -} // namespace cru::platform::graph::win::direct +} // namespace cru::platform::graphics::win::direct diff --git a/src/win/graphics/direct/CMakeLists.txt b/src/win/graphics/direct/CMakeLists.txt new file mode 100644 index 00000000..d4c96a65 --- /dev/null +++ b/src/win/graphics/direct/CMakeLists.txt @@ -0,0 +1,29 @@ +set(CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/win/graphics/direct) + +add_library(cru_win_graphics_direct STATIC + Brush.cpp + Font.cpp + Geometry.cpp + Factory.cpp + Painter.cpp + Resource.cpp + TextLayout.cpp + WindowPainter.cpp + WindowRenderTarget.cpp +) +target_sources(cru_win_graphics_direct PUBLIC + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/Brush.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/ComResource.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/ConvertUtil.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/Exception.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/Font.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/Geometry.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/Factory.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/Painter.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/Resource.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/TextLayout.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/WindowPainter.hpp + ${CRU_WIN_GRAPHICS_DIRECT_INCLUDE_DIR}/WindowRenderTarget.hpp +) +target_link_libraries(cru_win_graphics_direct PUBLIC D3D11 D2d1 DWrite) +target_link_libraries(cru_win_graphics_direct PUBLIC cru_win_base cru_platform_graphics) diff --git a/src/win/graph/direct/Factory.cpp b/src/win/graphics/direct/Factory.cpp index 03e64e13..6694801f 100644 --- a/src/win/graph/direct/Factory.cpp +++ b/src/win/graphics/direct/Factory.cpp @@ -1,16 +1,16 @@ -#include "cru/win/graph/direct/Factory.hpp" +#include "cru/win/graphics/direct/Factory.hpp" #include "cru/common/Logger.hpp" -#include "cru/win/graph/direct/Brush.hpp" -#include "cru/win/graph/direct/Exception.hpp" -#include "cru/win/graph/direct/Font.hpp" -#include "cru/win/graph/direct/Geometry.hpp" -#include "cru/win/graph/direct/TextLayout.hpp" +#include "cru/win/graphics/direct/Brush.hpp" +#include "cru/win/graphics/direct/Exception.hpp" +#include "cru/win/graphics/direct/Font.hpp" +#include "cru/win/graphics/direct/Geometry.hpp" +#include "cru/win/graphics/direct/TextLayout.hpp" #include <cstdlib> #include <utility> -namespace cru::platform::graph::win::direct { +namespace cru::platform::graphics::win::direct { namespace { void InitializeCom() { const auto hresult = ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); @@ -104,4 +104,4 @@ std::unique_ptr<ITextLayout> DirectGraphFactory::CreateTextLayout( return std::make_unique<DWriteTextLayout>(this, std::move(font), std::move(text)); } -} // namespace cru::platform::graph::win::direct +} // namespace cru::platform::graphics::win::direct diff --git a/src/win/graph/direct/Font.cpp b/src/win/graphics/direct/Font.cpp index 34de5b71..1d6a5c88 100644 --- a/src/win/graph/direct/Font.cpp +++ b/src/win/graphics/direct/Font.cpp @@ -1,12 +1,12 @@ -#include "cru/win/graph/direct/Font.hpp" +#include "cru/win/graphics/direct/Font.hpp" -#include "cru/win/graph/direct/Exception.hpp" -#include "cru/win/graph/direct/Factory.hpp" +#include "cru/win/graphics/direct/Exception.hpp" +#include "cru/win/graphics/direct/Factory.hpp" #include <array> #include <utility> -namespace cru::platform::graph::win::direct { +namespace cru::platform::graphics::win::direct { DWriteFont::DWriteFont(DirectGraphFactory* factory, std::u16string font_family, float font_size) : DirectGraphResource(factory), font_family_(std::move(font_family)) { @@ -28,4 +28,4 @@ DWriteFont::DWriteFont(DirectGraphFactory* factory, std::u16string font_family, } float DWriteFont::GetFontSize() { return text_format_->GetFontSize(); } -} // namespace cru::platform::graph::win::direct +} // namespace cru::platform::graphics::win::direct diff --git a/src/win/graph/direct/Geometry.cpp b/src/win/graphics/direct/Geometry.cpp index e77b4749..8aa961b2 100644 --- a/src/win/graph/direct/Geometry.cpp +++ b/src/win/graphics/direct/Geometry.cpp @@ -1,10 +1,10 @@ -#include "cru/win/graph/direct/Geometry.hpp" +#include "cru/win/graphics/direct/Geometry.hpp" -#include "cru/win/graph/direct/ConvertUtil.hpp" -#include "cru/win/graph/direct/Exception.hpp" -#include "cru/win/graph/direct/Factory.hpp" +#include "cru/win/graphics/direct/ConvertUtil.hpp" +#include "cru/win/graphics/direct/Exception.hpp" +#include "cru/win/graphics/direct/Factory.hpp" -namespace cru::platform::graph::win::direct { +namespace cru::platform::graphics::win::direct { D2DGeometryBuilder::D2DGeometryBuilder(DirectGraphFactory* factory) : DirectGraphResource(factory) { ThrowIfFailed(factory->GetD2D1Factory()->CreatePathGeometry(&geometry_)); @@ -59,4 +59,4 @@ bool D2DGeometry::FillContains(const Point& point) { Convert(point), D2D1::Matrix3x2F::Identity(), &result)); return result != 0; } -} // namespace cru::platform::graph::win::direct +} // namespace cru::platform::graphics::win::direct diff --git a/src/win/graph/direct/Painter.cpp b/src/win/graphics/direct/Painter.cpp index 3ffb5208..d6999cfa 100644 --- a/src/win/graph/direct/Painter.cpp +++ b/src/win/graphics/direct/Painter.cpp @@ -1,15 +1,15 @@ -#include "cru/win/graph/direct/Painter.hpp" +#include "cru/win/graphics/direct/Painter.hpp" #include "cru/platform/Check.hpp" -#include "cru/win/graph/direct/Brush.hpp" -#include "cru/win/graph/direct/ConvertUtil.hpp" -#include "cru/win/graph/direct/Exception.hpp" -#include "cru/win/graph/direct/Geometry.hpp" -#include "cru/win/graph/direct/TextLayout.hpp" +#include "cru/win/graphics/direct/Brush.hpp" +#include "cru/win/graphics/direct/ConvertUtil.hpp" +#include "cru/win/graphics/direct/Exception.hpp" +#include "cru/win/graphics/direct/Geometry.hpp" +#include "cru/win/graphics/direct/TextLayout.hpp" #include <type_traits> -namespace cru::platform::graph::win::direct { +namespace cru::platform::graphics::win::direct { D2DPainter::D2DPainter(ID2D1RenderTarget* render_target) { Expects(render_target); render_target_ = render_target; @@ -32,6 +32,14 @@ void D2DPainter::Clear(const Color& color) { render_target_->Clear(Convert(color)); } +void D2DPainter::DrawLine(const Point& start, const Point& end, IBrush* brush, + float width) { + CheckValidation(); + const auto b = CheckPlatform<ID2DBrush>(brush, GetPlatformId()); + render_target_->DrawLine(Convert(start), Convert(end), + b->GetD2DBrushInterface(), width); +} + void D2DPainter::StrokeRectangle(const Rect& rectangle, IBrush* brush, float width) { CheckValidation(); @@ -101,4 +109,4 @@ void D2DPainter::CheckValidation() { "Can't do that on painter after end drawing."); } } -} // namespace cru::platform::graph::win::direct +} // namespace cru::platform::graphics::win::direct diff --git a/src/win/graphics/direct/Resource.cpp b/src/win/graphics/direct/Resource.cpp new file mode 100644 index 00000000..2b4a0772 --- /dev/null +++ b/src/win/graphics/direct/Resource.cpp @@ -0,0 +1,12 @@ +#include "cru/win/graphics/direct/Resource.hpp" + +#include "cru/win/graphics/direct/Factory.hpp" + +namespace cru::platform::graphics::win::direct { +DirectGraphResource::DirectGraphResource(DirectGraphFactory* factory) + : factory_(factory) { + Expects(factory); +} + +IGraphFactory* DirectGraphResource::GetGraphFactory() { return factory_; } +} // namespace cru::platform::graphics::win::direct diff --git a/src/win/graph/direct/TextLayout.cpp b/src/win/graphics/direct/TextLayout.cpp index 0d4a6392..0b3c68ca 100644 --- a/src/win/graph/direct/TextLayout.cpp +++ b/src/win/graphics/direct/TextLayout.cpp @@ -1,14 +1,14 @@ -#include "cru/win/graph/direct/TextLayout.hpp" +#include "cru/win/graphics/direct/TextLayout.hpp" #include "cru/common/Logger.hpp" #include "cru/platform/Check.hpp" -#include "cru/win/graph/direct/Exception.hpp" -#include "cru/win/graph/direct/Factory.hpp" -#include "cru/win/graph/direct/Font.hpp" +#include "cru/win/graphics/direct/Exception.hpp" +#include "cru/win/graphics/direct/Factory.hpp" +#include "cru/win/graphics/direct/Font.hpp" #include <utility> -namespace cru::platform::graph::win::direct { +namespace cru::platform::graphics::win::direct { DWriteTextLayout::DWriteTextLayout(DirectGraphFactory* factory, std::shared_ptr<IFont> font, std::u16string text) @@ -58,10 +58,13 @@ void DWriteTextLayout::SetMaxHeight(float max_height) { ThrowIfFailed(text_layout_->SetMaxHeight(max_height_)); } -Rect DWriteTextLayout::GetTextBounds() { +Rect DWriteTextLayout::GetTextBounds(bool includingTrailingSpace) { DWRITE_TEXT_METRICS metrics; ThrowIfFailed(text_layout_->GetMetrics(&metrics)); - return Rect{metrics.left, metrics.top, metrics.width, metrics.height}; + return Rect{metrics.left, metrics.top, + includingTrailingSpace ? metrics.widthIncludingTrailingWhitespace + : metrics.width, + metrics.height}; } std::vector<Rect> DWriteTextLayout::TextRangeRect( @@ -121,4 +124,4 @@ TextHitTestResult DWriteTextLayout::HitTest(const Point& point) { result.insideText = inside != 0; return result; } -} // namespace cru::platform::graph::win::direct +} // namespace cru::platform::graphics::win::direct diff --git a/src/win/graphics/direct/WindowPainter.cpp b/src/win/graphics/direct/WindowPainter.cpp new file mode 100644 index 00000000..c88667b6 --- /dev/null +++ b/src/win/graphics/direct/WindowPainter.cpp @@ -0,0 +1,20 @@ +#include "cru/win/graphics/direct/WindowPainter.hpp" + +#include "cru/win/graphics/direct/Exception.hpp" +#include "cru/win/graphics/direct/Factory.hpp" +#include "cru/win/graphics/direct/WindowRenderTarget.hpp" + +namespace cru::platform::graphics::win::direct { +D2DWindowPainter::D2DWindowPainter(D2DWindowRenderTarget* render_target) + : D2DPainter(render_target->GetD2D1DeviceContext()), + render_target_(render_target) { + render_target_->GetD2D1DeviceContext()->BeginDraw(); +} + +D2DWindowPainter::~D2DWindowPainter() { EndDraw(); } + +void D2DWindowPainter::DoEndDraw() { + ThrowIfFailed(render_target_->GetD2D1DeviceContext()->EndDraw()); + render_target_->Present(); +} +} // namespace cru::platform::graphics::win::direct diff --git a/src/win/native/WindowRenderTarget.cpp b/src/win/graphics/direct/WindowRenderTarget.cpp index 4a114ebf..7479ae24 100644 --- a/src/win/native/WindowRenderTarget.cpp +++ b/src/win/graphics/direct/WindowRenderTarget.cpp @@ -1,19 +1,17 @@ -#include "cru/win/native/WindowRenderTarget.hpp" +#include "cru/win/graphics/direct/WindowRenderTarget.hpp" -#include "cru/win/graph/direct/Exception.hpp" -#include "cru/win/graph/direct/Factory.hpp" -#include "DpiUtil.hpp" - -namespace cru::platform::native::win { -using namespace cru::platform::graph::win::direct; -WindowRenderTarget::WindowRenderTarget(DirectGraphFactory* factory, HWND hwnd) - : factory_(factory) { - Expects(factory); +#include "cru/win/graphics/direct/Exception.hpp" +#include "cru/win/graphics/direct/Factory.hpp" +namespace cru::platform::graphics::win::direct { +D2DWindowRenderTarget::D2DWindowRenderTarget( + gsl::not_null<DirectGraphFactory*> factory, HWND hwnd) + : factory_(factory), hwnd_(hwnd) { const auto d3d11_device = factory->GetD3D11Device(); const auto dxgi_factory = factory->GetDxgiFactory(); d2d1_device_context_ = factory->CreateD2D1DeviceContext(); + d2d1_device_context_->SetUnitMode(D2D1_UNIT_MODE_DIPS); // Allocate a descriptor. DXGI_SWAP_CHAIN_DESC1 swap_chain_desc; @@ -40,7 +38,11 @@ WindowRenderTarget::WindowRenderTarget(DirectGraphFactory* factory, HWND hwnd) CreateTargetBitmap(); } -void WindowRenderTarget::ResizeBuffer(const int width, const int height) { +void D2DWindowRenderTarget::SetDpi(float x, float y) { + d2d1_device_context_->SetDpi(x, y); +} + +void D2DWindowRenderTarget::ResizeBuffer(const int width, const int height) { // In order to resize buffer, we need to untarget the buffer first. d2d1_device_context_->SetTarget(nullptr); target_bitmap_ = nullptr; @@ -49,11 +51,11 @@ void WindowRenderTarget::ResizeBuffer(const int width, const int height) { CreateTargetBitmap(); } -void WindowRenderTarget::Present() { +void D2DWindowRenderTarget::Present() { ThrowIfFailed(dxgi_swap_chain_->Present(1, 0)); } -void WindowRenderTarget::CreateTargetBitmap() { +void D2DWindowRenderTarget::CreateTargetBitmap() { Expects(target_bitmap_ == nullptr); // target bitmap must not exist. // Direct2D needs the dxgi version of the backbuffer surface pointer. @@ -61,12 +63,13 @@ void WindowRenderTarget::CreateTargetBitmap() { ThrowIfFailed( dxgi_swap_chain_->GetBuffer(0, IID_PPV_ARGS(&dxgi_back_buffer))); - const auto dpi = GetDpi(); // TODO! DPI awareness. + float dpi_x, dpi_y; + d2d1_device_context_->GetDpi(&dpi_x, &dpi_y); auto bitmap_properties = D2D1::BitmapProperties1( D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE), - dpi.x, dpi.y); + dpi_x, dpi_y); // Get a D2D surface from the DXGI back buffer to use as the D2D render // target. @@ -75,4 +78,4 @@ void WindowRenderTarget::CreateTargetBitmap() { d2d1_device_context_->SetTarget(target_bitmap_.Get()); } -} // namespace cru::platform::native::win +} // namespace cru::platform::graphics::win::direct diff --git a/src/win/gui/CMakeLists.txt b/src/win/gui/CMakeLists.txt new file mode 100644 index 00000000..48bed00d --- /dev/null +++ b/src/win/gui/CMakeLists.txt @@ -0,0 +1,31 @@ +set(CRU_WIN_GUI_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/win/gui) + +add_library(cru_win_gui STATIC + TimerManager.hpp + WindowManager.hpp + + Cursor.cpp + GodWindow.cpp + InputMethod.cpp + Keyboard.cpp + TimerManager.cpp + UiApplication.cpp + Window.cpp + WindowClass.cpp + WindowManager.cpp +) +target_sources(cru_win_gui PUBLIC + ${CRU_WIN_GUI_INCLUDE_DIR}/Cursor.hpp + ${CRU_WIN_GUI_INCLUDE_DIR}/Exception.hpp + ${CRU_WIN_GUI_INCLUDE_DIR}/Base.hpp + ${CRU_WIN_GUI_INCLUDE_DIR}/GodWindow.hpp + ${CRU_WIN_GUI_INCLUDE_DIR}/InputMethod.hpp + ${CRU_WIN_GUI_INCLUDE_DIR}/Keyboard.hpp + ${CRU_WIN_GUI_INCLUDE_DIR}/Resource.hpp + ${CRU_WIN_GUI_INCLUDE_DIR}/UiApplication.hpp + ${CRU_WIN_GUI_INCLUDE_DIR}/Window.hpp + ${CRU_WIN_GUI_INCLUDE_DIR}/WindowClass.hpp + ${CRU_WIN_GUI_INCLUDE_DIR}/WindowNativeMessageEventArgs.hpp +) +target_link_libraries(cru_win_gui PUBLIC imm32) +target_link_libraries(cru_win_gui PUBLIC cru_win_graphics_direct cru_platform_gui) diff --git a/src/win/native/Cursor.cpp b/src/win/gui/Cursor.cpp index 429f6e7c..80e8a749 100644 --- a/src/win/native/Cursor.cpp +++ b/src/win/gui/Cursor.cpp @@ -1,11 +1,11 @@ -#include "cru/win/native/Cursor.hpp" +#include "cru/win/gui/Cursor.hpp" #include "cru/common/Logger.hpp" -#include "cru/win/native/Exception.hpp" +#include "cru/win/gui/Exception.hpp" #include <stdexcept> -namespace cru::platform::native::win { +namespace cru::platform::gui::win { WinCursor::WinCursor(HCURSOR handle, bool auto_destroy) { handle_ = handle; auto_destroy_ = auto_destroy; @@ -35,7 +35,8 @@ WinCursor* LoadWinCursor(const wchar_t* name) { WinCursorManager::WinCursorManager() : sys_arrow_(LoadWinCursor(IDC_ARROW)), - sys_hand_(LoadWinCursor(IDC_HAND)) {} + sys_hand_(LoadWinCursor(IDC_HAND)), + sys_ibeam_(LoadWinCursor(IDC_IBEAM)) {} std::shared_ptr<WinCursor> WinCursorManager::GetSystemWinCursor( SystemCursorType type) { @@ -44,8 +45,10 @@ std::shared_ptr<WinCursor> WinCursorManager::GetSystemWinCursor( return sys_arrow_; case SystemCursorType::Hand: return sys_hand_; + case SystemCursorType::IBeam: + return sys_ibeam_; default: throw std::runtime_error("Unknown system cursor value."); } } -} // namespace cru::platform::native::win +} // namespace cru::platform::gui::win diff --git a/src/win/native/GodWindow.cpp b/src/win/gui/GodWindow.cpp index b1e7275e..7bce83a3 100644 --- a/src/win/native/GodWindow.cpp +++ b/src/win/gui/GodWindow.cpp @@ -1,13 +1,11 @@ -#include "cru/win/native/GodWindow.hpp" +#include "cru/win/gui/GodWindow.hpp" -#include "GodWindowMessage.hpp" -#include "Timer.hpp" #include "cru/common/Logger.hpp" -#include "cru/win/native/Exception.hpp" -#include "cru/win/native/UiApplication.hpp" -#include "cru/win/native/WindowClass.hpp" +#include "cru/win/gui/Exception.hpp" +#include "cru/win/gui/UiApplication.hpp" +#include "cru/win/gui/WindowClass.hpp" -namespace cru::platform::native::win { +namespace cru::platform::gui::win { constexpr auto god_window_class_name = L"GodWindowClass"; LRESULT CALLBACK GodWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, @@ -16,14 +14,14 @@ LRESULT CALLBACK GodWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, if (app) { LRESULT result; - const auto handled = app->GetGodWindow()->HandleGodWindowMessage( - hWnd, uMsg, wParam, lParam, &result); - if (handled) - return result; - else - return DefWindowProcW(hWnd, uMsg, wParam, lParam); - } else - return DefWindowProcW(hWnd, uMsg, wParam, lParam); + auto god_window = app->GetGodWindow(); + if (god_window != nullptr) { + const auto handled = god_window->HandleGodWindowMessage( + hWnd, uMsg, wParam, lParam, &result); + if (handled) return result; + } + } + return DefWindowProcW(hWnd, uMsg, wParam, lParam); } GodWindow::GodWindow(WinUiApplication* application) { @@ -51,32 +49,15 @@ GodWindow::~GodWindow() { bool GodWindow::HandleGodWindowMessage(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param, LRESULT* result) { - CRU_UNUSED(hwnd) - CRU_UNUSED(l_param) + WindowNativeMessageEventArgs args( + WindowNativeMessage{hwnd, msg, w_param, l_param}); + message_event_.Raise(args); - switch (msg) { - case invoke_later_message_id: { - const auto p_action = reinterpret_cast<std::function<void()>*>(w_param); - (*p_action)(); - delete p_action; - *result = 0; - return true; - } - case WM_TIMER: { - const auto id = static_cast<UINT_PTR>(w_param); - const auto action = application_->GetTimerManager()->GetAction(id); - if (action.has_value()) { - (action.value().second)(); - if (!action.value().first) - application_->GetTimerManager()->KillTimer(id); - result = 0; - return true; - } - break; - } - default: - return false; + if (args.IsHandled()) { + *result = args.GetResult(); + return true; } + return false; } -} // namespace cru::platform::native::win +} // namespace cru::platform::gui::win diff --git a/src/win/native/InputMethod.cpp b/src/win/gui/InputMethod.cpp index 21681de2..cc237e88 100644 --- a/src/win/native/InputMethod.cpp +++ b/src/win/gui/InputMethod.cpp @@ -1,15 +1,15 @@ -#include "cru/win/native/InputMethod.hpp" +#include "cru/win/gui/InputMethod.hpp" -#include "DpiUtil.hpp" #include "cru/common/Logger.hpp" #include "cru/common/StringUtil.hpp" #include "cru/platform/Check.hpp" +#include "cru/platform/gui/DebugFlags.hpp" #include "cru/win/Exception.hpp" -#include "cru/win/native/Window.hpp" +#include "cru/win/gui/Window.hpp" #include <vector> -namespace cru::platform::native::win { +namespace cru::platform::gui::win { AutoHIMC::AutoHIMC(HWND hwnd) : hwnd_(hwnd) { Expects(hwnd); handle_ = ::ImmGetContext(hwnd); @@ -146,36 +146,26 @@ CompositionText GetCompositionInfo(HIMC imm_context) { WinInputMethodContext::WinInputMethodContext( gsl::not_null<WinNativeWindow*> window) - : native_window_resolver_(window->GetResolver()) { - event_revoker_guards_.push_back( - EventRevokerGuard(window->NativeMessageEvent()->AddHandler( - std::bind(&WinInputMethodContext::OnWindowNativeMessage, this, - std::placeholders::_1)))); + : native_window_(window) { + event_guard_ += window->NativeMessageEvent()->AddHandler( + std::bind(&WinInputMethodContext::OnWindowNativeMessage, this, + std::placeholders::_1)); } WinInputMethodContext::~WinInputMethodContext() {} void WinInputMethodContext::EnableIME() { - const auto native_window = Resolve(native_window_resolver_.get()); - if (native_window == nullptr) return; - const auto hwnd = native_window->GetWindowHandle(); - + const auto hwnd = native_window_->GetWindowHandle(); if (::ImmAssociateContextEx(hwnd, nullptr, IACE_DEFAULT) == FALSE) { log::TagWarn(log_tag, u"Failed to enable ime."); } } void WinInputMethodContext::DisableIME() { - const auto native_window = Resolve(native_window_resolver_.get()); - if (native_window == nullptr) return; - const auto hwnd = native_window->GetWindowHandle(); - + const auto hwnd = native_window_->GetWindowHandle(); AutoHIMC himc{hwnd}; - if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) { - log::TagWarn(log_tag, - u"Failed to complete composition before disable ime."); - } + ::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0); if (::ImmAssociateContextEx(hwnd, nullptr, 0) == FALSE) { log::TagWarn(log_tag, u"Failed to disable ime."); @@ -183,42 +173,32 @@ void WinInputMethodContext::DisableIME() { } void WinInputMethodContext::CompleteComposition() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return; - auto himc = *std::move(optional_himc); - + auto himc = GetHIMC(); if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) { log::TagWarn(log_tag, u"Failed to complete composition."); } } void WinInputMethodContext::CancelComposition() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return; - auto himc = *std::move(optional_himc); - + auto himc = GetHIMC(); if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_CANCEL, 0)) { log::TagWarn(log_tag, u"Failed to complete composition."); } } CompositionText WinInputMethodContext::GetCompositionText() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return CompositionText{}; - auto himc = *std::move(optional_himc); - + auto himc = GetHIMC(); return GetCompositionInfo(himc.Get()); } void WinInputMethodContext::SetCandidateWindowPosition(const Point& point) { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return; - auto himc = *std::move(optional_himc); + auto himc = GetHIMC(); ::CANDIDATEFORM form; - form.dwIndex = 1; + form.dwIndex = 0; form.dwStyle = CFS_CANDIDATEPOS; - form.ptCurrentPos = DipToPi(point); + + form.ptCurrentPos = native_window_->DipToPixel(point); if (!::ImmSetCandidateWindow(himc.Get(), &form)) log::TagDebug(log_tag, @@ -246,7 +226,7 @@ void WinInputMethodContext::OnWindowNativeMessage( const auto& message = args.GetWindowMessage(); switch (message.msg) { case WM_CHAR: { - const auto c = static_cast<char16_t>(message.w_param); + auto c = static_cast<char16_t>(message.w_param); if (IsUtf16SurrogatePairCodeUnit(c)) { // I don't think this will happen because normal key strike without ime // should only trigger ascci character. If it is a charater from @@ -255,8 +235,12 @@ void WinInputMethodContext::OnWindowNativeMessage( u"A WM_CHAR message for character from supplementary " u"planes is ignored."); } else { - char16_t s[1] = {c}; - text_event_.Raise({s, 1}); + if (c != '\b') { // ignore backspace + if (c == '\r') c = '\n'; // Change \r to \n + + char16_t s[1] = {c}; + text_event_.Raise({s, 1}); + } } args.HandleWithResult(0); break; @@ -264,8 +248,10 @@ void WinInputMethodContext::OnWindowNativeMessage( case WM_IME_COMPOSITION: { composition_event_.Raise(nullptr); auto composition_text = GetCompositionText(); - log::TagDebug(log_tag, u"WM_IME_COMPOSITION composition text:\n{}", - composition_text); + if constexpr (DebugFlags::input_method) { + log::TagDebug(log_tag, u"WM_IME_COMPOSITION composition text:\n{}", + composition_text); + } if (message.l_param & GCS_RESULTSTR) { auto result_string = GetResultString(); text_event_.Raise(result_string); @@ -273,10 +259,16 @@ void WinInputMethodContext::OnWindowNativeMessage( break; } case WM_IME_STARTCOMPOSITION: { + if constexpr (DebugFlags::input_method) { + log::TagDebug(log_tag, u"WM_IME_STARTCOMPOSITION received."); + } composition_start_event_.Raise(nullptr); break; } case WM_IME_ENDCOMPOSITION: { + if constexpr (DebugFlags::input_method) { + log::TagDebug(log_tag, u"WM_IME_ENDCOMPOSITION received."); + } composition_end_event_.Raise(nullptr); break; } @@ -284,29 +276,13 @@ void WinInputMethodContext::OnWindowNativeMessage( } std::u16string WinInputMethodContext::GetResultString() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return u""; - auto himc = *std::move(optional_himc); - + auto himc = GetHIMC(); auto result = win::GetResultString(himc.Get()); return result; } -std::optional<AutoHIMC> WinInputMethodContext::TryGetHIMC() { - const auto native_window = Resolve(native_window_resolver_.get()); - if (native_window == nullptr) return std::nullopt; - const auto hwnd = native_window->GetWindowHandle(); +AutoHIMC WinInputMethodContext::GetHIMC() { + const auto hwnd = native_window_->GetWindowHandle(); return AutoHIMC{hwnd}; } - -WinInputMethodManager::WinInputMethodManager(WinUiApplication*) {} - -WinInputMethodManager::~WinInputMethodManager() {} - -std::unique_ptr<IInputMethodContext> WinInputMethodManager::GetContext( - INativeWindow* window) { - Expects(window); - const auto w = CheckPlatform<WinNativeWindow>(window, GetPlatformId()); - return std::make_unique<WinInputMethodContext>(w); -} -} // namespace cru::platform::native::win +} // namespace cru::platform::gui::win diff --git a/src/win/native/Keyboard.cpp b/src/win/gui/Keyboard.cpp index 929ca737..b706b240 100644 --- a/src/win/native/Keyboard.cpp +++ b/src/win/gui/Keyboard.cpp @@ -1,6 +1,6 @@ -#include "cru/win/native/Keyboard.hpp" +#include "cru/win/gui/Keyboard.hpp" -namespace cru::platform::native::win { +namespace cru::platform::gui::win { KeyCode VirtualKeyToKeyCode(int virtual_key) { if (virtual_key >= 0x30 && virtual_key <= 0x39) { return KeyCode{static_cast<int>(KeyCode::N0) + (virtual_key - 0x30)}; @@ -71,4 +71,4 @@ KeyModifier RetrieveKeyMofifier() { if (::GetKeyState(VK_MENU) < 0) result |= KeyModifiers::alt; return result; } -} // namespace cru::platform::native::win +} // namespace cru::platform::gui::win diff --git a/src/win/gui/TimerManager.cpp b/src/win/gui/TimerManager.cpp new file mode 100644 index 00000000..fc26b6c4 --- /dev/null +++ b/src/win/gui/TimerManager.cpp @@ -0,0 +1,100 @@ +#include "TimerManager.hpp" + +#include "cru/win/gui/Base.hpp" +#include "cru/win/gui/Exception.hpp" +#include "gsl/gsl_util" + +#include <functional> +#include <type_traits> + +namespace cru::platform::gui::win { +constexpr int kSetImmediateWindowMessageId = WM_USER + 2000; + +TimerManager::TimerManager(GodWindow* god_window) { + god_window_ = god_window; + event_guard_ += god_window->MessageEvent()->AddHandler(std::bind( + &TimerManager::HandleGodWindowMessage, this, std::placeholders::_1)); +} + +long long TimerManager::SetTimer(TimerType type, int period, + std::function<void()> action) { + auto id = next_id_++; + TimerInfo timer_info{id, type, type == TimerType::Immediate ? 0 : period, + std::move(action)}; + if (type == TimerType::Immediate) { + if (!::PostMessageW(god_window_->GetHandle(), kSetImmediateWindowMessageId, + gsl::narrow<UINT_PTR>(id), 0)) { + throw Win32Error( + ::GetLastError(), + "Failed to post window message to god window for set immediate."); + } + } else { + CreateNativeTimer(&timer_info); + } + + info_map_.emplace(id, std::move(timer_info)); + return id; +} + +void TimerManager::CancelTimer(long long id) { + if (id <= 0) return; + auto find_result = this->info_map_.find(id); + if (find_result != info_map_.cend()) { + auto& info = find_result->second; + KillNativeTimer(&info); + this->info_map_.erase(find_result); + } +} + +void TimerManager::CreateNativeTimer(TimerInfo* info) { + info->native_timer_id = gsl::narrow<UINT_PTR>(info->id); + ::SetTimer(god_window_->GetHandle(), info->native_timer_id, info->period, + nullptr); +} + +void TimerManager::KillNativeTimer(TimerInfo* info) { + if (info->native_timer_id == 0) return; + ::KillTimer(god_window_->GetHandle(), info->native_timer_id); + info->native_timer_id = 0; +} + +void TimerManager::HandleGodWindowMessage(WindowNativeMessageEventArgs& args) { + const auto& message = args.GetWindowMessage(); + + switch (message.msg) { + case kSetImmediateWindowMessageId: { + auto find_result = + this->info_map_.find(static_cast<long long>(message.w_param)); + if (find_result != info_map_.cend()) { + auto& info = find_result->second; + info.action(); + info_map_.erase(find_result); + } + args.SetResult(0); + args.SetHandled(true); + return; + } + case WM_TIMER: { + auto find_result = + this->info_map_.find(static_cast<long long>(message.w_param)); + if (find_result != info_map_.cend()) { + auto& info = find_result->second; + if (info.type == TimerType::Interval) { + info.action(); + args.SetResult(0); + args.SetHandled(true); + } else if (info.type == TimerType::Timeout) { + info.action(); + KillNativeTimer(&info); + info_map_.erase(find_result); + args.SetResult(0); + args.SetHandled(true); + } + } + return; + } + default: + return; + } +} +} // namespace cru::platform::gui::win diff --git a/src/win/gui/TimerManager.hpp b/src/win/gui/TimerManager.hpp new file mode 100644 index 00000000..a8db1075 --- /dev/null +++ b/src/win/gui/TimerManager.hpp @@ -0,0 +1,61 @@ +#pragma once +#include "cru/common/Event.hpp" +#include "cru/win/WinPreConfig.hpp" + +#include "cru/common/Base.hpp" +#include "cru/win/gui/GodWindow.hpp" +#include "cru/win/gui/WindowNativeMessageEventArgs.hpp" + +#include <chrono> +#include <functional> +#include <optional> +#include <unordered_map> + +namespace cru::platform::gui::win { +enum class TimerType { Immediate, Timeout, Interval }; + +struct TimerInfo { + TimerInfo(long long id, TimerType type, int period, + std::function<void()> action, UINT_PTR native_timer_id = 0) + : id(id), + type(type), + period(period), + action(std::move(action)), + native_timer_id(native_timer_id) {} + + long long id; + TimerType type; + int period; // in milliseconds + std::function<void()> action; + UINT_PTR native_timer_id; +}; + +class TimerManager : public Object { + public: + TimerManager(GodWindow* god_window); + + CRU_DELETE_COPY(TimerManager) + CRU_DELETE_MOVE(TimerManager) + + ~TimerManager() override = default; + + // Period is in milliseconds. When type is immediate, it is not checked and + // used. + long long SetTimer(TimerType type, int period, std::function<void()> action); + void CancelTimer(long long id); + + private: + void HandleGodWindowMessage(WindowNativeMessageEventArgs& args); + + void CreateNativeTimer(TimerInfo* info); + void KillNativeTimer(TimerInfo* info); + + private: + GodWindow* god_window_; + + EventRevokerListGuard event_guard_; + + long long next_id_ = 1; + std::unordered_map<long long, TimerInfo> info_map_; +}; +} // namespace cru::platform::gui::win diff --git a/src/win/native/UiApplication.cpp b/src/win/gui/UiApplication.cpp index dbf52e05..f4541dd0 100644 --- a/src/win/native/UiApplication.cpp +++ b/src/win/gui/UiApplication.cpp @@ -1,25 +1,25 @@ -#include "cru/win/native/UiApplication.hpp" +#include "cru/win/gui/UiApplication.hpp" #include "../DebugLogger.hpp" +#include "../StdOutLogger.hpp" +#include "TimerManager.hpp" +#include "WindowManager.hpp" #include "cru/common/Logger.hpp" #include "cru/platform/Check.hpp" -#include "cru/win/graph/direct/Factory.hpp" -#include "cru/win/native/Cursor.hpp" -#include "cru/win/native/Exception.hpp" -#include "cru/win/native/GodWindow.hpp" -#include "cru/win/native/InputMethod.hpp" -#include "cru/win/native/Window.hpp" -#include "GodWindowMessage.hpp" -#include "Timer.hpp" -#include "WindowManager.hpp" - -namespace cru::platform::native { +#include "cru/win/graphics/direct/Factory.hpp" +#include "cru/win/gui/Cursor.hpp" +#include "cru/win/gui/Exception.hpp" +#include "cru/win/gui/GodWindow.hpp" +#include "cru/win/gui/InputMethod.hpp" +#include "cru/win/gui/Window.hpp" + +namespace cru::platform::gui { std::unique_ptr<IUiApplication> CreateUiApplication() { return std::make_unique<win::WinUiApplication>(); } -} // namespace cru::platform::native +} // namespace cru::platform::gui -namespace cru::platform::native::win { +namespace cru::platform::gui::win { WinUiApplication* WinUiApplication::instance = nullptr; WinUiApplication::WinUiApplication() { @@ -29,17 +29,20 @@ WinUiApplication::WinUiApplication() { if (!instance_handle_) throw Win32Error("Failed to get module(instance) handle."); + ::SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); + log::Logger::GetInstance()->AddSource( std::make_unique<::cru::platform::win::WinDebugLoggerSource>()); + log::Logger::GetInstance()->AddSource( + std::make_unique<::cru::platform::win::WinStdOutLoggerSource>()); - graph_factory_ = - std::make_unique<cru::platform::graph::win::direct::DirectGraphFactory>(); + graph_factory_ = std::make_unique< + cru::platform::graphics::win::direct::DirectGraphFactory>(); god_window_ = std::make_unique<GodWindow>(this); timer_manager_ = std::make_unique<TimerManager>(god_window_.get()); window_manager_ = std::make_unique<WindowManager>(this); cursor_manager_ = std::make_unique<WinCursorManager>(); - input_method_manager_ = std::make_unique<WinInputMethodManager>(this); } WinUiApplication::~WinUiApplication() { instance = nullptr; } @@ -64,30 +67,27 @@ void WinUiApplication::AddOnQuitHandler(std::function<void()> handler) { quit_handlers_.push_back(std::move(handler)); } -void WinUiApplication::InvokeLater(std::function<void()> action) { - // copy the action to a safe place - auto p_action_copy = new std::function<void()>(std::move(action)); - - if (::PostMessageW(GetGodWindow()->GetHandle(), invoke_later_message_id, - reinterpret_cast<WPARAM>(p_action_copy), 0) == 0) - throw Win32Error(::GetLastError(), "InvokeLater failed to post message."); +long long WinUiApplication::SetImmediate(std::function<void()> action) { + return this->timer_manager_->SetTimer(TimerType::Immediate, 0, + std::move(action)); } long long WinUiApplication::SetTimeout(std::chrono::milliseconds milliseconds, std::function<void()> action) { - return gsl::narrow<long long>(timer_manager_->CreateTimer( - static_cast<UINT>(milliseconds.count()), false, std::move(action))); + return this->timer_manager_->SetTimer(TimerType::Timeout, + gsl::narrow<int>(milliseconds.count()), + std::move(action)); } long long WinUiApplication::SetInterval(std::chrono::milliseconds milliseconds, std::function<void()> action) { - return gsl::narrow<long long>(timer_manager_->CreateTimer( - static_cast<UINT>(milliseconds.count()), true, std::move(action))); + return this->timer_manager_->SetTimer(TimerType::Interval, + gsl::narrow<int>(milliseconds.count()), + std::move(action)); } void WinUiApplication::CancelTimer(long long id) { - if (id < 0) return; - timer_manager_->KillTimer(static_cast<UINT_PTR>(id)); + timer_manager_->CancelTimer(id); } std::vector<INativeWindow*> WinUiApplication::GetAllWindow() { @@ -99,26 +99,24 @@ std::vector<INativeWindow*> WinUiApplication::GetAllWindow() { return result; } -std::shared_ptr<INativeWindowResolver> WinUiApplication::CreateWindow( - INativeWindow* parent) { +INativeWindow* WinUiApplication::CreateWindow(INativeWindow* parent, + CreateWindowFlag flag) { WinNativeWindow* p = nullptr; if (parent != nullptr) { p = CheckPlatform<WinNativeWindow>(parent, GetPlatformId()); } - return (new WinNativeWindow(this, window_manager_->GetGeneralWindowClass(), - WS_OVERLAPPEDWINDOW, p)) - ->GetResolver(); + return new WinNativeWindow(this, window_manager_->GetGeneralWindowClass(), + flag & CreateWindowFlags::NoCaptionAndBorder + ? WS_POPUP + : WS_OVERLAPPEDWINDOW, + p); } -cru::platform::graph::IGraphFactory* WinUiApplication::GetGraphFactory() { +cru::platform::graphics::IGraphFactory* WinUiApplication::GetGraphFactory() { return graph_factory_.get(); } ICursorManager* WinUiApplication::GetCursorManager() { return cursor_manager_.get(); } - -IInputMethodManager* WinUiApplication::GetInputMethodManager() { - return input_method_manager_.get(); -} -} // namespace cru::platform::native::win +} // namespace cru::platform::gui::win diff --git a/src/win/native/Window.cpp b/src/win/gui/Window.cpp index 81642451..efd3bfcc 100644 --- a/src/win/native/Window.cpp +++ b/src/win/gui/Window.cpp @@ -1,27 +1,27 @@ -#include "cru/win/native/Window.hpp" +#include "cru/win/gui/Window.hpp" -#include "DpiUtil.hpp" -#include "WindowD2DPainter.hpp" #include "WindowManager.hpp" #include "cru/common/Logger.hpp" #include "cru/platform/Check.hpp" -#include "cru/win/native/Cursor.hpp" -#include "cru/win/native/Exception.hpp" -#include "cru/win/native/Keyboard.hpp" -#include "cru/win/native/UiApplication.hpp" -#include "cru/win/native/WindowClass.hpp" -#include "cru/win/native/WindowRenderTarget.hpp" +#include "cru/platform/gui/Base.hpp" +#include "cru/platform/gui/DebugFlags.hpp" +#include "cru/win/graphics/direct/WindowPainter.hpp" +#include "cru/win/gui/Cursor.hpp" +#include "cru/win/gui/Exception.hpp" +#include "cru/win/gui/InputMethod.hpp" +#include "cru/win/gui/Keyboard.hpp" +#include "cru/win/gui/UiApplication.hpp" +#include "cru/win/gui/WindowClass.hpp" #include <imm.h> #include <windowsx.h> +#include <memory> -namespace cru::platform::native::win { +namespace cru::platform::gui::win { WinNativeWindow::WinNativeWindow(WinUiApplication* application, WindowClass* window_class, DWORD window_style, WinNativeWindow* parent) - : application_(application), - resolver_(std::make_shared<WinNativeWindowResolver>(this)), - parent_window_(parent) { + : application_(application), parent_window_(parent) { Expects(application); // application can't be null. if (parent != nullptr) { @@ -39,13 +39,24 @@ WinNativeWindow::WinNativeWindow(WinUiApplication* application, if (hwnd_ == nullptr) throw Win32Error(::GetLastError(), "Failed to create window."); + auto dpi = ::GetDpiForWindow(hwnd_); + if (dpi == 0) + throw Win32Error(::GetLastError(), "Failed to get dpi of window."); + dpi_ = static_cast<float>(dpi); + log::Debug(u"Dpi of window is {}.", dpi_); + window_manager->RegisterWindow(hwnd_, this); SetCursor(application->GetCursorManager()->GetSystemCursor( - cru::platform::native::SystemCursorType::Arrow)); + cru::platform::gui::SystemCursorType::Arrow)); + + window_render_target_ = + std::make_unique<graphics::win::direct::D2DWindowRenderTarget>( + application->GetDirectFactory(), hwnd_); + window_render_target_->SetDpi(dpi_, dpi_); - window_render_target_ = std::make_unique<WindowRenderTarget>( - application->GetDirectFactory(), hwnd_); + input_method_context_ = std::make_unique<WinInputMethodContext>(this); + input_method_context_->DisableIME(); } WinNativeWindow::~WinNativeWindow() { @@ -53,7 +64,6 @@ WinNativeWindow::~WinNativeWindow() { sync_flag_ = true; Close(); } - resolver_->Reset(); } void WinNativeWindow::Close() { ::DestroyWindow(hwnd_); } @@ -65,7 +75,7 @@ void WinNativeWindow::SetVisible(bool is_visible) { } Size WinNativeWindow::GetClientSize() { const auto pixel_rect = GetClientRectPixel(); - return Size(PixelToDipX(pixel_rect.right), PixelToDipY(pixel_rect.bottom)); + return Size(PixelToDip(pixel_rect.right), PixelToDip(pixel_rect.bottom)); } void WinNativeWindow::SetClientSize(const Size& size) { @@ -77,8 +87,8 @@ void WinNativeWindow::SetClientSize(const Size& size) { RECT rect; rect.left = 0; rect.top = 0; - rect.right = DipToPixelX(size.width); - rect.bottom = DipToPixelY(size.height); + rect.right = DipToPixel(size.width); + rect.bottom = DipToPixel(size.height); if (!AdjustWindowRectEx(&rect, window_style, FALSE, window_ex_style)) throw Win32Error(::GetLastError(), "Failed to invoke AdjustWindowRectEx."); @@ -92,14 +102,14 @@ Rect WinNativeWindow::GetWindowRect() { if (!::GetWindowRect(hwnd_, &rect)) throw Win32Error(::GetLastError(), "Failed to invoke GetWindowRect."); - return Rect::FromVertices(PixelToDipX(rect.left), PixelToDipY(rect.top), - PixelToDipX(rect.right), PixelToDipY(rect.bottom)); + return Rect::FromVertices(PixelToDip(rect.left), PixelToDip(rect.top), + PixelToDip(rect.right), PixelToDip(rect.bottom)); } void WinNativeWindow::SetWindowRect(const Rect& rect) { - if (!SetWindowPos(hwnd_, nullptr, DipToPixelX(rect.left), - DipToPixelY(rect.top), DipToPixelX(rect.GetRight()), - DipToPixelY(rect.GetBottom()), SWP_NOZORDER)) + if (!SetWindowPos(hwnd_, nullptr, DipToPixel(rect.left), DipToPixel(rect.top), + DipToPixel(rect.GetRight()), DipToPixel(rect.GetBottom()), + SWP_NOZORDER)) throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos."); } @@ -109,7 +119,7 @@ Point WinNativeWindow::GetMousePosition() { throw Win32Error(::GetLastError(), "Failed to get cursor position."); if (!::ScreenToClient(hwnd_, &p)) throw Win32Error(::GetLastError(), "Failed to call ScreenToClient."); - return PiToDip(p); + return PixelToDip(p); } bool WinNativeWindow::CaptureMouse() { @@ -123,15 +133,18 @@ bool WinNativeWindow::ReleaseMouse() { } void WinNativeWindow::RequestRepaint() { - log::TagDebug(log_tag, u"A repaint is requested."); + if constexpr (DebugFlags::paint) { + log::TagDebug(log_tag, u"A repaint is requested."); + } if (!::InvalidateRect(hwnd_, nullptr, FALSE)) throw Win32Error(::GetLastError(), "Failed to invalidate window."); if (!::UpdateWindow(hwnd_)) throw Win32Error(::GetLastError(), "Failed to update window."); } -std::unique_ptr<graph::IPainter> WinNativeWindow::BeginPaint() { - return std::make_unique<WindowD2DPainter>(window_render_target_.get()); +std::unique_ptr<graphics::IPainter> WinNativeWindow::BeginPaint() { + return std::make_unique<graphics::win::direct::D2DWindowPainter>( + window_render_target_.get()); } void WinNativeWindow::SetCursor(std::shared_ptr<ICursor> cursor) { @@ -190,6 +203,10 @@ void WinNativeWindow::SetCursor(std::shared_ptr<ICursor> cursor) { } } +IInputMethodContext* WinNativeWindow::GetInputMethodContext() { + return static_cast<IInputMethodContext*>(input_method_context_.get()); +} + bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param, LRESULT* result) { @@ -229,7 +246,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg, POINT point; point.x = GET_X_LPARAM(l_param); point.y = GET_Y_LPARAM(l_param); - OnMouseDownInternal(platform::native::mouse_buttons::left, point); + OnMouseDownInternal(platform::gui::mouse_buttons::left, point); *result = 0; return true; } @@ -237,7 +254,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg, POINT point; point.x = GET_X_LPARAM(l_param); point.y = GET_Y_LPARAM(l_param); - OnMouseUpInternal(platform::native::mouse_buttons::left, point); + OnMouseUpInternal(platform::gui::mouse_buttons::left, point); *result = 0; return true; } @@ -245,7 +262,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg, POINT point; point.x = GET_X_LPARAM(l_param); point.y = GET_Y_LPARAM(l_param); - OnMouseDownInternal(platform::native::mouse_buttons::right, point); + OnMouseDownInternal(platform::gui::mouse_buttons::right, point); *result = 0; return true; } @@ -253,7 +270,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg, POINT point; point.x = GET_X_LPARAM(l_param); point.y = GET_Y_LPARAM(l_param); - OnMouseUpInternal(platform::native::mouse_buttons::right, point); + OnMouseUpInternal(platform::gui::mouse_buttons::right, point); *result = 0; return true; } @@ -261,7 +278,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg, POINT point; point.x = GET_X_LPARAM(l_param); point.y = GET_Y_LPARAM(l_param); - OnMouseDownInternal(platform::native::mouse_buttons::middle, point); + OnMouseDownInternal(platform::gui::mouse_buttons::middle, point); *result = 0; return true; } @@ -269,7 +286,7 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg, POINT point; point.x = GET_X_LPARAM(l_param); point.y = GET_Y_LPARAM(l_param); - OnMouseUpInternal(platform::native::mouse_buttons::middle, point); + OnMouseUpInternal(platform::gui::mouse_buttons::middle, point); *result = 0; return true; } @@ -328,6 +345,15 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg, case WM_IME_COMPOSITION: *result = 0; return true; + case WM_DPICHANGED: { + dpi_ = static_cast<float>(LOWORD(w_param)); + const RECT* suggest_rect = reinterpret_cast<const RECT*>(l_param); + window_render_target_->SetDpi(dpi_, dpi_); + SetWindowPos(hwnd_, NULL, suggest_rect->left, suggest_rect->top, + suggest_rect->right - suggest_rect->left, + suggest_rect->bottom - suggest_rect->top, + SWP_NOZORDER | SWP_NOACTIVATE); + } default: return false; } @@ -341,9 +367,9 @@ RECT WinNativeWindow::GetClientRectPixel() { } void WinNativeWindow::OnDestroyInternal() { + destroy_event_.Raise(nullptr); application_->GetWindowManager()->UnregisterWindow(hwnd_); hwnd_ = nullptr; - destroy_event_.Raise(nullptr); if (!sync_flag_) { sync_flag_ = true; delete this; @@ -353,14 +379,16 @@ void WinNativeWindow::OnDestroyInternal() { void WinNativeWindow::OnPaintInternal() { paint_event_.Raise(nullptr); ValidateRect(hwnd_, nullptr); - log::TagDebug(log_tag, u"A repaint is finished."); + if constexpr (DebugFlags::paint) { + log::TagDebug(log_tag, u"A repaint is finished."); + } } void WinNativeWindow::OnResizeInternal(const int new_width, const int new_height) { if (!(new_width == 0 && new_height == 0)) { window_render_target_->ResizeBuffer(new_width, new_height); - resize_event_.Raise(Size{PixelToDipX(new_width), PixelToDipY(new_height)}); + resize_event_.Raise(Size{PixelToDip(new_width), PixelToDip(new_height)}); } } @@ -389,7 +417,7 @@ void WinNativeWindow::OnMouseMoveInternal(const POINT point) { mouse_enter_leave_event_.Raise(MouseEnterLeaveType::Enter); } - mouse_move_event_.Raise(PiToDip(point)); + mouse_move_event_.Raise(PixelToDip(point)); } void WinNativeWindow::OnMouseLeaveInternal() { @@ -397,15 +425,15 @@ void WinNativeWindow::OnMouseLeaveInternal() { mouse_enter_leave_event_.Raise(MouseEnterLeaveType::Leave); } -void WinNativeWindow::OnMouseDownInternal(platform::native::MouseButton button, +void WinNativeWindow::OnMouseDownInternal(platform::gui::MouseButton button, POINT point) { - const auto dip_point = PiToDip(point); + const auto dip_point = PixelToDip(point); mouse_down_event_.Raise({button, dip_point, RetrieveKeyMofifier()}); } -void WinNativeWindow::OnMouseUpInternal(platform::native::MouseButton button, +void WinNativeWindow::OnMouseUpInternal(platform::gui::MouseButton button, POINT point) { - const auto dip_point = PiToDip(point); + const auto dip_point = PixelToDip(point); mouse_up_event_.Raise({button, dip_point, RetrieveKeyMofifier()}); } @@ -427,16 +455,4 @@ void WinNativeWindow::OnKeyUpInternal(int virtual_code) { void WinNativeWindow::OnActivatedInternal() {} void WinNativeWindow::OnDeactivatedInternal() {} - -void WinNativeWindowResolver::Reset() { - Expects(window_); // already reset, can't reset again - window_ = nullptr; -} - -WinNativeWindow* Resolve(gsl::not_null<INativeWindowResolver*> resolver) { - const auto window = resolver->Resolve(); - return window == nullptr ? nullptr - : CheckPlatform<WinNativeWindow>( - window, WinNativeResource::k_platform_id); -} // namespace cru::platform::native::win -} // namespace cru::platform::native::win +} // namespace cru::platform::gui::win diff --git a/src/win/native/WindowClass.cpp b/src/win/gui/WindowClass.cpp index 2e74606e..a033d091 100644 --- a/src/win/native/WindowClass.cpp +++ b/src/win/gui/WindowClass.cpp @@ -1,8 +1,8 @@ -#include "cru/win/native/WindowClass.hpp" +#include "cru/win/gui/WindowClass.hpp" -#include "cru/win/native/Exception.hpp" +#include "cru/win/gui/Exception.hpp" -namespace cru::platform::native::win { +namespace cru::platform::gui::win { WindowClass::WindowClass(std::wstring name, WNDPROC window_proc, HINSTANCE h_instance) : name_(std::move(name)) { @@ -25,4 +25,4 @@ WindowClass::WindowClass(std::wstring name, WNDPROC window_proc, if (atom_ == 0) throw Win32Error(::GetLastError(), "Failed to create window class."); } -} // namespace cru::platform::native::win +} // namespace cru::platform::gui::win diff --git a/src/win/native/WindowManager.cpp b/src/win/gui/WindowManager.cpp index 56cc8981..4e84e967 100644 --- a/src/win/native/WindowManager.cpp +++ b/src/win/gui/WindowManager.cpp @@ -1,10 +1,10 @@ #include "WindowManager.hpp" -#include "cru/win/native/UiApplication.hpp" -#include "cru/win/native/Window.hpp" -#include "cru/win/native/WindowClass.hpp" +#include "cru/win/gui/UiApplication.hpp" +#include "cru/win/gui/Window.hpp" +#include "cru/win/gui/WindowClass.hpp" -namespace cru::platform::native::win { +namespace cru::platform::gui::win { LRESULT __stdcall GeneralWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { auto window = @@ -53,4 +53,4 @@ std::vector<WinNativeWindow*> WindowManager::GetAllWindows() const { for (const auto& [key, value] : window_map_) windows.push_back(value); return windows; } -} // namespace cru::platform::native::win +} // namespace cru::platform::gui::win diff --git a/src/win/native/WindowManager.hpp b/src/win/gui/WindowManager.hpp index 3f6387f7..3b037f89 100644 --- a/src/win/native/WindowManager.hpp +++ b/src/win/gui/WindowManager.hpp @@ -7,7 +7,7 @@ #include <memory> #include <vector> -namespace cru::platform::native::win { +namespace cru::platform::gui::win { class WinUiApplication; class WinNativeWindow; class WindowClass; @@ -48,4 +48,4 @@ class WindowManager : public Object { std::unique_ptr<WindowClass> general_window_class_; std::map<HWND, WinNativeWindow*> window_map_; }; -} // namespace cru::platform::native::win +} // namespace cru::platform::gui::win diff --git a/src/win/native/CMakeLists.txt b/src/win/native/CMakeLists.txt deleted file mode 100644 index f1b167d2..00000000 --- a/src/win/native/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -set(CRU_WIN_NATIVE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/win/native) - -add_library(cru_win_native STATIC - DpiUtil.hpp - GodWindowMessage.hpp - Timer.hpp - WindowD2DPainter.hpp - WindowManager.hpp - - Cursor.cpp - GodWindow.cpp - InputMethod.cpp - Keyboard.cpp - Timer.cpp - UiApplication.cpp - Window.cpp - WindowClass.cpp - WindowD2DPainter.cpp - WindowManager.cpp - WindowRenderTarget.cpp -) -target_sources(cru_win_native PUBLIC - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Cursor.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Exception.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Base.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/GodWindow.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/InputMethod.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Keyboard.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Resource.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/UiApplication.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Window.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/WindowClass.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/WindowNativeMessageEventArgs.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/WindowRenderTarget.hpp -) -target_link_libraries(cru_win_native PUBLIC imm32) -target_link_libraries(cru_win_native PUBLIC cru_win_graph_direct cru_platform_native) diff --git a/src/win/native/DpiUtil.hpp b/src/win/native/DpiUtil.hpp deleted file mode 100644 index 16ffda25..00000000 --- a/src/win/native/DpiUtil.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include "cru/platform/native/Base.hpp" - -// The dpi awareness needs to be implemented in the future. Currently we use 96 -// as default. - -namespace cru::platform::native::win { -inline platform::native::Dpi GetDpi() { - return platform::native::Dpi{96.0f, 96.0f}; -} - -inline int DipToPixelInternal(const float dip, const float dpi) { - return static_cast<int>(dip * dpi / 96.0f); -} - -inline int DipToPixelX(const float dip_x) { - return DipToPixelInternal(dip_x, GetDpi().x); -} - -inline int DipToPixelY(const float dip_y) { - return DipToPixelInternal(dip_y, GetDpi().y); -} - -inline float DipToPixelInternal(const int pixel, const float dpi) { - return static_cast<float>(pixel) * 96.0f / dpi; -} - -inline float PixelToDipX(const int pixel_x) { - return DipToPixelInternal(pixel_x, GetDpi().x); -} - -inline float PixelToDipY(const int pixel_y) { - return DipToPixelInternal(pixel_y, GetDpi().y); -} - -inline Point PiToDip(const POINT& pi_point) { - return Point(PixelToDipX(pi_point.x), PixelToDipY(pi_point.y)); -} - -inline POINT DipToPi(const Point& dip_point) { - POINT result; - result.x = DipToPixelX(dip_point.x); - result.y = DipToPixelY(dip_point.y); - return result; -} -} // namespace cru::platform::native::win diff --git a/src/win/native/GodWindowMessage.hpp b/src/win/native/GodWindowMessage.hpp deleted file mode 100644 index 9063cb4d..00000000 --- a/src/win/native/GodWindowMessage.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "cru/win/WinPreConfig.hpp" - -namespace cru::platform::native::win { -constexpr int invoke_later_message_id = WM_USER + 2000; -} diff --git a/src/win/native/Timer.cpp b/src/win/native/Timer.cpp deleted file mode 100644 index 662067fb..00000000 --- a/src/win/native/Timer.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "Timer.hpp" - -namespace cru::platform::native::win { -TimerManager::TimerManager(GodWindow* god_window) { god_window_ = god_window; } - -UINT_PTR TimerManager::CreateTimer(const UINT milliseconds, const bool loop, - TimerAction action) { - const auto id = current_count_++; - ::SetTimer(god_window_->GetHandle(), id, milliseconds, nullptr); - map_.emplace(id, std::make_pair(loop, std::move(action))); - return id; -} - -void TimerManager::KillTimer(const UINT_PTR id) { - const auto find_result = map_.find(id); - if (find_result != map_.cend()) { - ::KillTimer(god_window_->GetHandle(), id); - map_.erase(find_result); - } -} - -std::optional<std::pair<bool, TimerAction>> TimerManager::GetAction( - const UINT_PTR id) { - const auto find_result = map_.find(id); - if (find_result == map_.cend()) return std::nullopt; - return find_result->second; -} -} // namespace cru::platform::native::win diff --git a/src/win/native/Timer.hpp b/src/win/native/Timer.hpp deleted file mode 100644 index 95f186a1..00000000 --- a/src/win/native/Timer.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include "cru/win/WinPreConfig.hpp" - -#include "cru/common/Base.hpp" -#include "cru/win/native/GodWindow.hpp" - -#include <chrono> -#include <functional> -#include <map> -#include <optional> - -namespace cru::platform::native::win { -using TimerAction = std::function<void()>; - -class TimerManager : public Object { - public: - TimerManager(GodWindow* god_window); - - CRU_DELETE_COPY(TimerManager) - CRU_DELETE_MOVE(TimerManager) - - ~TimerManager() override = default; - - UINT_PTR CreateTimer(UINT milliseconds, bool loop, TimerAction action); - void KillTimer(UINT_PTR id); - std::optional<std::pair<bool, TimerAction>> GetAction(UINT_PTR id); - - private: - GodWindow* god_window_; - - std::map<UINT_PTR, std::pair<bool, TimerAction>> map_{}; - UINT_PTR current_count_ = 0; -}; -} // namespace cru::platform::native::win diff --git a/src/win/native/WindowD2DPainter.cpp b/src/win/native/WindowD2DPainter.cpp deleted file mode 100644 index 7a97480b..00000000 --- a/src/win/native/WindowD2DPainter.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "WindowD2DPainter.hpp" - -#include "cru/win/graph/direct/Exception.hpp" -#include "cru/win/graph/direct/Factory.hpp" -#include "cru/win/native/WindowRenderTarget.hpp" - -namespace cru::platform::native::win { -using namespace cru::platform::graph::win::direct; - -WindowD2DPainter::WindowD2DPainter(WindowRenderTarget* render_target) - : D2DPainter(render_target->GetD2D1DeviceContext()), - render_target_(render_target) { - render_target_->GetD2D1DeviceContext()->BeginDraw(); -} - -WindowD2DPainter::~WindowD2DPainter() { EndDraw(); } - -void WindowD2DPainter::DoEndDraw() { - ThrowIfFailed(render_target_->GetD2D1DeviceContext()->EndDraw()); - render_target_->Present(); -} -} // namespace cru::platform::native::win diff --git a/src/win/native/WindowD2DPainter.hpp b/src/win/native/WindowD2DPainter.hpp deleted file mode 100644 index a638b77a..00000000 --- a/src/win/native/WindowD2DPainter.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include "cru/win/graph/direct/Painter.hpp" -#include "cru/win/native/WindowRenderTarget.hpp" - -namespace cru::platform::native::win { -class WindowD2DPainter : public graph::win::direct::D2DPainter { - public: - explicit WindowD2DPainter(WindowRenderTarget* window); - - CRU_DELETE_COPY(WindowD2DPainter) - CRU_DELETE_MOVE(WindowD2DPainter) - - ~WindowD2DPainter() override; - - protected: - void DoEndDraw() override; - - private: - WindowRenderTarget* render_target_; -}; -} // namespace cru::platform::native::win |