Rust-Libui: libui-rs — libui bindings .

libui: a portable GUI library for C

This README is being written.
Build Status, Azure Pipelines
Build Status, AppVeyor


It has come to my attention that I have not been particularly clear about how usable or feature-complete libui is, and that this has fooled many people into expecting more from libui right this moment than I have explicitly promised to make available. I apologize for not doing this sooner.

libui is currently mid-alpha software. Much of what is currently present runs stabily enough for the examples and perhaps some small programs to work, but the stability is still a work-in-progress, much of what is already there is not feature-complete, some of it will be buggy on certain platforms, and there's a lot of stuff missing. In short, here's a list of features that I would like to add to libui, but that aren't in yet:

  • trees
  • clipboard support, including drag and drop
  • more and better dialogs
  • printing
  • accessibility for uiArea and custom controls
  • document-based programs
  • tighter OS integration (especially for document-based programs), to allow programs to fully feel native, rather than merely look and act native
  • better support for standard dialogs and features (search bars, etc.)
  • OpenGL support

In addition, here is a list of issues generalizing existing problems.

Furthermore, libui is not properly fully documented yet. This is mainly due to the fact that the API was initially unstable enough so as to result in rewriting documentation multiple times, in addition to me not being happy with really any existing C code documentation tool. That being said, I have started to pin down my ideal code documentation style in parts of ui.h, most notably in the uiAttributedString APIs. Over time, I plan on extending this to the rest of the headers. You can also use the documentation for libui's Go bindings as a reference, though it is somewhat stale and not optimally written.

But libui is not dead; I am working on it whenever I can, and I hope to get it to a point of real quality soon!


Note that today's entry (Eastern Time) may be updated later today.

  • 7 April 2019

    • The build system has been switched to Meson. See below for instructions. This change was made because the previous build system, CMake, caused countless headaches over trivial issues. Meson was chosen due to how unproblematic setting up libui's build just right was, as well as having design goals that are by coincidence closely aligned with what libui wants.
    • Travis CI has been replaced with Azure Pipelines and much of the AppVeyor CI configuration was integrated into the Azure Pipelines configuration. This shouldn't affect most developers.
  • 1 September 2018

    • Alpha 4.1 is here. This is an emergency fix to Alpha 4 to fix uiImageAppend() not working as documented. It now works properly, with one important difference you'll need to care about: it now requires image data to be alpha-premultiplied. In addition, uiImage also is implemented slightly more nicely now, and ui.h has minor documentation typo fixes.
    • Alpha 4.1 also tries to make everything properly PIC-enabled.
  • 10 August 2018

    • Alpha 4 is finally here. Everything from Alpha 3.5 and what's listed below is in this release; the two biggest changes are still the new text drawing API and new uiTable control. In between all that is a whole bunch of bugfixes, and hopefully more stability too. Thanks to everybody who helped contribute!
    • Alpha 4 should hopefully also include automated binary releases via CI. Thanks to those who helped set that up!
  • 8 August 2018

    • Finally introduced an API for loading images, uiImage, and a new control, uiTable, for displaying tabular data. These provide enough basic functionality for now, but will be improved over time. You can read the documentation for the new features as they are here. Thanks to everyone who helped get to this point, in particular @bcampbell for the initial Windows code, and to everyone else for their patience!
  • 30 May 2018

    • Merged the previous Announcements and Updates section of this README into a single News section, and merged the respective archive files into a single file.
  • 16 May 2018

    • Thanks to @parro-it and @msink, libui now has better CI, including AppVeyor for Windows CI, and automated creation of binary releases when I make a tagged release.
  • 13 May 2018

    • Added new functions to work with uiDateTimePickers: uiDateTimePickerTime(), uiDateTimePickerSetTime(), and uiDateTimePickerOnChanged(). These operate on standard <time.h> struct tms. Thanks @cody271!
    • Release builds on Windows with MSVC should be fixed now; thanks @l0calh05t, @slahn, @mischnic, and @zentner-kyle.
  • 12 May 2018

    • GTK+ and OS X now have a cleaner build process for static libraries which no longer has intermediate files and differing configurations. As a result, certain issues should no longer be present. New naming rules for internal symbols of libui have also started being drafted; runtime symbols and edge cases still need to be handled (and the rules applied to Windows) before this can become a regular thing.
  • 2 May 2018

    • On Windows, you no longer need to carry around a libui.res file with static builds. You do need to link in the appropriate manifest file, such as the one in the windows/ folder (I still need to figure out exactly what is needed apart from the Common Controls v6 dependency, or at least to create a complete-ish template), or at least include it alongside your executables. This also means you should no longer see random cmake errors when building the static libraries.
  • 18 April 2018

    • Introduced a new uiTimer() function for running code on a timer on the main thread. (Thanks to @cody271.)
    • Migrated all code in the common/ directory to use uipriv prefixes for everything that isn't static. This is the first step toward fixing static library oddities within libui, allowing libui to truly be safely used as either a static library or a shared library.
  • 18 March 2018

    • Introduced an all-new formatted text API that allows you to process formatted text in ways that the old API wouldn't allow. You can read on the whole API here. There is also a new examples for it: drawtext, which shows the whole API at a glance. It doesn't yet support measuring or manipulating text, nor does it currently support functions that would be necessary for things like text editors; all of this will be added back later.
    • libui also now uses my utf library for UTF-8 and UTF-16 processing, to allow consistent behavior across platforms. This usage is not completely propagated throughout libui, but the Windows port uses it in most places now, and eventually this will become what libui will use throughout.
    • Also introduced a formal set of contribution guidelines, see for details. They are still WIP.
  • 17 February 2018

    • The longstanding Enter+Escape crashes on Windows have finally been fixed (thanks to @lxn).
    • Alpha 3.5 is now here. This is a quickie release primiarly intended to deploy the above fix to package ui itself. It is a partial binary release; sorry! More new things will come in the next release, which will also introduce semver (so it will be called v0.4.0 instead).
    • Alpha 3.5 also includes a new control gallery example. The screenshots below have not been updated yet.

