75 lines
3.1 KiB
C++
75 lines
3.1 KiB
C++
#ifndef RUNNER_FLUTTER_WINDOW_H_
|
||
#define RUNNER_FLUTTER_WINDOW_H_
|
||
|
||
#include <flutter/dart_project.h>
|
||
#include <flutter/flutter_view_controller.h>
|
||
#include <flutter/method_channel.h>
|
||
|
||
#include <memory>
|
||
|
||
#include "win32_window.h"
|
||
|
||
// A window that does nothing but host a Flutter view.
|
||
class FlutterWindow : public Win32Window {
|
||
public:
|
||
// Creates a new FlutterWindow hosting a Flutter view running |project|.
|
||
explicit FlutterWindow(const flutter::DartProject& project);
|
||
virtual ~FlutterWindow();
|
||
|
||
protected:
|
||
// Win32Window:
|
||
bool OnCreate() override;
|
||
void OnDestroy() override;
|
||
LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
|
||
LPARAM const lparam) noexcept override;
|
||
|
||
private:
|
||
// The project to run.
|
||
flutter::DartProject project_;
|
||
|
||
// The Flutter instance hosted in this window.
|
||
std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
|
||
|
||
// Windows platform MethodChannel for theme control.
|
||
std::unique_ptr<flutter::MethodChannel<>> platform_channel_;
|
||
|
||
// 窗口控制 MethodChannel(窗口大小预设菜单等)
|
||
std::unique_ptr<flutter::MethodChannel<>> window_control_channel_;
|
||
|
||
// 弹出原生窗口大小预设菜单(TrackPopupMenuEx)
|
||
// 返回 true 表示用户选择了某个尺寸,false 表示用户取消了菜单
|
||
bool ShowWindowSizeMenu(HWND hwnd);
|
||
|
||
// Subclass ID for the Flutter child window (WM_NCHITTEST → HTTRANSPARENT)
|
||
static const UINT_PTR kChildSubclassId = 12345;
|
||
|
||
// Subclass callback: forward title-bar hit-test to parent window so the
|
||
// parent can return HTCAPTION and Windows performs native modal dragging.
|
||
static LRESULT CALLBACK ChildWndProc(HWND hwnd, UINT message,
|
||
WPARAM wparam, LPARAM lparam,
|
||
UINT_PTR subclass_id,
|
||
DWORD_PTR ref_data);
|
||
|
||
// ============================================================
|
||
// 原生拖拽状态:SC_MOVE 模态循环期间绕过插件链 + 子窗口消息拦截
|
||
//
|
||
// 根因(经 v1~v8 验证):
|
||
// 1. 手动 SetWindowPos 拖拽不触发 DWM "live drag" 优化
|
||
// 2. 完全禁用 Mica 能解决卡顿(v8 验证),但临时禁用 Mica(v4~v7)失败
|
||
// 3. v4~v7 失败的原因:EnterSizeMove 遗漏了 SetWindowCompositionAttribute
|
||
// (ACCENT_DISABLED) 调用——这是 flutter_acrylic 的 setEffect(disabled)
|
||
// 能立即禁用 Mica 的关键。仅靠 DwmSetWindowAttribute 是异步的,不生效。
|
||
//
|
||
// 修复(v9):
|
||
// - WM_NCLBUTTONDOWN(HTCAPTION) 时调用 EnterSizeMove 禁用 Mica
|
||
// (现在包含 SetWindowCompositionAttribute(ACCENT_DISABLED),能立即生效)
|
||
// - SWP_FRAMECHANGED 强制 DWM 同步应用变更
|
||
// - DefWindowProc 进入 SC_MOVE 模态循环
|
||
// - DefWindowProc 返回后调用 ExitSizeMove 恢复 Mica + SWP_FRAMECHANGED
|
||
// - 模态循环期间绕过插件链 + 子窗口消息拦截(v8)
|
||
// ============================================================
|
||
static bool is_in_native_drag_;
|
||
};
|
||
|
||
#endif // RUNNER_FLUTTER_WINDOW_H_
|