Pugl is a minimal portability layer for embeddable GUIs. It provides a drawing context and event-based main loop API, which can be used to create graphical applications or embedded views.

Pugl is particularly suitable for plugins, since it has no implicit context or mutable static data, and can be statically linked. The “core” library implements platform support, and depends only on standard system libraries. MacOS, Windows, and X11 are currently supported.

Graphics backends are built as separate libraries, so applications depend only on the APIs that they use. Pugl includes graphics backends for Cairo, OpenGL, and Vulkan. Other graphics APIs can be used by implementing a custom backend.


Using an Installed Version

When Pugl is installed, particularly on POSIX systems, pkg-config packages are provided that link with the core platform library and desired backend:

pkg-config --cflags --libs pugl-0
pkg-config --cflags --libs pugl-cairo-0
pkg-config --cflags --libs pugl-gl-0
pkg-config --cflags --libs pugl-vulkan-0

Depending on one of these packages should be all that is necessary to use Pugl. If pkg-config is not available, details on the individual libraries that are installed are available in the README.

Using a Meson Subproject

Pugl uses the meson build system, which allows it to be included as a subproject within other meson projects.

To use Pugl as a subproject, copy the source tree (or use a git submodule or subtree) to your subprojects directory, for example to subprojects/pugl, and use the subproject function in meson to include it:

pugl_proj = subproject('pugl')

See the Meson subproject documentation for details.

Vendoring Manually

To “vendor” Pugl with projects that use a different build system, the headers in the include subdirectory and sources in src are needed. The include directory needs to be added to the search path for the compiler, and the required source files need to be compiled. It is only necessary to build the needed platform and backend implementations. Due to the modular design, no centralized configuration is needed to enable or disable platform/backend support. However, a few preprocessor symbols can be used to control which X11 features are used, see the top of src/x11.c for details.


The Pugl API revolves around two main objects: the world and the view. An application creates a world to manage top-level state, then creates one or more views to display.

The core API (excluding backend-specific components) is declared in pugl.h:

#include <pugl/pugl.h>

Creating a World

The world is the top-level object which represents an instance of Pugl. It handles the connection to the window system, and manages views and the event loop.

An application typically has a single world, which is constructed once on startup and used to drive the main event loop.


A world must be created before any views, and it must outlive all of its views. A world is created with puglNewWorld(), for example:

PuglWorld* world = puglNewWorld(PUGL_PROGRAM, 0);

For a plugin, specify PUGL_MODULE instead. In some cases, it is necessary to pass additional flags. For example, Vulkan requires thread support:

PuglWorld* world = puglNewWorld(PUGL_MODULE, PUGL_WORLD_THREADS)

It is a good idea to set a class name for your project with puglSetWorldString(). This allows the window system to distinguish different applications and, for example, users to set up rules to manage their windows nicely:

puglSetWorldString(world, PUGL_CLASS_NAME, "MyAwesomeProject")

Setting Application Data

Pugl will call an event handler in the application with only a view pointer and an event, so there needs to be some way to access the data you use in your application. This is done by setting an opaque handle on the world with puglSetWorldHandle(), for example:

puglSetWorldHandle(world, myApp);

The handle can be later retrieved with puglGetWorldHandle():

MyApp* app = (MyApp*)puglGetWorldHandle(world);

All non-constant data should be accessed via this handle, to avoid problems associated with static mutable data.

Creating a View

A view is a drawable region that receives events. You may think of it as a window, though it may be embedded and not represent a top-level system window. [1]

Creating a visible view is a multi-step process. When a new view is created with puglNewView(), it does not yet represent a “real” system view:

PuglView* view = puglNewView(world);

Configuring the Frame

Before display, the necessary frame and window attributes should be set. These allow the window system (or plugin host) to arrange the view properly. For example:

const PuglSpan defaultWidth  = 1920;
const PuglSpan defaultHeight = 1080;

puglSetViewString(view, PUGL_WINDOW_TITLE, "My Window");
puglSetSizeHint(view, PUGL_DEFAULT_SIZE, 1920, 1080);
puglSetSizeHint(view, PUGL_MIN_SIZE, 640, 480);
puglSetSizeHint(view, PUGL_MIN_ASPECT, 1, 1);
puglSetSizeHint(view, PUGL_MAX_ASPECT, 16, 9);

There are also several hints for basic attributes that can be set:

puglSetViewHint(view, PUGL_RESIZABLE, PUGL_TRUE);


To embed the view in another window, you will need to somehow get the native view handle for the parent, then set it with puglSetParentWindow(). If the parent is a Pugl view, the native handle can be accessed with puglGetNativeView(). For example:

puglSetParentWindow(view, puglGetNativeView(parent));

Setting an Event Handler

In order to actually do anything, a view must process events from the system. Pugl dispatches all events to a single event handling function, which is set with puglSetEventFunc():

puglSetEventFunc(view, onEvent);

See Handling Events for details on writing the event handler itself.

Setting View Data

Since the event handler is called with only a view pointer and an event, there needs to be some way to access application data associated with the view. Similar to setting application data, this is done by setting an opaque handle on the view with puglSetHandle(), for example:

puglSetHandle(view, myViewData);

The handle can be later retrieved, likely in the event handler, with puglGetHandle():

MyViewData* data = (MyViewData*)puglGetHandle(view);

All non-constant data should be accessed via this handle, to avoid problems associated with static mutable data.

If data is also associated with the world, it can be retrieved via the view using puglGetWorld():

PuglWorld* world = puglGetWorld(view);
MyApp*     app   = (MyApp*)puglGetWorldHandle(world);

Setting a Backend

Before being realized, the view must have a backend set with puglSetBackend().

The backend manages the graphics API that will be used for drawing. Pugl includes backends and supporting API for Cairo, OpenGL, and Vulkan.

Using Cairo

Cairo-specific API is declared in the cairo.h header:

#include <pugl/cairo.h>

The Cairo backend is provided by puglCairoBackend():

puglSetBackend(view, puglCairoBackend());

No additional configuration is required for Cairo. To draw when handling an expose event, the Cairo context can be accessed with puglGetContext():

cairo_t* cr = (cairo_t*)puglGetContext(view);
Using OpenGL

OpenGL-specific API is declared in the gl.h header:

#include <pugl/gl.h>

The OpenGL backend is provided by puglGlBackend():

puglSetBackend(view, puglGlBackend());

Some hints must also be set so that the context can be set up correctly. For example, to use OpenGL 3.3 Core Profile:

puglSetViewHint(view, PUGL_CONTEXT_VERSION_MAJOR, 3);
puglSetViewHint(view, PUGL_CONTEXT_VERSION_MINOR, 3);

If you need to perform some setup using the OpenGL API, there are two ways to do so.

The OpenGL context is active when PUGL_REALIZE and PUGL_UNREALIZE events are dispatched, so things like creating and destroying shaders and textures can be done then.

Alternatively, if it is cumbersome to set up and tear down OpenGL in the event handler, puglEnterContext() and puglLeaveContext() can be used to manually activate the OpenGL context during application setup. Note, however, that unlike many other APIs, these functions must not be used for drawing. It is only valid to use the OpenGL API for configuration in a manually entered context, rendering will not work. For example:


