aboutsummaryrefslogtreecommitdiff
path: root/subprojects/d2tk/pugl/pugl/pugl.h
blob: 57e23fa77859d5dcec229cbaf6d8b9599cd00198 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
/*
  Copyright 2012-2020 David Robillard <http://drobilla.net>

  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted, provided that the above
  copyright notice and this permission notice appear in all copies.

  THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

/**
   @file pugl.h Pugl API.
*/

#ifndef PUGL_PUGL_H
#define PUGL_PUGL_H

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#ifdef PUGL_SHARED
#    ifdef _WIN32
#        define PUGL_LIB_IMPORT __declspec(dllimport)
#        define PUGL_LIB_EXPORT __declspec(dllexport)
#    else
#        define PUGL_LIB_IMPORT __attribute__((visibility("default")))
#        define PUGL_LIB_EXPORT __attribute__((visibility("default")))
#    endif
#    ifdef PUGL_INTERNAL
#        define PUGL_API PUGL_LIB_EXPORT
#    else
#        define PUGL_API PUGL_LIB_IMPORT
#    endif
#else
#    define PUGL_API
#endif

#ifndef PUGL_DISABLE_DEPRECATED
#    if defined(__clang__)
#        define PUGL_DEPRECATED_BY(rep) __attribute__((deprecated("", rep)))
#    elif defined(__GNUC__)
#        define PUGL_DEPRECATED_BY(rep) __attribute__((deprecated("Use " rep)))
#    else
#        define PUGL_DEPRECATED_BY(rep)
#    endif
#endif

#ifdef __cplusplus
#	define PUGL_BEGIN_DECLS extern "C" {
#	define PUGL_END_DECLS }
#else
#	define PUGL_BEGIN_DECLS
#	define PUGL_END_DECLS
#endif

PUGL_BEGIN_DECLS

/**
   @defgroup pugl_api Pugl
   A minimal portable API for embeddable GUIs.
   @{
*/

/**
   A rectangle.

   This is used to describe things like view position and size.  Pugl generally
   uses coordinates where the top left corner is 0,0.
*/
typedef struct {
	double x;
	double y;
	double width;
	double height;
} PuglRect;

/**
   @defgroup events Events

   Event definitions.

   All updates to the view happen via events, which are dispatched to the
   view's #PuglEventFunc by Pugl.  Most events map directly to one from the
   underlying window system, but some are constructed by Pugl itself so there
   is not necessarily a direct correspondence.

   @{
*/

/**
   Keyboard modifier flags.
*/
typedef enum {
	PUGL_MOD_SHIFT = 1,      ///< Shift key
	PUGL_MOD_CTRL  = 1 << 1, ///< Control key
	PUGL_MOD_ALT   = 1 << 2, ///< Alt/Option key
	PUGL_MOD_SUPER = 1 << 3  ///< Mod4/Command/Windows key
} PuglMod;

/**
   Bitwise OR of #PuglMod values.
*/
typedef uint32_t PuglMods;

/**
   Keyboard key codepoints.

   All keys are identified by a Unicode code point in PuglEventKey::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.
*/
typedef enum {
	// ASCII control codes
	PUGL_KEY_BACKSPACE = 0x08,
	PUGL_KEY_ESCAPE    = 0x1B,
	PUGL_KEY_DELETE    = 0x7F,

	// Unicode Private Use Area
	PUGL_KEY_F1 = 0xE000,
	PUGL_KEY_F2,
	PUGL_KEY_F3,
	PUGL_KEY_F4,
	PUGL_KEY_F5,
	PUGL_KEY_F6,
	PUGL_KEY_F7,
	PUGL_KEY_F8,
	PUGL_KEY_F9,
	PUGL_KEY_F10,
	PUGL_KEY_F11,
	PUGL_KEY_F12,
	PUGL_KEY_LEFT,
	PUGL_KEY_UP,
	PUGL_KEY_RIGHT,
	PUGL_KEY_DOWN,
	PUGL_KEY_PAGE_UP,
	PUGL_KEY_PAGE_DOWN,
	PUGL_KEY_HOME,
	PUGL_KEY_END,
	PUGL_KEY_INSERT,
	PUGL_KEY_SHIFT,
	PUGL_KEY_SHIFT_L = PUGL_KEY_SHIFT,
	PUGL_KEY_SHIFT_R,
	PUGL_KEY_CTRL,
	PUGL_KEY_CTRL_L = PUGL_KEY_CTRL,
	PUGL_KEY_CTRL_R,
	PUGL_KEY_ALT,
	PUGL_KEY_ALT_L = PUGL_KEY_ALT,
	PUGL_KEY_ALT_R,
	PUGL_KEY_SUPER,
	PUGL_KEY_SUPER_L = PUGL_KEY_SUPER,
	PUGL_KEY_SUPER_R,
	PUGL_KEY_MENU,
	PUGL_KEY_CAPS_LOCK,
	PUGL_KEY_SCROLL_LOCK,
	PUGL_KEY_NUM_LOCK,
	PUGL_KEY_PRINT_SCREEN,
	PUGL_KEY_PAUSE
} PuglKey;

