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