while (!myApp->quit) {
  puglUpdate(world, 0.0);

Using Vulkan

Vulkan-specific API is declared in the vulkan.h header. This header includes Vulkan headers, so if you are dynamically loading Vulkan at runtime, you should define VK_NO_PROTOTYPES before including it.


#include <pugl/vulkan.h>

The Vulkan backend is provided by puglVulkanBackend():

puglSetBackend(view, puglVulkanBackend());

Unlike OpenGL, almost all Vulkan configuration is done using the Vulkan API directly. Pugl only provides a portable mechanism to load the Vulkan library and get the functions used to load the rest of the Vulkan API.

Loading Vulkan

For maximum compatibility, it is best to not link to Vulkan at compile-time, but instead load the Vulkan API at run-time. To do so, first create a PuglVulkanLoader:

PuglVulkanLoader* loader = puglNewVulkanLoader(world, NULL);

The loader manages the dynamically loaded Vulkan library, so it must be kept alive for as long as the application is using Vulkan. You can get the function used to load Vulkan functions with puglGetInstanceProcAddrFunc():

PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =

This vkGetInstanceProcAddr function can be used to load the rest of the Vulkan API. For example, you can use it to get the vkCreateInstance function, then use that to create your Vulkan instance. In practice, you will want to use some loader or wrapper API since there are many Vulkan functions.

For advanced situations, there is also puglGetDeviceProcAddrFunc() which retrieves the vkGetDeviceProcAddr function instead.

The Vulkan loader is provided for convenience, so that applications to not need to write platform-specific code to load Vulkan. Its use it not mandatory and Pugl can be used with Vulkan loaded by some other method.

Linking with Vulkan

If you do want to link to the Vulkan library at compile time, note that the Pugl Vulkan backend does not depend on it, so you will have to do so explicitly.

Creating a Surface

The details of using Vulkan are far beyond the scope of this documentation, but Pugl provides a portable function, puglCreateSurface(), to get the Vulkan surface for a view. Assuming you have somehow created your VkInstance, you can get the surface for a view using puglCreateSurface():

VkSurfaceKHR* surface = NULL;

Showing the View

Once the view is configured, it can be “realized” with puglRealize(). This creates a “real” system view, for example:

PuglStatus status = puglRealize(view);
if (status) {
  fprintf(stderr, "Error realizing view (%s)\n", puglStrerror(status));

Note that realizing a view can fail for many reasons, so the return code should always be checked. This is generally the case for any function that interacts with the window system. Most functions also return a PuglStatus, but these checks are omitted for brevity in the rest of this documentation.

A realized view is not initially visible, but can be shown with puglShow():


To create an initially visible view, it is also possible to simply call puglShow() right away. The view will be automatically realized if necessary.


Handling Events

Events are sent to a view when it has received user input, must be drawn, or in other situations that may need to be handled such as resizing.

Events are sent to the event handler as a PuglEvent union. The type field defines the type of the event and which field of the union is active. The application must handle at least PUGL_CONFIGURE and PUGL_EXPOSE to draw anything, but there are many other event types.

For example, a basic event handler might look something like this:

static PuglStatus
onEvent(PuglView* view, const PuglEvent* event)
  MyApp* app = (MyApp*)puglGetHandle(view);

  switch (event->type) {
    return setupGraphics(app);
    return teardownGraphics(app);
    return resize(app, event->configure.width, event->configure.height);
    return draw(app, view);
  case PUGL_CLOSE:
    return quit(app);
     return onButtonPress(app, view, event->button);

  return PUGL_SUCCESS;

Using the Graphics Context


Note that Pugl uses a different drawing model than many libraries, particularly those designed for game-style main loops like SDL and GLFW.

In that style of code, drawing is performed imperatively in the main loop, but with Pugl, the application must draw only while handling an expose event. This is because Pugl supports event-driven applications that only draw the damaged region when necessary, and handles exposure internally to provide optimized and consistent behavior across platforms.

Cairo Context

A Cairo context is created for each PuglExposeEvent, and only exists during the handling of that event. Null is returned by puglGetContext() at any other time.

OpenGL Context

The OpenGL context is only active during the handling of these events:

As always, drawing is only possible during an expose.

Vulkan Context

With Vulkan, the graphics context is managed by the application rather than Pugl. However, drawing must still only be performed during an expose.

Driving the Event Loop

Pugl does not contain any threads or other event loop “magic”. For flexibility, the event loop is driven explicitly by repeatedly calling puglUpdate(), which processes events from the window system and dispatches them to views when necessary.

The exact use of puglUpdate() depends on the application. Plugins should call it with a timeout of 0 in a callback driven by the host. This avoids blocking the main loop, since other plugins and the host itself need to run as well.

A program can use whatever timeout is appropriate: event-driven applications may wait forever by using a timeout of -1, while those that draw continuously may use a significant fraction of the frame period (with enough time left over to render).


Occasional redrawing can be requested by calling puglPostRedisplay() or puglPostRedisplayRect(). After these are called, a PuglExposeEvent will be dispatched on the next call to puglUpdate().

For continuous redrawing, call puglPostRedisplay() while handling a PuglUpdateEvent event. This event is sent just before views are redrawn, so it can be used as a hook to expand the update region right before the view is exposed. Anything else that needs to be done every frame can be handled similarly.

Event Dispatching

Ideally, pending events are dispatched during a call to puglUpdate(), directly within the scope of that call.

Unfortunately, this is not universally true due to differences between platforms.


On MacOS, drawing is handled specially and not by the normal event queue mechanism. This means that configure and expose events, and possibly others, may be dispatched to a view outside the scope of a puglUpdate() call. In general, you can not rely on coherent event dispatching semantics on MacOS: the operating system can call into application code at “random” times, and these calls may result in Pugl events being dispatched.

An application that follows the Pugl guidelines should work fine, but there is one significant inconsistency you may encounter on MacOS: posting a redisplay will not wake up a blocked puglUpdate() call.


On Windows, the application has relatively tight control over the event loop, so events are typically dispatched explicitly by puglUpdate(). Drawing is handled by events, so posting a redisplay will wake up a blocked puglUpdate() call.

However, it is possible for the system to dispatch events at other times. So, it is possible for events to be dispatched outside the scope of a puglUpdate() call, but this does not happen in normal circumstances and can largely be ignored.


On X11, the application strictly controls event dispatching, and there is no way for the system to call into application code at surprising times. So, all events are dispatched in the scope of a puglUpdate() call.

Recursive Event Loops

On Windows and MacOS, the event loop is stalled while the user is resizing the window or, on Windows, has displayed the window menu. This means that puglUpdate() will block until the resize is finished, or the menu is closed.

Pugl dispatches PuglLoopEnterEvent and PuglLoopLeaveEvent events to notify the application of this situation. If you want to continuously redraw during resizing on these platforms, you can schedule a timer with puglStartTimer() when the recursive loop is entered, and post redisplays when handling the PuglTimerEvent. Be sure to remove the timer with puglStopTimer() when the recursive loop is finished.

On X11, there are no recursive event loops, and everything works as usual while the user is resizing the window. There is nothing special about a “live resize” on X11, and the above loop events will never be dispatched.

Using Clipboards

Clipboards provide a way to transfer data between different views, including views in different processes. A clipboard transfer is a multi-step event-driven process, where the sender and receiver can negotiate a mutually supported data format.


Data can be copied to the general clipboard with puglSetClipboard(). The MIME type of the data must be specified. Commonly supported types are text/plain for plain text, and text/uri-list for lists of URIs (including local files).

For example, a string can be copied to the clipboard by setting the general clipboard to text/plain data:

const char* someString = "Copied string";



Data from a clipboard can be pasted to a view using puglPaste():


This initiates a data transfer from the clipboard to the view if possible. If data is available, the view will be sent a PUGL_DATA_OFFER event to begin the transfer.

Receiving Data

A data transfer from a clipboard to a view begins with the view receiving a PUGL_DATA_OFFER event. This indicates that data (possibly in several formats) is being offered to a view, which can either “accept” or “reject” it:

  onDataOffer(view, &event->offer);

When handling this event, puglGetNumClipboardTypes() and puglGetClipboardType() can be used to enumerate the available data types:

static void
onDataOffer(PuglView* view, const PuglEventDataOffer* event)
  size_t numTypes = puglGetNumClipboardTypes(view, clipboard);

  for (uint32_t t = 0; t < numTypes; ++t) {
    const char* type = puglGetClipboardType(view, t);
    printf("Offered type: %s\n", type);

If the view supports one of the data types, it can accept the offer with puglAcceptOffer():

for (uint32_t t = 0; t < numTypes; ++t) {
  const char* type = puglGetClipboardType(view, t);
  if (!strcmp(type, "text/uri-list")) {
    puglAcceptOffer(view, event, t);

When an offer is accepted, the data will be transferred and converted if necessary, then the view will be sent a PUGL_DATA event. When the data event is received, the data can be fetched with puglGetClipboard():

  onData(view, &event->data);

// ...

static void
onData(PuglView* view, const PuglEventData* event)
  uint32_t typeIndex = event->typeIndex;

  const char* type = puglGetClipboardType(view, typeIndex);

  fprintf(stderr, "Received data type: %s\n", type);

  if (!strcmp(type, "text/plain")) {
    size_t      len  = 0;
    const void* data = puglGetClipboard(view, typeIndex, &len);

    printf("Dropped: %s\n", (const char*)data);

Shutting Down

When a view is closed, it will receive a PuglCloseEvent. An application may also set a flag based on user input or other conditions, which can be used to break out of the main loop and stop calling puglUpdate().

When the main event loop has finished running, any views and the world need to be destroyed, in that order. For example:


Pugl C API

Pugl C API.


Cairo graphics support.

const PuglBackend *puglCairoBackend(void)

Cairo graphics backend accessor.

Pass the returned value to puglSetBackend() to draw to a view with Cairo.


OpenGL graphics support.

typedef void (*PuglGlFunc)(void)

OpenGL extension function.

PuglGlFunc puglGetProcAddress(const char *name)

Return the address of an OpenGL extension function.

PuglStatus puglEnterContext(PuglView *view)

Enter the OpenGL context.

This can be used to enter the graphics context in unusual situations, for doing things like loading textures. Note that this must not be used for drawing, which may only be done while processing an expose event.

PuglStatus puglLeaveContext(PuglView *view)

Leave the OpenGL context.

This must only be called after puglEnterContext().

const PuglBackend *puglGlBackend(void)

OpenGL graphics backend.

Pass the returned value to puglSetBackend() to draw to a view with OpenGL.

Geometry Types

struct PuglRect

A rectangle in a view or on the screen.

This type is used to describe two things: the position and size of a view (for configuring), or a rectangle within a view (for exposing).

The coordinate (0, 0) represents the top-left pixel of the parent window (or display if there isn’t one), or the top-left pixel of the view, respectively.

enum PuglStringHint

A string property for configuration.

enumerator PUGL_CLASS_NAME

The application class name.

This is a stable identifier for the application, which should be a short camel-case name like “MyApp”. This should be the same for every instance of the application, but different from any other application. On X11 and Windows, it is used to set the class name of windows (that underlie realized views), which is used for things like loading configuration, or custom window management rules.


The title of the window or application.

This is used by the system to display a title for the application or window, for example in title bars or window/application switchers. It is only used to display a label to the user, not as an identifier, and can change over time to reflect the current state of the application. For example, it is common for programs to add the name of the current document, like “myfile.txt - Fancy Editor”.

typedef int16_t PuglCoord

A pixel coordinate within/of a view.

This is relative to the top left corner of the view’s parent, or to the top left corner of the view itself, depending on the context.

There are platform-imposed limits on window positions. For portability, applications should keep coordinates between -16000 and 16000. Note that negative frame coordinates are possible, for example with multiple screens.

typedef uint16_t PuglSpan

A pixel span (width or height) within/of a view.

Due to platform limits, the span of a view in either dimension should be between 1 and 10000.


The number of PuglStringHint values.


All updates to the view happen via events, which are dispatched to the view’s event function.

An event is a tagged union with a type, and a set of more specific fields depending on the type.

Management Events

struct PuglConfigureEvent

View resize or move event.

A configure event is sent whenever the view is resized or moved. When a configure event is received, the graphics context is active but not set up for drawing. For example, it is valid to adjust the OpenGL viewport or otherwise configure the context, but not to draw anything.

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

PuglCoord x

Parent-relative X coordinate of view.

PuglCoord y

Parent-relative Y coordinate of view.

PuglSpan width

Width of view.

PuglSpan height

Height of view.

PuglViewStyleFlags style

Bitwise OR of PuglViewStyleFlag flags.

enum PuglViewStyleFlag

View style flags.

Style flags reflect special modes and states supported by the window system. Applications should ideally use a single main view, but can monitor or manipulate style flags to better integrate with the window system.


View is mapped to a real window and potentially visible.


View is modal, typically a dialog box of its transient parent.


View should be above most others.


View should be below most others.


View is minimized, shaded, or otherwise invisible.


View is maximized to fill the screen vertically.


View is maximized to fill the screen horizontally.


View is enlarged to fill the entire screen with no decorations.


View is being resized.


View is ready for input or otherwise demanding attention.

typedef uint32_t PuglViewStyleFlags

Bitwise OR of PuglViewStyleFlag values.

typedef PuglAnyEvent PuglRealizeEvent

View realize event.

This event is sent when a view is realized before it is first displayed, with the graphics context entered. This is typically used for setting up the graphics system, for example by loading OpenGL extensions.

This event type has no extra fields.

typedef PuglAnyEvent PuglUnrealizeEvent

View unrealize event.

This event is the counterpart to PuglRealizeEvent, and is sent when the view will no longer be displayed. This is typically used for tearing down the graphics system, or otherwise freeing any resources allocated when the realize event was handled.

This event type has no extra fields.

typedef PuglAnyEvent PuglLoopEnterEvent

Recursive loop enter event.

This event is sent when the window system enters a recursive loop. The main loop will be stalled and no expose events will be received while in the recursive loop. To give the application full control, Pugl does not do any special handling of this situation, but this event can be used to install a timer to perform continuous actions (such as drawing) on platforms that do this.

  • MacOS: A recursive loop is entered while the window is being live resized.

  • Windows: A recursive loop is entered while the window is being live resized or the menu is shown.

  • X11: A recursive loop is never entered and the event loop runs as usual while the view is being resized.

This event type has no extra fields.

typedef PuglAnyEvent PuglLoopLeaveEvent

Recursive loop leave event.

This event is sent after a loop enter event when the recursive loop is finished and normal iteration will continue.

This event type has no extra fields.

typedef PuglAnyEvent PuglCloseEvent

View close event.

This event is sent when the view is to be closed, for example when the user clicks the close button.

This event type has no extra fields.


The maximum PuglViewStyleFlag value.

Update Events

struct PuglExposeEvent

Expose event for when a region must be redrawn.

When an expose event is received, the graphics context is active, and the view must draw the entire specified region. The contents of the region are undefined, there is no preservation of anything drawn previously.

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

PuglCoord x

View-relative top-left X coordinate of region.

PuglCoord y

View-relative top-left Y coordinate of region.

PuglSpan width

Width of exposed region.

PuglSpan height

Height of exposed region.

typedef PuglAnyEvent PuglUpdateEvent

View update event.

This event is sent to every view near the end of a main loop iteration when any pending exposures are about to be redrawn. It is typically used to mark regions to expose with puglPostRedisplay() or puglPostRedisplayRect(). For example, to continuously animate, a view calls puglPostRedisplay() when an update event is received, and it will then shortly receive an expose event.

Keyboard Events

struct PuglFocusEvent

Keyboard focus event.

This event is sent whenever the view gains or loses the keyboard focus. The view with the keyboard focus will receive any key press or release events.

PuglEventType type

PuglEventType.PUGL_FOCUS_IN or PuglEventType.PUGL_FOCUS_OUT

PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

PuglCrossingMode mode

Reason for focus change.

struct PuglKeyEvent

Key press or release event.

This event represents low-level key presses and releases. This can be used for “direct” keyboard handing like key bindings, but must not be interpreted as text input.

Keys are represented portably as Unicode code points, using the “natural” code point for the key where possible (see PuglKey for details). The key field is the code for the pressed key, without any modifiers applied. For example, a press or release of the ‘A’ key will have key 97 (‘a’) regardless of whether shift or control are being held.

Alternatively, the raw keycode can be used to work directly with physical keys, but note that this value is not portable and differs between platforms and hardware.

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

double time

Time in seconds.

double x

View-relative X coordinate.

double y

View-relative Y coordinate.

double xRoot

Root-relative X coordinate.

double yRoot

Root-relative Y coordinate.

PuglMods state

Bitwise OR of PuglMod flags.

uint32_t keycode

Raw key code.

uint32_t key

Unshifted Unicode character code, or 0.

struct PuglTextEvent

Character input event.

This event represents text input, usually as the result of a key press. The text is given both as a Unicode character code and a UTF-8 string.

Note that this event is generated by the platform’s input system, so there is not necessarily a direct correspondence between text events and physical key presses. For example, with some input methods a sequence of several key presses will generate a single character.

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

double time

Time in seconds.

double x

View-relative X coordinate.

double y

View-relative Y coordinate.

double xRoot

Root-relative X coordinate.

double yRoot

Root-relative Y coordinate.

PuglMods state

Bitwise OR of PuglMod flags.

uint32_t keycode

Raw key code.

uint32_t character

Unicode character code.

char string[8]

UTF-8 string.

enum PuglKey

Keyboard key codepoints.

All keys are identified by a Unicode code point in PuglKeyEvent.key. This enumeration defines constants for special keys that do not have a standard code point, and some convenience constants for control characters. Note that all keys are handled in the same way, this enumeration is just for convenience when writing hard-coded key bindings.

Keys that do not have a standard code point use values in the Private Use Area in the Basic Multilingual Plane (U+E000 to U+F8FF). Applications must take care to not interpret these values beyond key detection, the mapping used here is arbitrary and specific to Pugl.



enumerator PUGL_KEY_TAB


enumerator PUGL_KEY_ENTER


enumerator PUGL_KEY_ESCAPE


enumerator PUGL_KEY_DELETE


enumerator PUGL_KEY_SPACE


enumerator PUGL_KEY_F1


enumerator PUGL_KEY_F2


enumerator PUGL_KEY_F3


enumerator PUGL_KEY_F4


enumerator PUGL_KEY_F5


enumerator PUGL_KEY_F6


enumerator PUGL_KEY_F7


enumerator PUGL_KEY_F8


enumerator PUGL_KEY_F9


enumerator PUGL_KEY_F10


enumerator PUGL_KEY_F11


enumerator PUGL_KEY_F12


enumerator PUGL_KEY_PAGE_UP

Page Up.


Page Down.

enumerator PUGL_KEY_END


enumerator PUGL_KEY_HOME


enumerator PUGL_KEY_LEFT


enumerator PUGL_KEY_UP


enumerator PUGL_KEY_RIGHT


enumerator PUGL_KEY_DOWN



Print Screen.

enumerator PUGL_KEY_INSERT


enumerator PUGL_KEY_PAUSE


enumerator PUGL_KEY_MENU


enumerator PUGL_KEY_NUM_LOCK

Num Lock.


Scroll Lock.


Caps Lock.

enumerator PUGL_KEY_SHIFT_L

Left Shift.

enumerator PUGL_KEY_SHIFT_R

Right Shift.

enumerator PUGL_KEY_CTRL_L

Left Control.

enumerator PUGL_KEY_CTRL_R

Right Control.

enumerator PUGL_KEY_ALT_L

Left Alt.

enumerator PUGL_KEY_ALT_R

Right Alt / AltGr.

enumerator PUGL_KEY_SUPER_L

Left Super.

enumerator PUGL_KEY_SUPER_R

Right Super.

enumerator PUGL_KEY_PAD_0

Keypad 0.

enumerator PUGL_KEY_PAD_1

Keypad 1.

enumerator PUGL_KEY_PAD_2

Keypad 2.

enumerator PUGL_KEY_PAD_3

Keypad 3.

enumerator PUGL_KEY_PAD_4

Keypad 4.

enumerator PUGL_KEY_PAD_5

Keypad 5.

enumerator PUGL_KEY_PAD_6

Keypad 6.

enumerator PUGL_KEY_PAD_7

Keypad 7.

enumerator PUGL_KEY_PAD_8

Keypad 8.

enumerator PUGL_KEY_PAD_9

Keypad 9.


Keypad Enter.


Keypad Page Up.


Keypad Page Down.

enumerator PUGL_KEY_PAD_END

Keypad End.

enumerator PUGL_KEY_PAD_HOME

Keypad Home.

enumerator PUGL_KEY_PAD_LEFT

Keypad Left.

enumerator PUGL_KEY_PAD_UP

Keypad Up.


Keypad Right.

enumerator PUGL_KEY_PAD_DOWN

Keypad Down.


Keypad Clear/Begin.


Keypad Insert.


Keypad Delete.


Keypad Equal.


Keypad Multiply.

enumerator PUGL_KEY_PAD_ADD

Keypad Add.


Keypad Separator.


Keypad Subtract.


Keypad Decimal.


Keypad Divide.

enum PuglMod

Keyboard modifier flags.

enumerator PUGL_MOD_SHIFT

Shift pressed.

enumerator PUGL_MOD_CTRL

Control pressed.

enumerator PUGL_MOD_ALT

Alt/Option pressed.

enumerator PUGL_MOD_SUPER

Super/Command/Windows pressed.

enumerator PUGL_MOD_NUM_LOCK

Num lock enabled.


Scroll lock enabled.


Caps lock enabled.

typedef uint32_t PuglMods

Bitwise OR of PuglMod values.

Pointer Events

struct PuglCrossingEvent

Pointer enter or leave event.

This event is sent when the pointer enters or leaves the view. This can happen for several reasons (not just the user dragging the pointer over the window edge), as described by the mode field.

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

double time

Time in seconds.

double x

View-relative X coordinate.

double y

View-relative Y coordinate.

double xRoot

Root-relative X coordinate.

double yRoot

Root-relative Y coordinate.

PuglMods state

Bitwise OR of PuglMod flags.

PuglCrossingMode mode

Reason for crossing.

struct PuglButtonEvent

Button press or release event.

Button numbers start from 0, and are ordered: primary, secondary, middle. So, on a typical right-handed mouse, the button numbers are:

Left: 0 Right: 1 Middle (often a wheel): 2

Higher button numbers are reported in the same order they are represented on the system. There is no universal standard here, but buttons 3 and 4 are typically a pair of buttons or a rocker, which are usually bound to “back” and “forward” operations.

Note that these numbers may differ from those used on the underlying platform, since they are manipulated to provide a consistent portable API.

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

double time

Time in seconds.

double x

View-relative X coordinate.

double y

View-relative Y coordinate.

double xRoot

Root-relative X coordinate.

double yRoot

Root-relative Y coordinate.

PuglMods state

Bitwise OR of PuglMod flags.

uint32_t button

Button number starting from 0.

struct PuglMotionEvent

Pointer motion event.

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

double time

Time in seconds.

double x

View-relative X coordinate.

double y

View-relative Y coordinate.

double xRoot

Root-relative X coordinate.

double yRoot

Root-relative Y coordinate.

PuglMods state

Bitwise OR of PuglMod flags.

struct PuglScrollEvent

Scroll event.

The scroll distance is expressed in “lines”, an arbitrary unit that corresponds to a single tick of a detented mouse wheel. For example, dy = 1.0 scrolls 1 line up. Some systems and devices support finer resolution and/or higher values for fast scrolls, so programs should handle any value gracefully.

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

double time

Time in seconds.

double x

View-relative X coordinate.

double y

View-relative Y coordinate.

double xRoot

Root-relative X coordinate.

double yRoot

Root-relative Y coordinate.

PuglMods state

Bitwise OR of PuglMod flags.

PuglScrollDirection direction

Scroll direction.

double dx

Scroll X distance in lines.

double dy

Scroll Y distance in lines.

enum PuglScrollDirection

Scroll direction.

Describes the direction of a PuglScrollEvent along with whether the scroll is a “smooth” scroll. The discrete directions are for devices like mouse wheels with constrained axes, while a smooth scroll is for those with arbitrary scroll direction freedom, like some touchpads.

enumerator PUGL_SCROLL_UP

Scroll up.


Scroll down.


Scroll left.


Scroll right.


Smooth scroll in any direction.

Custom Events

struct PuglClientEvent

Custom client message event.

This can be used to send a custom message to a view, which is delivered via the window system and processed in the event loop as usual. Among other things, this makes it possible to wake up the event loop for any reason.

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

uintptr_t data1

Client-specific data.

uintptr_t data2

Client-specific data.

struct PuglTimerEvent

Timer event.

This event is sent at the regular interval specified in the call to puglStartTimer() that activated it.

The id is the application-specific ID given to puglStartTimer() which distinguishes this timer from others. It should always be checked in the event handler, even in applications that register only one timer.

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

uintptr_t id

Timer ID.

Clipboard Events

struct PuglDataOfferEvent

Clipboard data offer event.

This event is sent when a clipboard has data present, possibly with several datatypes. While handling this event, the types can be investigated with puglGetClipboardType() to decide whether to accept the offer with puglAcceptOffer().

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

double time

Time in seconds.

struct PuglDataEvent

Clipboard data event.

This event is sent after accepting a data offer when the data has been retrieved and converted. While handling this event, the data can be accessed with puglGetClipboard().

PuglEventType type


PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

double time

Time in seconds.

uint32_t typeIndex

Index of datatype.

struct PuglAnyEvent

Common header for all event structs.

PuglEventType type

Event type.

PuglEventFlags flags

Bitwise OR of PuglEventFlag values.

union PuglEvent

View event.

This is a union of all event types. The type must be checked to determine which fields are safe to access. A pointer to PuglEvent can either be cast to the appropriate type, or the union members used.

The graphics system may only be accessed when handling certain events. The graphics context is active for PuglEventType.PUGL_REALIZE, PuglEventType.PUGL_UNREALIZE, PuglEventType.PUGL_CONFIGURE, and PuglEventType.PUGL_EXPOSE, but only enabled for drawing for PuglEventType.PUGL_EXPOSE.

PuglAnyEvent any

Valid for all event types.

PuglEventType type

Event type.

PuglButtonEvent button


PuglConfigureEvent configure


PuglExposeEvent expose


PuglKeyEvent key


PuglTextEvent text


PuglCrossingEvent crossing


PuglMotionEvent motion


PuglScrollEvent scroll


PuglFocusEvent focus


PuglClientEvent client


PuglTimerEvent timer


PuglDataOfferEvent offer


PuglDataEvent data


enum PuglEventType

The type of a PuglEvent.

enumerator PUGL_NOTHING

No event.

enumerator PUGL_REALIZE

View realized, a PuglRealizeEvent.


View unrealizeed, a PuglUnrealizeEvent.


View configured, a PuglConfigureEvent.

enumerator PUGL_UPDATE

View ready to draw, a PuglUpdateEvent.

enumerator PUGL_EXPOSE

View must be drawn, a PuglExposeEvent.

enumerator PUGL_CLOSE

View will be closed, a PuglCloseEvent.

enumerator PUGL_FOCUS_IN

Keyboard focus entered view, a PuglFocusEvent.

enumerator PUGL_FOCUS_OUT

Keyboard focus left view, a PuglFocusEvent.

enumerator PUGL_KEY_PRESS

Key pressed, a PuglKeyEvent.


Key released, a PuglKeyEvent.

enumerator PUGL_TEXT

Character entered, a PuglTextEvent.

enumerator PUGL_POINTER_IN

Pointer entered view, a PuglCrossingEvent.


Pointer left view, a PuglCrossingEvent.


Mouse button pressed, a PuglButtonEvent.


Mouse button released, a PuglButtonEvent.

enumerator PUGL_MOTION

Pointer moved, a PuglMotionEvent.

enumerator PUGL_SCROLL

Scrolled, a PuglScrollEvent.

enumerator PUGL_CLIENT

Custom client message, a PuglClientEvent.

enumerator PUGL_TIMER

Timer triggered, a PuglTimerEvent.

enumerator PUGL_LOOP_ENTER

Recursive loop entered, a PuglLoopEnterEvent.

enumerator PUGL_LOOP_LEAVE

Recursive loop left, a PuglLoopLeaveEvent.

enumerator PUGL_DATA_OFFER

Data offered from clipboard, a PuglDataOfferEvent.

enumerator PUGL_DATA

Data available from clipboard, a PuglDataEvent.

enum PuglEventFlag

Common flags for all event types.


Event is synthetic.

enumerator PUGL_IS_HINT

Event is a hint (not direct user input)

enum PuglCrossingMode

Reason for a PuglCrossingEvent.


Crossing due to pointer motion.


Crossing due to a grab.


Crossing due to a grab release.

typedef uint32_t PuglEventFlags

Bitwise OR of PuglEventFlag values.


Most functions return a status code which can be used to check for errors.

enum PuglStatus

Return status code.

enumerator PUGL_SUCCESS


enumerator PUGL_FAILURE

Non-fatal failure.


Unknown system error.


Invalid or missing backend.


Invalid view configuration.


Invalid parameter.


Backend initialization failed.


Class registration failed.


System view realization failed.


Failed to set pixel format.


Failed to create drawing context.


Unsupported operation.

enumerator PUGL_NO_MEMORY

Failed to allocate memory.

const char *puglStrerror(PuglStatus status)

Return a string describing a status code.


The top-level context of a Pugl application or plugin.

The world contains all library-wide state. There is no static data in Pugl, so it is safe to use multiple worlds in a single process. This is to facilitate plugins or other situations where it is not possible to share a world, but a single world should be shared for all views where possible.

enum PuglWorldType

The type of a World.

enumerator PUGL_PROGRAM

Top-level application.

enumerator PUGL_MODULE

Plugin or module within a larger application.

enum PuglWorldFlag

World flags.


Set up support for threads if necessary.

X11: Calls XInitThreads() which is required for some drivers.

typedef struct PuglWorldImpl PuglWorld

The “world” of application state.

The world represents everything that is not associated with a particular view. Several worlds can be created in a single process, but code using different worlds must be isolated so they are never mixed. Views are strongly associated with the world they were created in.

typedef void *PuglWorldHandle

Handle for the world’s opaque user data.

typedef uint32_t PuglWorldFlags

Bitwise OR of PuglWorldFlag values.

PuglWorld *puglNewWorld(PuglWorldType type, PuglWorldFlags flags)

Create a new world.

  • type – The type, which dictates what this world is responsible for.

  • flags – Flags to control world features.


A new world, which must be later freed with puglFreeWorld().

void puglFreeWorld(PuglWorld *world)

Free a world allocated with puglNewWorld()

void puglSetWorldHandle(PuglWorld *world, PuglWorldHandle handle)

Set the user data for the world.

This is usually a pointer to a struct that contains all the state which must be accessed by several views.

The handle is opaque to Pugl and is not interpreted in any way.

PuglWorldHandle puglGetWorldHandle(PuglWorld *world)

Get the user data for the world.

void *puglGetNativeWorld(PuglWorld *world)

Return a pointer to the native handle of the world.

X11: Returns a pointer to the Display.

MacOS: Returns a pointer to the NSApplication.

Windows: Returns the HMODULE of the calling process.

PuglStatus puglSetWorldString(PuglWorld *world, PuglStringHint key, const char *value)

Set a string property to configure the world or application.

The string value only needs to be valid for the duration of this call, it will be copied if necessary.

const char *puglGetWorldString(const PuglWorld *world, PuglStringHint key)

Get a world or application string property.

The returned string should be accessed immediately, or copied. It may become invalid upon any call to any function that manipulates the same view.

double puglGetTime(const PuglWorld *world)

Return the time in seconds.

This is a monotonically increasing clock with high resolution. The returned time is only useful to compare against other times returned by this function, its absolute value has no meaning.

PuglStatus puglUpdate(PuglWorld *world, double timeout)

Update by processing events from the window system.

This function is a single iteration of the main loop, and should be called repeatedly to update all views.

If timeout is zero, then this function will not block. Plugins should always use a timeout of zero to avoid blocking the host.

If a positive timeout is given, then events will be processed for that amount of time, starting from when this function was called.

If a negative timeout is given, this function will block indefinitely until an event occurs.

For continuously animating programs, a timeout that is a reasonable fraction of the ideal frame period should be used, to minimize input latency by ensuring that as many input events are consumed as possible before drawing.


PuglStatus.PUGL_SUCCESS if events are read, PuglStatus.PUGL_FAILURE if no events are read, or an error.


A drawable region that receives events.

A view can be thought of as a window, but does not necessarily correspond to a top-level window in a desktop environment. For example, a view can be embedded in some other window, or represent an embedded system where there is no concept of multiple windows at all.


Functions for creating and destroying a view.

PuglView *puglNewView(PuglWorld *world)

Create a new view.

A newly created view does not correspond to a real system view or window. It must first be configured, then the system view can be created with puglRealize().

void puglFreeView(PuglView *view)

Free a view created with puglNewView()

PuglWorld *puglGetWorld(PuglView *view)

Return the world that view is a part of.

void puglSetHandle(PuglView *view, PuglHandle handle)

Set the user data for a view.

This is usually a pointer to a struct that contains all the state which must be accessed by a view. Everything needed to process events should be stored here, not in static variables.

The handle is opaque to Pugl and is not interpreted in any way.

PuglHandle puglGetHandle(PuglView *view)

Get the user data for a view.

PuglStatus puglSetBackend(PuglView *view, const PuglBackend *backend)

Set the graphics backend to use for a view.

This must be called once to set the graphics backend before calling puglRealize().

Pugl includes the following backends:

Note that backends are modular and not compiled into the main Pugl library to avoid unnecessary dependencies. To use a particular backend, applications must link against the appropriate backend library, or be sure to compile in the appropriate code if using a local copy of Pugl.

const PuglBackend *puglGetBackend(const PuglView *view)

Return the graphics backend used by a view.

PuglStatus puglSetEventFunc(PuglView *view, PuglEventFunc eventFunc)

Set the function to call when an event occurs.

PuglStatus puglSetViewHint(PuglView *view, PuglViewHint hint, int value)

Set a hint to configure view properties.

This only has an effect when called before puglRealize().

int puglGetViewHint(const PuglView *view, PuglViewHint hint)

Get the value for a view hint.

If the view has been realized, this can be used to get the actual value of a hint which was initially set to PUGL_DONT_CARE, or has been adjusted from the suggested value.

PuglStatus puglSetViewString(PuglView *view, PuglStringHint key, const char *value)

Set a string property to configure view properties.

This is similar to puglSetViewHint() but sets hints with string values. The string value only needs to be valid for the duration of this call, it will be copied if necessary.

const char *puglGetViewString(const PuglView *view, PuglStringHint key)

Get a view string property.

The returned string should be accessed immediately, or copied. It may become invalid upon any call to any function that manipulates the same view.

double puglGetScaleFactor(const PuglView *view)

Return the scale factor of the view.

This factor describe how large UI elements (especially text) should be compared to “normal”. For example, 2.0 means the UI should be drawn twice as large.

“Normal” is loosely defined, but means a good size on a “standard DPI” display (around 96 DPI). In other words, the scale 1.0 should have text that is reasonably sized on a 96 DPI display, and the scale 2.0 should have text twice that large.


Functions for working with the position and size of a view.

PuglRect puglGetFrame(const PuglView *view)

Get the current position and size of the view.

The position is in screen coordinates with an upper left origin.

PuglStatus puglSetFrame(PuglView *view, PuglRect frame)

Set the current position and size of the view.

The position is in screen coordinates with an upper left origin.


PuglStatus.PUGL_UNKNOWN_ERROR on failure, in which case the view frame is unchanged.

PuglStatus puglSetPosition(PuglView *view, int x, int y)

Set the current position of the view.


PuglStatus.PUGL_UNKNOWN_ERROR on failure, in which case the view frame is unchanged.

PuglStatus puglSetSize(PuglView *view, unsigned width, unsigned height)

Set the current size of the view.


PuglStatus.PUGL_UNKNOWN_ERROR on failure, in which case the view frame is unchanged.

PuglStatus puglSetSizeHint(PuglView *view, PuglSizeHint hint, PuglSpan width, PuglSpan height)

Set a size hint for the view.

This can be used to set the default, minimum, and maximum size of a view, as well as the supported range of aspect ratios.

This should be called before puglRealize() so the initial window for the view can be configured correctly.


PuglStatus.PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is not yet realized.


Functions to control the top-level window of a view.

enum PuglShowCommand

A command to control the behaviour of puglShow()


Realize and show the window without intentionally raising it.

This will weakly “show” the window but without making any effort to raise it. Depending on the platform or system configuration, the window may be raised above some others regardless.

enumerator PUGL_SHOW_RAISE

Raise the window to the top of the application’s stack.

This is the normal “well-behaved” way to show and raise the window, which should be used in most cases.


Aggressively force the window to be raised to the top.

This will attempt to raise the window to the top, even if this isn’t the active application, or if doing so would otherwise go against the platform’s guidelines. This generally shouldn’t be used, and isn’t guaranteed to work. On modern Windows systems, the active application must explicitly grant permission for others to steal the foreground from it.

PuglStatus puglSetParentWindow(PuglView *view, PuglNativeView parent)

Set the parent window for embedding a view in an existing window.

This must be called before puglRealize(), reparenting is not supported.

PuglNativeView puglGetParentWindow(const PuglView *view)

Return the parent window this view is embedded in, or null.

PuglStatus puglSetTransientParent(PuglView *view, PuglNativeView parent)

Set the transient parent of the window.

Set this for transient children like dialogs, to have them properly associated with their parent window. This should be called before puglRealize().

A view can either have a parent (for embedding) or a transient parent (for top-level windows like dialogs), but not both.

PuglNativeView puglGetTransientParent(const PuglView *view)

Return the transient parent of the window.


The native handle to the window this view is a transient child of, or null.

PuglStatus puglRealize(PuglView *view)

Realize a view by creating a corresponding system view or window.

After this call, the (initially invisible) underlying system view exists and can be accessed with puglGetNativeView().

The view should be fully configured using the above functions before this is called. This function may only be called once per view.

PuglStatus puglUnrealize(PuglView *view)

Unrealize a view by destroying the corresponding system view or window.

This is the inverse of puglRealize(). After this call, the view no longer corresponds to a real system view, and can be realized again later.

PuglStatus puglShow(PuglView *view, PuglShowCommand command)

Show the view.

If the view has not yet been realized, the first call to this function will do so automatically.

If the view is currently hidden, it will be shown and possibly raised to the top depending on the platform.

PuglStatus puglHide(PuglView *view)

Hide the current window.

PuglStatus puglSetViewStyle(PuglView *view, PuglViewStyleFlags flags)

Set a view state, if supported by the system.

This can be used to manipulate the window into various special states, but note that not all states are supported on all systems. This function may return failure or an error if the platform implementation doesn’t “understand” how to set the given style, but the return value here can’t be used to determine if the state has actually been set. Any changes to the actual state of the view will arrive in later configure events.

PuglViewStyleFlags puglGetViewStyle(const PuglView *view)

Return true if the view currently has a state flag set.

The result is determined based on the state announced in the last configure event.

bool puglGetVisible(const PuglView *view)

Return true iff the view is currently visible.

PuglNativeView puglGetNativeView(PuglView *view)

Return the native window handle.


Functions for working with the graphics context and scheduling redisplays.

void *puglGetContext(PuglView *view)

Get the graphics context.

This is a backend-specific context used for drawing if the backend graphics API requires one. It is only available during an expose.

Cairo: Returns a pointer to a cairo_t.

All other backends: returns null.

PuglStatus puglPostRedisplay(PuglView *view)

Request a redisplay for the entire view.

This will cause an expose event to be dispatched later. If called from within the event handler, the expose should arrive at the end of the current event loop iteration, though this is not strictly guaranteed on all platforms. If called elsewhere, an expose will be enqueued to be processed in the next event loop iteration.

PuglStatus puglPostRedisplayRect(PuglView *view, PuglRect rect)

Request a redisplay of the given rectangle within the view.

This has the same semantics as puglPostRedisplay(), but allows giving a precise region for redrawing only a portion of the view.


Functions for interacting with the user and window system.

enum PuglCursor

A mouse cursor type.

This is a portable subset of mouse cursors that exist on X11, MacOS, and Windows.


Default pointing arrow.


Caret (I-Beam) for text entry.




Hand with a pointing finger.

enumerator PUGL_CURSOR_NO

Operation not allowed.


Left/right arrow for horizontal resize.


Up/down arrow for vertical resize.


Diagonal arrow for down/right resize.


Diagonal arrow for down/left resize.


Omnidirectional “arrow” for scrolling.

PuglStatus puglGrabFocus(PuglView *view)

Grab the keyboard input focus.

Note that this will fail if the view is not mapped and so should not, for example, be called immediately after puglShow().


PuglStatus.PUGL_SUCCESS if the focus was successfully grabbed, or an error.

bool puglHasFocus(const PuglView *view)

Return whether view has the keyboard input focus.

PuglStatus puglPaste(PuglView *view)

Request data from the general copy/paste clipboard.

A PuglEventType.PUGL_DATA_OFFER event will be sent if data is available.

uint32_t puglGetNumClipboardTypes(const PuglView *view)

Return the number of types available for the data in a clipboard.

Returns zero if the clipboard is empty.

const char *puglGetClipboardType(const PuglView *view, uint32_t typeIndex)

Return the identifier of a type available in a clipboard.

This is usually a MIME type, but may also be another platform-specific type identifier. Applications must ignore any type they do not recognize.

Returns null if typeIndex is out of bounds according to puglGetNumClipboardTypes().

PuglStatus puglAcceptOffer(PuglView *view, const PuglDataOfferEvent *offer, uint32_t typeIndex)

Accept data offered from a clipboard.

To accept data, this must be called while handling a PuglEventType.PUGL_DATA_OFFER event. Doing so will request the data from the source as the specified type. When the data is available, a PuglEventType.PUGL_DATA event will be sent to the view which can then retrieve the data with puglGetClipboard().

  • view – The view.

  • offer – The data offer event.

  • typeIndex – The index of the type that the view will accept. This is the typeIndex argument to the call of puglGetClipboardType() that returned the accepted type.

PuglStatus puglSetClipboard(PuglView *view, const char *type, const void *data, size_t len)

Set the clipboard contents.

This sets the system clipboard contents, which can be retrieved with puglGetClipboard() or pasted into other applications.

  • view – The view.

  • type – The MIME type of the data, “text/plain” is assumed if NULL.

  • data – The data to copy to the clipboard.

  • len – The length of data in bytes (including terminator if necessary).

const void *puglGetClipboard(PuglView *view, uint32_t typeIndex, size_t *len)

Get the clipboard contents.

This gets the system clipboard contents, which may have been set with puglSetClipboard() or copied from another application.

  • view – The view.

  • typeIndex – Index of the data type to get the item as.

  • len – Set to the length of the data in bytes.


The clipboard contents, or null.

PuglStatus puglSetCursor(PuglView *view, PuglCursor cursor)

Set the mouse cursor.

This changes the system cursor that is displayed when the pointer is inside the view. May fail if setting the cursor is not supported on this system, for example if compiled on X11 without Xcursor support.


PuglStatus.PUGL_BAD_PARAMETER if the given cursor is invalid, PuglStatus.PUGL_FAILURE if the cursor is known but loading it system fails.

PuglStatus puglStartTimer(PuglView *view, uintptr_t id, double timeout)

Activate a repeating timer event.

This starts a timer which will send a PuglTimerEvent to view every timeout seconds. This can be used to perform some action in a view at a regular interval with relatively low frequency. Note that the frequency of timer events may be limited by how often puglUpdate() is called.

If the given timer already exists, it is replaced.

  • view – The view to begin sending PuglEventType.PUGL_TIMER events to.

  • id – The identifier for this timer. This is an application-specific ID that should be a low number, typically the value of a constant or enum that starts from 0. There is a platform-specific limit to the number of supported timers, and overhead associated with each, so applications should create only a few timers and perform several tasks in one if necessary.

  • timeout – The period, in seconds, of this timer. This is not guaranteed to have a resolution better than 10ms (the maximum timer resolution on Windows) and may be rounded up if it is too short. On X11 and MacOS, a resolution of about 1ms can usually be relied on.


PuglStatus.PUGL_FAILURE if timers are not supported by the system, PuglStatus.PUGL_UNKNOWN_ERROR if setting the timer failed.

PuglStatus puglStopTimer(PuglView *view, uintptr_t id)

Stop an active timer.

  • view – The view that the timer is set for.

  • id – The ID previously passed to puglStartTimer().


PuglStatus.PUGL_FAILURE if timers are not supported by this system, PuglStatus.PUGL_UNKNOWN_ERROR if stopping the timer failed.

PuglStatus puglSendEvent(PuglView *view, const PuglEvent *event)

Send an event to a view via the window system.

If supported, the event will be delivered to the view via the event loop like other events. Note that this function only works for certain event types.

Currently, only PuglEventType.PUGL_CLIENT events are supported on all platforms.

X11: A PuglEventType.PUGL_EXPOSE event can be sent, which is similar to calling puglPostRedisplayRect(), but will always send a message to the X server, even when called in an event handler.


PuglStatus.PUGL_UNSUPPORTED if sending events of this type is not supported, PuglStatus.PUGL_UNKNOWN_ERROR if sending the event failed.


The number of PuglCursor values.

enum PuglViewHint

An integer hint for configuring a view.


OpenGL render API (GL/GLES)


OpenGL context major version.


OpenGL context minor version.


OpenGL context profile (core/compatibility)


OpenGL context debugging enabled.

enumerator PUGL_RED_BITS

Number of bits for red channel.

enumerator PUGL_GREEN_BITS

Number of bits for green channel.

enumerator PUGL_BLUE_BITS

Number of bits for blue channel.

enumerator PUGL_ALPHA_BITS

Number of bits for alpha channel.

enumerator PUGL_DEPTH_BITS

Number of bits for depth buffer.


Number of bits for stencil buffer.


Number of sample buffers (AA)

enumerator PUGL_SAMPLES

Number of samples per pixel (AA)


True if double buffering should be used.


Number of frames between buffer swaps.


True if view should be resizable.


True if key repeat events are ignored.


Refresh rate in Hz.

enumerator PUGL_VIEW_TYPE

View type (a PuglViewType)

enumerator PUGL_DARK_FRAME

True if window frame should be dark.

enum PuglViewHintValue

A special view hint value.

enumerator PUGL_DONT_CARE

Generic trinary: Use best default.

enumerator PUGL_FALSE

Generic trinary: Explicitly false.

enumerator PUGL_TRUE

Generic trinary: Explicitly true.

enumerator PUGL_OPENGL_API








enum PuglViewType

View type.


A normal top-level window.


A utility window like a palette or toolbox.


A dialog window.

enum PuglSizeHint

A hint for configuring/constraining the size of a view.

The system will attempt to make the view’s window adhere to these, but they are suggestions, not hard constraints. Applications should handle any view size gracefully.


Default size.

This is used as the size during window creation as a default, if no other size is specified.

enumerator PUGL_MIN_SIZE

Minimum size.

If set, the view’s size should be constrained to be at least this large.

enumerator PUGL_MAX_SIZE

Maximum size.

If set, the view’s size should be constrained to be at most this large.


Fixed aspect ratio.

If set, the view’s size should be constrained to this aspect ratio. Mutually exclusive with PuglSizeHint.PUGL_MIN_ASPECT and PuglSizeHint.PUGL_MAX_ASPECT.

enumerator PUGL_MIN_ASPECT

Minimum aspect ratio.

If set, the view’s size should be constrained to an aspect ratio no lower than this. Mutually exclusive with PuglSizeHint.PUGL_FIXED_ASPECT.

enumerator PUGL_MAX_ASPECT

Maximum aspect ratio.

If set, the view’s size should be constrained to an aspect ratio no higher than this. Mutually exclusive with PuglSizeHint.PUGL_FIXED_ASPECT.

typedef struct PuglViewImpl PuglView

A drawable region that receives events.

typedef struct PuglBackendImpl PuglBackend

A graphics backend.

The backend dictates how graphics are set up for a view, and how drawing is performed. A backend must be set by calling puglSetBackend() before realising a view.

If you are using a local copy of Pugl, it is possible to implement a custom backend. See the definition of PuglBackendImpl in the source code for details.

typedef uintptr_t PuglNativeView

A native view handle.

X11: This is a Window.

MacOS: This is a pointer to an NSView*.

Windows: This is a HWND.

typedef void *PuglHandle

Handle for a view’s opaque user data.

typedef PuglStatus (*PuglEventFunc)(PuglView *view, const PuglEvent *event)

A function called when an event occurs.


The number of PuglViewHint values.


The number of PuglSizeHint values.


Native graphics support.

const PuglBackend *puglStubBackend(void)

Stub graphics backend accessor.

This backend just creates a simple native window without setting up any portable graphics API.


Vulkan graphics support.

Vulkan support differs from OpenGL because almost all most configuration is done using the Vulkan API itself, rather than by setting view hints to configure the context. Pugl only provides a minimal loader for loading the Vulkan library, and a portable function to create a Vulkan surface for a view, which hides the platform-specific implementation details.

typedef struct PuglVulkanLoaderImpl PuglVulkanLoader

Dynamic Vulkan loader.

This can be used to dynamically load the Vulkan library. Applications or plugins should not link against the Vulkan library, but instead use this at runtime. This ensures that things will work on as many systems as possible, and allows errors to be handled gracefully.

This is not a “loader” in the sense of loading all the required Vulkan functions (which is the application’s responsibility), but just a minimal implementation to portably load the Vulkan library and get the two functions that are used to load everything else.

Note that this owns the loaded Vulkan library, so it must outlive all use of the Vulkan API.

See also: https://www.khronos.org/registry/vulkan/specs/1.0/html/chap4.html

PuglVulkanLoader *puglNewVulkanLoader(PuglWorld *world, const char *libraryName)

Create a new dynamic loader for Vulkan functions.

This dynamically loads the Vulkan library and gets the load functions from it.

  • world – The world the returned loader is a part of.

  • libraryName – The name of the Vulkan library to load, or null. Typically, this is left unset, which will load the standard Vulkan library for the current platform. It can be set to an alternative name, or an absolute path, to support special packaging scenarios or unusual system configurations. This name is passed directly to the underlying platform library loading function (dlopen or LoadLibrary).


A new Vulkan loader, or null on failure.

void puglFreeVulkanLoader(PuglVulkanLoader *loader)

Free a loader created with puglNewVulkanLoader().

Note that this closes the Vulkan library, so no Vulkan objects or API may be used after this is called.

PFN_vkGetInstanceProcAddr puglGetInstanceProcAddrFunc(const PuglVulkanLoader *loader)

Return the vkGetInstanceProcAddr function.


Null if the Vulkan library does not contain this function (which is unlikely and indicates a broken system).

PFN_vkGetDeviceProcAddr puglGetDeviceProcAddrFunc(const PuglVulkanLoader *loader)

Return the vkGetDeviceProcAddr function.


Null if the Vulkan library does not contain this function (which is unlikely and indicates a broken system).

const char *const *puglGetInstanceExtensions(uint32_t *count)

Return the Vulkan instance extensions required to draw to a PuglView.

This simply returns static strings, it does not access Vulkan or the window system. The returned array always contains at least “VK_KHR_surface”.

  • count – The number of extensions in the returned array.


An array of extension name strings.

VkResult puglCreateSurface(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr, PuglView *view, VkInstance instance, const VkAllocationCallbacks *allocator, VkSurfaceKHR *surface)

Create a Vulkan surface for a Pugl view.

  • vkGetInstanceProcAddr – Accessor for Vulkan functions.

  • view – The view the surface is to be displayed on.

  • instance – The Vulkan instance.

  • allocator – Vulkan allocation callbacks, may be NULL.

  • surface – Pointed to a newly created Vulkan surface.


VK_SUCCESS on success, or a Vulkan error code.

const PuglBackend *puglVulkanBackend(void)

Vulkan graphics backend.

Pass the returned value to puglSetBackend() to draw to a view with Vulkan.