/**
   The type of a PuglEvent.
*/
typedef enum {
	PUGL_NOTHING,        ///< No event
	PUGL_CREATE,         ///< View created, a #PuglEventCreate
	PUGL_DESTROY,        ///< View destroyed, a #PuglEventDestroy
	PUGL_CONFIGURE,      ///< View moved/resized, a #PuglEventConfigure
	PUGL_MAP,            ///< View made visible, a #PuglEventMap
	PUGL_UNMAP,          ///< View made invisible, a #PuglEventUnmap
	PUGL_UPDATE,         ///< View ready to draw, a #PuglEventUpdate
	PUGL_EXPOSE,         ///< View must be drawn, a #PuglEventExpose
	PUGL_CLOSE,          ///< View will be closed, a #PuglEventClose
	PUGL_FOCUS_IN,       ///< Keyboard focus entered view, a #PuglEventFocus
	PUGL_FOCUS_OUT,      ///< Keyboard focus left view, a #PuglEventFocus
	PUGL_KEY_PRESS,      ///< Key pressed, a #PuglEventKey
	PUGL_KEY_RELEASE,    ///< Key released, a #PuglEventKey
	PUGL_TEXT,           ///< Character entered, a #PuglEventText
	PUGL_POINTER_IN,     ///< Pointer entered view, a #PuglEventCrossing
	PUGL_POINTER_OUT,    ///< Pointer left view, a #PuglEventCrossing
	PUGL_BUTTON_PRESS,   ///< Mouse button pressed, a #PuglEventButton
	PUGL_BUTTON_RELEASE, ///< Mouse button released, a #PuglEventButton
	PUGL_MOTION,         ///< Pointer moved, a #PuglEventMotion
	PUGL_SCROLL,         ///< Scrolled, a #PuglEventScroll
	PUGL_CLIENT,         ///< Custom client message, a #PuglEventClient
	PUGL_TIMER,          ///< Timer triggered, a #PuglEventTimer

#ifndef PUGL_DISABLE_DEPRECATED
	PUGL_ENTER_NOTIFY PUGL_DEPRECATED_BY("PUGL_POINTER_IN") = PUGL_POINTER_IN,
	PUGL_LEAVE_NOTIFY PUGL_DEPRECATED_BY("PUGL_POINTER_OUT") = PUGL_POINTER_OUT,
	PUGL_MOTION_NOTIFY PUGL_DEPRECATED_BY("PUGL_MOTION") = PUGL_MOTION,
#endif

} PuglEventType;

/**
   Common flags for all event types.
*/
typedef enum {
	PUGL_IS_SEND_EVENT = 1 ///< Event is synthetic
} PuglEventFlag;

/**
   Bitwise OR of #PuglEventFlag values.
*/
typedef uint32_t PuglEventFlags;

/**
   Reason for a PuglEventCrossing.
*/
typedef enum {
	PUGL_CROSSING_NORMAL, ///< Crossing due to pointer motion
	PUGL_CROSSING_GRAB,   ///< Crossing due to a grab
	PUGL_CROSSING_UNGRAB  ///< Crossing due to a grab release
} PuglCrossingMode;

/**
   Common header for all event structs.
*/
typedef struct {
	PuglEventType  type;  ///< Event type
	PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
} PuglEventAny;

/**
   View create 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 PuglEventAny PuglEventCreate;

/**
   View destroy event.

   This event is the counterpart to #PuglEventCreate, and it is sent when the
   view is being destroyed.  This is typically used for tearing down the
   graphics system, or otherwise freeing any resources allocated when the
   create event was handled.

   This is the last event sent to any view, and immediately after it is
   processed, the view is destroyed and may no longer be used.

   This event type has no extra fields.
*/
typedef PuglEventAny PuglEventDestroy;

/**
   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.
*/
typedef struct {
	PuglEventType  type;   ///< #PUGL_CONFIGURE
	PuglEventFlags flags;  ///< Bitwise OR of #PuglEventFlag values
	double         x;      ///< New parent-relative X coordinate
	double         y;      ///< New parent-relative Y coordinate
	double         width;  ///< New width
	double         height; ///< New height
} PuglEventConfigure;

