From 09eec8dd4b01578c6ca98b2f17f655b6200b9be1 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 3 Dec 2019 20:58:40 +0800 Subject: [PATCH 01/47] Nit. --- src/WebWindow.Native/WebWindow.Native.vcxproj | 4 + src/WebWindow.Native/WebWindow.Windows.cpp | 80 ++++++++----------- src/WebWindow.Native/WebWindow.h | 30 ++++--- 3 files changed, 53 insertions(+), 61 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Native.vcxproj b/src/WebWindow.Native/WebWindow.Native.vcxproj index 3c5ef82..939299a 100644 --- a/src/WebWindow.Native/WebWindow.Native.vcxproj +++ b/src/WebWindow.Native/WebWindow.Native.vcxproj @@ -91,6 +91,7 @@ true WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true + stdcpp17 true @@ -104,6 +105,7 @@ true _DEBUG;_WINDOWS;%(PreprocessorDefinitions) true + stdcpp17 true @@ -120,6 +122,7 @@ true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true + stdcpp17 true @@ -137,6 +140,7 @@ true NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true + stdcpp17 true diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index ba8d802..c88bf42 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -6,13 +6,14 @@ #include #include #include + #define WM_USER_SHOWMESSAGE (WM_USER + 0x0001) #define WM_USER_INVOKE (WM_USER + 0x0002) using namespace Microsoft::WRL; LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -LPWSTR Utf8ToLPWSTR(UTF8String str); +std::wstring Utf8ToLPWSTR(UTF8String str); LPCWSTR CLASS_NAME = L"WebWindow"; std::mutex invokeLockMutex; HINSTANCE WebWindow::_hInstance; @@ -27,8 +28,8 @@ struct InvokeWaitInfo struct ShowMessageParams { - LPCWSTR title; - LPCWSTR body; + std::wstring title; + std::wstring body; UINT type; }; @@ -51,11 +52,11 @@ WebWindow::WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCall // Create the window _webMessageReceivedCallback = webMessageReceivedCallback; _parent = parent; - LPCWSTR wtitle = Utf8ToLPWSTR(title); + std::wstring wtitle = Utf8ToLPWSTR(title); _hWnd = CreateWindowExW( 0, // Optional window styles. CLASS_NAME, // Window class - wtitle, // Window text + wtitle.c_str(), // Window text WS_OVERLAPPEDWINDOW, // Window style // Size and position @@ -66,7 +67,6 @@ WebWindow::WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCall _hInstance, // Instance handle this // Additional application data ); - delete[] wtitle; hwndToWebWindow[_hWnd] = this; } @@ -93,9 +93,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_USER_SHOWMESSAGE: { ShowMessageParams* params = (ShowMessageParams*)wParam; - MessageBoxW(hwnd, params->body, params->title, params->type); - delete params->title; - delete params->body; + MessageBoxW(hwnd, params->body.c_str(), params->title.c_str(), params->type); delete params; return 0; } @@ -121,7 +119,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } return 0; } - break; + break; } return DefWindowProc(hwnd, uMsg, wParam, lParam); @@ -139,9 +137,8 @@ void WebWindow::RefitContent() void WebWindow::SetTitle(UTF8String title) { - LPCWSTR wtitle = Utf8ToLPWSTR(title); - SetWindowTextW(_hWnd, wtitle); - delete[] wtitle; + std::wstring wtitle = Utf8ToLPWSTR(title); + SetWindowTextW(_hWnd, wtitle.c_str()); } void WebWindow::Show() @@ -172,7 +169,7 @@ void WebWindow::WaitForExit() void WebWindow::ShowMessage(UTF8String title, UTF8String body, UINT type) { - ShowMessageParams *params = new ShowMessageParams; + ShowMessageParams* params = new ShowMessageParams; params->title = Utf8ToLPWSTR(title); params->body = Utf8ToLPWSTR(body); params->type = type; @@ -181,7 +178,7 @@ void WebWindow::ShowMessage(UTF8String title, UTF8String body, UINT type) void WebWindow::Invoke(ACTION callback) { - InvokeWaitInfo waitInfo = {}; + InvokeWaitInfo waitInfo = {}; PostMessageW(_hWnd, WM_USER_INVOKE, (WPARAM)callback, (LPARAM)&waitInfo); // Block until the callback is actually executed and completed @@ -190,19 +187,19 @@ void WebWindow::Invoke(ACTION callback) waitInfo.completionNotifier.wait(uLock, [&] { return waitInfo.isCompleted; }); } -LPWSTR Utf8ToLPWSTR(UTF8String str) +std::wstring Utf8ToLPWSTR(UTF8String str) { int wchars_num = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); - wchar_t* wstr = new wchar_t[wchars_num]; - MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, wchars_num); + std::wstring wstr(wchars_num, L'\0'); + MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr.data(), wchars_num); return wstr; } -UTF8String LPWSTRToUtf8(LPWSTR str) +std::string LPWSTRToUtf8(LPWSTR str) { int utf8chars_num = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); - char* utf8 = new char[utf8chars_num]; - WideCharToMultiByte(CP_UTF8, 0, str, -1, utf8, utf8chars_num, NULL, NULL); + std::string utf8(utf8chars_num, '\0'); + WideCharToMultiByte(CP_UTF8, 0, str, -1, utf8.data(), utf8chars_num, NULL, NULL); return utf8; } @@ -236,12 +233,10 @@ void WebWindow::AttachWebView() _webviewWindow->AddScriptToExecuteOnDocumentCreated(L"window.external = { sendMessage: function(message) { window.chrome.webview.postMessage(message); }, receiveMessage: function(callback) { window.chrome.webview.addEventListener(\'message\', function(e) { callback(e.data); }); } };", nullptr); _webviewWindow->add_WebMessageReceived(Callback( [this](IWebView2WebView* webview, IWebView2WebMessageReceivedEventArgs* args) -> HRESULT { - PWSTR message; + wil::unique_cotaskmem_string message; args->get_WebMessageAsString(&message); - UTF8String messageUtf8 = LPWSTRToUtf8(message); - _webMessageReceivedCallback(messageUtf8); - delete[] messageUtf8; - CoTaskMemFree(message); + std::string messageUtf8 = LPWSTRToUtf8(message.get()); + _webMessageReceivedCallback(messageUtf8.data()); return S_OK; }).Get(), &webMessageToken); @@ -252,11 +247,9 @@ void WebWindow::AttachWebView() IWebView2WebResourceRequest* req; args->get_Request(&req); - LPWSTR uri; + wil::unique_cotaskmem_string uri; req->get_Uri(&uri); - UTF8String uriUtf8 = LPWSTRToUtf8(uri); - - std::string uriString(uriUtf8); + std::string uriString = LPWSTRToUtf8(uri.get()); size_t colonPos = uriString.find(':', 0); if (colonPos > 0) { @@ -266,28 +259,22 @@ void WebWindow::AttachWebView() { int numBytes; UTF8String contentType; - void* dotNetResponse = handler(uriUtf8, &numBytes, &contentType); + wil::unique_cotaskmem dotNetResponse(handler(uriString.data(), &numBytes, &contentType)); if (dotNetResponse != nullptr && contentType != nullptr) { - LPWSTR contentTypeW = Utf8ToLPWSTR(contentType); - std::wstring contentTypeWS(contentTypeW); + std::wstring contentTypeWS = Utf8ToLPWSTR(contentType); - IStream* dataStream = SHCreateMemStream((byte*)dotNetResponse, numBytes); + IStream* dataStream = SHCreateMemStream((BYTE*)dotNetResponse.get(), numBytes); wil::com_ptr response; _webviewEnvironment->CreateWebResourceResponse( dataStream, 200, L"OK", (L"Content-Type: " + contentTypeWS).c_str(), &response); args->put_Response(response.get()); - CoTaskMemFree(dotNetResponse); - delete[] contentTypeW; } } } - delete[] uriUtf8; - CoTaskMemFree(uri); - return S_OK; } ).Get(), &webResourceRequestedToken); @@ -321,23 +308,20 @@ void WebWindow::AttachWebView() void WebWindow::NavigateToUrl(UTF8String url) { - LPCWSTR urlW = Utf8ToLPWSTR(url); - _webviewWindow->Navigate(urlW); - delete[] urlW; + std::wstring urlW = Utf8ToLPWSTR(url); + _webviewWindow->Navigate(urlW.c_str()); } void WebWindow::NavigateToString(UTF8String content) { - LPCWSTR contentW = Utf8ToLPWSTR(content); - _webviewWindow->NavigateToString(contentW); - delete[] contentW; + std::wstring contentW = Utf8ToLPWSTR(content); + _webviewWindow->NavigateToString(contentW.c_str()); } void WebWindow::SendMessage(UTF8String message) { - LPCWSTR messageW = Utf8ToLPWSTR(message); - _webviewWindow->PostWebMessageAsString(messageW); - delete[] messageW; + std::wstring messageW = Utf8ToLPWSTR(message); + _webviewWindow->PostWebMessageAsString(messageW.c_str()); } void WebWindow::AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback requestHandler) diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index e7cab14..cfaf60d 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -1,25 +1,27 @@ -#pragma once -typedef char* UTF8String; +#ifndef WEBWINDOW_H +#define WEBWINDOW_H #ifdef _WIN32 #include -#include +#include #include #include #include -#include "WebView2.h" -typedef void(__stdcall* ACTION)(); -typedef void(__stdcall* WebMessageReceivedCallback)(UTF8String message); -typedef void* (__stdcall *WebResourceRequestedCallback) (UTF8String url, int* outNumBytes, UTF8String *outContentType); +#include +#define WEBWINDOW_STDCALL __stdcall #else - #ifdef OS_LINUX - #include - #endif -typedef void (*ACTION) (); -typedef void (*WebMessageReceivedCallback) (UTF8String message); -typedef void* (*WebResourceRequestedCallback) (UTF8String url, int* outNumBytes, UTF8String* outContentType); +#ifdef OS_LINUX +#include +#endif +#define WEBWINDOW_STDCALL #endif +typedef char* UTF8String; + +typedef void (WEBWINDOW_STDCALL* ACTION)(); +typedef void (WEBWINDOW_STDCALL* WebMessageReceivedCallback)(UTF8String message); +typedef void* (WEBWINDOW_STDCALL* WebResourceRequestedCallback)(UTF8String url, int* outNumBytes, UTF8String* outContentType); + class WebWindow { private: @@ -62,3 +64,5 @@ class WebWindow void SendMessage(UTF8String message); void AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback requestHandler); }; + +#endif // !WEBWINDOW_H From 27d4a5205244f7509eb4de3763e33baba60784ff Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 3 Dec 2019 21:33:08 +0800 Subject: [PATCH 02/47] Add GetSize & SetSize. --- src/WebWindow.Native/WebWindow.Linux.cpp | 10 ++++++++++ src/WebWindow.Native/WebWindow.Mac.mm | 20 ++++++++++++++++++++ src/WebWindow.Native/WebWindow.Windows.cpp | 13 +++++++++++++ src/WebWindow.Native/WebWindow.h | 2 ++ 4 files changed, 45 insertions(+) diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index 9dd6416..34f3981 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -215,4 +215,14 @@ void WebWindow::AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback (void*)requestHandler, NULL); } +void WebWindow::GetSize(int* width, int* height) +{ + gtk_window_get_size(_window, width, height); +} + +void WebWindow::SetSize(int width, int height) +{ + gtk_window_resize(_window, width, height); +} + #endif diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index cec29ba..92529ec 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -168,4 +168,24 @@ [webviewConfiguration setURLSchemeHandler:schemeHandler forURLScheme:nsscheme]; } +void WebWindow::GetSize(int* width, int* height) +{ + NSWindow* window = (NSWindow*)_window; + NSSize size = [[window contentView] frame].size; + if (width) *width = (int)roundf(size.width); + if (height) *height = (int)roundf(size.height); +} + +void WebWindow::SetSize(int width, int height) +{ + NSWindow* window = (NSWindow*)_window; + NSRect frame = [window frame]; + frame.origin.x -= frame.size.width; + frame.origin.x += (CGFloat)width; + frame.origin.y -= frame.size.height; + frame.origin.y += (CGFloat)height; + frame.size = CGSize(width: (CGFloat)width, height: (CGFloat)height); + [window setFrame: frame display: YES] +} + #endif diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index c88bf42..a2a3b0f 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -328,3 +328,16 @@ void WebWindow::AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback { _schemeToRequestHandler[scheme] = requestHandler; } + +void WebWindow::GetSize(int* width, int* height) +{ + RECT rect = {}; + GetWindowRect(_hWnd, &rect); + if (width) *width = rect.right - rect.left; + if (height) *height = rect.bottom - rect.top; +} + +void WebWindow::SetSize(int width, int height) +{ + SetWindowPos(_hWnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER); +} diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index cfaf60d..e7957f8 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -63,6 +63,8 @@ class WebWindow void NavigateToString(UTF8String content); void SendMessage(UTF8String message); void AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback requestHandler); + void GetSize(int* width, int* height); + void SetSize(int width, int height); }; #endif // !WEBWINDOW_H From 81fc8a4cdea2cdb6e304e94c4e5212bef2d8c8d5 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 3 Dec 2019 21:40:57 +0800 Subject: [PATCH 03/47] Add width and height property. --- src/WebWindow.Native/Exports.cpp | 15 +++++++++++ src/WebWindow/WebWindow.cs | 44 ++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/WebWindow.Native/Exports.cpp b/src/WebWindow.Native/Exports.cpp index 9d2a2f4..b85620d 100644 --- a/src/WebWindow.Native/Exports.cpp +++ b/src/WebWindow.Native/Exports.cpp @@ -30,6 +30,11 @@ extern "C" return new WebWindow(title, parent, webMessageReceivedCallback); } + EXPORTED void WebWindow_dtor(WebWindow* instance) + { + delete instance; + } + EXPORTED void WebWindow_SetTitle(WebWindow* instance, UTF8String title) { instance->SetTitle(title); @@ -74,4 +79,14 @@ extern "C" { instance->AddCustomScheme(scheme, requestHandler); } + + EXPORTED void WebWindow_GetSize(WebWindow* instance, int* width, int* height) + { + instance->GetSize(width, height); + } + + EXPORTED void WebWindow_SetSize(WebWindow* instance, int width, int height) + { + instance->SetSize(width, height); + } } diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index b73597d..255a60d 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -15,6 +15,7 @@ public class WebWindow [DllImport(DllName)] static extern IntPtr WebWindow_register_win32(IntPtr hInstance); [DllImport(DllName)] static extern IntPtr WebWindow_register_mac(); [DllImport(DllName)] static extern IntPtr WebWindow_ctor([MarshalAs(UnmanagedType.LPUTF8Str)] string title, IntPtr parentWebWindow, IntPtr webMessageReceivedCallback); + [DllImport(DllName)] static extern void WebWindow_dtor(IntPtr instance); [DllImport(DllName)] static extern IntPtr WebWindow_getHwnd_win32(IntPtr instance); [DllImport(DllName)] static extern void WebWindow_SetTitle(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string title); [DllImport(DllName)] static extern void WebWindow_Show(IntPtr instance); @@ -25,6 +26,8 @@ public class WebWindow [DllImport(DllName)] static extern void WebWindow_ShowMessage(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string title, [MarshalAs(UnmanagedType.LPUTF8Str)] string body, uint type); [DllImport(DllName)] static extern void WebWindow_SendMessage(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string message); [DllImport(DllName)] static extern void WebWindow_AddCustomScheme(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string scheme, IntPtr requestHandler); + [DllImport(DllName)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height); + [DllImport(DllName)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height); private List _gcHandlesToFree = new List(); private IntPtr _nativeWebWindow; @@ -212,5 +215,46 @@ private void AddCustomScheme(string scheme, ResolveWebResourceDelegate requestHa var callbackPtr = Marshal.GetFunctionPointerForDelegate(callback); WebWindow_AddCustomScheme(_nativeWebWindow, scheme, callbackPtr); } + + private int _width; + private int _height; + + private void GetSize() + { + WebWindow_GetSize(_nativeWebWindow, out _width, out _height); + } + + private void SetSize() + { + WebWindow_SetSize(_nativeWebWindow, _width, _height); + } + + public int Width + { + get + { + GetSize(); + return _width; + } + set + { + _width = value; + SetSize(); + } + } + + public int Height + { + get + { + GetSize(); + return _height; + } + set + { + _height = value; + SetSize(); + } + } } } From 8f4d41c6547408afc38e7c152f49b3bc6b2c821d Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 3 Dec 2019 21:41:31 +0800 Subject: [PATCH 04/47] Fix finilizer. --- src/WebWindow/WebWindow.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 255a60d..3ba633e 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -93,6 +93,7 @@ public WebWindow(string title, Action configure) gcHandle.Free(); } _gcHandlesToFree.Clear(); + WebWindow_dtor(_nativeWebWindow); } public void Show() => WebWindow_Show(_nativeWebWindow); From c049a98c33e2f5b8be05ccaa2fb3e8b47890c4fc Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 3 Dec 2019 21:50:13 +0800 Subject: [PATCH 05/47] Fix Mac code. --- src/WebWindow.Native/WebWindow.Mac.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index 92529ec..751218a 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -184,8 +184,8 @@ frame.origin.x += (CGFloat)width; frame.origin.y -= frame.size.height; frame.origin.y += (CGFloat)height; - frame.size = CGSize(width: (CGFloat)width, height: (CGFloat)height); - [window setFrame: frame display: YES] + frame.size = CGSize((CGFloat)width, (CGFloat)height); + [window setFrame: frame display: YES]; } #endif From e59397344c13afcc3e311825987c32c1650de336 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 3 Dec 2019 21:51:34 +0800 Subject: [PATCH 06/47] Fix Linux code. --- src/WebWindow.Native/WebWindow.Linux.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index 34f3981..8b25d4c 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -37,7 +37,7 @@ WebWindow::WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCall g_signal_connect(G_OBJECT(_window), "destroy", G_CALLBACK(+[](GtkWidget* w, gpointer arg) { gtk_main_quit(); - }), + }), this); } } @@ -217,12 +217,12 @@ void WebWindow::AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback void WebWindow::GetSize(int* width, int* height) { - gtk_window_get_size(_window, width, height); + gtk_window_get_size((GtkWindow*)_window, width, height); } void WebWindow::SetSize(int width, int height) { - gtk_window_resize(_window, width, height); + gtk_window_resize((GtkWindow*)_window, width, height); } #endif From ad87dc144437d001c685df7c7bf5b632871ec61a Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 3 Dec 2019 21:57:16 +0800 Subject: [PATCH 07/47] Fix Mac again. --- src/WebWindow.Native/WebWindow.Mac.mm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index 751218a..a221732 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -176,15 +176,17 @@ if (height) *height = (int)roundf(size.height); } -void WebWindow::SetSize(int width, int height) +void WebWindow::SetSize(int w, int h) { + CGFloat fw = (CGFloat)width; + CGFloat fh = (CGFloat)height; NSWindow* window = (NSWindow*)_window; NSRect frame = [window frame]; frame.origin.x -= frame.size.width; - frame.origin.x += (CGFloat)width; + frame.origin.x += fw; frame.origin.y -= frame.size.height; - frame.origin.y += (CGFloat)height; - frame.size = CGSize((CGFloat)width, (CGFloat)height); + frame.origin.y += fh; + frame.size = CGSize(fw, fh); [window setFrame: frame display: YES]; } From 7a3cbe9675eaac67c80787b97176ca5c22f963e4 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 3 Dec 2019 22:00:33 +0800 Subject: [PATCH 08/47] Fix typo. --- src/WebWindow.Native/WebWindow.Mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index a221732..c3ee288 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -176,7 +176,7 @@ if (height) *height = (int)roundf(size.height); } -void WebWindow::SetSize(int w, int h) +void WebWindow::SetSize(int width, int height) { CGFloat fw = (CGFloat)width; CGFloat fh = (CGFloat)height; From baa3a3d343e46b481d21acf9b2c2460ff2c5ed55 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 3 Dec 2019 22:05:01 +0800 Subject: [PATCH 09/47] Fix Mac. --- src/WebWindow.Native/WebWindow.Mac.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index c3ee288..f6d5d4b 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -176,17 +176,17 @@ if (height) *height = (int)roundf(size.height); } -void WebWindow::SetSize(int width, int height) +void WebWindow::SetSize(int w, int h) { - CGFloat fw = (CGFloat)width; - CGFloat fh = (CGFloat)height; + CGFloat fw = (CGFloat)w; + CGFloat fh = (CGFloat)h; NSWindow* window = (NSWindow*)_window; NSRect frame = [window frame]; frame.origin.x -= frame.size.width; frame.origin.x += fw; frame.origin.y -= frame.size.height; frame.origin.y += fh; - frame.size = CGSize(fw, fh); + frame.size = CGSize(width: fw, height: fh); [window setFrame: frame display: YES]; } From 5b25a010db83d2abc692ec98412a92a7ce2a5ff5 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 3 Dec 2019 22:12:12 +0800 Subject: [PATCH 10/47] Use CGSizeMake? --- src/WebWindow.Native/WebWindow.Mac.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index f6d5d4b..62ad446 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -176,17 +176,17 @@ if (height) *height = (int)roundf(size.height); } -void WebWindow::SetSize(int w, int h) +void WebWindow::SetSize(int width, int height) { - CGFloat fw = (CGFloat)w; - CGFloat fh = (CGFloat)h; + CGFloat fw = (CGFloat)width; + CGFloat fh = (CGFloat)height; NSWindow* window = (NSWindow*)_window; NSRect frame = [window frame]; frame.origin.x -= frame.size.width; frame.origin.x += fw; frame.origin.y -= frame.size.height; frame.origin.y += fh; - frame.size = CGSize(width: fw, height: fh); + frame.size = CGSizeMake(fw, fh); [window setFrame: frame display: YES]; } From 61d5299dcba9c5d8b13224846f1e628081687591 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sat, 7 Dec 2019 15:03:34 +0800 Subject: [PATCH 11/47] Add GetPosition & SetPosition. --- src/WebWindow.Native/WebWindow.Linux.cpp | 10 ++++++++++ src/WebWindow.Native/WebWindow.Mac.mm | 19 ++++++++++++++++++- src/WebWindow.Native/WebWindow.Windows.cpp | 13 +++++++++++++ src/WebWindow.Native/WebWindow.h | 2 ++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index 8b25d4c..dbd5c9e 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -225,4 +225,14 @@ void WebWindow::SetSize(int width, int height) gtk_window_resize((GtkWindow*)_window, width, height); } +void WebWindow::GetPosition(int* x, int* y) +{ + gtk_window_get_pos((GtkWindow*)_window, x, y); +} + +void WebWindow::SetPosition(int x, int y) +{ + gtk_window_move((GtkWindow*), _window, x, y); +} + #endif diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index 62ad446..ab51bc6 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -171,7 +171,7 @@ void WebWindow::GetSize(int* width, int* height) { NSWindow* window = (NSWindow*)_window; - NSSize size = [[window contentView] frame].size; + NSSize size = [window frame].size; if (width) *width = (int)roundf(size.width); if (height) *height = (int)roundf(size.height); } @@ -190,4 +190,21 @@ [window setFrame: frame display: YES]; } +void WebWindow::GetPosition(int* x, int* y) +{ + NSWindow* window = (NSWindow*)_window; + NSRect frame = [window frame]; + if (x) *x = (int)roundf(frame.origin.x - frame.size.width); + if (y) *y = (int)roundf(frame.origin.y - frame.size.height); +} + +void WebWindow::SetPosition(int x, int y) +{ + NSWindow* window = (NSWindow*)_window; + NSRect frame = [window frame]; + frame.origin.x = frame.size.width + (CGFloat)x; + frame.origin.y = frame.size.height + (CGFloat)y; + [window setFrame: frame display: YES]; +} + #endif diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index a2a3b0f..ae35b75 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -341,3 +341,16 @@ void WebWindow::SetSize(int width, int height) { SetWindowPos(_hWnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER); } + +void WebWindow::GetPosition(int* x, int* y) +{ + RECT rect = {}; + GetWindowRect(_hWnd, &rect); + if (x) *x = rect.left; + if (y) *y = rect.top; +} + +void WebWindow::SetPosition(int x, int y) +{ + SetWindowPos(_hWnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index e7957f8..b704030 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -65,6 +65,8 @@ class WebWindow void AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback requestHandler); void GetSize(int* width, int* height); void SetSize(int width, int height); + void GetPosition(int* x, int* y); + void SetPosition(int x, int y); }; #endif // !WEBWINDOW_H From b04cfefe27f8753080dbed72cbf8ccfd357de50c Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sat, 7 Dec 2019 15:21:27 +0800 Subject: [PATCH 12/47] Add location pinvoke. --- src/WebWindow.Native/Exports.cpp | 10 ++++ src/WebWindow/WebWindow.cs | 78 ++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/src/WebWindow.Native/Exports.cpp b/src/WebWindow.Native/Exports.cpp index b85620d..f598664 100644 --- a/src/WebWindow.Native/Exports.cpp +++ b/src/WebWindow.Native/Exports.cpp @@ -89,4 +89,14 @@ extern "C" { instance->SetSize(width, height); } + + EXPORTED void WebWindow_GetPosition(WebWindow* instance, int* x, int* y) + { + instance->GetPosition(x, y); + } + + EXPORTED void WebWindow_SetPosition(WebWindow* instance, int x, int y) + { + instance->SetPosition(x, y); + } } diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 3ba633e..bf4942a 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Threading; @@ -28,6 +29,8 @@ public class WebWindow [DllImport(DllName)] static extern void WebWindow_AddCustomScheme(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string scheme, IntPtr requestHandler); [DllImport(DllName)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height); [DllImport(DllName)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height); + [DllImport(DllName)] static extern void WebWindow_GetPosition(IntPtr instance, out int x, out int y); + [DllImport(DllName)] static extern void WebWindow_SetPosition(IntPtr instance, int x, int y); private List _gcHandlesToFree = new List(); private IntPtr _nativeWebWindow; @@ -220,15 +223,9 @@ private void AddCustomScheme(string scheme, ResolveWebResourceDelegate requestHa private int _width; private int _height; - private void GetSize() - { - WebWindow_GetSize(_nativeWebWindow, out _width, out _height); - } + private void GetSize() => WebWindow_GetSize(_nativeWebWindow, out _width, out _height); - private void SetSize() - { - WebWindow_SetSize(_nativeWebWindow, _width, _height); - } + private void SetSize() => WebWindow_SetSize(_nativeWebWindow, _width, _height); public int Width { @@ -257,5 +254,70 @@ public int Height SetSize(); } } + + public Size Size + { + get + { + GetSize(); + return new Size(_width, _height); + } + set + { + _width = value.Width; + _height = value.Height; + SetSize(); + } + } + + private int _x; + private int _y; + + private void GetPosition() => WebWindow_GetPosition(_nativeWebWindow, out _x, out _y); + + private void SetPosition() => WebWindow_SetPosition(_nativeWebWindow, _x, _y); + + public int Left + { + get + { + GetPosition(); + return _x; + } + set + { + _x = value; + SetPosition(); + } + } + + public int Top + { + get + { + GetPosition(); + return _y; + } + set + { + _y = value; + SetPosition(); + } + } + + public Point Location + { + get + { + GetPosition(); + return new Point(_x, _y); + } + set + { + _x = value.X; + _y = value.Y; + SetPosition(); + } + } } } From 0250361b65d0aed378bc9cd1e1a4e5799a2bd5e8 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sat, 7 Dec 2019 15:25:45 +0800 Subject: [PATCH 13/47] Fix typo. --- src/WebWindow.Native/WebWindow.Linux.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index dbd5c9e..f92d8fb 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -227,12 +227,12 @@ void WebWindow::SetSize(int width, int height) void WebWindow::GetPosition(int* x, int* y) { - gtk_window_get_pos((GtkWindow*)_window, x, y); + gtk_window_get_position((GtkWindow*)_window, x, y); } void WebWindow::SetPosition(int x, int y) { - gtk_window_move((GtkWindow*), _window, x, y); + gtk_window_move((GtkWindow*)_window, x, y); } #endif From 9df1f49734cc02140d588059bd981eb566a3e8aa Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sat, 7 Dec 2019 16:21:13 +0800 Subject: [PATCH 14/47] Add GetScreenSize & GetScreenDpi. --- src/WebWindow.Native/Exports.cpp | 12 +++++++++++- src/WebWindow.Native/WebWindow.Linux.cpp | 15 +++++++++++++++ src/WebWindow.Native/WebWindow.Mac.mm | 13 +++++++++++++ src/WebWindow.Native/WebWindow.Windows.cpp | 13 +++++++++++++ src/WebWindow.Native/WebWindow.h | 2 ++ src/WebWindow/WebWindow.cs | 17 +++++++++++++++++ 6 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/WebWindow.Native/Exports.cpp b/src/WebWindow.Native/Exports.cpp index f598664..ca70561 100644 --- a/src/WebWindow.Native/Exports.cpp +++ b/src/WebWindow.Native/Exports.cpp @@ -1,7 +1,7 @@ #include "WebWindow.h" #ifdef _WIN32 -# define EXPORTED __declspec( dllexport ) +# define EXPORTED __declspec(dllexport) #else # define EXPORTED #endif @@ -90,6 +90,16 @@ extern "C" instance->SetSize(width, height); } + EXPORTED void WebWindow_GetScreenSize(WebWindow* instance, int* width, int* height) + { + instance->GetScreenSize(width, height); + } + + EXPORTED unsigned int WebWindow_GetScreenDpi(WebWindow* instance) + { + return instance->GetScreenDpi(); + } + EXPORTED void WebWindow_GetPosition(WebWindow* instance, int* x, int* y) { instance->GetPosition(x, y); diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index f92d8fb..1fe5890 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -225,6 +225,21 @@ void WebWindow::SetSize(int width, int height) gtk_window_resize((GtkWindow*)_window, width, height); } +void WebWindow::GetScreenSize(int* width, int* height) +{ + GdkScreen* screen = gtk_window_get_screen((GtkWindow*)_window); + if (width) *width = gdk_screen_get_width(screen); + if (height) *height = gdk_screen_get_height(screen); +} + +unsigned int WebWindow::GetScreenDpi() +{ + GdkScreen* screen = gtk_window_get_screen((GtkWindow*)_window); + gdouble dpi = gdk_screen_get_resolution(screen); + if (dpi < 0) return 96; + else return (unsigned int)dpi; +} + void WebWindow::GetPosition(int* x, int* y) { gtk_window_get_position((GtkWindow*)_window, x, y); diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index ab51bc6..095d49b 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -190,6 +190,19 @@ [window setFrame: frame display: YES]; } +void WebWindow::GetScreenSize(int* width, int* height) +{ + NSWindow* window = (NSWindow*)_window; + NSSize size = [[window screen] frame].size; + if (width) *width = (int)roundf(size.width); + if (height) *height = (int)roundf(size.height); +} + +unsigned int WebWindow::GetScreenDpi() +{ + return 72; +} + void WebWindow::GetPosition(int* x, int* y) { NSWindow* window = (NSWindow*)_window; diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index ae35b75..0127c49 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -342,6 +342,19 @@ void WebWindow::SetSize(int width, int height) SetWindowPos(_hWnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER); } +void WebWindow::GetScreenSize(int* width, int* height) +{ + RECT rect = {}; + GetWindowRect(HWND_DESKTOP, &rect); + if (width) *width = rect.right - rect.left; + if (height) *height = rect.bottom - rect.top; +} + +unsigned int WebWindow::GetScreenDpi() +{ + return GetDpiForWindow(_hWnd); +} + void WebWindow::GetPosition(int* x, int* y) { RECT rect = {}; diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index b704030..d2de31d 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -65,6 +65,8 @@ class WebWindow void AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback requestHandler); void GetSize(int* width, int* height); void SetSize(int width, int height); + void GetScreenSize(int* width, int* height); + unsigned int GetScreenDpi(); void GetPosition(int* x, int* y); void SetPosition(int x, int y); }; diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index bf4942a..60a36e6 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -29,6 +29,8 @@ public class WebWindow [DllImport(DllName)] static extern void WebWindow_AddCustomScheme(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string scheme, IntPtr requestHandler); [DllImport(DllName)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height); [DllImport(DllName)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height); + [DllImport(DllName)] static extern void WebWindow_GetScreenSize(IntPtr instance, out int width, out int height); + [DllImport(DllName)] static extern uint WebWindow_GetScreenDpi(IntPtr instance); [DllImport(DllName)] static extern void WebWindow_GetPosition(IntPtr instance, out int x, out int y); [DllImport(DllName)] static extern void WebWindow_SetPosition(IntPtr instance, int x, int y); @@ -236,6 +238,7 @@ public int Width } set { + GetSize(); _width = value; SetSize(); } @@ -250,6 +253,7 @@ public int Height } set { + GetSize(); _height = value; SetSize(); } @@ -286,6 +290,7 @@ public int Left } set { + GetPosition(); _x = value; SetPosition(); } @@ -300,6 +305,7 @@ public int Top } set { + GetPosition(); _y = value; SetPosition(); } @@ -319,5 +325,16 @@ public Point Location SetPosition(); } } + + public Size ScreenSize + { + get + { + WebWindow_GetScreenSize(_nativeWebWindow, out int width, out int height); + return new Size(width, height); + } + } + + public uint ScreenDpi => WebWindow_GetScreenDpi(_nativeWebWindow); } } From fd636b539a08049af0cd6fbed2e881f66fd5fc95 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sat, 7 Dec 2019 22:55:40 +0800 Subject: [PATCH 15/47] Add dtor & Topmost. --- src/WebWindow.Native/WebWindow.Linux.cpp | 12 +++++++++++- src/WebWindow.Native/WebWindow.Mac.mm | 18 ++++++++++++++++++ src/WebWindow.Native/WebWindow.Windows.cpp | 8 ++++++++ src/WebWindow.Native/WebWindow.h | 2 ++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index 1fe5890..dc2f99e 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -37,11 +37,16 @@ WebWindow::WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCall g_signal_connect(G_OBJECT(_window), "destroy", G_CALLBACK(+[](GtkWidget* w, gpointer arg) { gtk_main_quit(); - }), + }), this); } } +WebWindow::~WebWindow() +{ + gtk_widget_destroy(_window); +} + void HandleWebMessage(WebKitUserContentManager* contentManager, WebKitJavascriptResult* jsResult, gpointer arg) { JSCValue* jsValue = webkit_javascript_result_get_js_value(jsResult); @@ -250,4 +255,9 @@ void WebWindow::SetPosition(int x, int y) gtk_window_move((GtkWindow*)_window, x, y); } +void WebWindow::SetTopmost(bool topmost) +{ + gtk_window_set_keep_above((GtkWindow*)_window, topmost ? TRUE : FALSE); +} + #endif diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index 095d49b..38e30e7 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -49,6 +49,17 @@ _webview = nil; } +WebWindow::~WebWindow() +{ + WKWebViewConfiguration *webViewConfiguration = (WKWebViewConfiguration*)_webviewConfiguration; + [webViewConfiguration release]; + WKWebView *webView = (WKWebView*)_webview; + [webView release]; + NSWindow* window = (NSWindow*)_window; + [window close]; + [window release]; +} + void WebWindow::AttachWebView() { MyUiDelegate *uiDelegate = [[[MyUiDelegate alloc] init] autorelease]; @@ -220,4 +231,11 @@ [window setFrame: frame display: YES]; } +void WebWindow::SetTopmost(bool topmost) +{ + NSWindow* window = (NSWindow*)_window; + if (topmost) [window setLevel:NSFloatingWindowLevel]; + else [window setLevel:NSNormalWindowLevel]; +} + #endif diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 0127c49..2663535 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -70,6 +70,9 @@ WebWindow::WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCall hwndToWebWindow[_hWnd] = this; } +// Needn't to release the handles. +WebWindow::~WebWindow() {} + HWND WebWindow::getHwnd() { return _hWnd; @@ -367,3 +370,8 @@ void WebWindow::SetPosition(int x, int y) { SetWindowPos(_hWnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } + +void WebWindow::SetTopmost(bool topmost) +{ + SetWindowPos(_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); +} diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index d2de31d..218b872 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -54,6 +54,7 @@ class WebWindow #endif WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback); + ~WebWindow(); void SetTitle(UTF8String title); void Show(); void WaitForExit(); @@ -69,6 +70,7 @@ class WebWindow unsigned int GetScreenDpi(); void GetPosition(int* x, int* y); void SetPosition(int x, int y); + void SetTopmost(bool topmost); }; #endif // !WEBWINDOW_H From bd9f56c72e391901ad13e83bc9449edcfe7204bb Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sat, 7 Dec 2019 22:58:45 +0800 Subject: [PATCH 16/47] Add Topmost prop. --- src/WebWindow.Native/Exports.cpp | 5 +++++ src/WebWindow/WebWindow.cs | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/WebWindow.Native/Exports.cpp b/src/WebWindow.Native/Exports.cpp index ca70561..1d0ad33 100644 --- a/src/WebWindow.Native/Exports.cpp +++ b/src/WebWindow.Native/Exports.cpp @@ -109,4 +109,9 @@ extern "C" { instance->SetPosition(x, y); } + + EXPORTED void WebWindow_SetTopmost(WebWindow* instance, int topmost) + { + instance->SetTopmost(topmost); + } } diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 60a36e6..23dfc7c 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -33,6 +33,7 @@ public class WebWindow [DllImport(DllName)] static extern uint WebWindow_GetScreenDpi(IntPtr instance); [DllImport(DllName)] static extern void WebWindow_GetPosition(IntPtr instance, out int x, out int y); [DllImport(DllName)] static extern void WebWindow_SetPosition(IntPtr instance, int x, int y); + [DllImport(DllName)] static extern void WebWindow_SetTopmost(IntPtr instance, int topmost); private List _gcHandlesToFree = new List(); private IntPtr _nativeWebWindow; @@ -336,5 +337,16 @@ public Size ScreenSize } public uint ScreenDpi => WebWindow_GetScreenDpi(_nativeWebWindow); + + private bool _topmost = false; + public bool Topmost + { + get => _topmost; + set + { + _topmost = value; + WebWindow_SetTopmost(_nativeWebWindow, _topmost ? 1 : 0); + } + } } } From 807cc17049b3a5963192e86e5e20b8265817ea3e Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sat, 7 Dec 2019 23:49:59 +0800 Subject: [PATCH 17/47] Clean-up: use auto charset for strings. --- src/WebWindow.Native/Exports.cpp | 14 ++-- src/WebWindow.Native/WebWindow.Native.vcxproj | 4 -- src/WebWindow.Native/WebWindow.Windows.cpp | 65 ++++++------------- src/WebWindow.Native/WebWindow.h | 24 +++---- src/WebWindow/WebWindow.cs | 26 +++++--- 5 files changed, 56 insertions(+), 77 deletions(-) diff --git a/src/WebWindow.Native/Exports.cpp b/src/WebWindow.Native/Exports.cpp index 1d0ad33..9b78200 100644 --- a/src/WebWindow.Native/Exports.cpp +++ b/src/WebWindow.Native/Exports.cpp @@ -25,7 +25,7 @@ extern "C" } #endif - EXPORTED WebWindow* WebWindow_ctor(UTF8String title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback) + EXPORTED WebWindow* WebWindow_ctor(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback) { return new WebWindow(title, parent, webMessageReceivedCallback); } @@ -35,7 +35,7 @@ extern "C" delete instance; } - EXPORTED void WebWindow_SetTitle(WebWindow* instance, UTF8String title) + EXPORTED void WebWindow_SetTitle(WebWindow* instance, AutoString title) { instance->SetTitle(title); } @@ -50,7 +50,7 @@ extern "C" instance->WaitForExit(); } - EXPORTED void WebWindow_ShowMessage(WebWindow* instance, UTF8String title, UTF8String body, unsigned int type) + EXPORTED void WebWindow_ShowMessage(WebWindow* instance, AutoString title, AutoString body, unsigned int type) { instance->ShowMessage(title, body, type); } @@ -60,22 +60,22 @@ extern "C" instance->Invoke(callback); } - EXPORTED void WebWindow_NavigateToString(WebWindow* instance, UTF8String content) + EXPORTED void WebWindow_NavigateToString(WebWindow* instance, AutoString content) { instance->NavigateToString(content); } - EXPORTED void WebWindow_NavigateToUrl(WebWindow* instance, UTF8String url) + EXPORTED void WebWindow_NavigateToUrl(WebWindow* instance, AutoString url) { instance->NavigateToUrl(url); } - EXPORTED void WebWindow_SendMessage(WebWindow* instance, UTF8String message) + EXPORTED void WebWindow_SendMessage(WebWindow* instance, AutoString message) { instance->SendMessage(message); } - EXPORTED void WebWindow_AddCustomScheme(WebWindow* instance, UTF8String scheme, WebResourceRequestedCallback requestHandler) + EXPORTED void WebWindow_AddCustomScheme(WebWindow* instance, AutoString scheme, WebResourceRequestedCallback requestHandler) { instance->AddCustomScheme(scheme, requestHandler); } diff --git a/src/WebWindow.Native/WebWindow.Native.vcxproj b/src/WebWindow.Native/WebWindow.Native.vcxproj index 939299a..3c5ef82 100644 --- a/src/WebWindow.Native/WebWindow.Native.vcxproj +++ b/src/WebWindow.Native/WebWindow.Native.vcxproj @@ -91,7 +91,6 @@ true WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp17 true @@ -105,7 +104,6 @@ true _DEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp17 true @@ -122,7 +120,6 @@ true WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp17 true @@ -140,7 +137,6 @@ true NDEBUG;_WINDOWS;%(PreprocessorDefinitions) true - stdcpp17 true diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 2663535..4e95809 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -13,7 +13,6 @@ using namespace Microsoft::WRL; LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -std::wstring Utf8ToLPWSTR(UTF8String str); LPCWSTR CLASS_NAME = L"WebWindow"; std::mutex invokeLockMutex; HINSTANCE WebWindow::_hInstance; @@ -47,16 +46,15 @@ void WebWindow::Register(HINSTANCE hInstance) SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); } -WebWindow::WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback) +WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback) { // Create the window _webMessageReceivedCallback = webMessageReceivedCallback; _parent = parent; - std::wstring wtitle = Utf8ToLPWSTR(title); _hWnd = CreateWindowExW( 0, // Optional window styles. CLASS_NAME, // Window class - wtitle.c_str(), // Window text + title, // Window text WS_OVERLAPPEDWINDOW, // Window style // Size and position @@ -138,10 +136,9 @@ void WebWindow::RefitContent() } } -void WebWindow::SetTitle(UTF8String title) +void WebWindow::SetTitle(AutoString title) { - std::wstring wtitle = Utf8ToLPWSTR(title); - SetWindowTextW(_hWnd, wtitle.c_str()); + SetWindowTextW(_hWnd, title); } void WebWindow::Show() @@ -170,11 +167,11 @@ void WebWindow::WaitForExit() } } -void WebWindow::ShowMessage(UTF8String title, UTF8String body, UINT type) +void WebWindow::ShowMessage(AutoString title, AutoString body, UINT type) { ShowMessageParams* params = new ShowMessageParams; - params->title = Utf8ToLPWSTR(title); - params->body = Utf8ToLPWSTR(body); + params->title = title; + params->body = body; params->type = type; PostMessageW(_hWnd, WM_USER_SHOWMESSAGE, (WPARAM)params, 0); } @@ -190,22 +187,6 @@ void WebWindow::Invoke(ACTION callback) waitInfo.completionNotifier.wait(uLock, [&] { return waitInfo.isCompleted; }); } -std::wstring Utf8ToLPWSTR(UTF8String str) -{ - int wchars_num = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); - std::wstring wstr(wchars_num, L'\0'); - MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr.data(), wchars_num); - return wstr; -} - -std::string LPWSTRToUtf8(LPWSTR str) -{ - int utf8chars_num = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); - std::string utf8(utf8chars_num, '\0'); - WideCharToMultiByte(CP_UTF8, 0, str, -1, utf8.data(), utf8chars_num, NULL, NULL); - return utf8; -} - void WebWindow::AttachWebView() { std::atomic_flag flag = ATOMIC_FLAG_INIT; @@ -238,8 +219,7 @@ void WebWindow::AttachWebView() [this](IWebView2WebView* webview, IWebView2WebMessageReceivedEventArgs* args) -> HRESULT { wil::unique_cotaskmem_string message; args->get_WebMessageAsString(&message); - std::string messageUtf8 = LPWSTRToUtf8(message.get()); - _webMessageReceivedCallback(messageUtf8.data()); + _webMessageReceivedCallback(message.get()); return S_OK; }).Get(), &webMessageToken); @@ -252,21 +232,21 @@ void WebWindow::AttachWebView() wil::unique_cotaskmem_string uri; req->get_Uri(&uri); - std::string uriString = LPWSTRToUtf8(uri.get()); - size_t colonPos = uriString.find(':', 0); + std::wstring uriString = uri.get(); + size_t colonPos = uriString.find(L':', 0); if (colonPos > 0) { - std::string scheme = uriString.substr(0, colonPos); + std::wstring scheme = uriString.substr(0, colonPos); WebResourceRequestedCallback handler = _schemeToRequestHandler[scheme]; if (handler != NULL) { int numBytes; - UTF8String contentType; - wil::unique_cotaskmem dotNetResponse(handler(uriString.data(), &numBytes, &contentType)); + AutoString contentType; + wil::unique_cotaskmem dotNetResponse(handler(uriString.c_str(), &numBytes, &contentType)); if (dotNetResponse != nullptr && contentType != nullptr) { - std::wstring contentTypeWS = Utf8ToLPWSTR(contentType); + std::wstring contentTypeWS = contentType; IStream* dataStream = SHCreateMemStream((BYTE*)dotNetResponse.get(), numBytes); wil::com_ptr response; @@ -309,25 +289,22 @@ void WebWindow::AttachWebView() } } -void WebWindow::NavigateToUrl(UTF8String url) +void WebWindow::NavigateToUrl(AutoString url) { - std::wstring urlW = Utf8ToLPWSTR(url); - _webviewWindow->Navigate(urlW.c_str()); + _webviewWindow->Navigate(url); } -void WebWindow::NavigateToString(UTF8String content) +void WebWindow::NavigateToString(AutoString content) { - std::wstring contentW = Utf8ToLPWSTR(content); - _webviewWindow->NavigateToString(contentW.c_str()); + _webviewWindow->NavigateToString(content); } -void WebWindow::SendMessage(UTF8String message) +void WebWindow::SendMessage(AutoString message) { - std::wstring messageW = Utf8ToLPWSTR(message); - _webviewWindow->PostWebMessageAsString(messageW.c_str()); + _webviewWindow->PostWebMessageAsString(message); } -void WebWindow::AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback requestHandler) +void WebWindow::AddCustomScheme(AutoString scheme, WebResourceRequestedCallback requestHandler) { _schemeToRequestHandler[scheme] = requestHandler; } diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index 218b872..9452e8c 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -9,18 +9,18 @@ #include #include #define WEBWINDOW_STDCALL __stdcall +typedef const wchar_t* AutoString; #else #ifdef OS_LINUX #include #endif #define WEBWINDOW_STDCALL +typedef const char* AutoString; #endif -typedef char* UTF8String; - typedef void (WEBWINDOW_STDCALL* ACTION)(); -typedef void (WEBWINDOW_STDCALL* WebMessageReceivedCallback)(UTF8String message); -typedef void* (WEBWINDOW_STDCALL* WebResourceRequestedCallback)(UTF8String url, int* outNumBytes, UTF8String* outContentType); +typedef void (WEBWINDOW_STDCALL* WebMessageReceivedCallback)(AutoString message); +typedef void* (WEBWINDOW_STDCALL* WebResourceRequestedCallback)(AutoString url, int* outNumBytes, AutoString* outContentType); class WebWindow { @@ -32,7 +32,7 @@ class WebWindow WebWindow* _parent; wil::com_ptr _webviewEnvironment; wil::com_ptr _webviewWindow; - std::map _schemeToRequestHandler; + std::map _schemeToRequestHandler; void AttachWebView(); #elif OS_LINUX GtkWidget* _window; @@ -53,17 +53,17 @@ class WebWindow static void Register(); #endif - WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback); + WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback); ~WebWindow(); - void SetTitle(UTF8String title); + void SetTitle(AutoString title); void Show(); void WaitForExit(); - void ShowMessage(UTF8String title, UTF8String body, unsigned int type); + void ShowMessage(AutoString title, AutoString body, unsigned int type); void Invoke(ACTION callback); - void NavigateToUrl(UTF8String url); - void NavigateToString(UTF8String content); - void SendMessage(UTF8String message); - void AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback requestHandler); + void NavigateToUrl(AutoString url); + void NavigateToString(AutoString content); + void SendMessage(AutoString message); + void AddCustomScheme(AutoString scheme, WebResourceRequestedCallback requestHandler); void GetSize(int* width, int* height); void SetSize(int width, int height); void GetScreenSize(int* width, int* height); diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 23dfc7c..546116e 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -9,24 +9,30 @@ namespace WebWindows { public class WebWindow { - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void OnWebMessageReceivedCallback([MarshalAs(UnmanagedType.LPUTF8Str)] string message); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate IntPtr OnWebResourceRequestedCallback([MarshalAs(UnmanagedType.LPUTF8Str)] string url, out int numBytes, [MarshalAs(UnmanagedType.LPUTF8Str)] out string contentType); + // Here we use auto charset instead of forcing UTF-8. + // Thus the native code for Windows will be much more simple. + // Auto charset is UTF-16 on Windows and UTF-8 on Unix(.NET Core 3.0 and later and Mono). + // As we target .NET Standard 2.1, we assume it runs on .NET Core 3.0 and later. + // We should specify using auto charset because the default value is ANSI. + + [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] delegate void OnWebMessageReceivedCallback(string message); + [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] delegate IntPtr OnWebResourceRequestedCallback(string url, out int numBytes, out string contentType); const string DllName = "WebWindow.Native"; [DllImport(DllName)] static extern IntPtr WebWindow_register_win32(IntPtr hInstance); [DllImport(DllName)] static extern IntPtr WebWindow_register_mac(); - [DllImport(DllName)] static extern IntPtr WebWindow_ctor([MarshalAs(UnmanagedType.LPUTF8Str)] string title, IntPtr parentWebWindow, IntPtr webMessageReceivedCallback); + [DllImport(DllName, CharSet = CharSet.Auto)] static extern IntPtr WebWindow_ctor(string title, IntPtr parentWebWindow, IntPtr webMessageReceivedCallback); [DllImport(DllName)] static extern void WebWindow_dtor(IntPtr instance); [DllImport(DllName)] static extern IntPtr WebWindow_getHwnd_win32(IntPtr instance); - [DllImport(DllName)] static extern void WebWindow_SetTitle(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string title); + [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_SetTitle(IntPtr instance, string title); [DllImport(DllName)] static extern void WebWindow_Show(IntPtr instance); [DllImport(DllName)] static extern void WebWindow_WaitForExit(IntPtr instance); [DllImport(DllName)] static extern void WebWindow_Invoke(IntPtr instance, IntPtr callback); - [DllImport(DllName)] static extern void WebWindow_NavigateToString(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string content); - [DllImport(DllName)] static extern void WebWindow_NavigateToUrl(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string url); - [DllImport(DllName)] static extern void WebWindow_ShowMessage(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string title, [MarshalAs(UnmanagedType.LPUTF8Str)] string body, uint type); - [DllImport(DllName)] static extern void WebWindow_SendMessage(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string message); - [DllImport(DllName)] static extern void WebWindow_AddCustomScheme(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string scheme, IntPtr requestHandler); + [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_NavigateToString(IntPtr instance, string content); + [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_NavigateToUrl(IntPtr instance, string url); + [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_ShowMessage(IntPtr instance, string title, string body, uint type); + [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_SendMessage(IntPtr instance, string message); + [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_AddCustomScheme(IntPtr instance, string scheme, IntPtr requestHandler); [DllImport(DllName)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height); [DllImport(DllName)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height); [DllImport(DllName)] static extern void WebWindow_GetScreenSize(IntPtr instance, out int width, out int height); @@ -182,7 +188,7 @@ private void WriteTitleField(string value) _title = value; } - private void ReceiveWebMessage([MarshalAs(UnmanagedType.LPUTF8Str)] string message) + private void ReceiveWebMessage(string message) { OnWebMessageReceived?.Invoke(this, message); } From 93edc2c9a6a66367e8216ac00e6d30bfda4282a0 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sat, 7 Dec 2019 23:58:08 +0800 Subject: [PATCH 18/47] Add UTF8String typedef. --- src/WebWindow.Native/WebWindow.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index 9452e8c..4e4eea4 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -16,6 +16,7 @@ typedef const wchar_t* AutoString; #endif #define WEBWINDOW_STDCALL typedef const char* AutoString; +typedef AutoString UTF8String; #endif typedef void (WEBWINDOW_STDCALL* ACTION)(); From 30c73ce12c2dfd2dde04e03923c1012ccde7a605 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 00:02:53 +0800 Subject: [PATCH 19/47] Fix string define on Unix. --- src/WebWindow.Native/WebWindow.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index 4e4eea4..1a824c4 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -15,7 +15,7 @@ typedef const wchar_t* AutoString; #include #endif #define WEBWINDOW_STDCALL -typedef const char* AutoString; +typedef char* AutoString; typedef AutoString UTF8String; #endif From 59f8eb0364c74ce0fc9eb04b0bf78f752e47ffe1 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 11:07:37 +0800 Subject: [PATCH 20/47] Add SetResizable. --- src/WebWindow.Native/Exports.cpp | 5 +++++ src/WebWindow.Native/WebWindow.Linux.cpp | 9 ++++++--- src/WebWindow.Native/WebWindow.Mac.mm | 7 +++++++ src/WebWindow.Native/WebWindow.Windows.cpp | 8 ++++++++ src/WebWindow.Native/WebWindow.h | 1 + src/WebWindow/WebWindow.cs | 22 ++++++++++++++++++++-- 6 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/WebWindow.Native/Exports.cpp b/src/WebWindow.Native/Exports.cpp index 9b78200..4f85951 100644 --- a/src/WebWindow.Native/Exports.cpp +++ b/src/WebWindow.Native/Exports.cpp @@ -80,6 +80,11 @@ extern "C" instance->AddCustomScheme(scheme, requestHandler); } + EXPORTED void WebWindow_SetResizable(WebWindow* instance, int resizable) + { + instance->SetResizable(resizable); + } + EXPORTED void WebWindow_GetSize(WebWindow* instance, int* width, int* height) { instance->GetSize(width, height); diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index dc2f99e..4f383ee 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -35,9 +35,7 @@ WebWindow::WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCall if (parent == NULL) { g_signal_connect(G_OBJECT(_window), "destroy", - G_CALLBACK(+[](GtkWidget* w, gpointer arg) { - gtk_main_quit(); - }), + G_CALLBACK(+[](GtkWidget* w, gpointer arg) { gtk_main_quit(); }), this); } } @@ -220,6 +218,11 @@ void WebWindow::AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback (void*)requestHandler, NULL); } +void WebWindow::SetResizable(bool resizable) +{ + gtk_window_set_resizable((GtkWindow*)_window, resizable ? TRUE : FALSE); +} + void WebWindow::GetSize(int* width, int* height) { gtk_window_get_size((GtkWindow*)_window, width, height); diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index 38e30e7..da05053 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -179,6 +179,13 @@ [webviewConfiguration setURLSchemeHandler:schemeHandler forURLScheme:nsscheme]; } +void WebWindow::SetResizable(bool resizable) +{ + NSWindow* window = (NSWindow*)_window; + if (resizable) window.styleMask |= NSWindowStyleMaskResizable; + else window.styleMask &= ~NSWindowStyleMaskResizable; +} + void WebWindow::GetSize(int* width, int* height) { NSWindow* window = (NSWindow*)_window; diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 4e95809..ac895c5 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -309,6 +309,14 @@ void WebWindow::AddCustomScheme(AutoString scheme, WebResourceRequestedCallback _schemeToRequestHandler[scheme] = requestHandler; } +void WebWindow::SetResizable(bool resizable) +{ + LONG_PTR style = GetWindowLongPtr(_hWnd, GWL_STYLE); + if (resizable) style |= WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; + else style &= (~WS_THICKFRAME) & (~WS_MINIMIZEBOX) & (~WS_MAXIMIZEBOX); + SetWindowLongPtr(_hWnd, GWL_STYLE, style); +} + void WebWindow::GetSize(int* width, int* height) { RECT rect = {}; diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index 1a824c4..f840e30 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -65,6 +65,7 @@ class WebWindow void NavigateToString(AutoString content); void SendMessage(AutoString message); void AddCustomScheme(AutoString scheme, WebResourceRequestedCallback requestHandler); + void SetResizable(bool resizable); void GetSize(int* width, int* height); void SetSize(int width, int height); void GetScreenSize(int* width, int* height); diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 546116e..f5fb2fb 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -33,6 +33,7 @@ public class WebWindow [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_ShowMessage(IntPtr instance, string title, string body, uint type); [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_SendMessage(IntPtr instance, string message); [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_AddCustomScheme(IntPtr instance, string scheme, IntPtr requestHandler); + [DllImport(DllName)] static extern void WebWindow_SetResizable(IntPtr instance, int resizable); [DllImport(DllName)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height); [DllImport(DllName)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height); [DllImport(DllName)] static extern void WebWindow_GetScreenSize(IntPtr instance, out int width, out int height); @@ -229,6 +230,20 @@ private void AddCustomScheme(string scheme, ResolveWebResourceDelegate requestHa WebWindow_AddCustomScheme(_nativeWebWindow, scheme, callbackPtr); } + private bool _resizable = false; + public bool Resizable + { + get => _resizable; + set + { + if (_resizable != value) + { + _resizable = value; + WebWindow_SetResizable(_nativeWebWindow, _resizable ? 1 : 0); + } + } + } + private int _width; private int _height; @@ -350,8 +365,11 @@ public bool Topmost get => _topmost; set { - _topmost = value; - WebWindow_SetTopmost(_nativeWebWindow, _topmost ? 1 : 0); + if (_topmost != value) + { + _topmost = value; + WebWindow_SetTopmost(_nativeWebWindow, _topmost ? 1 : 0); + } } } } From 0c25fc7876d50a04c4ee97a8aa36377ccae0e435 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 11:22:14 +0800 Subject: [PATCH 21/47] Add size demo. --- src/WebWindow.Blazor/ComponentsDesktop.cs | 16 ++++++++-------- src/WebWindow.Native/WebWindow.Windows.cpp | 2 +- src/WebWindow/WebWindow.cs | 2 +- testassets/MyBlazorApp/Pages/Size.razor | 15 +++++++++++++++ testassets/MyBlazorApp/Shared/NavMenu.razor | 5 +++++ testassets/MyBlazorApp/_Imports.razor | 1 + 6 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 testassets/MyBlazorApp/Pages/Size.razor diff --git a/src/WebWindow.Blazor/ComponentsDesktop.cs b/src/WebWindow.Blazor/ComponentsDesktop.cs index e9f9a52..c7ceee6 100644 --- a/src/WebWindow.Blazor/ComponentsDesktop.cs +++ b/src/WebWindow.Blazor/ComponentsDesktop.cs @@ -20,8 +20,7 @@ public static class ComponentsDesktop internal static string BaseUriAbsolute { get; private set; } internal static DesktopJSRuntime DesktopJSRuntime { get; private set; } internal static DesktopRenderer DesktopRenderer { get; private set; } - - internal static WebWindow webWindow; + internal static WebWindow WebWindow { get; private set; } public static void Run(string windowTitle, string hostHtmlPath) { @@ -30,7 +29,7 @@ public static void Run(string windowTitle, string hostHtmlPath) UnhandledException(exception); }; - webWindow = new WebWindow(windowTitle, options => + WebWindow = new WebWindow(windowTitle, options => { var contentRootAbsolute = Path.GetDirectoryName(Path.GetFullPath(hostHtmlPath)); @@ -57,11 +56,11 @@ public static void Run(string windowTitle, string hostHtmlPath) }); CancellationTokenSource appLifetimeCts = new CancellationTokenSource(); - Task.Factory.StartNew(async() => + Task.Factory.StartNew(async () => { try { - var ipc = new IPC(webWindow); + var ipc = new IPC(WebWindow); await RunAsync(ipc, appLifetimeCts.Token); } catch (Exception ex) @@ -73,8 +72,8 @@ public static void Run(string windowTitle, string hostHtmlPath) try { - webWindow.NavigateToUrl(BlazorAppScheme + "://app/"); - webWindow.WaitForExit(); + WebWindow.NavigateToUrl(BlazorAppScheme + "://app/"); + WebWindow.WaitForExit(); } finally { @@ -110,7 +109,7 @@ private static string BlazorAppScheme private static void UnhandledException(Exception ex) { - webWindow.ShowMessage("Error", $"{ex.Message}\n{ex.StackTrace}"); + WebWindow.ShowMessage("Error", $"{ex.Message}\n{ex.StackTrace}"); } private static async Task RunAsync(IPC ipc, CancellationToken appLifetime) @@ -124,6 +123,7 @@ private static async Task RunAsync(IPC ipc, CancellationToken appLifet serviceCollection.AddSingleton(DesktopNavigationManager.Instance); serviceCollection.AddSingleton(DesktopJSRuntime); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(WebWindow); var startup = new ConventionBasedStartup(Activator.CreateInstance(typeof(TStartup))); startup.ConfigureServices(serviceCollection); diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index ac895c5..3ad2eda 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -333,7 +333,7 @@ void WebWindow::SetSize(int width, int height) void WebWindow::GetScreenSize(int* width, int* height) { RECT rect = {}; - GetWindowRect(HWND_DESKTOP, &rect); + GetWindowRect(GetDesktopWindow(), &rect); if (width) *width = rect.right - rect.left; if (height) *height = rect.bottom - rect.top; } diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index f5fb2fb..0d5a900 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -230,7 +230,7 @@ private void AddCustomScheme(string scheme, ResolveWebResourceDelegate requestHa WebWindow_AddCustomScheme(_nativeWebWindow, scheme, callbackPtr); } - private bool _resizable = false; + private bool _resizable = true; public bool Resizable { get => _resizable; diff --git a/testassets/MyBlazorApp/Pages/Size.razor b/testassets/MyBlazorApp/Pages/Size.razor new file mode 100644 index 0000000..165db27 --- /dev/null +++ b/testassets/MyBlazorApp/Pages/Size.razor @@ -0,0 +1,15 @@ +@page "/size" +@inject WebWindow Window + +

