bohonghuang / cl-gtk4 Goto Github PK
View Code? Open in Web Editor NEWGTK4/Libadwaita/WebKit2 bindings for Common Lisp.
License: GNU Lesser General Public License v3.0
GTK4/Libadwaita/WebKit2 bindings for Common Lisp.
License: GNU Lesser General Public License v3.0
Updating Ultralisp and attempting to load the package:
CL-USER> (ql:update-dist "ultralisp")
You already have the latest version of "ultralisp": 20230305133500.
NIL
CL-USER> (ql:quickload :cl-gtk4)
To load "cl-gtk4":
Load 1 ASDF system:
cl-gtk4
; Loading "cl-gtk4"
..................................................
[package gtk4].
results in this error:
no symbol named "*APPLICATION*" in "GIO"
[Condition of type SB-KERNEL:SIMPLE-PACKAGE-ERROR]
Restarts:
0: [CONTINUE] INTERN it.
1: [RETRY] Retry compiling #<CL-SOURCE-FILE "cl-gtk4" "gtk4">.
2: [ACCEPT] Continue, treating compiling #<CL-SOURCE-FILE "cl-gtk4" "gtk4"> as having been successful.
3: [RETRY] Retry ASDF operation.
4: [CLEAR-CONFIGURATION-AND-RETRY] Retry ASDF operation after resetting the configuration.
5: [RETRY] Retry ASDF operation.
--more--
SBCL 2.3.1, Linux.
I've noticed several functions that set/provide/insert text - for example (setf text-buffer-text)
will, in the GTK version accept a length (bytes) parameter, but the wrappers will populate this parameter with length
called on the argument. (i.e. number of characters, not number of bytes). In the case where the text contains any unicode characters, this can cause bugs, as the length provided by CL is wrong.
你好,我在运行此条命令:(asdf:operate :program-op :cl-gtk4/example)时出现了如下问题:
Symbol "SIMPLE" not found in the GTK4.EXAMPLE package.
Stream: #<dynamic-extent STRING-INPUT-STREAM (unavailable) from "gtk4.exa...">
[Condition of type SB-INT:SIMPLE-READER-PACKAGE-ERROR]
请问该如何解决,谢谢
In this example:
https://github.com/bigos/Pyrulis/blob/da5decdb6a8639511a5422a7b365106b2332ce6e/Lisp/menu-cairo-test.lisp#L161
I have modified your cl-gtk4 examples to have menu and cairo tests in one file. I have noticed that I can move some code outside define-application
, and the code still seems to work. Can you please comment if it is OK to do it that way?
After a lot of tinkering with CL-GTK4, running and restarting examples frequently, the FLOATING-POINT-INVALID-OPERATION error started appearing. I don't understand why this happens. Both applications that I load via C-c C-c and built-in examples are affected by this error, although everything was working before.
I rebooted REPL and it went away on its own. Although last time, as I remember, rebooting REPL didn't help.
It seems the same error occurred some time after I ran the example I wrote.
What do you think about the idea of developing complex UI in separation from Gtk?
Did you listened about Nile, special language for drawing? The main idea is that when we program in Cairo, we need to find the optimal path for rendering. You need to indicate HOW to draw. Nile's idea is that we describe WHAT needs to be drawn, and the compiler itself looks for an efficient way to do it. At least that's how I understood the articles I read.
https://tinlizzie.org/VPRIPapers/tr2009016_steps09.pdf
https://github.com/damelang/nile/tree/master
http://tinlizzie.org/dbjr/high_contrast.html
I thought maybe I could write a macro that would provide a convenient interface to Cairo? Declarative. I understand that the task is not an easy one, but you must agree, it is quite interesting.
Hello!
Could you add a list of unsolved tasks and problems to the readme? This will help a lot in development. Other people will be able to help you. I really support your development.
Hi!
I'm fairly new to LISP and am currently using this library to create an image viewing program.
However, I've hit a roadblock when trying to handle the "open" signal.
According to the official GTK documentation, the type of files
is GFile**
, i.e. a pointer to an array of GFile
elements.
I have tried the following:
(connect app "open"
(lambda (app files n-files hint)
;; How do I use files here?
(format T "~a~%" files)))
;; This prints "#.(SB-SYS:INT-SAP #X56334FB51140)"
I have not been able to figure out how to convert this into a LISP-usable list. Could you perhaps point me to a solution or documentation that might aid me in this?
Sorry I'm fairly new to common lisp/gtk/etc--I was wondering if you could take a quick look and point me in the right direction. The simple counter window did not pop up when I tried it. Thanks!
guix package --list-installed|grep -E '(^gtk|^gobject)'
gtk 4.6.6 out /gnu/store/ivwgqpd70pz4i28xs39dwza9mpjsshfy-gtk-4.6.6
gobject-introspection 1.66.1 out /gnu/store/whngbagkibx40rsprgair62c59l0b2m8-gobject-introspection-1.66.1
GI_TYPELIB_PATH=~/.guix-profile/lib/girepository-1.0 LD_LIBRARY_PATH="$LIBRARY_PATH" sbcl
This is SBCL 2.2.6, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (ql:quickload :cl-gtk4/example)
To load "cl-gtk4/example":
Load 1 ASDF system:
cl-gtk4/example
; Loading "cl-gtk4/example"
...................
(:CL-GTK4/EXAMPLE)
* (gtk4.example:simple)
(process:4632): GLib-GObject-WARNING **: 21:45:59.712: cannot register existing type 'GApplication'
(process:4632): GLib-GObject-WARNING **: 21:45:59.713: cannot add private field to invalid (non-instantiatable) type '<invalid>'
(process:4632): GLib-GObject-WARNING **: 21:45:59.713: cannot register existing type 'GActionGroup'
(process:4632): GLib-GObject-CRITICAL **: 21:45:59.713: g_type_interface_add_prerequisite: assertion 'G_TYPE_IS_INTERFACE (interface_type)' failed
(process:4632): GLib-CRITICAL **: 21:45:59.713: g_once_init_leave: assertion 'result != 0' failed
(process:4632): GLib-GObject-CRITICAL **: 21:45:59.713: g_type_add_interface_static: assertion 'G_TYPE_IS_INSTANTIATABLE (instance_type)' failed
(process:4632): GLib-GObject-WARNING **: 21:45:59.713: cannot register existing type 'GActionMap'
(process:4632): GLib-GObject-CRITICAL **: 21:45:59.713: g_type_interface_add_prerequisite: assertion 'G_TYPE_IS_INTERFACE (interface_type)' failed
(process:4632): GLib-CRITICAL **: 21:45:59.713: g_once_init_leave: assertion 'result != 0' failed
(process:4632): GLib-GObject-CRITICAL **: 21:45:59.713: g_type_add_interface_static: assertion 'G_TYPE_IS_INSTANTIATABLE (instance_type)' failed
(process:4632): GLib-CRITICAL **: 21:45:59.713: g_once_init_leave: assertion 'result != 0' failed
(process:4632): GLib-GIO-CRITICAL **: 21:45:59.713: g_application_run: assertion 'G_IS_APPLICATION (application)' failed
1
*
Hi I'm new to common-lisp. I'm using nixos, so the standard positions of libraries vary. I have successfully loaded the library by setting the LD_LIBRARY_PATH to all the libraries mentioned. The $LD_LIBRARY_PATH also contains the location of gtk4/lib directory, so it should have no problem finding gtk functions. Any help please?
New error has appeared today on one on my computers:
Error while trying to load definition for system cl-gtk4 from
pathname
/home/jacek/quicklisp/dists/ultralisp/software/bohonghuang-cl-gtk4-20231024143206/cl-gtk4.asd:
Typelib file for namespace 'Gtk', version '4.0' not found
[Condition of type ASDF/FIND-SYSTEM:LOAD-SYSTEM-DEFINITION-ERROR]
In order to load the latest version, I am using a git submodule to put this application in the /libs/cl-gtk4 folder. When attempting to load (ql:quickload :cl-gtk4)
in a fresh Slime session, I recevie the following error:
CL-USER> (ql:quickload :cl-gtk4)
To load "cl-gtk4":
Load 1 ASDF system:
cl-gtk4
; Loading "cl-gtk4"
[package gtk4]....................................
..................................................
.................
;
; caught ERROR:
; READ error during COMPILE-FILE:
;
; Symbol "APPLICATION-QUIT" not found in the GIO package.
;
; Line: 69, Column: 44, File-Position: 2688
;
; Stream: #<SB-INT:FORM-TRACKING-STREAM for "file /Users/jonathanbennett/.roswell/lisp/quicklisp/local-projects/megastrike/libs/cl-gtk4/gtk4.lisp" {70052A1083}>
This is related to #11 , where I encountered a surprise. I was assuming I can completely remove define-application. While trying this I got this error:
Cannot expand DEFINE-MAIN-WINDOW outside DEFINE-APPLICATION.
I am exploring this path because there are some programs that use several windows. One such example would be a paint program with a separate toolbar window. While you perform painting on canvas window, and it could be considered to be the main window, there are situations with several windows and no one of them really being the main window. Some text editors like Emacs could be such examples. When I have multiple windows open and I close the first window, what happens with the concept of the main window? Would the remaining windows still be open and fully functional?
Hello!
I'm comparing application code on your library and on CL-CFFI-GTK4. The second library provides a more declarative interface. For example:
(defun do-level-bar (&optional application)
(let* ((vbox (make-instance 'gtk:box
:orientation :vertical
:margin-top 12
:margin-bottom 12
:margin-start 12
:margin-end 12
:spacing 12))
(window (make-instance 'gtk:window
:title "Level bar"
:child vbox
:application application
:default-width 420
:default-height 240))
(adj (make-instance 'gtk:adjustment
:value 0.0
:lower 0.0
:upper 10.0
:step-increment 0.1))
(scale (make-instance 'gtk:scale
:orientation :horizontal
:digits 1
:value-pos :top
:draw-value t
:adjustment adj))
(levelbar1 (create-level-bar :horizontal :continuous))
(levelbar2 (create-level-bar :horizontal :discrete)))
;; Bind adjustment value for the scale to the level bar values
(g:object-bind-property adj "value" levelbar1 "value" :default)
(g:object-bind-property adj "value" levelbar2 "value" :default)
;; Pack and show the widgets
(gtk:box-append vbox (make-instance 'gtk:label
:xalign 0.0
:use-markup t
:label "<b>Continuous mode</b>"))
(gtk:box-append vbox levelbar1)
(gtk:box-append vbox (make-instance 'gtk:label
:xalign 0.0
:use-markup t
:label "<b>Discrete mode</b>"))
(gtk:box-append vbox levelbar2)
(gtk:box-append vbox (make-instance 'gtk:label
:use-markup t
:xalign 0.0
:label "<b>Change value</b>"))
(gtk:box-append vbox scale)
(gtk:widget-show window)))
Your code, sorry for the directness, merges into one whole when you look at it. It is very difficult to distinguish one part from another. I wish the code was more like a tree:
(defun main ()
(ltk:with-ltk ()
(let* (
(control-frame (make-instance 'ltk:frame :width 100
:height 100))
(text-frame (make-instance 'ltk:frame :width 100
:height 100))
(speed-spinbox (make-instance 'ltk:spinbox
:from 0 :to 10000
:master control-frame))
(text-field (make-instance 'ltk:scrolled-text :master text-frame
:width 1
:height 1))
(load-button (make-instance 'ltk:button
:text "Load"
:master control-frame
:command #'(lambda ()
(let* ((path-to-space-config (ltk:get-open-file :filetypes '(("S-expression" ".sxp"))))
(space-config (if (equal path-to-space-config "")
nil
(alexandria:read-file-into-string path-to-space-config))))
(when space-config
(setf (ltk:text text-field)
space-config))))))
(start-button (make-instance 'ltk:button
:text "Start"
:master control-frame
:command #'(lambda ()
(visualise (parse-space-from-string (ltk:text text-field))
:speed (parse-integer (ltk:text speed-spinbox)))))))
(ltk:grid text-frame 0 0)
(ltk:grid text-field 0 0)
(ltk:grid control-frame 1 0) (ltk:grid speed-spinbox 0 0)
(ltk:grid load-button 1 0)
(ltk:grid start-button 1 1))))
So you can immediately see what is responsible for what.
Best wishes
Filipp
I need it for radio and checkbox menus.
https://gitlab.gnome.org/GNOME/gtk/blob/main/examples/application9/exampleappwin.c
I tried to make binding for GStreamer and get fiasco.
cl-gtk4.gstreamer.asd:
(defsystem cl-gtk4.gstreamer
:version "1.0.0"
:author "Filipp Druan <[email protected]>"
:maintainer "Bohong Huang <[email protected]>"
:license "lgpl3"
:description "GStreamer bindings for Common Lisp."
:homepage "https://github.com/bohonghuang/cl-gtk4"
:bug-tracker "https://github.com/bohonghuang/cl-gtk4/issues"
:source-control (:git "https://github.com/bohonghuang/cl-gtk4.git")
:serial t
:components ((:file "gstreamer"))
:depends-on (#:cl-gobject-introspection-wrapper #:cl-gtk4))
(uiop:register-image-restore-hook
(lambda ()
(let ((package (find-package :sourceview)))
(when package
(setf (symbol-value (find-symbol "*NS*" package))
(uiop:symbol-call :gir :require-namespace "gstreamer"))))))
gstreamer.lisp:
(cl:defpackage gtkgstreamer
(:use)
(:nicknames #:gstreamer)
(:export #:*ns*))
(in-package #:gstreamer)
(gir-wrapper:define-gir-namespace "gstreamer")
I tried different versions, different spellings of the library name, but Lisp still gave me an error:
CL-USER> (ql:quickload :cl-gtk4.gstreamer)
To load "cl-gtk4.gstreamer":
Load 1 ASDF system:
cl-gtk4.gstreamer
; Loading "cl-gtk4.gstreamer"
[package gtkgstreamer]
; file: /home/iam/quicklisp/local-projects/cl-gtk4/gstreamer.lisp
; in: GOBJECT-INTROSPECTION-WRAPPER:DEFINE-GIR-NAMESPACE "gstreamer"
; (GOBJECT-INTROSPECTION-WRAPPER:DEFINE-GIR-NAMESPACE "gstreamer")
;
; caught COMMON-LISP:ERROR:
; (during macroexpansion of (GOBJECT-INTROSPECTION-WRAPPER:DEFINE-GIR-NAMESPACE "gstreamer"))
; Typelib file for namespace 'gstreamer' (any version) not found
; Debugger entered on #<UIOP/LISP-BUILD:COMPILE-FILE-ERROR {10046B53C3}>
;
; compilation unit aborted
; caught 1 fatal ERROR condition
; caught 1 ERROR condition
[1] CL-USER>
; Evaluation aborted on #<UIOP/LISP-BUILD:COMPILE-FILE-ERROR {10046B53C3}>
How I can make a binding?
Hello, could you please add a list of examples of practical use of your library? Small pimers are good, but I would like to see how the library is used in everyday development.
I’ve been trying to play around with adding markup tags to a GTK TextView
using cl-gtk4, but have encountered a few issues with getting the appropriate TextIter
s for a user selection in CL. The obvious route would be to use get_selection_bounds
, but as a relative newcomer to Common Lisp I’m unsure exactly how the two TextIter*
arguments are represented in cl-gtk4; I thus decided to instead use get_insert
and get_selection_bound
, and then get the corresponding TextIter
using get_iter_at_mark
. Alas, trying to call gtk4:text-buffer-get-insert
produces the following error:
Bad FFI method name get_insert
[Condition of type SIMPLE-ERROR]
Hello,
I wanted to implement this feature as part of a menubar action, however when trying to use (gtk:file-dialog-open) I am unable to figure out what would go in place of userdata and callback. Here is a simplified version of what I am trying to do:
(gtk:define-application (:name test-menu :id "okaynoobz.org")
(defun test-menu-menu ()
(let ((menu (gio:make-menu)))
(let ((submenu (gio:make-menu)))
(gio:menu-append-item submenu (gio:make-menu-item :model menu :label "Load Excel File"
:detailed-action "app.open"))
(gio:menu-append-submenu menu "File" submenu))
menu))
(defun setup-file-dialog ()
(let ((dialog (gtk:make-file-dialog)))
dialog))
(gtk:define-main-window (window (gtk:make-application-window :application gtk:*application*))
(setf (gtk:window-title window) "Test Menu")
(let ((action (gio:make-simple-action :name "open" :parameter-type nil)))
(gio:action-map-add-action gtk:*application* action)
(gtk:connect action "activate" (lambda (action param)
(declare (ignore action param))
(let ((dialog (gtk:make-file-dialog)))
(gtk:file-dialog-open dialog window (gio:make-cancellable)
(gio:make-task ) -12932)
(setf (gtk:window-transient-for dialog) window
(gtk:window-modal-p dialog) t)
(gtk:window-present dialog)))))
(let ((window-box (gtk:make-box :orientation gtk:+orientation-vertical+ :spacing 0))
(menubar (gtk:make-popover-menu-bar :model (test-menu-menu))))
(gtk:box-append window-box menubar)
(setf (gtk:window-child window) window-box))
(unless (gtk:widget-visible-p window)
(gtk:window-present window))))
I tried looking at other examples in C but there is no AsyncReadyCallback class which I can instatiate nor any make- functions. I know you can make a task, but that itself requires a callback and it's own userdata. Kindly help me with this, love for your project. Thanks
Regards,
Hamza Shahid
I need to use a list store in my program, but there is no demo of that and I cannot figure it out from the API and the error messages I'm getting. How do I pass the list of columns (I'm assuming that's via the :type
keyword, but when I try different things, I get the following error:
The value STRING is not of type (UNSIGNED-BYTE 64)
Quicklisp seems to pull your latest code, but it needs more work. I had to comment out the code in 3 places to have a successful compilation.
Also, with gdk moved to the dependency, I have to modify my example code.
But it is a nice project and has good potential.
I've been working through multiple of your examples, including those in issues #25 and #19 and the GTKMM C++ demos of the new List API, with the ultimate goal of displaying a tree view with GtkTreeListModel and GtkColumView, however, the CFFI callback seems to cause an internal floating point error with SBCL, but not in CCL.
(in-package #:gtk-test)
(proclaim '(optimize (safety 0) (speed 0)))
(cffi:defcallback tree-list-model-create-model-func :pointer ((item :pointer) (user-data :pointer))
(declare (ignore user-data))
(when item
(let* ((uuid (string-object-string (gobj:pointer-object item 'string-object))))
(print uuid)))
(cffi:null-pointer))
(defstruct product-info
name cost sale)
(define-application (:name closting :id "com.closting")
(define-main-window (window (make-application-window :application *application*))
(let* ((product-table (make-hash-table :test #'equal))
(rows (loop :for (name cost sale) :in '(("HP Zbook 15" "250$" "300$")
("Infinix S90" "40$" "60$")
("Casio Calculator" "50$" "80$"))
:for product-info := (make-product-info :name name :cost cost :sale sale)
:for uuid := (prin1-to-string (uuid:make-v4-uuid))
:do (setf (gethash uuid product-table) product-info)
:collect uuid))
(root-model (make-string-list :strings rows))
(tree-list-model (make-tree-list-model :root (make-multi-selection :model root-model)
:passthrough nil
:autoexpand t
:create-func (cffi:callback tree-list-model-create-model-func)
:user-data (cffi:make-pointer (glib::put-object nil))
:user-destroy (cffi:callback glib::free-object-callback)))
(column-view (make-column-view :model (make-multi-selection :model tree-list-model))))
(let* ((factory (make-signal-list-item-factory))
(col (make-column-view-column :title "Test" :factory factory)))
(flet ((setup (factory item) (declare (ignore factory))
(let ((expander (make-tree-expander))
(label (make-label :str "")))
(setf (tree-expander-child expander) label
(list-item-child item) expander)))
(bind (factory item) (declare (ignore factory))
(let* ((row (gobj:coerce (list-item-item item) 'tree-list-row))
(uuid (string-object-string (gobj:coerce (tree-list-row-item row) 'string-object)))
(expander (gobj:coerce (list-item-child item) 'tree-expander))
(label (gobj:coerce (tree-expander-child expander) 'label)))
(setf (label-text label) uuid))))
(connect factory "setup" #'setup)
(connect factory "bind" #'bind))
(column-view-append-column column-view col))
(setf (widget-vexpand-p column-view) t
(widget-hexpand-p column-view) t
(window-title window) "Closting"
(window-child window) column-view)
(unless (widget-visible-p window)
(window-present window)))))
arithmetic error FLOATING-POINT-INVALID-OPERATION signalled
[Condition of type FLOATING-POINT-INVALID-OPERATION]
0: ((FLET SB-UNIX::RUN-HANDLER :IN SB-UNIX::%INSTALL-HANDLER) 8 #.(SB-SYS:INT-SAP #X66B8E750BD70) #.(SB-SYS:INT-SAP #X66B8E750BC40))
1: ("foreign function: call_into_lisp_")
2: ("foreign function: funcall3")
3: ("foreign function: interrupt_handle_now_handler")
4: ((LAMBDA (&REST GIR::ARGS-IN) :IN GIR::BUILD-FUNCTION) #.(SB-SYS:INT-SAP #X66B8E00FDB30))
5: ((LAMBDA (GTK4::APP) :IN GTK-TEST::COM.CLOSTING.MAIN) #<unused argument>)
6: ((LAMBDA (&REST GTK4::ARGS) :IN GTK4::ATTACH-RESTARTS) #<GIR::OBJECT-INSTANCE {10045A5D53}>)
7: ((LAMBDA (GIR::CLOSURE RETURN GIR::N-VALUES GIR::PARAMS GIR::HINT GIR::DATA) :IN "/home/soz/quicklisp/dists/quicklisp/software/cl-gobject-introspection-20230618-git/src/signal.lisp") #.(SB-SYS:INT-SAP..
8: ((LAMBDA (SB-ALIEN::ARGS-POINTER SB-ALIEN::RESULT-POINTER FUNCTION) :IN "/home/soz/quicklisp/dists/quicklisp/software/cl-gobject-introspection-20230618-git/src/signal.lisp") #<unavailable argument> #<..
9: ("foreign function: funcall_alien_callback")
10: ("foreign function: #x50000DEB")
11: ((LAMBDA (&REST GIR::ARGS-IN) :IN GIR::BUILD-FUNCTION) #.(SB-SYS:INT-SAP #X66B8E0016930) NIL)
12: (GIO:APPLICATION-RUN #<GIR::OBJECT-INSTANCE {1002411A93}> NIL)
13: (SB-INT:SIMPLE-EVAL-IN-LEXENV (GTK-TEST::CLOSTING) #<NULL-LEXENV>)
14: (EVAL (GTK-TEST::CLOSTING))
15: ((LAMBDA NIL :IN SLYNK-MREPL::MREPL-EVAL-1))
I also can't figure out how to return a pointer to the child model from the GtkTreeListModelCreateModelFunc
callback, using
(cffi:make-pointer (glib::put-object (make-string-list :strings (list))))
causes a memory fault under SBCL, and simply hangs under CCL.
I appreciate any help, and thank you very much for the great library.
https://docs.gtk.org/gtk4/method.Application.get_windows.html
I am trying to find the list of windows associated with the application. Also, how do I programmatically exit from Gtk4 application close all windows and return to REPL?
https://github.com/bigos/Pyrulis/blob/master/Lisp/LiterateLisp/menu-cairo-test.org
With slight modification, the code can be run from the org file.
Feel free to close the issue, as there is no problem. It was just the easiest to send the message this way.
I started with my own toy application, a clock. I get a window, the label widget, and initial content, but I can't update the label. Sort of. The code executes, but the window doesn't change, unless I resize it or maximize it, or somehow convince GTK4 to redraw it. Simply hiding it behind another window and re-exposing it doesn't work, nor does minimizing it and un-minimizing it. The tooltip works (and shows the progression of time), presumably because it's reconstructed and drawn fresh every time rather than updated.
Then I tried running cl-gtk4/example:simple, and it does the same thing: the application runs, but the window doesn't update until I do something with the window manager to force a redraw.
Same thing from a shell or slime.
SBCL 2.1.11, Arch Linux, jwm window manager, gtk4 4.8.3, 2022-11-07 quicklisp distribution.
I used quicklisp to install cl-glib and cl-gobject-introspection-wrapper; and cloned cl-gtk4 into my local projects directory.
What other information can I provide?
I tried to install CL-GTK.WEBKIT and got an error:
CL-USER> (ql:quickload :cl-gtk4.webkit2/example)
To load "cl-gtk4.webkit2/example":
Load 1 ASDF system:
cl-gtk4.webkit2/example
; Loading "cl-gtk4.webkit2/example"
[package webkit2]
; file: /home/iam/quicklisp/dists/ultralisp/software/bohonghuang-cl-gtk4-20231015170944/webkit2.lisp
; in: GOBJECT-INTROSPECTION-WRAPPER:DEFINE-GIR-NAMESPACE "WebKit2"
; (GOBJECT-INTROSPECTION-WRAPPER:DEFINE-GIR-NAMESPACE "WebKit2" "5.0")
;
; caught COMMON-LISP:ERROR:
; (during macroexpansion of (GOBJECT-INTROSPECTION-WRAPPER:DEFINE-GIR-NAMESPACE "WebKit2" ...))
; Typelib file for namespace 'WebKit2', version '5.0' not found
; Debugger entered on #<UIOP/LISP-BUILD:COMPILE-FILE-ERROR {1005F712F3}>
Manjaro Linux.
Installed: webkit2gtk, webkit2gtk-4.1, webkit2gtk-6.0,
I have this little example which closely resembles your example:
https://github.com/bigos/Pyrulis/blob/d6e4e55a76e2e000d680250c89f5f73864871730/Lisp/cl-gtk4-example.lisp#L127
But I need help finding how to call your gio:application in the example context.
I've experiences with gtk, but I'm new to Lisp. I've been trying to make a simple front-end using a Grid.
I guess I need to use grid-attach
to attach a widget to the grid. But when running that code, I got a Bad FFI method name attach
error. What am I doing wrong?
My code is below. Thanks in advance!
(define-application (:name recycle-app
:id "org.recycle-app")
(define-main-window
(window (make-application-window :application *application*))
(setf (window-title window) "recycle-app")
(let ((box (make-box :orientation +orientation-vertical+
:spacing 4))
(grid-input (make-grid-layout))
(label-postalcode (make-label :str "Postal code:"))
;(label-streetname (make-label :str "Streetname:"))
;(label-housenumber (make-label :str "Housenumber:"))
(button-collect (make-button :label "get collections")))
(setf (grid-column-spacing grid-input) 8)
(setf (grid-row-spacing grid-input) 4)
(grid-attach grid-input label-postalcode 0 0 1 1)
(box-append box grid-input)
(box-append box button-collect)
(setf (window-child window) box))
(unless (widget-visible-p window)
(window-present window))))``
老兄还是不行啊,报错信息:
failed AVER: (SB-THREAD::THREAD-P SB-IMPL::THREAD)
This is probably a bug in SBCL itself. (Alternatively, SBCL
might have been corrupted by bad user code, e.g. by an undefined
Lisp operation like (FMAKUNBOUND 'COMPILE), or by stray pointers
from alien code or from unsafe Lisp code; or there might be a
bug in the OS or hardware that SBCL is running on.) If it seems
to be a bug in SBCL itself, the maintainers would like to know
about it. Bug reports are welcome on the SBCL mailing lists,
which you can find at http://sbcl.sourceforge.net/.
[Condition of type SB-INT:BUG]
Before I deleted the Lisp cache everything loaded and worked fine. After that I tried to load the library and it gave the following error:
CL-USER> (ql:quickload :cl-gtk4.sourceview/example)
To load "cl-gtk4.sourceview/example":
Load 1 ASDF system:
cl-gtk4.sourceview/example
; Loading "cl-gtk4.sourceview/example"
[package glib]
; file: /home/iam/quicklisp/dists/ultralisp/software/bohonghuang-cl-glib-20230831185201/glib/package.lisp
; in: GOBJECT-INTROSPECTION-WRAPPER:DEFINE-GIR-NAMESPACE "GLib"
; (GOBJECT-INTROSPECTION-WRAPPER:DEFINE-GIR-NAMESPACE "GLib")
;
; caught COMMON-LISP:ERROR:
; (during macroexpansion of (GOBJECT-INTROSPECTION-WRAPPER:DEFINE-GIR-NAMESPACE "GLib"))
; Unhandled memory fault at #x18.
; Debugger entered on #<UIOP/LISP-BUILD:COMPILE-FILE-ERROR {10057A03B3}>
cl-gtk4/examples/gdk4-cairo.lisp
Line 29 in e391563
Using float allows me to write color-to-rgba function.
(cffi:defcstruct gdk-rgba
(red :float)
(green :float)
(blue :float)
(alpha :float))
(defmacro with-gdk-rgba ((pointer color) &body body)
`(cffi:with-foreign-object (,pointer '(:struct gdk-rgba))
(let ((,pointer (make-instance 'gir::struct-instance
:class (gir:nget gdk::*ns* "RGBA")
:this ,pointer)))
(gdk:rgba-parse ,pointer ,color)
,@body)))
(defun color-to-rgba (color) ;names are trnaslated correctly
(cffi:with-foreign-object (rgba '(:struct gdk-rgba))
(let ((pointer (make-instance 'gir::struct-instance
:class (gir:nget gdk::*ns* "RGBA")
:this rgba)))
(let ((valid-color (gdk:rgba-parse pointer color)))
(cffi:with-foreign-slots ((red green blue alpha) rgba (:struct gdk-rgba))
(list valid-color red green blue alpha))))))
Hello!
I really need a tutorial, thet would help my figure out how to deal with the Lisp version of the library using the official documentation for GTK4, which uses C.
There are following questions:
Hello!
I tried to write the most simple application:
(define-application (:name main
:id "qwertyuiop")
(define-main-window (main-window (make-application-window :application
*application*))
(setf (window-title main-window)
"Share-files")
(let ((main-box (make-box :orientation +orientation-vertical+
:spacing 0)))
(setf (window-child main-window)
main-box)
(window-present main-window))))
When I called main function I got this:
Backtrace:
0: (GIR::G-SIGNAL-CONNECT-CLOSURE NIL "activate" #.(SB-SYS:INT-SAP #X7FF90EB56AF0) NIL)
1: (GIR:CONNECT NIL "activate" #<FUNCTION (LAMBDA (&REST GTK4::ARGS) :IN GTK4::ATTACH-RESTARTS) {10074D8B1B}> :AFTER NIL :SWAPPED NIL)
Locals:
#:.DEFAULTING-TEMP. = NIL
#:.DEFAULTING-TEMP.#1 = NIL
AFTER = NIL
C-HANDLER = #<FUNCTION (LAMBDA (&REST GTK4::ARGS) :IN GTK4::ATTACH-RESTARTS) {10074D8B1B}>
C-HANDLER#1 = #<FUNCTION (LAMBDA (&REST GTK4::ARGS) :IN GTK4::ATTACH-RESTARTS) {10074D8B1B}>
FLAGS = 0
G-OBJECT = NIL
#:G0 = #<FUNCTION (LAMBDA (&REST GTK4::ARGS) :IN GTK4::ATTACH-RESTARTS) {10074D8B1B}>
OBJECT-PTR = NIL
SIGNAL = "activate"
STR-SIGNAL = "activate"
SWAPPED = NIL
2: (QWERTYUIOP.MAIN NIL)
Locals:
GTK4::ARGV = NIL
3: (SB-INT:SIMPLE-EVAL-IN-LEXENV (MAIN) #<NULL-LEXENV>)
4: (EVAL (MAIN))
5: ((LAMBDA NIL :IN SLYNK-MREPL::MREPL-EVAL-1))
--more--
application = NIL
What's the deal with Cairo in Lisp? In one of the examples, you used CL-Cairo2, which has not been updated for seven years. Is it still relevant? Maybe it's time to update? Maybe it makes sense to write the same generator for it as for GObject?
Or has the library API not changed since then?
https://docs.gtk.org/gtk4/class.DrawingArea.html
Can you please provide a simple example of creating a drawing area and drawing some lines and text?
Hello, love the work you have done!
I wanted to create a GtkListView, but didn't know how to. After hours of looking through the GTK docs I came up with this code:
(let* ((model (gtk:make-list-store :types `(,(gobject:type-from-name "GtkLabel"))))
(selmodel (gtk:make-single-selection :model model))
(factory (gtk:make-signal-list-item-factory))
(view (gtk:make-list-view :model selmodel :factory factory))
(item1 (gtk:make-label :str "BRUHSEIDh")))
(gtk::list-box-append model 6)
(setf (gtk:window-child window) view))
Turns out for a reason I cannot understand, list-box-append gives out an error saying it takes only 1 argument...
Please give an example for ListViews or explain this problem to me!
I really don't want to drop this application and write it in another language. Thanks a bunch.
Regards,
Hamza
I'm trying to understand what the lambda used to connect to a response signal from a dialog. Here's what I've got currently
(gtk:connect dialog "response"
(lambda (response) (format t "I'm in the response!")))
When I run this, I get the following error:
debugger invoked on a SB-INT:SIMPLE-PROGRAM-ERROR @7005729BE0 in thread
#<THREAD "main thread" RUNNING {7006070573}>:
invalid number of arguments: 2
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [REPLACE-FUNCTION ] Call a different function with the same arguments
1: [CALL-FORM ] Call a different form
2: [RETURN ] Return from current handler.
3: [RETURN-AND-ABORT ] Return from current handler and abort the GTK application.
4: [RETURN-VALUE ] Return from current handler with specified value.
5: [RETURN-VALUE-AND-ABORT] Return from current handler with specified value and abort the GTK application.
6: [CONTINUE ] Ignore runtime option --eval "(megastrike)".
7: [ABORT ] Skip rest of --eval and --load options.
8: Skip to toplevel READ/EVAL/PRINT loop.
9: [EXIT ] Exit SBCL (calling #'EXIT, killing the process).
((LAMBDA (RESPONSE) :IN BUILD-COMMAND-BAR) #<GIR::OBJECT-INSTANCE {7009F083D3}> -2) [external]
source: (LAMBDA (RESPONSE) (FORMAT T "I'm in the response!"))
I'm guessing that means there should be 2 arguments to the function, but I can't tell what they would be from the documentation
Mostly I need an example of translating:
https://docs.gtk.org/gtk4/getting_started.html
https://docs.gtk.org/gtk4/getting_started.html#packing-buttons-with-gtkbuilder
/* Construct a GtkBuilder instance and load our UI description */
GtkBuilder *builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, "builder.ui", NULL);
/* Connect signal handlers to the constructed widgets. */
GObject *window = gtk_builder_get_object (builder, "window");
gtk_window_set_application (GTK_WINDOW (window), app);
I do not understand how to translate variable pairs like *builder and builder, one with asterix and another without one.
i can't find a way to get key pressed events
i tried
(connect window "key-press-event" (lambda (window event) (print event)))
as a C equivalent to
g_signal_connect (G_OBJECT (window), "key_press_event", G_CALLBACK (gkeypress), NULL);
but i always end up getting this type of error
(sbcl:6073): GLib-GObject-WARNING **: 11:33:38.867: ../../../gobject/gsignal.c:2510: signal 'key_press_event' is invalid
I suppose i have to cast widgets to G_OBJECT but i can't find a way to do it in lisp
an example of how to handle key events would be welcome
also i did not manage to create new tags, or in other words to find an equivalent of
tag = gtk_text_buffer_create_tag (buffer, "blue_foreground", "foreground", "blue", NULL);
make-text-tag function does not seem to provide properties
(make-text-tag :name name)
and many thanks for this excellent work btw !
I'm trying to build a shippable binary for my program that other people can download and install without really knowing Lisp works. When I do so, I get the following error: Link to error in Github Action.
The action that is running here seems like it should work, but I don't know anything about Github actions, so it is entirely possible that I'm doing this completely wrong. If this isn't the right way to approach this, please let me know. What I want to happen is to have a Linux, a MacOS, and a Windows tarball attached to each release of my game that people can download, unzip, and then just click the file named "megastrike" and it runs.
I have a situation where using a GtkStringList to maintain a tree view would be wasteful, as I have directly mapping indexes to an array. As far as I understand from the GTK documentation, GListStore items must be subclasses of GObject.Object, so to use integers, in C I would have to create a new GObject with my integer field, but I can't seem to find a way to do that in cl-gtk4.
This was mentioned in #27 but you ended up providing an alternative solution.
Perhaps my idea of subclassing GObject is suboptimal as well and there is a simpler way to use fixnums?
In sbcl, some (all?) gtk objects seem to requite a persistent reference originating from within the lisp program, otherwise upon garbage collection the object will be deleted (even if there are references to that object from other gtk objects).
To demonstrate the issue I've written a short script (assuming quicklisp is installed).
(ql:quickload '(:cl-gtk4 :cl-glib :bordeaux-threads))
(defun wait-trigger-gc ()
(sleep 5)
(sb-ext:gc))
(defvar *shortcuts* nil)
(defvar *window* nil)
(defun start (app)
(let ((window (gtk4:make-application-window :application app))
(shortcuts (gtk4:make-shortcut-controller)))
(setf (gtk4:window-title window) "Test")
(gtk4:widget-add-controller window shortcuts)
;; (setf *shortcuts* shortcuts)
;; (setf *window* window)
(unless (gtk4:widget-visible-p window)
(gtk4:window-present window))))
(defun run-app ()
(let ((app (gtk4:make-application
:application-id "org.rationalis-petra.test"
:flags gio:+application-flags-flags-none+)))
(gtk:connect app "activate" #'start)
(unwind-protect (gio:application-run app nil)
(progn
(mapcar (alexandria:compose
#'gtk4:window-close
(alexandria:rcurry #'gobj:pointer-object 'window))
(glib:glist-list (gtk4:application-windows app)))
(glib:idle-add (lambda () (gio:application-quit app)))))))
(defun run-test ()
(bt:make-thread #'wait-trigger-gc)
(run-app))
(run-test)
On my system (intel laptop running Linux/EndeavourOS), executing with sbcl --load <filename>
results in the following behaviour:
By default, after 5 seconds (i.e. when gc is forcibly triggered), the application will report the following error message:
(sbcl:20304): Gdk-WARNING **: 14:14:19.069: gdk_gl_context_make_current() failed
(sbcl:20304): GLib-GObject-CRITICAL **: 14:14:19.069: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
0
Sometimes, it will drop you into ldb, and sometimes the application crashes outright.
If line (setf *window* window)
is uncommented, then after 5 seconds the controller will be deleted, so any event (mouse-move, keypress etc.) will result in sbcl reporting the following error:
(sbcl:20404): Gtk-CRITICAL **: 14:16:56.782: gtk_event_controller_get_propagation_phase: assertion 'GTK_IS_EVENT_CONTROLLER (controller)' failed
Further, trying to close the window will drop the user into ldb
Finally, if both lines are uncommented, then the application works as expected.
Whether or not this is a bug, I am unsure, but if it is expected behaviour I think it should be documented somewhere.
when executing the code
(let ((level-bar-widget (gtk:make-level-bar :min-value 0 :max-value 4)))
(setf (gtk:level-bar-mode level-bar-widget) gtk:+level-bar-mode-discrete+)
(setf (gtk:level-bar-value level-bar-widget) 2)
(gtk:box-append layout level-bar-widget))
I receive the following error:
#<THREAD "main thread" RUNNING {7006070483}>:
The value
0
is not of type
DOUBLE-FLOAT
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [RETURN ] Return from current handler.
1: [RETURN-AND-ABORT ] Return from current handler and abort the GTK application.
2: [RETURN-VALUE ] Return from current handler with specified value.
3: [RETURN-VALUE-AND-ABORT] Return from current handler with specified value and abort the GTK application.
4: [CONTINUE ] Ignore runtime option --eval "(megastrike)".
5: [ABORT ] Skip rest of --eval and --load options.
6: Skip to toplevel READ/EVAL/PRINT loop.
7: [EXIT ] Exit SBCL (calling #'EXIT, killing the process).
(CFFI-SYS:%MEM-SET 0 #.(SB-SYS:INT-SAP #X600003149108) :DOUBLE 0)
source: (DEFINE-TYPE-MAPPING
((8 SB-SYS:SIGNED-SAP-REF-8 SB-SYS:SAP-REF-8)
(16 SB-SYS:SIGNED-SAP-REF-16 SB-SYS:SAP-REF-16)
(32 SB-SYS:SIGNED-SAP-REF-32 SB-SYS:SAP-REF-32)
(64 SB-SYS:SIGNED-SAP-REF-64 SB-SYS:SAP-REF-64))
((:CHAR CHAR) (:UNSIGNED-CHAR UNSIGNED-CHAR) (:SHORT SHORT)
(:UNSIGNED-SHORT UNSIGNED-SHORT) (:INT INT)
(:UNSIGNED-INT UNSIGNED-INT) (:LONG LONG)
(:UNSIGNED-LONG UNSIGNED-LONG) (:LONG-LONG LONG-LONG)
(:UNSIGNED-LONG-LONG UNSIGNED-LONG-LONG)
(:FLOAT SINGLE-FLOAT SB-SYS:SAP-REF-SINGLE)
(:DOUBLE DOUBLE-FLOAT SB-SYS:SAP-REF-DOUBLE) ...))
I receive the same error when using 0.0, 4.0, and 2.0 and my fumbling around inside the GTK and GOBJ namespaces doesn't return anything that looks like DOUBLE-FLOAT to me.
As it says in the title: could you please add an example for using Asynchronous programming. I'm particularly interested in using GAsyncReadyCallback
as it's required as an input to some functions (like the file dialogs).
Thanks!
I need to add images to my game. In cl-cffi-gtk, they did this via PixBufs but it seems like the Picture Class is the way I need to go. But I cannot get it to load. Here is my current code
(let ((frame (gtk:make-frame :label (cu/full-name u)))
(statblock (gtk:make-box :orientation gtk:+orientation-vertical+ :spacing 5))
(img (gtk:make-picture :filename (namestring (cu/display u)))))
(setf (gtk:frame-child frame) statblock)
(gtk:box-append statblock img)
frame)
frame
is rendered in another function. This same code works when I replace gtk:make-picture
with gtk:make-image
, but it seems like make-image is for displaying images at a fixed size, not at natural size (which is what I want).
EDIT: Extraneous code rendering labels and other rows of this stat block have been removed. But the code fails whether they are commented out or not. And I am sure that (cu/display u)
contains the path to the correct file because gtk:make-image
puts a very tiny rendering of that image inside the frame whereas gtk:make-picture
does not.
Hello!
I have high hopes for this library. I hope it will be a serious, thorough, long-term project.
Every serious library needs serious documentation. So far it's pretty bad.
Please write docstrings at least for the macros you write. Please!
You can use these tools:
https://github.com/Shinmera/staple
https://github.com/Shinmera/documentation-utils
If need be, I'm willing to put the documentation in a nice way, I'd be very happy to do so. Just please write a description of macros, please.
https://docs.gtk.org/gdk4/struct.Rectangle.html
I am trying to add popover and need it to show at mouse coordinates.
What's the best way to get the current root window? Should I be storing it in a global variable or is there already a global variable that has it?
In the game I am building, there are different phases of play, each phase of play needs to modify the contents of the window. I'm just now getting to the point where I need to find the best way to manage the transitions between phases and I'm running into a conceptual problem figuring out the best way to handle passing the window around to change it.
So for example, I have created a *game*
global variable which has a CLOS class containing all the relevant global variables for the game's state (current turn, current phase, list of units, initiative order, etc). Then I write a advance-phase
function that calls (incf (game/current-phase *game*))
which dispatches to a set of functions that I have written to build the display for each screen, like draw-initiative-phase
, draw-deployment-phase
. Each of those functions creates a gtk:container
such as (let ((layout (gtk:make-grid))) ...)
or make-box
. How do I then get that container passed to my main window?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.