webkitgtk support

This commit is contained in:
Stefan Salewski 2021-01-06 17:21:35 +01:00
commit fc520f71eb
4 changed files with 71 additions and 8 deletions

View file

@ -1,6 +1,6 @@
= High level GTK3 (and GTK4) bindings for the Nim programming language = High level GTK4 and GTK3 bindings for the Nim programming language
(c) Stefan Salewski //(c) Stefan Salewski
//Version 0.8.4 //Version 0.8.5
:experimental: :experimental:
:imagesdir: http://ssalewski.de/tmp :imagesdir: http://ssalewski.de/tmp
:source-highlighter: pygments :source-highlighter: pygments
@ -25,8 +25,16 @@ with code inserted from files directly.
NOTE: This work is partly based on earlier works of J. Mansour and has been supported by A. Rumpf, E. Bassi and other _Nim_ and _GTK/Gnome_ developers. NOTE: This work is partly based on earlier works of J. Mansour and has been supported by A. Rumpf, E. Bassi and other _Nim_ and _GTK/Gnome_ developers.
The `combinatorics` module was kindly provided by R. Behrends. The `combinatorics` module was kindly provided by R. Behrends.
NOTE: This is version 0.8.4 of the gintro Nim GTK bindings. We do support the NOTE: This is version 0.8.5 of the gintro Nim GTK bindings.
libnice module now for Linux and Windows. And we added gtksourceview5 to Due to a serious request we have added webkitgtk support.
Unfortunately still only for GTK3, as the latest webkitgtk package 2.30.4
does not compile with stable GTK4. But we should get
webkitgtk for GTK4 in a few weeks. One question is still how to name the GTK4
version then. The official name of the version for GTK3 is webkit2, so shall
we call the version for GTK4 webkitgtk4 or webkit4? Or different?
NOTE: Since version 0.8.4 we do support the
libnice module for Linux and Windows. And we added gtksourceview5 to
support gtksourceview usage for GTK4. The module is called gtksourceview5 support gtksourceview usage for GTK4. The module is called gtksourceview5
because the underlying C library has mayor version 5 already. So you can because the underlying C library has mayor version 5 already. So you can
write your own GTK4 Nim editor now. Additional optional var out parameters write your own GTK4 Nim editor now. Additional optional var out parameters

View file

@ -0,0 +1,20 @@
# https://wiki.gnome.org/Projects/WebKitGtk/ProgrammingGuide/Tutorial
# nim c --gc:arc webkitgtk.nim
import gintro/[gtk, glib, gobject, gio, webkit2]
proc appActivate (app: Application) =
let window = newApplicationWindow(app)
window.title = "WebKitGtk"
window.defaultSize = (800, 600)
let view = newWebView()
view.loadUri("https://nim-lang.org/")
window.add(view)
window.showAll
proc main =
let app = newApplication("org.gtk.example")
connect(app, "activate", appActivate)
discard app.run
main()

View file

@ -1,6 +1,6 @@
# Package # Package
version = "0.8.4" version = "0.8.5"
author = "Stefan Salewski" author = "Stefan Salewski"
description = "High level GObject-Introspection based GTK3/GTK4 bindings" description = "High level GObject-Introspection based GTK3/GTK4 bindings"
license = "MIT" license = "MIT"

View file