/**
   View show event.

   This event is sent when a view is mapped to the screen and made visible.

   This event type has no extra fields.
*/
typedef PuglEventAny PuglEventMap;

/**
   View hide event.

   This event is sent when a view is unmapped from the screen and made
   invisible.

   This event type has no extra fields.
*/
typedef PuglEventAny PuglEventUnmap;

/**
   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.
*/
typedef PuglEventAny PuglEventUpdate;

/**
   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.
*/
typedef struct {
	PuglEventType  type;   ///< #PUGL_EXPOSE
	PuglEventFlags flags;  ///< Bitwise OR of #PuglEventFlag values
	double         x;      ///< View-relative X coordinate
	double         y;      ///< View-relative Y coordinate
	double         width;  ///< Width of exposed region
	double         height; ///< Height of exposed region
	int            count;  ///< Number of expose events to follow
} PuglEventExpose;

/**
   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.
*/
typedef PuglEventAny PuglEventClose;

/**
   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.
*/
typedef struct {
	PuglEventType  type;  ///< #PUGL_FOCUS_IN or #PUGL_FOCUS_OUT
	PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
	bool           grab;  ///< True iff this is a grab/ungrab event
} PuglEventFocus;

/**
   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.
*/
typedef struct {
	PuglEventType  type;    ///< #PUGL_KEY_PRESS or #PUGL_KEY_RELEASE
	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
} PuglEventKey;

/**
   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.
*/
typedef struct {
	PuglEventType  type;      ///< #PUGL_TEXT
	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
} PuglEventText;

/**
   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.
*/
typedef struct {
	PuglEventType    type;  ///< #PUGL_POINTER_IN or #PUGL_POINTER_OUT
	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
} PuglEventCrossing;

/**
   Button press or release event.
*/
typedef struct {
	PuglEventType  type;   ///< #PUGL_BUTTON_PRESS or #PUGL_BUTTON_RELEASE
	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 1
} PuglEventButton;

/**
   Pointer motion event.
*/
typedef struct {
	PuglEventType  type;   ///< #PUGL_MOTION
	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
	bool           isHint; ///< True iff this event is a motion hint
	bool           focus;  ///< True iff this is the focused view
} PuglEventMotion;

/**
   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.
*/
typedef struct {
	PuglEventType  type;  ///< #PUGL_SCROLL
	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
	double         dx;    ///< Scroll X distance in lines
	double         dy;    ///< Scroll Y distance in lines
} PuglEventScroll;

/**
   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.
*/
typedef struct {
	PuglEventType  type;  ///< #PUGL_CLIENT
	PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
	uintptr_t      data1; ///< Client-specific data
	uintptr_t      data2; ///< Client-specific data
} PuglEventClient;

/**
   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.
*/
typedef struct {
	PuglEventType  type;  ///< #PUGL_TIMER
	PuglEventFlags flags; ///< Bitwise OR of #PuglEventFlag values
	uintptr_t      id;    ///< Timer ID
} PuglEventTimer;

/**
   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 #PUGL_CREATE, #PUGL_DESTROY, #PUGL_CONFIGURE,
   and #PUGL_EXPOSE, but only enabled for drawing for #PUGL_EXPOSE.
*/
typedef union {
	PuglEventAny       any;       ///< Valid for all event types
	PuglEventType      type;      ///< Event type
	PuglEventButton    button;    ///< #PUGL_BUTTON_PRESS, #PUGL_BUTTON_RELEASE
	PuglEventConfigure configure; ///< #PUGL_CONFIGURE
	PuglEventExpose    expose;    ///< #PUGL_EXPOSE
	PuglEventKey       key;       ///< #PUGL_KEY_PRESS, #PUGL_KEY_RELEASE
	PuglEventText      text;      ///< #PUGL_TEXT
	PuglEventCrossing  crossing;  ///< #PUGL_POINTER_IN, #PUGL_POINTER_OUT
	PuglEventMotion    motion;    ///< #PUGL_MOTION
	PuglEventScroll    scroll;    ///< #PUGL_SCROLL
	PuglEventFocus     focus;     ///< #PUGL_FOCUS_IN, #PUGL_FOCUS_OUT
	PuglEventClient    client;    ///< #PUGL_CLIENT
	PuglEventTimer     timer;     ///< #PUGL_TIMER
} PuglEvent;

/**
   @}
   @defgroup status Status

   Status codes and error handling.

   @{
*/

