Skip to content
 
 

Latest commit

 

History

18 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

webview

A tiny cross-platform webview library written in C++ using EdgeHTML / WinRT (Windows), Cocoa + Webkit (MacOS) and WebkitGTK (Linux).

Inspired from zerge's webview, this library was rewritten with several priorities:

  • A more "C++"-like API
  • Support for Microsoft Edge on Windows
  • Replaced Objective-C runtime C code with actual Objective-C code

Support

Windows MacOS Linux
Version Windows 10, v1809+ Tested on MacOS Mojave, Catalina Tested on Ubuntu 18.04.02 LTS
Web Engine EdgeHTML Webkit WebKit
GUI Windows API Cocoa GTK

There is also experimental support for the new Edge (Chromium) for Windows.

Usage

// main.cpp
#include "webview.h"

WEBVIEW_MAIN {
  // Create a 800 x 600 webview that shows Google
  wv::WebView w{800, 600, true, true, Str("Hello world!"), Str("http://google.com")};

  if (w.init() == -1) {
    return 1;
  }

  while (w.run() == 0);

  return 0;
}

Since Windows (WinAPI) uses std::wstrings, all string literals should be wrapped in the macro Str(s).

The following URL schemes are supported:

  • HTTP(S): http:// and https://
  • Local file: file:///, make sure to point to an html file
    • TODO: this doesn't work in Windows
  • Inline data: data:text/html,<html>...</html>
    • TODO: test on Windows

Check out example programs in the examples/ directory in this repo.

Note: WEBVIEW_MAIN is a macro that resolves to the correct entry point:

#ifdef WEBVIEW_WIN
#define WEBVIEW_MAIN int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
#else
#define WEBVIEW_MAIN int main(int argc, char **argv)
#endif

This is needed since Win32 GUI applications uses WinMain as the entry point rather than the standard main. You can write your own main for more control, but make sure to use WinMain if you need to support Windows.

Limitations

