The Webview Univeral Flutter package for Appeto SDK.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

244 lignes
7.5 KiB

  1. //
  2. // Created by yangbin on 2021/10/20.
  3. //
  4. #include <windows.h>
  5. #include "webview_window.h"
  6. #include <tchar.h>
  7. #include <utility>
  8. #include "strconv.h"
  9. #include "utils.h"
  10. #include "include/webview_universal/webview_universal_plugin.h"
  11. namespace {
  12. TCHAR kWebViewWindowClassName[] = _T("WebviewWindow");
  13. using namespace webview_window;
  14. // Scale helper to convert logical scaler values to physical using passed in
  15. // scale factor
  16. int Scale(int source, double scale_factor) {
  17. return static_cast<int>(source * scale_factor);
  18. }
  19. }
  20. using namespace Microsoft::WRL;
  21. WebviewWindow::WebviewWindow(
  22. MethodChannelPtr method_channel,
  23. int64_t window_id,
  24. int title_bar_height,
  25. std::function<void()> on_close_callback
  26. ) : method_channel_(std::move(method_channel)),
  27. window_id_(window_id),
  28. on_close_callback_(std::move(on_close_callback)),
  29. hwnd_(),
  30. title_bar_height_(title_bar_height) {
  31. }
  32. WebviewWindow::~WebviewWindow() {
  33. flutter_action_bar_.reset();
  34. web_view_.reset();
  35. SetWindowLongPtr(hwnd_.get(), GWLP_USERDATA, 0);
  36. hwnd_.reset();
  37. }
  38. void WebviewWindow::CreateAndShow(const std::wstring &title, int height, int width,
  39. const std::wstring &userDataFolder,
  40. CreateCallback callback) {
  41. RegisterWindowClass(kWebViewWindowClassName, WebviewWindow::WndProc);
  42. // the same as flutter default main.cpp
  43. const POINT target_point = {static_cast<LONG>(10),
  44. static_cast<LONG>(10)};
  45. HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
  46. UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
  47. double scale_factor = dpi / 96.0;
  48. hwnd_ = wil::unique_hwnd(::CreateWindow(
  49. kWebViewWindowClassName, title.c_str(),
  50. WS_OVERLAPPEDWINDOW | WS_VISIBLE,
  51. CW_USEDEFAULT, CW_USEDEFAULT,
  52. Scale(width, scale_factor), Scale(height, scale_factor),
  53. nullptr, nullptr, GetModuleHandle(nullptr), this));
  54. if (!hwnd_) {
  55. callback(false);
  56. return;
  57. }
  58. // Centered window on screen.
  59. RECT rc;
  60. GetClientRect(hwnd_.get(), &rc);
  61. ClipOrCenterRectToMonitor(&rc, MONITOR_CENTER);
  62. SetWindowPos(hwnd_.get(), nullptr, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  63. auto title_bar_height = Scale(title_bar_height_, scale_factor);
  64. // Create the browser view.
  65. web_view_ = std::make_unique<webview_window::WebView>(
  66. method_channel_, window_id_, userDataFolder,
  67. [callback](HRESULT hr) {
  68. if (SUCCEEDED(hr)) {
  69. callback(true);
  70. } else {
  71. callback(false);
  72. }
  73. });
  74. auto web_view_handle = web_view_->NativeWindow().get();
  75. SetParent(web_view_handle, hwnd_.get());
  76. MoveWindow(web_view_handle, 0, title_bar_height,
  77. rc.right - rc.left,
  78. rc.bottom - rc.top - title_bar_height,
  79. true);
  80. ShowWindow(web_view_handle, SW_SHOW);
  81. // Create the title bar view.
  82. std::vector<std::string> args = {"web_view_title_bar", std::to_string(window_id_)};
  83. flutter_action_bar_ = std::make_unique<webview_window::FlutterView>(std::move(args));
  84. auto title_bar_handle = flutter_action_bar_->GetWindow();
  85. SetParent(title_bar_handle, hwnd_.get());
  86. MoveWindow(title_bar_handle, 0, 0, rc.right - rc.left, title_bar_height, true);
  87. ShowWindow(title_bar_handle, SW_SHOW);
  88. assert(hwnd_ != nullptr);
  89. ShowWindow(hwnd_.get(), SW_SHOW);
  90. UpdateWindow(hwnd_.get());
  91. }
  92. void WebviewWindow::SetBrightness(int brightness) {
  93. }
  94. // static
  95. LRESULT CALLBACK
  96. WebviewWindow::WndProc(
  97. HWND window,
  98. UINT message,
  99. WPARAM wparam,
  100. LPARAM lparam
  101. ) noexcept {
  102. if (message == WM_NCCREATE) {
  103. auto window_struct = reinterpret_cast<CREATESTRUCT *>(lparam);
  104. SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
  105. // auto that = static_cast<WebviewWindow *>(window_struct->lpCreateParams);
  106. // that->hwnd_ = window;
  107. } else if (WebviewWindow *that = GetThisFromHandle(window)) {
  108. return that->MessageHandler(window, message, wparam, lparam);
  109. }
  110. return DefWindowProc(window, message, wparam, lparam);
  111. }
  112. LRESULT
  113. WebviewWindow::MessageHandler(
  114. HWND hwnd,
  115. UINT message,
  116. WPARAM wparam,
  117. LPARAM lparam
  118. ) noexcept {
  119. // Give Flutter, including plugins, an opportunity to handle window messages.
  120. if (flutter_action_bar_) {
  121. std::optional<LRESULT> result = flutter_action_bar_->HandleTopLevelWindowProc(hwnd, message, wparam, lparam);
  122. if (result) {
  123. return *result;
  124. }
  125. }
  126. switch (message) {
  127. case WM_DESTROY: {
  128. flutter_action_bar_.reset();
  129. web_view_.reset();
  130. // might receive multiple WM_DESTROY messages.
  131. if (!destroyed_) {
  132. destroyed_ = true;
  133. auto args = flutter::EncodableMap{
  134. {flutter::EncodableValue("id"), flutter::EncodableValue(window_id_)}
  135. };
  136. method_channel_->InvokeMethod(
  137. "onWindowClose",
  138. std::make_unique<flutter::EncodableValue>(args)
  139. );
  140. if (on_close_callback_) {
  141. on_close_callback_();
  142. }
  143. }
  144. return 0;
  145. }
  146. case WM_DPICHANGED: {
  147. auto newRectSize = reinterpret_cast<RECT *>(lparam);
  148. LONG newWidth = newRectSize->right - newRectSize->left;
  149. LONG newHeight = newRectSize->bottom - newRectSize->top;
  150. SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
  151. newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
  152. return 0;
  153. }
  154. case WM_SIZE: {
  155. RECT rect;
  156. GetClientRect(hwnd, &rect);
  157. HMONITOR monitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);
  158. UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
  159. double scale_factor = dpi / 96.0;
  160. auto title_bar_height = Scale(title_bar_height_, scale_factor);
  161. if (web_view_ != nullptr) {
  162. MoveWindow(web_view_->NativeWindow().get(), 0, title_bar_height,
  163. rect.right - rect.left, rect.bottom - rect.top - title_bar_height,
  164. true);
  165. web_view_->UpdateBounds();
  166. }
  167. if (flutter_action_bar_) {
  168. // FIXME(BOYAN) remove this trick if flutter provide a properly way to force redraw the flutter view.
  169. // When user only change the height of window, flutter title bar height will not change, because the title_bar_height
  170. // is a fixed value. In this situation, the flutter view will not perform draw since no size changed. So we need
  171. // perform a force redraw to flutter view. Although flutter provide a function FlutterDesktopViewControllerForceRedraw.
  172. // https://github.com/flutter/engine/pull/24186 But we can not use this because it not provided on wrapper.
  173. if (last_title_bar_width_ != rect.right - rect.left) {
  174. // Size and position the flutter window.
  175. last_title_bar_width_ = rect.right - rect.left;
  176. MoveWindow(flutter_action_bar_->GetWindow(), 0, 0,
  177. last_title_bar_width_, title_bar_height, true);
  178. } else {
  179. last_title_bar_width_ = rect.right - rect.left + 1;
  180. MoveWindow(flutter_action_bar_->GetWindow(), 0, 0,
  181. last_title_bar_width_, title_bar_height, true);
  182. }
  183. }
  184. return 0;
  185. }
  186. case WM_FONTCHANGE: {
  187. if (flutter_action_bar_) {
  188. flutter_action_bar_->ReloadSystemFonts();
  189. }
  190. break;
  191. }
  192. case WM_ACTIVATE: {
  193. return 0;
  194. }
  195. }
  196. return DefWindowProc(hwnd, message, wparam, lparam);
  197. }
  198. // static
  199. WebviewWindow *WebviewWindow::GetThisFromHandle(HWND const window) noexcept {
  200. return reinterpret_cast<WebviewWindow *>(
  201. GetWindowLongPtr(window, GWLP_USERDATA));
  202. }