@ -1,6 +1,6 @@
# High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language # High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language
# nimpretty --maxLineLen:130 gen.nim # nimpretty --maxLineLen:130 gen.nim
# v 0.8.4 2020-DEC-14 # v 0.8.5 2021-JAN-06
# (c) S. Salewski 2018 # (c) S. Salewski 2018
# usefull for finding death code: # usefull for finding death code:
@ -251,6 +251,7 @@ defaultParameters["gtk_application_new"] = "flags gio.ApplicationFlags {}"
defaultParameters["gtk_builder_new_from_string"] = "length int64 -1" defaultParameters["gtk_builder_new_from_string"] = "length int64 -1"
defaultParameters["gtk_box_new"] = "spacing int 0" defaultParameters["gtk_box_new"] = "spacing int 0"
defaultParameters["gtk_grid_attach"] = "width int 1|height int 1" defaultParameters["gtk_grid_attach"] = "width int 1|height int 1"
defaultParameters["gtk_adjustment_new"] = "pageSize cdouble 1.0"
for i in keywords: mangledNames[i] = '`' & i & '`' for i in keywords: mangledNames[i] = '`' & i & '`'
@ -1913,6 +1914,7 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
methodBuffer.cut(p) methodBuffer.cut(p)
template genBoxedFree = template genBoxedFree =
#echo gBaseInfoGetName(info)
if not callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))): if not callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))):
if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE and gTypeFundamental(gRegisteredTypeInfoGetGType(info)) == if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE and gTypeFundamental(gRegisteredTypeInfoGetGType(info)) ==
G_TYPE_BOXED and G_TYPE_BOXED and
@ -1978,6 +1980,8 @@ template genDestroyFreeUnref =
freeMe = gStructInfoFindMethod(info, "free") freeMe = gStructInfoFindMethod(info, "free")
if freeMe.isNil: if freeMe.isNil:
freeMe = gStructInfoFindMethod(info, "unref") freeMe = gStructInfoFindMethod(info, "unref")
if freeMe.isNil:
freeMe = gStructInfoFindMethod(info, "destroy") # pango, new in v0.8.5
if freeMe != nil and gCallableInfoGetNArgs(freeMe) == (if gCallableInfoIsMethod(freeMe): 0 else: 1): if freeMe != nil and gCallableInfoGetNArgs(freeMe) == (if gCallableInfoIsMethod(freeMe): 0 else: 1):
# methodBuffer.writeLine("\nwhen compileOption(\"gc\", \"arc\"):") # methodBuffer.writeLine("\nwhen compileOption(\"gc\", \"arc\"):")
methodBuffer.writeLine("\nwhen defined(gcDestructors):") methodBuffer.writeLine("\nwhen defined(gcDestructors):")
@ -1986,6 +1990,13 @@ template genDestroyFreeUnref =
methodBuffer.writeLine(" $1(self.impl)" % [$gFunctionInfoGetSymbol(freeMe)]) methodBuffer.writeLine(" $1(self.impl)" % [$gFunctionInfoGetSymbol(freeMe)])
methodBuffer.writeLine(" self.impl = nil") methodBuffer.writeLine(" self.impl = nil")
# new in v0.8.5
methodBuffer.writeLine("\nproc newWithFinalizer*(x: var " & mangleName(gBaseInfoGetName(info)) & ") =")
methodBuffer.writeLine(" when defined(gcDestructors):")
methodBuffer.writeLine(" new(x)")
methodBuffer.writeLine(" else:")
methodBuffer.writeLine(" new(x, $1)" % [$gBaseInfoGetName(freeMe)])
template writeGetTypeProc = template writeGetTypeProc =
var getTypeProc {.inject.}: string var getTypeProc {.inject.}: string
if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE: if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE:
@ -2095,6 +2106,9 @@ proc keymapKeyArrayToSeq(s: ptr KeymapKey; n: int): seq[KeymapKey] =
proc writeStruct(info: GIStructInfo) = proc writeStruct(info: GIStructInfo) =
if gBaseInfoGetName(info) in ["_ContextMenu", "_ContextMenuItem"]:
return # WebKit2WebExtension-4.0.gir bug
if gStructInfoIsGtypeStruct(info) and gBaseInfoGetName(info) != "ObjectClass": if gStructInfoIsGtypeStruct(info) and gBaseInfoGetName(info) != "ObjectClass":
return # we should not need the class and interface structs return # we should not need the class and interface structs
if gBaseInfoGetName(info).endsWith("Private"): # since v0.5.3 we do not write private structs if gBaseInfoGetName(info).endsWith("Private"): # since v0.5.3 we do not write private structs
@ -2149,6 +2163,12 @@ proc writeStruct(info: GIStructInfo) =
mseq.add(gStructInfoGetMethod(info, j)) mseq.add(gStructInfoGetMethod(info, j))
if freePos < 0 and gBaseInfoGetName(gStructInfoGetMethod(info, j)) in ["free", "unref"]: if freePos < 0 and gBaseInfoGetName(gStructInfoGetMethod(info, j)) in ["free", "unref"]:
freePos = j freePos = j
if freePos < 0:
for j in 0.cint ..< gStructInfoGetNMethods(info):
if freePos < 0 and gBaseInfoGetName(gStructInfoGetMethod(info, j)) in ["destroy"]: # add destroy for v0.8.5
freePos = j
if freePos > 0: swap(mseq[0], mseq[freePos]) if freePos > 0: swap(mseq[0], mseq[freePos])
if mangleName(gBaseInfoGetName(info)) == "List" and moduleNamespace == "glib": if mangleName(gBaseInfoGetName(info)) == "List" and moduleNamespace == "glib":
output.writeLine("\nproc g_list_free*(list: ptr glib.List) {.importc: \"g_list_free\", libprag.}") output.writeLine("\nproc g_list_free*(list: ptr glib.List) {.importc: \"g_list_free\", libprag.}")
@ -2582,6 +2602,9 @@ proc writeConst(info: GIConstantInfo) =
if h == "ATTR_INDEX_FROM_TEXT_BEGINNING": if h == "ATTR_INDEX_FROM_TEXT_BEGINNING":
return # gint in gir, but should be guint return # gint in gir, but should be guint
if gBaseInfoGetNamespace(info) == "Soup":
h.add("_STR") # too many name conflicts with enums!
if h.replace("_", "").toLowerAscii == "keych": if h.replace("_", "").toLowerAscii == "keych":
h.add(str[^5]) h.add(str[^5])
if gdkKeys.contains(h.toLowerAscii): if gdkKeys.contains(h.toLowerAscii):
@ -3000,6 +3023,11 @@ proc getPosition*(self: Event): (float, float) =
const GTK_EPI = """ const GTK_EPI = """
# allow connecting GtkText and GtkEntry to "changed" signal of GtkEditable!
proc editable*(x: Text): Editable = cast[Editable](x)
proc editable*(x: Entry): Editable = cast[Editable](x)
#proc loadFromData*(self: CssProvider; data: cstring): bool = #proc loadFromData*(self: CssProvider; data: cstring): bool =
# loadFromData(self, uint8Array(data), -1) # loadFromData(self, uint8Array(data), -1)
@ -3275,6 +3303,8 @@ proc cstringArrayToSeq*(s: ptr cstring): seq[string] =
output.writeLine("import glib\n") output.writeLine("import glib\n")
elif namespace == "Gst": elif namespace == "Gst":
discard discard
elif namespace == "WebKit2":
output.writeLine("from atk import ImplementorIface\n") # Extern interfaces support
elif namespace == "Nice": elif namespace == "Nice":
output.writeLine("import macros, nativesockets\n") output.writeLine("import macros, nativesockets\n")
output.writeLine("from strutils import `%`\n") output.writeLine("from strutils import `%`\n")
@ -3683,6 +3713,7 @@ proc launch() =
if ISGTK3: if ISGTK3:
echo "Generating bindings for GTK3..." echo "Generating bindings for GTK3..."
main("Gtk", "3.0") # the 3 new 4.0 releases in old version main("Gtk", "3.0") # the 3 new 4.0 releases in old version
#main("Pango")
when true: when true:
main("Gdk", "3.0") main("Gdk", "3.0")
main("GdkX11", "3.0") main("GdkX11", "3.0")
@ -3709,6 +3740,10 @@ proc launch() =
main("Handy") main("Handy")
main("Nice") main("Nice")
main("cairo") main("cairo")
main("WebKit2")
main("JavaScriptCore")
main("Soup")
main("WebKit2WebExtension")
else: else:
echo "First we try generating bindings for GTK4, this may fail when GTK4 is not properly installed" echo "First we try generating bindings for GTK4, this may fail when GTK4 is not properly installed"
echo "on your computer. But don't worry, you can still use GTK3" echo "on your computer. But don't worry, you can still use GTK3"
@ -3765,7 +3800,7 @@ launch()
# if not xcallerAlloc.contains(el): # if not xcallerAlloc.contains(el):
# echo el # echo el
# 3741 lines # 3741 lines Extern import writeConst gBaseInfoGetNamespace atk writeStruct attribute destroy
# gtk_icon_view_get_tooltip_context bug Candidate # gtk_icon_view_get_tooltip_context bug Candidate
# gtk_tree_view_get_cursor bug # gtk_tree_view_get_cursor bug
# #