There are several limitations on Windows stemming from the EdgeHTML webview:

  • The webview cannot be run as an administrator.
  • The webview cannot navigate to local HTML files (i.e: file:///...).

Build

If you have CMake installed, the included config should work for all platforms.

Windows

First define WEBVIEW_WIN before adding webview.h.

In order to target EdgeHTML (Microsoft Edge), webview uses the new C++/WinRT API. This requires some additional requirements:

tl;dr: Upgrade to latest version of Windows 10, install Visual Studio 2019, install the Windows 10 SDK, and add the C++/WinRT VSIX.

To debug, install the Microsoft Edge DevTools.

Compiler

Also, use std::wstring in place of std::string when using webview APIs (with the exception of wv::WebView::callback).

I don't like Visual Studio!

While not officially supported, Microsoft does use Clang internally for testing purposes. If you want to use Clang, they have some basic instructions on their website.

I've gotten clang-cl to compile with the following steps:

  1. Download / clone this repo and navigate to it.

  2. Install the Windows 10 SDK. Make sure to install at least version 1809.

    1. (Optional) Add cppwinrt.exe to your PATH (located in C:\Program Files (x86)\Windows Kits\10\{version}\bin\x86\cppwinrt.exe).
  3. Run cppwinrt.exe -in sdk. (Optionally, you can add the -verbose flag.)

    1. This should generate a local directory called winrt containing a bunch of headers. These are WinRT projection headers that you can use to consume from C++ code. You will be needing these headers for compilation.
    2. For more on cppwinrt.exe, check out this blog post by the creator of C++/WinRT.
  4. Install LLVM 8.0.0. (I've tested it with 8.0.0, but Microsoft says LLVM 6.0.0 should work too.)

    1. (Optional) Add LLVM to your PATH, specifically clang-cl.exe.
  5. Compile by running clang-cl examples\main.cpp /EHsc /I "." -Xclang -std=c++17 -Xclang -Wno-delete-non-virtual-dtor -o webview.exe /link "WindowsApp.lib" "user32.lib" "kernel32.lib".

If your winrt/ directory is located somewhere else, change the /I "." argument above.

You may result in some compiler errors in some of the winrt:: headers. I fixed them by manually editing the headers in the winrt/ subdirectory.

Windows OS

  • Requires Windows 10, version 1809 (Build 17763)

The C++/WinRT API is fairly new, and its webview was introduced in v1803 (UniversalAPIContract v6). This also uses WebViewControl.AddInitializeScript introduced in v1809. For more information about API contracts, read this blog post by Microsoft.

Also, displaying localhost in the webview will only work after adding a loopback exception. A simple way to enable this is to run

CheckNetIsolation.exe LoopbackExempt -a -n=Microsoft.Win32WebViewHost_cw5n1h2txyewy

This can then be checked using CheckNetIsolation.exe LoopbackExempt -s. Read more about network loopbacks here.

MacOS

webview depends on the Cocoa and Webkit frameworks. Also, make sure your compiler supports Objective-C (g++ and clang++ should both work).

To compile,

g++ main.cpp -DWEBVIEW_MAC -ObjC++ -std=c++11 -framework Cocoa -framework Webkit -o webview

Linux

First install gtk+-3.0 and webkit2gtk-4.0:

sudo apt-get install libgtk-3-dev libwebkit2gtk-4.0-37 libwebkit2gtk-4.0-dev

Then to compile,

g++ main.cpp -DWEBVIEW_GTK=1 `pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.0` -o webview

Make sure to define WEBVIEW_GTK.

API (JavaScript)

To communicate from JavaScript to C++, use the method window.external.invoke:

// JavaScript
window.exteral.invoke('hello world!');
// C++
void callback(WebView &w, std::string &arg) {
  // arg = "hello world!"
}

This method can only accept strings, so objects must be serialized in some way:

// JavaScript
window.external.invoke(JSON.stringify({ foo: 'bar' }));

API (C++)

Note: On Windows, all strings are std::wstring due to the underlying WinRT API. On Linux, they are std::string. The only exception is WebView::setCallback, which uses std::string even on Windows.

If you need to support Windows, make sure to use the following main declaration:

#ifdef WIN32
int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
#else
int main() {
#endif
  // ...
}

Constructor

WebView(int width, int height, bool resizable, bool debug, string title,
        string url = DEFAULT_URL)

The default url (DEFAULT_URL) will render a blank page with a single root div:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  </head>
  <body>
    <div id="app"></div>
    <script type="text/javascript"></script>
  </body>
</html>

init

int init();

Initializes the webview window.

Returns

0 if successful, otherwise -1.

Example

#include "webview.h"

int main() {
  wv::WebView w{800, 600, true, true, "My WebView"};

  // Initialize the webview
  if (w.init() == -1) {
    return 1;
  }

  // Do stuff with the webview

  return 0;
}

setCallback

void setCallback(std::function<void(WebView &, std::string &)> callback);

Attaches a function that will run when receiving messages from JavaScript.

Params

  • callback: A callback function

Example

#include "webview.h"

void callback(WebView &w, std::string &arg) {
  if (arg == "color") {
    w.css("body { background-color: red; }");
  }
}

// ...

w.setCallback(callback);

setTitle

void setTitle(string title);

Sets the title of the webview window.

Params

  • title: The new title of the webview

setFullscreen

void setFullscreen(bool fs);

Sets the webview window to fullscreen or windowed mode.

Params

  • fs: True if setting to fullscreen, false if windowed

setBgColor

Sets the background color of the webview. If the webpage has a background color, it will take precedence over this color.

void setBgColor(uint8_t r, uint8_t g, uint8_t b, uint8_t a)

Params

  • r: Red component of the color (0 to 255)
  • g: Green component of the color (0 to 255)
  • b: Blue component of the color (0 to 255)
  • a: Alpha component of the color (0 to 255)

run

bool run();

Runs one iteration of the main loop. This method is blocking if no events are pending.

Returns

True if the webview window will be closed, otherwise false.

Example

#include "webview.h"

int main() {
  wv::WebView w{800, 600, true, true, "My WebView"};

  if (w.init() == -1) {
    return 1;
  }

  // Keep running until the window will close
  while (w.run() == 0);

  return 0;
}

navigate

void navigate(string uri);

Navigates the webview to the specified URI.

Params

  • uri: URI to the webpage

'preEval'

void preEval(string js);

Injects the JavaScript string into the webpage before it loads.

eval

void eval(string js);

Executes the JavaScript string in the current webpage.

Params

  • js: JavaScript string to execute

Example

#include "webview.h"

void callback(WebView &w, std::string &arg) {
  if (arg == "eval") {
    w.eval("alert('boo!')");
  }
}

int main() {
  wv::WebView w{800, 600, true, true, "My WebView"};

  if (w.init() == -1) {
    return 1;
  }

  w.setCallback(callback);

  while (w.run() == 0);

  return 0;
}

The alert will display when this is executed in the webpage:

window.external.invoke('eval');

css

void css(string css);

Applies the CSS string to the current webpage.

Params

  • css: CSS string to apply

Example

This method works similar to WebView::eval.

#include "webview.h"

void callback(WebView &w, std::string &arg) {
  if (arg == "style") {
    w.css("p { color: red; }");
  }
}

int main() {
  wv::WebView w{800, 600, true, true, "My WebView"};

  if (w.init() == -1) {
    return 1;
  }

  w.setCallback(callback);

  while (w.run() == 0);

  return 0;
}

All p tags will be colored red when this is executed in the webpage:

window.external.invoke('style');

exit

void exit();

Closes the webview window. This will cause the next invocation of WebView::run to return true.

About

Cross-platform webview library for C++

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages