• Stars
    star
    188
  • Rank 205,563 (Top 5 %)
  • Language
    Common Lisp
  • License
    GNU Lesser Genera...
  • Created about 2 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

GTK4/Libadwaita/WebKit2 bindings for Common Lisp.

cl-gtk4

https://docs.gtk.org/gtk4/gtk-logo.svg

GTK4/Libadwaita/WebKit2 bindings for Common Lisp.

Requirement

Before getting started, please ensure these libraries are available in your system:

  • GTK4
  • GObject Introspection
  • WebKit2GTK (optional)
  • libadwaita (optional)

Theoretically, the application built with cl-gtk4 can run on most systems supported by GTK4 and most implementations that support CFFI callback (required by cl-gobject-introspection). The examples are tested to run on following implementations:

Usage

  1. Currently, cl-gtk4 is available on Ultralisp, so it can be downloaded via Quicklisp with Ultralisp installed as its distribution. To install cl-gtk4 manually, you can clone this repository along with the following dependencies into the local-projects under your Quicklisp installation root:
  2. Load the library with:
    • (ql:quickload :cl-gtk4)
    • (ql:quickload :cl-gtk4.adw) (if you need libadwaita)
    • (ql:quickload :cl-gtk4.webkit2) (if you need WebKit2GTK)
  3. For GTK4 usage, please refer to GTK API reference and check out the conversion rules for these APIs.

Multi-threading

Please note that GTK runs in a single thread and is NOT thread-safe, so all the UI-related operations must happen in GTK main event loop, which means you cannot write the code like this:

(let ((label (make-label :str "0"))
      (count 0))
  (bt:make-thread
   (lambda ()
     (loop :repeat 5
           :do (setf (label-text label) (format nil "~A" (incf count)))
               (sleep 1)))))

GLib provides idle_add and timeout_add to add a function to execute in the main event loop, which is thread-safe so that it can be called in other threads. cl-glib wraps idle_add and timeout_add, and cl-gtk4 create restarts for the handler passed for them to be invoked safely, even when conditions are signaled. It also provides the API for convenience:

  • gtk:run-in-main-event-loop
    Execute the body in GTK main event loop, in which we can access the UI safely:
    (let ((label (make-label :str "0"))
          (count 0))
      (bt:make-thread
       (lambda ()
         (loop :repeat 5
               :do (gtk:run-in-main-event-loop
                     (setf (label-text label) (format nil "~A" (incf count))))
                   (sleep 1)))))    ; Don't put this into `gtk:run-in-main-event-loop'
        

Interactive Programming

Live Reload

You can reload the application without closing the window constructed in define-main-window by recompiling the define-application macro in top-level (Simply stroke C-c C-c if using Slime/Sly in Emacs):

screenshots/live-reload.gif

Restarts

The API in cl-gtk4 handles almost all possible recoverable errors by providing restarts, by which you can recover the program or safely exit the GTK application when encountering an error.

Please note that stack unwinding into FFI functions is unsafe and may cause you to be unable to run the GTK application in the current session again, or even freeze or crash the Lisp implementation. Therefore, it is important to always use the restarts provided by cl-gtk4 or other restarts that do not unwind the stack into FFI functions to recover or exit the application.

Additionally, when you attempt to interrupt a GTK program through Slime/Sly, such as C-c C-c in Emacsโ€™ REPL, remember to choose ABORT-APPLICATION provided by cl-gtk4 instead of ABORT provided by the Lisp implementation.

The highlighted restarts as follows, for example, are safe, while the rest perform stack unwinding and are therefore unsafe in GTK applications:

screenshots/restart-1.png

screenshots/restart-2.png

Examples

See the examples folder.

Deployment

The examples are ready for being built into executable if the implementation supports :program-op:

(asdf:operate :program-op :cl-gtk4/example)

Then you could find the executable file under the examples folder.

