[windows] Closer to webview2 integration

This commit is contained in:
Lea Anthony
2021-04-28 15:45:36 +10:00
parent 7f54f7bb7e
commit 944e1c99ff
5 changed files with 6715 additions and 50 deletions

View File

@@ -1,7 +1,12 @@
// Some code may be inspired by or directly used from Webview. // Some code may be inspired by or directly used from Webview.
#include "ffenestri_windows.h" #include "ffenestri_windows.h"
//#include "wv2ComHandler_windows.h" #include "wv2ComHandler_windows.h"
#include <functional> #include <functional>
#include <atomic>
#include <Shlwapi.h>
#include <locale>
#include <codecvt>
#include "windows/WebView2.h"
int debug = 0; int debug = 0;
DWORD mainThread; DWORD mainThread;
@@ -11,40 +16,14 @@ void dispatch(dispatchFunction func) {
PostThreadMessage(mainThread, WM_APP, 0, (LPARAM) new dispatchFunction(func)); PostThreadMessage(mainThread, WM_APP, 0, (LPARAM) new dispatchFunction(func));
} }
struct Application{
// Window specific
HWND window;
// WebViewControl webview;
// ICoreWebView2Controller* controller;
// Application
const char *title;
int width;
int height;
int resizable;
int devtools;
int fullscreen;
int startHidden;
int logLevel;
int hideWindowOnClose;
int minSizeSet;
LONG minWidth;
LONG minHeight;
int maxSizeSet;
LONG maxWidth;
LONG maxHeight;
int frame;
};
struct Application *NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose) { struct Application *NewApplication(const char *title, int width, int height, int resizable, int devtools, int fullscreen, int startHidden, int logLevel, int hideWindowOnClose) {
// Create application // Create application
struct Application *result = (struct Application*)malloc(sizeof(struct Application)); struct Application *result = (struct Application*)malloc(sizeof(struct Application));
result->window = nullptr; result->window = nullptr;
// result->webview = nullptr; result->webview = nullptr;
// result->controller = nullptr; result->webviewController = nullptr;
result->title = title; result->title = title;
result->width = width; result->width = width;
@@ -89,8 +68,16 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
case WM_DESTROY: { case WM_DESTROY: {
DestroyApplication(app); DestroyApplication(app);
return 0; break;
} }
// case WM_SIZE: {
// if( app->webviewController != nullptr) {
// RECT bounds;
// GetClientRect(app->window, &bounds);
// app->webviewController->put_Bounds(bounds);
// }
// break;
// }
case WM_GETMINMAXINFO: { case WM_GETMINMAXINFO: {
// Exit early if this is called before the window is created. // Exit early if this is called before the window is created.
if ( app == NULL ) { if ( app == NULL ) {
@@ -127,29 +114,31 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
default: default:
return DefWindowProc(hwnd, msg, wParam, lParam); return DefWindowProc(hwnd, msg, wParam, lParam);
} }
return 0;
} }
//
bool initWebView2(struct Application *app, int debug, messageCallback cb) {
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
std::atomic_flag flag = ATOMIC_FLAG_INIT;
flag.test_and_set();
//void initWebView2(struct Application *app, int debug, messageCallback cb) {
// CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
//
// std::atomic_flag flag = ATOMIC_FLAG_INIT;
// flag.test_and_set();
//
// char currentExePath[MAX_PATH]; // char currentExePath[MAX_PATH];
// GetModuleFileNameA(NULL, currentExePath, MAX_PATH); // GetModuleFileNameA(NULL, currentExePath, MAX_PATH);
// char *currentExeName = PathFindFileNameA(currentExePath); // char *currentExeName = PathFindFileNameA(currentExePath);
// //
// printf("current exe name = %s\n", currentExeName);
// std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> wideCharConverter; // std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> wideCharConverter;
// std::wstring userDataFolder = wideCharConverter.from_bytes(std::getenv("APPDATA")); // std::wstring userDataFolder = wideCharConverter.from_bytes(std::getenv("APPDATA"));
// std::wstring currentExeNameW = wideCharConverter.from_bytes(currentExeName); // std::wstring currentExeNameW = wideCharConverter.from_bytes(currentExeName);
// //
// HRESULT res = CreateCoreWebView2EnvironmentWithOptions( // HRESULT res = CreateCoreWebView2EnvironmentWithOptions(
// nullptr, (userDataFolder + L"/" + currentExeNameW).c_str(), nullptr, // nullptr, (userDataFolder + L"/" + currentExeNameW).c_str(), nullptr,
// new wv2ComHandler(app->window, cb, // new wv2ComHandler(app, cb,
// [&](ICoreWebView2Controller *controller) { // [&](ICoreWebView2Controller *webviewController) {
// app->controller = controller; // app->webviewController = webviewController;
// app->controller->get_CoreWebView2(&(app->webview)); // app->webviewController->get_CoreWebView2(&(app->webview));
// app->webview->AddRef(); // app->webview->AddRef();
// flag.clear(); // flag.clear();
// })); // }));
@@ -163,9 +152,13 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
// TranslateMessage(&msg); // TranslateMessage(&msg);
// DispatchMessage(&msg); // DispatchMessage(&msg);
// } // }
// init("window.external={invoke:s=>window.chrome.webview.postMessage(s)}"); //// init("window.external={invoke:s=>window.chrome.webview.postMessage(s)}");
// return true; return true;
//} }
void initialCallback(std::string message) {
printf("MESSAGE=%s\n", message);
}
void Run(struct Application* app, int argc, char **argv) { void Run(struct Application* app, int argc, char **argv) {
@@ -177,6 +170,9 @@ void Run(struct Application* app, int argc, char **argv) {
wc.lpszClassName = (LPCWSTR)"ffenestri"; wc.lpszClassName = (LPCWSTR)"ffenestri";
wc.lpfnWndProc = WndProc; wc.lpfnWndProc = WndProc;
// TODO: Menu
// wc.lpszMenuName = nullptr;
// Process window resizable // Process window resizable
DWORD windowStyle = WS_OVERLAPPEDWINDOW; DWORD windowStyle = WS_OVERLAPPEDWINDOW;
@@ -190,8 +186,8 @@ void Run(struct Application* app, int argc, char **argv) {
RegisterClassEx(&wc); RegisterClassEx(&wc);
app->window = CreateWindow((LPCWSTR)"ffenestri", (LPCWSTR)"", windowStyle, CW_USEDEFAULT, app->window = CreateWindow((LPCWSTR)"ffenestri", (LPCWSTR)"", windowStyle, CW_USEDEFAULT,
CW_USEDEFAULT, app->width, app->height, NULL, NULL, CW_USEDEFAULT, app->width, app->height, NULL, NULL,
GetModuleHandle(NULL), NULL); hInstance, NULL);
// Private setTitle as we're on the main thread // Private setTitle as we're on the main thread
setTitle(app, app->title); setTitle(app, app->title);
@@ -211,8 +207,8 @@ void Run(struct Application* app, int argc, char **argv) {
UpdateWindow(app->window); UpdateWindow(app->window);
SetFocus(app->window); SetFocus(app->window);
// TODO: Add webview2 // Add webview2
// initWebView2(app->window); initWebView2(app, 1, initialCallback);
// Main event loop // Main event loop
MSG msg; MSG msg;

View File

@@ -2,18 +2,45 @@
#ifndef _FFENESTRI_WINDOWS_H #ifndef _FFENESTRI_WINDOWS_H
#define _FFENESTRI_WINDOWS_H #define _FFENESTRI_WINDOWS_H
#define WIN32_LEAN_AND_MEAN
#define UNICODE 1 #define UNICODE 1
#include "ffenestri.h" #include "ffenestri.h"
#include <windows.h> #include <windows.h>
#include <wingdi.h> #include <wingdi.h>
#include <functional> #include <functional>
#include "windows/WebView2.h"
struct Application{
// Window specific
HWND window;
ICoreWebView2 *webview;
ICoreWebView2Controller* webviewController;
// Application
const char *title;
int width;
int height;
int resizable;
int devtools;
int fullscreen;
int startHidden;
int logLevel;
int hideWindowOnClose;
int minSizeSet;
LONG minWidth;
LONG minHeight;
int maxSizeSet;
LONG maxWidth;
LONG maxHeight;
int frame;
};
#define ON_MAIN_THREAD(code) dispatch( [=]{ code; } ) #define ON_MAIN_THREAD(code) dispatch( [=]{ code; } )
typedef std::function<void()> dispatchFunction; typedef std::function<void()> dispatchFunction;
//typedef std::function<void(const std::string)> messageCallback; typedef std::function<void(const std::string)> messageCallback;
//typedef std::function<void(ICoreWebView2Controller *)> comHandlerCallback; typedef std::function<void(ICoreWebView2Controller *)> comHandlerCallback;
void center(struct Application*); void center(struct Application*);
void setTitle(struct Application* app, const char *title); void setTitle(struct Application* app, const char *title);

View File

@@ -0,0 +1,68 @@
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 8.01.0622 */
/* @@MIDL_FILE_HEADING( ) */
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 500
#endif
/* verify that the <rpcsal.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCSAL_H_VERSION__
#define __REQUIRED_RPCSAL_H_VERSION__ 100
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif /* __RPCNDR_H_VERSION__ */
#ifndef __eventtoken_h__
#define __eventtoken_h__
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
/* Forward Declarations */
#ifdef __cplusplus
extern "C"{
#endif
/* interface __MIDL_itf_eventtoken_0000_0000 */
/* [local] */
// Microsoft Windows
// Copyright (c) Microsoft Corporation. All rights reserved.
#pragma once
typedef struct EventRegistrationToken
{
__int64 value;
} EventRegistrationToken;
extern RPC_IF_HANDLE __MIDL_itf_eventtoken_0000_0000_v0_0_c_ifspec;
extern RPC_IF_HANDLE __MIDL_itf_eventtoken_0000_0000_v0_0_s_ifspec;
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
#ifndef WV2COMHANDLER_H
#define WV2COMHANDLER_H
#include "ffenestri_windows.h"
#include "windows/WebView2.h"
#include <locale>
#include <codecvt>
class wv2ComHandler
: public ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler,
public ICoreWebView2CreateCoreWebView2ControllerCompletedHandler,
public ICoreWebView2WebMessageReceivedEventHandler,
public ICoreWebView2PermissionRequestedEventHandler {
struct Application *app;
messageCallback mcb;
comHandlerCallback cb;
public:
wv2ComHandler(struct Application *app, messageCallback mcb, comHandlerCallback cb) {
this->app = app;
this->mcb = mcb;
this->cb = cb;
}
ULONG STDMETHODCALLTYPE AddRef() { return 1; }
ULONG STDMETHODCALLTYPE Release() { return 1; }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppv) {
return S_OK;
}
HRESULT STDMETHODCALLTYPE Invoke(HRESULT res,
ICoreWebView2Environment *env) {
env->CreateCoreWebView2Controller(app->window, this);
return S_OK;
}
HRESULT STDMETHODCALLTYPE Invoke(HRESULT res,
ICoreWebView2Controller *controller) {
controller->AddRef();
ICoreWebView2 *webview;
::EventRegistrationToken token;
controller->get_CoreWebView2(&webview);
webview->add_WebMessageReceived(this, &token);
webview->add_PermissionRequested(this, &token);
cb(controller);
return S_OK;
}
HRESULT STDMETHODCALLTYPE Invoke(
ICoreWebView2 *sender, ICoreWebView2WebMessageReceivedEventArgs *args) {
LPWSTR message;
args->TryGetWebMessageAsString(&message);
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> wideCharConverter;
mcb(wideCharConverter.to_bytes(message));
sender->PostWebMessageAsString(message);
CoTaskMemFree(message);
return S_OK;
}
HRESULT STDMETHODCALLTYPE
Invoke(ICoreWebView2 *sender,
ICoreWebView2PermissionRequestedEventArgs *args) {
COREWEBVIEW2_PERMISSION_KIND kind;
args->get_PermissionKind(&kind);
if (kind == COREWEBVIEW2_PERMISSION_KIND_CLIPBOARD_READ) {
args->put_State(COREWEBVIEW2_PERMISSION_STATE_ALLOW);
}
return S_OK;
}
};
#endif