Size demo

+

Screen size

+

Width: @Window.ScreenSize.Width, Height: @Window.ScreenSize.Height, DPI: @Window.ScreenDpi

+

Window size

+

Width: @Window.Width, Height: @Window.Height

+

Window location

+

Left: @Window.Left, Top: @Window.Top

+

Window properties

+Resizable +
+Topmost +
diff --git a/testassets/MyBlazorApp/Shared/NavMenu.razor b/testassets/MyBlazorApp/Shared/NavMenu.razor index fbf2526..a695cdb 100644 --- a/testassets/MyBlazorApp/Shared/NavMenu.razor +++ b/testassets/MyBlazorApp/Shared/NavMenu.razor @@ -22,6 +22,11 @@ Fetch data + diff --git a/testassets/MyBlazorApp/_Imports.razor b/testassets/MyBlazorApp/_Imports.razor index 0661f47..2d99771 100644 --- a/testassets/MyBlazorApp/_Imports.razor +++ b/testassets/MyBlazorApp/_Imports.razor @@ -6,3 +6,4 @@ @using Microsoft.JSInterop @using MyBlazorApp @using MyBlazorApp.Shared +@using WebWindows; From 8d8d67811a35c3c7d4682baf91522bfaf8460858 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 18:31:00 +0800 Subject: [PATCH 22/47] Remove function ptr allocations. --- src/WebWindow.Native/WebWindow.Windows.cpp | 2 +- src/WebWindow/WebWindow.cs | 17 ++++++----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 3ad2eda..a4d9d20 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -358,5 +358,5 @@ void WebWindow::SetPosition(int x, int y) void WebWindow::SetTopmost(bool topmost) { - SetWindowPos(_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + SetWindowPos(_hWnd, topmost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 0d5a900..d70f123 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -21,18 +21,18 @@ public class WebWindow const string DllName = "WebWindow.Native"; [DllImport(DllName)] static extern IntPtr WebWindow_register_win32(IntPtr hInstance); [DllImport(DllName)] static extern IntPtr WebWindow_register_mac(); - [DllImport(DllName, CharSet = CharSet.Auto)] static extern IntPtr WebWindow_ctor(string title, IntPtr parentWebWindow, IntPtr webMessageReceivedCallback); + [DllImport(DllName, CharSet = CharSet.Auto)] static extern IntPtr WebWindow_ctor(string title, IntPtr parentWebWindow, OnWebMessageReceivedCallback webMessageReceivedCallback); [DllImport(DllName)] static extern void WebWindow_dtor(IntPtr instance); [DllImport(DllName)] static extern IntPtr WebWindow_getHwnd_win32(IntPtr instance); [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_SetTitle(IntPtr instance, string title); [DllImport(DllName)] static extern void WebWindow_Show(IntPtr instance); [DllImport(DllName)] static extern void WebWindow_WaitForExit(IntPtr instance); - [DllImport(DllName)] static extern void WebWindow_Invoke(IntPtr instance, IntPtr callback); + [DllImport(DllName)] static extern void WebWindow_Invoke(IntPtr instance, Action callback); [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_NavigateToString(IntPtr instance, string content); [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_NavigateToUrl(IntPtr instance, string url); [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_ShowMessage(IntPtr instance, string title, string body, uint type); [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_SendMessage(IntPtr instance, string message); - [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_AddCustomScheme(IntPtr instance, string scheme, IntPtr requestHandler); + [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_AddCustomScheme(IntPtr instance, string scheme, OnWebResourceRequestedCallback requestHandler); [DllImport(DllName)] static extern void WebWindow_SetResizable(IntPtr instance, int resizable); [DllImport(DllName)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height); [DllImport(DllName)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height); @@ -83,10 +83,9 @@ public WebWindow(string title, Action configure) var onWebMessageReceivedDelegate = (OnWebMessageReceivedCallback)ReceiveWebMessage; _gcHandlesToFree.Add(GCHandle.Alloc(onWebMessageReceivedDelegate)); - var onWebMessageReceivedPtr = Marshal.GetFunctionPointerForDelegate(onWebMessageReceivedDelegate); var parentPtr = options.Parent?._nativeWebWindow ?? default; - _nativeWebWindow = WebWindow_ctor(_title, parentPtr, onWebMessageReceivedPtr); + _nativeWebWindow = WebWindow_ctor(_title, parentPtr, onWebMessageReceivedDelegate); foreach (var (schemeName, handler) in options.SchemeHandlers) { @@ -129,9 +128,7 @@ public void ShowMessage(string title, string body) public void Invoke(Action workItem) { - var fnPtr = Marshal.GetFunctionPointerForDelegate(workItem); - WebWindow_Invoke(_nativeWebWindow, fnPtr); - GC.KeepAlive(fnPtr); + WebWindow_Invoke(_nativeWebWindow, workItem); } public IntPtr Hwnd @@ -225,9 +222,7 @@ private void AddCustomScheme(string scheme, ResolveWebResourceDelegate requestHa }; _gcHandlesToFree.Add(GCHandle.Alloc(callback)); - - var callbackPtr = Marshal.GetFunctionPointerForDelegate(callback); - WebWindow_AddCustomScheme(_nativeWebWindow, scheme, callbackPtr); + WebWindow_AddCustomScheme(_nativeWebWindow, scheme, callback); } private bool _resizable = true; From 36cbb64f785105e8327d1e98929aa4917394ecf1 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 18:51:06 +0800 Subject: [PATCH 23/47] Add FreeHGlobal. --- src/WebWindow/WebWindow.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index d70f123..cc06da6 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -43,6 +43,7 @@ public class WebWindow [DllImport(DllName)] static extern void WebWindow_SetTopmost(IntPtr instance, int topmost); private List _gcHandlesToFree = new List(); + private List _hGlobalToFree = new List(); private IntPtr _nativeWebWindow; private string _title; @@ -105,6 +106,11 @@ public WebWindow(string title, Action configure) gcHandle.Free(); } _gcHandlesToFree.Clear(); + foreach (var handle in _hGlobalToFree) + { + Marshal.FreeHGlobal(handle); + } + _hGlobalToFree.Clear(); WebWindow_dtor(_nativeWebWindow); } @@ -217,6 +223,7 @@ private void AddCustomScheme(string scheme, ResolveWebResourceDelegate requestHa numBytes = (int)ms.Position; var buffer = Marshal.AllocHGlobal(numBytes); Marshal.Copy(ms.GetBuffer(), 0, buffer, numBytes); + _hGlobalToFree.Add(buffer); return buffer; } }; From ea98b3ab1f225e064b56e46167b7693fdda96b97 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 18:58:03 +0800 Subject: [PATCH 24/47] Demo: input size and location. --- testassets/MyBlazorApp/Pages/Size.razor | 36 ++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/testassets/MyBlazorApp/Pages/Size.razor b/testassets/MyBlazorApp/Pages/Size.razor index 165db27..179e80d 100644 --- a/testassets/MyBlazorApp/Pages/Size.razor +++ b/testassets/MyBlazorApp/Pages/Size.razor @@ -5,11 +5,35 @@

Screen size

Width: @Window.ScreenSize.Width, Height: @Window.ScreenSize.Height, DPI: @Window.ScreenDpi

Window size

-

Width: @Window.Width, Height: @Window.Height

+
+
+ + +
+
+ + +
+

Window location

-

Left: @Window.Left, Top: @Window.Top

+
+
+ + +
+
+ + +
+

Window properties

-Resizable -
-Topmost -
+
+
+ + +
+
+ + +
+
From 0b0b526bffc2c19fec186fc5f25ec5c1fe32e02d Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 22:03:35 +0800 Subject: [PATCH 25/47] Add SetIconFile. --- src/WebWindow.Native/Exports.cpp | 5 +++++ src/WebWindow.Native/WebWindow.Linux.cpp | 5 +++++ src/WebWindow.Native/WebWindow.Mac.mm | 11 +++++++++++ src/WebWindow.Native/WebWindow.Windows.cpp | 6 ++++++ src/WebWindow.Native/WebWindow.h | 1 + src/WebWindow/WebWindow.cs | 3 +++ 6 files changed, 31 insertions(+) diff --git a/src/WebWindow.Native/Exports.cpp b/src/WebWindow.Native/Exports.cpp index 4f85951..c9f1131 100644 --- a/src/WebWindow.Native/Exports.cpp +++ b/src/WebWindow.Native/Exports.cpp @@ -119,4 +119,9 @@ extern "C" { instance->SetTopmost(topmost); } + + EXPORTED void WebWindow_SetIconFile(WebWindow* instance, AutoString filename) + { + instance->SetIconFile(filename); + } } diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index 4f383ee..229efa9 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -263,4 +263,9 @@ void WebWindow::SetTopmost(bool topmost) gtk_window_set_keep_above((GtkWindow*)_window, topmost ? TRUE : FALSE); } +void WebWindow::SetIconFile(AutoString filename) +{ + gtk_window_set_icon_from_file((GtkWindow*)_window, filename, NULL); +} + #endif diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index da05053..72b57e8 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -245,4 +245,15 @@ else [window setLevel:NSNormalWindowLevel]; } +void WebWindow::SetIconFile(AutoString filename) +{ + NSString* path = [[NSString stringWithUTF8String:filename] autorelease]; + NSImage* icon = [[NSImage alloc] initWithContentsOfFile:path]; + if (icon != nil) + { + NSWindow* window = (NSWindow*)_window; + [[window standardWindowButton:NSWindowDocumentIconButton] setImage:icon]; + } +} + #endif diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index a4d9d20..6748c14 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -360,3 +360,9 @@ void WebWindow::SetTopmost(bool topmost) { SetWindowPos(_hWnd, topmost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } + +void WebWindow::SetIconFile(AutoString filename) +{ + HICON icon = (HICON)LoadImage(NULL, filename, IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_SHARED); + SetWindowLongPtr(_hWnd, GCLP_HICON, (LONG_PTR)icon); +} diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index f840e30..c86bcdd 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -73,6 +73,7 @@ class WebWindow void GetPosition(int* x, int* y); void SetPosition(int x, int y); void SetTopmost(bool topmost); + void SetIconFile(AutoString filename); }; #endif // !WEBWINDOW_H diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index cc06da6..116b712 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -41,6 +41,7 @@ public class WebWindow [DllImport(DllName)] static extern void WebWindow_GetPosition(IntPtr instance, out int x, out int y); [DllImport(DllName)] static extern void WebWindow_SetPosition(IntPtr instance, int x, int y); [DllImport(DllName)] static extern void WebWindow_SetTopmost(IntPtr instance, int topmost); + [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_SetIconFile(IntPtr instance, string filename); private List _gcHandlesToFree = new List(); private List _hGlobalToFree = new List(); @@ -374,5 +375,7 @@ public bool Topmost } } } + + public void SetIconFile(string filename) => WebWindow_SetIconFile(_nativeWebWindow, filename); } } From c46b63f88e08c9766242d87ab3769b59653b2e71 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 22:10:51 +0800 Subject: [PATCH 26/47] Fix calling convention. It is necessary if we want to implement for 32-bit Windows. --- src/WebWindow.Native/WebWindow.h | 8 ++---- src/WebWindow/WebWindow.cs | 49 ++++++++++++++++---------------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index c86bcdd..41cbdf1 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -8,20 +8,18 @@ #include #include #include -#define WEBWINDOW_STDCALL __stdcall typedef const wchar_t* AutoString; #else #ifdef OS_LINUX #include #endif -#define WEBWINDOW_STDCALL typedef char* AutoString; typedef AutoString UTF8String; #endif -typedef void (WEBWINDOW_STDCALL* ACTION)(); -typedef void (WEBWINDOW_STDCALL* WebMessageReceivedCallback)(AutoString message); -typedef void* (WEBWINDOW_STDCALL* WebResourceRequestedCallback)(AutoString url, int* outNumBytes, AutoString* outContentType); +typedef void (*ACTION)(); +typedef void (*WebMessageReceivedCallback)(AutoString message); +typedef void* (*WebResourceRequestedCallback)(AutoString url, int* outNumBytes, AutoString* outContentType); class WebWindow { diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 116b712..44d3cc9 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -17,31 +17,32 @@ public class WebWindow [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] delegate void OnWebMessageReceivedCallback(string message); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] delegate IntPtr OnWebResourceRequestedCallback(string url, out int numBytes, out string contentType); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void InvokeCallback(); const string DllName = "WebWindow.Native"; - [DllImport(DllName)] static extern IntPtr WebWindow_register_win32(IntPtr hInstance); - [DllImport(DllName)] static extern IntPtr WebWindow_register_mac(); - [DllImport(DllName, CharSet = CharSet.Auto)] static extern IntPtr WebWindow_ctor(string title, IntPtr parentWebWindow, OnWebMessageReceivedCallback webMessageReceivedCallback); - [DllImport(DllName)] static extern void WebWindow_dtor(IntPtr instance); - [DllImport(DllName)] static extern IntPtr WebWindow_getHwnd_win32(IntPtr instance); - [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_SetTitle(IntPtr instance, string title); - [DllImport(DllName)] static extern void WebWindow_Show(IntPtr instance); - [DllImport(DllName)] static extern void WebWindow_WaitForExit(IntPtr instance); - [DllImport(DllName)] static extern void WebWindow_Invoke(IntPtr instance, Action callback); - [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_NavigateToString(IntPtr instance, string content); - [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_NavigateToUrl(IntPtr instance, string url); - [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_ShowMessage(IntPtr instance, string title, string body, uint type); - [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_SendMessage(IntPtr instance, string message); - [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_AddCustomScheme(IntPtr instance, string scheme, OnWebResourceRequestedCallback requestHandler); - [DllImport(DllName)] static extern void WebWindow_SetResizable(IntPtr instance, int resizable); - [DllImport(DllName)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height); - [DllImport(DllName)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height); - [DllImport(DllName)] static extern void WebWindow_GetScreenSize(IntPtr instance, out int width, out int height); - [DllImport(DllName)] static extern uint WebWindow_GetScreenDpi(IntPtr instance); - [DllImport(DllName)] static extern void WebWindow_GetPosition(IntPtr instance, out int x, out int y); - [DllImport(DllName)] static extern void WebWindow_SetPosition(IntPtr instance, int x, int y); - [DllImport(DllName)] static extern void WebWindow_SetTopmost(IntPtr instance, int topmost); - [DllImport(DllName, CharSet = CharSet.Auto)] static extern void WebWindow_SetIconFile(IntPtr instance, string filename); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr WebWindow_register_win32(IntPtr hInstance); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr WebWindow_register_mac(); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern IntPtr WebWindow_ctor(string title, IntPtr parentWebWindow, OnWebMessageReceivedCallback webMessageReceivedCallback); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_dtor(IntPtr instance); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr WebWindow_getHwnd_win32(IntPtr instance); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void WebWindow_SetTitle(IntPtr instance, string title); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_Show(IntPtr instance); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_WaitForExit(IntPtr instance); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_Invoke(IntPtr instance, InvokeCallback callback); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void WebWindow_NavigateToString(IntPtr instance, string content); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void WebWindow_NavigateToUrl(IntPtr instance, string url); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void WebWindow_ShowMessage(IntPtr instance, string title, string body, uint type); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void WebWindow_SendMessage(IntPtr instance, string message); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void WebWindow_AddCustomScheme(IntPtr instance, string scheme, OnWebResourceRequestedCallback requestHandler); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetResizable(IntPtr instance, int resizable); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetScreenSize(IntPtr instance, out int width, out int height); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern uint WebWindow_GetScreenDpi(IntPtr instance); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetPosition(IntPtr instance, out int x, out int y); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetPosition(IntPtr instance, int x, int y); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetTopmost(IntPtr instance, int topmost); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void WebWindow_SetIconFile(IntPtr instance, string filename); private List _gcHandlesToFree = new List(); private List _hGlobalToFree = new List(); @@ -135,7 +136,7 @@ public void ShowMessage(string title, string body) public void Invoke(Action workItem) { - WebWindow_Invoke(_nativeWebWindow, workItem); + WebWindow_Invoke(_nativeWebWindow, workItem.Invoke); } public IntPtr Hwnd From 1aef85173a452fdd7bfc7c16dc1a9be678f3a449 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 22:14:14 +0800 Subject: [PATCH 27/47] Remove UTF8String define. --- src/WebWindow.Native/WebWindow.Linux.cpp | 44 ++++++++++++------------ src/WebWindow.Native/WebWindow.Mac.mm | 14 ++++---- src/WebWindow.Native/WebWindow.h | 1 - 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index 229efa9..87c31d2 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -23,13 +23,13 @@ struct InvokeJSWaitInfo bool isCompleted; }; -WebWindow::WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback) +WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback) { _webMessageReceivedCallback = webMessageReceivedCallback; gtk_init(0, NULL); _window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size((GtkWindow*)_window, 900, 600); + gtk_window_set_default_size(GTK_WINDOW(_window), 900, 600); SetTitle(title); if (parent == NULL) @@ -49,7 +49,7 @@ void HandleWebMessage(WebKitUserContentManager* contentManager, WebKitJavascript { JSCValue* jsValue = webkit_javascript_result_get_js_value(jsResult); if (jsc_value_is_string(jsValue)) { - UTF8String str_value = jsc_value_to_string(jsValue); + AutoString str_value = jsc_value_to_string(jsValue); WebMessageReceivedCallback callback = (WebMessageReceivedCallback)arg; callback(str_value); @@ -94,9 +94,9 @@ void WebWindow::Show() webkit_web_inspector_show(WEBKIT_WEB_INSPECTOR(inspector)); } -void WebWindow::SetTitle(UTF8String title) +void WebWindow::SetTitle(AutoString title) { - gtk_window_set_title((GtkWindow*)_window, title); + gtk_window_set_title(GTK_WINDOW(_window), title); } void WebWindow::WaitForExit() @@ -128,9 +128,9 @@ void WebWindow::Invoke(ACTION callback) waitInfo.completionNotifier.wait(uLock, [&] { return waitInfo.isCompleted; }); } -void WebWindow::ShowMessage(UTF8String title, UTF8String body, unsigned int type) +void WebWindow::ShowMessage(AutoString title, AutoString body, unsigned int type) { - GtkWidget* dialog = gtk_message_dialog_new((GtkWindow*)_window, + GtkWidget* dialog = gtk_message_dialog_new(GTK_WINDOW(_window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_OTHER, GTK_BUTTONS_OK, @@ -141,12 +141,12 @@ void WebWindow::ShowMessage(UTF8String title, UTF8String body, unsigned int type gtk_widget_destroy(dialog); } -void WebWindow::NavigateToUrl(UTF8String url) +void WebWindow::NavigateToUrl(AutoString url) { webkit_web_view_load_uri(WEBKIT_WEB_VIEW(_webview), url); } -void WebWindow::NavigateToString(UTF8String content) +void WebWindow::NavigateToString(AutoString content) { webkit_web_view_load_html(WEBKIT_WEB_VIEW(_webview), content, NULL); } @@ -181,7 +181,7 @@ static void webview_eval_finished(GObject* object, GAsyncResult* result, gpointe waitInfo->isCompleted = true; } -void WebWindow::SendMessage(UTF8String message) +void WebWindow::SendMessage(AutoString message) { std::string js; js.append("__dispatchMessageCallback(\""); @@ -202,15 +202,15 @@ void HandleCustomSchemeRequest(WebKitURISchemeRequest* request, gpointer user_da const gchar* uri = webkit_uri_scheme_request_get_uri(request); int numBytes; - UTF8String contentType; - void* dotNetResponse = webResourceRequestedCallback((UTF8String)uri, &numBytes, &contentType); + AutoString contentType; + void* dotNetResponse = webResourceRequestedCallback((AutoString)uri, &numBytes, &contentType); GInputStream* stream = g_memory_input_stream_new_from_data(dotNetResponse, numBytes, NULL); webkit_uri_scheme_request_finish(request, (GInputStream*)stream, -1, contentType); g_object_unref(stream); delete[] contentType; } -void WebWindow::AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback requestHandler) +void WebWindow::AddCustomScheme(AutoString scheme, WebResourceRequestedCallback requestHandler) { WebKitWebContext* context = webkit_web_context_get_default(); webkit_web_context_register_uri_scheme(context, scheme, @@ -220,29 +220,29 @@ void WebWindow::AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback void WebWindow::SetResizable(bool resizable) { - gtk_window_set_resizable((GtkWindow*)_window, resizable ? TRUE : FALSE); + gtk_window_set_resizable(GTK_WINDOW(_window), resizable ? TRUE : FALSE); } void WebWindow::GetSize(int* width, int* height) { - gtk_window_get_size((GtkWindow*)_window, width, height); + gtk_window_get_size(GTK_WINDOW(_window), width, height); } void WebWindow::SetSize(int width, int height) { - gtk_window_resize((GtkWindow*)_window, width, height); + gtk_window_resize(GTK_WINDOW(_window), width, height); } void WebWindow::GetScreenSize(int* width, int* height) { - GdkScreen* screen = gtk_window_get_screen((GtkWindow*)_window); + GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(_window)); if (width) *width = gdk_screen_get_width(screen); if (height) *height = gdk_screen_get_height(screen); } unsigned int WebWindow::GetScreenDpi() { - GdkScreen* screen = gtk_window_get_screen((GtkWindow*)_window); + GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(_window)); gdouble dpi = gdk_screen_get_resolution(screen); if (dpi < 0) return 96; else return (unsigned int)dpi; @@ -250,22 +250,22 @@ unsigned int WebWindow::GetScreenDpi() void WebWindow::GetPosition(int* x, int* y) { - gtk_window_get_position((GtkWindow*)_window, x, y); + gtk_window_get_position(GTK_WINDOW(_window), x, y); } void WebWindow::SetPosition(int x, int y) { - gtk_window_move((GtkWindow*)_window, x, y); + gtk_window_move(GTK_WINDOW(_window), x, y); } void WebWindow::SetTopmost(bool topmost) { - gtk_window_set_keep_above((GtkWindow*)_window, topmost ? TRUE : FALSE); + gtk_window_set_keep_above(GTK_WINDOW(_window), topmost ? TRUE : FALSE); } void WebWindow::SetIconFile(AutoString filename) { - gtk_window_set_icon_from_file((GtkWindow*)_window, filename, NULL); + gtk_window_set_icon_from_file(GTK_WINDOW(_window), filename, NULL); } #endif diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index 72b57e8..b4b0a4c 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -29,7 +29,7 @@ [application setDelegate:appDelegate]; } -WebWindow::WebWindow(UTF8String title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback) +WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback) { _webMessageReceivedCallback = webMessageReceivedCallback; NSRect frame = NSMakeRect(0, 0, 900, 600); @@ -107,7 +107,7 @@ [window makeKeyAndOrderFront:nil]; } -void WebWindow::SetTitle(UTF8String title) +void WebWindow::SetTitle(AutoString title) { NSWindow* window = (NSWindow*)_window; NSString* nstitle = [[NSString stringWithUTF8String:title] autorelease]; @@ -126,7 +126,7 @@ }); } -void WebWindow::ShowMessage(UTF8String title, UTF8String body, unsigned int type) +void WebWindow::ShowMessage(AutoString title, AutoString body, unsigned int type) { NSString* nstitle = [[NSString stringWithUTF8String:title] autorelease]; NSString* nsbody= [[NSString stringWithUTF8String:body] autorelease]; @@ -136,14 +136,14 @@ [alert runModal]; } -void WebWindow::NavigateToString(UTF8String content) +void WebWindow::NavigateToString(AutoString content) { WKWebView *webView = (WKWebView *)_webview; NSString* nscontent = [[NSString stringWithUTF8String:content] autorelease]; [webView loadHTMLString:nscontent baseURL:nil]; } -void WebWindow::NavigateToUrl(UTF8String url) +void WebWindow::NavigateToUrl(AutoString url) { WKWebView *webView = (WKWebView *)_webview; NSString* nsurlstring = [[NSString stringWithUTF8String:url] autorelease]; @@ -152,7 +152,7 @@ [webView loadRequest:nsrequest]; } -void WebWindow::SendMessage(UTF8String message) +void WebWindow::SendMessage(AutoString message) { // JSON-encode the message NSString* nsmessage = [NSString stringWithUTF8String:message]; @@ -167,7 +167,7 @@ [webView evaluateJavaScript:javaScriptToEval completionHandler:nil]; } -void WebWindow::AddCustomScheme(UTF8String scheme, WebResourceRequestedCallback requestHandler) +void WebWindow::AddCustomScheme(AutoString scheme, WebResourceRequestedCallback requestHandler) { // Note that this can only be done *before* the WKWebView is instantiated, so we only let this // get called from the options callback in the constructor diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index 41cbdf1..838516f 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -14,7 +14,6 @@ typedef const wchar_t* AutoString; #include #endif typedef char* AutoString; -typedef AutoString UTF8String; #endif typedef void (*ACTION)(); From 07f59141b3d43b5c67b3a35809f414cc93db5c9b Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 22:20:29 +0800 Subject: [PATCH 28/47] Size->WindowProp --- testassets/MyBlazorApp/Pages/{Size.razor => WindowProp.razor} | 4 ++-- testassets/MyBlazorApp/Shared/NavMenu.razor | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename testassets/MyBlazorApp/Pages/{Size.razor => WindowProp.razor} (96%) diff --git a/testassets/MyBlazorApp/Pages/Size.razor b/testassets/MyBlazorApp/Pages/WindowProp.razor similarity index 96% rename from testassets/MyBlazorApp/Pages/Size.razor rename to testassets/MyBlazorApp/Pages/WindowProp.razor index 179e80d..71bd8ab 100644 --- a/testassets/MyBlazorApp/Pages/Size.razor +++ b/testassets/MyBlazorApp/Pages/WindowProp.razor @@ -1,7 +1,7 @@ -@page "/size" +@page "/window" @inject WebWindow Window -

Size demo

+

Window properties

Screen size

Width: @Window.ScreenSize.Width, Height: @Window.ScreenSize.Height, DPI: @Window.ScreenDpi

Window size

diff --git a/testassets/MyBlazorApp/Shared/NavMenu.razor b/testassets/MyBlazorApp/Shared/NavMenu.razor index a695cdb..ae83c2d 100644 --- a/testassets/MyBlazorApp/Shared/NavMenu.razor +++ b/testassets/MyBlazorApp/Shared/NavMenu.razor @@ -23,8 +23,8 @@ From 1b523bff711dc9db9b3e014a80b3e8b253c67f45 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 22:50:15 +0800 Subject: [PATCH 29/47] Add icon demo. --- src/WebWindow.Native/WebWindow.Windows.cpp | 7 ++- src/WebWindow/WebWindow.cs | 2 +- testassets/MyBlazorApp/MyBlazorApp.csproj | 2 +- testassets/MyBlazorApp/Pages/WindowProp.razor | 51 ++++++++++++++----- 4 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 6748c14..35b834a 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -363,6 +363,9 @@ void WebWindow::SetTopmost(bool topmost) void WebWindow::SetIconFile(AutoString filename) { - HICON icon = (HICON)LoadImage(NULL, filename, IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_SHARED); - SetWindowLongPtr(_hWnd, GCLP_HICON, (LONG_PTR)icon); + HICON icon = (HICON)LoadImage(NULL, filename, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + if (icon) + { + ::SendMessage(_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)icon); + } } diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 44d3cc9..1de4db0 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -377,6 +377,6 @@ public bool Topmost } } - public void SetIconFile(string filename) => WebWindow_SetIconFile(_nativeWebWindow, filename); + public void SetIconFile(string filename) => WebWindow_SetIconFile(_nativeWebWindow, Path.GetFullPath(filename)); } } diff --git a/testassets/MyBlazorApp/MyBlazorApp.csproj b/testassets/MyBlazorApp/MyBlazorApp.csproj index b855521..ff215c4 100644 --- a/testassets/MyBlazorApp/MyBlazorApp.csproj +++ b/testassets/MyBlazorApp/MyBlazorApp.csproj @@ -2,7 +2,7 @@ netcoreapp3.0 - WinExe + Exe diff --git a/testassets/MyBlazorApp/Pages/WindowProp.razor b/testassets/MyBlazorApp/Pages/WindowProp.razor index 71bd8ab..cc0ccd6 100644 --- a/testassets/MyBlazorApp/Pages/WindowProp.razor +++ b/testassets/MyBlazorApp/Pages/WindowProp.razor @@ -1,39 +1,62 @@ @page "/window" +@using System.IO @inject WebWindow Window

Window properties

Screen size

Width: @Window.ScreenSize.Width, Height: @Window.ScreenSize.Height, DPI: @Window.ScreenDpi

Window size

-
-
+ +
- +
-
+
- +

Window location

-
-
+ +
- +
-
+
- +

Window properties

-
- +
+
-
- +
+
+

Icon

+
+
+ + +
+
+ +
+
+ +@code { + string iconFilename; + + void ChangeIconFile() + { + if (!string.IsNullOrEmpty(iconFilename)) + { + Window.SetIconFile(iconFilename); + } + } +} From 6998bc71d3013cdbb454a3dd18864439d7805fec Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sun, 8 Dec 2019 22:50:57 +0800 Subject: [PATCH 30/47] Revert temp change. --- testassets/MyBlazorApp/MyBlazorApp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testassets/MyBlazorApp/MyBlazorApp.csproj b/testassets/MyBlazorApp/MyBlazorApp.csproj index ff215c4..b855521 100644 --- a/testassets/MyBlazorApp/MyBlazorApp.csproj +++ b/testassets/MyBlazorApp/MyBlazorApp.csproj @@ -2,7 +2,7 @@ netcoreapp3.0 - Exe + WinExe From e61f89e4b67fac353e360d5a4d3165c273cf8fac Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Mon, 9 Dec 2019 00:28:15 +0800 Subject: [PATCH 31/47] Add ResizedCallback and MovedCallback for Win & Linux. --- src/WebWindow.Native/Exports.cpp | 10 +++ src/WebWindow.Native/WebWindow.Linux.cpp | 19 ++++++ src/WebWindow.Native/WebWindow.Windows.cpp | 14 ++++ src/WebWindow.Native/WebWindow.h | 8 +++ src/WebWindow/WebWindow.cs | 68 +++++++++++++++---- testassets/MyBlazorApp/Pages/WindowProp.razor | 3 +- 6 files changed, 107 insertions(+), 15 deletions(-) diff --git a/src/WebWindow.Native/Exports.cpp b/src/WebWindow.Native/Exports.cpp index c9f1131..f96310f 100644 --- a/src/WebWindow.Native/Exports.cpp +++ b/src/WebWindow.Native/Exports.cpp @@ -95,6 +95,11 @@ extern "C" instance->SetSize(width, height); } + EXPORTED void WebWindow_SetResizedCallback(WebWindow* instance, ResizedCallback callback) + { + instance->SetResizedCallback(callback); + } + EXPORTED void WebWindow_GetScreenSize(WebWindow* instance, int* width, int* height) { instance->GetScreenSize(width, height); @@ -115,6 +120,11 @@ extern "C" instance->SetPosition(x, y); } + EXPORTED void WebWindow_SetMovedCallback(WebWindow* instance, MovedCallback callback) + { + instance->SetMovedCallback(callback); + } + EXPORTED void WebWindow_SetTopmost(WebWindow* instance, int topmost) { instance->SetTopmost(topmost); diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index 87c31d2..c060fc9 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -37,6 +37,9 @@ WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCall g_signal_connect(G_OBJECT(_window), "destroy", G_CALLBACK(+[](GtkWidget* w, gpointer arg) { gtk_main_quit(); }), this); + g_signal_connect(G_OBJECT(_window), "size-allocate", + G_CALLBACK(+on_size_allocate), + this); } } @@ -233,6 +236,13 @@ void WebWindow::SetSize(int width, int height) gtk_window_resize(GTK_WINDOW(_window), width, height); } +void on_size_allocate(GtkWidget* widget, GdkRectangle* allocation, gpointer self) +{ + int width, height; + gtk_window_get_size(GTK_WINDOW(widget), &width, &height); + ((WebWindow*)self)->InvokeResized(width, height); +} + void WebWindow::GetScreenSize(int* width, int* height) { GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(_window)); @@ -258,6 +268,15 @@ void WebWindow::SetPosition(int x, int y) gtk_window_move(GTK_WINDOW(_window), x, y); } +gboolean on_configure_event(GtkWidget* widget, GdkEvent* event, gpointer self) +{ + if (event->type == GDK_CONFIGURE) + { + ((WebWindow*)self)->InvokeMoved(event->configure.x, event->configure.y); + } + return FALSE; +} + void WebWindow::SetTopmost(bool topmost) { gtk_window_set_keep_above(GTK_WINDOW(_window), topmost ? TRUE : FALSE); diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 35b834a..5514077 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -117,6 +117,20 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (webWindow) { webWindow->RefitContent(); + int width, height; + webWindow->GetSize(&width, &height); + webWindow->InvokeResized(width, height); + } + return 0; + } + case WM_MOVE: + { + WebWindow* webWindow = hwndToWebWindow[hwnd]; + if (webWindow) + { + int x, y; + webWindow->GetPosition(&x, &y); + webWindow->InvokeMoved(x, y); } return 0; } diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index 838516f..2f20377 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -19,11 +19,15 @@ typedef char* AutoString; typedef void (*ACTION)(); typedef void (*WebMessageReceivedCallback)(AutoString message); typedef void* (*WebResourceRequestedCallback)(AutoString url, int* outNumBytes, AutoString* outContentType); +typedef void (*ResizedCallback)(int width, int height); +typedef void (*MovedCallback)(int x, int y); class WebWindow { private: WebMessageReceivedCallback _webMessageReceivedCallback; + MovedCallback _movedCallback; + ResizedCallback _resizedCallback; #ifdef _WIN32 static HINSTANCE _hInstance; HWND _hWnd; @@ -65,10 +69,14 @@ class WebWindow void SetResizable(bool resizable); void GetSize(int* width, int* height); void SetSize(int width, int height); + void SetResizedCallback(ResizedCallback callback) { _resizedCallback = callback; } + void InvokeResized(int width, int height) { if (_resizedCallback) _resizedCallback(width, height); } void GetScreenSize(int* width, int* height); unsigned int GetScreenDpi(); void GetPosition(int* x, int* y); void SetPosition(int x, int y); + void SetMovedCallback(MovedCallback callback) { _movedCallback = callback; } + void InvokeMoved(int x, int y) { if (_movedCallback) _movedCallback(x, y); } void SetTopmost(bool topmost); void SetIconFile(AutoString filename); }; diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 1de4db0..3e59614 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -18,6 +18,8 @@ public class WebWindow [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] delegate void OnWebMessageReceivedCallback(string message); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] delegate IntPtr OnWebResourceRequestedCallback(string url, out int numBytes, out string contentType); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void InvokeCallback(); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void ResizedCallback(int width, int height); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void MovedCallback(int x, int y); const string DllName = "WebWindow.Native"; [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern IntPtr WebWindow_register_win32(IntPtr hInstance); @@ -37,10 +39,12 @@ public class WebWindow [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetResizable(IntPtr instance, int resizable); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetResizedCallback(IntPtr instance, ResizedCallback callback); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetScreenSize(IntPtr instance, out int width, out int height); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern uint WebWindow_GetScreenDpi(IntPtr instance); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetPosition(IntPtr instance, out int x, out int y); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetPosition(IntPtr instance, int x, int y); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetMovedCallback(IntPtr instance, MovedCallback callback); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetTopmost(IntPtr instance, int topmost); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void WebWindow_SetIconFile(IntPtr instance, string filename); @@ -95,6 +99,14 @@ public WebWindow(string title, Action configure) AddCustomScheme(schemeName, handler); } + var onResizedDelegate = (ResizedCallback)OnResized; + _gcHandlesToFree.Add(GCHandle.Alloc(onResizedDelegate)); + WebWindow_SetResizedCallback(_nativeWebWindow, onResizedDelegate); + + var onMovedDelegate = (MovedCallback)OnMoved; + _gcHandlesToFree.Add(GCHandle.Alloc(onMovedDelegate)); + WebWindow_SetMovedCallback(_nativeWebWindow, onMovedDelegate); + // Auto-show to simplify the API, but more importantly because you can't // do things like navigate until it has been shown Show(); @@ -103,6 +115,8 @@ public WebWindow(string title, Action configure) ~WebWindow() { // TODO: IDisposable + WebWindow_SetResizedCallback(_nativeWebWindow, null); + WebWindow_SetMovedCallback(_nativeWebWindow, null); foreach (var gcHandle in _gcHandlesToFree) { gcHandle.Free(); @@ -265,8 +279,11 @@ public int Width set { GetSize(); - _width = value; - SetSize(); + if (_width != value) + { + _width = value; + SetSize(); + } } } @@ -280,8 +297,11 @@ public int Height set { GetSize(); - _height = value; - SetSize(); + if (_height != value) + { + _height = value; + SetSize(); + } } } @@ -294,12 +314,19 @@ public Size Size } set { - _width = value.Width; - _height = value.Height; - SetSize(); + if (_width != value.Width || _height != value.Height) + { + _width = value.Width; + _height = value.Height; + SetSize(); + } } } + private void OnResized(int width, int height) => SizeChanged?.Invoke(this, new Size(width, height)); + + public event EventHandler SizeChanged; + private int _x; private int _y; @@ -317,8 +344,11 @@ public int Left set { GetPosition(); - _x = value; - SetPosition(); + if (_x != value) + { + _x = value; + SetPosition(); + } } } @@ -332,8 +362,11 @@ public int Top set { GetPosition(); - _y = value; - SetPosition(); + if (_y != value) + { + _y = value; + SetPosition(); + } } } @@ -346,12 +379,19 @@ public Point Location } set { - _x = value.X; - _y = value.Y; - SetPosition(); + if (_x != value.X || _y != value.Y) + { + _x = value.X; + _y = value.Y; + SetPosition(); + } } } + private void OnMoved(int x, int y) => LocationChanged?.Invoke(this, new Point(x, y)); + + public event EventHandler LocationChanged; + public Size ScreenSize { get diff --git a/testassets/MyBlazorApp/Pages/WindowProp.razor b/testassets/MyBlazorApp/Pages/WindowProp.razor index cc0ccd6..505325b 100644 --- a/testassets/MyBlazorApp/Pages/WindowProp.razor +++ b/testassets/MyBlazorApp/Pages/WindowProp.razor @@ -3,6 +3,7 @@ @inject WebWindow Window

Window properties

+

Screen size

Width: @Window.ScreenSize.Width, Height: @Window.ScreenSize.Height, DPI: @Window.ScreenDpi

Window size

@@ -39,7 +40,7 @@

Icon

-
+
From efdfaf07b30cee0f7c5f6966f627293312c63840 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Mon, 9 Dec 2019 13:05:26 +0800 Subject: [PATCH 32/47] Fix Gtk issue. --- .gitignore | 1 + .vscode/c_cpp_properties.json | 25 ------------------------ src/WebWindow.Native/WebWindow.Linux.cpp | 24 ++++++++++++++++++----- 3 files changed, 20 insertions(+), 30 deletions(-) delete mode 100644 .vscode/c_cpp_properties.json diff --git a/.gitignore b/.gitignore index d32efda..359e550 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .vs/ +.vscode/ bin/ obj/ *.user diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index fe605c4..0000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "configurations": [ - { - "name": "Mac", - "includePath": [ - "${workspaceFolder}/**", - "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/**" - ], - "defines": [ - "OS_MAC" - ], - "macFrameworkPath": [ - "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks" - ], - "compilerPath": "/usr/bin/gcc", - "cStandard": "c11", - "cppStandard": "c++17", - "intelliSenseMode": "gcc-x64", - "compilerArgs": [ - "-shared -lstdc++ -DOS_MAC Exports.cpp WebWindow.Mac.cpp" - ] - } - ], - "version": 4 -} \ No newline at end of file diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index c060fc9..4526a3e 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -4,6 +4,7 @@ #include "WebWindow.h" #include #include +#include #include #include #include @@ -23,10 +24,17 @@ struct InvokeJSWaitInfo bool isCompleted; }; -WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback) +void on_size_allocate(GtkWidget* widget, GdkRectangle* allocation, gpointer self); +gboolean on_configure_event(GtkWidget* widget, GdkEvent* event, gpointer self); + +WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCallback webMessageReceivedCallback) : _webview(nullptr) { _webMessageReceivedCallback = webMessageReceivedCallback; + // It makes xlib thread safe. + // Needed for get_position. + XInitThreads(); + gtk_init(0, NULL); _window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(_window), 900, 600); @@ -38,7 +46,10 @@ WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCall G_CALLBACK(+[](GtkWidget* w, gpointer arg) { gtk_main_quit(); }), this); g_signal_connect(G_OBJECT(_window), "size-allocate", - G_CALLBACK(+on_size_allocate), + G_CALLBACK(on_size_allocate), + this); + g_signal_connect(G_OBJECT(_window), "configure-event", + G_CALLBACK(on_configure_event), this); } } @@ -245,9 +256,12 @@ void on_size_allocate(GtkWidget* widget, GdkRectangle* allocation, gpointer self void WebWindow::GetScreenSize(int* width, int* height) { - GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(_window)); - if (width) *width = gdk_screen_get_width(screen); - if (height) *height = gdk_screen_get_height(screen); + GdkRectangle workarea = {}; + gdk_monitor_get_workarea( + gdk_display_get_primary_monitor(gdk_display_get_default()), + &workarea); + if (width) *width = workarea.width; + if (height) *height = workarea.height; } unsigned int WebWindow::GetScreenDpi() From 986574bb6a0ba5d0d53dda7a7c19626d6adbbed1 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 10 Dec 2019 19:31:59 +0800 Subject: [PATCH 33/47] Use per-monitor API. --- src/WebWindow.Native/Exports.cpp | 4 +- src/WebWindow.Native/WebWindow.Linux.cpp | 22 ++++++--- src/WebWindow.Native/WebWindow.Mac.mm | 24 +++++++-- src/WebWindow.Native/WebWindow.Windows.cpp | 28 +++++++++-- src/WebWindow.Native/WebWindow.h | 15 +++++- src/WebWindow/WebWindow.cs | 49 +++++++++++++++++-- testassets/MyBlazorApp/Pages/WindowProp.razor | 6 ++- 7 files changed, 123 insertions(+), 25 deletions(-) diff --git a/src/WebWindow.Native/Exports.cpp b/src/WebWindow.Native/Exports.cpp index f96310f..1b62fbd 100644 --- a/src/WebWindow.Native/Exports.cpp +++ b/src/WebWindow.Native/Exports.cpp @@ -100,9 +100,9 @@ extern "C" instance->SetResizedCallback(callback); } - EXPORTED void WebWindow_GetScreenSize(WebWindow* instance, int* width, int* height) + EXPORTED void WebWindow_GetAllMonitors(WebWindow* instance, GetAllMonitorsCallback callback) { - instance->GetScreenSize(width, height); + instance->GetAllMonitors(callback); } EXPORTED unsigned int WebWindow_GetScreenDpi(WebWindow* instance) diff --git a/src/WebWindow.Native/WebWindow.Linux.cpp b/src/WebWindow.Native/WebWindow.Linux.cpp index 4526a3e..8ec24c1 100644 --- a/src/WebWindow.Native/WebWindow.Linux.cpp +++ b/src/WebWindow.Native/WebWindow.Linux.cpp @@ -254,14 +254,22 @@ void on_size_allocate(GtkWidget* widget, GdkRectangle* allocation, gpointer self ((WebWindow*)self)->InvokeResized(width, height); } -void WebWindow::GetScreenSize(int* width, int* height) +void WebWindow::GetAllMonitors(GetAllMonitorsCallback callback) { - GdkRectangle workarea = {}; - gdk_monitor_get_workarea( - gdk_display_get_primary_monitor(gdk_display_get_default()), - &workarea); - if (width) *width = workarea.width; - if (height) *height = workarea.height; + if (callback) + { + GdkScreen* screen = gtk_window_get_screen(GTK_WINDOW(_window)); + GdkDisplay* display = gdk_screen_get_display(screen); + int n = gdk_display_get_n_monitors(display); + for (int i = 0; i < n; i++) + { + GdkMonitor* monitor = gdk_display_get_monitor(display, i); + Monitor props = {}; + gdk_monitor_get_geometry(monitor, (GdkRectangle*)&props.monitor); + gdk_monitor_get_workarea(monitor, (GdkRectangle*)&props.work); + if (!callback(&props)) break; + } + } } unsigned int WebWindow::GetScreenDpi() diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index b4b0a4c..0b77659 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -208,12 +208,26 @@ [window setFrame: frame display: YES]; } -void WebWindow::GetScreenSize(int* width, int* height) +void WebWindow::GetAllMonitors(GetAllMonitorsCallback callback) { - NSWindow* window = (NSWindow*)_window; - NSSize size = [[window screen] frame].size; - if (width) *width = (int)roundf(size.width); - if (height) *height = (int)roundf(size.height); + if (callback) + { + for (NSScreen* screen in [NSScreen screens]) + { + Monitor props = {}; + NSRect frame = [screen frame]; + props.monitor.x = (int)roundf(frame.origin.x); + props.monitor.y = (int)roundf(frame.origin.y); + props.monitor.width = (int)roundf(frame.size.width); + props.monitor.height = (int)roundf(frame.size.height); + NSRect vframe = [screen visibleFrame]; + props.work.x = (int)roundf(vframe.origin.x); + props.work.y = (int)roundf(vframe.origin.y); + props.work.width = (int)roundf(vframe.size.width); + props.work.height = (int)roundf(vframe.size.height); + callback(&props); + } + } } unsigned int WebWindow::GetScreenDpi() diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 5514077..3d0764d 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -344,12 +344,30 @@ void WebWindow::SetSize(int width, int height) SetWindowPos(_hWnd, HWND_TOP, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER); } -void WebWindow::GetScreenSize(int* width, int* height) +BOOL MonitorEnum(HMONITOR monitor, HDC, LPRECT, LPARAM arg) { - RECT rect = {}; - GetWindowRect(GetDesktopWindow(), &rect); - if (width) *width = rect.right - rect.left; - if (height) *height = rect.bottom - rect.top; + auto callback = (GetAllMonitorsCallback)arg; + MONITORINFO info = {}; + info.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(monitor, &info); + Monitor props = {}; + props.monitor.x = info.rcMonitor.left; + props.monitor.y = info.rcMonitor.top; + props.monitor.width = info.rcMonitor.right - info.rcMonitor.left; + props.monitor.height = info.rcMonitor.bottom - info.rcMonitor.top; + props.work.x = info.rcWork.left; + props.work.y = info.rcWork.top; + props.work.width = info.rcWork.right - info.rcWork.left; + props.work.height = info.rcWork.bottom - info.rcWork.top; + return callback(&props) ? TRUE : FALSE; +} + +void WebWindow::GetAllMonitors(GetAllMonitorsCallback callback) +{ + if (callback) + { + EnumDisplayMonitors(NULL, NULL, MonitorEnum, (LPARAM)callback); + } } unsigned int WebWindow::GetScreenDpi() diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index 2f20377..302b05c 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -16,9 +16,22 @@ typedef const wchar_t* AutoString; typedef char* AutoString; #endif +struct Rect +{ + int x, y; + int width, height; +}; + +struct Monitor +{ + Rect monitor; + Rect work; +}; + typedef void (*ACTION)(); typedef void (*WebMessageReceivedCallback)(AutoString message); typedef void* (*WebResourceRequestedCallback)(AutoString url, int* outNumBytes, AutoString* outContentType); +typedef int (*GetAllMonitorsCallback)(const Monitor* monitor); typedef void (*ResizedCallback)(int width, int height); typedef void (*MovedCallback)(int x, int y); @@ -71,7 +84,7 @@ class WebWindow void SetSize(int width, int height); void SetResizedCallback(ResizedCallback callback) { _resizedCallback = callback; } void InvokeResized(int width, int height) { if (_resizedCallback) _resizedCallback(width, height); } - void GetScreenSize(int* width, int* height); + void GetAllMonitors(GetAllMonitorsCallback callback); unsigned int GetScreenDpi(); void GetPosition(int* x, int* y); void SetPosition(int x, int y); diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 3e59614..93920f9 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -7,6 +7,40 @@ namespace WebWindows { + [StructLayout(LayoutKind.Sequential)] + struct NativeRect + { + public int x, y; + public int width, height; + } + + [StructLayout(LayoutKind.Sequential)] + struct NativeMonitor + { + public NativeRect monitor; + public NativeRect work; + } + + public readonly struct Monitor + { + public readonly Rectangle MonitorArea; + public readonly Rectangle WorkArea; + + public Monitor(Rectangle monitor, Rectangle work) + { + MonitorArea = monitor; + WorkArea = work; + } + + internal Monitor(NativeRect monitor, NativeRect work) + : this(new Rectangle(monitor.x, monitor.y, monitor.width, monitor.height), new Rectangle(work.x, work.y, work.width, work.height)) + { } + + internal Monitor(NativeMonitor nativeMonitor) + : this(nativeMonitor.monitor, nativeMonitor.work) + { } + } + public class WebWindow { // Here we use auto charset instead of forcing UTF-8. @@ -18,6 +52,7 @@ public class WebWindow [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] delegate void OnWebMessageReceivedCallback(string message); [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)] delegate IntPtr OnWebResourceRequestedCallback(string url, out int numBytes, out string contentType); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void InvokeCallback(); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int GetAllMonitorsCallback(in NativeMonitor monitor); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void ResizedCallback(int width, int height); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void MovedCallback(int x, int y); @@ -40,7 +75,7 @@ public class WebWindow [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetSize(IntPtr instance, out int width, out int height); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetSize(IntPtr instance, int width, int height); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetResizedCallback(IntPtr instance, ResizedCallback callback); - [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetScreenSize(IntPtr instance, out int width, out int height); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetAllMonitors(IntPtr instance, GetAllMonitorsCallback callback); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern uint WebWindow_GetScreenDpi(IntPtr instance); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_GetPosition(IntPtr instance, out int x, out int y); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetPosition(IntPtr instance, int x, int y); @@ -392,12 +427,18 @@ public Point Location public event EventHandler LocationChanged; - public Size ScreenSize + public IEnumerable Monitors { get { - WebWindow_GetScreenSize(_nativeWebWindow, out int width, out int height); - return new Size(width, height); + List monitors = new List(); + int callback(in NativeMonitor monitor) + { + monitors.Add(new Monitor(monitor)); + return 1; + } + WebWindow_GetAllMonitors(_nativeWebWindow, callback); + return monitors; } } diff --git a/testassets/MyBlazorApp/Pages/WindowProp.razor b/testassets/MyBlazorApp/Pages/WindowProp.razor index 505325b..5b476cc 100644 --- a/testassets/MyBlazorApp/Pages/WindowProp.razor +++ b/testassets/MyBlazorApp/Pages/WindowProp.razor @@ -5,7 +5,11 @@