Note that:

  • On ECL, for unknown reason, the :entry-point of the ASDF system is ignored. This command should be used instead:
    (asdf:make-build :cl-gtk4/example :type :program :epilogue-code '(progn (uiop:symbol-call :gtk4.example :simple) (si:exit)))
        
  • On Microsoft Windows, itโ€™s recommended to launch your application via Dependency Walker, then the shared libraries used by your application would appear in it. You should copy all these .dll files into the folder where you place the executable file. If you are using MSYS2, the folder structure might be like this:
    .
    โ”œโ”€โ”€ bin
    โ”‚ย ย  โ”œโ”€โ”€ gdbus.exe
    โ”‚ย ย  โ”œโ”€โ”€ libgio-2.0-0.dll
    โ”‚ย ย  โ”œโ”€โ”€ libgirepository-1.0-1.dll
    โ”‚ย ย  โ”œโ”€โ”€ libglib-2.0-0.dll
    โ”‚ย ย  โ”œโ”€โ”€ libgobject-2.0-0.dll
    โ”‚ย ย  โ”œโ”€โ”€ libgtk-4-1.dll
    โ”‚ย ย  โ”œโ”€โ”€ your_application.exe
    โ”‚ย ย  โ””โ”€โ”€ ...
    โ”œโ”€โ”€ lib
    โ”‚ย ย  โ”œโ”€โ”€ girepository-1.0
    โ”‚ย ย  โ”œโ”€โ”€ gtk-4.0
    โ”‚ย ย  โ””โ”€โ”€ ...
    โ””โ”€โ”€ share
        โ”œโ”€โ”€ icons
        โ””โ”€โ”€ ...
        

    The folder lib/girepository-1.0 is mandatory, without which your application wonโ€™t work as expected.

More Repositories

1

cffi-ops

A Common Lisp library that helps write concise CFFI-related code.
Common Lisp
28
star
2

sbcl-termux-build

Prebuilt SBCL binary for Android (Termux)
Shell
26
star
3

cl-universal-tween-engine

Common Lisp port of the Universal Tween Engine
Common Lisp
15
star
4

cl-gobject-introspection-wrapper

Wrap and call GObject Introspection FFI function in LISP style.
Common Lisp
15
star
5

cffi-object

A Common Lisp library that enables fast and convenient interoperation with foreign objects.
Common Lisp
14
star
6

claw-raylib

Fully auto-generated Common Lisp bindings to Raylib and Raygui using claw and cffi-object
Common Lisp
10
star
7

calc-textrail

Create Tex preview from calc-trail-buffer for better readability.
Emacs Lisp
9
star
8

rov-host

A cross-platform, high-performance underwater robot controll program written in Rust
Rust
6
star
9

cl-glib

GLib bindings for Common Lisp.
Common Lisp
6
star
10

OpenCV_DCP

DCP dehazing algorithm written in C++ and OpenCV
C++
4
star
11

vgmplay

An unfinished video game music player written in Common Lisp
Common Lisp
4
star
12

VisPID

PID controll algorithm and visualizer implemented with LibGDX and Box2D, written in Kotlin
Kotlin
3
star
13

cffi-static-link-example

An example project for static linking C extensions in Common Lisp
Common Lisp
3
star
14

wemeet-attend-stats

WeMeet attendance statistics CLI program written in Python
Python
3
star
15

indent-yank

Emacs Lisp
2
star
16

SUB_Rov

ๆฐดไธ‹ๆœบๅ™จไบบไธŠไฝๆœบ็จ‹ๅบ๏ผˆROV Controller๏ผ‰
C++
1
star
17

trivial-segmentation-fault

A Common Lisp library that provides a portable way to handle segmentation faults.
Common Lisp
1
star
18

promise-async-await

Async/await support for Shinmera's promise library.
Common Lisp
1
star
19

7seg_led_detect

Python+OpenCVๆจกๆฟๅŒน้…ๅฎž็Žฐ็š„ๆ•ฐ็ ็ฎก่ฏ†ๅˆซ
Python
1
star