diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..48b3a0d --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +all: + @echo "oke" + +clean: + rm -f *.rkt~ + (cd private;rm -f *.rkt~) diff --git a/rktwebview/.gitignore b/rktwebview/.gitignore deleted file mode 100644 index 8a9d35c..0000000 --- a/rktwebview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.user diff --git a/rktwebview/CMakeLists.txt b/rktwebview/CMakeLists.txt deleted file mode 100644 index a4dfdc7..0000000 --- a/rktwebview/CMakeLists.txt +++ /dev/null @@ -1,123 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -project(rktwebview LANGUAGES CXX) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(GIT_EXECUTABLE git) -set(CMAKE_VERBOSE_MAKEFILE ON) - -set(WEBVIEW_BUILD_STATIC_LIBRARY ON) -set(WEBVIEW_WEBKITGTK_API "6.0") -#set(WEBVIEW_WEBKITGTK_PREFERRED_API_LIST webkitgtk-6.0) - -if("${CMAKE_BUILD_TYPE}" STREQUAL "") - set(CMAKE_BUILD_TYPE "Release") -endif() - -if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - set(LIBKIND "d") -else() - set(LIBKIND "r") -endif() - -if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - set(LIBEXT lib) - set(LIBPRE ) -else() - set(LIBEXT a) - set(LIBPRE lib) -endif() - -if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - # using Clang - add_compile_options(-fPIC) - set(CFLAGS_ENV "CFLAGS=-fPIC") -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # using GCC - add_compile_options(-fPIC) - set(CFLAGS_ENV "CFLAGS=-fPIC") -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") - # using Intel C++ - set(CFLAGS_ENV "") -elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") - # using Visual Studio C++ - set(CFLAGS_ENV "") -endif() - -if(NOT(EXISTS ./deps)) - file(MAKE_DIRECTORY ./deps) -endif() - -function(git_dep dir dep) - if(EXISTS ${rktwebview_SOURCE_DIR}/deps/${dir}) - execute_process( - COMMAND ${GIT_EXECUTABLE} pull - COMMAND_ECHO STDOUT - WORKING_DIRECTORY ${rktwebview_SOURCE_DIR}/deps/${dir} - ) - else() - message("Executing git clone...") - execute_process( - COMMAND ${GIT_EXECUTABLE} clone ${dep} ${rktwebview_SOURCE_DIR}/deps/${dir} - COMMAND_ECHO STDOUT - ) - endif() -endfunction() - -git_dep(webview https://github.com/webview/webview.git) -add_subdirectory(deps/webview) - - -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - find_package(PkgConfig REQUIRED) - pkg_check_modules(GTK REQUIRED gtk+-3.0) - - include_directories(${GTK_INCLUDE_DIRS}) - message("${GTK_INCLUDE_DIRS}") - link_directories(${GTK_LIBRARY_DIRS}) - - pkg_check_modules(GTKWEBVIEW REQUIRED webkit2gtk-4.1) - include_directories(${GTKWEBVIEW_INCLUDE_DIRS}) - message("${GTKWEBVIEW_INCLUDE_DIRS}") - link_directories(${GTKWEBVIEW_LIBRARY_DIRS}) -endif() - -include_directories(deps/webview/core/include) -include_directories(deps/webview/build/Release/_deps/microsoft_web_webview2-src/build/native/include) -link_directories(build/Release/deps/webview/core) -link_directories(build/Release) - -add_library(rktwebview SHARED - rktwebview_global.h - rktwebview.cpp - rktwebview.h - - json.h - json.cpp -) - -add_executable(rktwebview_test - main.cpp - - rktwebview_global.h - rktwebview.cpp - rktwebview.h - - json.h - json.cpp -) - -#add_dependencies(rktwebview webview) - -target_link_libraries(rktwebview webview_core_static) -#target_link_libraries(rktwebview_test rktwebview) -target_link_libraries(rktwebview_test webview_core_static) - -target_compile_definitions(rktwebview PRIVATE RKTWEBVIEW_LIBRARY) - -if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - target_link_libraries(rktwebview ${GTK_LIBRARIES} ${GTKWEBVIEW_LIBRARIES}) - target_link_libraries(rktwebview_test ${GTK_LIBRARIES} ${GTKWEBVIEW_LIBRARIES}) -endif() - diff --git a/rktwebview/json.cpp b/rktwebview/json.cpp deleted file mode 100644 index 571eaa9..0000000 --- a/rktwebview/json.cpp +++ /dev/null @@ -1,505 +0,0 @@ -#include "json.h" - -using std::map; -using std::deque; -using std::string; -using std::enable_if; -using std::initializer_list; -using std::is_same; -using std::is_convertible; -using std::is_integral; -using std::is_floating_point; - -std::string json_escape(const string &str) { - string output; - for( unsigned i = 0; i < str.length(); ++i ) - switch( str[i] ) { - case '\"': output += "\\\""; break; - case '\\': output += "\\\\"; break; - case '\b': output += "\\b"; break; - case '\f': output += "\\f"; break; - case '\n': output += "\\n"; break; - case '\r': output += "\\r"; break; - case '\t': output += "\\t"; break; - default : output += str[i]; break; - } - return std::move( output ); -} - -JSON::JSON() : Internal(), Type( Class::Null ){} - -JSON::JSON(std::initializer_list list) - : JSON() -{ - SetType( Class::Object ); - for( auto i = list.begin(), e = list.end(); i != e; ++i, ++i ) - operator[]( i->toString() ) = *std::next( i ); -} - -JSON::JSON(JSON &&other) - : Internal( other.Internal ) - , Type( other.Type ) -{ other.Type = Class::Null; other.Internal.Map = nullptr; } - -JSON::JSON(const JSON &other) { - switch( other.Type ) { - case Class::Object: - Internal.Map = - new map( other.Internal.Map->begin(), - other.Internal.Map->end() ); - break; - case Class::Array: - Internal.List = - new deque( other.Internal.List->begin(), - other.Internal.List->end() ); - break; - case Class::String: - Internal.String = - new string( *other.Internal.String ); - break; - default: - Internal = other.Internal; - } - Type = other.Type; -} - -JSON JSON::Make(Class type) { - JSON ret; ret.SetType( type ); - return ret; -} - -JSON &JSON::operator[](unsigned int index) { - SetType( Class::Array ); - if( index >= Internal.List->size() ) Internal.List->resize( index + 1 ); - return Internal.List->operator[]( index ); -} - -JSON &JSON::at(const std::string &key) { - return operator[]( key ); -} - -const JSON &JSON::at(const std::string &key) const { - return Internal.Map->at( key ); -} - -JSON &JSON::at(unsigned int index) { - return operator[]( index ); -} - -const JSON &JSON::at(unsigned int index) const { - return Internal.List->at( index ); -} - -int JSON::length() const { - if( Type == Class::Array ) - return Internal.List->size(); - else - return -1; -} - -bool JSON::hasKey(const std::string &key) const { - if( Type == Class::Object ) - return Internal.Map->find( key ) != Internal.Map->end(); - return false; -} - -int JSON::size() const { - if( Type == Class::Object ) - return Internal.Map->size(); - else if( Type == Class::Array ) - return Internal.List->size(); - else - return -1; -} - -JSON::Class JSON::JSONType() const { return Type; } - -bool JSON::IsNull() const { return Type == Class::Null; } - -string JSON::toString() const { bool b; return std::move( toString( b ) ); } - -string JSON::toString(bool &ok) const { - ok = (Type == Class::String); - return ok ? std::move( json_escape( *Internal.String ) ): string(""); -} - -double JSON::toFloat() const { bool b; return toFloat( b ); } - -double JSON::toFloat(bool &ok) const { - ok = (Type == Class::Floating); - return ok ? Internal.Float : 0.0; -} - -long JSON::toInt() const { bool b; return toInt( b ); } - -long JSON::toInt(bool &ok) const { - ok = (Type == Class::Integral); - return ok ? Internal.Int : 0; -} - -bool JSON::toBool() const { bool b; return toBool( b ); } - -bool JSON::toBool(bool &ok) const { - ok = (Type == Class::Boolean); - return ok ? Internal.Bool : false; -} - -JSON::JSONWrapper > JSON::ObjectRange() { - if( Type == Class::Object ) - return JSONWrapper>( Internal.Map ); - return JSONWrapper>( nullptr ); -} - -JSON::JSONWrapper > JSON::ArrayRange() { - if( Type == Class::Array ) - return JSONWrapper>( Internal.List ); - return JSONWrapper>( nullptr ); -} - -JSON::JSONConstWrapper > JSON::ObjectRange() const { - if( Type == Class::Object ) - return JSONConstWrapper>( Internal.Map ); - return JSONConstWrapper>( nullptr ); -} - -JSON::JSONConstWrapper > JSON::ArrayRange() const { - if( Type == Class::Array ) - return JSONConstWrapper>( Internal.List ); - return JSONConstWrapper>( nullptr ); -} - -string JSON::dump(int depth, const std::string &tab) const { - std::string pad = ""; - for( int i = 0; i < depth; ++i, pad += tab ); - - switch( Type ) { - case Class::Null: - return "null"; - case Class::Object: { - std::string s = "{ "; - bool skip = true; - for( auto &p : *Internal.Map ) { - if( !skip ) s += ", "; - s += ( pad + "\"" + p.first + "\" : " + p.second.dump( depth + 1, tab ) ); - skip = false; - } - s += ( " " + pad.erase( 0, 2 ) + "}" ) ; - return s; - } - case Class::Array: { - std::string s = "["; - bool skip = true; - for( auto &p : *Internal.List ) { - if( !skip ) s += ", "; - s += p.dump( depth + 1, tab ); - skip = false; - } - s += "]"; - return s; - } - case Class::String: - return "\"" + json_escape( *Internal.String ) + "\""; - case Class::Floating: - return std::to_string( Internal.Float ); - case Class::Integral: - return std::to_string( Internal.Int ); - case Class::Boolean: - return Internal.Bool ? "true" : "false"; - default: - return ""; - } - return ""; -} - -void JSON::SetType(Class type) { - if( type == Type ) - return; - - ClearInternal(); - - switch( type ) { - case Class::Null: Internal.Map = nullptr; break; - case Class::Object: Internal.Map = new std::map(); break; - case Class::Array: Internal.List = new std::deque(); break; - case Class::String: Internal.String = new std::string(); break; - case Class::Floating: Internal.Float = 0.0; break; - case Class::Integral: Internal.Int = 0; break; - case Class::Boolean: Internal.Bool = false; break; - } - - Type = type; -} - -void JSON::ClearInternal() { - switch( Type ) { - case Class::Object: delete Internal.Map; break; - case Class::Array: delete Internal.List; break; - case Class::String: delete Internal.String; break; - default:; - } -} - -JSON &JSON::operator[](const std::string &key) { - SetType( Class::Object ); return Internal.Map->operator[]( key ); -} - -JSON &JSON::operator=(const JSON &other) { - - if (&other == this) { return *this; } - - ClearInternal(); - switch( other.Type ) { - case Class::Object: - Internal.Map = - new map( other.Internal.Map->begin(), - other.Internal.Map->end() ); - break; - case Class::Array: - Internal.List = - new deque( other.Internal.List->begin(), - other.Internal.List->end() ); - break; - case Class::String: - Internal.String = - new string( *other.Internal.String ); - break; - default: - Internal = other.Internal; - } - Type = other.Type; - return *this; -} - -JSON &JSON::operator=(JSON &&other) { - ClearInternal(); - Internal = other.Internal; - Type = other.Type; - other.Internal.Map = nullptr; - other.Type = Class::Null; - return *this; -} - -JSON Array() { - return std::move( JSON::Make( JSON::Class::Array ) ); -} - -//JSON Object() { return std::move(JSON::Make(JSON::Class::Object)); } - -JSON Object() { - return std::move( JSON::Make( JSON::Class::Object ) ); -} - -std::ostream &operator<<(std::ostream &os, const JSON &json) { - os << json.dump(); - return os; -} - -// Private functions. - -static JSON parse_next( const std::string &, size_t &, std::function ); - - -static void consume_ws( const std::string &str, size_t &offset ) { - while( isspace( str[offset] ) ) ++offset; -} - -static JSON parse_object( const string &str, size_t &offset, std::function on_error ) { - JSON Object = JSON::Make( JSON::Class::Object ); - - ++offset; - consume_ws( str, offset ); - if( str[offset] == '}' ) { - ++offset; return std::move( Object ); - } - - while( true ) { - JSON Key = parse_next( str, offset, on_error ); - consume_ws( str, offset ); - if( str[offset] != ':' ) { - on_error(std::string("Error: Object: Expected colon, found '") + str[offset] + "'"); - break; - } - consume_ws( str, ++offset ); - JSON Value = parse_next( str, offset, on_error ); - Object[Key.toString()] = Value; - - consume_ws( str, offset ); - if( str[offset] == ',' ) { - ++offset; continue; - } - else if( str[offset] == '}' ) { - ++offset; break; - } - else { - on_error(std::string("ERROR: Object: Expected comma, found '") + str[offset] + "'"); - break; - } - } - - return std::move( Object ); -} - -static JSON parse_array( const string &str, size_t &offset, std::function on_error ) { - JSON Array = JSON::Make( JSON::Class::Array ); - unsigned index = 0; - - ++offset; - consume_ws( str, offset ); - if( str[offset] == ']' ) { - ++offset; return std::move( Array ); - } - - while( true ) { - Array[index++] = parse_next( str, offset, on_error ); - consume_ws( str, offset ); - - if( str[offset] == ',' ) { - ++offset; continue; - } - else if( str[offset] == ']' ) { - ++offset; break; - } - else { - on_error(std::string("ERROR: Array: Expected ',' or ']', found '") + str[offset] + "'"); - return std::move( JSON::Make( JSON::Class::Array ) ); - } - } - - return std::move( Array ); -} - -static JSON parse_string( const string &str, size_t &offset, std::function on_error ) { - JSON String; - string val; - for( char c = str[++offset]; c != '\"' ; c = str[++offset] ) { - if( c == '\\' ) { - switch( str[ ++offset ] ) { - case '\"': val += '\"'; break; - case '\\': val += '\\'; break; - case '/' : val += '/' ; break; - case 'b' : val += '\b'; break; - case 'f' : val += '\f'; break; - case 'n' : val += '\n'; break; - case 'r' : val += '\r'; break; - case 't' : val += '\t'; break; - case 'u' : { - val += "\\u" ; - for( unsigned i = 1; i <= 4; ++i ) { - c = str[offset+i]; - if( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) - val += c; - else { - on_error(std::string("ERROR: String: Expected hex character in unicode escape, found '") + c + "'"); - return std::move( JSON::Make( JSON::Class::String ) ); - } - } - offset += 4; - } break; - default : val += '\\'; break; - } - } - else - val += c; - } - ++offset; - String = val; - return std::move( String ); -} - -static JSON parse_number( const string &str, size_t &offset, std::function on_error ) { - JSON Number; - string val, exp_str; - char c; - bool isDouble = false; - long exp = 0; - while( true ) { - c = str[offset++]; - if( (c == '-') || (c >= '0' && c <= '9') ) - val += c; - else if( c == '.' ) { - val += c; - isDouble = true; - } - else - break; - } - if( c == 'E' || c == 'e' ) { - c = str[ offset++ ]; - if( c == '-' ){ ++offset; exp_str += '-';} - while( true ) { - c = str[ offset++ ]; - if( c >= '0' && c <= '9' ) - exp_str += c; - else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) { - on_error(std::string("ERROR: Number: Expected a number for exponent, found '") + c + "'"); - return std::move( JSON::Make( JSON::Class::Null ) ); - } - else - break; - } - exp = std::stol( exp_str ); - } - else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) { - on_error(std::string("ERROR: Number: unexpected character '") + c + "'"); - return std::move( JSON::Make( JSON::Class::Null ) ); - } - --offset; - - if( isDouble ) - Number = std::stod( val ) * std::pow( 10, exp ); - else { - if( !exp_str.empty() ) - Number = std::stol( val ) * std::pow( 10, exp ); - else - Number = std::stol( val ); - } - return std::move( Number ); -} - -static JSON parse_bool( const string &str, size_t &offset, std::function on_error ) { - JSON Bool; - if( str.substr( offset, 4 ) == "true" ) - Bool = true; - else if( str.substr( offset, 5 ) == "false" ) - Bool = false; - else { - on_error(std::string("ERROR: Bool: Expected 'true' or 'false', found '") + str.substr( offset, 5 ) + "'"); - return std::move( JSON::Make( JSON::Class::Null ) ); - } - offset += (Bool.toBool() ? 4 : 5); - return std::move( Bool ); -} - -static JSON parse_null( const string &str, size_t &offset, std::function on_error ) { - JSON Null; - if( str.substr( offset, 4 ) != "null" ) { - on_error(std::string("ERROR: Null: Expected 'null', found '") + str.substr( offset, 4 ) + "'" ); - return std::move( JSON::Make( JSON::Class::Null ) ); - } - offset += 4; - return std::move( Null ); -} - -static JSON parse_next( const string &str, size_t &offset, std::function on_error ) { - char value; - consume_ws( str, offset ); - value = str[offset]; - switch( value ) { - case '[' : return std::move( parse_array( str, offset, on_error ) ); - case '{' : return std::move( parse_object( str, offset, on_error ) ); - case '\"': return std::move( parse_string( str, offset, on_error ) ); - case 't' : - case 'f' : return std::move( parse_bool( str, offset, on_error ) ); - case 'n' : return std::move( parse_null( str, offset, on_error ) ); - default : if( ( value <= '9' && value >= '0' ) || value == '-' ) - return std::move( parse_number( str, offset, on_error ) ); - } - on_error(std::string("ERROR: Parse: Unknown starting character '") + value + "'"); - return JSON(); -} - -JSON JSON::Load( const string &str, std::function on_error) { - size_t offset = 0; - return std::move( parse_next( str, offset, on_error ) ); -} - diff --git a/rktwebview/json.h b/rktwebview/json.h deleted file mode 100644 index 7f54c39..0000000 --- a/rktwebview/json.h +++ /dev/null @@ -1,221 +0,0 @@ -#ifndef JSON_H -#define JSON_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -std::string json_escape( const std::string &str ); - -#ifdef Bool -#undef Bool -#endif - -class JSON -{ - union BackingData { - BackingData( double d ) : Float( d ){} - BackingData( long l ) : Int( l ){} - BackingData( bool b ) : Bool( b ){} - BackingData( std::string s ) : String( new std::string( s ) ){} - BackingData() : Int( 0 ){} - - std::deque *List; - std::map *Map; - std::string *String; - double Float; - long Int; - bool Bool; - } Internal; - -public: - enum class Class { - Null, - Object, - Array, - String, - Floating, - Integral, - Boolean - }; - - template - class JSONWrapper { - Container *object; - - public: - JSONWrapper( Container *val ) : object( val ) {} - JSONWrapper( std::nullptr_t ) : object( nullptr ) {} - - typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); } - typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); } - typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::iterator(); } - typename Container::const_iterator end() const { return object ? object->end() : typename Container::iterator(); } - }; - - template - class JSONConstWrapper { - const Container *object; - - public: - JSONConstWrapper( const Container *val ) : object( val ) {} - JSONConstWrapper( std::nullptr_t ) : object( nullptr ) {} - - typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); } - typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); } - }; - - JSON(); - JSON( std::nullptr_t ) : Internal(), Type( Class::Null ){} - JSON( std::initializer_list list ); - JSON( JSON&& other ); - JSON( const JSON &other ); - - JSON& operator=( const JSON &other ); - JSON& operator=( JSON&& other ); - - // Template T constructors - template - JSON( T b, typename std::enable_if::value>::type* = 0 ); - - template - JSON( T i, typename std::enable_if::value && !std::is_same::value>::type* = 0 ); - - template - JSON( T f, typename std::enable_if::value>::type* = 0 ); - - template - JSON( T s, typename std::enable_if::value>::type* = 0 ); - - ~JSON() { - switch( Type ) { - case Class::Array: - delete Internal.List; - break; - case Class::Object: - delete Internal.Map; - break; - case Class::String: - delete Internal.String; - break; - default:; - } - } - - static JSON Make( Class type ); - static JSON Load( const std::string &, std::function ); - - // Appending things. - - template - void append( T arg ) { - SetType( Class::Array ); Internal.List->emplace_back( arg ); - } - - template - void append( T arg, U... args ) { - append( arg ); append( args... ); - } - - // Assignments (template T). - - template - typename std::enable_if::value, JSON&>::type operator=( T b ) { - SetType( Class::Boolean ); Internal.Bool = b; return *this; - } - - template - typename std::enable_if::value && !std::is_same::value, JSON&>::type operator=( T i ) { - SetType( Class::Integral ); Internal.Int = i; return *this; - } - - template - typename std::enable_if::value, JSON&>::type operator=( T f ) { - SetType( Class::Floating ); Internal.Float = f; return *this; - } - - template - typename std::enable_if::value, JSON&>::type operator=( T s ) { - SetType( Class::String ); *Internal.String = std::string( s ); return *this; - } - - - - // Indexing. - JSON& operator[]( const std::string &key ); - JSON& operator[]( unsigned index ); - - JSON &at( const std::string &key ); - const JSON &at( const std::string &key ) const; - JSON &at( unsigned index ); - const JSON &at( unsigned index ) const; - - int length() const; - int size() const; - - bool hasKey( const std::string &key ) const; - - Class JSONType() const; - - /// Functions for getting primitives from the JSON object. - bool IsNull() const; - - std::string toString() const; - std::string toString( bool &ok ) const; - - double toFloat() const; - double toFloat( bool &ok ) const; - - long toInt() const; - long toInt( bool &ok ) const; - - bool toBool() const; - bool toBool( bool &ok ) const; - - JSONWrapper> ObjectRange(); - JSONWrapper> ArrayRange(); - JSONConstWrapper> ObjectRange() const; - JSONConstWrapper> ArrayRange() const; - - std::string dump( int depth = 1, const std::string &tab = std::string(" ")) const; - - friend std::ostream& operator<<( std::ostream&, const JSON & ); - -private: - void SetType( Class type ); - -private: - /* beware: only call if YOU know that Internal is allocated. No checks performed here. - This function should be called in a constructed JSON just before you are going to - overwrite Internal... - */ - void ClearInternal(); - -private: - - Class Type = Class::Null; -}; - -JSON Array(); - -template -JSON Array( T... args ) { - JSON arr = JSON::Make( JSON::Class::Array ); - arr.append( args... ); - return std::move( arr ); -} - -JSON Object(); - -std::ostream& operator<<( std::ostream &os, const JSON &json ); - - -#endif // JSON_H diff --git a/rktwebview/main.cpp b/rktwebview/main.cpp deleted file mode 100644 index eb0a3b6..0000000 --- a/rktwebview/main.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "rktwebview.h" -#include - -int main() -{ - rkt_webview_t *wv = rkt_create_webview(); - result_t r = rkt_webview_navigate(wv, "https://wikipedia.org"); - - rkt_webview_t *wv1 = nullptr; - //result_t r = rkt_set_html(wv, "He daar!

