diff --git a/README.adoc b/README.adoc index 5642e7d..d664e6d 100644 --- a/README.adoc +++ b/README.adoc @@ -1,6 +1,6 @@ = High level GTK3 (and GTK4) bindings for the Nim programming language (c) Stefan Salewski -//Version 0.7.3 +//Version 0.7.4 :experimental: :imagesdir: http://ssalewski.de/tmp :source-highlighter: pygments @@ -25,7 +25,9 @@ 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. The `combinatorics` module was kindly provided by R. Behrends. -NOTE: Starting with current version v0.7.3 we allow passing a type descriptor as first parameter to the +NOTE: With current version 0.7.4 we support latest GTK 3.98.3 which may become GTK 4 at the end of 2020. + +NOTE: Starting with version v0.7.3 we allow passing a type descriptor as first parameter to the new() procs like `newButton(MyButtonSubclass)` to support subclassing and extending Widgets in OOP style. See <> for an complete example. The init() procs which were used before for this task are now deprecated and will be removed later. This new approach generally saves @@ -2723,6 +2725,7 @@ proc main = ## Wait until error or EOS bus = gst.getBus(pipeline) msg = gst.timedPopFiltered(bus, gst.Clock_Time_None, {gst.MessageFlag.error, gst.MessageFlag.eos}) + echo msg.getType discard gst.setState(pipeline, gst.State.null) # is this necessary? main() @@ -2752,8 +2755,10 @@ button, but called after gtk4.main(). A bit strange indeed, see forum note of Mr .headerbar.nim ---- # https://github.com/GNOME/gtk/blob/mainline/tests/testheaderbar.c +# this is still based on the original testheaderbar.c, which was recently replaced by testheaderbar2.c +# and testheaderbar.c is not a very good Nim GTK4 example unfortunately -- too comlicated and strange code. # nim c headerbar.nim -import gintro/[gtk4, glib, gobject, gio] +import gintro/[gtk4, glib, gobject] const Css = """ @@ -2775,7 +2780,7 @@ const # we try to avoid use of global header variable as done in C code type MyWindow = ref object of gtk4.Window - header: gtk4.Headerbar + header: gtk4.Widget proc response(d: gtk4.FileChooserDialog; responseID: int) = gtk4.destroy(d) @@ -2787,11 +2792,11 @@ proc onBookmarkClicked(button: Button; data: MyWindow) = chooser.connect("response", response) chooser.show -proc changeSubtitle(button: Button; w: MyWindow) = - if w.header.subtitle == "": - w.header.setSubtitle("(subtle subtitle)") - else: - w.header.setSubtitle("") # can we pass nil? +#proc changeSubtitle(button: Button; w: MyWindow) = +# if w.header.subtitle == "": +# w.header.setSubtitle("(subtle subtitle)") +# else: +# w.header.setSubtitle("") # can we pass nil? proc toggleFullscreen(button: Button; window: MyWindow) = var fullscreen {.global.}: bool @@ -2807,68 +2812,85 @@ proc toIntVal(i: int): Value = discard init(result, gtype) setInt(result, i) -proc quit(b: Button) = gtk4.mainQuit() +var done = false + +proc quit_cb(b: Button) = # we can not pass a var parameter + #gtk4.mainQuit() + done = true + wakeup(defaultMainContext()) # g_main_context_wakeup (NULL); proc changeHeader(button: ToggleButton; window: MyWindow) = if button != nil and button.getActive: - window.header = cast[HeaderBar](newBox(gtk4.Orientation.horizontal, - 10)) # intended cast, see C code! - addClass(getStyleContext(window.header), "titlebar") - addClass(getStyleContext(window.header), "header-bar") - window.header.setProperty("margin", toIntVal(10)) + window.header = (newBox(gtk4.Orientation.horizontal, + 10)) + addCssClass(window.header, "titlebar") + addCssClass(window.header, "header-bar") + #window.header.setProperty("margin_start", toIntVal(10)) + #window.header.setProperty("margin_end", toIntVal(10)) + #window.header.setProperty("margin_top", toIntVal(10)) + #window.header.setProperty("margin_bottom", toIntVal(10)) + window.header.setMarginStart(10) + window.header.setMarginEnd(10) + window.header.setMarginTop(10) + window.header.setMarginBottom(10) let label = newLabel("Label") - window.header.add(label) + gtk4.Box(window.header).append(label) let levelBar = newLevelBar() levelBar.setValue(0.4) levelBar.setHexpand - window.header.add(levelBar) + gtk4.Box(window.header).append(levelBar) else: window.header = newHeaderBar() - addClass(getStyleContext(window.header), "titlebar") - window.header.setTitle("Example header") + #addClass(getStyleContext(window.header), "titlebar") + addCssClass(window.header, "titlebar") + #window.header.setTitle("Example header") var button = newButton("_Close") button.setUseUnderline - addClass(getStyleContext(button), "suggested-action") - button.connect("clicked", quit) - window.header.packEnd(button) + addCssClass(button, "suggested-action") + button.connect("clicked", quit_cb) + gtk4.HeaderBar(window.header).packEnd(button) button = newButton() let image = newImageFromIconName("bookmark-new-symbolic") button.connect("clicked", onBookmarkClicked, window) - button.add(image) - window.header.packStart(button) + button.setChild(image) + gtk4.HeaderBar(window.header).packStart(button) window.setTitlebar(window.header) proc main = gtk4.init() - var window: MyWindow - initWindow(window) - addClass(getStyleContext(window), "main") + #var window: MyWindow + let window = newWindow(MyWindow) + addCssClass(window, "main") # gtk_widget_add_css_class (window, "main"); let provider = newCssProvider() provider.loadFromData(Css) addProviderForDisplay(getDisplay(window), provider, STYLE_PROVIDER_PRIORITY_USER) changeHeader(nil, window) let box = newBox(Orientation.vertical, 0) - window.add(box) + window.setChild(box) # gtk_window_set_child (GTK_WINDOW (window), box); + #window.add(box) let content = newImageFromIconName("start-here-symbolic") content.setPixelSize(512) - box.add(content) + content.setVexpand + box.append(content) let footer = newActionBar() footer.setCenterWidget(newCheckButtonWithLabel("Middle")) let button = newToggleButtonWithLabel("Custom") button.connect("clicked", changeHeader, window) footer.packStart(button) - var button1 = newButton("Subtitle") - button1.connect("clicked", changeSubtitle, window) - footer.packEnd(button1) - button1 = newButton("Fullscreen") + #var button1 = newButton("Subtitle") + #button1.connect("clicked", changeSubtitle, window) + #footer.packEnd(button1) + var button1 = newButton("Fullscreen") footer.packEnd(button1) button1.connect("clicked", toggleFullscreen, window) - box.add(footer) + box.append(footer) window.show - gtk4.main() + #gtk4.main() + while not done: + discard iteration(defaultMainContext(), true) # g_main_context_iteration (NULL, TRUE); destroy(window) # this is special for this example, see https://discourse.gnome.org/t/tests-testgaction-c/2232/6 -main() # 118 lines +main() # 137 lines ---- NOTE: Related work: https://github.com/jdmansour/nim-smartgi diff --git a/examples/gtk3/app0.nim b/examples/gtk3/app0.nim index e583bc8..8d6f70b 100644 --- a/examples/gtk3/app0.nim +++ b/examples/gtk3/app0.nim @@ -1,6 +1,6 @@ # app0.nim -- minimal application style example # nim c app0.nim -import gintro/[gtk, glib, gobject, gio] +import gintro/[gtk, gobject, gio] proc appActivate(app: Application) = let window = newApplicationWindow(app) diff --git a/examples/gtk3/builder.nim b/examples/gtk3/builder.nim index 334cf73..2908780 100644 --- a/examples/gtk3/builder.nim +++ b/examples/gtk3/builder.nim @@ -1,7 +1,7 @@ # https://developer.gnome.org/gtk3/stable/ch01s03.html # builder.nim -- application style example using builder/glade xml file for user interface # nim c builder.nim -import gintro/[gtk, glib, gobject, gio] +import gintro/[gtk, gobject, gio] proc hello(b: Button; msg: string) = echo "Hello", msg diff --git a/examples/gtk3/celldatafunction.nim b/examples/gtk3/celldatafunction.nim index e9c7fb6..e85157c 100644 --- a/examples/gtk3/celldatafunction.nim +++ b/examples/gtk3/celldatafunction.nim @@ -1,6 +1,6 @@ # This example shows how to apply a CellDataFunc to a GtkTreeView # C example code was provided by A.Krause in chapter 8 of his book -import gintro/[gtk, gobject, glib] +import gintro/[gtk, gobject] const Color = 0 diff --git a/examples/gtk3/colorpickers.nim b/examples/gtk3/colorpickers.nim new file mode 100644 index 0000000..ae035bc --- /dev/null +++ b/examples/gtk3/colorpickers.nim @@ -0,0 +1,55 @@ +# nim c button.nim +import gintro/[gtk, glib, gobject, gio, cairo] +from math import Tau + +type + ColorPicker = ref object of Button + c: array[4, float] + +proc newColorPicker(c: array[4, float]): ColorPicker = + result = newButton(ColorPicker) + result.c = c + +proc buttonClicked (button: ColorPicker) = + #button.label = utf8Strreverse(button.label, -1) + echo "clicked" + +proc draw(b: ColorPicker; cr: cairo.Context): bool = + echo "draw" + let x = getAllocatedWidth(b).float / 2 + let y = getAllocatedHeight(b).float / 2 + cr.moveTo(x, y) + cr.newPath + cr.arc(x, y, 10, 0, math.Tau) + cr.setSource(b.c) + cr.setLineWidth(5) + cr.stroke + +proc appActivate (app: Application) = + let window = newApplicationWindow(app) + window.title = "GNOME Button" + window.defaultSize = (250, 50) + let box = newBox(Orientation.horizontal, 0) + var button = newColorPicker([1.0, 0, 0, 1])#newButton(ColorPicker)#"Click Me") + box.add(button) + button.connect("clicked", buttonClicked) + button.connectAfter("draw", draw) + button = newColorPicker([0.0, 0, 1, 1])#newButton(ColorPicker)#"Click Me") + box.add(button) + button.connect("clicked", buttonClicked) + button.connectAfter("draw", draw) + button = newColorPicker([0.0, 1, 0, 1])#newButton(ColorPicker)#"Click Me") + box.add(button) + button.connect("clicked", buttonClicked) + button.connectAfter("draw", draw) + window.add(box) + + window.showAll + +proc main = + let app = newApplication("org.gtk.example") + connect(app, "activate", appActivate) + discard app.run + +main() + diff --git a/examples/gtk3/drawingarea.nim b/examples/gtk3/drawingarea.nim index e52ec71..d1b941a 100644 --- a/examples/gtk3/drawingarea.nim +++ b/examples/gtk3/drawingarea.nim @@ -60,7 +60,7 @@ type handlerID: uint64 proc newPosAdj: PosAdj = - initAdjustment(result, 0, 0, 1, 1, 10, 1) + newAdjustment(PosAdj, 0, 0, 1, 1, 10, 1) type PDA_Data* = object @@ -104,7 +104,7 @@ proc drawingAreaDrawCb(darea: DrawingArea; cr: Context; this: PDA): bool = if this.selecting: cr.rectangle(this.lastButtonDownPosX, this.lastButtonDownPosY, this.zoomRectX1 - this.lastButtonDownPosX, this.zoomRectY1 - this.lastButtonDownPosY) - cr.setSource(0, 0, 1, 0.5) # SELECT_RECT_COL) # 0, 0, 1, 0.5 + cr.setSource(SelectRectCol) # SELECT_RECT_COL) # 0, 0, 1, 0.5 cr.fillPreserve cr.setSource(0, 0, 0) cr.setLineWidth(2) @@ -256,7 +256,7 @@ proc onAdjustmentEvent(this: PosAdj; pda: PDA) = pda.darea.queueDrawArea(0, 0, pda.darea.allocatedWidth, pda.darea.allocatedHeight) proc newPDA: PDA = - initGrid(result) + result = newGrid(PDA) let da = newDrawingArea() result.darea = da da.setHExpand diff --git a/examples/gtk3/gaction2.nim b/examples/gtk3/gaction2.nim index 115686e..f6b64b5 100644 --- a/examples/gtk3/gaction2.nim +++ b/examples/gtk3/gaction2.nim @@ -62,9 +62,9 @@ proc radio(action: SimpleAction; parameter: Variant; label: Label) = let str: string = "From Radio menu item " & getString(newState, l) label.setLabel(str) -proc bye(w: Window) = - mainQuit() - echo "Bye..." +#proc bye(w: Window) = +# mainQuit() +# echo "Bye..." proc main = gtk.init() diff --git a/examples/gtk3/gsettings.nim b/examples/gtk3/gsettings.nim index 6159ee4..eb71dbd 100644 --- a/examples/gtk3/gsettings.nim +++ b/examples/gtk3/gsettings.nim @@ -1,13 +1,13 @@ # gsettings.nim -- basic use of gsettings # nim c gsettings.nim # https://blog.gtk.org/2017/05/01/first-steps-with-gsettings/ -import gintro/[gtk, glib, gobject, gio] +import gintro/[gtk, gobject, gio] # unused -proc toggle(b: CheckButton) = - echo b.active - let s = newSettings("org.gnome.Recipes") - discard s.setBoolean("like-nim", b.active) +#proc toggle(b: CheckButton) = +# echo b.active +# let s = newSettings("org.gnome.Recipes") +# discard s.setBoolean("like-nim", b.active) proc appActivate(app: Application) = let window = newApplicationWindow(app) diff --git a/examples/gtk3/gstBasicTutorial1.nim b/examples/gtk3/gstBasicTutorial1.nim index d19f2b6..84cab47 100644 --- a/examples/gtk3/gstBasicTutorial1.nim +++ b/examples/gtk3/gstBasicTutorial1.nim @@ -15,6 +15,7 @@ proc main = ## Wait until error or EOS bus = gst.getBus(pipeline) msg = gst.timedPopFiltered(bus, gst.Clock_Time_None, {gst.MessageFlag.error, gst.MessageFlag.eos}) + echo msg.getType discard gst.setState(pipeline, gst.State.null) # is this necessary? main() diff --git a/examples/gtk3/simpledrawingarea.nim b/examples/gtk3/simpledrawingarea.nim index cf5cfd9..eedeb95 100644 --- a/examples/gtk3/simpledrawingarea.nim +++ b/examples/gtk3/simpledrawingarea.nim @@ -53,7 +53,7 @@ type handlerID: uint64 proc newPosAdj: PosAdj = - initAdjustment(result, 0, 0, 1, 1, 10, 1) + newAdjustment(PosAdj, 0, 0, 1, 1, 10, 1) type PDA_Data* = object @@ -98,7 +98,7 @@ proc drawingAreaDrawCb(darea: DrawingArea; cr: Context; this: PDA): bool = if this.selecting: cr.rectangle(this.lastButtonDownPosX, this.lastButtonDownPosY, this.zoomRectX1 - this.lastButtonDownPosX, this.zoomRectY1 - this.lastButtonDownPosY) - cr.setSource(0, 0, 1, 0.5) # SELECT_RECT_COL) # 0, 0, 1, 0.5 + cr.setSource(SelectRectCol) # SELECT_RECT_COL) # 0, 0, 1, 0.5 cr.fillPreserve cr.setSource(0, 0, 0) cr.setLineWidth(2) @@ -227,7 +227,7 @@ proc onAdjustmentEvent(this: PosAdj; pda: PDA) = pda.darea.queueDrawArea(0, 0, pda.darea.allocatedWidth, pda.darea.allocatedHeight) proc newPDA: PDA = - initGrid(result) + result = newGrid(PDA) let da = newDrawingArea() result.darea = da da.setHExpand diff --git a/examples/gtk3/sourceview_test.nim b/examples/gtk3/sourceview_test.nim index 06ac181..ff9d028 100644 --- a/examples/gtk3/sourceview_test.nim +++ b/examples/gtk3/sourceview_test.nim @@ -1,4 +1,4 @@ -import gintro/[gtk, glib, gobject, gio, gtksource] +import gintro/[gtk, gobject, gio, gtksource] proc appActivate (app: Application) = let window = newApplicationWindow(app) diff --git a/examples/gtk4/app0.nim b/examples/gtk4/app0.nim index 91bd897..111a280 100644 --- a/examples/gtk4/app0.nim +++ b/examples/gtk4/app0.nim @@ -1,6 +1,6 @@ # app0.nim -- minimal application style example # nim c app0.nim -import gintro/[gtk4, glib, gobject, gio] +import gintro/[gtk4, gobject, gio] proc appActivate(app: Application) = let window = newApplicationWindow(app) diff --git a/examples/gtk4/headerbar.nim b/examples/gtk4/headerbar.nim index 356fb8d..7d505fa 100644 --- a/examples/gtk4/headerbar.nim +++ b/examples/gtk4/headerbar.nim @@ -1,6 +1,8 @@ # https://github.com/GNOME/gtk/blob/mainline/tests/testheaderbar.c +# this is still based on the original testheaderbar.c, which was recently replaced by testheaderbar2.c +# and testheaderbar.c is not a very good Nim GTK4 example unfortunately -- too comlicated and strange code. # nim c headerbar.nim -import gintro/[gtk4, glib, gobject, gio] +import gintro/[gtk4, glib, gobject] const Css = """ @@ -22,7 +24,7 @@ const # we try to avoid use of global header variable as done in C code type MyWindow = ref object of gtk4.Window - header: gtk4.Headerbar + header: gtk4.Widget proc response(d: gtk4.FileChooserDialog; responseID: int) = gtk4.destroy(d) @@ -34,11 +36,11 @@ proc onBookmarkClicked(button: Button; data: MyWindow) = chooser.connect("response", response) chooser.show -proc changeSubtitle(button: Button; w: MyWindow) = - if w.header.subtitle == "": - w.header.setSubtitle("(subtle subtitle)") - else: - w.header.setSubtitle("") # can we pass nil? +#proc changeSubtitle(button: Button; w: MyWindow) = +# if w.header.subtitle == "": +# w.header.setSubtitle("(subtle subtitle)") +# else: +# w.header.setSubtitle("") # can we pass nil? proc toggleFullscreen(button: Button; window: MyWindow) = var fullscreen {.global.}: bool @@ -54,65 +56,82 @@ proc toIntVal(i: int): Value = discard init(result, gtype) setInt(result, i) -proc quit(b: Button) = gtk4.mainQuit() +var done = false + +proc quit_cb(b: Button) = # we can not pass a var parameter + #gtk4.mainQuit() + done = true + wakeup(defaultMainContext()) # g_main_context_wakeup (NULL); proc changeHeader(button: ToggleButton; window: MyWindow) = if button != nil and button.getActive: - window.header = cast[HeaderBar](newBox(gtk4.Orientation.horizontal, - 10)) # intended cast, see C code! - addClass(getStyleContext(window.header), "titlebar") - addClass(getStyleContext(window.header), "header-bar") - window.header.setProperty("margin", toIntVal(10)) + window.header = (newBox(gtk4.Orientation.horizontal, + 10)) + addCssClass(window.header, "titlebar") + addCssClass(window.header, "header-bar") + #window.header.setProperty("margin_start", toIntVal(10)) + #window.header.setProperty("margin_end", toIntVal(10)) + #window.header.setProperty("margin_top", toIntVal(10)) + #window.header.setProperty("margin_bottom", toIntVal(10)) + window.header.setMarginStart(10) + window.header.setMarginEnd(10) + window.header.setMarginTop(10) + window.header.setMarginBottom(10) let label = newLabel("Label") - window.header.add(label) + gtk4.Box(window.header).append(label) let levelBar = newLevelBar() levelBar.setValue(0.4) levelBar.setHexpand - window.header.add(levelBar) + gtk4.Box(window.header).append(levelBar) else: window.header = newHeaderBar() - addClass(getStyleContext(window.header), "titlebar") - window.header.setTitle("Example header") + #addClass(getStyleContext(window.header), "titlebar") + addCssClass(window.header, "titlebar") + #window.header.setTitle("Example header") var button = newButton("_Close") button.setUseUnderline - addClass(getStyleContext(button), "suggested-action") - button.connect("clicked", quit) - window.header.packEnd(button) + addCssClass(button, "suggested-action") + button.connect("clicked", quit_cb) + gtk4.HeaderBar(window.header).packEnd(button) button = newButton() let image = newImageFromIconName("bookmark-new-symbolic") button.connect("clicked", onBookmarkClicked, window) - button.add(image) - window.header.packStart(button) + button.setChild(image) + gtk4.HeaderBar(window.header).packStart(button) window.setTitlebar(window.header) proc main = gtk4.init() - var window: MyWindow - initWindow(window) - addClass(getStyleContext(window), "main") + #var window: MyWindow + let window = newWindow(MyWindow) + addCssClass(window, "main") # gtk_widget_add_css_class (window, "main"); let provider = newCssProvider() provider.loadFromData(Css) addProviderForDisplay(getDisplay(window), provider, STYLE_PROVIDER_PRIORITY_USER) changeHeader(nil, window) let box = newBox(Orientation.vertical, 0) - window.add(box) + window.setChild(box) # gtk_window_set_child (GTK_WINDOW (window), box); + #window.add(box) let content = newImageFromIconName("start-here-symbolic") content.setPixelSize(512) - box.add(content) + content.setVexpand + box.append(content) let footer = newActionBar() footer.setCenterWidget(newCheckButtonWithLabel("Middle")) let button = newToggleButtonWithLabel("Custom") button.connect("clicked", changeHeader, window) footer.packStart(button) - var button1 = newButton("Subtitle") - button1.connect("clicked", changeSubtitle, window) - footer.packEnd(button1) - button1 = newButton("Fullscreen") + #var button1 = newButton("Subtitle") + #button1.connect("clicked", changeSubtitle, window) + #footer.packEnd(button1) + var button1 = newButton("Fullscreen") footer.packEnd(button1) button1.connect("clicked", toggleFullscreen, window) - box.add(footer) + box.append(footer) window.show - gtk4.main() + #gtk4.main() + while not done: + discard iteration(defaultMainContext(), true) # g_main_context_iteration (NULL, TRUE); destroy(window) # this is special for this example, see https://discourse.gnome.org/t/tests-testgaction-c/2232/6 -main() # 118 lines +main() # 137 lines diff --git a/gintro.nimble b/gintro.nimble index 48e6926..a156fc2 100644 --- a/gintro.nimble +++ b/gintro.nimble @@ -1,6 +1,6 @@ # Package -version = "0.7.3" +version = "0.7.4" author = "Stefan Salewski" description = "High level GObject-Introspection based GTK3/GTK4 bindings" license = "MIT" diff --git a/tests/gen.nim b/tests/gen.nim index 1b47551..087f89a 100644 --- a/tests/gen.nim +++ b/tests/gen.nim @@ -1,6 +1,6 @@ # High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language # nimpretty --maxLineLen:130 gen.nim -# v 0.7.3 2020-MAR-09 +# v 0.7.4 2020-MAY-19 # (c) S. Salewski 2018 # https://wiki.gnome.org/Projects/GObjectIntrospection @@ -33,9 +33,7 @@ # This module is really ugly currently -- the first goal was to get a working gi solution -# NOTE: Currently we support subclassing only for constructor functions like gtk_button_new() -- for -# these we provide an initButton() additional to the well know newButton(). Maybe other functions -# with a result variable that we may intent to subclass should get a init() variant also... +# NOTE: Currently we support subclassing only for constructor functions like gtk_button_new() from os import `/`, paramCount import gir, gobject, glib @@ -167,6 +165,8 @@ var allSyms: HashSet[string] var droppedSyms: HashSet[string] var privStr: HashSet[string] var processedFunctions: HashSet[string] +var useTempProcessedFunctions: bool +var tempProcessedFunctions: seq[string] var knownSyms: HashSet[string] var gdkKeys: Table[string, seq[string]] @@ -210,9 +210,14 @@ fixedProcNames.add("gtk_settings_get_for_display", "getSettingsForDisplay") fixedProcNames.add("gtk_icon_theme_get_for_display", "getIconThemeForDisplay") fixedProcNames.add("gst_element_factory_find", "findElementFactory") +fixedProcNames.add("gtk_shortcut_action_parse_string", "shortcutActionParseString") +fixedProcNames.add("gtk_shortcut_trigger_parse_string", "shortcutTriggerParseString") +fixedProcNames.add("g_main_context_default", "defaultMainContext") + defaultParameters.add("gtk_window_new", "`type` WindowType WindowType.toplevel") defaultParameters.add("gtk_application_new", "flags gio.ApplicationFlags {}") defaultParameters.add("gtk_builder_new_from_string", "length int64 -1") +defaultParameters.add("gtk_box_new", "spacing int32 0") for i in keywords: mangledNames.add(i, '`' & i & '`') @@ -340,10 +345,11 @@ graphene.Euler #cairo.Matrix cairo.Rectangle cairo.RectangleInt +gsk.RoundedRect """.split.toHashSet type - UndefEx = object of Exception + UndefEx = object of CatchableError proc mangleType(s: cstring): string = result = mangleName(s) @@ -534,7 +540,10 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil): ( self = "(self: " & manglename(gBaseInfoGetName(binfo)) & "; " arglist = "(self" else: - arglist = "(cast[ptr " & manglename(gBaseInfoGetName(binfo)) & "00](" & "self.impl)" + ## only for very few procs the instance variable itself can be NULL in GTK. We assume non NULL and may provide an overload. + arglist = "(cast[ptr " & manglename(gBaseInfoGetName(binfo)) & "00](" & + "self.impl)" # https://discourse.gnome.org/t/g-arg-info-may-be-null-for-the-instace-itself/3284/7 + # arglist = "(if self.isNil: nil else: cast[ptr " & manglename(gBaseInfoGetName(binfo)) & "00](" & "self.impl)" if genProxy: var h = manglename(gBaseInfoGetName(binfo)) let provider = interfaceProvider.getOrDefault(h, @[]) @@ -759,6 +768,18 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) = if boxedFreeMeName == "gBoxedFreeGVariantType": # this does not work assert false + if gBaseInfoGetType(info) == GIInfoType.Object: + assert(gObjectInfoGetFundamental(info) == GTrue) + var parent = info + while true: + let h = g_object_info_get_parent(parent) + if h == nil: + break + parent = h + boxedFreeMeName = "" + freeMeName = "generic_" & $g_object_info_get_unref_function(parent) + assert(freeMeName != "") + # assert(info != nil) # why can it be nil? assert(isCallableInfo(mInfo)) assert(isFunctionInfo(mInfo)) @@ -819,7 +840,8 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) = try: (plist, arglist, replist, arrLex) = genPars(mInfo, false, info) processedFunctions.incl(sym) - if sym.startsWith("g_param_spec_", "g_type_interface_", "g_object_interface_"): return + if not sym.startsWith("g_param_spec_uref"): + if sym.startsWith("g_param_spec_", "g_type_interface_", "g_object_interface_"): return if sym in ["gtk_widget_class_find_style_property", "gtk_container_class_find_child_property", "gtk_cell_area_class_find_cell_property"]: return var asym = manglename(gBaseInfoGetName(mInfo)) @@ -878,7 +900,8 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) = let tag = gTypeInfoGetTag(ret2) if tag == GITypeTag.INTERFACE: let iface = gTypeInfoGetInterface(ret2) - if gBaseInfoGetType(iface) == GIInfoType.Object and gBaseInfoGetName(iface) != "ParamSpec": + #if gBaseInfoGetType(iface) == GIInfoType.Object and gBaseInfoGetName(iface) != "ParamSpec": + if gBaseInfoGetType(iface) == GIInfoType.Object and gObjectInfoGetFundamental(iface) == GFalse: isGObject = true (plist, arglist, replist, arrLex, blex) = genPars(mInfo, true, info) var sss = "" @@ -954,6 +977,7 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) = methodBuffer.writeLine(" fnew(result, $1)" % boxedFreeMeName) elif freeMeName == "": assert false + echo "????????", sym methodBuffer.writeLine(" new(result)") else: methodBuffer.writeLine(" fnew(result, $1)" % freeMeName) @@ -999,16 +1023,17 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) = assert tag == GITypeTag.INTERFACE var iface = gTypeInfoGetInterface(ret2) if gBaseInfoGetType(iface) == GIInfoType.INTERFACE: + #methodBuffer.writeLine("#GIInfoType.INTERFACE") gobjectTemp() #iface = gInterfaceInfoGetIfaceStruct(iface) #methodBuffer.writeLine(" fnew(result, $1genericGObjectUnref) # Interface" % [mprefix]) #methodBuffer.writeLine(" result.impl = " & sym & arglist) - elif gBaseInfoGetType(iface) == GIInfoType.OBJECT: # rare, ParamSpec in gobject.nim + elif false: #gBaseInfoGetType(iface) == GIInfoType.OBJECT: # rare, ParamSpec in gobject.nim #echo "XXXXXXXXXXXXXXXXX what shall we do? for ", sym methodBuffer.writeLine(" fnew(result, $1genericGObjectUnref) # Object" % [mprefix]) methodBuffer.writeLine(" result.impl = " & sym & arglist) else: - assert(gBaseInfoGetType(iface) in {GIInfoType.STRUCT, GIInfoType.UNION}) + assert(gBaseInfoGetType(iface) in {GIInfoType.STRUCT, GIInfoType.UNION, GIInfoType.OBJECT}) var freeMeName: string var freeMe: GIFunctionInfo var boxedFreeMeName: string @@ -1017,7 +1042,7 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) = methodBuffer.writeLine(" fnew(result, $1)" % boxedFreeMeName) elif freeMeName == "": # assert false # TODO we have to fix this case manually - #echo "xCaution: No free/unref found for ", ' ', gBaseInfoGetName(iface), " (", sym, ')' + # echo "xCaution: No free/unref found for ", ' ', gBaseInfoGetName(iface), " (", sym, ')' # check this from time to time! methodBuffer.writeLine(" new(result)") else: methodBuffer.writeLine(" fnew(result, $1)" % freeMeName) @@ -1149,18 +1174,39 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) = methodBuffer.writeLine("\nproc `defaultSize=`*(self: Window; dim: tuple[width: int; height: int]) =") methodBuffer.writeLine(" gtk_window_set_default_size(cast[ptr Window00](self.impl), int32(dim[0]), int32(dim[1]))") if sym == "g_object_unref": - methodBuffer.writeLine("\nproc genericGObjectUnref*[T](self: ref T) =") + # methodBuffer.writeLine("\nproc genericGObjectUnref*[T](self: ref T) =") # we do not really need generics here + methodBuffer.writeLine("\nproc genericGObjectUnref*(self: Object) =") methodBuffer.writeLine(" if not self.ignoreFinalizer:") methodBuffer.writeLine(" g_object_unref(cast[ptr Object00](self.impl))") + #if gBaseInfoGetType(info) == GIInfoType.Object and isgobject + if info != nil and gBaseInfoGetType(info) == GIInfoType.Object and gObjectInfoGetFundamental(info) == GTrue and sym.endsWith("unref"): + when false: # we can not use baseName, we have to use generics. + var parent = info + while true: + let h = g_object_info_get_parent(parent) + if h == nil: + break + parent = h + let baseName = $gBaseInfoGetName(parent) + methodBuffer.writeLine("\nproc generic_$1*[T](self: ref T) =" % [sym]) + # methodBuffer.writeLine("\nproc generic_$1*(self: $2) =" % [sym, baseName]) # we can not avoid generics here + methodBuffer.writeLine(" if not self.ignoreFinalizer:") + # methodBuffer.writeLine(" $1(cast[ptr Object00](self.impl))" % [sym]) # we do not need that cast! + methodBuffer.writeLine(" $1(self.impl)" % [sym]) + + if useTempProcessedFunctions: + tempProcessedFunctions.add(sym) except UndefEx: + processedFunctions.excl(sym) delayedMethods.add((info, minfo)) methodBuffer.cut(p) template genBoxedFree = if not callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))): - if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE and gTypeFundamental(gRegisteredTypeInfoGetGType(info)) == G_TYPE_BOXED and + if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE and gTypeFundamental(gRegisteredTypeInfoGetGType(info)) == + G_TYPE_BOXED and gBaseInfoGetName(info) != "VariantType": # we have no g_variant_type_get_gtype # For example, GVariant has a GType but is not a boxed type #assert(g_type_fundamental(g_registered_type_info_get_g_type(info)) == G_TYPE_BOXED) @@ -1195,12 +1241,7 @@ template genBoxedFree = else: #if gStructInfoIsGtypeStruct(info) and gBaseInfoGetName(info) != "ObjectClass": assert gBaseInfoGetType(info) == GIInfoType.STRUCT - #echo "aaa", info.isNil - #echo "bbb", gStructInfoIsGtypeStruct(info) - #echo "ccc", gStructInfoGetNMethods(info) - #echo gBaseInfoGetName(info) freeMe = gStructInfoFindMethod(info, "free") - #echo "xxxxxxxx" if freeMe.isNil: freeMe = gStructInfoFindMethod(info, "unref") @@ -1208,7 +1249,6 @@ template genDestroyFreeUnref = if not callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))): if gRegisteredTypeInfoGetGType(info) == G_TYPE_NONE or gTypeFundamental(gRegisteredTypeInfoGetGType(info)) != G_TYPE_BOXED or gBaseInfoGetName(info) == "VariantType": # we have no g_variant_type_get_gtype - #if true: if gBaseInfoGetType(info) == GIInfoType.UNION or gBaseInfoGetType(info) == GIInfoType.STRUCT and gBaseInfoGetName(info) != "ObjectClass" and gBaseInfoGetName(info) != "TypeFind": var freeMe: GIFunctionInfo @@ -1217,7 +1257,6 @@ template genDestroyFreeUnref = if freeMe.isNil: freeMe = gUnionInfoFindMethod(info, "unref") else: - #if gStructInfoIsGtypeStruct(info) and gBaseInfoGetName(info) != "ObjectClass": assert gBaseInfoGetType(info) == GIInfoType.STRUCT freeMe = gStructInfoFindMethod(info, "free") if freeMe.isNil: @@ -1350,7 +1389,8 @@ proc writeStruct(info: GIStructInfo) = output.writeLine(" ", mangleName(gBaseInfoGetName(info)) & "00" & EM & " {.pure.} = object") if WriteFields or callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName( info))) or - mangleName(gBaseInfoGetName(info)) == "TargetEntry": + mangleName(gBaseInfoGetName(info)) == "TargetEntry" or + ["gst.Message", "gst.MiniObject"].contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))): for j in 0.cint ..< info.gStructInfoGetNFields(): let field = info.gStructInfoGetField(j) let name = manglename(gBaseInfoGetName(field)) & EM @@ -1506,7 +1546,7 @@ proc writeModifierType(info: GIEnumInfo) = output.writeLine(i) output.writeLine("\n ", we & EM, " {.size: sizeof(cint).} = set[$1Flag]" % [tname]) if we == "ModifierType": - output.writeLine("\nconst ModifierMask* = {ModifierFlag.shift .. ModifierFlag.button5, ModifierFlag.super .. ModifierFlag.meta, ModifierFlag.release}") + output.writeLine("\nconst ModifierMask* = {ModifierFlag.shift .. ModifierFlag.button5, ModifierFlag.super .. ModifierFlag.meta}") #, ModifierFlag.release}") elif we == "EventMask": output.writeLine("\nconst AllEventsMask* = {EventFlag.exposure .. EventFlag.smoothScroll}") for j in 0.cint ..< gEnumInfoGetNMethods(info): @@ -1638,7 +1678,7 @@ proc writeObj(info: GIObjectInfo) = assert not callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))) when WriteFields: if mangleName(gBaseInfoGetName(info)) != "InitiallyUnowned": - for j in 0.cint ..< n: + for j in 0.cint ..< info.gObjectInfoGetNFields(): let field = info.gObjectInfoGetField(j) var name = mangleName(gBaseInfoGetName(field)) if privStr.contains(name) and cnt > 0: @@ -1674,6 +1714,7 @@ proc writeObj(info: GIObjectInfo) = if getTypeProc notin ["intern", "g_gstring_get_type"]: output.write("\nproc " & getTypeProc & "*(): GType ") output.writeLine("{.importc, " & libprag & ".}") + let numsig = info.gObjectInfoGetNSignals #if numsig > 0: signalbuffer.writeLine("") for j in 0.cint ..< numsig: @@ -1685,9 +1726,23 @@ proc writeObj(info: GIObjectInfo) = var h = genPars(signalInfo, false)[0][1..^1] let zzzu = gCallableInfoGetReturnType(signalinfo) writeSignal() + #for j in 0.cint ..< gObjectInfoGetNMethods(info): + # let mInfo = gObjectInfoGetMethod(info, j) + # writeMethod(info, minfo) + + var mseq: seq[GIFunctionInfo] + var freePos = -1 for j in 0.cint ..< gObjectInfoGetNMethods(info): - let mInfo = gObjectInfoGetMethod(info, j) + mseq.add(gObjectInfoGetMethod(info, j)) + if freePos < 0 and gBaseInfoGetName(gObjectInfoGetMethod(info, j)) in ["free", "unref"]: + #assert false executed for gtk3 + freePos = j + if freePos > 0: swap(mseq[0], mseq[freePos]) + for i, mInfo in mseq: writeMethod(info, minfo) + #if i == 0: + # genDestroyFreeUnref() + if class != nil and not allSyms.contains(mangleName(gBaseInfoGetName(class))): assert false classList.add(class) @@ -1704,6 +1759,45 @@ proc writeObj(info: GIObjectInfo) = output.writeLine(" g_object_remove_toggle_ref(self.impl, toggleNotify, addr(self))") output.writeLine(" self.impl = nil") + if gBaseInfoGetName(info) == "ParamSpec" and moduleNamespace == "gobject": + ## for ParamSpec no unref proc is provided by gobject-introspection, and it asks for uref! + output.writeLine("\nproc g_param_spec_unref(self: ptr ParamSpec00) {.") + output.writeLine(" importc, libprag.}") + + output.writeLine("\nproc g_param_spec_uref(self: ptr ParamSpec00) {.") + output.writeLine(" importc: \"g_param_spec_unref\", libprag.}") + + output.writeLine("\nproc unref*(self: ParamSpec) =") + output.writeLine(" g_param_spec_unref(cast[ptr ParamSpec00](self.impl))") + + output.writeLine("\nproc uref*(self: ParamSpec) =") + output.writeLine(" g_param_spec_unref(cast[ptr ParamSpec00](self.impl))") + + output.writeLine("\nproc generic_g_param_spec_uref*(self: ParamSpec) =") + output.writeLine(" g_param_spec_unref(cast[ptr ParamSpec00](self.impl))") + + if gBaseInfoGetType(info) == GIInfoType.Object and gObjectInfoGetFundamental(info) == GTrue: + ## generate the destroy() for the non gobject objects + assert(gObjectInfoGetFundamental(info) == GTrue) + var parent = info + while true: + let h = g_object_info_get_parent(parent) + if h == nil: + break + parent = h + let freeMeName = $g_object_info_get_unref_function(parent) + if freeMeName != "": + output.writeLine("\nwhen defined(gcDestructors):") + let n = mangleName(gBaseInfoGetName(info)) + output.writeLine(" proc destroy_" & freeMeName & "(self: ptr " & n & "00) {.importc: \"" & freeMeName & "\", libprag.}\n") + output.writeLine(" proc `=destroy`*(self: var typeof(" & mangleName(gBaseInfoGetName(info)) & "()[])) =") + output.writeLine(" if not self.ignoreFinalizer and self.impl != nil:") + if n in ["ParamArray", "ParamFraction"]: + output.writeLine(" destroy_$#(cast[ptr $#00](self.impl))" % [freeMeName, n]) + else: + output.writeLine(" destroy_$1(self.impl)" % [freeMeName]) + output.writeLine(" self.impl = nil") + proc extractFromUnion(tag: GITypeTag; arg: GIArgumentObj): string = result = case tag: @@ -1738,6 +1832,8 @@ proc writeConst(info: GIConstantInfo) = var str = extractFromUnion(tag, arg) if str == """"\"""": str = """"\\"""" var h = $gBaseInfoGetName(info) + if h == "MODIFIER_MASK": + return if h.replace("_", "").toLowerAscii == "keych": h.add(str[^5]) if gdkKeys.contains(h.toLowerAscii): @@ -1833,6 +1929,45 @@ proc getView*(builder: Builder; name: string): View = const GDK3_EPI = """ +proc getButton*(self: SomeEvent): int = + var button: uint32 + if not toBool(gdk_event_get_button(cast[ptr Event00](self.impl), button)): + raise newException(Defect, "Event don't has a button field.") + return int(button) + +proc getClickCount*(self: SomeEvent): int = + var clickCount_00: uint32 + if not toBool(gdk_event_get_click_count(cast[ptr Event00](self.impl), clickCount_00)): + raise newException(Defect, "Event does not support getClickCount().") + return int(clickCount_00) + +proc getCoords*(self: SomeEvent): (cdouble, cdouble) = + if not toBool(gdk_event_get_coords(cast[ptr Event00](self.impl), result[0], result[1])): + raise newException(Defect, "This event don't has a coordinate field.") + +proc getKeyval*(self: SomeEvent): int = + var keyval_00: uint32 + if not toBool(gdk_event_get_keyval(cast[ptr Event00](self.impl), keyval_00)): + raise newException(Defect, "This event don't has a keyval field.") + return int(keyval_00) + +# not available in GTK4 +proc getRootCoords*(self: SomeEvent): (cdouble, cdouble) = + if not toBool(gdk_event_get_root_coords(cast[ptr Event00](self.impl), result[0], result[1])): + raise newException(Defect, "This event don't has a rootCoordinate field.") + +proc getScrollDeltas*(self: SomeEvent): (cdouble, cdouble) = + if not toBool(gdk_event_get_scroll_deltas(cast[ptr Event00](self.impl), result[0], result[1])): + raise newException(Defect, "This event don't has a scrollDeltas field.") + +proc getScrollDirection*(self: SomeEvent): ScrollDirection = + if not toBool(gdk_event_get_scroll_direction(cast[ptr Event00](self.impl), result)): + raise newException(Defect, "Event don't has a scrollDirection field.") + +proc getState*(self: SomeEvent): ModifierType = + if not toBool(gdk_event_get_state(cast[ptr Event00](self.impl), result)): + raise newException(Defect, "Event don't has a state field.") + proc gdk_window_invalidate_nilrect(self: ptr Window00; rect: ptr Rectangle; invalidateChildren: gboolean) {. importc: "gdk_window_invalidate_rect", libprag.} @@ -1868,45 +2003,6 @@ proc getAxis*(self: SomeEvent; axisUse: AxisUse): cdouble = if not toBool(gdk_event_get_axis(cast[ptr Event00](self.impl), axisUse, result)): raise newException(Defect, "Event does not support getAxis().") -proc getButton*(self: SomeEvent): int = - var button: uint32 - if not toBool(gdk_event_get_button(cast[ptr Event00](self.impl), button)): - raise newException(Defect, "Event don't has a button field.") - return int(button) - -proc getClickCount*(self: SomeEvent): int = - var clickCount_00: uint32 - if not toBool(gdk_event_get_click_count(cast[ptr Event00](self.impl), clickCount_00)): - raise newException(Defect, "Event does not support getClickCount().") - return int(clickCount_00) - -proc getCoords*(self: SomeEvent): (cdouble, cdouble) = - if not toBool(gdk_event_get_coords(cast[ptr Event00](self.impl), result[0], result[1])): - raise newException(Defect, "This event don't has a coordinate field.") - -proc getKeyval*(self: SomeEvent): int = - var keyval_00: uint32 - if not toBool(gdk_event_get_keyval(cast[ptr Event00](self.impl), keyval_00)): - raise newException(Defect, "This event don't has a keyval field.") - return int(keyval_00) - -# not available in GTK4 -#proc getRootCoords*(self: SomeEvent): (cdouble, cdouble) = -# if not toBool(gdk_event_get_root_coords(cast[ptr Event00](self.impl), result[0], result[1])): -# raise newException(Defect, "This event don't has a rootCoordinate field.") - -proc getScrollDeltas*(self: SomeEvent): (cdouble, cdouble) = - if not toBool(gdk_event_get_scroll_deltas(cast[ptr Event00](self.impl), result[0], result[1])): - raise newException(Defect, "This event don't has a scrollDeltas field.") - -proc getScrollDirection*(self: SomeEvent): ScrollDirection = - if not toBool(gdk_event_get_scroll_direction(cast[ptr Event00](self.impl), result)): - raise newException(Defect, "Event don't has a scrollDirection field.") - -proc getState*(self: SomeEvent): ModifierType = - if not toBool(gdk_event_get_state(cast[ptr Event00](self.impl), result)): - raise newException(Defect, "Event don't has a state field.") - """ const GIO_EPI = """ @@ -1916,13 +2012,17 @@ proc run*(self: GApplication): int = """ +const GTK3_EPI = """ + +proc mainQuit*(w: Window) = mainQuit() + +""" + const GTK_EPI = """ #proc loadFromData*(self: CssProvider; data: cstring): bool = # loadFromData(self, uint8Array(data), -1) -proc mainQuit*(w: Window) = mainQuit() - proc gtk_file_chooser_dialog_new*(title: cstring; parent: ptr Window00; action: FileChooserAction; firstButtonText: cstring = nil): ptr FileChooserDialog00 {.varargs, importc: "gtk_file_chooser_dialog_new", libprag.} @@ -1993,8 +2093,7 @@ proc main(namespace: string; version: cstring = nil) = #g_irepository_prepend_search_path("/opt/gtk/lib64/girepository-1.0") # ISGTK3 = not (((namespace == "Gtk") or (namespace == "Gdk") or (namespace == "GdkX11")) and version == "4.0") # ISGTK3 = parmCount() == 0 # we have to launch the generator two times, as typelibs can not be unloaded! - let typelib = gi.gIrepositoryRequire(namespace, version, cast[ - GIRepositoryLoadFlags](0), error) + let typelib = gi.gIrepositoryRequire(namespace, version, cast[GIRepositoryLoadFlags](0), error) #let typelib = gIrepositoryRequirePrivate(nil, namespace, "/usr/lib/girepository-1.0", version, cast[GIRepositoryLoadFlags](0), error) if typelib.isNil: echo "Failed to load ", namespace @@ -2011,8 +2110,7 @@ proc main(namespace: string; version: cstring = nil) = if j == 0: importedModules = "import " output.writeLine("# ", dep[j]) - importedModules.add(fixedModName(($dep[j]).split('-', - 2)[0].toLowerAscii) & ", ") + importedModules.add(fixedModName(($dep[j]).split('-', 2)[0].toLowerAscii) & ", ") importedModules.removeSuffix(", ") strfreev(dep) let idep: cstringArray = gi.gIrepositoryGetImmediateDependencies(namespace) @@ -2028,8 +2126,8 @@ proc main(namespace: string; version: cstring = nil) = output.writeLine("{.warning[UnusedImport]: off.}") # gmodule, xlib, cairo output.writeLine(importedModules) var Lib = if libs.isNil: "" else: ($libs).split(',', 2)[0] - if namespace == "PangoCairo" and Lib.startsWith( - "libpango-"): Lib = Lib.replace("libpango-", "libpangocairo-") # GI bug? + if namespace == "PangoCairo" and Lib.startsWith("libpango-"): + Lib = Lib.replace("libpango-", "libpangocairo-") # GI bug? output.writeLine("const Lib = \"$1\"" % Lib) output.writeLine("{.pragma: libprag, cdecl, dynlib: Lib.}") if namespace == "GObject": # declare array types to make it compile -- procs using these will need special care! @@ -2084,8 +2182,7 @@ proc main(namespace: string; version: cstring = nil) = #gtype.h-#else /* for historic reasons, C++ links against gulong GTypes */ #gtype.h-typedef gulong GType; #gtype.h-#endif - output.writeLine( - "when GLIB_SIZEOF_SIZE_T != GLIB_SIZEOF_LONG or not defined(cpp):") + output.writeLine("when GLIB_SIZEOF_SIZE_T != GLIB_SIZEOF_LONG or not defined(cpp):") output.writeLine(" type\n GType* = Gsize") output.writeLine("else:") output.writeLine(" type\n GType* = culong") @@ -2139,15 +2236,13 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] = inc(i) """) - output.writeLine( - "proc cogfree*(mem: pointer) {.importc: \"g_free\", libprag.}") - output.writeLine( - "proc g_strfreev*(strArray: cstringArray) {.importc: \"g_strfreev\", libprag.}") + output.writeLine("proc cogfree*(mem: pointer) {.importc: \"g_free\", libprag.}") + output.writeLine("proc g_strfreev*(strArray: cstringArray) {.importc: \"g_strfreev\", libprag.}") output.writeLine("proc toBool*(g: gboolean): bool = g.int != 0") - output.writeLine( - "proc safeStringToCString*(s: cstring): cstring = (if s.len == 0: nil else: s)") + output.writeLine("proc safeStringToCString*(s: cstring): cstring = (if s.len == 0: nil else: s)") output.writeLine(PRO) elif namespace == "Gdk": + output.writeLine("type\n ContentProvider00Array* = pointer") output.writeLine("type\n Atom00Array* = pointer") output.writeLine("type\n KeymapKeyArray* = pointer") output.writeLine("type\n VisualTypeArray* = pointer") # enums! @@ -2169,6 +2264,7 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] = output.writeLine("type\n StockItemArray* = pointer") output.writeLine("type\n PageRangeArray* = pointer") output.writeLine("type\n PadActionEntry00Array* = pointer") + output.writeLine("type\n Widget00Array* = pointer") output.writeLine("type\n Array* = pointer") elif namespace == "Atk": output.writeLine("type\n StateTypeArray* = pointer") # enums! @@ -2234,16 +2330,14 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] = var n = gi.gIrepositoryGetNInfos(namespace) var s: seq[GIBaseInfo] for i in 0.cint ..< n: - if not droppedSyms.contains(mangleName(gBaseInfoGetName( - gi.gIrepositoryGetInfo(namespace, i)))): + if not droppedSyms.contains(mangleName(gBaseInfoGetName(gi.gIrepositoryGetInfo(namespace, i)))): s.add(gi.gIrepositoryGetInfo(namespace, i)) for i in s: if gBaseInfoGetType(i) in {GIInfoType.OBJECT, GIInfoType.INTERFACE, GIInfoType.STRUCT, GIInfoType.UNION} or isEnumInfo(i) or isCallbackInfo(i): allSyms.incl(mangleName(gBaseInfoGetName(i))) for i in 0 .. s.high: - if namespace == "GLib" and gBaseInfoGetType(s[ - i]) == GIInfoType.STRUCT and gBaseInfoGetName(s[i]) == "Error": + if namespace == "GLib" and gBaseInfoGetType(s[i]) == GIInfoType.STRUCT and gBaseInfoGetName(s[i]) == "Error": let h = s[i] s.delete(i, i) s.insert([h]) @@ -2255,16 +2349,13 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] = var interf: seq[string] let name = $gBaseInfoGetName(info) for i in 0.cint ..< ninterfaces: - var ns = ($gBaseInfoGetNamespace(info.gObjectInfoGetInterface( - i))).toLowerAscii + var ns = ($gBaseInfoGetNamespace(info.gObjectInfoGetInterface(i))).toLowerAscii if ns != moduleNamespace: var iname = $gBaseInfoGetName(info.gObjectInfoGetInterface(i)) var fname = iname; fname.unCap iname = fixedModName(ns) & "." & iname - let tname = fixedModName(moduleNamespace) & "." & - $gBaseInfoGetName(info) - externInterfaces.add("proc " & fname & "*(x: " & tname & "): " & - iname & " = cast[" & iname & "](x)") + let tname = fixedModName(moduleNamespace) & "." & $gBaseInfoGetName(info) + externInterfaces.add("proc " & fname & "*(x: " & tname & "): " & iname & " = cast[" & iname & "](x)") interf.add($gBaseInfoGetName(info.gObjectInfoGetInterface(i))) let builderinter = info.gObjectInfoGetInterface(i) if gBaseInfoGetName(builderinter) == "Buildable": @@ -2307,15 +2398,11 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] = var more_runs = 50 while s.len > 0 or more_runs > 0: if s.len == 0: dec(more_runs) - if namespace == "GObject" and not knownSyms.contains( - "g_signal_connect_data"): - if knownSyms.contains("ClosureNotify") and knownSyms.contains( - "ConnectFlags"): + if namespace == "GObject" and not knownSyms.contains("g_signal_connect_data"): + if knownSyms.contains("ClosureNotify") and knownSyms.contains("ConnectFlags"): knownSyms.incl("g_signal_connect_data") - output.writeLine( - "proc g_signal_connect_data*(instance: pointer; detailedSignal: cstring; cHandler: GCallback;") - output.writeLine( - " data: pointer; destroyData: ClosureNotify; connectFlags: ConnectFlags): culong {.") + output.writeLine("proc g_signal_connect_data*(instance: pointer; detailedSignal: cstring; cHandler: GCallback;") + output.writeLine(" data: pointer; destroyData: ClosureNotify; connectFlags: ConnectFlags): culong {.") output.writeLine(" importc: \"g_signal_connect_data\", libprag.}") while priList.len > 0: # move missing symbols to top, but only once! let h = priList.pop @@ -2370,6 +2457,9 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] = methodBuffer = newStringStream() signalBuffer = newStringStream() let x = delayedMethods.len + #var processedFunctionsBack = processedFunctions # var due to https://forum.nim-lang.org/t/6312 + tempProcessedFunctions.setLen(0) + useTempProcessedFunctions = true try: var h = false for k in t: @@ -2384,8 +2474,7 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] = for k in t: processInfo(k) for k in t: - delayedSyms.keepItIf(mangleName(gBaseInfoGetName( - k)) != mangleName(gBaseInfoGetName(it))) + delayedSyms.keepItIf(mangleName(gBaseInfoGetName(k)) != mangleName(gBaseInfoGetName(it))) suppressType = false output.write(signalBuffer.data) output.write(methodBuffer.data) @@ -2396,6 +2485,10 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] = output.setPosition(pos) supmod3.cut(supmodpos3) supmod4.cut(supmodpos4) + #processedFunctions = processedFunctionsBack # + for el in tempProcessedFunctions: + processedFunctions.excl(el) + useTempProcessedFunctions = false assert delayedMethods.len >= x delayedMethods.setLen(x) suppressType = false @@ -2411,8 +2504,7 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] = assert false processInfo(i) if externInterfaces.len > 0: - output.writeLine( - "\n# Extern interfaces: (we don't use converters, but explicit procs for now.)") + output.writeLine("\n# Extern interfaces: (we don't use converters, but explicit procs for now.)") for i in externInterfaces: output.writeLine("") output.writeLine(i) @@ -2424,10 +2516,14 @@ proc init* = var argc: int32 = 0 var argv: cstringArray = nil gst_init(argc, argv) + +proc getType*(m: gst.Message): gst.MessageType = + m.impl.type """) if namespace == "Gtk": if ISGTK3: + output.write(GTK3_EPI) output.write( """ proc init* = @@ -2506,7 +2602,7 @@ proc get$1*(builder: Builder; name: string): $1 = if namespace == "Gdk": if ISGTK3: - output.write(GDK3_EPI) + output.write(GDK3_EPI.replace("SomeEvent", "Event")) output.write(GDK_EPI.replace("SomeEvent", "Event")) if namespace == "GtkSource": output.write(GTK_SOURCE_EPI) @@ -2612,4 +2708,4 @@ proc launch() = supmod4.close launch() -# 2615 lines +# 2711 lines