Old announcements can be found in the file.

Runtime Requirements

  • Windows: Windows Vista SP2 with Platform Update or newer
  • Unix: GTK+ 3.10 or newer
  • Mac OS X: OS X 10.8 or newer

Build Requirements

  • All platforms:
    • Meson 0.48.0 or newer
    • Any of Meson's backends; this section assumes you are using Ninja, but there is no reason the other backends shouldn't work.
  • Windows: either
    • Microsoft Visual Studio 2013 or newer (2013 is needed for va_copy()) — you can build either a static or a shared library
    • MinGW-w64 (other flavors of MinGW may not work) — you can only build a static library; shared library support will be re-added once the following features come in:
      • Isolation awareness, which is how you get themed controls from a DLL without needing a manifest
  • Unix: nothing else specific
  • Mac OS X: nothing else specific, so long as you can build Cocoa programs


libui uses only the standard Meson build options, so a libui build can be set up just like any other:

$ # you must be in the top-level libui directory, otherwise this won't work
$ meson setup build [options]
$ ninja -C build

Once this completes, everything will be under build/meson-out/. (Note that unlike the previous build processes, everything is built by default, including tests and examples.)

The most important options are:

  • --buildtype=(debug|release|...) controls the type of build made; the default is debug. For a full list of valid values, consult the Meson documentation.
  • --default-library=(shared|static) controls whether libui is built as a shared library or a static library; the default is shared. You currently cannot specify both, as the build process changes depending on the target type (though I am willing to look into changing things if at all possible).
  • -Db_sanitize=which allows enabling the chosen sanitizer on a system that supports sanitizers. The list of supported values is in the Meson documentation.
  • --backend=backend allows using the specified backend for builds instead of ninja (the default). A list of supported values is in the Meson documentation.

Most other built-in options will work, though keep in mind there are a handful of options that cannot be overridden because libui depends on them holding a specific value; if you do override these, though, libui will warn you when you run meson.

The Meson website and documentation has more in-depth usage instructions.

For the sake of completeness, I should note that the default value of --layout is flat, not the usual mirror. This is done both to make creating the release archives easier as well as to reduce the chance that shared library builds will fail to start on Windows because the DLL is in another directory. You can always specify this manually if you want.

Backends other than ninja should work, but are untested by me.


Meson also supports installing from source; if you use Ninja, just do

$ ninja -C build install

When running meson, the --prefix option will set the installation prefix. The Meson documentation has more information, and even lists more fine-grained options that you can use to control the installation.

Arch Linux

Can be built from AUR:


Needs to be written. Consult ui.h and the examples for details for now.

Language Bindings

libui was originally written as part of my package ui for Go. Now that libui is separate, package ui has become a binding to libui. As such, package ui is the only official binding.

