WebView widget is now patched.

[GB.GTK3]
* NEW: Allow other GTK+3 components to patch their widget.

[GB.GTK3.WEBVIEW]
* NEW: WebView widget is now patched.
This commit is contained in:
gambas 2020-11-09 03:31:34 +01:00
parent fa57dd5934
commit 52d7ddf745
4 changed files with 224 additions and 212 deletions

View file

@ -53,23 +53,6 @@
static GList *controls = NULL;
static GList *controls_destroyed = NULL;
#ifdef GTK3
typedef
struct {
void (*get_preferred_height)(GtkWidget *widget, gint *minimum_height, gint *natural_height);
void (*get_preferred_width_for_height)(GtkWidget *widget, gint height, gint *minimum_width, gint *natural_width);
void (*get_preferred_width)(GtkWidget *widget, gint *minimum_width, gint *natural_width);
void (*get_preferred_height_for_width)(GtkWidget *widget, gint width, gint *minimum_height, gint *natural_height);
#if GTK_CHECK_VERSION(3, 10, 0)
void (*get_preferred_height_and_baseline_for_width)(GtkWidget *widget, gint width, gint *minimum, gint *natural, gint *minimum_baseline, gint *natural_baseline);
void (*size_allocate)(GtkWidget *widget, GtkAllocation *allocation);
#endif
}
PATCH_FUNCS;
#endif
#if 0
static const char *_cursor_fdiag[] =
{
@ -1710,15 +1693,21 @@ static bool must_patch(GtkWidget *widget)
GtkWidget *parent;
gControl *parent_control;
if (GTK_IS_ENTRY(widget)) // || GTK_IS_FIXED(widget))
return true;
/*if (GTK_IS_ENTRY(widget)) // || GTK_IS_FIXED(widget))
return true;*/
if (gt_get_control(widget))
{
//fprintf(stderr, "must_patch: %p -> 1\n", widget);
return true;
}
parent = gtk_widget_get_parent(widget);
if (!parent)
{
//fprintf(stderr, "must_patch: %p -> 0\n", widget);
return false;
}
if (GTK_IS_NOTEBOOK(parent) && GTK_IS_FIXED(widget))
return true;
@ -1737,171 +1726,7 @@ static bool must_patch(GtkWidget *widget)
return (parent_control->widget == widget || (GtkWidget *)parent_control->_scroll == widget);
}
//fprintf(stderr, #type "_get_preferred_height: %d %d\n", minimum_size ? *minimum_size : -1, natural_size ? *natural_size : -1);
//fprintf(stderr, #type "_get_preferred_width: %d %d\n", minimum_size ? *minimum_size : -1, natural_size ? *natural_size : -1);
#define OLD_FUNC ((PATCH_FUNCS *)(klass->_gtk_reserved6))
#define PATCH_DECLARE_COMMON(_type, _name) \
static void _name##get_preferred_width(GtkWidget *widget, gint *minimum_size, gint *natural_size) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass*)g_type_class_peek(_type); \
(*OLD_FUNC->get_preferred_width)(widget, minimum_size, natural_size); \
if (minimum_size && must_patch(widget)) \
*minimum_size = 0; \
} \
static void _name##get_preferred_height(GtkWidget *widget, gint *minimum_size, gint *natural_size) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(_type); \
(*OLD_FUNC->get_preferred_height)(widget, minimum_size, natural_size); \
if (minimum_size && must_patch(widget)) \
*minimum_size = 0; \
} \
static void _name##get_preferred_height_for_width(GtkWidget *widget, gint width, gint *minimum_size, gint *natural_size) \
{ \
if (minimum_size && must_patch(widget)) \
{ \
*minimum_size = 0; \
*natural_size = 0; \
return; \
} \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(_type); \
(*OLD_FUNC->get_preferred_height_for_width)(widget, width, minimum_size, natural_size); \
} \
static void _name##get_preferred_width_for_height(GtkWidget *widget, gint height, gint *minimum_size, gint *natural_size) \
{ \
if (minimum_size && must_patch(widget)) \
{ \
*minimum_size = 0; \
*natural_size = 0; \
return; \
} \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(_type); \
(*OLD_FUNC->get_preferred_height_for_width)(widget, height, minimum_size, natural_size); \
}
#if GTK_CHECK_VERSION(3, 14, 0)
#define PATCH_DECLARE_SIZE(_type, _name) \
static void _name##size_allocate(GtkWidget *widget, GtkAllocation *allocation) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(_type); \
(*OLD_FUNC->size_allocate)(widget, allocation); \
gtk_widget_set_clip(widget, allocation); \
}
#elif GTK_CHECK_VERSION(3, 10, 0)
#define PATCH_DECLARE_SIZE(_type, _name) \
static void _name##size_allocate(GtkWidget *widget, GtkAllocation *allocation) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(_type); \
(*OLD_FUNC->size_allocate)(widget, allocation); \
}
#else
#define PATCH_DECLARE_SIZE(_type, _name)
#endif
#define PATCH_DECLARE(type) PATCH_DECLARE_COMMON(type, type##_) PATCH_DECLARE_SIZE(type, type##_)
#define PATCH_DECLARE_BASELINE(type) \
static void type##_get_preferred_height_and_baseline_for_width(GtkWidget *widget, gint width, gint *minimum, gint *natural, gint *minimum_baseline, gint *natural_baseline) \
{ \
if (minimum && minimum_baseline && must_patch(widget)) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(type); \
if (OLD_FUNC->get_preferred_height_and_baseline_for_width) \
(*OLD_FUNC->get_preferred_height_and_baseline_for_width)(widget, width, minimum, natural, minimum_baseline, natural_baseline); \
else \
{ \
*minimum_baseline = 0; \
*natural_baseline = 0; \
} \
*minimum = 0; \
*natural = 0; \
return; \
} \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(type); \
if (OLD_FUNC->get_preferred_height_and_baseline_for_width) \
(*OLD_FUNC->get_preferred_height_and_baseline_for_width)(widget, width, minimum, natural, minimum_baseline, natural_baseline); \
}
//fprintf(stderr, "patching [%p %s] (%p %p)\n", klass, G_OBJECT_TYPE_NAME(widget), klass->get_preferred_width, klass->get_preferred_height);
// fprintf(stderr, "PATCH_CLASS: %s\n", G_OBJECT_TYPE_NAME(widget));
#if GTK_CHECK_VERSION(3,10,0)
#define PATCH_CLASS(widget, type) \
if (G_OBJECT_TYPE(widget) == type) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)GTK_WIDGET_GET_CLASS(widget); \
if (klass->get_preferred_width != type##_get_preferred_width) \
{ \
PATCH_FUNCS *funcs = g_new0(PATCH_FUNCS, 1); \
funcs->get_preferred_width = klass->get_preferred_width; \
funcs->get_preferred_height = klass->get_preferred_height; \
funcs->get_preferred_height_for_width = klass->get_preferred_height_for_width; \
funcs->get_preferred_width_for_height = klass->get_preferred_width_for_height; \
funcs->size_allocate = klass->size_allocate; \
klass->_gtk_reserved6 = (void(*)())funcs; \
klass->get_preferred_width = type##_get_preferred_width; \
klass->get_preferred_height = type##_get_preferred_height; \
klass->get_preferred_height_for_width = type##_get_preferred_height_for_width; \
klass->get_preferred_width_for_height = type##_get_preferred_width_for_height; \
klass->size_allocate = type##_size_allocate; \
} \
}
#define PATCH_CLASS_BASELINE(widget, type) \
if (G_OBJECT_TYPE(widget) == type) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)GTK_WIDGET_GET_CLASS(widget); \
if (klass->get_preferred_width != type##_get_preferred_width) \
{ \
PATCH_FUNCS *funcs = g_new0(PATCH_FUNCS, 1); \
funcs->get_preferred_width = klass->get_preferred_width; \
funcs->get_preferred_height = klass->get_preferred_height; \
funcs->get_preferred_height_for_width = klass->get_preferred_height_for_width; \
funcs->get_preferred_width_for_height = klass->get_preferred_width_for_height; \
funcs->size_allocate = klass->size_allocate; \
funcs->get_preferred_height_and_baseline_for_width = klass->get_preferred_height_and_baseline_for_width; \
klass->_gtk_reserved6 = (void(*)())funcs; \
klass->get_preferred_width = type##_get_preferred_width; \
klass->get_preferred_height = type##_get_preferred_height; \
klass->get_preferred_height_for_width = type##_get_preferred_height_for_width; \
klass->get_preferred_width_for_height = type##_get_preferred_width_for_height; \
klass->size_allocate = type##_size_allocate; \
klass->get_preferred_height_and_baseline_for_width = type##_get_preferred_height_and_baseline_for_width; \
} \
}
#else
#define PATCH_CLASS(widget, type) \
if (G_OBJECT_TYPE(widget) == type) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)GTK_WIDGET_GET_CLASS(widget); \
if (klass->get_preferred_width != type##_get_preferred_width) \
{ \
PATCH_FUNCS *funcs = g_new0(PATCH_FUNCS, 1); \
funcs->get_preferred_width = klass->get_preferred_width; \
funcs->get_preferred_height = klass->get_preferred_height; \
funcs->get_preferred_height_for_width = klass->get_preferred_height_for_width; \
funcs->get_preferred_width_for_height = klass->get_preferred_width_for_height; \
klass->_gtk_reserved6 = (void(*)())funcs; \
klass->get_preferred_width = type##_get_preferred_width; \
klass->get_preferred_height = type##_get_preferred_height; \
klass->get_preferred_height_for_width = type##_get_preferred_height_for_width; \
klass->get_preferred_width_for_height = type##_get_preferred_width_for_height; \
} \
}
#define PATCH_CLASS_BASELINE PATCH_CLASS
#endif
#include "gb.gtk.patch.h"
PATCH_DECLARE(GTK_TYPE_WINDOW)
PATCH_DECLARE(GTK_TYPE_ENTRY)
@ -1929,30 +1754,6 @@ PATCH_DECLARE_BASELINE(GTK_TYPE_SPIN_BUTTON)
PATCH_DECLARE_BASELINE(GTK_TYPE_BUTTON)
#endif
/*int gt_get_preferred_width(GtkWidget *widget)
{
int m, n;
GtkWidgetClass *klass = (GtkWidgetClass*)g_type_class_peek(G_OBJECT_TYPE(widget));
if (klass->_gtk_reserved6)
(*(void (*)(GtkWidget *, gint *, gint *))klass->_gtk_reserved6)(widget, &m, &n);
return m;
}*/
/*int gControl::getPreferredWidth() const
{
GtkWidgetClass *klass = (GtkWidgetClass*)g_type_class_peek(G_OBJECT_TYPE(border));
int size = -1;
if (OLD_FUNC)
{
int nat;
(*OLD_FUNC->get_preferred_width)(border, &size, &nat);
fprintf(stderr, "getPreferredWidth: %d %d\n", size, nat);
}
return size;
}*/
void gt_patch_control(GtkWidget *border, GtkWidget *widget)
{
PATCH_CLASS(border, GTK_TYPE_WINDOW)
@ -1972,8 +1773,6 @@ void gt_patch_control(GtkWidget *border, GtkWidget *widget)
else PATCH_CLASS(border, GTK_TYPE_TEXT_VIEW)
else PATCH_CLASS(border, GTK_TYPE_SCROLLBAR)
else PATCH_CLASS(border, GTK_TYPE_SCALE)
else
fprintf(stderr, "gb.gtk3: warning: class %s was not patched\n", G_OBJECT_TYPE_NAME(border));
if (!widget)
return;

View file

@ -11,7 +11,7 @@ gb_gtk3_la_CPPFLAGS = @GTK3_INC@ -I$(top_srcdir)/share -DGTK3 -DGTK_DISABLE_SING
gb_gtk3_la_SOURCES = \
gtag.h ggambastag.h gshare.h \
gb.gtk.h widgets.h font-parser.h font-parser.cpp \
gb.gtk.h gb.gtk.patch.h widgets.h font-parser.h font-parser.cpp \
gtools.cpp gcolor.h \
gfont.cpp gpicture.cpp \
gdesktop.cpp gmessage.cpp \

203
gb.gtk3/src/gb.gtk.patch.h Normal file
View file

@ -0,0 +1,203 @@
/***************************************************************************
gb.gtk.patch.h
(c) Benoît Minisini <g4mba5@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#ifndef GB_GTK_PATCH_H
#define GB_GTK_PATCH_H
typedef
struct {
void (*get_preferred_height)(GtkWidget *widget, gint *minimum_height, gint *natural_height);
void (*get_preferred_width_for_height)(GtkWidget *widget, gint height, gint *minimum_width, gint *natural_width);
void (*get_preferred_width)(GtkWidget *widget, gint *minimum_width, gint *natural_width);
void (*get_preferred_height_for_width)(GtkWidget *widget, gint width, gint *minimum_height, gint *natural_height);
#if GTK_CHECK_VERSION(3, 10, 0)
void (*get_preferred_height_and_baseline_for_width)(GtkWidget *widget, gint width, gint *minimum, gint *natural, gint *minimum_baseline, gint *natural_baseline);
void (*size_allocate)(GtkWidget *widget, GtkAllocation *allocation);
#endif
}
PATCH_FUNCS;
#define PATCH_OLD_FUNC ((PATCH_FUNCS *)(klass->_gtk_reserved6))
#define PATCH_DECLARE_COMMON(_type, _name) \
static void _name##get_preferred_width(GtkWidget *widget, gint *minimum_size, gint *natural_size) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass*)g_type_class_peek(_type); \
(*PATCH_OLD_FUNC->get_preferred_width)(widget, minimum_size, natural_size); \
if (minimum_size && must_patch(widget)) \
*minimum_size = 0; \
} \
static void _name##get_preferred_height(GtkWidget *widget, gint *minimum_size, gint *natural_size) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(_type); \
(*PATCH_OLD_FUNC->get_preferred_height)(widget, minimum_size, natural_size); \
if (minimum_size && must_patch(widget)) \
*minimum_size = 0; \
} \
static void _name##get_preferred_height_for_width(GtkWidget *widget, gint width, gint *minimum_size, gint *natural_size) \
{ \
if (minimum_size && must_patch(widget)) \
{ \
*minimum_size = 0; \
*natural_size = 0; \
return; \
} \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(_type); \
(*PATCH_OLD_FUNC->get_preferred_height_for_width)(widget, width, minimum_size, natural_size); \
} \
static void _name##get_preferred_width_for_height(GtkWidget *widget, gint height, gint *minimum_size, gint *natural_size) \
{ \
if (minimum_size && must_patch(widget)) \
{ \
*minimum_size = 0; \
*natural_size = 0; \
return; \
} \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(_type); \
(*PATCH_OLD_FUNC->get_preferred_height_for_width)(widget, height, minimum_size, natural_size); \
}
#if GTK_CHECK_VERSION(3, 14, 0)
#define PATCH_DECLARE_SIZE(_type, _name) \
static void _name##size_allocate(GtkWidget *widget, GtkAllocation *allocation) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(_type); \
(*PATCH_OLD_FUNC->size_allocate)(widget, allocation); \
gtk_widget_set_clip(widget, allocation); \
}
#elif GTK_CHECK_VERSION(3, 10, 0)
#define PATCH_DECLARE_SIZE(_type, _name) \
static void _name##size_allocate(GtkWidget *widget, GtkAllocation *allocation) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(_type); \
(*PATCH_OLD_FUNC->size_allocate)(widget, allocation); \
}
#else
#define PATCH_DECLARE_SIZE(_type, _name)
#endif
#define PATCH_DECLARE(type) PATCH_DECLARE_COMMON(type, type##_) PATCH_DECLARE_SIZE(type, type##_)
#define PATCH_DECLARE_BASELINE(type) \
static void type##_get_preferred_height_and_baseline_for_width(GtkWidget *widget, gint width, gint *minimum, gint *natural, gint *minimum_baseline, gint *natural_baseline) \
{ \
if (minimum && minimum_baseline && must_patch(widget)) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(type); \
if (PATCH_OLD_FUNC->get_preferred_height_and_baseline_for_width) \
(*PATCH_OLD_FUNC->get_preferred_height_and_baseline_for_width)(widget, width, minimum, natural, minimum_baseline, natural_baseline); \
else \
{ \
*minimum_baseline = 0; \
*natural_baseline = 0; \
} \
*minimum = 0; \
*natural = 0; \
return; \
} \
GtkWidgetClass *klass = (GtkWidgetClass *)g_type_class_peek(type); \
if (PATCH_OLD_FUNC->get_preferred_height_and_baseline_for_width) \
(*PATCH_OLD_FUNC->get_preferred_height_and_baseline_for_width)(widget, width, minimum, natural, minimum_baseline, natural_baseline); \
}
//fprintf(stderr, "patching [%p %s] (%p %p)\n", klass, G_OBJECT_TYPE_NAME(widget), klass->get_preferred_width, klass->get_preferred_height);
// fprintf(stderr, "PATCH_CLASS: %s\n", G_OBJECT_TYPE_NAME(widget));
#if GTK_CHECK_VERSION(3,10,0)
#define PATCH_CLASS(widget, type) \
if (G_OBJECT_TYPE(widget) == type) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)GTK_WIDGET_GET_CLASS(widget); \
if (klass->get_preferred_width != type##_get_preferred_width) \
{ \
PATCH_FUNCS *funcs = g_new0(PATCH_FUNCS, 1); \
funcs->get_preferred_width = klass->get_preferred_width; \
funcs->get_preferred_height = klass->get_preferred_height; \
funcs->get_preferred_height_for_width = klass->get_preferred_height_for_width; \
funcs->get_preferred_width_for_height = klass->get_preferred_width_for_height; \
funcs->size_allocate = klass->size_allocate; \
klass->_gtk_reserved6 = (void(*)())funcs; \
klass->get_preferred_width = type##_get_preferred_width; \
klass->get_preferred_height = type##_get_preferred_height; \
klass->get_preferred_height_for_width = type##_get_preferred_height_for_width; \
klass->get_preferred_width_for_height = type##_get_preferred_width_for_height; \
klass->size_allocate = type##_size_allocate; \
} \
}
#define PATCH_CLASS_BASELINE(widget, type) \
if (G_OBJECT_TYPE(widget) == type) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)GTK_WIDGET_GET_CLASS(widget); \
if (klass->get_preferred_width != type##_get_preferred_width) \
{ \
PATCH_FUNCS *funcs = g_new0(PATCH_FUNCS, 1); \
funcs->get_preferred_width = klass->get_preferred_width; \
funcs->get_preferred_height = klass->get_preferred_height; \
funcs->get_preferred_height_for_width = klass->get_preferred_height_for_width; \
funcs->get_preferred_width_for_height = klass->get_preferred_width_for_height; \
funcs->size_allocate = klass->size_allocate; \
funcs->get_preferred_height_and_baseline_for_width = klass->get_preferred_height_and_baseline_for_width; \
klass->_gtk_reserved6 = (void(*)())funcs; \
klass->get_preferred_width = type##_get_preferred_width; \
klass->get_preferred_height = type##_get_preferred_height; \
klass->get_preferred_height_for_width = type##_get_preferred_height_for_width; \
klass->get_preferred_width_for_height = type##_get_preferred_width_for_height; \
klass->size_allocate = type##_size_allocate; \
klass->get_preferred_height_and_baseline_for_width = type##_get_preferred_height_and_baseline_for_width; \
} \
}
#else
#define PATCH_CLASS(widget, type) \
if (G_OBJECT_TYPE(widget) == type) \
{ \
GtkWidgetClass *klass = (GtkWidgetClass *)GTK_WIDGET_GET_CLASS(widget); \
if (klass->get_preferred_width != type##_get_preferred_width) \
{ \
PATCH_FUNCS *funcs = g_new0(PATCH_FUNCS, 1); \
funcs->get_preferred_width = klass->get_preferred_width; \
funcs->get_preferred_height = klass->get_preferred_height; \
funcs->get_preferred_height_for_width = klass->get_preferred_height_for_width; \
funcs->get_preferred_width_for_height = klass->get_preferred_width_for_height; \
klass->_gtk_reserved6 = (void(*)())funcs; \
klass->get_preferred_width = type##_get_preferred_width; \
klass->get_preferred_height = type##_get_preferred_height; \
klass->get_preferred_height_for_width = type##_get_preferred_height_for_width; \
klass->get_preferred_width_for_height = type##_get_preferred_width_for_height; \
} \
}
#define PATCH_CLASS_BASELINE PATCH_CLASS
#endif
#endif

View file

@ -75,9 +75,9 @@ static void cb_load_changed(WebKitWebView *widget, WebKitLoadEvent load_event, C
switch (load_event)
{
case WEBKIT_LOAD_FINISHED:
GB.FreeString(&THIS->link);
if (!THIS->error)
GB.Raise(THIS, EVENT_FINISH, 0);
GB.FreeString(&THIS->link);
break;
default:
break;
@ -156,6 +156,14 @@ static gboolean cb_decide_policy(WebKitWebView *widget, WebKitPolicyDecision *de
return FALSE;
}
//---------------------------------------------------------------------------
#define must_patch(_widget) (true)
#include "../gb.gtk.patch.h"
PATCH_DECLARE(WEBKIT_TYPE_WEB_VIEW)
//---------------------------------------------------------------------------
BEGIN_METHOD(WebView_new, GB_OBJECT parent)
@ -164,6 +172,8 @@ BEGIN_METHOD(WebView_new, GB_OBJECT parent)
GTK.CreateControl(THIS, VARG(parent), THIS->widget);
PATCH_CLASS(THIS->widget, WEBKIT_TYPE_WEB_VIEW)
if (!_init)
{
//webkit_settings_set_load_icons_ignoring_image_load_setting(WEBVIEW_default_settings, TRUE);