From 8ea56cbd30deb1d9a3ee5d1b5bacac1677cc4e0c Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 16 Jun 2026 13:16:19 +0200 Subject: [PATCH] Extract UI state and Win32 window shell --- cmake/PanoPainterSources.cmake | 3 + docs/modernization/roadmap.md | 22 +- docs/modernization/tasks.md | 17 +- src/app_layout.cpp | 319 ------------------ src/app_layout_ui_state.cpp | 216 ++++++++++++ src/keymap.h | 8 +- src/main.cpp | 276 +-------------- src/node_stroke_preview.cpp | 142 ++++---- src/node_stroke_preview.h | 9 + .../windows_bootstrap_helpers.cpp | 5 +- src/platform_windows/windows_window_shell.cpp | 247 ++++++++++++++ src/platform_windows/windows_window_shell.h | 25 ++ 12 files changed, 619 insertions(+), 670 deletions(-) create mode 100644 src/app_layout_ui_state.cpp create mode 100644 src/platform_windows/windows_window_shell.cpp create mode 100644 src/platform_windows/windows_window_shell.h diff --git a/cmake/PanoPainterSources.cmake b/cmake/PanoPainterSources.cmake index 607318b8..277641be 100644 --- a/cmake/PanoPainterSources.cmake +++ b/cmake/PanoPainterSources.cmake @@ -97,6 +97,7 @@ set(PP_PANOPAINTER_APP_SOURCES src/app_dialogs_info_openers.cpp src/app_events.cpp src/app_layout.cpp + src/app_layout_ui_state.cpp src/app_layout_sidebar.cpp src/app_layout_main_toolbar.cpp src/app_layout_edit_menu.cpp @@ -177,6 +178,8 @@ set(PP_WINDOWS_PLATFORM_SOURCES src/platform_windows/windows_splash.h src/platform_windows/windows_stylus_input.cpp src/platform_windows/windows_stylus_input.h + src/platform_windows/windows_window_shell.cpp + src/platform_windows/windows_window_shell.h ) set(PP_WINDOWS_APP_SOURCES diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 77e66544..ea85fb62 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -80,12 +80,12 @@ What is still carrying too much live ownership: Current hotspot files: - `src/canvas.cpp`: 2645 lines -- `src/app_layout.cpp`: 717 lines +- `src/app_layout.cpp`: 353 lines - `src/canvas_modes.cpp`: 1798 lines - `src/node.cpp`: 1594 lines -- `src/main.cpp`: 847 lines +- `src/main.cpp`: 487 lines - `src/node_panel_brush.cpp`: 1197 lines -- `src/node_stroke_preview.cpp`: 948 lines +- `src/node_stroke_preview.cpp`: 890 lines - `src/node_canvas.cpp`: 910 lines - `src/app.cpp`: 502 lines - `src/app_dialogs.cpp`: 142 lines @@ -144,7 +144,10 @@ Current architecture mismatches that must be treated as real blockers: now also lives in `src/app_layout_main_toolbar.cpp` and `App::init_toolbar_main()` is now a thin call-through, while edit-menu binding now also lives in `src/app_layout_edit_menu.cpp` and - `App::init_menu_edit()` is now a thin call-through, while the + `App::init_menu_edit()` is now a thin call-through, while UI-direction and + persisted floating/docked panel-state ownership now also live in + `src/app_layout_ui_state.cpp`, and `src/app_layout.cpp` is now mostly + layout/bootstrap composition, while the informational overlay opener family now also lives in `src/app_dialogs_info_openers.cpp` and the corresponding `App::dialog_*` entrypoints are thinner, while the export/video/PPBR dialog family now also @@ -192,8 +195,10 @@ Current architecture mismatches that must be treated as real blockers: `src/platform_windows/windows_bootstrap_helpers.*` for runtime-data discovery, startup-state initialization, window creation, pixel-format setup, GL loader init, runtime-info logging, and core-context upgrade - sequencing, which materially thins `src/main.cpp` even though broader window - procedure and retained shell flow still remain there, + sequencing, while the Win32 window procedure and retained message-handling + shell now also live in `src/platform_windows/windows_window_shell.*` + instead of `src/main.cpp`, which materially thins `src/main.cpp` even + though broader entrypoint/runtime composition still remains there, while `App::rec_loop()` now delegates worker-iteration orchestration into the retained recording bridge, `App::update_rec_frames()` now delegates recording label refresh through that same retained recording path, and the @@ -212,7 +217,10 @@ Current architecture mismatches that must be treated as real blockers: still owns worker-side readback flow and encoder-state label reads, while the main live-pass request assembly and framebuffer-copy setup now also route through `src/legacy_node_stroke_preview_execution_services.h`, even though - broader preview-pass orchestration still lives in `src/node_stroke_preview.cpp`, while + broader preview-pass orchestration still lives in + `src/node_stroke_preview.cpp`, while the immediate preview pass-sequencing + family inside `draw_stroke_immediate()` now also routes through + `NodeStrokePreview::execute_stroke_draw_immediate_pass_sequence(...)`, while `Node` child attach/detach/reorder operations now route through named local helpers in `src/node.cpp`, which makes the scene-graph mutation paths easier to reason about without yet reducing the file or moving ownership into diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 85ee1b95..0e663fa8 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -153,6 +153,11 @@ Current slice: `legacy_node_stroke_preview_execution_services.h`, which trims another coherent pass-setup block from `src/node_stroke_preview.cpp`, but broader preview-pass orchestration is still inline. +- `NodeStrokePreview::draw_stroke_immediate()` immediate preview pass + sequencing now also routes through the private + `execute_stroke_draw_immediate_pass_sequence(...)` helper, which removes + another live orchestration block from the node even though worker/readback + flow still remains in the file. - `NodeCanvas` merged-path per-plane merged-texture draw execution now also routes through `execute_legacy_canvas_draw_merge_layer_texture(...)`. - `NodeCanvas` merged-path and non-blend checkerboard background setup now also @@ -298,7 +303,7 @@ targets look like helpers under one old monolith. Status: In Progress Why now: -`src/app_layout.cpp` is still a 717-line mixed file that builds menus, +`src/app_layout.cpp` is still a 353-line mixed file that builds menus, attaches callbacks, computes planner inputs, and mutates UI state directly. Current slice: @@ -325,6 +330,9 @@ Current slice: `App::init_menu_edit()` is now a thin call-through, but draw-toolbar, brush-refresh, and broader layout composition are still inline in `src/app_layout.cpp`. +- UI-direction plus persisted floating/docked panel-state ownership now also + lives in `src/app_layout_ui_state.cpp`, and `src/app_layout.cpp` is down to + the remaining draw-toolbar, brush-refresh, and layout/bootstrap composition. Write scope: - `src/app_layout.cpp` @@ -489,8 +497,11 @@ Current slice: `src/platform_windows/windows_bootstrap_helpers.*` for runtime-data discovery, startup-state initialization, window creation, pixel-format setup, GL loader init, runtime-info logging, and core-context upgrade - sequencing, which materially thins `src/main.cpp`, but the retained Win32 - window procedure and broader shell flow are still open + sequencing +- the Win32 window procedure and retained message-handling shell now also live + in `src/platform_windows/windows_window_shell.*` instead of `src/main.cpp`, + which materially thins the entry file even though broader runtime/entrypoint + composition is still open - prepared-file background work now runs through an `AppRuntime`-owned worker queue instead of a retained static worker in `src/app_events.cpp` - canvas async import/export/save/open background work now also runs through an diff --git a/src/app_layout.cpp b/src/app_layout.cpp index 7ee654c4..6cf2e0ac 100644 --- a/src/app_layout.cpp +++ b/src/app_layout.cpp @@ -21,8 +21,6 @@ #include "legacy_canvas_tool_services.h" #include "legacy_document_layer_services.h" #include "legacy_preference_storage.h" -#include "legacy_ui_overlay_services.h" -#include "serializer.h" #include "font.h" #include "node_remote_page.h" #include "node_shorcuts.h" @@ -398,320 +396,3 @@ void App::set_ui_scale(float scale) pp::panopainter::save_legacy_ui_scale_preference(plan.scale); App::I->title_update(); } - -void App::set_ui_rtl(bool rtl) -{ - const auto plan = pp::app::plan_interface_direction(rtl); - ui_rtl = plan.direction == pp::app::InterfaceDirection::right_to_left; - layout[main_id]->find("central-row")->SetRTL( - ui_rtl ? YGDirectionRTL : YGDirectionLTR); -} - -bool App::get_ui_rtl() const -{ - return ui_rtl; -} - -void App::ui_save() -{ - Serializer::Descriptor d; - d.class_id = "ui-state"; - - Serializer::List list_floatings; - for (auto const& c : layout[main_id]->find("floatings")->m_children) - { - if (auto const& f = std::dynamic_pointer_cast(c)) - { - auto fd = list_floatings.add(); - fd->class_id = "ui-flt"; - fd->set("pos", Serializer::Vec2(f->GetPosition())); - fd->set("size", Serializer::Vec2(f->m_size)); - fd->set("class", Serializer::Integer((int)f->m_class)); - fd->set("title", Serializer::CString(f->m_title->m_text)); - } - } - d.set("floatings", list_floatings); - - Serializer::List list_drop_left; - for (auto const& c : layout[main_id]->find("drop-left")->m_children) - { - if (auto const& f = std::dynamic_pointer_cast(c)) - { - auto fd = list_drop_left.add(); - fd->class_id = "ui-dpl"; - fd->set("size", Serializer::Vec2(f->m_size)); - fd->set("class", Serializer::Integer((int)f->m_class)); - fd->set("title", Serializer::CString(f->m_title->m_text)); - } - } - d.set("drop-left", list_drop_left); - - Serializer::List list_drop_right; - for (auto const& c : layout[main_id]->find("drop-right")->m_children) - { - if (auto const& f = std::dynamic_pointer_cast(c)) - { - auto fd = list_drop_right.add(); - fd->class_id = "ui-dpr"; - fd->set("size", Serializer::Vec2(f->m_size)); - fd->set("class", Serializer::Integer((int)f->m_class)); - fd->set("title", Serializer::CString(f->m_title->m_text)); - } - } - d.set("drop-right", list_drop_right); - - pp::panopainter::set_legacy_ui_state_preferences(d, ui_rtl); - save_platform_ui_state(); - - pp::panopainter::save_legacy_preferences(); -} - -void App::ui_restore() -{ - const auto preferences = pp::panopainter::read_legacy_ui_preferences(); - if (preferences.has_rtl) - set_ui_rtl(preferences.rtl); - - if (!preferences.state) - return; - - auto floatings = layout[main_id]->find_ref("floatings"); - auto drop_left = layout[main_id]->find_ref("drop-left"); - auto drop_right = layout[main_id]->find_ref("drop-right"); - auto d = preferences.state; - for (auto const& l : d->get("floatings")->items) - { - auto ld = std::static_pointer_cast(l); - auto pos = ld->value("pos"); - auto size = ld->value("size"); - auto cls = static_cast(ld->value("class")); - auto f = floatings->add_child(); - std::string title = "Floating Panel"; - ld->value("title", title); - f->m_title->set_text(title.c_str()); - switch (cls) - { - case NodePanelFloating::kClass::Presets: - { - floating_presets = f->m_container->add_child_ref(); - floating_presets->SetHeightP(100); - //floating_presets->find("toolbar")->destroy(); - floating_presets->on_brush_changed = [this](Node* target, std::shared_ptr& b) { - apply_brush_preset_plan(*this, b); - }; - break; - } - case NodePanelFloating::kClass::Color: - { - floating_color = f->m_container->add_child_ref(); - floating_color->SetHeightP(100); - floating_color->find("title")->SetVisibility(false); - floating_color->on_color_changed = [this](Node* target, glm::vec4 color) { - apply_brush_color_plan(*this, color, false, false); - }; - break; - } - case NodePanelFloating::kClass::ColorAdv: - { - floating_picker = f->m_container->add_child_ref(); - floating_picker->m_autohide = false; - floating_picker->on_color_change = [this](Node* target, glm::vec3 color) { - apply_brush_color_plan(*this, glm::vec4(color, 1.f), false, false); - }; - break; - } - case NodePanelFloating::kClass::Layers: - f->m_container->add_child(layers); - f->SetMinHeight(100); - f->SetHeight(300); - layers->find("title")->SetVisibility(false); - layers->SetPositioning(YGPositionTypeRelative); - layers->SetPosition(0, 0); - layers->SetWidthP(100); - layers->SetHeightP(100); - layers->SetFlexShrink(0); - break; - case NodePanelFloating::kClass::Brush: - f->m_container->add_child(stroke); - stroke->find("title")->SetVisibility(false); - stroke->SetPositioning(YGPositionTypeRelative); - stroke->SetPosition(0, 0); - stroke->SetWidthP(100); - stroke->SetHeightP(100); - break; - case NodePanelFloating::kClass::Grids: - f->m_container->add_child(grid); - grid->find("title")->SetVisibility(false); - grid->SetPositioning(YGPositionTypeRelative); - grid->SetPosition(0, 0); - grid->SetWidthP(100); - grid->SetHeightP(100); - break; - case NodePanelFloating::kClass::Animation: - f->m_container->add_child(animation); - f->m_droppable = false; - //grid->find("title")->SetVisibility(false); - animation->SetPositioning(YGPositionTypeRelative); - animation->SetPosition(0, 0); - animation->SetWidthP(100); - animation->SetHeightP(100); - break; - case NodePanelFloating::kClass::Generic: - default: - f->m_container->add_child(); - break; - } - f->m_class = cls; - f->SetSize(size); - f->SetPosition(pos); - f->SetPositioning(YGPositionTypeAbsolute); - } - - for (auto const& l : d->get("drop-left")->items) - { - auto ld = std::static_pointer_cast(l); - auto size = ld->value("size"); - auto cls = static_cast(ld->value("class")); - auto f = drop_left->add_child(); - std::string title = "Floating Panel"; - ld->value("title", title); - f->m_title->set_text(title.c_str()); - switch (cls) - { - case NodePanelFloating::kClass::Presets: - { - auto floating_presets = f->m_container->add_child(); - floating_presets->SetHeightP(100); - //floating_presets->find("toolbar")->destroy(); - floating_presets->on_brush_changed = [this](Node* target, std::shared_ptr& b) { - apply_brush_preset_plan(*this, b); - }; - break; - } - case NodePanelFloating::kClass::Color: - { - auto floating_color = f->m_container->add_child(); - floating_color->SetHeightP(100); - pp::panopainter::destroy_legacy_node(*floating_color->find("title")); - floating_color->on_color_changed = [this](Node* target, glm::vec4 color) { - apply_brush_color_plan(*this, color, false, false); - }; - break; - } - case NodePanelFloating::kClass::ColorAdv: - { - floating_picker = f->m_container->add_child_ref(); - floating_picker->m_autohide = false; - floating_picker->on_color_change = [this](Node* target, glm::vec3 color) { - apply_brush_color_plan(*this, glm::vec4(color, 1.f), false, false); - }; - break; - } - case NodePanelFloating::kClass::Layers: - f->m_container->add_child(layers); - layers->SetPositioning(YGPositionTypeRelative); - layers->SetPosition(0, 0); - layers->SetWidthP(100); - layers->SetHeightP(100); - layers->SetFlexShrink(0); - break; - case NodePanelFloating::kClass::Brush: - f->m_container->add_child(stroke); - stroke->SetPositioning(YGPositionTypeRelative); - stroke->SetPosition(0, 0); - stroke->SetWidthP(100); - stroke->SetHeightP(100); - break; - case NodePanelFloating::kClass::Grids: - f->m_container->add_child(grid); - grid->SetPositioning(YGPositionTypeRelative); - grid->SetPosition(0, 0); - grid->SetWidthP(100); - grid->SetHeightP(100); - break; - case NodePanelFloating::kClass::Generic: - default: - f->m_container->add_child(); - break; - } - f->m_class = cls; - f->m_dock = drop_left; - f->SetPositioning(YGPositionTypeRelative); - f->SetPosition(0, 0); - f->SetSize(size); - } - - for (auto const& l : d->get("drop-right")->items) - { - auto ld = std::static_pointer_cast(l); - auto size = ld->value("size"); - auto cls = static_cast(ld->value("class")); - auto f = drop_right->add_child(); - std::string title = "Floating Panel"; - ld->value("title", title); - f->m_title->set_text(title.c_str()); - switch (cls) - { - case NodePanelFloating::kClass::Presets: - { - auto floating_presets = f->m_container->add_child(); - floating_presets->SetHeightP(100); - //floating_presets->find("toolbar")->destroy(); - floating_presets->on_brush_changed = [this](Node* target, std::shared_ptr& b) { - apply_brush_preset_plan(*this, b); - }; - break; - } - case NodePanelFloating::kClass::Color: - { - auto floating_color = f->m_container->add_child(); - floating_color->SetHeightP(100); - pp::panopainter::destroy_legacy_node(*floating_color->find("title")); - floating_color->on_color_changed = [this](Node* target, glm::vec4 color) { - apply_brush_color_plan(*this, color, false, false); - }; - break; - } - case NodePanelFloating::kClass::ColorAdv: - { - floating_picker = f->m_container->add_child_ref(); - floating_picker->m_autohide = false; - floating_picker->on_color_change = [this](Node* target, glm::vec3 color) { - apply_brush_color_plan(*this, glm::vec4(color, 1.f), false, false); - }; - break; - } - case NodePanelFloating::kClass::Layers: - f->m_container->add_child(layers); - layers->SetPositioning(YGPositionTypeRelative); - layers->SetPosition(0, 0); - layers->SetWidthP(100); - layers->SetHeightP(100); - layers->SetFlexShrink(0); - break; - case NodePanelFloating::kClass::Brush: - f->m_container->add_child(stroke); - stroke->SetPositioning(YGPositionTypeRelative); - stroke->SetPosition(0, 0); - stroke->SetWidthP(100); - stroke->SetHeightP(100); - break; - case NodePanelFloating::kClass::Grids: - f->m_container->add_child(grid); - grid->SetPositioning(YGPositionTypeRelative); - grid->SetPosition(0, 0); - grid->SetWidthP(100); - grid->SetHeightP(100); - break; - case NodePanelFloating::kClass::Generic: - default: - f->m_container->add_child(); - break; - } - f->m_class = cls; - f->m_dock = drop_right; - f->SetPositioning(YGPositionTypeRelative); - f->SetPosition(0, 0); - f->SetSize(size); - } -} diff --git a/src/app_layout_ui_state.cpp b/src/app_layout_ui_state.cpp new file mode 100644 index 00000000..09c4b33d --- /dev/null +++ b/src/app_layout_ui_state.cpp @@ -0,0 +1,216 @@ +#include "pch.h" +#include "app.h" +#include "app_core/app_preferences.h" +#include "legacy_brush_ui_services.h" +#include "legacy_ui_overlay_services.h" +#include "legacy_preference_storage.h" +#include "node_dialog_picker.h" +#include "node_panel_brush.h" +#include "node_panel_color.h" +#include "node_panel_grid.h" +#include "node_panel_floating.h" +#include "serializer.h" + +namespace { + +bool apply_brush_color_plan(App& app, glm::vec4 color, bool update_quick, bool update_color_panel) +{ + return pp::panopainter::apply_legacy_brush_color_plan(app, color, update_quick, update_color_panel); +} + +bool apply_brush_preset_plan(App& app, const std::shared_ptr& brush) +{ + return pp::panopainter::apply_legacy_brush_preset_plan(app, brush); +} + +void save_floating_panel_state(Serializer::List& list, const std::shared_ptr& child) +{ + if (auto const& f = std::dynamic_pointer_cast(child)) + { + auto fd = list.add(); + fd->class_id = "ui-flt"; + fd->set("pos", Serializer::Vec2(f->GetPosition())); + fd->set("size", Serializer::Vec2(f->m_size)); + fd->set("class", Serializer::Integer((int)f->m_class)); + fd->set("title", Serializer::CString(f->m_title->m_text)); + } +} + +void save_docked_panel_state(Serializer::List& list, const std::shared_ptr& child, const char* class_id) +{ + if (auto const& f = std::dynamic_pointer_cast(child)) + { + auto fd = list.add(); + fd->class_id = class_id; + fd->set("size", Serializer::Vec2(f->m_size)); + fd->set("class", Serializer::Integer((int)f->m_class)); + fd->set("title", Serializer::CString(f->m_title->m_text)); + } +} + +template +void restore_panel_children( + App& app, + std::shared_ptr container, + const TList& items, + bool docked) +{ + for (auto const& l : items) + { + auto ld = std::static_pointer_cast(l); + auto size = ld->value("size"); + auto cls = static_cast(ld->value("class")); + auto f = container->add_child(); + std::string title = "Floating Panel"; + ld->value("title", title); + f->m_title->set_text(title.c_str()); + switch (cls) + { + case NodePanelFloating::kClass::Presets: + { + auto floating_presets = f->m_container->add_child_ref(); + if (!docked) + app.floating_presets = floating_presets; + floating_presets->SetHeightP(100); + floating_presets->on_brush_changed = [&app](Node*, std::shared_ptr& b) { + apply_brush_preset_plan(app, b); + }; + break; + } + case NodePanelFloating::kClass::Color: + { + auto floating_color = f->m_container->add_child_ref(); + if (!docked) + app.floating_color = floating_color; + floating_color->SetHeightP(100); + if (docked) + pp::panopainter::destroy_legacy_node(*floating_color->find("title")); + else + floating_color->find("title")->SetVisibility(false); + floating_color->on_color_changed = [&app](Node*, glm::vec4 color) { + apply_brush_color_plan(app, color, false, false); + }; + break; + } + case NodePanelFloating::kClass::ColorAdv: + { + app.floating_picker = f->m_container->add_child_ref(); + app.floating_picker->m_autohide = false; + app.floating_picker->on_color_change = [&app](Node*, glm::vec3 color) { + apply_brush_color_plan(app, glm::vec4(color, 1.f), false, false); + }; + break; + } + case NodePanelFloating::kClass::Layers: + f->m_container->add_child(app.layers); + if (!docked) + f->SetMinHeight(100); + if (!docked) + f->SetHeight(300); + if (!docked) + app.layers->find("title")->SetVisibility(false); + app.layers->SetPositioning(YGPositionTypeRelative); + app.layers->SetPosition(0, 0); + app.layers->SetWidthP(100); + app.layers->SetHeightP(100); + app.layers->SetFlexShrink(0); + break; + case NodePanelFloating::kClass::Brush: + f->m_container->add_child(app.stroke); + if (!docked) + app.stroke->find("title")->SetVisibility(false); + app.stroke->SetPositioning(YGPositionTypeRelative); + app.stroke->SetPosition(0, 0); + app.stroke->SetWidthP(100); + app.stroke->SetHeightP(100); + break; + case NodePanelFloating::kClass::Grids: + f->m_container->add_child(app.grid); + if (!docked) + app.grid->find("title")->SetVisibility(false); + app.grid->SetPositioning(YGPositionTypeRelative); + app.grid->SetPosition(0, 0); + app.grid->SetWidthP(100); + app.grid->SetHeightP(100); + break; + case NodePanelFloating::kClass::Animation: + f->m_container->add_child(app.animation); + f->m_droppable = false; + app.animation->SetPositioning(YGPositionTypeRelative); + app.animation->SetPosition(0, 0); + app.animation->SetWidthP(100); + app.animation->SetHeightP(100); + break; + case NodePanelFloating::kClass::Generic: + default: + f->m_container->add_child(); + break; + } + f->m_class = cls; + if (docked) + f->m_dock = container; + f->SetPositioning(docked ? YGPositionTypeRelative : YGPositionTypeAbsolute); + f->SetPosition(0, 0); + f->SetSize(size); + } +} + +} // namespace + +void App::set_ui_rtl(bool rtl) +{ + const auto plan = pp::app::plan_interface_direction(rtl); + ui_rtl = plan.direction == pp::app::InterfaceDirection::right_to_left; + layout[main_id]->find("central-row")->SetRTL( + ui_rtl ? YGDirectionRTL : YGDirectionLTR); +} + +bool App::get_ui_rtl() const +{ + return ui_rtl; +} + +void App::ui_save() +{ + Serializer::Descriptor d; + d.class_id = "ui-state"; + + Serializer::List list_floatings; + for (auto const& c : layout[main_id]->find("floatings")->m_children) + save_floating_panel_state(list_floatings, c); + d.set("floatings", list_floatings); + + Serializer::List list_drop_left; + for (auto const& c : layout[main_id]->find("drop-left")->m_children) + save_docked_panel_state(list_drop_left, c, "ui-dpl"); + d.set("drop-left", list_drop_left); + + Serializer::List list_drop_right; + for (auto const& c : layout[main_id]->find("drop-right")->m_children) + save_docked_panel_state(list_drop_right, c, "ui-dpr"); + d.set("drop-right", list_drop_right); + + pp::panopainter::set_legacy_ui_state_preferences(d, ui_rtl); + save_platform_ui_state(); + + pp::panopainter::save_legacy_preferences(); +} + +void App::ui_restore() +{ + const auto preferences = pp::panopainter::read_legacy_ui_preferences(); + if (preferences.has_rtl) + set_ui_rtl(preferences.rtl); + + if (!preferences.state) + return; + + auto floatings = layout[main_id]->find_ref("floatings"); + auto drop_left = layout[main_id]->find_ref("drop-left"); + auto drop_right = layout[main_id]->find_ref("drop-right"); + auto d = preferences.state; + + restore_panel_children(*this, floatings, d->get("floatings")->items, false); + restore_panel_children(*this, drop_left, d->get("drop-left")->items, true); + restore_panel_children(*this, drop_right, d->get("drop-right")->items, true); +} diff --git a/src/keymap.h b/src/keymap.h index 425053a4..74b873e2 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -119,7 +119,7 @@ enum { kVK_UpArrow = 0x7E }; -kKey convert_key(int key) +inline kKey convert_key(int key) { switch(key) { @@ -240,7 +240,7 @@ kKey convert_key(int key) } } #elif __WIN__ -kKey convert_key(int key) +inline kKey convert_key(int key) { static auto KL = GetKeyboardLayout(0); if (key == (VkKeyScanA('[') & 0xFF)) @@ -450,7 +450,7 @@ kKey convert_key(int key) } } #elif __ANDROID__ -kKey convert_key(int key) +inline kKey convert_key(int key) { switch (key) { @@ -682,7 +682,7 @@ kKey convert_key(int key) } } #elif __WEB__ -kKey convert_key(int key) +inline kKey convert_key(int key) { switch (key) { diff --git a/src/main.cpp b/src/main.cpp index d14eb47d..4e404e23 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,6 +12,7 @@ #include "platform_windows/windows_lifecycle_shell.h" #include "platform_windows/windows_splash.h" #include "platform_windows/windows_stylus_input.h" +#include "platform_windows/windows_window_shell.h" #include "platform_windows/windows_vr_shell.h" #include "../resource.h" @@ -30,24 +31,9 @@ namespace pp::platform::windows { bool try_lock_async_render_context(); void unlock_async_render_context(); void swap_async_render_context(); + RetainedState& retained_state(); } -struct RetainedState -{ - HINSTANCE hInst{}; - HWND hWnd{}; - bool keys[256]{}; - std::map vkey_map; - wchar_t window_title[512]{}; - bool sandboxed = false; - pp::platform::windows::VrShellState vr; -}; - -RetainedState& retained_state() -{ - static RetainedState state; - return state; -} - +using pp::platform::windows::retained_state; namespace { struct RetainedMainTaskQueue final @@ -571,262 +557,6 @@ int main(int argc, char** argv) LogRemote::I.stop(); } -LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) -{ - auto& state = retained_state(); - static bool leftDown = false; - static DWORD lastTime; - static glm::vec2 lastPoint; - - auto extra = GetMessageExtraInfo(); -// if ((extra & 0xFFFFFF00) == 0xFF515700) -// LOG("source %s", extra & 0x80 ? "touch" : "pen"); - - switch (msg) - { - case pp::platform::windows::kUserCloseMessage: - pp::platform::windows::handle_window_close_message(state.vr); - return 0; - case WM_PAINT: - App::I->redraw = true; - break; - case WM_CREATE: - BT_SetTerminate(); - break; - case WM_CLOSE: - { - App::I->ui_task_async([] { - if (App::I->request_close()) - { - destroy_window(); - } - }); - return 1; - break; - } - case WM_SIZE: - { - auto w = (float)LOWORD(lp); - auto h = (float)HIWORD(lp); - if (h != 0 && pp::platform::windows::lifecycle_is_running()) - { - App::I->ui_task_async([=] - { - App::I->resize(w, h); - App::I->redraw = true; - }, true); - } - break; - } - case WM_ACTIVATE: - { - pp::platform::windows::platform_services().set_cursor_visible(true); - App::I->ui_task_async([&state, wp, lp] { - int active = GET_WM_ACTIVATE_STATE(wp, lp); - WacomTablet::I.set_focus(active); - static BYTE keys[256]; - if (GetKeyboardState(keys)) - { - bool alt = keys[VK_MENU] & 0x80; - for (auto k : state.vkey_map) - { - // ignore alt + tab - if (alt && k.first == kKey::KeyTab) - continue; - bool down = keys[k.second] & 0x80; - if (App::I->keys[(int)k.first] && !down) - App::I->key_up(k.first); - else if(!App::I->keys[(int)k.first] && down) - App::I->key_down(k.first); - } - } - }); - break; - } -// case WM_TOUCH: -// { -// App::I->ui_task_async([=] { -// //LOG("touch"); -// }); -// break; -// } - case WT_PACKET: - { - pp::platform::windows::note_wintab_packet(); - App::I->ui_task_async([=] { - WacomTablet::I.handle_message(hWnd, msg, wp, lp); - }); - break; - } - case WM_SYSKEYDOWN: - case WM_KEYDOWN: - if ((lp >> 30 & 1) == 0 && // ignore repeated - !(wp == VK_TAB && App::I->keys[(int)kKey::KeyAlt])) // ignore alt+tab - { - App::I->ui_task_async([wp] { - App::I->key_down(convert_key((int)wp)); - }); - } - break; - case WM_SYSKEYUP: - case WM_KEYUP: - if (!(wp == VK_TAB && App::I->keys[(int)kKey::KeyAlt])) // ignore alt+tab - { - App::I->ui_task_async([wp] { - App::I->key_up(convert_key((int)wp)); - }); - } - break; - case WM_CHAR: - { - App::I->ui_task_async([wp]{ - App::I->key_char((int)wp); - }); - } - break; - case WM_MOUSEMOVE: - { -/* - RECT r; - POINT curpos; - GetWindowRect(hWnd, &r); - glm::vec2 center = { r.left + (r.right - r.left) / 2, r.top + (r.bottom - r.top) / 2 }; - GetCursorPos(&curpos); - SetCursorPos(center.x, center.y); - - //glm::vec2 cur = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) }; - glm::vec2 sz = { App::I->width, App::I->height }; - glm::vec2 diff = { curpos.x - center.x, curpos.y - center.y }; - lastPoint = glm::clamp(lastPoint + diff, { 0, 0 }, sz); - -*/ - lastPoint = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) }; - - auto pt = lastPoint; - App::I->ui_task_async([pt, extra, p = WacomTablet::I.get_pressure()]{ - kEventSource pointer_source; - if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) - { - pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; - } - else - { - pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; - if ((extra & 0xFFFFFF00) == 0xFF515700) - pointer_source = kEventSource::Touch; - } - App::I->mouse_move((float)pt.x, (float)pt.y, p, pointer_source, WacomTablet::I.m_eraser); - }); - } - break; - case WM_LBUTTONDOWN: - { - SetCapture(hWnd); - auto pt = lastPoint; - App::I->ui_task_async([pt, extra, hWnd, p = WacomTablet::I.get_pressure()]{ - kEventSource pointer_source; - if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) - { - pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; - } - else - { - pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; - if ((extra & 0xFFFFFF00) == 0xFF515700) - pointer_source = kEventSource::Touch; - } - App::I->mouse_down(0, (float)pt.x, (float)pt.y, p, pointer_source, WacomTablet::I.m_eraser); - }); - } - break; - case WM_LBUTTONUP: - { - ReleaseCapture(); - auto pt = lastPoint; - App::I->ui_task_async([pt, extra] { - WacomTablet::I.reset_pressure(); - kEventSource pointer_source; - if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) - { - pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; - } - else - { - pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; - if ((extra & 0xFFFFFF00) == 0xFF515700) - pointer_source = kEventSource::Touch; - } - App::I->mouse_up(0, (float)pt.x, (float)pt.y, pointer_source, WacomTablet::I.m_eraser); - }); - } - break; - case WM_RBUTTONDOWN: - { - SetCapture(hWnd); - auto pt = lastPoint; - App::I->ui_task_async([pt, extra, hWnd] { - kEventSource pointer_source; - if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) - { - pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; - } - else - { - pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; - if ((extra & 0xFFFFFF00) == 0xFF515700) - pointer_source = kEventSource::Touch; - } - App::I->mouse_down(1, (float)pt.x, (float)pt.y, 1.f, pointer_source, 0); - }); - } - break; - case WM_RBUTTONUP: - { - ReleaseCapture(); - auto pt = lastPoint; - App::I->ui_task_async([pt, extra] { - kEventSource pointer_source; - if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) - { - pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; - } - else - { - pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; - if ((extra & 0xFFFFFF00) == 0xFF515700) - pointer_source = kEventSource::Touch; - } - App::I->mouse_up(1, (float)pt.x, (float)pt.y, pointer_source, 0); - }); - } - break; - case WM_MOUSEWHEEL: - { - POINT pt; - pt.x = GET_X_LPARAM(lp); - pt.y = GET_Y_LPARAM(lp); - ScreenToClient(hWnd, &pt); - { - App::I->ui_task_async([pt, wp] { - App::I->mouse_scroll((float)pt.x, (float)pt.y, - (float)GET_WHEEL_DELTA_WPARAM(wp) / (float)WHEEL_DELTA); - }); - } - break; - } - case WM_POINTERUPDATE: - { - pp::platform::windows::handle_pointer_update_message(wp); - break; - } - } - - // avoid annoying alt system menu - if (wp == SC_KEYMENU && (lp >> 16) <= 0) return 0; - - return DefWindowProc(hWnd, msg, wp, lp); -} - int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { int argc = 0; diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index d5132de6..ae639a5b 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -656,68 +656,16 @@ void NodeStrokePreview::draw_stroke_immediate() .mvp = ortho_proj, }); const bool copy_stroke_destination = pass_orchestration.copy_stroke_destination; - const auto& material = pass_orchestration.material; pp::panopainter::setup_legacy_stroke_shader(pass_orchestration.stroke_shader); - - const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_immediate_pass_sequence( - pp::panopainter::LegacyNodeStrokePreviewImmediatePassSequenceRequest { - .execute_dual_pass = [&] { - if (!pass_orchestration.material.dual_pass.enabled) { - return; - } - - pp::panopainter::setup_legacy_stroke_dual_shader( - pass_orchestration.material.dual_pass.uses_pattern); - bind_stroke_preview_dual_pass_textures(*dual_brush); - execute_stroke_draw_immediate_dual_pass( - m_dual_stroke, - *b, - pass_orchestration, - std::move(dual_brush), - copy_stroke_destination, - zoom, - size); - }, - .capture_background = [&] { - execute_stroke_preview_background_capture_pass( - size, - pass_orchestration.background_colorize, - m_tex_background, - [&] { - m_plane.draw_fill(); - }); - }, - .execute_main_live_pass = [&]() -> bool { - return pp::panopainter::execute_legacy_node_stroke_preview_main_live_pass( - make_stroke_draw_immediate_main_live_pass_request( - m_stroke, - *b, - pass_orchestration, - copy_stroke_destination, - zoom, - size)); - }, - .execute_final_composite = [&]() -> bool { - return pp::panopainter::execute_legacy_node_stroke_preview_final_composite( - size, - glm::vec2(b->m_pattern_scale), - *b, - material.composite_pass, - m_tex_background, - m_tex, - m_tex_dual, - m_tex_preview, - m_sampler_linear, - m_sampler_linear_repeat, - [&] { - b->m_pattern_texture ? b->m_pattern_texture->bind() : unbind_texture_2d(); - }, - [&] { - m_plane.draw_fill(); - }); - }, - }); - assert(sequence_ok); + execute_stroke_draw_immediate_pass_sequence( + m_stroke, + m_dual_stroke, + *b, + std::move(dual_brush), + pass_orchestration, + copy_stroke_destination, + zoom, + size); m_rtt.unbindFramebuffer(); @@ -811,6 +759,78 @@ void NodeStrokePreview::execute_stroke_draw_immediate_dual_pass( }); } +void NodeStrokePreview::execute_stroke_draw_immediate_pass_sequence( + Stroke& stroke, + Stroke& dual_stroke, + const Brush& brush, + std::shared_ptr dual_brush, + const pp::panopainter::LegacyNodeStrokePreviewPassOrchestrationPlan& pass_orchestration, + bool copy_stroke_destination, + float zoom, + const glm::vec2& size) +{ + const auto& material = pass_orchestration.material; + const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_immediate_pass_sequence( + pp::panopainter::LegacyNodeStrokePreviewImmediatePassSequenceRequest { + .execute_dual_pass = [&] { + if (!material.dual_pass.enabled) { + return; + } + + pp::panopainter::setup_legacy_stroke_dual_shader( + material.dual_pass.uses_pattern); + bind_stroke_preview_dual_pass_textures(*dual_brush); + execute_stroke_draw_immediate_dual_pass( + dual_stroke, + brush, + pass_orchestration, + std::move(dual_brush), + copy_stroke_destination, + zoom, + size); + }, + .capture_background = [&] { + execute_stroke_preview_background_capture_pass( + size, + pass_orchestration.background_colorize, + m_tex_background, + [&] { + m_plane.draw_fill(); + }); + }, + .execute_main_live_pass = [&]() -> bool { + return pp::panopainter::execute_legacy_node_stroke_preview_main_live_pass( + make_stroke_draw_immediate_main_live_pass_request( + stroke, + brush, + pass_orchestration, + copy_stroke_destination, + zoom, + size)); + }, + .execute_final_composite = [&]() -> bool { + return pp::panopainter::execute_legacy_node_stroke_preview_final_composite( + size, + glm::vec2(brush.m_pattern_scale), + brush, + material.composite_pass, + m_tex_background, + m_tex, + m_tex_dual, + m_tex_preview, + m_sampler_linear, + m_sampler_linear_repeat, + [&] { + brush.m_pattern_texture ? brush.m_pattern_texture->bind() : unbind_texture_2d(); + }, + [&] { + m_plane.draw_fill(); + }); + }, + }); + assert(sequence_ok); +} + void NodeStrokePreview::execute_stroke_draw_immediate_main_live_sample_pass( const Brush& brush, bool copy_stroke_destination, diff --git a/src/node_stroke_preview.h b/src/node_stroke_preview.h index 4172620c..c4bc3ee4 100644 --- a/src/node_stroke_preview.h +++ b/src/node_stroke_preview.h @@ -30,6 +30,15 @@ class NodeStrokePreview : public NodeBorder static Sampler m_sampler_mipmap; static DynamicShape m_brush_shape; Texture2D m_tex_preview; + void execute_stroke_draw_immediate_pass_sequence( + Stroke& stroke, + Stroke& dual_stroke, + const Brush& brush, + std::shared_ptr dual_brush, + const pp::panopainter::LegacyNodeStrokePreviewPassOrchestrationPlan& pass_orchestration, + bool copy_stroke_destination, + float zoom, + const glm::vec2& size); public: using parent = NodeBorder; static std::atomic_int s_instances; diff --git a/src/platform_windows/windows_bootstrap_helpers.cpp b/src/platform_windows/windows_bootstrap_helpers.cpp index 1a69b897..7a44ece0 100644 --- a/src/platform_windows/windows_bootstrap_helpers.cpp +++ b/src/platform_windows/windows_bootstrap_helpers.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "platform_windows/windows_bootstrap_helpers.h" +#include "platform_windows/windows_window_shell.h" #include "app.h" #include "legacy_gl_runtime_dispatch.h" @@ -15,8 +16,6 @@ #define USE_RENDERDOC #endif -LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); - namespace pp::platform::windows { void set_async_render_context(HDC hdc, HGLRC hrc); } @@ -113,7 +112,7 @@ MainWindowStartupState initialize_main_window_startup_state() const auto className = L"EngineMain"; startup.window_class.hInstance = hInst; - startup.window_class.lpfnWndProc = (WNDPROC)WndProc; + startup.window_class.lpfnWndProc = (WNDPROC)main_window_proc; startup.window_class.lpszClassName = className; startup.window_class.hbrBackground = (HBRUSH)COLOR_WINDOW; startup.window_class.hCursor = LoadCursor(NULL, IDC_ARROW); diff --git a/src/platform_windows/windows_window_shell.cpp b/src/platform_windows/windows_window_shell.cpp new file mode 100644 index 00000000..1d5aa800 --- /dev/null +++ b/src/platform_windows/windows_window_shell.cpp @@ -0,0 +1,247 @@ +#include "pch.h" + +#include "platform_windows/windows_window_shell.h" + +#include "app.h" +#include "platform_windows/windows_lifecycle_shell.h" +#include "platform_windows/windows_platform_services.h" +#include "platform_windows/windows_stylus_input.h" +#include "keymap.h" +#include "wacom.h" + +void destroy_window(); + +namespace pp::platform::windows { + +RetainedState& retained_state() +{ + static RetainedState state; + return state; +} + +LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) +{ + auto& state = retained_state(); + static glm::vec2 lastPoint; + + auto extra = GetMessageExtraInfo(); + + switch (msg) + { + case kUserCloseMessage: + handle_window_close_message(state.vr); + return 0; + case WM_PAINT: + App::I->redraw = true; + break; + case WM_CREATE: + BT_SetTerminate(); + break; + case WM_CLOSE: + { + App::I->ui_task_async([] { + if (App::I->request_close()) + { + destroy_window(); + } + }); + return 1; + break; + } + case WM_SIZE: + { + auto w = (float)LOWORD(lp); + auto h = (float)HIWORD(lp); + if (h != 0 && lifecycle_is_running()) + { + App::I->ui_task_async([=] + { + App::I->resize(w, h); + App::I->redraw = true; + }, true); + } + break; + } + case WM_ACTIVATE: + { + platform_services().set_cursor_visible(true); + App::I->ui_task_async([&state, wp, lp] { + int active = GET_WM_ACTIVATE_STATE(wp, lp); + WacomTablet::I.set_focus(active); + static BYTE keys[256]; + if (GetKeyboardState(keys)) + { + bool alt = keys[VK_MENU] & 0x80; + for (auto k : state.vkey_map) + { + if (alt && k.first == kKey::KeyTab) + continue; + bool down = keys[k.second] & 0x80; + if (App::I->keys[(int)k.first] && !down) + App::I->key_up(k.first); + else if (!App::I->keys[(int)k.first] && down) + App::I->key_down(k.first); + } + } + }); + break; + } + case WT_PACKET: + { + note_wintab_packet(); + App::I->ui_task_async([=] { + WacomTablet::I.handle_message(hWnd, msg, wp, lp); + }); + break; + } + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + if ((lp >> 30 & 1) == 0 && + !(wp == VK_TAB && App::I->keys[(int)kKey::KeyAlt])) + { + App::I->ui_task_async([wp] { + App::I->key_down(convert_key((int)wp)); + }); + } + break; + case WM_SYSKEYUP: + case WM_KEYUP: + if (!(wp == VK_TAB && App::I->keys[(int)kKey::KeyAlt])) + { + App::I->ui_task_async([wp] { + App::I->key_up(convert_key((int)wp)); + }); + } + break; + case WM_CHAR: + App::I->ui_task_async([wp] { + App::I->key_char((int)wp); + }); + break; + case WM_MOUSEMOVE: + lastPoint = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) }; + { + auto pt = lastPoint; + App::I->ui_task_async([pt, extra, p = WacomTablet::I.get_pressure()] { + kEventSource pointer_source; + if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) + { + pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; + } + else + { + pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; + if ((extra & 0xFFFFFF00) == 0xFF515700) + pointer_source = kEventSource::Touch; + } + App::I->mouse_move((float)pt.x, (float)pt.y, p, pointer_source, WacomTablet::I.m_eraser); + }); + } + break; + case WM_LBUTTONDOWN: + { + SetCapture(hWnd); + auto pt = lastPoint; + App::I->ui_task_async([pt, extra, hWnd, p = WacomTablet::I.get_pressure()] { + kEventSource pointer_source; + if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) + { + pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; + } + else + { + pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; + if ((extra & 0xFFFFFF00) == 0xFF515700) + pointer_source = kEventSource::Touch; + } + App::I->mouse_down(0, (float)pt.x, (float)pt.y, p, pointer_source, WacomTablet::I.m_eraser); + }); + } + break; + case WM_LBUTTONUP: + { + ReleaseCapture(); + auto pt = lastPoint; + App::I->ui_task_async([pt, extra] { + WacomTablet::I.reset_pressure(); + kEventSource pointer_source; + if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) + { + pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; + } + else + { + pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; + if ((extra & 0xFFFFFF00) == 0xFF515700) + pointer_source = kEventSource::Touch; + } + App::I->mouse_up(0, (float)pt.x, (float)pt.y, pointer_source, WacomTablet::I.m_eraser); + }); + } + break; + case WM_RBUTTONDOWN: + { + SetCapture(hWnd); + auto pt = lastPoint; + App::I->ui_task_async([pt, extra, hWnd] { + kEventSource pointer_source; + if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) + { + pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; + } + else + { + pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; + if ((extra & 0xFFFFFF00) == 0xFF515700) + pointer_source = kEventSource::Touch; + } + App::I->mouse_down(1, (float)pt.x, (float)pt.y, 1.f, pointer_source, 0); + }); + } + break; + case WM_RBUTTONUP: + { + ReleaseCapture(); + auto pt = lastPoint; + App::I->ui_task_async([pt, extra] { + kEventSource pointer_source; + if (WacomTablet::I.m_ink_pen || WacomTablet::I.m_ink_touch) + { + pointer_source = WacomTablet::I.m_ink_pen ? kEventSource::Stylus : kEventSource::Touch; + } + else + { + pointer_source = WacomTablet::I.m_stylus ? kEventSource::Stylus : kEventSource::Mouse; + if ((extra & 0xFFFFFF00) == 0xFF515700) + pointer_source = kEventSource::Touch; + } + App::I->mouse_up(1, (float)pt.x, (float)pt.y, pointer_source, 0); + }); + } + break; + case WM_MOUSEWHEEL: + { + POINT pt; + pt.x = GET_X_LPARAM(lp); + pt.y = GET_Y_LPARAM(lp); + ScreenToClient(hWnd, &pt); + App::I->ui_task_async([pt, wp] { + App::I->mouse_scroll((float)pt.x, (float)pt.y, + (float)GET_WHEEL_DELTA_WPARAM(wp) / (float)WHEEL_DELTA); + }); + break; + } + case WM_POINTERUPDATE: + { + handle_pointer_update_message(wp); + break; + } + } + + if (wp == SC_KEYMENU && (lp >> 16) <= 0) + return 0; + + return DefWindowProc(hWnd, msg, wp, lp); +} + +} diff --git a/src/platform_windows/windows_window_shell.h b/src/platform_windows/windows_window_shell.h new file mode 100644 index 00000000..f8ac928a --- /dev/null +++ b/src/platform_windows/windows_window_shell.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include "event.h" +#include "platform_windows/windows_vr_shell.h" + +struct RetainedState +{ + HINSTANCE hInst{}; + HWND hWnd{}; + bool keys[256]{}; + std::map vkey_map; + wchar_t window_title[512]{}; + bool sandboxed = false; + pp::platform::windows::VrShellState vr; +}; + +namespace pp::platform::windows { + +RetainedState& retained_state(); +LRESULT CALLBACK main_window_proc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); + +}