Other people have made bindings to other languages:

Language Bindings
C++ libui-cpp, cpp-libui-qtlike
C# / .NET Framework LibUI.Binding
C# / .NET Core DevZH.UI, SharpUI, TCD.UI
CHICKEN Scheme wasamasa/libui
Common Lisp jinwoo/cl-ui
Crystal, hedron
D DerelictLibui (flat API), libuid (object-oriented)
Euphoria libui-euphoria
Harbour hbui
Haskell haskell-libui
JavaScript/Node.js libui-node, libui.js (merged into libui-node?), proton-native, vuido
Julia Libui.jl
Kotlin kotlin-libui
Lua libuilua, libui-lua, lui, lui
Nim ui
Perl6 perl6-libui
PHP ui
Python pylibui
Ruby libui-ruby
Rust libui-rs
Scala scalaui
Swift libui-swift

Frequently Asked Questions

Why does my program start in the background on OS X if I run from the command line?

OS X normally does not start program executables directly; instead, it uses Launch Services to coordinate the launching of the program between the various parts of the system and the loading of info from an .app bundle. One of these coordination tasks is responsible for bringing a newly launched app into the foreground. This is called "activation".

When you run a binary directly from the Terminal, however, you are running it directly, not through Launch Services. Therefore, the program starts in the background, because no one told it to activate! Now, it turns out there is an API that we can use to force our app to be activated. But if we use it, then we'd be trampling over Launch Services, which already knows whether it should activate or not. Therefore, libui does not step over Launch Services, at the cost of requiring an extra user step if running directly from the command line.

See also this and this.




