1 /*
2   Copyright 2012-2016 David Robillard <http://drobilla.net>
3 
4   Permission to use, copy, modify, and/or distribute this software for any
5   purpose with or without fee is hereby granted, provided that the above
6   copyright notice and this permission notice appear in all copies.
7 
8   THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16 
17 /**
18    @file pugl.h API for Pugl, a minimal portable API for OpenGL.
19 */
20 
21 #ifndef PUGL_H_INCLUDED
22 #define PUGL_H_INCLUDED
23 
24 #include <stdbool.h>
25 #include <stdint.h>
26 
27 #ifdef PUGL_SHARED
28 #    ifdef _WIN32
29 #        define PUGL_LIB_IMPORT __declspec(dllimport)
30 #        define PUGL_LIB_EXPORT __declspec(dllexport)
31 #    else
32 #        define PUGL_LIB_IMPORT __attribute__((visibility("default")))
33 #        define PUGL_LIB_EXPORT __attribute__((visibility("default")))
34 #    endif
35 #    ifdef PUGL_INTERNAL
36 #        define PUGL_API PUGL_LIB_EXPORT
37 #    else
38 #        define PUGL_API PUGL_LIB_IMPORT
39 #    endif
40 #else
41 #    define PUGL_API
42 #endif
43 
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47 
48 /**
49    @defgroup pugl Pugl
50    A minimal portable API for OpenGL.
51    @{
52 */
53 
54 /**
55    A Pugl view.
56 */
57 typedef struct PuglViewImpl PuglView;
58 
59 /**
60    A native window handle.
61 
62    On X11, this is a Window.
63    On OSX, this is an NSView*.
64    On Windows, this is a HWND.
65 */
66 typedef intptr_t PuglNativeWindow;
67 
68 /**
69    Handle for opaque user data.
70 */
71 typedef void* PuglHandle;
72 
73 /**
74    Return status code.
75 */
76 typedef enum {
77 	PUGL_SUCCESS = 0
78 } PuglStatus;
79 
80 /**
81    Drawing context type.
82 */
83 typedef enum {
84 	PUGL_GL    = 1 << 0,  /**< OpenGL (3D) */
85 	PUGL_CAIRO = 1 << 1   /**< Cairo (2D) */
86 } PuglContextType;
87 
88 /**
89    Window hint.
90 */
91 typedef enum {
92 	PUGL_USE_COMPAT_PROFILE,    /**< Use compatible (not core) OpenGL profile */
93 	PUGL_CONTEXT_VERSION_MAJOR, /**< OpenGL context major version */
94 	PUGL_CONTEXT_VERSION_MINOR, /**< OpenGL context minor version */
95 	PUGL_RED_BITS,              /**< Number of bits for red channel */
96 	PUGL_GREEN_BITS,            /**< Number of bits for green channel */
97 	PUGL_BLUE_BITS,             /**< Number of bits for blue channel */
98 	PUGL_ALPHA_BITS,            /**< Number of bits for alpha channel */
99 	PUGL_DEPTH_BITS,            /**< Number of bits for depth buffer */
100 	PUGL_STENCIL_BITS,          /**< Number of bits for stencil buffer */
101 	PUGL_SAMPLES,               /**< Number of samples per pixel (AA) */
102 	PUGL_DOUBLE_BUFFER,         /**< True if double buffering should be used */
103 	PUGL_RESIZABLE,             /**< True if window should be resizable */
104 } PuglWindowHint;
105 
106 /**
107    Special window hint value.
108 */
109 typedef enum {
110 	PUGL_DONT_CARE = -1,  /**< Use best available value */
111 	PUGL_FALSE     = 0,   /**< Explicitly false */
112 	PUGL_TRUE      = 1    /**< Explicitly true */
113 } PuglWindowHintValue;
114 
115 /**
116    Convenience symbols for ASCII control characters.
117 */
118 typedef enum {
119 	PUGL_CHAR_BACKSPACE = 0x08,
120 	PUGL_CHAR_ESCAPE    = 0x1B,
121 	PUGL_CHAR_DELETE    = 0x7F
122 } PuglChar;
123 
124 /**
125    Keyboard modifier flags.
126 */
127 typedef enum {
128 	PUGL_MOD_SHIFT = 1,       /**< Shift key */
129 	PUGL_MOD_CTRL  = 1 << 1,  /**< Control key */
130 	PUGL_MOD_ALT   = 1 << 2,  /**< Alt/Option key */
131 	PUGL_MOD_SUPER = 1 << 3   /**< Mod4/Command/Windows key */
132 } PuglMod;
133 
134 /**
135    Special (non-Unicode) keyboard keys.
136 
137    The numerical values of these symbols occupy a reserved range of Unicode
138    points, so it is possible to express either a PuglKey value or a Unicode
139    character in the same variable.  This is sometimes useful for interfacing
140    with APIs that do not make this distinction.
141 */
142 typedef enum {
143 	PUGL_KEY_F1 = 0xE000,
144 	PUGL_KEY_F2,
145 	PUGL_KEY_F3,
146 	PUGL_KEY_F4,
147 	PUGL_KEY_F5,
148 	PUGL_KEY_F6,
149 	PUGL_KEY_F7,
150 	PUGL_KEY_F8,
151 	PUGL_KEY_F9,
152 	PUGL_KEY_F10,
153 	PUGL_KEY_F11,
154 	PUGL_KEY_F12,
155 	PUGL_KEY_LEFT,
156 	PUGL_KEY_UP,
157 	PUGL_KEY_RIGHT,
158 	PUGL_KEY_DOWN,
159 	PUGL_KEY_PAGE_UP,
160 	PUGL_KEY_PAGE_DOWN,
161 	PUGL_KEY_HOME,
162 	PUGL_KEY_END,
163 	PUGL_KEY_INSERT,
164 	PUGL_KEY_SHIFT,
165 	PUGL_KEY_CTRL,
166 	PUGL_KEY_ALT,
167 	PUGL_KEY_SUPER
168 } PuglKey;
169 
170 /**
171    The type of a PuglEvent.
172 */
173 typedef enum {
174 	PUGL_NOTHING,              /**< No event */
175 	PUGL_BUTTON_PRESS,         /**< Mouse button press */
176 	PUGL_BUTTON_RELEASE,       /**< Mouse button release */
177 	PUGL_CONFIGURE,            /**< View moved and/or resized */
178 	PUGL_EXPOSE,               /**< View exposed, redraw required */
179 	PUGL_CLOSE,                /**< Close view */
180 	PUGL_KEY_PRESS,            /**< Key press */
181 	PUGL_KEY_RELEASE,          /**< Key release */
182 	PUGL_ENTER_NOTIFY,         /**< Pointer entered view */
183 	PUGL_LEAVE_NOTIFY,         /**< Pointer left view */
184 	PUGL_MOTION_NOTIFY,        /**< Pointer motion */
185 	PUGL_SCROLL,               /**< Scroll */
186 	PUGL_FOCUS_IN,             /**< Keyboard focus entered view */
187 	PUGL_FOCUS_OUT             /**< Keyboard focus left view */
188 } PuglEventType;
189 
190 typedef enum {
191 	PUGL_IS_SEND_EVENT = 1
192 } PuglEventFlag;
193 
194 /**
195    Reason for a PuglEventCrossing.
196 */
197 typedef enum {
198 	PUGL_CROSSING_NORMAL,      /**< Crossing due to pointer motion. */
199 	PUGL_CROSSING_GRAB,        /**< Crossing due to a grab. */
200 	PUGL_CROSSING_UNGRAB       /**< Crossing due to a grab release. */
201 } PuglCrossingMode;
202 
203 /**
204    Common header for all event structs.
205 */
206 typedef struct {
207 	PuglEventType type;        /**< Event type. */
208 	PuglView*     view;        /**< View that received this event. */
209 	uint32_t      flags;       /**< Bitwise OR of PuglEventFlag values. */
210 } PuglEventAny;
211 
212 /**
213    Button press or release event.
214 
215    For event types PUGL_BUTTON_PRESS and PUGL_BUTTON_RELEASE.
216 */
217 typedef struct {
218 	PuglEventType type;        /**< PUGL_BUTTON_PRESS or PUGL_BUTTON_RELEASE. */
219 	PuglView*     view;        /**< View that received this event. */
220 	uint32_t      flags;       /**< Bitwise OR of PuglEventFlag values. */
221 	uint32_t      time;        /**< Time in milliseconds. */
222 	double        x;           /**< View-relative X coordinate. */
223 	double        y;           /**< View-relative Y coordinate. */
224 	double        x_root;      /**< Root-relative X coordinate. */
225 	double        y_root;      /**< Root-relative Y coordinate. */
226 	unsigned      state;       /**< Bitwise OR of PuglMod flags. */
227 	unsigned      button;      /**< 1-relative button number. */
228 } PuglEventButton;
229 
230 /**
231    Configure event for when window size or position has changed.
232 */
233 typedef struct {
234 	PuglEventType type;        /**< PUGL_CONFIGURE. */
235 	PuglView*     view;        /**< View that received this event. */
236 	uint32_t      flags;       /**< Bitwise OR of PuglEventFlag values. */
237 	double        x;           /**< New parent-relative X coordinate. */
238 	double        y;           /**< New parent-relative Y coordinate. */
239 	double        width;       /**< New width. */
240 	double        height;      /**< New height. */
241 } PuglEventConfigure;
242 
243 /**
244    Expose event for when a region must be redrawn.
245 */
246 typedef struct {
247 	PuglEventType type;        /**< PUGL_EXPOSE. */
248 	PuglView*     view;        /**< View that received this event. */
249 	uint32_t      flags;       /**< Bitwise OR of PuglEventFlag values. */
250 	double        x;           /**< View-relative X coordinate. */
251 	double        y;           /**< View-relative Y coordinate. */
252 	double        width;       /**< Width of exposed region. */
253 	double        height;      /**< Height of exposed region. */
254 	int           count;       /**< Number of expose events to follow. */
255 } PuglEventExpose;
256 
257 /**
258    Window close event.
259 */
260 typedef struct {
261 	PuglEventType type;        /**< PUGL_CLOSE. */
262 	PuglView*     view;        /**< View that received this event. */
263 	uint32_t      flags;       /**< Bitwise OR of PuglEventFlag values. */
264 } PuglEventClose;
265 
266 /**
267    Key press/release event.
268 
269    Keys that correspond to a Unicode character have `character` and `utf8` set.
270    Other keys will have `character` 0, but `special` may be set if this is a
271    known special key.
272 
273    A key press may be part of a multi-key sequence to generate a wide
274    character.  If `filter` is set, this event is part of a multi-key sequence
275    and should be ignored if the application is reading textual input.
276    Following the series of filtered press events, a press event with
277    `character` and `utf8` (but `keycode` 0) will be sent.  This event will have
278    no corresponding release event.
279 
280    Generally, an application should either work with raw keyboard press/release
281    events based on `keycode` (ignoring events with `keycode` 0), or
282    read textual input based on `character` or `utf8` (ignoring releases and
283    events with `filter` 1).  Note that blindly appending `utf8` will yield
284    incorrect text, since press events are sent for both individually composed
285    keys and the resulting synthetic multi-byte press.
286 */
287 typedef struct {
288 	PuglEventType type;        /**< PUGL_KEY_PRESS or PUGL_KEY_RELEASE. */
289 	PuglView*     view;        /**< View that received this event. */
290 	uint32_t      flags;       /**< Bitwise OR of PuglEventFlag values. */
291 	uint32_t      time;        /**< Time in milliseconds. */
292 	double        x;           /**< View-relative X coordinate. */
293 	double        y;           /**< View-relative Y coordinate. */
294 	double        x_root;      /**< Root-relative X coordinate. */
295 	double        y_root;      /**< Root-relative Y coordinate. */
296 	unsigned      state;       /**< Bitwise OR of PuglMod flags. */
297 	unsigned      keycode;     /**< Raw key code. */
298 	uint32_t      character;   /**< Unicode character code, or 0. */
299 	PuglKey       special;     /**< Special key, or 0. */
300 	uint8_t       utf8[8];     /**< UTF-8 string. */
301 	bool          filter;      /**< True if part of a multi-key sequence. */
302 } PuglEventKey;
303 
304 /**
305    Pointer crossing event (enter and leave).
306 */
307 typedef struct {
308 	PuglEventType    type;     /**< PUGL_ENTER_NOTIFY or PUGL_LEAVE_NOTIFY. */
309 	PuglView*        view;     /**< View that received this event. */
310 	uint32_t         flags;    /**< Bitwise OR of PuglEventFlag values. */
311 	uint32_t         time;     /**< Time in milliseconds. */
312 	double           x;        /**< View-relative X coordinate. */
313 	double           y;        /**< View-relative Y coordinate. */
314 	double           x_root;   /**< Root-relative X coordinate. */
315 	double           y_root;   /**< Root-relative Y coordinate. */
316 	unsigned         state;    /**< Bitwise OR of PuglMod flags. */
317 	PuglCrossingMode mode;     /**< Reason for crossing. */
318 } PuglEventCrossing;
319 
320 /**
321    Pointer motion event.
322 */
323 typedef struct {
324 	PuglEventType type;        /**< PUGL_MOTION_NOTIFY. */
325 	PuglView*     view;        /**< View that received this event. */
326 	uint32_t      flags;       /**< Bitwise OR of PuglEventFlag values. */
327 	uint32_t      time;        /**< Time in milliseconds. */
328 	double        x;           /**< View-relative X coordinate. */
329 	double        y;           /**< View-relative Y coordinate. */
330 	double        x_root;      /**< Root-relative X coordinate. */
331 	double        y_root;      /**< Root-relative Y coordinate. */
332 	unsigned      state;       /**< Bitwise OR of PuglMod flags. */
333 	bool          is_hint;     /**< True iff this event is a motion hint. */
334 	bool          focus;       /**< True iff this is the focused window. */
335 } PuglEventMotion;
336 
337 /**
338    Scroll event.
339 
340    The scroll distance is expressed in "lines", an arbitrary unit that
341    corresponds to a single tick of a detented mouse wheel.  For example, `dy` =
342    1.0 scrolls 1 line up.  Some systems and devices support finer resolution
343    and/or higher values for fast scrolls, so programs should handle any value
344    gracefully.
345  */
346 typedef struct {
347 	PuglEventType type;        /**< PUGL_SCROLL. */
348 	PuglView*     view;        /**< View that received this event. */
349 	uint32_t      flags;       /**< Bitwise OR of PuglEventFlag values. */
350 	uint32_t      time;        /**< Time in milliseconds. */
351 	double        x;           /**< View-relative X coordinate. */
352 	double        y;           /**< View-relative Y coordinate. */
353 	double        x_root;      /**< Root-relative X coordinate. */
354 	double        y_root;      /**< Root-relative Y coordinate. */
355 	unsigned      state;       /**< Bitwise OR of PuglMod flags. */
356 	double        dx;          /**< Scroll X distance in lines. */
357 	double        dy;          /**< Scroll Y distance in lines. */
358 } PuglEventScroll;
359 
360 /**
361    Keyboard focus event.
362 */
363 typedef struct {
364 	PuglEventType type;        /**< PUGL_FOCUS_IN or PUGL_FOCUS_OUT. */
365 	PuglView*     view;        /**< View that received this event. */
366 	uint32_t      flags;       /**< Bitwise OR of PuglEventFlag values. */
367 	bool          grab;        /**< True iff this is a grab/ungrab event. */
368 } PuglEventFocus;
369 
370 /**
371    Interface event.
372 
373    This is a union of all event structs.  The `type` must be checked to
374    determine which fields are safe to access.  A pointer to PuglEvent can
375    either be cast to the appropriate type, or the union members used.
376 */
377 typedef union {
378 	PuglEventType      type;       /**< Event type. */
379 	PuglEventAny       any;        /**< Valid for all event types. */
380 	PuglEventButton    button;     /**< PUGL_BUTTON_PRESS, PUGL_BUTTON_RELEASE. */
381 	PuglEventConfigure configure;  /**< PUGL_CONFIGURE. */
382 	PuglEventExpose    expose;     /**< PUGL_EXPOSE. */
383 	PuglEventClose     close;      /**< PUGL_CLOSE. */
384 	PuglEventKey       key;        /**< PUGL_KEY_PRESS, PUGL_KEY_RELEASE. */
385 	PuglEventCrossing  crossing;   /**< PUGL_ENTER_NOTIFY, PUGL_LEAVE_NOTIFY. */
386 	PuglEventMotion    motion;     /**< PUGL_MOTION_NOTIFY. */
387 	PuglEventScroll    scroll;     /**< PUGL_SCROLL. */
388 	PuglEventFocus     focus;      /**< PUGL_FOCUS_IN, PUGL_FOCUS_OUT. */
389 } PuglEvent;
390 
391 /**
392    @name Initialization
393    Configuration functions which must be called before creating a window.
394    @{
395 */
396 
397 /**
398    Create a Pugl view.
399 
400    To create a window, call the various puglInit* functions as necessary, then
401    call puglCreateWindow().
402 
403    @param pargc Pointer to argument count (currently unused).
404    @param argv  Arguments (currently unused).
405    @return A newly created view.
406 */
407 PUGL_API PuglView*
408 puglInit(int* pargc, char** argv);
409 
410 /**
411    Set a hint before creating a window.
412 */
413 PUGL_API void
414 puglInitWindowHint(PuglView* view, PuglWindowHint hint, int value);
415 
416 /**
417    Set the window class name before creating a window.
418 */
419 PUGL_API void
420 puglInitWindowClass(PuglView* view, const char* name);
421 
422 /**
423    Set the parent window before creating a window (for embedding).
424 */
425 PUGL_API void
426 puglInitWindowParent(PuglView* view, PuglNativeWindow parent);
427 
428 /**
429    Set the window size before creating a window.
430 */
431 PUGL_API void
432 puglInitWindowSize(PuglView* view, int width, int height);
433 
434 /**
435    Set the minimum window size before creating a window.
436 */
437 PUGL_API void
438 puglInitWindowMinSize(PuglView* view, int width, int height);
439 
440 /**
441    Set the window aspect ratio range before creating a window.
442 
443    The x and y values here represent a ratio of width to height.  To set a
444    fixed aspect ratio, set the minimum and maximum values to the same ratio.
445 */
446 PUGL_API void
447 puglInitWindowAspectRatio(PuglView* view,
448                           int       min_x,
449                           int       min_y,
450                           int       max_x,
451                           int       max_y);
452 
453 /**
454    Enable or disable resizing before creating a window.
455 */
456 PUGL_API void
457 puglInitResizable(PuglView* view, bool resizable);
458 
459 /**
460    Set transient parent before creating a window.
461 
462    On X11, parent must be a Window.
463    On OSX, parent must be an NSView*.
464 */
465 PUGL_API void
466 puglInitTransientFor(PuglView* view, uintptr_t parent);
467 
468 /**
469    Set the context type before creating a window.
470 */
471 PUGL_API void
472 puglInitContextType(PuglView* view, PuglContextType type);
473 
474 /**
475    @}
476 */
477 
478 /**
479    @name Windows
480    Functions for creating and managing a visible window for a view.
481    @{
482 */
483 
484 /**
485    Create a window with the settings given by the various puglInit functions.
486 
487    @return 1 (pugl does not currently support multiple windows).
488 */
489 PUGL_API int
490 puglCreateWindow(PuglView* view, const char* title);
491 
492 /**
493    Show the current window.
494 */
495 PUGL_API void
496 puglShowWindow(PuglView* view);
497 
498 /**
499    Hide the current window.
500 */
501 PUGL_API void
502 puglHideWindow(PuglView* view);
503 
504 /**
505    Return the native window handle.
506 */
507 PUGL_API PuglNativeWindow
508 puglGetNativeWindow(PuglView* view);
509 
510 /**
511    @}
512 */
513 
514 /**
515    Set the handle to be passed to all callbacks.
516 
517    This is generally a pointer to a struct which contains all necessary state.
518    Everything needed in callbacks should be here, not in static variables.
519 */
520 PUGL_API void
521 puglSetHandle(PuglView* view, PuglHandle handle);
522 
523 /**
524    Get the handle to be passed to all callbacks.
525 */
526 PUGL_API PuglHandle
527 puglGetHandle(PuglView* view);
528 
529 /**
530    Return true iff the view is currently visible.
531 */
532 PUGL_API bool
533 puglGetVisible(PuglView* view);
534 
535 /**
536    Get the current size of the view.
537 */
538 PUGL_API void
539 puglGetSize(PuglView* view, int* width, int* height);
540 
541 /**
542    @name Context
543    Functions for accessing the drawing context.
544    @{
545 */
546 
547 /**
548    Get the drawing context.
549 
550    For PUGL_GL contexts, this is unused and returns NULL.
551    For PUGL_CAIRO contexts, this returns a pointer to a cairo_t.
552 */
553 PUGL_API void*
554 puglGetContext(PuglView* view);
555 
556 /**
557    Enter the drawing context.
558 
559    This must be called before any code that accesses the drawing context,
560    including any GL functions.  This is only necessary for code that does so
561    outside the usual draw callback or handling of an expose event.
562 */
563 PUGL_API void
564 puglEnterContext(PuglView* view);
565 
566 /**
567    Leave the drawing context.
568 
569    This must be called after puglEnterContext and applies the results of the
570    drawing code (for example, by swapping buffers).
571 */
572 PUGL_API void
573 puglLeaveContext(PuglView* view, bool flush);
574 
575 /**
576    @}
577 */
578 
579 /**
580    @name Event Handling
581    @{
582 */
583 
584 /**
585    A function called when an event occurs.
586 */
587 typedef void (*PuglEventFunc)(PuglView* view, const PuglEvent* event);
588 
589 /**
590    Set the function to call when an event occurs.
591 */
592 PUGL_API void
593 puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc);
594 
595 /**
596    Ignore synthetic repeated key events.
597 */
598 PUGL_API void
599 puglIgnoreKeyRepeat(PuglView* view, bool ignore);
600 
601 /**
602    Grab the input focus.
603 */
604 PUGL_API void
605 puglGrabFocus(PuglView* view);
606 
607 /**
608    Block and wait for an event to be ready.
609 
610    This can be used in a loop to only process events via puglProcessEvents when
611    necessary.  This function will block indefinitely if no events are
612    available, so is not appropriate for use in programs that need to perform
613    regular updates (e.g. animation).
614 */
615 PUGL_API PuglStatus
616 puglWaitForEvent(PuglView* view);
617 
618 /**
619    Process all pending window events.
620 
621    This handles input events as well as rendering, so it should be called
622    regularly and rapidly enough to keep the UI responsive.  This function does
623    not block if no events are pending.
624 */
625 PUGL_API PuglStatus
626 puglProcessEvents(PuglView* view);
627 
628 /**
629    @}
630 */
631 
632 /**
633    OpenGL extension function.
634 */
635 typedef void (*PuglGlFunc)();
636 
637 /**
638    Return the address of an OpenGL extension function.
639 */
640 PUGL_API PuglGlFunc
641 puglGetProcAddress(const char* name);
642 
643 /**
644    Request a redisplay on the next call to puglProcessEvents().
645 */
646 PUGL_API void
647 puglPostRedisplay(PuglView* view);
648 
649 /**
650    Destroy a GL window.
651 */
652 PUGL_API void
653 puglDestroy(PuglView* view);
654 
655 /**
656    @}
657 */
658 
659 #ifdef __cplusplus
660 }  /* extern "C" */
661 #endif
662 
663 #endif  /* PUGL_H_INCLUDED */
664