He daar!

"); - printf("Navigate: result = %d\n", r); - int i = 0; - while(rkt_webview_valid(wv)) { - printf("Waiting...%d\n", i); -#ifdef USE_WIN_THREADS - Sleep(1000); -#endif -#ifdef USE_PTHREADS - usleep(1000 * 1000); -#endif - i += 1; - if (i > 5) { - item_t item = rkt_webview_call_js(wv, "{ window.location = 'https://dijkewijk.nl'; return 42; }"); - printf("%d, %s\n", item.context, item.data); - rkt_webview_destroy_item(item); - item_t item1 = rkt_webview_call_js(wv, "{ return stuffwrong + 5 }"); - printf("%d, %s\n", item1.context, item1.data); - rkt_webview_destroy_item(item1); - } - if (i == 16) { - wv1 = rkt_create_webview(); - result_t r = rkt_webview_navigate(wv, "https://www.cs.cmu.edu/afs/cs/academic/class/15492-f07/www/pthreads.html"); - } - - } - return 0; -} diff --git a/rktwebview/rktwebview.cpp b/rktwebview/rktwebview.cpp deleted file mode 100644 index b50d288..0000000 --- a/rktwebview/rktwebview.cpp +++ /dev/null @@ -1,549 +0,0 @@ -#include "rktwebview.h" - -#include -#include "json.h" - -static void queue_init(queue_t *q); -static void enqueue(queue_t *q, item_t item); -static bool dequeue(queue_t *q, item_t *item); -static int queue_length(queue_t *q); -static void queue_destroy(queue_t *q); -static void free_item(item_t i); - -static void mutex_lock(rkt_webview_t *); -static void mutex_unlock(rkt_webview_t *); -static void thread_sleep_ms(rkt_webview_t *, int ms); - -static void handle_event(const char *id, const char *data, void *_wv); -static void handle_js_call(const char *id, const char *data, void *_wv); - -static void dispatcher(webview_t w, void *args); -static result_t do_dispatch(rkt_webview_t *, item_t item); - -#ifdef USE_WIN_THREADS -static DWORD webviewThread(LPVOID args) -#endif -#ifdef USE_PTHREADS -static void *webviewThread(void *args) -#endif -{ - rkt_webview_t *wv = (rkt_webview_t *) args; - mutex_lock(wv); - webview_t w = webview_create(0, NULL); - wv->webview_handle = w; - wv->handle_set = true; - webview_bind(w, "web_ui_wire_handle_event", handle_event, wv); - webview_bind(w, "rkt_webview_call_js_result", handle_js_call, wv); - mutex_unlock(wv); - webview_run(w); - webview_destroy(w); - mutex_lock(wv); - wv->webview_handle = NULL; - wv->handle_destroyed = true; - mutex_unlock(wv); -#ifdef USE_WIN_THREADS - return 0; -#endif -#ifdef USE_PTHREADS - return NULL; -#endif -} - -#ifdef USE_WIN_THREADS -static DWORD queueGuardThread(LPVOID args) -#endif -#ifdef USE_PTHREADS -static void *queueGuardThread(void *args) -#endif -{ - rkt_webview_t *wv = (rkt_webview_t *) args; - - auto handle_ok = [](rkt_webview_t *wv) { - mutex_lock(wv); - bool ok = !wv->handle_destroyed; - mutex_unlock(wv); - return ok; - }; - - while(handle_ok(wv)) { - mutex_lock(wv); - if (wv->queue_callback != NULL) { - while(queue_length(&wv->from_webview) > 0) { - item_t item; - dequeue(&wv->from_webview, &item); - wv->queue_callback(wv->queue_callback_id, item); - } - } - mutex_unlock(wv); - thread_sleep_ms(wv, 10); - } - -#ifdef USE_WIN_THREADS - return 0; -#endif -#ifdef USE_PTHREADS - return NULL; -#endif -} - - -RKTWEBVIEW_EXPORT rkt_webview_t *rkt_create_webview() -{ - rkt_webview_t *wv = (rkt_webview_t *) malloc(sizeof(rkt_webview_t)); - if (wv == NULL) { return NULL; } - - #ifdef USE_WIN_THREADS - wv->mutex = CreateMutex(NULL, FALSE, NULL); - #endif - #ifdef USE_PTHREADS - wv->mutex = PTHREAD_MUTEX_INITIALIZER; - #endif - wv->handle_set = false; - wv->handle_destroyed = false; - queue_init(&wv->to_webview); - queue_init(&wv->from_webview); - wv->webview_handle = NULL; - wv->queue_callback = NULL; - wv->js_call_nr = 0; - wv->js_evaluated = new std::map(); - - #ifdef USE_WIN_THREADS - wv->webview_thread = CreateThread( - NULL, - 0, - webviewThread, - wv, - 0, - &wv->webview_thread_id - ); - wv->queue_guard_thread = CreateThread( - NULL, - 0, - queueGuardThread, - wv, - 0, - &wv->queue_guard_thread_id - ); - #endif - #ifdef USE_PTHREADS - wv->webview_thread_id = pthread_create(&wv->webview_thread, NULL, webviewThread, wv); - wv->queue_guard_thread_id = pthread_create(&wv->queue_guard_thread, NULL, queueGuardThread, wv); - #endif - bool go_on = true; - while(go_on) { - mutex_lock(wv); - go_on = (wv->handle_set == false); - mutex_unlock(wv); - if (go_on) { - thread_sleep_ms(wv, 10); - } - } - printf("handle_set = %d\n", wv->handle_set); - return wv; -} - -RKTWEBVIEW_EXPORT result_t rkt_webview_navigate(rkt_webview_t *wv, const char *url) -{ - item_t item = { CONTEXT_NAVIGATE, const_cast(url) }; - return do_dispatch(wv, item); -} - -RKTWEBVIEW_EXPORT result_t rkt_webview_set_html(rkt_webview_t *wv, const char *html) -{ - item_t item = { CONTEXT_SET_HTML, const_cast(html) }; - return do_dispatch(wv, item); -} - -RKTWEBVIEW_EXPORT result_t rkt_webview_run_js(rkt_webview_t *wv, const char *js) -{ - item_t item = { CONTEXT_EVAL_JS, const_cast(js) }; - return do_dispatch(wv, item); -} - -RKTWEBVIEW_EXPORT item_t rkt_webview_call_js(rkt_webview_t *wv, const char *js) -{ - mutex_lock(wv); - wv->js_call_nr += 1; - int call_nr = wv->js_call_nr; - mutex_unlock(wv); - char buf[30]; - sprintf(buf, "%d", call_nr); - - std::string _js = std::string("{ let f = function() { ") + js + " };" + - " let call_nr = " + buf + ";" + - " try { let r = { result: f() };" + - " rkt_webview_call_js_result(call_nr, true, JSON.stringify(r)); " + - " } catch(e) {" + - " rkt_webview_call_js_result(call_nr, false, e.message); " + - " }" + - "}"; - - - item_t item = { CONTEXT_CALL_JS, strdup(_js.c_str()) }; - result_t r = do_dispatch(wv, item); - if (r == error) { - item_t item = { CONTEXT_INVALID , NULL }; - return item; - } - - auto has_result = [](rkt_webview_t *wv, int call_nr) { - mutex_lock(wv); - bool result = false; - if (wv->js_evaluated->find(call_nr) != wv->js_evaluated->end()) { - mutex_unlock(wv); - return true; - } else { - mutex_unlock(wv); - return false; - } - }; - - while(!has_result(wv, call_nr)) { - thread_sleep_ms(wv, 2); - } - - free_item(item); - - mutex_lock(wv); - JSON j = JSON::Load(wv->js_evaluated->at(call_nr), [](std::string) { }); - bool result_oke = j[1].toBool(); - std::string data = j[2].toString(); - - item_t result_item; - if (result_oke) { - result_item = { CONTEXT_CALL_JS, strdup(data.c_str()) }; - } else { - result_item = { CONTEXT_INVALID, strdup(data.c_str()) }; - } - wv->js_evaluated->erase(call_nr); - mutex_unlock(wv); - - return result_item; -} - -RKTWEBVIEW_EXPORT bool rkt_webview_valid(rkt_webview_t *handle) -{ - if (handle == NULL) { - return false; - } else { - bool valid; - mutex_lock(handle); - valid = (!handle->handle_destroyed && handle->handle_set); - mutex_unlock(handle); - return valid; - } -} - -RKTWEBVIEW_EXPORT result_t rkt_destroy_webview(rkt_webview_t *wv) -{ - if (rkt_webview_valid(wv)) { - webview_error_t e = webview_terminate(WEBVIEW_HANDLE(wv)); - result_t r = (e >= 0) ? oke : error; - if (r == oke) { - queue_destroy(&wv->to_webview); - queue_destroy(&wv->from_webview); -#ifdef USE_WIN_THREADS - WaitForSingleObject(wv->webview_thread, 2000); // Give up after 2s. - CloseHandle(wv->webview_thread); - WaitForSingleObject(wv->queue_guard_thread, 2000); // Give up after 2s. - CloseHandle(wv->queue_guard_thread); - CloseHandle(wv->mutex); -#endif -#ifdef USE_PTHREADS - pthread_join(wv->webview_thread, NULL); - pthread_join(wv->queue_guard_thread, NULL); -#endif - delete wv->js_evaluated; - free(wv); - } - return r; - } else { - return error; - } -} - -RKTWEBVIEW_EXPORT int rkt_webview_pending_events(rkt_webview_t *wv) -{ - mutex_lock(wv); - int len = queue_length(&wv->from_webview); - mutex_unlock(wv); - return len; -} - - -RKTWEBVIEW_EXPORT item_t rkt_webview_get_event(rkt_webview_t *wv) -{ - item_t i; - mutex_lock(wv); - if (queue_length(&wv->from_webview) > 0) { - dequeue(&wv->from_webview, &i); - } else { - i.context = CONTEXT_INVALID; - i.data = NULL; - } - mutex_unlock(wv); - return i; -} - - -RKTWEBVIEW_EXPORT void rkt_webview_destroy_item(item_t item) -{ - free_item(item); -} - - -RKTWEBVIEW_EXPORT result_t rkt_webview_devtools(rkt_webview_t *wv) -{ - item_t item = { CONTEXT_OPEN_DEVTOOLS, const_cast("") }; - return do_dispatch(wv, item); -} - -RKTWEBVIEW_EXPORT reason_t rkt_webview_last_reason(rkt_webview_t *wv) -{ - return wv->last_reason; -} - -RKTWEBVIEW_EXPORT void rkt_webview_register_queue_callback(rkt_webview_t *wv, int id, void (*cb)(int, item_t)) -{ - mutex_lock(wv); - wv->queue_callback = cb; - wv->queue_callback_id = id; - mutex_unlock(wv); -} - -static void handle_event(const char *id, const char *data, void *_wv) -{ - rkt_webview_t *wv = static_cast(_wv); - mutex_lock(wv); - - JSON json; - json["id"] = id; - json["data"] = data; - std::string s = json.dump(); - - item_t item; - item.context = CONTEXT_BOUND_EVENT; - item.data = const_cast(s.c_str()); - - enqueue(&wv->from_webview, item); - mutex_unlock(wv); -} - -static void handle_js_call(const char *id, const char *data, void *_wv) -{ - rkt_webview_t *wv = static_cast(_wv); - mutex_lock(wv); - std::string d(data); - JSON j = JSON::Load(d, [](std::string err) { }); - int call_nr = j[0].toInt(); - wv->js_evaluated->insert(std::pair(call_nr, std::string(data))); - mutex_unlock(wv); -} - -void dispatcher(webview_t w, void *args) -{ - rkt_webview_t *wv = reinterpret_cast(args); - item_t item; - mutex_lock(wv); - if (dequeue(&wv->to_webview, &item)) { - if (item.context == CONTEXT_SET_HTML) { - webview_error_t e = webview_set_html(w, item.data); - wv->wv_res = static_cast(e); - wv->last_result = (e >= 0) ? oke : error; - wv->last_reason = (wv->last_result == oke) ? reason_oke : reason_set_html_failed; - } else if (item.context == CONTEXT_NAVIGATE) { - webview_error_t e = webview_navigate(w, item.data); - wv->wv_res = static_cast(e); - wv->last_result = (e >= 0) ? oke : error; - wv->last_reason = (wv->last_result == oke) ? reason_oke : reason_set_navigate_failed; - } else if (item.context == CONTEXT_EVAL_JS || item.context == CONTEXT_CALL_JS) { - webview_error_t e = webview_eval(w, item.data); - wv->wv_res = static_cast(e); - wv->last_result = (e >= 0) ? oke : error; - wv->last_reason = (wv->last_result == oke) ? reason_oke : reason_eval_js_failed; - } else if (item.context == CONTEXT_OPEN_DEVTOOLS) { - bool handled = false; -#ifdef _WIN32 - void *handle = webview_get_native_handle(wv->webview_handle, WEBVIEW_NATIVE_HANDLE_KIND_BROWSER_CONTROLLER); - ICoreWebView2Controller *c = static_cast(handle); - ICoreWebView2 *cwv = nullptr; - HRESULT r = c->get_CoreWebView2(&cwv); - if (cwv != nullptr) { - r = cwv->OpenDevToolsWindow(); - if (r == S_OK) { - wv->last_result = oke; - wv->last_reason = reason_oke; - } else { - wv->last_result = error; - wv->last_reason = reason_no_devtools_on_platform; - } - } else { - wv->last_result = error; - wv->last_reason = reason_no_devtools_on_platform; - } -#endif - if (!handled) { - wv->last_result = error; - wv->last_reason = reason_no_devtools_on_platform; - } - } else { - wv->last_result = error; - wv->last_reason = reason_no_delegate_for_context; - } - } - mutex_unlock(wv); - free_item(item); -} - -result_t do_dispatch(rkt_webview_t *wv, item_t item) -{ - webview_t w = WEBVIEW_HANDLE(wv); - - mutex_lock(wv); - enqueue(&wv->to_webview, item); - wv->last_reason = reason_no_result_yet; - mutex_unlock(wv); - - webview_error_t e = webview_dispatch(w, dispatcher, wv); - - reason_t lr; - result_t r; - - if (e >= 0) { - bool go_on = true; - while(go_on) { - mutex_lock(wv); - r = wv->last_result; - lr = wv->last_reason; - mutex_unlock(wv); - if (lr != reason_no_result_yet) { - go_on = false; - } else { - thread_sleep_ms(wv, 10); - } - } - return r; - } else { - switch(e) { - case WEBVIEW_ERROR_MISSING_DEPENDENCY: lr = reason_webview_missing_dependency; - break; - case WEBVIEW_ERROR_CANCELED: lr = reason_webview_canceled; - break; - case WEBVIEW_ERROR_INVALID_STATE: lr = reason_webview_invalid_state; - break; - case WEBVIEW_ERROR_INVALID_ARGUMENT: lr = reason_webview_invalid_argument; - break; - case WEBVIEW_ERROR_UNSPECIFIED: lr = reason_webview_unspecified; - break; - default: - lr = reason_webview_dispatch_failed; - } - r = error; - } - - printf("error = %d, reason = %d\n", r, lr); - - return r; -} - -///////////////////////////////////////////////////////////////////// -// Supporting functions -///////////////////////////////////////////////////////////////////// - -void queue_init(queue_t *q) -{ - q->length = 0; - q->first = NULL; - q->last = NULL; -} - -void enqueue(queue_t *q, item_t item) -{ - queue_item_t *itm = (queue_item_t *) malloc(sizeof(queue_item_t)); - itm->item.context = item.context; - itm->item.data = strdup(item.data); - if (q->first == NULL) { - q->first = itm; - q->last = itm; - itm->prev = NULL; - itm->next = NULL; - q->length = 1; - } else { - itm->prev = q->last; - itm->next = NULL; - q->last->next = itm; - q->last = itm; - q->length += 1; - } -} - -bool dequeue(queue_t *q, item_t *item) -{ - if (q->length == 0) { - item->context = CONTEXT_INVALID; - item->data = NULL; - return false; - } else { - queue_item_t *itm = q->first; - q->first = q->first->next; - q->length -= 1; - if (q->length == 0) { - q->first = NULL; - q->last = NULL; - } - item->context = itm->item.context; - item->data = itm->item.data; - free(itm); - return true; - } -} - -int queue_length(queue_t *q) -{ - return q->length; -} - -void queue_destroy(queue_t *q) -{ - item_t i; - while(dequeue(q, &i)) { - free(i.data); - } -} - -void free_item(item_t item) -{ - free(item.data); -} - - -void mutex_lock(rkt_webview_t *wv) -{ -#ifdef USE_WIN_THREADS - WaitForSingleObject(wv->mutex, INFINITE); -#endif -#ifdef USE_PTHREADS - pthread_mutex_lock(&wv->mutex); -#endif -} - - -void mutex_unlock(rkt_webview_t *wv) -{ -#ifdef USE_WIN_THREADS - ReleaseMutex(wv->mutex); -#endif -#ifdef USE_PTHREADS - pthread_mutex_unlock(&wv->mutex); -#endif -} - -static void thread_sleep_ms(rkt_webview_t *wv, int ms) -{ -#ifdef USE_WIN_THREADS - Sleep(ms); -#endif -#ifdef USE_PTHREADS - usleep(ms * 1000); -#endif -} diff --git a/rktwebview/rktwebview.h b/rktwebview/rktwebview.h deleted file mode 100644 index 762fd0e..0000000 --- a/rktwebview/rktwebview.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef RKTWEBVIEW_H -#define RKTWEBVIEW_H - -#include "rktwebview_global.h" -#include -#include - -#ifdef _WIN32 -#include -typedef HANDLE mutex_t; -typedef HANDLE thread_t; -typedef DWORD thread_id_t; -#define USE_WIN_THREADS -#endif - -#ifdef __linux -#include -#include -typedef pthread_t thread_t; -typedef pthread_mutex_t mutex_t; -typedef int thread_id_t; -#define USE_PTHREADS -#endif - -#define CONTEXT_INVALID 0 -#define CONTEXT_BOUND_EVENT 1 -#define CONTEXT_WINDOW_RESIZE 2 -#define CONTEXT_WINDOW_MOVE 3 -#define CONTEXT_WINDOW_CAN_CLOSE 4 -#define CONTEXT_WINDOW_CLOSED 5 -#define CONTEXT_SET_HTML 6 -#define CONTEXT_NAVIGATE 7 -#define CONTEXT_EVAL_JS 8 -#define CONTEXT_OPEN_DEVTOOLS 9 -#define CONTEXT_CALL_JS 10 - -typedef enum { - oke = 0, - error = 1 -} result_t; - -typedef enum { - reason_no_result_yet = -1, - reason_oke = 0, - reason_set_html_failed = 1, - reason_set_navigate_failed = 2, - reason_eval_js_failed = 3, - reason_no_devtools_on_platform = 4, - reason_no_delegate_for_context = 5, - reason_webview_missing_dependency = 6, - reason_webview_canceled = 7, - reason_webview_invalid_state = 8, - reason_webview_invalid_argument = 9, - reason_webview_unspecified = 10, - reason_webview_dispatch_failed = 11 -} reason_t; - -typedef struct { - int context; - char *data; -} item_t; - -typedef struct _item { - item_t item; - struct _item *next; - struct _item *prev; -} queue_item_t; - -typedef struct { - queue_item_t *first; - queue_item_t *last; - int length; -} queue_t; - -typedef struct { - void *webview_handle; - mutex_t mutex; - thread_t webview_thread; - thread_id_t webview_thread_id; - queue_t to_webview; - queue_t from_webview; - int wv_res; - result_t last_result; - reason_t last_reason; - bool handle_set; - bool handle_destroyed; - void (*queue_callback)(int id, item_t data); - int queue_callback_id; - thread_t queue_guard_thread; - thread_id_t queue_guard_thread_id; - std::map *js_evaluated; - int js_call_nr; -} rkt_webview_t; - -#define WEBVIEW_HANDLE(wv) reinterpret_cast(wv->webview_handle) - -extern "C" { - -RKTWEBVIEW_EXPORT rkt_webview_t *rkt_create_webview(); -RKTWEBVIEW_EXPORT result_t rkt_destroy_webview(rkt_webview_t *wv); - -RKTWEBVIEW_EXPORT result_t rkt_close_webview(rkt_webview_t *handle); -RKTWEBVIEW_EXPORT result_t rkt_webview_navigate(rkt_webview_t *handle, const char *url); -RKTWEBVIEW_EXPORT result_t rkt_webview_set_html(rkt_webview_t *handle, const char *html); - - -RKTWEBVIEW_EXPORT result_t rkt_webview_run_js(rkt_webview_t *handle, const char *js); -RKTWEBVIEW_EXPORT item_t rkt_webview_call_js(rkt_webview_t *handle, const char *js); - -//RKTWEBVIEW_EXPORT result_t rkt_bind(rkt_webview_t *handle, const char *selector, const char *event); -//RKTWEBVIEW_EXPORT result_t rkt_unbind(rkt_webview_t *handle, const char *selector, const char *event); - -RKTWEBVIEW_EXPORT bool rkt_webview_valid(rkt_webview_t *handle); - -RKTWEBVIEW_EXPORT int rkt_webview_pending_events(rkt_webview_t *wv); -RKTWEBVIEW_EXPORT item_t rkt_webview_get_event(rkt_webview_t *wv); -RKTWEBVIEW_EXPORT void rkt_webview_register_queue_callback(rkt_webview_t *wv, int id, void(*cb)(int id, item_t item)); -RKTWEBVIEW_EXPORT void rkt_webview_destroy_item(item_t item); - -RKTWEBVIEW_EXPORT result_t rkt_webview_move(rkt_webview_t *wv, int x, int y); -RKTWEBVIEW_EXPORT result_t rkt_webview_resize(rkt_webview_t *wv, int w, int h); -RKTWEBVIEW_EXPORT result_t rkt_webview_set_title(rkt_webview_t *wv, const char *title); - -RKTWEBVIEW_EXPORT result_t rkt_webview_devtools(rkt_webview_t *wv); - -RKTWEBVIEW_EXPORT reason_t rkt_webview_last_reason(rkt_webview_t *wv); - - -} - -#endif // RKTWEBVIEW_H diff --git a/rktwebview/rktwebview_global.h b/rktwebview/rktwebview_global.h deleted file mode 100644 index 9d04e28..0000000 --- a/rktwebview/rktwebview_global.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef RKTWEBVIEW_GLOBAL_H -#define RKTWEBVIEW_GLOBAL_H - -#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) \ - || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) -#define Q_DECL_EXPORT __declspec(dllexport) -#define Q_DECL_IMPORT __declspec(dllimport) -#else -#define Q_DECL_EXPORT __attribute__((visibility("default"))) -#define Q_DECL_IMPORT __attribute__((visibility("default"))) -#endif - -#if defined(RKTWEBVIEW_LIBRARY) -#define RKTWEBVIEW_EXPORT Q_DECL_EXPORT -#else -#define RKTWEBVIEW_EXPORT Q_DECL_IMPORT -#endif - -#endif // RKTWEBVIEW_GLOBAL_H