Window properties

Screen size

-

Width: @Window.ScreenSize.Width, Height: @Window.ScreenSize.Height, DPI: @Window.ScreenDpi

+

DPI: @Window.ScreenDpi

+@foreach (var (m, i) in Window.Monitors.Select((monitor, index) => (monitor, index))) +{ +

Monitor @i: Width: @m.MonitorArea.Width, Height: @m.MonitorArea.Height

+}

Window size

From 5d48327184b445e3650c787fc9708a909cf9016f Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 10 Dec 2019 20:39:08 +0800 Subject: [PATCH 34/47] Add windowDidResize and windowDidMove for Mac. --- .../WebWindow.Mac.AppDelegate.m | 21 --------- .../WebWindow.Mac.AppDelegate.mm | 47 +++++++++++++++++++ src/WebWindow.Native/WebWindow.Mac.mm | 8 +++- src/WebWindow/WebWindow.csproj | 2 +- 4 files changed, 54 insertions(+), 24 deletions(-) delete mode 100644 src/WebWindow.Native/WebWindow.Mac.AppDelegate.m create mode 100644 src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm diff --git a/src/WebWindow.Native/WebWindow.Mac.AppDelegate.m b/src/WebWindow.Native/WebWindow.Mac.AppDelegate.m deleted file mode 100644 index 57e881d..0000000 --- a/src/WebWindow.Native/WebWindow.Mac.AppDelegate.m +++ /dev/null @@ -1,21 +0,0 @@ -#import "WebWindow.Mac.AppDelegate.h" - -@implementation MyApplicationDelegate : NSObject -- (id)init { - if (self = [super init]) { - // allocate and initialize window and stuff here .. - } - return self; -} - -- (void)applicationDidFinishLaunching:(NSNotification *)notification { - [window makeKeyAndOrderFront:nil]; - [NSApp activateIgnoringOtherApps:YES]; -} - -- (void)dealloc { - [window release]; - [super dealloc]; -} - -@end diff --git a/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm b/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm new file mode 100644 index 0000000..3ea7e4d --- /dev/null +++ b/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm @@ -0,0 +1,47 @@ +#import "WebWindow.Mac.AppDelegate.h" +#include "WebWindow.h" +#include + +extern map nsWindowToWebWindow; + +@implementation MyApplicationDelegate : NSObject +- (id)init { + if (self = [super init]) { + // allocate and initialize window and stuff here .. + } + return self; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)notification { + [window makeKeyAndOrderFront:nil]; + [NSApp activateIgnoringOtherApps:YES]; +} + +- (void)windowDidResize:(NSNotification *)notification { + NSWindow *window = notification.object; + WebWindow* webWindow = nsWindowToWebWindow[hwnd]; + if (webWindow) + { + int width, height; + webWindow->GetSize(&width, &height); + webWindow->InvokeResized(width, height); + } +} + +- (void)windowDidMove:(NSNotification *)notification { + NSWindow *window = notification.object; + WebWindow* webWindow = nsWindowToWebWindow[hwnd]; + if (webWindow) + { + int x, y; + webWindow->GetPosition(&x, &y); + webWindow->InvokeMoved(x, y); + } +} + +- (void)dealloc { + [window release]; + [super dealloc]; +} + +@end diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index 0b77659..bbfb7b0 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -3,10 +3,15 @@ #import "WebWindow.Mac.AppDelegate.h" #import "WebWindow.Mac.UiDelegate.h" #import "WebWindow.Mac.UrlSchemeHandler.h" -#include +#include +#include #import #import +using namespace std; + +map nsWindowToWebWindow; + void WebWindow::Register() { [NSAutoreleasePool new]; @@ -57,7 +62,6 @@ [webView release]; NSWindow* window = (NSWindow*)_window; [window close]; - [window release]; } void WebWindow::AttachWebView() diff --git a/src/WebWindow/WebWindow.csproj b/src/WebWindow/WebWindow.csproj index d58a22f..eb0fb6b 100644 --- a/src/WebWindow/WebWindow.csproj +++ b/src/WebWindow/WebWindow.csproj @@ -20,7 +20,7 @@ + Command="gcc -shared -lstdc++ -DOS_MAC -framework Cocoa -framework WebKit WebWindow.Mac.mm Exports.cpp WebWindow.Mac.AppDelegate.mm WebWindow.Mac.UiDelegate.m WebWindow.Mac.UrlSchemeHandler.m -o x64/$(Configuration)/WebWindow.Native.dylib" /> From faf35eef0f739bdeadc3ae909db3b005562f55e0 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Tue, 10 Dec 2019 20:43:15 +0800 Subject: [PATCH 35/47] Fix name conflict. --- src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm | 6 +++--- src/WebWindow.Native/WebWindow.h | 13 +++++-------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm b/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm index 3ea7e4d..a7c5848 100644 --- a/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm +++ b/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm @@ -2,7 +2,7 @@ #include "WebWindow.h" #include -extern map nsWindowToWebWindow; +extern std::map nsWindowToWebWindow; @implementation MyApplicationDelegate : NSObject - (id)init { @@ -19,7 +19,7 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { - (void)windowDidResize:(NSNotification *)notification { NSWindow *window = notification.object; - WebWindow* webWindow = nsWindowToWebWindow[hwnd]; + WebWindow* webWindow = nsWindowToWebWindow[window]; if (webWindow) { int width, height; @@ -30,7 +30,7 @@ - (void)windowDidResize:(NSNotification *)notification { - (void)windowDidMove:(NSNotification *)notification { NSWindow *window = notification.object; - WebWindow* webWindow = nsWindowToWebWindow[hwnd]; + WebWindow* webWindow = nsWindowToWebWindow[window]; if (webWindow) { int x, y; diff --git a/src/WebWindow.Native/WebWindow.h b/src/WebWindow.Native/WebWindow.h index 302b05c..f5cf4f7 100644 --- a/src/WebWindow.Native/WebWindow.h +++ b/src/WebWindow.Native/WebWindow.h @@ -16,16 +16,13 @@ typedef const wchar_t* AutoString; typedef char* AutoString; #endif -struct Rect -{ - int x, y; - int width, height; -}; - struct Monitor { - Rect monitor; - Rect work; + struct MonitorRect + { + int x, y; + int width, height; + } monitor, work; }; typedef void (*ACTION)(); From a76ccd1de0b464ed68c8a0cf5e7fa8f4d0b13fc8 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Wed, 11 Dec 2019 19:50:35 +0800 Subject: [PATCH 36/47] Fix for new Edge Dev. --- src/WebWindow.Native/WebWindow.Native.vcxproj | 10 +++++----- .../WebWindow.Native.vcxproj.filters | 2 +- src/WebWindow.Native/WebWindow.Windows.cpp | 12 ++++++++---- src/WebWindow.Native/packages.config | 4 ++-- testassets/MyBlazorApp/MyBlazorApp.csproj | 2 +- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Native.vcxproj b/src/WebWindow.Native/WebWindow.Native.vcxproj index 3c5ef82..5b1eecf 100644 --- a/src/WebWindow.Native/WebWindow.Native.vcxproj +++ b/src/WebWindow.Native/WebWindow.Native.vcxproj @@ -159,14 +159,14 @@ - - + + - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 - - + + \ No newline at end of file diff --git a/src/WebWindow.Native/WebWindow.Native.vcxproj.filters b/src/WebWindow.Native/WebWindow.Native.vcxproj.filters index eaf12b1..9e7bf64 100644 --- a/src/WebWindow.Native/WebWindow.Native.vcxproj.filters +++ b/src/WebWindow.Native/WebWindow.Native.vcxproj.filters @@ -31,7 +31,7 @@ - + \ No newline at end of file diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 3d0764d..8f31239 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -237,8 +237,12 @@ void WebWindow::AttachWebView() return S_OK; }).Get(), &webMessageToken); + IWebView2WebView5* webviewWindow5; + _webviewWindow->QueryInterface(&webviewWindow5); + EventRegistrationToken webResourceRequestedToken; - _webviewWindow->add_WebResourceRequested(nullptr, nullptr, 0, Callback( + webviewWindow5->AddWebResourceRequestedFilter(nullptr, WEBVIEW2_WEB_RESOURCE_CONTEXT_ALL); + webviewWindow5->add_WebResourceRequested(Callback( [this](IWebView2WebView* sender, IWebView2WebResourceRequestedEventArgs* args) { IWebView2WebResourceRequest* req; @@ -247,18 +251,18 @@ void WebWindow::AttachWebView() wil::unique_cotaskmem_string uri; req->get_Uri(&uri); std::wstring uriString = uri.get(); - size_t colonPos = uriString.find(L':', 0); + size_t colonPos = uriString.find(L':'); if (colonPos > 0) { std::wstring scheme = uriString.substr(0, colonPos); WebResourceRequestedCallback handler = _schemeToRequestHandler[scheme]; - if (handler != NULL) + if (handler) { int numBytes; AutoString contentType; wil::unique_cotaskmem dotNetResponse(handler(uriString.c_str(), &numBytes, &contentType)); - if (dotNetResponse != nullptr && contentType != nullptr) + if (dotNetResponse && contentType) { std::wstring contentTypeWS = contentType; diff --git a/src/WebWindow.Native/packages.config b/src/WebWindow.Native/packages.config index 8137acf..f10b389 100644 --- a/src/WebWindow.Native/packages.config +++ b/src/WebWindow.Native/packages.config @@ -1,5 +1,5 @@  - - + + \ No newline at end of file diff --git a/testassets/MyBlazorApp/MyBlazorApp.csproj b/testassets/MyBlazorApp/MyBlazorApp.csproj index b855521..ff215c4 100644 --- a/testassets/MyBlazorApp/MyBlazorApp.csproj +++ b/testassets/MyBlazorApp/MyBlazorApp.csproj @@ -2,7 +2,7 @@ netcoreapp3.0 - WinExe + Exe From acdb2a1d8918eb8a0378a5359ad42cf8b7174cee Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Wed, 11 Dec 2019 21:56:37 +0800 Subject: [PATCH 37/47] Fix invoke block. --- src/WebWindow.Native/WebWindow.Windows.cpp | 30 ++++--------------- testassets/MyBlazorApp/MyBlazorApp.csproj | 2 +- testassets/MyBlazorApp/Pages/WindowProp.razor | 7 ++++- 3 files changed, 13 insertions(+), 26 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 8f31239..0a73397 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -19,12 +19,6 @@ HINSTANCE WebWindow::_hInstance; HWND messageLoopRootWindowHandle; std::map hwndToWebWindow; -struct InvokeWaitInfo -{ - std::condition_variable completionNotifier; - bool isCompleted; -}; - struct ShowMessageParams { std::wstring title; @@ -41,7 +35,7 @@ void WebWindow::Register(HINSTANCE hInstance) wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; - RegisterClassW(&wc); + RegisterClass(&wc); SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); } @@ -51,7 +45,7 @@ WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCall // Create the window _webMessageReceivedCallback = webMessageReceivedCallback; _parent = parent; - _hWnd = CreateWindowExW( + _hWnd = CreateWindowEx( 0, // Optional window styles. CLASS_NAME, // Window class title, // Window text @@ -94,7 +88,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_USER_SHOWMESSAGE: { ShowMessageParams* params = (ShowMessageParams*)wParam; - MessageBoxW(hwnd, params->body.c_str(), params->title.c_str(), params->type); + MessageBox(hwnd, params->body.c_str(), params->title.c_str(), params->type); delete params; return 0; } @@ -103,12 +97,6 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { ACTION callback = (ACTION)wParam; callback(); - InvokeWaitInfo* waitInfo = (InvokeWaitInfo*)lParam; - { - std::lock_guard guard(invokeLockMutex); - waitInfo->isCompleted = true; - } - waitInfo->completionNotifier.notify_one(); return 0; } case WM_SIZE: @@ -152,7 +140,7 @@ void WebWindow::RefitContent() void WebWindow::SetTitle(AutoString title) { - SetWindowTextW(_hWnd, title); + SetWindowText(_hWnd, title); } void WebWindow::Show() @@ -187,18 +175,12 @@ void WebWindow::ShowMessage(AutoString title, AutoString body, UINT type) params->title = title; params->body = body; params->type = type; - PostMessageW(_hWnd, WM_USER_SHOWMESSAGE, (WPARAM)params, 0); + ::SendMessage(_hWnd, WM_USER_SHOWMESSAGE, (WPARAM)params, 0); } void WebWindow::Invoke(ACTION callback) { - InvokeWaitInfo waitInfo = {}; - PostMessageW(_hWnd, WM_USER_INVOKE, (WPARAM)callback, (LPARAM)&waitInfo); - - // Block until the callback is actually executed and completed - // TODO: Add return values, exception handling, etc. - std::unique_lock uLock(invokeLockMutex); - waitInfo.completionNotifier.wait(uLock, [&] { return waitInfo.isCompleted; }); + ::SendMessage(_hWnd, WM_USER_INVOKE, (WPARAM)callback, 0); } void WebWindow::AttachWebView() diff --git a/testassets/MyBlazorApp/MyBlazorApp.csproj b/testassets/MyBlazorApp/MyBlazorApp.csproj index ff215c4..b855521 100644 --- a/testassets/MyBlazorApp/MyBlazorApp.csproj +++ b/testassets/MyBlazorApp/MyBlazorApp.csproj @@ -2,7 +2,7 @@ netcoreapp3.0 - Exe + WinExe diff --git a/testassets/MyBlazorApp/Pages/WindowProp.razor b/testassets/MyBlazorApp/Pages/WindowProp.razor index 5b476cc..7c577c5 100644 --- a/testassets/MyBlazorApp/Pages/WindowProp.razor +++ b/testassets/MyBlazorApp/Pages/WindowProp.razor @@ -3,7 +3,6 @@ @inject WebWindow Window

Window properties

-

Screen size

DPI: @Window.ScreenDpi

@foreach (var (m, i) in Window.Monitors.Select((monitor, index) => (monitor, index))) @@ -55,6 +54,12 @@
@code { + protected override void OnInitialized() + { + Window.SizeChanged += (sender, e) => StateHasChanged(); + Window.LocationChanged += (sender, e) => StateHasChanged(); + } + string iconFilename; void ChangeIconFile() From 9cb955a077ce9e47ffa8561c0bc609900d4004f5 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Thu, 12 Dec 2019 00:02:15 +0800 Subject: [PATCH 38/47] Revert "Fix invoke block." This reverts commit 4af9a65e2582bcfdf1c28b1d06913f9925bf5da6. --- src/WebWindow.Native/WebWindow.Windows.cpp | 30 +++++++++++++++---- testassets/MyBlazorApp/MyBlazorApp.csproj | 2 +- testassets/MyBlazorApp/Pages/WindowProp.razor | 7 +---- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 0a73397..8f31239 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -19,6 +19,12 @@ HINSTANCE WebWindow::_hInstance; HWND messageLoopRootWindowHandle; std::map hwndToWebWindow; +struct InvokeWaitInfo +{ + std::condition_variable completionNotifier; + bool isCompleted; +}; + struct ShowMessageParams { std::wstring title; @@ -35,7 +41,7 @@ void WebWindow::Register(HINSTANCE hInstance) wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; - RegisterClass(&wc); + RegisterClassW(&wc); SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); } @@ -45,7 +51,7 @@ WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCall // Create the window _webMessageReceivedCallback = webMessageReceivedCallback; _parent = parent; - _hWnd = CreateWindowEx( + _hWnd = CreateWindowExW( 0, // Optional window styles. CLASS_NAME, // Window class title, // Window text @@ -88,7 +94,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_USER_SHOWMESSAGE: { ShowMessageParams* params = (ShowMessageParams*)wParam; - MessageBox(hwnd, params->body.c_str(), params->title.c_str(), params->type); + MessageBoxW(hwnd, params->body.c_str(), params->title.c_str(), params->type); delete params; return 0; } @@ -97,6 +103,12 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { ACTION callback = (ACTION)wParam; callback(); + InvokeWaitInfo* waitInfo = (InvokeWaitInfo*)lParam; + { + std::lock_guard guard(invokeLockMutex); + waitInfo->isCompleted = true; + } + waitInfo->completionNotifier.notify_one(); return 0; } case WM_SIZE: @@ -140,7 +152,7 @@ void WebWindow::RefitContent() void WebWindow::SetTitle(AutoString title) { - SetWindowText(_hWnd, title); + SetWindowTextW(_hWnd, title); } void WebWindow::Show() @@ -175,12 +187,18 @@ void WebWindow::ShowMessage(AutoString title, AutoString body, UINT type) params->title = title; params->body = body; params->type = type; - ::SendMessage(_hWnd, WM_USER_SHOWMESSAGE, (WPARAM)params, 0); + PostMessageW(_hWnd, WM_USER_SHOWMESSAGE, (WPARAM)params, 0); } void WebWindow::Invoke(ACTION callback) { - ::SendMessage(_hWnd, WM_USER_INVOKE, (WPARAM)callback, 0); + InvokeWaitInfo waitInfo = {}; + PostMessageW(_hWnd, WM_USER_INVOKE, (WPARAM)callback, (LPARAM)&waitInfo); + + // Block until the callback is actually executed and completed + // TODO: Add return values, exception handling, etc. + std::unique_lock uLock(invokeLockMutex); + waitInfo.completionNotifier.wait(uLock, [&] { return waitInfo.isCompleted; }); } void WebWindow::AttachWebView() diff --git a/testassets/MyBlazorApp/MyBlazorApp.csproj b/testassets/MyBlazorApp/MyBlazorApp.csproj index b855521..ff215c4 100644 --- a/testassets/MyBlazorApp/MyBlazorApp.csproj +++ b/testassets/MyBlazorApp/MyBlazorApp.csproj @@ -2,7 +2,7 @@ netcoreapp3.0 - WinExe + Exe diff --git a/testassets/MyBlazorApp/Pages/WindowProp.razor b/testassets/MyBlazorApp/Pages/WindowProp.razor index 7c577c5..5b476cc 100644 --- a/testassets/MyBlazorApp/Pages/WindowProp.razor +++ b/testassets/MyBlazorApp/Pages/WindowProp.razor @@ -3,6 +3,7 @@ @inject WebWindow Window

Window properties

+

Screen size

DPI: @Window.ScreenDpi

@foreach (var (m, i) in Window.Monitors.Select((monitor, index) => (monitor, index))) @@ -54,12 +55,6 @@
@code { - protected override void OnInitialized() - { - Window.SizeChanged += (sender, e) => StateHasChanged(); - Window.LocationChanged += (sender, e) => StateHasChanged(); - } - string iconFilename; void ChangeIconFile() From 5b1b5c4372a63a59e0e18d267d7ef10cce7d8f69 Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Thu, 12 Dec 2019 00:06:35 +0800 Subject: [PATCH 39/47] Fix block in another thread. --- src/WebWindow.Native/WebWindow.Windows.cpp | 12 ++++++------ testassets/MyBlazorApp/MyBlazorApp.csproj | 2 +- testassets/MyBlazorApp/Pages/WindowProp.razor | 8 ++++++-- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 8f31239..8f5d3c0 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -41,7 +41,7 @@ void WebWindow::Register(HINSTANCE hInstance) wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; - RegisterClassW(&wc); + RegisterClass(&wc); SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); } @@ -51,7 +51,7 @@ WebWindow::WebWindow(AutoString title, WebWindow* parent, WebMessageReceivedCall // Create the window _webMessageReceivedCallback = webMessageReceivedCallback; _parent = parent; - _hWnd = CreateWindowExW( + _hWnd = CreateWindowEx( 0, // Optional window styles. CLASS_NAME, // Window class title, // Window text @@ -94,7 +94,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_USER_SHOWMESSAGE: { ShowMessageParams* params = (ShowMessageParams*)wParam; - MessageBoxW(hwnd, params->body.c_str(), params->title.c_str(), params->type); + MessageBox(hwnd, params->body.c_str(), params->title.c_str(), params->type); delete params; return 0; } @@ -152,7 +152,7 @@ void WebWindow::RefitContent() void WebWindow::SetTitle(AutoString title) { - SetWindowTextW(_hWnd, title); + SetWindowText(_hWnd, title); } void WebWindow::Show() @@ -187,13 +187,13 @@ void WebWindow::ShowMessage(AutoString title, AutoString body, UINT type) params->title = title; params->body = body; params->type = type; - PostMessageW(_hWnd, WM_USER_SHOWMESSAGE, (WPARAM)params, 0); + PostMessage(_hWnd, WM_USER_SHOWMESSAGE, (WPARAM)params, 0); } void WebWindow::Invoke(ACTION callback) { InvokeWaitInfo waitInfo = {}; - PostMessageW(_hWnd, WM_USER_INVOKE, (WPARAM)callback, (LPARAM)&waitInfo); + PostMessage(_hWnd, WM_USER_INVOKE, (WPARAM)callback, (LPARAM)&waitInfo); // Block until the callback is actually executed and completed // TODO: Add return values, exception handling, etc. diff --git a/testassets/MyBlazorApp/MyBlazorApp.csproj b/testassets/MyBlazorApp/MyBlazorApp.csproj index ff215c4..b855521 100644 --- a/testassets/MyBlazorApp/MyBlazorApp.csproj +++ b/testassets/MyBlazorApp/MyBlazorApp.csproj @@ -2,7 +2,7 @@ netcoreapp3.0 - Exe + WinExe diff --git a/testassets/MyBlazorApp/Pages/WindowProp.razor b/testassets/MyBlazorApp/Pages/WindowProp.razor index 5b476cc..2fab8a2 100644 --- a/testassets/MyBlazorApp/Pages/WindowProp.razor +++ b/testassets/MyBlazorApp/Pages/WindowProp.razor @@ -1,9 +1,7 @@ @page "/window" -@using System.IO @inject WebWindow Window

Window properties

-

Screen size

DPI: @Window.ScreenDpi

@foreach (var (m, i) in Window.Monitors.Select((monitor, index) => (monitor, index))) @@ -55,6 +53,12 @@
@code { + protected override void OnInitialized() + { + Window.SizeChanged += async (sender, e) => await Task.Run(StateHasChanged); + Window.LocationChanged += async (sender, e) => await Task.Run(StateHasChanged); + } + string iconFilename; void ChangeIconFile() From 758dba0eb5205ec04e72780898f81cde03baa67a Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sat, 14 Dec 2019 17:24:35 +0800 Subject: [PATCH 40/47] Use IReadOnlyList for monitors. --- src/WebWindow/WebWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 93920f9..47dd3f2 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -427,7 +427,7 @@ public Point Location public event EventHandler LocationChanged; - public IEnumerable Monitors + public IReadOnlyList Monitors { get { From f26a0dca83431bd0dfadefa1a2f0bc005869e5ce Mon Sep 17 00:00:00 2001 From: Berrysoft Date: Sat, 14 Dec 2019 17:26:28 +0800 Subject: [PATCH 41/47] Fix warning. --- src/WebWindow.Blazor/IPC.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WebWindow.Blazor/IPC.cs b/src/WebWindow.Blazor/IPC.cs index fa7b18d..6c3863e 100644 --- a/src/WebWindow.Blazor/IPC.cs +++ b/src/WebWindow.Blazor/IPC.cs @@ -19,7 +19,7 @@ public IPC(WebWindow webWindow) _webWindow.OnWebMessageReceived += HandleScriptNotify; } - public async Task Send(string eventName, params object[] args) + public void Send(string eventName, params object[] args) { try { From 7c23f3ab0de1940b6303e61f9237ace8d25dbcfa Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 23 Dec 2019 10:35:18 +0000 Subject: [PATCH 42/47] Revert "Fix for new Edge Dev." This reverts commit d7fb7caf1476c041fbaf254dad9ffd39a8213636. --- src/WebWindow.Native/WebWindow.Native.vcxproj | 10 +++++----- .../WebWindow.Native.vcxproj.filters | 2 +- src/WebWindow.Native/WebWindow.Windows.cpp | 12 ++++-------- src/WebWindow.Native/packages.config | 4 ++-- 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Native.vcxproj b/src/WebWindow.Native/WebWindow.Native.vcxproj index 5b1eecf..3c5ef82 100644 --- a/src/WebWindow.Native/WebWindow.Native.vcxproj +++ b/src/WebWindow.Native/WebWindow.Native.vcxproj @@ -159,14 +159,14 @@ - - + + - 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + \ No newline at end of file diff --git a/src/WebWindow.Native/WebWindow.Native.vcxproj.filters b/src/WebWindow.Native/WebWindow.Native.vcxproj.filters index 9e7bf64..eaf12b1 100644 --- a/src/WebWindow.Native/WebWindow.Native.vcxproj.filters +++ b/src/WebWindow.Native/WebWindow.Native.vcxproj.filters @@ -31,7 +31,7 @@ - + \ No newline at end of file diff --git a/src/WebWindow.Native/WebWindow.Windows.cpp b/src/WebWindow.Native/WebWindow.Windows.cpp index 8f5d3c0..f56db8c 100644 --- a/src/WebWindow.Native/WebWindow.Windows.cpp +++ b/src/WebWindow.Native/WebWindow.Windows.cpp @@ -237,12 +237,8 @@ void WebWindow::AttachWebView() return S_OK; }).Get(), &webMessageToken); - IWebView2WebView5* webviewWindow5; - _webviewWindow->QueryInterface(&webviewWindow5); - EventRegistrationToken webResourceRequestedToken; - webviewWindow5->AddWebResourceRequestedFilter(nullptr, WEBVIEW2_WEB_RESOURCE_CONTEXT_ALL); - webviewWindow5->add_WebResourceRequested(Callback( + _webviewWindow->add_WebResourceRequested(nullptr, nullptr, 0, Callback( [this](IWebView2WebView* sender, IWebView2WebResourceRequestedEventArgs* args) { IWebView2WebResourceRequest* req; @@ -251,18 +247,18 @@ void WebWindow::AttachWebView() wil::unique_cotaskmem_string uri; req->get_Uri(&uri); std::wstring uriString = uri.get(); - size_t colonPos = uriString.find(L':'); + size_t colonPos = uriString.find(L':', 0); if (colonPos > 0) { std::wstring scheme = uriString.substr(0, colonPos); WebResourceRequestedCallback handler = _schemeToRequestHandler[scheme]; - if (handler) + if (handler != NULL) { int numBytes; AutoString contentType; wil::unique_cotaskmem dotNetResponse(handler(uriString.c_str(), &numBytes, &contentType)); - if (dotNetResponse && contentType) + if (dotNetResponse != nullptr && contentType != nullptr) { std::wstring contentTypeWS = contentType; diff --git a/src/WebWindow.Native/packages.config b/src/WebWindow.Native/packages.config index f10b389..8137acf 100644 --- a/src/WebWindow.Native/packages.config +++ b/src/WebWindow.Native/packages.config @@ -1,5 +1,5 @@  - - + + \ No newline at end of file From 46dfaf5a5e1f03baaea30b50c666039419c6885e Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 23 Dec 2019 11:39:32 +0000 Subject: [PATCH 43/47] Make Invoke always safe by skipping dispatch when on UI thread --- src/WebWindow/WebWindow.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index 47dd3f2..b243d45 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -83,9 +83,10 @@ public class WebWindow [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] static extern void WebWindow_SetTopmost(IntPtr instance, int topmost); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)] static extern void WebWindow_SetIconFile(IntPtr instance, string filename); - private List _gcHandlesToFree = new List(); - private List _hGlobalToFree = new List(); - private IntPtr _nativeWebWindow; + private readonly List _gcHandlesToFree = new List(); + private readonly List _hGlobalToFree = new List(); + private readonly IntPtr _nativeWebWindow; + private readonly int _ownerThreadId; private string _title; static WebWindow() @@ -113,6 +114,8 @@ public WebWindow(string title) : this(title, _ => { }) public WebWindow(string title, Action configure) { + _ownerThreadId = Thread.CurrentThread.ManagedThreadId; + if (configure is null) { throw new ArgumentNullException(nameof(configure)); @@ -185,7 +188,15 @@ public void ShowMessage(string title, string body) public void Invoke(Action workItem) { - WebWindow_Invoke(_nativeWebWindow, workItem.Invoke); + // If we're already on the UI thread, no need to dispatch + if (Thread.CurrentThread.ManagedThreadId == _ownerThreadId) + { + workItem(); + } + else + { + WebWindow_Invoke(_nativeWebWindow, workItem.Invoke); + } } public IntPtr Hwnd From 651239882185989005a49a508d32b24a300b5d7b Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 23 Dec 2019 11:42:46 +0000 Subject: [PATCH 44/47] Fix threading issues for setting width/position/resizable/topmost --- src/WebWindow/WebWindow.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WebWindow/WebWindow.cs b/src/WebWindow/WebWindow.cs index b243d45..49e3b5a 100644 --- a/src/WebWindow/WebWindow.cs +++ b/src/WebWindow/WebWindow.cs @@ -303,7 +303,7 @@ public bool Resizable if (_resizable != value) { _resizable = value; - WebWindow_SetResizable(_nativeWebWindow, _resizable ? 1 : 0); + Invoke(() => WebWindow_SetResizable(_nativeWebWindow, _resizable ? 1 : 0)); } } } @@ -313,7 +313,7 @@ public bool Resizable private void GetSize() => WebWindow_GetSize(_nativeWebWindow, out _width, out _height); - private void SetSize() => WebWindow_SetSize(_nativeWebWindow, _width, _height); + private void SetSize() => Invoke(() => WebWindow_SetSize(_nativeWebWindow, _width, _height)); public int Width { @@ -378,7 +378,7 @@ public Size Size private void GetPosition() => WebWindow_GetPosition(_nativeWebWindow, out _x, out _y); - private void SetPosition() => WebWindow_SetPosition(_nativeWebWindow, _x, _y); + private void SetPosition() => Invoke(() => WebWindow_SetPosition(_nativeWebWindow, _x, _y)); public int Left { @@ -464,7 +464,7 @@ public bool Topmost if (_topmost != value) { _topmost = value; - WebWindow_SetTopmost(_nativeWebWindow, _topmost ? 1 : 0); + Invoke(() => WebWindow_SetTopmost(_nativeWebWindow, _topmost ? 1 : 0)); } } } From f9da5213d3a05035007ef79d57e8b2c908b6af1c Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 23 Dec 2019 12:15:37 +0000 Subject: [PATCH 45/47] On macOS, fix notifications for move/resize --- .../WebWindow.Mac.AppDelegate.mm | 26 ------------------- .../WebWindow.Mac.UiDelegate.h | 2 ++ ...Delegate.m => WebWindow.Mac.UiDelegate.mm} | 13 ++++++++++ src/WebWindow.Native/WebWindow.Mac.mm | 4 +++ src/WebWindow/WebWindow.csproj | 2 +- 5 files changed, 20 insertions(+), 27 deletions(-) rename src/WebWindow.Native/{WebWindow.Mac.UiDelegate.m => WebWindow.Mac.UiDelegate.mm} (88%) diff --git a/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm b/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm index a7c5848..57e881d 100644 --- a/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm +++ b/src/WebWindow.Native/WebWindow.Mac.AppDelegate.mm @@ -1,8 +1,4 @@ #import "WebWindow.Mac.AppDelegate.h" -#include "WebWindow.h" -#include - -extern std::map nsWindowToWebWindow; @implementation MyApplicationDelegate : NSObject - (id)init { @@ -17,28 +13,6 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { [NSApp activateIgnoringOtherApps:YES]; } -- (void)windowDidResize:(NSNotification *)notification { - NSWindow *window = notification.object; - WebWindow* webWindow = nsWindowToWebWindow[window]; - if (webWindow) - { - int width, height; - webWindow->GetSize(&width, &height); - webWindow->InvokeResized(width, height); - } -} - -- (void)windowDidMove:(NSNotification *)notification { - NSWindow *window = notification.object; - WebWindow* webWindow = nsWindowToWebWindow[window]; - if (webWindow) - { - int x, y; - webWindow->GetPosition(&x, &y); - webWindow->InvokeMoved(x, y); - } -} - - (void)dealloc { [window release]; [super dealloc]; diff --git a/src/WebWindow.Native/WebWindow.Mac.UiDelegate.h b/src/WebWindow.Native/WebWindow.Mac.UiDelegate.h index 8a75fee..96e16e9 100644 --- a/src/WebWindow.Native/WebWindow.Mac.UiDelegate.h +++ b/src/WebWindow.Native/WebWindow.Mac.UiDelegate.h @@ -1,11 +1,13 @@ #import #import +#include "WebWindow.h" typedef void (*WebMessageReceivedCallback) (char* message); @interface MyUiDelegate : NSObject { @public NSWindow * window; + WebWindow * webWindow; WebMessageReceivedCallback webMessageReceivedCallback; } @end diff --git a/src/WebWindow.Native/WebWindow.Mac.UiDelegate.m b/src/WebWindow.Native/WebWindow.Mac.UiDelegate.mm similarity index 88% rename from src/WebWindow.Native/WebWindow.Mac.UiDelegate.m rename to src/WebWindow.Native/WebWindow.Mac.UiDelegate.mm index 9af0136..89eddd2 100644 --- a/src/WebWindow.Native/WebWindow.Mac.UiDelegate.m +++ b/src/WebWindow.Native/WebWindow.Mac.UiDelegate.mm @@ -58,4 +58,17 @@ - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSSt [alert release]; }]; } + +- (void)windowDidResize:(NSNotification *)notification { + int width, height; + webWindow->GetSize(&width, &height); + webWindow->InvokeResized(width, height); +} + +- (void)windowDidMove:(NSNotification *)notification { + int x, y; + webWindow->GetPosition(&x, &y); + webWindow->InvokeMoved(x, y); +} + @end diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index bbfb7b0..3f9a513 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -67,6 +67,7 @@ void WebWindow::AttachWebView() { MyUiDelegate *uiDelegate = [[[MyUiDelegate alloc] init] autorelease]; + uiDelegate->webWindow = this; NSString *initScriptSource = @"window.__receiveMessageCallbacks = [];" "window.__dispatchMessageCallback = function(message) {" @@ -98,6 +99,9 @@ uiDelegate->webMessageReceivedCallback = _webMessageReceivedCallback; [userContentController addScriptMessageHandler:uiDelegate name:@"webwindowinterop"]; + [[NSNotificationCenter defaultCenter] addObserver:uiDelegate selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:window]; + [[NSNotificationCenter defaultCenter] addObserver:uiDelegate selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:window]; + _webview = webView; } diff --git a/src/WebWindow/WebWindow.csproj b/src/WebWindow/WebWindow.csproj index eb0fb6b..f2a56da 100644 --- a/src/WebWindow/WebWindow.csproj +++ b/src/WebWindow/WebWindow.csproj @@ -20,7 +20,7 @@ + Command="gcc -shared -lstdc++ -DOS_MAC -framework Cocoa -framework WebKit WebWindow.Mac.mm Exports.cpp WebWindow.Mac.AppDelegate.mm WebWindow.Mac.UiDelegate.mm WebWindow.Mac.UrlSchemeHandler.m -o x64/$(Configuration)/WebWindow.Native.dylib" /> From c31c396c048fb2fd746528cf6dc831b6ffee8bb7 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 23 Dec 2019 12:29:29 +0000 Subject: [PATCH 46/47] Fix size and position calculations for macOS --- src/WebWindow.Native/WebWindow.Mac.mm | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index 3f9a513..3d95055 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -208,11 +208,10 @@ CGFloat fh = (CGFloat)height; NSWindow* window = (NSWindow*)_window; NSRect frame = [window frame]; - frame.origin.x -= frame.size.width; - frame.origin.x += fw; - frame.origin.y -= frame.size.height; - frame.origin.y += fh; + CGFloat oldHeight = frame.size.height; + CGFloat heightDelta = fh - oldHeight; frame.size = CGSizeMake(fw, fh); + frame.origin.y -= heightDelta; [window setFrame: frame display: YES]; } @@ -247,16 +246,16 @@ { NSWindow* window = (NSWindow*)_window; NSRect frame = [window frame]; - if (x) *x = (int)roundf(frame.origin.x - frame.size.width); - if (y) *y = (int)roundf(frame.origin.y - frame.size.height); + if (x) *x = (int)roundf(frame.origin.x); + if (y) *y = (int)roundf(-frame.size.height - frame.origin.y); // It will be negative, because macOS measures from bottom-left. For x-plat consistency, we want increasing this value to mean moving down. } void WebWindow::SetPosition(int x, int y) { NSWindow* window = (NSWindow*)_window; NSRect frame = [window frame]; - frame.origin.x = frame.size.width + (CGFloat)x; - frame.origin.y = frame.size.height + (CGFloat)y; + frame.origin.x = (CGFloat)x; + frame.origin.y = -frame.size.height - (CGFloat)y; [window setFrame: frame display: YES]; } From 7263328df3fa9606e41a86b2d5c85c0d825f2723 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 23 Dec 2019 12:47:26 +0000 Subject: [PATCH 47/47] Update WebWindow.Mac.mm --- src/WebWindow.Native/WebWindow.Mac.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WebWindow.Native/WebWindow.Mac.mm b/src/WebWindow.Native/WebWindow.Mac.mm index 3d95055..cdee0bf 100644 --- a/src/WebWindow.Native/WebWindow.Mac.mm +++ b/src/WebWindow.Native/WebWindow.Mac.mm @@ -99,6 +99,7 @@ uiDelegate->webMessageReceivedCallback = _webMessageReceivedCallback; [userContentController addScriptMessageHandler:uiDelegate name:@"webwindowinterop"]; + // TODO: Remove these observers when the window is closed [[NSNotificationCenter defaultCenter] addObserver:uiDelegate selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:window]; [[NSNotificationCenter defaultCenter] addObserver:uiDelegate selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:window];