From examples/controlgallery:





  • minor weird ci config on appveyor
    minor weird ci config on appveyor

    Mar 14, 2020

    I was just learning something from appveyor's config and saw this weird which is asked to file a bug :)

  • uiNewLabel

    Mar 19, 2020


    NewLabel is different between Linux and Windows

    for example:

    		uiControl(uiNewLabel("This is a label\n . Right now, labels can only span one line." )),

    A new line will be made in Linux but in Windows not

  • is this lib support rtl language like Arabic language
    is this lib support rtl language like Arabic language

    Mar 22, 2020

    is this lib support rtl language like Arabic language "السلام عليكم " because i try nana lib and fltk and they had issue for supporting arabic and Hebrew not full support

  • key events
    key events

    Mar 23, 2020

    Please write a simple example of how to use the key. for example, after pressing the F1 key, run uiMsgBox ();

    I didn't find an example from Key Thank you in advance

  • uiWindowTitle

    Mar 31, 2020

    This example works fine, it is OK after closing. If we change the line 40 to 41the program hangs on closing. After removing the uiUninit () function in both cases the program works correctly.

    #include <stdio.h>
    #include <string.h>
    #include "../../ui.h"
    static int onClosing(uiWindow *w, void *data)
       return 1;
    static int onShouldQuit(void *data)
       uiWindow *mainwin = uiWindow(data);
       return 1;
    static uiWindow *mainwin;
    int main(void)
       uiInitOptions options;
       const char *err;
       memset(&options, 0, sizeof(uiInitOptions));
       err = uiInit(&options);
       if (err != NULL)
          fprintf(stderr, "error initializing libui: %s", err);
          return 1;
       mainwin = uiNewWindow("libui Control Gallery", 640, 480, 1);
       uiWindowOnClosing(mainwin, onClosing, NULL);
       uiOnShouldQuit(onShouldQuit, mainwin);
       /* uiWindowSetChild(mainwin, uiControl(uiNewLabel(uiWindowTitle(mainwin)))); */
       uiWindowSetChild(mainwin, uiControl(uiNewLabel("uiWindowTitle")));
       return 0;
  • Set column title on OS X 10.9.
    Set column title on OS X 10.9.

    May 12, 2020


    The title property of NSTableColumn is only available on macOS 10.10+, so I get the following error on OS X 10.9.5:

    2020-05-12 12:01:59.876 x[40635:303] get 0x0
    2020-05-12 12:01:59.899 x[40635:303] -[uiprivTextImageCheckboxTableColumn setTitle:]: unrecognized selector sent to instance 0x7f9d43e184c0
    2020-05-12 12:01:59.958 x[40635:303] An uncaught exception was raised
    2020-05-12 12:01:59.959 x[40635:303] -[uiprivTextImageCheckboxTableColumn setTitle:]: unrecognized selector sent to instance 0x7f9d43e184c0

    However the headerCell property of NSTableColumn, which inherits from NSCell, supports the stringValue property on all versions.

  • Tracking issue for replacing cmake
    Tracking issue for replacing cmake

    Dec 30, 2018

    cmake has been headache after headache; see for a list of particular incidents; there's probably more than this, even

    • [x] Find a replacement
    • [x] Do the replacement
    • [x] Make sure it works with CI

    Requirements, indicating how hard or soft they are:

    • [HARD] Must support both MSVC and MinGW on Windows
    • [HARD] Must support both static and shared library output, on all platforms in all toolkits (except MinGW shared libraries, which libui does not yet support building as)
    • [HARD] Must either support custom .rc files on Windows or provide a supported way of turning them off (even MinGW-w64 has started trying to be "helpful" in a way that makes .exe.manifest files impossible; see this)
    • [MEDIUM-HARD] Must be as easy to configure a build as mkdir build; cd build; tool option=setting option2=setting2 and must be as easy to clean up as rm -rf build
    • [MEDIUM] Must either be explicit about what it's doing or give me a supported way of turning off automatic insertions I don't want
    • [MEDIUM] Should not have any undocumented magic build configurations I don't know about that will break for the one person who tries to use them
    • [MEDIUM] Should not increase the amount of effort required to build libui from source by much; this means being light and generally uncontroversial on dependencies
    • this list is probably incomplete

    Suggested by others for replacement:

    • waf (requires python at runtime)
    • [the winner] meson (requires python and ninja at runtime)

    Other possibilities, in order of decreasing likelihood:

    • a custom thing entirely
    • scons (requires python at runtime)
    • bazel (requires java at runtime)
    • gn (not sure what it depends on at runtime, but there does not seem to be an easily-accessible place for the official one, and lots of forks on github)

    Suggestions from below:

    • buck (basically facebook's version of bazel; requires java at runtime)


    • autotools (I'm here to decrease headache, not increase headache)
  • unix: segmentation fault
    unix: segmentation fault

    Jun 21, 2016

    Thread 1 "main" received signal SIGSEGV, Segmentation fault.
    0x00000000010f40d0 in ?? ()
    (gdb) bt
    #0  0x00000000010f40d0 in ?? ()
    #1  0x00000000007aacae in onConfigure (win=0x1020df0, e=0x10f0ee0, data=0x105b020) at /home/simon/projects/libui/unix/window.c:53
    #2  0x00007ffff721372c in ?? () from /usr/lib/
    #3  0x00007ffff5973fa5 in g_closure_invoke () from /usr/lib/
    #4  0x00007ffff5985fb2 in ?? () from /usr/lib/
    #5  0x00007ffff598e6bf in g_signal_emit_valist () from /usr/lib/
    #6  0x00007ffff598efff in g_signal_emit () from /usr/lib/
    #7  0x00007ffff73557bc in ?? () from /usr/lib/
    #8  0x00007ffff7212784 in gtk_main_do_event () from /usr/lib/
    #9  0x00007ffff6d49735 in ?? () from /usr/lib/
    #10 0x00007ffff6d766a2 in ?? () from /usr/lib/
    #11 0x00007ffff569edd7 in g_main_context_dispatch () from /usr/lib/
    #12 0x00007ffff569f040 in ?? () from /usr/lib/
    #13 0x00007ffff569f362 in g_main_loop_run () from /usr/lib/
    #14 0x00007ffff7211a55 in gtk_main () from /usr/lib/
    #15 0x00000000007a757d in uiMain () at /home/simon/projects/libui/unix/main.c:37
    #16 0x0000000000469630 in runtime.asmcgocall () at /usr/lib/go/src/runtime/asm_amd64.s:582
    #17 0x000000c8200216d8 in ?? ()
    #18 0x000000000041017a in runtime.cgocall (fn=0xdbd100 <>, arg=0x7fffffffe790, ~r2=14406048) at /usr/lib/go/src/runtime/cgocall.go:110
    #19 0x000000000043df60 in runtime.startTheWorldWithSema () at /usr/lib/go/src/runtime/proc.go:986
    #20 0x0000000000dbd100 in ()
    #21 0x00007fffffffe790 in ?? ()
    #22 0x0000000000dbd1a0 in ()
    #23 0x000000000043dfd2 in runtime.mstart () at /usr/lib/go/src/runtime/proc.go:1068
    #24 0x0000000000467a68 in runtime.rt0_go () at /usr/lib/go/src/runtime/asm_amd64.s:149
    #25 0x0000000000000001 in ?? ()
    #26 0x00007fffffffe8a8 in ?? ()
    #27 0x0000000000000001 in ?? ()
    #28 0x00007fffffffe8a8 in ?? ()
    #29 0x0000000000000000 in ?? ()
  • CI: use AppVeyor for testing Windows build, upload artifacts from both Travis and AppVeyor
    CI: use AppVeyor for testing Windows build, upload artifacts from both Travis and AppVeyor

    May 4, 2018

  • Automating binary attachments to release.
    Automating binary attachments to release.

    Jun 18, 2016

    Hi, I'm trying to automate the process of binaries attachment to GH releases. We previously discussed this stuff on #124.

    I will use these binaries on libui-download to avoid compile libui on each libui-node install.

    This is a work in progress. Just publish the PR to get early feedback from you...

    Some open issues and questions:

    • You can see the actual attached files on this test release. Please suggest improvement or changes to file names as you like.
    • I created many tags on my fork to trigger travis release builds, I don't know if these could be polluting this PR. please double check!
    • The travis yaml file is becoming a mess. I'm thinking of creating a scripts folder to move some commands there... thoughts?
    • Actually, there is no binaries for windows and for linux 32bit. I could try to use docker on travis to get a 32bit env, and to use appveyor for windows build
    • You'll have to change the secure key with one for your repo after merge the PR. The actual one it's for my fork...
  • Table planning: loose ends
    Table planning: loose ends

    Jun 18, 2016

    Table views will operate like GtkTreeView or NSTableView: you have a model with columns for raw data and a view with a series of columns, each containing cells that take those model columns and build the final view out of them.

    There are a few things I'm not sure about when it comes to tables that I'll pose as an open question.

    First, should table view and tree view be separate? They are on OS X, are not on GTK+, and might be on Windows.

    Second, how should I permit the layout of each cell of the table? All cells in a column would have the same layout, but I really have two options here:

    • Fixed: you can have ONE checkbox, ONE image, ONE text, ONE progress bar, etc. or any combination of the above (in a fixed order), and one background color for everything in a cell
    • Variable: you can create complex but linear layouts of cell options, each pointing to different columns of your data model; this would be similar to uiBox, but with slightly different mechanics

    The question is really about how much freedom I need to give; it might not affect the implementation on GTK+ or OS X too much, but it will for Windows.

    Third, and speaking of Windows, I'm still not sure if I should just custom-draw a List View or use my own control for this. (I have my own, but I want to redesign it to use the variable cell renderer approach.) If I do take the custom draw approach, I wouldn't know how to handle accessibility...

  • [POLL] Build system change
    [POLL] Build system change

    May 24, 2016

    I had four reasons for choosing flat makefiles:

    1. I wanted libui to not have any extra dependencies (GNU make on Windows was already pushing it, but nmake is just way too primitive).
    2. I wanted to ensure that every generated file goes somewhere clean that I can predict away from the actual source code, in this case to just .obj and out directories (obviating the need for #13 in my opinion, at least)
    3. I'm not really a fan of other build systems to begin with, either because of their complexity or their mess (see point 2 above)
    4. I wanted to know exactly what was going on in the build process

    However it seems that this decision is causing problems for lots of people, mostly on Windows where the command-line Visual Studio tools either behave unpredictably or require special handling depending on the configuration. @kainjow in #15 makes a really good point: most Windows users are likely more familiar with an IDE than with the command-line build system, to the point that command-line systems like cmake are more accessible.

    While it's true I originally resisted changing, thinking make would be simpler, the number of build issues keeps growing, especially on other platforms. So now I'm willing ot hear arguments for specific build systems.

    I genuinely do not have a preference for any one build system over the other, so please make your case for one you prefer. As part of your case, you should demonstrate what a setup for libui, the test/ folder, and each example would look like, as well as (if possible) a rule to build all examples. Feel free to point out any other advantages or disadvantages.

    Here is a page detailing what an ideal build system would be like:

    Right now the following are being considered:

    • cmake
    • waf
    • scons

    I'll make my decision and switch build systems if one appeals to me more than the others.

    Thanks for your feedback! I do appreciate it all, and I want to make sure libui works for everyone :)

    enhancement help wanted question