/**
   Return status code.
*/
typedef enum {
	PUGL_SUCCESS,               ///< Success
	PUGL_FAILURE,               ///< Non-fatal failure
	PUGL_UNKNOWN_ERROR,         ///< Unknown system error
	PUGL_BAD_BACKEND,           ///< Invalid or missing backend
	PUGL_BAD_PARAMETER,         ///< Invalid parameter
	PUGL_BACKEND_FAILED,        ///< Backend initialisation failed
	PUGL_REGISTRATION_FAILED,   ///< Class registration failed
	PUGL_REALIZE_FAILED,        ///< System view realization failed
	PUGL_SET_FORMAT_FAILED,     ///< Failed to set pixel format
	PUGL_CREATE_CONTEXT_FAILED, ///< Failed to create drawing context
	PUGL_UNSUPPORTED_TYPE,      ///< Unsupported data type
} PuglStatus;

/**
   Return a string describing a status code.
*/
PUGL_API
const char*
puglStrerror(PuglStatus status);

/**
   @}
   @defgroup world World

   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.

   @{
*/

/**
   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 struct PuglWorldImpl PuglWorld;

/**
   Handle for the world's opaque user data.
*/
typedef void* PuglWorldHandle;

/**
   The type of a PuglWorld.
*/
typedef enum {
	PUGL_PROGRAM, ///< Top-level application
	PUGL_MODULE   ///< Plugin or module within a larger application
} PuglWorldType;

/**
   World flags.
*/
typedef enum {
	/**
	   Set up support for threads if necessary.

	   - X11: Calls XInitThreads() which is required for some drivers.
	*/
	PUGL_WORLD_THREADS = 1 << 0
} PuglWorldFlag;

/**
   Bitwise OR of #PuglWorldFlag values.
*/
typedef uint32_t PuglWorldFlags;

/**
   A log message level, compatible with syslog.
*/
typedef enum {
	PUGL_LOG_LEVEL_ERR     = 3, ///< Error
	PUGL_LOG_LEVEL_WARNING = 4, ///< Warning
	PUGL_LOG_LEVEL_INFO    = 6, ///< Informational message
	PUGL_LOG_LEVEL_DEBUG   = 7  ///< Debug message
} PuglLogLevel;

/**
   A function called to report log messages.

   @param world The world that produced this log message.
   @param level Log level.
   @param msg Message string.
*/
typedef void (*PuglLogFunc)(PuglWorld*   world,
                            PuglLogLevel level,
                            const char*  msg);

/**
   Create a new world.

   @param type The type, which dictates what this world is responsible for.
   @param flags Flags to control world features.
   @return A new world, which must be later freed with puglFreeWorld().
*/
PUGL_API PuglWorld*
puglNewWorld(PuglWorldType type, PuglWorldFlags flags);

/**
   Free a world allocated with puglNewWorld().
*/
PUGL_API void
puglFreeWorld(PuglWorld* world);

/**
   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.
*/
PUGL_API void
puglSetWorldHandle(PuglWorld* world, PuglWorldHandle handle);

/**
   Get the user data for the world.
*/
PUGL_API PuglWorldHandle
puglGetWorldHandle(PuglWorld* world);

/**
   Return a pointer to the native handle of the world.

   @return
   - X11: A pointer to the `Display`.
   - MacOS: `NULL`.
   - Windows: The `HMODULE` of the calling process.
*/
PUGL_API void*
puglGetNativeWorld(PuglWorld* world);

/**
   Set the function to call to log a message.

   This will be called to report any log messages generated internally by Pugl
   which are enabled according to the log level.
*/
PUGL_API PuglStatus
puglSetLogFunc(PuglWorld* world, PuglLogFunc logFunc);

/**
   Set the level of log messages to emit.

   Any log messages with a level less than or equal to `level` will be emitted.
*/
PUGL_API PuglStatus
puglSetLogLevel(PuglWorld* world, PuglLogLevel level);

/**
   Set the class name of the application.

   This is a stable identifier for the application, used as the window
   class/instance name on X11 and Windows.  It is not displayed to the user,
   but can be used in scripts and by window managers, so it should be the same
   for every instance of the application, but different from other
   applications.
*/
PUGL_API PuglStatus
puglSetClassName(PuglWorld* world, const char* name);

/**
   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.
*/
PUGL_API double
puglGetTime(const PuglWorld* world);

/**
   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 a positive timeout is given, then events will be processed for that
   amount of time, starting from when this function was called.  For purely
   event-driven programs, a timeout of -1.0 can be used to block indefinitely
   until something happens.  For continuously animating programs, a timeout
   that is a reasonable fraction of the ideal frame period should be used, to
   minimise input latency by ensuring that as many input events are consumed as
   possible before drawing.  Plugins should always use a timeout of 0.0 to
   avoid blocking the host.

   @param world The world to update.

   @param timeout Maximum time to wait, in seconds.  If zero, the call returns
   immediately, if negative, the call blocks indefinitely.

   @return #PUGL_SUCCESS if events are read, #PUGL_FAILURE if not, or an error.
*/
PUGL_API PuglStatus
puglUpdate(PuglWorld* world, double timeout);

/**
   @}

   @defgroup view View

   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.

   @{
*/

/**
   A drawable region that receives events.
*/
typedef struct PuglViewImpl PuglView;

/**
   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 struct PuglBackendImpl PuglBackend;

/**
   A native view handle.

   X11: This is a `Window`.

   MacOS: This is a pointer to an `NSView*`.

   Windows: This is a `HWND`.
*/
typedef uintptr_t PuglNativeView;

/**
   Handle for a view's opaque user data.
*/
typedef void* PuglHandle;

/**
   A hint for configuring a view.
*/
typedef enum {
	PUGL_USE_COMPAT_PROFILE,    ///< Use compatible (not core) OpenGL profile
	PUGL_USE_DEBUG_CONTEXT,     ///< True to use a debug OpenGL context
	PUGL_CONTEXT_VERSION_MAJOR, ///< OpenGL context major version
	PUGL_CONTEXT_VERSION_MINOR, ///< OpenGL context minor version
	PUGL_RED_BITS,              ///< Number of bits for red channel
	PUGL_GREEN_BITS,            ///< Number of bits for green channel
	PUGL_BLUE_BITS,             ///< Number of bits for blue channel
	PUGL_ALPHA_BITS,            ///< Number of bits for alpha channel
	PUGL_DEPTH_BITS,            ///< Number of bits for depth buffer
	PUGL_STENCIL_BITS,          ///< Number of bits for stencil buffer
	PUGL_SAMPLES,               ///< Number of samples per pixel (AA)
	PUGL_DOUBLE_BUFFER,         ///< True if double buffering should be used
	PUGL_SWAP_INTERVAL,         ///< Number of frames between buffer swaps
	PUGL_RESIZABLE,             ///< True if view should be resizable
	PUGL_IGNORE_KEY_REPEAT,     ///< True if key repeat events are ignored

	PUGL_NUM_VIEW_HINTS
} PuglViewHint;

/**
   A special view hint value.
*/
typedef enum {
	PUGL_DONT_CARE = -1, ///< Use best available value
	PUGL_FALSE     = 0,  ///< Explicitly false
	PUGL_TRUE      = 1   ///< Explicitly true
} PuglViewHintValue;

/**
   A function called when an event occurs.
*/
typedef PuglStatus (*PuglEventFunc)(PuglView* view, const PuglEvent* event);

/**
   @name Setup
   Functions for creating and destroying a view.
   @{
*/

/**
   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().
*/
PUGL_API PuglView*
puglNewView(PuglWorld* world);

/**
   Free a view created with puglNewView().
*/
PUGL_API void
puglFreeView(PuglView* view);

/**
   Return the world that `view` is a part of.
*/
PUGL_API PuglWorld*
puglGetWorld(PuglView* view);

/**
   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.
*/
PUGL_API void
puglSetHandle(PuglView* view, PuglHandle handle);

/**
   Get the user data for a view.
*/
PUGL_API PuglHandle
puglGetHandle(PuglView* view);

/**
   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:

   - puglGlBackend(), declared in pugl_gl.h
   - puglCairoBackend(), declared in pugl_cairo.h

   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.
*/
PUGL_API PuglStatus
puglSetBackend(PuglView* view, const PuglBackend* backend);

/**
   Set the function to call when an event occurs.
*/
PUGL_API PuglStatus
puglSetEventFunc(PuglView* view, PuglEventFunc eventFunc);

/**
   Set a hint to configure view properties.

   This only has an effect when called before puglRealize().
*/
PUGL_API PuglStatus
puglSetViewHint(PuglView* view, PuglViewHint hint, int value);

/**
   @}
   @anchor frame
   @name Frame
   Functions for working with the position and size of a view.
   @{
*/

/**
   Get the current position and size of the view.

   The position is in screen coordinates with an upper left origin.
*/
PUGL_API PuglRect
puglGetFrame(const PuglView* view);

/**
   Set the current position and size of the view.

   The position is in screen coordinates with an upper left origin.
*/
PUGL_API PuglStatus
puglSetFrame(PuglView* view, PuglRect frame);

/**
   Set the minimum size of the view.

   If an initial minimum size is known, this should be called before
   puglRealize() to avoid stutter, though it can be called afterwards as well.
*/
PUGL_API PuglStatus
puglSetMinSize(PuglView* view, int width, int height);

/**
   Set the view aspect ratio range.

   The x and y values here represent a ratio of width to height.  To set a
   fixed aspect ratio, set the minimum and maximum values to the same ratio.

   Note that setting different minimum and maximum constraints does not
   currenty work on MacOS (the minimum is used), so only setting a fixed aspect
   ratio works properly across all platforms.

   If an initial aspect ratio is known, this should be called before
   puglRealize() to avoid stutter, though it can be called afterwards as well.
*/
PUGL_API PuglStatus
puglSetAspectRatio(PuglView* view, int minX, int minY, int maxX, int maxY);

/**
   @}
   @name Windows
   Functions for working with system views and the window hierarchy.
   @{
*/

/**
   Set the title of the window.

   This only makes sense for non-embedded views that will have a corresponding
   top-level window, and sets the title, typically displayed in the title bar
   or in window switchers.
*/
PUGL_API PuglStatus
puglSetWindowTitle(PuglView* view, const char* title);

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

   This must be called before puglRealize(), reparenting is not supported.
*/
PUGL_API PuglStatus
puglSetParentWindow(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().
*/
PUGL_API PuglStatus
puglSetTransientFor(PuglView* view, PuglNativeView parent);

/**
   Realise 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 puglGetNativeWindow().  There is currently no
   corresponding unrealize function, the system view will be destroyed along
   with the view when puglFreeView() is called.

   The view should be fully configured using the above functions before this is
   called.  This function may only be called once per view.
*/
PUGL_API PuglStatus
puglRealize(PuglView* view);

/**
   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.
*/
PUGL_API PuglStatus
puglShowWindow(PuglView* view);

/**
   Hide the current window.
*/
PUGL_API PuglStatus
puglHideWindow(PuglView* view);

/**
   Return true iff the view is currently visible.
*/
PUGL_API bool
puglGetVisible(const PuglView* view);

/**
   Return the native window handle.
*/
PUGL_API PuglNativeView
puglGetNativeWindow(PuglView* view);

/**
   @}
   @name Graphics
   Functions for working with the graphics context and scheduling redisplays.
   @{
*/

/**
   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.

   @return
   - OpenGL: `NULL`.
   - Cairo: A pointer to a
     [`cairo_t`](http://www.cairographics.org/manual/cairo-cairo-t.html).
*/
PUGL_API void*
puglGetContext(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.
*/
PUGL_API PuglStatus
puglPostRedisplay(PuglView* view);

/**
   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.
*/
PUGL_API PuglStatus
puglPostRedisplayRect(PuglView* view, PuglRect rect);

/**
   @}
   @anchor interaction
   @name Interaction
   Functions for interacting with the user and window system.
   @{
*/

/**
   Grab the keyboard input focus.
*/
PUGL_API PuglStatus
puglGrabFocus(PuglView* view);

/**
   Return whether `view` has the keyboard input focus.
*/
PUGL_API bool
puglHasFocus(const PuglView* view);

/**
   Set the clipboard contents.

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

   @param view The view.
   @param type The MIME type of the data, "text/plain" is assumed if `NULL`.
   @param data The data to copy to the clipboard.
   @param len The length of data in bytes (including terminator if necessary).
*/
PUGL_API PuglStatus
puglSetClipboard(PuglView*   view,
                 const char* type,
                 const void* data,
                 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.

   @param view The view.
   @param[out] type Set to the MIME type of the data.
   @param[out] len Set to the length of the data in bytes.
   @return The clipboard contents.
*/
PUGL_API const void*
puglGetClipboard(PuglView* view, const char** type, size_t* len);

/**
   Request user attention.

   This hints to the system that the window or application requires attention
   from the user.  The exact effect depends on the platform, but is usually
   something like a flashing task bar entry or bouncing application icon.
*/
PUGL_API PuglStatus
puglRequestAttention(PuglView* view);

/**
   Activate a repeating timer event.

   This starts a timer which will send a #PuglEventTimer 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.

   @param view The view to begin seding #PUGL_TIMER events to.

   @param 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.

   @param 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.

   @return #PUGL_SUCCESS, #PUGL_FAILURE if timers are not supported on this
   system, or an error code.
*/
PUGL_API PuglStatus
puglStartTimer(PuglView* view, uintptr_t id, double timeout);

/**
   Stop an active timer.

   @param view The view that the timer is set for.
   @param id The ID previously passed to puglStartTimer().
   @return #PUGL_SUCCESS, or #PUGL_FAILURE if no such timer was found.
*/
PUGL_API PuglStatus
puglStopTimer(PuglView* view, uintptr_t id);

/**
   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, and will return PUGL_UNSUPPORTED_TYPE for events that are not
   supported.
*/
PUGL_API PuglStatus
puglSendEvent(PuglView* view, const PuglEvent* event);

/**
   @}
*/

#ifndef PUGL_DISABLE_DEPRECATED

/**
   @}
   @name Deprecated API
   @{
*/

/**
   A native window handle.

   X11: This is a `Window`.

   MacOS: This is a pointer to an `NSView*`.

   Windows: This is a `HWND`.
*/
typedef uintptr_t PuglNativeWindow;

/**
   Create a Pugl application and view.

   To create a window, call the various puglInit* functions as necessary, then
   call puglRealize().

   @deprecated Use puglNewApp() and puglNewView().

   @param pargc Pointer to argument count (currently unused).
   @param argv  Arguments (currently unused).
   @return A newly created view.
*/
static inline PUGL_DEPRECATED_BY("puglNewView") PuglView*
puglInit(const int* pargc, char** argv)
{
	(void)pargc;
	(void)argv;

	return puglNewView(puglNewWorld(PUGL_MODULE, 0));
}

/**
   Destroy an app and view created with `puglInit()`.

   @deprecated Use puglFreeApp() and puglFreeView().
*/
static inline PUGL_DEPRECATED_BY("puglFreeView") void
puglDestroy(PuglView* view)
{
	PuglWorld* const world = puglGetWorld(view);

	puglFreeView(view);
	puglFreeWorld(world);
}

/**
   Set the window class name before creating a window.
*/
static inline PUGL_DEPRECATED_BY("puglSetClassName") void
puglInitWindowClass(PuglView* view, const char* name)
{
	puglSetClassName(puglGetWorld(view), name);
}

/**
   Set the window size before creating a window.

   @deprecated Use puglSetFrame().
*/
static inline PUGL_DEPRECATED_BY("puglSetFrame") void
puglInitWindowSize(PuglView* view, int width, int height)
{
	PuglRect frame = puglGetFrame(view);

	frame.width = width;
	frame.height = height;

	puglSetFrame(view, frame);
}

/**
   Set the minimum window size before creating a window.
*/
static inline PUGL_DEPRECATED_BY("puglSetMinSize") void
puglInitWindowMinSize(PuglView* view, int width, int height)
{
	puglSetMinSize(view, width, height);
}

/**
   Set the window aspect ratio range before creating a window.

   The x and y values here represent a ratio of width to height.  To set a
   fixed aspect ratio, set the minimum and maximum values to the same ratio.

   Note that setting different minimum and maximum constraints does not
   currenty work on MacOS (the minimum is used), so only setting a fixed aspect
   ratio works properly across all platforms.
*/
static inline PUGL_DEPRECATED_BY("puglSetAspectRatio") void
puglInitWindowAspectRatio(PuglView* view,
                          int       minX,
                          int       minY,
                          int       maxX,
                          int       maxY)
{
	puglSetAspectRatio(view, minX, minY, maxX, maxY);
}

/**
   Set transient parent before creating a window.

   On X11, parent must be a Window.
   On OSX, parent must be an NSView*.
*/
static inline PUGL_DEPRECATED_BY("puglSetTransientFor") void
puglInitTransientFor(PuglView* view, uintptr_t parent)
{
	puglSetTransientFor(view, (PuglNativeWindow)parent);
}

/**
   Enable or disable resizing before creating a window.

   @deprecated Use puglSetViewHint() with #PUGL_RESIZABLE.
*/
static inline PUGL_DEPRECATED_BY("puglSetViewHint") void
puglInitResizable(PuglView* view, bool resizable)
{
	puglSetViewHint(view, PUGL_RESIZABLE, resizable);
}

/**
   Get the current size of the view.

   @deprecated Use puglGetFrame().

*/
static inline PUGL_DEPRECATED_BY("puglGetFrame") void
puglGetSize(PuglView* view, int* width, int* height)
{
	const PuglRect frame = puglGetFrame(view);

	*width  = (int)frame.width;
	*height = (int)frame.height;
}

/**
   Ignore synthetic repeated key events.

   @deprecated Use puglSetViewHint() with #PUGL_IGNORE_KEY_REPEAT.
*/
static inline PUGL_DEPRECATED_BY("puglSetViewHint") void
puglIgnoreKeyRepeat(PuglView* view, bool ignore)
{
	puglSetViewHint(view, PUGL_IGNORE_KEY_REPEAT, ignore);
}

/**
   Set a hint before creating a window.

   @deprecated Use puglSetWindowHint().
*/
static inline PUGL_DEPRECATED_BY("puglSetViewHint") void
puglInitWindowHint(PuglView* view, PuglViewHint hint, int value)
{
	puglSetViewHint(view, hint, value);
}

/**
   Set the parent window before creating a window (for embedding).

   @deprecated Use puglSetWindowParent().
*/
static inline PUGL_DEPRECATED_BY("puglSetParentWindow") void
puglInitWindowParent(PuglView* view, PuglNativeWindow parent)
{
	puglSetParentWindow(view, parent);
}

/**
   Set the graphics backend to use.

   @deprecated Use puglSetBackend().
*/
static inline PUGL_DEPRECATED_BY("puglSetBackend") int
puglInitBackend(PuglView* view, const PuglBackend* backend)
{
	return (int)puglSetBackend(view, backend);
}

/**
   Realise a view by creating a corresponding system view or window.

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

   @deprecated Use puglRealize(), or just show the view.
*/
static inline PUGL_DEPRECATED_BY("puglRealize") PuglStatus
puglCreateWindow(PuglView* view, const char* title)
{
	puglSetWindowTitle(view, title);
	return puglRealize(view);
}

/**
   Block and wait for an event to be ready.

   This can be used in a loop to only process events via puglProcessEvents when
   necessary.  This function will block indefinitely if no events are
   available, so is not appropriate for use in programs that need to perform
   regular updates (e.g. animation).

   @deprecated Use puglPollEvents().
*/
PUGL_API PUGL_DEPRECATED_BY("puglPollEvents") PuglStatus
puglWaitForEvent(PuglView* view);

/**
   Process all pending window events.

   This handles input events as well as rendering, so it should be called
   regularly and rapidly enough to keep the UI responsive.  This function does
   not block if no events are pending.

   @deprecated Use puglDispatchEvents().
*/
PUGL_API PUGL_DEPRECATED_BY("puglDispatchEvents") PuglStatus
puglProcessEvents(PuglView* view);

/**
   Poll for events that are ready to be processed.

   This polls for events that are ready for any view in the world, potentially
   blocking depending on `timeout`.

   @param world The world to poll for events.

   @param timeout Maximum time to wait, in seconds.  If zero, the call returns
   immediately, if negative, the call blocks indefinitely.

   @return #PUGL_SUCCESS if events are read, #PUGL_FAILURE if not, or an error.

   @deprecated Use puglUpdate().
*/
PUGL_API PUGL_DEPRECATED_BY("puglUpdate") PuglStatus
puglPollEvents(PuglWorld* world, double timeout);

/**
   Dispatch any pending events to views.

   This processes all pending events, dispatching them to the appropriate
   views.  View event handlers will be called in the scope of this call.  This
   function does not block, if no events are pending then it will return
   immediately.

   @deprecated Use puglUpdate().
*/
PUGL_API PUGL_DEPRECATED_BY("puglUpdate") PuglStatus
puglDispatchEvents(PuglWorld* world);

/**
   Enter the graphics context.

   Note that, unlike some similar libraries, Pugl automatically enters and
   leaves the graphics context when required and application should not
   normally do this.  Drawing in Pugl is only allowed during the processing of
   an expose event.

   However, this can be used to enter the graphics context elsewhere, for
   example to call any GL functions during setup.

   @param view The view being entered.
   @param drawing If true, prepare for drawing.

   @deprecated Set up graphics when a #PUGL_CREATE event is received.
*/
PUGL_API PUGL_DEPRECATED_BY("PUGL_CREATE") PuglStatus
puglEnterContext(PuglView* view, bool drawing);

/**
   Leave the graphics context.

   This must be called after puglEnterContext() with a matching `drawing`
   parameter.

   @param view The view being left.
   @param drawing If true, finish drawing, for example by swapping buffers.

   @deprecated Shut down graphics when a #PUGL_DESTROY event is received.
*/
PUGL_API PUGL_DEPRECATED_BY("PUGL_DESTROY") PuglStatus
puglLeaveContext(PuglView* view, bool drawing);

#endif  /* PUGL_DISABLE_DEPRECATED */

/**
   @}
   @}
*/

PUGL_END_DECLS

#endif  /* PUGL_PUGL_H */