aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/saffronwebkit.h1
-rw-r--r--meson.build3
-rw-r--r--src/sfwk-wpe.c135
-rw-r--r--tests/sfwk-minimal.c18
4 files changed, 127 insertions, 30 deletions
diff --git a/include/saffronwebkit.h b/include/saffronwebkit.h
index 1cb75f3..d15ace5 100644
--- a/include/saffronwebkit.h
+++ b/include/saffronwebkit.h
@@ -48,6 +48,7 @@ typedef struct {
typedef struct {
SaffronWidget base;
SFWKContext* context;
+ SaffronWindow* window; // just for the GL context
char* url;
int w, h;
diff --git a/meson.build b/meson.build
index 8c197d6..ea20db0 100644
--- a/meson.build
+++ b/meson.build
@@ -5,8 +5,10 @@ wpe_dep = dependency('wpe-webkit-2.0')
wpe_platform_dep = dependency('wpe-platform-2.0')
gles2_dep = dependency('glesv2')
+egl_dep = dependency('egl')
deps = [
+ egl_dep,
gles2_dep,
wpe_dep,
wpe_platform_dep,
@@ -24,6 +26,7 @@ sfwk_lib = static_library('saffronwebkit', sources, include_directories: inc, de
sfwk_dep = declare_dependency(link_with: sfwk_lib, include_directories: inc, dependencies: deps)
test_deps = [
+ egl_dep,
gles2_dep,
wpe_dep,
wpe_platform_dep,
diff --git a/src/sfwk-wpe.c b/src/sfwk-wpe.c
index d7cd128..e69d558 100644
--- a/src/sfwk-wpe.c
+++ b/src/sfwk-wpe.c
@@ -16,7 +16,11 @@
#include <SDL3/SDL_egl.h>
#include <SDL3/SDL_opengles2.h>
#include <saffronwebkit.h>
+#include <sys/types.h>
+#include <unistd.h>
+static EGLContext saved_egl_context = EGL_NO_CONTEXT;
+static EGLDisplay saved_egl_display = EGL_NO_DISPLAY;
G_DECLARE_FINAL_TYPE(WPEViewSDL3, wpe_view_sdl3, WPE, VIEW_SDL3, WPEView)
G_DECLARE_FINAL_TYPE(WPEToplevelSDL3, wpe_toplevel_sdl3, WPE, TOPLEVEL_SDL3, WPEToplevel)
@@ -26,6 +30,21 @@ G_DEFINE_FINAL_TYPE(WPEViewSDL3, wpe_view_sdl3, WPE_TYPE_VIEW)
G_DEFINE_FINAL_TYPE(WPEToplevelSDL3, wpe_toplevel_sdl3, WPE_TYPE_TOPLEVEL)
G_DEFINE_FINAL_TYPE(WPEDisplaySDL3, wpe_display_sdl3, WPE_TYPE_DISPLAY)
+static void on_load_changed(WebKitWebView *web_view, WebKitLoadEvent load_event, gpointer userdata) {
+ const char* event_str = "UNKNOWN";
+ switch(load_event) {
+ case WEBKIT_LOAD_STARTED: event_str = "STARTED"; break;
+ case WEBKIT_LOAD_REDIRECTED: event_str = "REDIRECTED"; break;
+ case WEBKIT_LOAD_COMMITTED: event_str = "COMMITTED"; break;
+ case WEBKIT_LOAD_FINISHED: event_str = "FINISHED"; break;
+ }
+ g_debug("=== WEBKIT LOAD EVENT: %s ===", event_str);
+}
+
+static void on_load_failed(WebKitWebView *web_view, WebKitLoadEvent load_event, const char *failing_uri, GError *error, gpointer userdata) {
+ g_warning("=== WEBKIT LOAD FAILED === URI: %s, Error: %s", failing_uri, error->message);
+}
+
static void
wpe_toplevel_sdl3_ensure_texture(WPEToplevelSDL3 *self, SDL_Renderer* renderer, SDL_PixelFormat format, int width, int height)
{
@@ -43,10 +62,12 @@ wpe_toplevel_sdl3_ensure_texture(WPEToplevelSDL3 *self, SDL_Renderer* renderer,
static gboolean
wpe_toplevel_sdl3_render(WPEToplevelSDL3 *self, SDL_Renderer* renderer, WPEView *view [[maybe_unused]], WPEBuffer *buffer, GError **error)
{
- // g_debug("%s: toplevel=%p, view=%p, buffer=%p is a %s", G_STRFUNC, self, view, buffer, G_OBJECT_TYPE_NAME(buffer));
+ g_debug("SFWK: wpe_toplevel_sdl3_render running");
+ g_debug("%s: toplevel=%p, view=%p, buffer=%p is a %s", G_STRFUNC, self, view, buffer, G_OBJECT_TYPE_NAME(buffer));
int buffer_width = wpe_buffer_get_width(buffer);
int buffer_height = wpe_buffer_get_height(buffer);
+ g_debug("Buffer size: %dx%d", buffer_width, buffer_height);
if (buffer) {
WPEDisplaySDL3 *display = (WPEDisplaySDL3*) wpe_toplevel_get_display((WPEToplevel*) self);
@@ -103,11 +124,11 @@ wpe_toplevel_sdl3_render(WPEToplevelSDL3 *self, SDL_Renderer* renderer, WPEView
return FALSE;
}
} else {
+ g_debug("SFWK: No buffer found, clearing to white");
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
SDL_RenderClear(renderer);
}
- SDL_RenderPresent(renderer);
return TRUE;
}
@@ -307,9 +328,6 @@ wpe_display_sdl3_finalize(GObject *object)
self->destroyImage = NULL;
self->imageTargetTexture2DOES = NULL;
- g_clear_pointer(&self->gl_context, SDL_GL_DestroyContext);
- g_clear_pointer(&self->hidden_window, SDL_DestroyWindow);
-
if (self->init_flags) {
SDL_QuitSubSystem(self->init_flags);
self->init_flags = 0;
@@ -322,28 +340,21 @@ static gboolean
wpe_display_sdl3_connect(WPEDisplay *display, GError **error)
{
WPEDisplaySDL3 *self = WPE_DISPLAY_SDL3(display);
-
+
self->egl_display = SDL_EGL_GetCurrentDisplay();
-
+
if (self->egl_display == EGL_NO_DISPLAY) {
g_set_error(error, WPE_DISPLAY_ERROR, WPE_DISPLAY_ERROR_CONNECTION_FAILED,
- "Could not get SDL-managed EGL display: %s", SDL_GetError());
+ "No active EGL display. Saffron must initialize OpenGL first.");
return FALSE;
}
-
+
self->destroyImage = (PFNEGLDESTROYIMAGEKHRPROC)
SDL_EGL_GetProcAddress("eglDestroyImageKHR");
self->imageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
SDL_EGL_GetProcAddress("glEGLImageTargetTexture2DOES");
- g_debug("%s: done, eglDestroyImageKHR=%p, glEGLImageTargetTexture2DOES=%p", G_STRFUNC,
- self->destroyImage, self->imageTargetTexture2DOES);
-
- if (!self->destroyImage) {
- g_set_error_literal(error, WPE_DISPLAY_ERROR, WPE_DISPLAY_ERROR_CONNECTION_FAILED,
- "EGL does not support eglDestroyImageKHR");
- return FALSE;
- }
-
+
+ g_debug("%s: Using existing EGL display %p", G_STRFUNC, self->egl_display);
return TRUE;
}
@@ -479,38 +490,86 @@ SFWKContext* sfwk_init() {
SFWKContext* context = g_new0(SFWKContext, 1);
context->main_context = g_main_context_new_with_flags(G_MAIN_CONTEXT_FLAGS_OWNERLESS_POLLING);
+ g_main_context_push_thread_default(context->main_context);
context->display = g_object_new(wpe_display_sdl3_get_type(), NULL);
// ensure_initialized will do the GL context later, hopefully
-
+
return context;
}
static bool sfwk_webview_ensure_initialized(SFWKWebView* webview) {
+ g_debug("SFWK: ensure initialized called");
if (webview->wpe.initialized) return true;
- EGLDisplay display = SDL_EGL_GetCurrentDisplay();
- if (display == EGL_NO_DISPLAY) {
+ g_debug("SFWK: checking for window reference");
+ if (!webview->window) {
+ g_debug("sfwk: no window reference, cannot get GL context");
+ return false;
+ }
+
+ g_debug("SFWK: checking for GL context in window");
+ SDL_GLContext ctx = webview->window->gl_context;
+ if (!ctx) {
+ g_debug("sfwk: no gl context in window?? good luck");
+ return false;
+ }
+
+ g_debug("SFWK: making GL context current...");
+ if (!SDL_GL_MakeCurrent(webview->window->sdl_window, ctx)) {
+ g_debug("SFWK: SDL_GL_MakeCurrent failed: %s", SDL_GetError());
return false;
}
+ saved_egl_context = eglGetCurrentContext();
+ saved_egl_display = eglGetCurrentDisplay();
+
+ if (saved_egl_context == EGL_NO_CONTEXT) {
+ g_debug("sfwk: No current EGL context, waiting...");
+ return false;
+ }
+
+ g_debug("sfwk: Found current EGL context %p on display %p", saved_egl_context, saved_egl_display);
+
g_autoptr(GError) error = NULL;
if (!wpe_display_connect(webview->context->display, &error)) {
+ g_warning("sfwk: Failed to connect display: %s", error->message);
return false;
}
+
+ WPEDisplaySDL3 *display_impl = WPE_DISPLAY_SDL3(webview->context->display);
+ display_impl->egl_display = saved_egl_display;
+
+ // webview->wpe.toplevel = wpe_toplevel_sdl3_new(webview->context->display);
+ // webview->wpe.wpeview = wpe_view_sdl3_new(webview->context->display);
+ // ((WPEViewSDL3*)webview->wpe.wpeview)->userdata = webview;
+ // wpe_view_set_toplevel(webview->wpe.wpeview, webview->wpe.toplevel);
+ //
+ // g_debug("Setting toplevel size to %dx%d", webview->w, webview->h);
+ // wpe_toplevel_resize(webview->wpe.toplevel, webview->w, webview->h);
+ //
+ // webview->wpe.wkwebview = g_object_new(WEBKIT_TYPE_WEB_VIEW, "display", webview->context->display, NULL);
+ // g_debug("sfwk: WebKitWebView created: %p", webview->wpe.wkwebview);
- webview->wpe.toplevel = wpe_toplevel_sdl3_new(webview->context->display);
- webview->wpe.wpeview = wpe_view_sdl3_new(webview->context->display);
+ webview->wpe.wkwebview = g_object_new(WEBKIT_TYPE_WEB_VIEW, "display", webview->context->display, NULL);
+ webview->wpe.wpeview = webkit_web_view_get_wpe_view(webview->wpe.wkwebview);
((WPEViewSDL3*)webview->wpe.wpeview)->userdata = webview;
- wpe_view_set_toplevel(webview->wpe.wpeview, webview->wpe.toplevel);
- webview->wpe.wkwebview = g_object_new(WEBKIT_TYPE_WEB_VIEW, "display", webview->context->display, NULL);
+ webview->wpe.toplevel = wpe_view_get_toplevel(webview->wpe.wpeview);
+
+ g_debug("Setting toplevel size to %dx%d", webview->w, webview->h);
+ wpe_toplevel_resize(webview->wpe.toplevel, webview->w, webview->h);
+
+ g_signal_connect(webview->wpe.wkwebview, "load-changed", G_CALLBACK(on_load_changed), webview);
+ g_signal_connect(webview->wpe.wkwebview, "load-failed", G_CALLBACK(on_load_failed), webview);
if (webview->url) {
webkit_web_view_load_uri(webview->wpe.wkwebview, webview->url);
+ g_debug("sfwk: Loading URL: %s", webview->url);
}
-
+
webview->wpe.initialized = TRUE;
+ g_debug("sfwk: WPE initialized successfully");
return true;
}
@@ -519,14 +578,31 @@ static void sfwk_webview_draw(SaffronWidget* widget, SDL_Renderer* renderer) {
webview->renderer = renderer;
if (sfwk_webview_ensure_initialized(webview)) {
+ g_debug("SFWK WebView draw: iterating context");
+ g_main_context_iteration(webview->context->main_context, FALSE);
+ static gboolean first_frame = TRUE;
+ if (first_frame) {
+ wpe_toplevel_resize(webview->wpe.toplevel, widget->w, widget->h);
+ wpe_view_resized(webview->wpe.wpeview, widget->w, widget->h);
+ first_frame = FALSE;
+ }
+
WPEToplevelSDL3* toplevel = (WPEToplevelSDL3*)webview->wpe.toplevel;
if (toplevel && toplevel->texture) {
- SDL_RenderTexture(renderer, toplevel->texture, NULL, NULL);
+ SDL_FRect dst = { widget->x, widget->y, widget->w, widget->h };
+ SDL_RenderTexture(renderer, toplevel->texture, NULL, &dst);
+
+ GLenum err = glGetError();
+ if (err != GL_NO_ERROR) {
+ g_warning("OpenGL error: 0x%x", err);
+ }
return;
}
}
-
- // if its not init just be blank, too bad so sad, notmyfault
+
+ // Draw a loading indicator
+ SDL_SetRenderDrawColor(renderer, 240, 240, 240, 255);
+ SDL_RenderFillRect(renderer, &(SDL_FRect){0, 0, widget->w, widget->h});
}
void sfwk_process_event(SFWKContext *context, SFWKWebView* webview, SDL_Event *event) {
@@ -547,6 +623,7 @@ SFWKWebView* sfwk_webview_new(SFWKContext* context, const char* url, int w, int
webview->context = context;
webview->url = strdup(url);
webview->wpe.initialized = FALSE;
+ webview->window = NULL;
// ensure initialized will init this later
diff --git a/tests/sfwk-minimal.c b/tests/sfwk-minimal.c
index 192dbe6..68dcd3c 100644
--- a/tests/sfwk-minimal.c
+++ b/tests/sfwk-minimal.c
@@ -1,3 +1,4 @@
+#include "glib.h"
#include <saffron.h>
#include <saffronwebkit.h>
@@ -10,9 +11,21 @@ bool hook_callback(SDL_Event* event) {
return true;
}
+void btn_callback(SaffronButton* btn) {
+ // do nothing
+}
+
int main() {
+ // if (!SDL_SetHint(SDL_HINT_VIDEO_DRIVER, "x11")) {
+ // printf("Warning: Could not set SDL_HINT_VIDEO_DRIVER\n");
+ // }
saffron_init();
+ const char* driver = SDL_GetCurrentVideoDriver();
+ printf("SDL is using driver: %s\n", driver); // please say x11
+
+ // make a button to prove the layout engine can move the webview around
+ SaffronButton* button = saffron_button_new(true, btn_callback, 200, 150);
SaffronWindow* window = saffron_window_new("SaffronWebKit (SFWK) Test", 1024, 768);
window->root->theme = SF_MACRO_DEFAULT_THEME;
@@ -20,8 +33,11 @@ int main() {
ctx = sfwk_init();
if (!ctx) return 1;
- SFWKWebView* webview = sfwk_webview_new(ctx, "https://arslaancodes.com", 900, 600);
+ SFWKWebView* webview = sfwk_webview_new(ctx, "https://brickmii.xyz", 900, 600);
+
+ saffron_widget_add_child(window->root, (SaffronWidget*)button);
saffron_widget_add_child(window->root, (SaffronWidget*)webview);
+ webview->window = window; // so the webview can access the GL context
saffron_hook_sdl_all_events(window, hook_callback, 999);