Browse code

Standardize OpenGL-related #includes and #defines

We use glXGetProcAddress to load glXCreateContextAttribsARB ourselves,
so GLX_GLXEXT_PROTOTYPES is not needed.

Robert Cranston authored on 27/02/2024 02:27:47
Showing 1 changed files
... ...
@@ -69,7 +69,7 @@
69 69
 #define GL_SILENCE_DEPRECATION
70 70
 
71 71
 #import <Cocoa/Cocoa.h>
72
-#include <OpenGL/gl.h>
72
+#include <OpenGL/gl3.h>
73 73
 #include <stdlib.h>
74 74
 #include <stdio.h>
75 75
 #include <stddef.h>
Browse code

Convert encoding from MacRoman to UTF-8

Swedish characters use a weird encoding. For instance, `file --mime`
just gives `charset=unknown-8bit` and `grep` just says `binary file
matches`.

Searching for them in the [Western Latin character sets comparison
table][] gives that this is the old [Mac OS Roman][] (MIME / IANA:
`macintosh`). Tooling support for this outside of Macs is very poor, as
can be seen above.

[Western Latin character sets comparison table]: https://en.wikipedia.org/wiki/Western_Latin_character_sets_(computing)#Comparison_table
[Mac OS Roman]: https://en.wikipedia.org/wiki/Mac_OS_Roman

To convert:

tmp_file="$(mktemp)"
trap 'rm "$tmp_file"' EXIT
find . -type f -exec file --mime {} + \
| while IFS=':' read file mime
do
if echo "$mime" | grep -qi 'charset=unknown-8bit'
then
iconv -f 'macintosh' -t 'utf-8' "$file" -o "$tmp_file"
mv "$tmp_file" "$file"
fi
done

Robert Cranston authored on 27/02/2024 02:27:29
Showing 1 changed files
... ...
@@ -25,7 +25,7 @@
25 25
 // 120301: Resizable window. Correct vertical window position.
26 26
 // 120808: Fixed a bug that caused error messages. (Calling finishLaunching twice.)
27 27
 // 120822: Stencil now uses 8 instead of 32
28
-// 120905: Two corrections suggested by Marcus Stenb�ck.
28
+// 120905: Two corrections suggested by Marcus Stenbäck.
29 29
 // 120913: Added 2-button emulation with CTRL
30 30
 // 130103: Added [m_context makeCurrentContext]; in all user callbacks. (GL calls had no effect.)
31 31
 // 130127: Added basic popup menu support
... ...
@@ -411,7 +411,7 @@ NSPoint gMousePosition;
411 411
 	}
412 412
 }
413 413
 
414
-// Clone of above, but necessary for supporting the alternative button. Thanks to Marcus Stenb�ck!
414
+// Clone of above, but necessary for supporting the alternative button. Thanks to Marcus Stenbäck!
415 415
 -(void) rightMouseDragged:(NSEvent *)theEvent
416 416
 {
417 417
 	NSPoint p;
... ...
@@ -752,7 +752,7 @@ void glutInit(int *argcp, char **argv)
752 752
 	pool = [NSAutoreleasePool new];
753 753
 	myApp = [MGApplication sharedApplication];
754 754
 	
755
-	[NSApp setActivationPolicy: NSApplicationActivationPolicyRegular]; // Thanks to Marcus Stenb�ck
755
+	[NSApp setActivationPolicy: NSApplicationActivationPolicyRegular]; // Thanks to Marcus Stenbäck
756 756
 	
757 757
 	gRunning = 1;
758 758
 	home();
... ...
@@ -1147,8 +1147,8 @@ void glutWarpPointer(int x, int y)
1147 1147
 
1148 1148
 // Deprecation hell below:
1149 1149
 //The NSWindow class provides these methods for converting between window local coordinates and screen global coordinates:
1150
-//	�	convertRectToScreen:
1151
-//	�	convertRectFromScreen:
1150
+//	•	convertRectToScreen:
1151
+//	•	convertRectFromScreen:
1152 1152
 //Use them instead of the deprecated convertBaseToScreen: and convertScreenToBase: methods.
1153 1153
 	NSRect mpmp;
1154 1154
 	mpmp.size.height = 0;
Browse code

Remove executable bit on files

find . -type f -exec chmod -x {} +

Robert Cranston authored on 27/02/2024 02:27:27
Showing 1 changed files
1 1
old mode 100755
2 2
new mode 100644
Browse code

Add cpp-v1

Ingemar Ragnemalm authored on 21/02/2024 20:24:28 • Robert Cranston committed on 21/02/2024 20:24:28
Showing 1 changed files
1 1
new file mode 100755
... ...
@@ -0,0 +1,1255 @@
1
+// Micro-GLUT, bare essentials
2
+// Mac version!
3
+// Single-file GLUT subset.
4
+// By Ingemar Ragnemalm 2012-2015
5
+
6
+// I wrote this since GLUT seems not to have been updated to support
7
+// creation of a 3.2 context on the Mac, plus that GLUT contains too
8
+// much deprecated material, and is impractical to modify. With a
9
+// single-file solution like this, there are no installation problems
10
+// at all and it is also easy to hack around in a local copy as needed.
11
+// Furthermore, this also removes all old deprecated code, and gives
12
+// better transparency. (Hack away!)
13
+
14
+// To do: iOS port. (Preliminary versions exists.)
15
+// Some additional features. Text rendering? Menus? (OK) Multi-window?
16
+
17
+// Changes:
18
+// Several additions for the lab 3 version: Simple menu, glutTimerFunc and my own glutrepeatingTimerFunc.
19
+// glutKeyboardUpFunc, glutInitDisplayMode.
20
+// 120209: Some more additions, like glutMotionFunc and GLUT_RIGHT_BUTTON.
21
+// 120228: Added glutSetWindowTitle, glutKeyIsDown, glutInitContextVersion
22
+// NOTE: glutInitContextVersion is now required for 3.2 code!
23
+// NOTE: This statement is incorrect; MicroGLUT still only supports 3.2 and with no extra calls.
24
+// Note however the GL3ONLY define.
25
+// 120301: Resizable window. Correct vertical window position.
26
+// 120808: Fixed a bug that caused error messages. (Calling finishLaunching twice.)
27
+// 120822: Stencil now uses 8 instead of 32
28
+// 120905: Two corrections suggested by Marcus Stenb�ck.
29
+// 120913: Added 2-button emulation with CTRL
30
+// 130103: Added [m_context makeCurrentContext]; in all user callbacks. (GL calls had no effect.)
31
+// 130127: Added basic popup menu support
32
+// 130214: Added glutSpecialFunc and glutSpecialUpFunc. Sets focus to window when created.
33
+// 130220: Modified idle support, added fake visibility support.
34
+// 130325: Corrected name of glutWarpPointer
35
+// 130330: Added GLUT_MULTISAMPLE
36
+// 130331: Added glutChangeMenuEntry
37
+// 130513: Added GLUT_WINDOW_WIDTH and GLUT_WINDOW_HEIGHT support to glutGet (which is still lacking a whole bunch of other types). Modified glutWarpPointer.
38
+// 130907: Added isFlipped to make mouse coordinates reasonable (and conform with Linux version).
39
+// 131011: Makes the context active before calling gReshape in case the reshape function calls OpenGL calls.
40
+// 140213: Rewrote glutWarpPointer.
41
+// 150205: Added glutPositionWindow and glutFullScreen plus glutExitFullScreen.
42
+// 150209: Small correction to full-screen mode, restores windows name!
43
+// 150424: Rewrote glutWarpPointer again!
44
+// 150520: Added glutExit().
45
+// 150618: Added glutMouseIsDown() (not in the old GLUT API but a nice extension!).
46
+// Added #ifdefs to produce errors if compiled on the wrong platform!
47
+// 150820: Minor bug fix in glutReshapeWindow.
48
+// 150827: Hacked around the needlessly deprecated convertBaseToScreen. Also skipped
49
+// CGSetLocalEventsSuppressionInterval which MIGHT not be needed...
50
+// 150918: More keys map properly to the GLUT constants, like GLUT_KEY_ESC.
51
+// Rewrote glutCheckLoop, now it seems to work fine. Tested with the "triangle" demo that lacks main loop.
52
+// Added GLUT_QUIT_FLAG for glutGet.
53
+// 150919: Added GLUT_MOUSE_POSITION_X and GLUT_MOUSE_POSITION_Y to glutGet.
54
+// 150923: Changed the keyboard special key constants to avoid all usable ASCII codes. This makes the "special key" calls unnecessary and keyboard handling simpler. We can stop using "special key" callbacks alltogether.
55
+// Some minor changes not documented.
56
+// 171019: Fixed a bug in context version handling.
57
+// 180208: Added activateIgnoringOtherApps to bring it to front when launched.
58
+// #include <Carbon/Carbon.h> removed. Might be needed on older OSX!
59
+// 181206: Changed the GlutView to inherit from NSOpenGLView instead of NSView.
60
+// 200926: Replaced a number of constants that have been renamed by Apple.
61
+// Also put in GL_SILENCE_DEPRECATION.
62
+// 210220: Change in drawRect, avoiding problem with random freezes. Also set swap to 1 = sync.
63
+
64
+// Incompatibility in mouse coordinates; global or local?
65
+// Should be local! (I think they are now!)
66
+
67
+// This silences most warnings but not the NS ones.
68
+//  -Wno-deprecated-declarations on command-line will silence all.
69
+#define GL_SILENCE_DEPRECATION
70
+
71
+#import <Cocoa/Cocoa.h>
72
+#include <OpenGL/gl.h>
73
+#include <stdlib.h>
74
+#include <stdio.h>
75
+#include <stddef.h>
76
+#include <string.h>
77
+#include <sys/time.h>
78
+
79
+#include "MicroGlut.h"
80
+
81
+// If this is compiled on something else than a Mac, tell me!
82
+#ifndef __APPLE__
83
+	ERROR! This (MicroGlut.m) is the Mac version of MicroGlut which will not work on other platforms!
84
+#endif
85
+
86
+// Comment out to support GL2, requiring glutInitContextVersion for newer.
87
+//#define GL3ONLY
88
+
89
+// Vital internal variables
90
+
91
+void (*gDisplay)(void);
92
+void (*gReshape)(int width, int height);
93
+void (*gKey)(unsigned char key, int x, int y);
94
+void (*gSpecialKey)(unsigned char key, int x, int y);
95
+void (*gKeyUp)(unsigned char key, int x, int y);
96
+void (*gSpecialKeyUp)(unsigned char key, int x, int y);
97
+void (*gMouseMoved)(int x, int y);
98
+void (*gMouseDragged)(int x, int y);
99
+void (*gMouseFunc)(int button, int state, int x, int y);
100
+unsigned int gContextInitMode = GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH;
101
+void (*gIdle)(void);
102
+char updatePending = 1;
103
+char gRunning = 1;
104
+char gKeymap[256];
105
+char gButtonPressed[10] = {0,0,0,0,0,0,0,0,0,0};
106
+int gContextVersionMajor = 0;
107
+int gContextVersionMinor = 0;
108
+char gTitle[255] = "MicroGlut window"; // Saved title, so we can restore after full screen!
109
+
110
+// -----------
111
+
112
+// Globals (was in GLViewDataPtr)
113
+NSOpenGLContext	*m_context;
114
+float lastWidth, lastHeight;
115
+NSView *theView;
116
+
117
+// Full screen support
118
+NSRect gSavedWindowPosition;
119
+char gFullScreen = 0;
120
+// See glutReshapeWindow, glutPositionWindow and glutFullScreen
121
+
122
+void MakeContext(NSView *view)
123
+{
124
+	NSOpenGLPixelFormat *fmt;
125
+	int zdepth, sdepth, i;
126
+	int profile = 0, profileVersion = 0;
127
+	
128
+	if (gContextInitMode & GLUT_DEPTH)
129
+		zdepth = 32;
130
+	else
131
+		zdepth = 0;
132
+	
133
+	if (gContextInitMode & GLUT_STENCIL)
134
+		sdepth = 8;
135
+	else
136
+		sdepth = 0;
137
+
138
+	NSOpenGLPixelFormatAttribute attrs[] =
139
+	{
140
+//		NSOpenGLPFAPixelBuffer,
141
+//		NSOpenGLPFAAccelerated,
142
+//		NSOpenGLPFADoubleBuffer,
143
+		NSOpenGLPFADepthSize, zdepth,
144
+		NSOpenGLPFAStencilSize, sdepth,
145
+		0,0,0,0,0,0,0
146
+//		profile, profileVersion,
147
+//		multi,
148
+	};
149
+	
150
+	i = 4;
151
+	
152
+// Def this out about for disabling profile selection support,
153
+// if it is on we are defaulting to GL 1/2
154
+#ifndef GL3ONLY
155
+	if (gContextVersionMajor >= 3)
156
+#endif
157
+	// I ignore the minor version for now, 3.2 is all we can choose currently
158
+	{
159
+		profile = NSOpenGLPFAOpenGLProfile;
160
+		profileVersion = NSOpenGLProfileVersion3_2Core;
161
+		attrs[i++] = profile;
162
+		attrs[i++] = profileVersion;
163
+	}
164
+
165
+	if (gContextInitMode & GLUT_DOUBLE)
166
+	{
167
+		attrs[i++] = NSOpenGLPFADoubleBuffer;
168
+	}
169
+	
170
+	if (gContextInitMode & GLUT_MULTISAMPLE)
171
+	{
172
+		attrs[i++] = NSOpenGLPFAMultisample;
173
+	}
174
+	
175
+	// Save view (should be packaged with context for multi-window application - to do)
176
+	theView = view;
177
+	
178
+	// Init GL context
179
+	fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: &attrs[0]];
180
+	
181
+	m_context = [[NSOpenGLContext alloc] initWithFormat: fmt shareContext: nil];
182
+	[fmt release];
183
+//	[m_context makeCurrentContext];
184
+
185
+	int iSwap = 1;
186
+	[m_context setValues:&iSwap forParameter:NSOpenGLCPSwapInterval];
187
+
188
+
189
+//	[m_context setView: theView];
190
+	[m_context makeCurrentContext];
191
+}
192
+
193
+// ---------------------- Menus ----------------------
194
+
195
+// MicroGlut menu support
196
+// This is a subset of the GLUT menu support, focused on what seems to be used
197
+// in current GLUT-using demos. If nobody uses it, don't add it (unless it is
198
+// a feature that you really want people to learn using).
199
+
200
+typedef void (*MenuProc)(int value);
201
+@interface TPopupMenu : NSMenu {@public MenuProc funcCallback;}
202
+-(void)selectMenuItem:(id *)sender;
203
+@end
204
+
205
+@implementation TPopupMenu
206
+
207
+-(void)selectMenuItem:(id *)sender
208
+{
209
+	funcCallback( [((NSMenuItem *) sender) tag]);
210
+}
211
+
212
+@end
213
+
214
+TPopupMenu *currentMenu;
215
+
216
+TPopupMenu *buttons[10]; // Menu by button id - for a button, what menu should be used, if any?
217
+TPopupMenu *menuList[10]; // List of menus by (internal) menu id
218
+int menuCount = -1;
219
+
220
+int glutCreateMenu(void (*func)(int value))
221
+{
222
+	currentMenu = [[TPopupMenu alloc] initWithTitle: @""];
223
+	currentMenu->funcCallback = func;
224
+	menuCount += 1;
225
+	menuList[menuCount] = currentMenu;
226
+	return menuCount;
227
+}
228
+void glutAddMenuEntry(char *name, int value)
229
+{
230
+	NSMenuItem *menuItem1;
231
+	
232
+	menuItem1 = NSMenuItem.alloc;
233
+	// string to NSString
234
+	NSString * s = [NSString stringWithCString: name encoding: NSASCIIStringEncoding];
235
+	[menuItem1 initWithTitle: s action: nil keyEquivalent: @""];
236
+	[menuItem1 setTarget: currentMenu]; // Who will handle it?
237
+	[menuItem1 setAction: @selector(selectMenuItem:)];
238
+	[menuItem1 setTag: value]; // Save value
239
+	[currentMenu addItem: menuItem1];
240
+}
241
+
242
+void glutChangeToMenuEntry(int index, char *name, int value)
243
+{
244
+	NSMenuItem *menuItem1;
245
+	
246
+	menuItem1 = [currentMenu itemAtIndex: index-1];
247
+	if (menuItem1 != NULL)
248
+	{
249
+		// string to NSString
250
+		NSString * s = [NSString stringWithCString: name encoding: NSASCIIStringEncoding];
251
+		[menuItem1 setTarget: currentMenu]; // Who will handle it?
252
+		[menuItem1 setAction: @selector(selectMenuItem:)];
253
+		[menuItem1 setTag: value]; // Save value
254
+		[menuItem1 setTitle: s];
255
+	}
256
+}
257
+
258
+
259
+
260
+void glutAttachMenu(int button)
261
+{
262
+	// set a data item for the button
263
+	buttons[button] = currentMenu;
264
+}
265
+
266
+void glutAddSubMenu(char *name, int menu)
267
+{
268
+	NSMenuItem *item;
269
+	NSString * s = [NSString stringWithCString: name encoding: NSASCIIStringEncoding];
270
+	
271
+	item = [currentMenu addItemWithTitle: s action: nil keyEquivalent: @""];
272
+	[currentMenu setSubmenu: menuList[menu] forItem: item];
273
+}
274
+
275
+void glutDetachMenu(int button)
276
+{
277
+	// reset a data item for the button
278
+	buttons[button] = nil;	
279
+}
280
+
281
+// Check name on this!
282
+void glutSetMenu(int menu)
283
+{
284
+	currentMenu = menuList[menu];
285
+}
286
+
287
+int glutGetMenu(void)
288
+{
289
+	int i;
290
+	for (i = 0; i <= menuCount; i++)
291
+		if (menuList[i] == currentMenu)
292
+			return i;
293
+	return -1;
294
+}
295
+
296
+// End of MicroGlut button support
297
+
298
+
299
+static void doKeyboardEvent(NSEvent *theEvent, void (*func)(unsigned char key, int x, int y), void (*specialfunc)(unsigned char key, int x, int y), int keyMapValue)
300
+{
301
+	char *chars;
302
+	
303
+	chars = (char *)[[theEvent characters] cStringUsingEncoding: NSMacOSRomanStringEncoding];
304
+	NSPoint mouseDownPos = [theEvent locationInWindow];
305
+
306
+	if (chars != NULL)
307
+	{
308
+		if (func != NULL) // Change 120913
309
+			func(chars[0], mouseDownPos.x, mouseDownPos.y); // TO DO: x and y
310
+		
311
+		gKeymap[(unsigned int)chars[0]] = keyMapValue;
312
+	}
313
+	else
314
+	{
315
+		char code;
316
+		switch( [theEvent keyCode] )
317
+		{
318
+			case 0x35: code = GLUT_KEY_ESC; break;
319
+			case 0x30: code = GLUT_KEY_TAB; break;
320
+			case 0x24: code = GLUT_KEY_RETURN; break;
321
+			case 0x31: code = GLUT_KEY_SPACE; break;
322
+			case 0x29: code = GLUT_KEY_SEMICOLON; break;
323
+			case 0x2B: code = GLUT_KEY_COMMA; break;
324
+			case 0x2F: code = GLUT_KEY_DECIMAL; break;
325
+			case 0x32: code = GLUT_KEY_GRAVE; break;
326
+			case 0x27: code = GLUT_KEY_QUOTE; break;
327
+			case 0x21: code = GLUT_KEY_LBRACKET; break;
328
+			case 0x1E: code = GLUT_KEY_RBRACKET; break;
329
+			case 0x2A: code = GLUT_KEY_BACKSLASH; break;
330
+			case 0x2C: code = GLUT_KEY_SLASH; break;
331
+			case 0x18:
332
+			case 0x51: code = GLUT_KEY_EQUAL; break;
333
+
334
+			case 126: code = GLUT_KEY_UP; break;
335
+			case 125: code = GLUT_KEY_DOWN; break;
336
+			case 124: code = GLUT_KEY_RIGHT; break;
337
+			case 123: code = GLUT_KEY_LEFT; break;
338
+			case 122: code = GLUT_KEY_F1; break;
339
+			case 120: code = GLUT_KEY_F2; break;
340
+			case 99: code = GLUT_KEY_F3; break;
341
+			case 118: code = GLUT_KEY_F4; break;
342
+			case 96: code = GLUT_KEY_F5; break;
343
+			case 97: code = GLUT_KEY_F6; break;
344
+			case 98: code = GLUT_KEY_F7; break;
345
+			case 115: code = GLUT_KEY_HOME; break; // ?
346
+			case 116: code = GLUT_KEY_PAGE_UP; break;
347
+			case 119: code = GLUT_KEY_END; break; // ?
348
+			case 121: code = GLUT_KEY_PAGE_DOWN; break;
349
+			case 117: code = GLUT_KEY_INSERT; break; // Looks more like DEL?
350
+			default: code = [theEvent keyCode];
351
+		}
352
+		if (specialfunc != NULL) // Change 130114
353
+			specialfunc(code, mouseDownPos.x, mouseDownPos.y); // TO DO: x and y
354
+		else // If no special, send to normal (future preferred way)
355
+		if (func != NULL) // Change 150114
356
+			func(code, mouseDownPos.x, mouseDownPos.y); // TO DO: x and y
357
+// NOTE: This was a bug until I modified the special key constants! We can now check gKeymap with normal ASCII and special codes with the same table!
358
+		gKeymap[(int)code] = keyMapValue;
359
+	}
360
+}
361
+
362
+
363
+// -------------------- View ------------------------
364
+
365
+@interface GlutView : NSOpenGLView <NSWindowDelegate> { }
366
+// Changed NSView to NSOpenGLView, and it worked.
367
+-(void)drawRect:(NSRect)rect;
368
+-(void)keyDown:(NSEvent *)theEvent;
369
+-(void)keyUp:(NSEvent *)theEvent;
370
+-(void)mouseMoved:(NSEvent *)theEvent;
371
+-(void)mouseDragged:(NSEvent *)theEvent;
372
+-(void)mouseDown:(NSEvent *)theEvent;
373
+-(void)mouseUp:(NSEvent *)theEvent;
374
+-(void)rightMouseDown:(NSEvent *)theEvent;
375
+-(void)rightMouseUp:(NSEvent *)theEvent;
376
+-(void)windowDidresize:(NSNotification *)note;
377
+-(BOOL)isFlipped;
378
+//-(void)setLayer:(CALayer*)layer; // Mojave???
379
+@end
380
+
381
+#define Pi 3.1415
382
+
383
+// Mouse position is saved so it can be retrieved at any time with glutGet
384
+NSPoint gMousePosition;
385
+
386
+@implementation GlutView
387
+
388
+-(void) mouseMoved:(NSEvent *)theEvent
389
+{
390
+//	NSPoint p;
391
+	[m_context makeCurrentContext];
392
+	
393
+	gMousePosition = [theEvent locationInWindow];
394
+	gMousePosition = [self convertPoint: gMousePosition fromView: nil];
395
+	if (gMouseMoved != nil)
396
+	{
397
+		gMouseMoved(gMousePosition.x, gMousePosition.y);
398
+	}
399
+}
400
+
401
+-(void) mouseDragged:(NSEvent *)theEvent
402
+{
403
+	NSPoint p;
404
+	[m_context makeCurrentContext];
405
+	
406
+	if (gMouseDragged != nil)
407
+	{
408
+		p = [theEvent locationInWindow];
409
+		p = [self convertPoint: p fromView: nil];
410
+		gMouseDragged((int)p.x, (int)p.y);
411
+	}
412
+}
413
+
414
+// Clone of above, but necessary for supporting the alternative button. Thanks to Marcus Stenb�ck!
415
+-(void) rightMouseDragged:(NSEvent *)theEvent
416
+{
417
+	NSPoint p;
418
+	[m_context makeCurrentContext];
419
+	
420
+	if (gMouseDragged != nil)
421
+	{
422
+		p = [theEvent locationInWindow];
423
+		p = [self convertPoint: p fromView: nil];
424
+		gMouseDragged((int)p.x, (int)p.y);
425
+	}
426
+}
427
+
428
+// Remember if last press on the left (default) button was modified to
429
+// a "right" with CTRL
430
+char gLeftIsRight = 0;
431
+
432
+-(void) mouseDown:(NSEvent *)theEvent
433
+{
434
+	NSPoint p;
435
+	[m_context makeCurrentContext];
436
+	
437
+	gButtonPressed[0] = 1; // Could maybe be modified by NSControlKeyMask...?
438
+
439
+	if (gMouseFunc != nil)
440
+	{
441
+		// Convert location in window to location in view
442
+		p = [theEvent locationInWindow];
443
+//	printf("mouseDown before convertPoint %f %f \n", p.x, p.y);
444
+		p = [self convertPoint: p fromView: nil];
445
+//	printf("mouseDown %f %f \n", p.x, p.y);
446
+		
447
+//		if ([NSEvent modifierFlags] & NSControlKeyMask)
448
+		if ([NSEvent modifierFlags] & NSEventModifierFlagControl)
449
+		{
450
+			gMouseFunc(GLUT_RIGHT_BUTTON, GLUT_DOWN, p.x, p.y);
451
+			gLeftIsRight = 1;
452
+		}
453
+		else
454
+		{
455
+			gMouseFunc(GLUT_LEFT_BUTTON, GLUT_DOWN, p.x, p.y);
456
+			gLeftIsRight = 0;
457
+		}
458
+	}
459
+//	else
460
+
461
+//	if ([NSEvent modifierFlags] & NSControlKeyMask)
462
+	if ([NSEvent modifierFlags] & NSEventModifierFlagControl)
463
+	{
464
+		if (buttons[GLUT_RIGHT_BUTTON] != nil)
465
+			[NSMenu popUpContextMenu: buttons[GLUT_RIGHT_BUTTON]
466
+						withEvent: theEvent forView: (NSButton *)self];
467
+	}
468
+	else
469
+	{
470
+		if (buttons[GLUT_LEFT_BUTTON] != nil)
471
+			[NSMenu popUpContextMenu: buttons[GLUT_LEFT_BUTTON]
472
+						withEvent: theEvent forView: (NSButton *)self];
473
+	}
474
+}
475
+
476
+-(void) mouseUp:(NSEvent *)theEvent
477
+{
478
+	NSPoint p;
479
+	[m_context makeCurrentContext];
480
+
481
+	gButtonPressed[0] = 0;
482
+
483
+	if (gMouseFunc != nil)
484
+	{
485
+		// Convert location in window to location in view
486
+		p = [theEvent locationInWindow];
487
+		p = [self convertPoint: p fromView: nil];
488
+		
489
+		// Assuming that the user won't release CTRL - then it looks like different buttons
490
+		if (gLeftIsRight)
491
+			gMouseFunc(GLUT_RIGHT_BUTTON, GLUT_UP, p.x, p.y);
492
+		else
493
+			gMouseFunc(GLUT_LEFT_BUTTON, GLUT_UP, p.x, p.y);
494
+	}
495
+}
496
+
497
+-(void) rightMouseDown:(NSEvent *)theEvent
498
+{
499
+	NSPoint p;
500
+	[m_context makeCurrentContext];
501
+	
502
+	gButtonPressed[1] = 1;
503
+
504
+	if (gMouseFunc != nil)
505
+	{
506
+		// Convert location in window to location in view
507
+		p = [theEvent locationInWindow];
508
+		p = [self convertPoint: p fromView: nil];
509
+		gMouseFunc(GLUT_RIGHT_BUTTON, GLUT_DOWN, p.x, p.y);
510
+	}
511
+	else
512
+		if (buttons[GLUT_RIGHT_BUTTON] != nil)
513
+			[NSMenu popUpContextMenu: buttons[GLUT_RIGHT_BUTTON]
514
+						withEvent: theEvent forView: (NSButton *)self];
515
+}
516
+
517
+-(void) rightMouseUp:(NSEvent *)theEvent
518
+{
519
+	NSPoint p;
520
+	[m_context makeCurrentContext];
521
+
522
+	gButtonPressed[1] = 0;
523
+
524
+	if (gMouseFunc != nil)
525
+	{
526
+		// Convert location in window to location in view
527
+		p = [theEvent locationInWindow];
528
+		p = [self convertPoint: p fromView: nil];
529
+		gMouseFunc(GLUT_RIGHT_BUTTON, GLUT_UP, p.x, p.y);
530
+	}
531
+}
532
+
533
+-(void)keyDown:(NSEvent *)theEvent
534
+{
535
+	[m_context makeCurrentContext];
536
+	doKeyboardEvent(theEvent, gKey, gSpecialKey, 1);
537
+}
538
+
539
+-(void)keyUp:(NSEvent *)theEvent
540
+{
541
+	[m_context makeCurrentContext];
542
+	doKeyboardEvent(theEvent, gKeyUp, gSpecialKeyUp, 0);
543
+}
544
+
545
+- (BOOL)acceptsFirstResponder	{ return YES; }
546
+
547
+- (BOOL)becomeFirstResponder	{ return YES; }
548
+
549
+- (BOOL)resignFirstResponder	{ return YES; }
550
+
551
+-(void)drawRect:(NSRect)rect
552
+{
553
+	[m_context clearDrawable];
554
+	[m_context setView: theView];
555
+	[m_context makeCurrentContext];
556
+
557
+	if (([theView frame].size.width != lastWidth) || ([theView frame].size.height != lastHeight))
558
+	{
559
+		lastWidth = [theView frame].size.width;
560
+		lastHeight = [theView frame].size.height;
561
+		
562
+		// Only needed on resize:
563
+//		[m_context clearDrawable];
564
+//		glViewport(0, 0, [theView frame].size.width, [theView frame].size.height);
565
+		
566
+		if (gReshape != NULL)
567
+		{
568
+//			[m_context setView: theView]; // Make the view current in case gReshape calls OpenGL
569
+//			[m_context makeCurrentContext]; // 131011
570
+			gReshape([theView frame].size.width, [theView frame].size.height);
571
+		}
572
+	}
573
+	
574
+	// Draw
575
+	updatePending = 0; // Did not help
576
+	if (gDisplay != NULL)
577
+		gDisplay();
578
+	
579
+	[m_context flushBuffer];
580
+//	[NSOpenGLContext clearCurrentContext];
581
+}
582
+
583
+-(void)windowWillClose:(NSNotification *)note
584
+{
585
+	[[NSApplication sharedApplication] terminate:self];
586
+}
587
+
588
+-(void)windowDidresize:(NSNotification *)note
589
+{
590
+	// Call gReshape now or in drawRect?
591
+}
592
+
593
+-(BOOL)isFlipped
594
+{
595
+	return YES;
596
+}
597
+
598
+// This was supposed to help for NSView but it didn't.
599
+//-(void)setLayer:(CALayer*)layer;
600
+//{
601
+//	[super setLayer:layer];
602
+//	[m_context update];
603
+//}
604
+
605
+@end
606
+
607
+
608
+// -------------------- Timer ------------------------
609
+
610
+// Data for timer
611
+@interface TimerInfoRec : NSObject
612
+{
613
+@public	void (*func)(int arg);
614
+	int arg;
615
+@private
616
+}
617
+@end
618
+
619
+@implementation TimerInfoRec
620
+@end
621
+
622
+// Mini-mini class for the timer
623
+@interface TimerController : NSObject { }
624
+-(void)timerFireMethod:(NSTimer *)t;
625
+@end
626
+
627
+NSTimer	*gTimer;
628
+TimerController	*myTimerController;
629
+NSView	*view;
630
+
631
+// Timer!
632
+@implementation TimerController
633
+-(void)timerFireMethod:(NSTimer *)t;
634
+{
635
+	TimerInfoRec *tr;
636
+	
637
+	if (t.userInfo != nil) // One-shot timer with a TimerInfoRec
638
+	{
639
+		tr = t.userInfo;
640
+		tr->func(tr->arg);
641
+		[tr release];
642
+//		((TimerInfoRec *)(t.userInfo))->func(((TimerInfoRec *)(t.userInfo))->arg);
643
+//		free((TimerInfoRec *)(t.userInfo));
644
+	}
645
+	else
646
+	{
647
+		[view setNeedsDisplay: YES];
648
+		updatePending = 1;
649
+	}
650
+}
651
+@end
652
+
653
+
654
+void glutPostRedisplay()
655
+{
656
+	[theView setNeedsDisplay: YES];
657
+	updatePending = 1;
658
+}
659
+
660
+//void home()
661
+//{
662
+//	p = Bundle.main.path(forResource: "???", ofType: "???");
663
+//}
664
+
665
+// home()
666
+
667
+#include <stdio.h>
668
+
669
+void home()
670
+{
671
+	CFBundleRef mainBundle = CFBundleGetMainBundle();
672
+	CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
673
+	char path[PATH_MAX];
674
+	if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
675
+	{
676
+		// error!
677
+		return;
678
+	}
679
+	CFRelease(resourcesURL);
680
+
681
+	chdir(path);
682
+//	printf("Current Path: %s\n", path);
683
+}
684
+
685
+// ------------------ Main program ---------------------
686
+
687
+@interface MGApplication : NSApplication
688
+@end
689
+
690
+@implementation MGApplication
691
+/* Invoked from the Quit menu item */
692
+- (void)terminate:(id)sender
693
+{
694
+	gRunning = 0;
695
+}
696
+@end
697
+
698
+NSApplication *myApp;
699
+NSView *view;
700
+NSAutoreleasePool *pool;
701
+NSWindow *window;
702
+static struct timeval timeStart;
703
+
704
+void CreateMenu()
705
+{
706
+	NSMenu *mainMenu, *theMiniMenu;
707
+	NSMenuItem *menuItem2, *dummyItem;
708
+
709
+	// Create main menu = menu bar
710
+	mainMenu = NSMenu.alloc;
711
+	[mainMenu initWithTitle: @""];
712
+	[NSApp setMainMenu: mainMenu];
713
+
714
+	// Create the custom menu
715
+	theMiniMenu = NSMenu.alloc;
716
+	[theMiniMenu initWithTitle: @"The MiniMenu"];
717
+	
718
+	// Create a menu item with standard message
719
+	menuItem2 = NSMenuItem.alloc;
720
+	[menuItem2 initWithTitle: @"Hide" action: @selector(hide:) keyEquivalent: @"h"];
721
+	[menuItem2 setKeyEquivalentModifierMask: NSEventModifierFlagCommand];
722
+	[theMiniMenu addItem: menuItem2];
723
+	
724
+	// Create a menu item with standard message
725
+	menuItem2 = NSMenuItem.alloc;
726
+	[menuItem2 initWithTitle: @"Hide others" action: @selector(hideOtherApplications:) keyEquivalent: @"h"];
727
+	[menuItem2 setKeyEquivalentModifierMask: NSEventModifierFlagCommand | NSEventModifierFlagOption];
728
+	[theMiniMenu addItem: menuItem2];
729
+	
730
+	// Create a menu item with standard message
731
+	menuItem2 = NSMenuItem.alloc;
732
+	[menuItem2 initWithTitle: @"Show all" action: @selector(unhideAllApplications:) keyEquivalent: @"h"];
733
+	[menuItem2 setKeyEquivalentModifierMask: NSEventModifierFlagCommand | NSEventModifierFlagControl];
734
+	[theMiniMenu addItem: menuItem2];
735
+	
736
+	// Create a menu item with standard message
737
+	menuItem2 = NSMenuItem.alloc;
738
+	[menuItem2 initWithTitle: @"Quit" action: @selector(terminate:) keyEquivalent: @"q"];
739
+	[menuItem2 setKeyEquivalentModifierMask: NSEventModifierFlagCommand];
740
+	[theMiniMenu addItem: menuItem2];
741
+	
742
+	// Adding a menu is done with a dummy item to connect the menu to its parent
743
+	dummyItem = NSMenuItem.alloc;
744
+	[dummyItem initWithTitle: @"" action: nil keyEquivalent: @""];
745
+	[dummyItem setSubmenu: theMiniMenu];
746
+
747
+	[mainMenu addItem: dummyItem];
748
+}
749
+
750
+void glutInit(int *argcp, char **argv)
751
+{
752
+	pool = [NSAutoreleasePool new];
753
+	myApp = [MGApplication sharedApplication];
754
+	
755
+	[NSApp setActivationPolicy: NSApplicationActivationPolicyRegular]; // Thanks to Marcus Stenb�ck
756
+	
757
+	gRunning = 1;
758
+	home();
759
+	gettimeofday(&timeStart, NULL);
760
+	CreateMenu();
761
+	myTimerController = [TimerController alloc];
762
+	
763
+	
764
+	// Apple REALLY doesn't like us to mess with the mouse pointer. Now this is deprecated...
765
+	// and some sources say it isn't needed.
766
+//	CGSetLocalEventsSuppressionInterval(0.0); // For glutWarpPointer
767
+
768
+	int i;
769
+	for (i = 0; i < 256; i++) gKeymap[i] = 0;
770
+}
771
+
772
+int gWindowPosX = 10;
773
+int gWindowPosY = 50;
774
+int gWindowWidth = 400;
775
+int gWindowHeight = 400;
776
+
777
+void glutInitWindowPosition (int x, int y)
778
+{
779
+	gWindowPosX = x;
780
+	gWindowPosY = y;
781
+}
782
+void glutInitWindowSize (int width, int height)
783
+{
784
+	gWindowWidth = width;
785
+	gWindowHeight = height;
786
+}
787
+int glutCreateWindow (const char *windowTitle)
788
+{
789
+	NSRect frame = NSMakeRect(gWindowPosX, NSScreen.mainScreen.frame.size.height - gWindowPosY-gWindowHeight, gWindowWidth, gWindowHeight);
790
+	
791
+	window = [NSWindow alloc];
792
+	[window initWithContentRect:frame
793
+//					styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask
794
+					styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable
795
+					backing:NSBackingStoreBuffered
796
+					defer:false];
797
+	
798
+	[window setTitle: [[NSString alloc] initWithCString:windowTitle
799
+				encoding:NSMacOSRomanStringEncoding]];
800
+	strcpy(gTitle, windowTitle); // Save title in case of full screen (which clears it)
801
+
802
+	view = [GlutView alloc];
803
+	[view initWithFrame: frame];
804
+	[window setAcceptsMouseMovedEvents:YES];
805
+
806
+	// OpenGL init!
807
+	MakeContext(view);
808
+
809
+// Moved from main loop
810
+	[NSApp activateIgnoringOtherApps:YES]; // Added 180208
811
+	[window setDelegate: (GlutView*)view];
812
+	[window makeKeyAndOrderFront: nil];
813
+	[window makeFirstResponder: view]; // Added 130214
814
+	[window setContentView: view];
815
+	return 0; // Fake placeholder
816
+}
817
+
818
+
819
+// MAIN LOOP
820
+
821
+/*
822
+void oglutMainLoop()
823
+{
824
+	[window setContentView: view];
825
+
826
+	[myApp finishLaunching];
827
+	NSEvent *event;
828
+
829
+	while (gRunning)
830
+	{
831
+		[pool release];
832
+		pool = [NSAutoreleasePool new];
833
+		
834
+		if (updatePending || gIdle != NULL) // If it is, then the setNeedsDisplay below has been called and we will get an update event - but must not block!
835
+		// (If there was an update coming I think it should not block, but at least this works.)
836
+		event = [myApp nextEventMatchingMask: NSEventMaskAny
837
+							untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.0]
838
+							inMode: NSDefaultRunLoopMode
839
+							dequeue: true
840
+							];
841
+		else
842
+		event = [myApp nextEventMatchingMask: NSEventMaskAny
843
+							untilDate: [NSDate distantFuture]
844
+							inMode: NSDefaultRunLoopMode
845
+							dequeue: true
846
+							];
847
+		
848
+		[myApp sendEvent: event];
849
+		[myApp updateWindows];
850
+	
851
+		if (gIdle != NULL)
852
+			if (!updatePending)
853
+				gIdle();
854
+		
855
+		// Did not help
856
+//		if (updatePending)
857
+//			[theView setNeedsDisplay: YES];
858
+	}
859
+}
860
+*/
861
+
862
+char inMainLoop = 0;
863
+char finished = 0;
864
+
865
+void internalCheckLoop()
866
+{
867
+	NSEvent *event;
868
+	
869
+//	[myApp runOnce]; // ???
870
+	
871
+	pool = [NSAutoreleasePool new];
872
+	
873
+	if (updatePending || gIdle != NULL || !inMainLoop) // If it is, then the setNeedsDisplay below has been called and we will get an update event - but must not block!
874
+	// (If there was an update coming I think it should not block, but at least this works.)
875
+		event = [myApp nextEventMatchingMask: NSEventMaskAny
876
+						untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.0]
877
+						inMode: NSDefaultRunLoopMode
878
+						dequeue: true
879
+						];
880
+	else
881
+		event = [myApp nextEventMatchingMask: NSEventMaskAny
882
+						untilDate: [NSDate distantFuture]
883
+						inMode: NSDefaultRunLoopMode
884
+						dequeue: true
885
+						];
886
+	
887
+	[myApp sendEvent: event];
888
+	[myApp updateWindows];
889
+
890
+	if (gIdle != NULL)
891
+		if (!updatePending)
892
+			gIdle();
893
+
894
+	// Did not help?
895
+	if (updatePending)
896
+		[theView setNeedsDisplay: YES];
897
+	[pool release];
898
+}
899
+
900
+void glutCheckLoop()
901
+{
902
+	inMainLoop = 0;
903
+	
904
+//	if (!inMainLoop) [window setContentView: view]; // Why isn't this a job for window creation???
905
+	if (!finished)
906
+	{
907
+		[myApp finishLaunching];
908
+		finished = 1;
909
+	}
910
+
911
+//	[NSOpenGLContext clearCurrentContext];
912
+//	[m_context makeCurrentContext];
913
+//	[m_context setView: theView];
914
+	[m_context flushBuffer];
915
+
916
+	internalCheckLoop();
917
+
918
+	[m_context setView: theView];
919
+//	[m_context makeCurrentContext];
920
+}
921
+
922
+void glutMainLoop()
923
+{
924
+	inMainLoop = 1;
925
+
926
+//	[window setContentView: view];
927
+	[myApp finishLaunching];
928
+	finished = 1;
929
+
930
+	while (gRunning)
931
+	{
932
+		internalCheckLoop();
933
+	}
934
+	inMainLoop = 0;
935
+}
936
+
937
+// END OF MAIN LOOP
938
+
939
+
940
+void glutTimerFunc(int millis, void (*func)(int arg), int arg)
941
+{
942
+	TimerInfoRec *timerInfo = [TimerInfoRec alloc];
943
+	timerInfo->arg = arg;
944
+	timerInfo->func = func;
945
+
946
+	gTimer = [NSTimer
947
+		scheduledTimerWithTimeInterval: millis/1000.0
948
+		target: myTimerController
949
+		selector: @selector(timerFireMethod:)
950
+		userInfo: timerInfo
951
+		repeats: NO];
952
+}
953
+
954
+// Added by Ingemar
955
+void glutRepeatingTimer(int millis)
956
+{
957
+	gTimer = [NSTimer
958
+		scheduledTimerWithTimeInterval: millis/1000.0
959
+		target: myTimerController
960
+		selector: @selector(timerFireMethod:)
961
+		userInfo: nil
962
+		repeats: YES];
963
+}
964
+
965
+// Bad name, will be removed
966
+void glutRepeatingTimerFunc(int millis)
967
+{
968
+	glutRepeatingTimer(millis);
969
+}
970
+
971
+void glutDisplayFunc(void (*func)(void))
972
+{
973
+	gDisplay = func;
974
+}
975
+
976
+void glutReshapeFunc(void (*func)(int width, int height))
977
+{
978
+	gReshape = func;
979
+}
980
+
981
+void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y))
982
+{
983
+	gKey = func;
984
+}
985
+
986
+void glutKeyboardUpFunc(void (*func)(unsigned char key, int x, int y))
987
+{
988
+	gKeyUp = func;
989
+}
990
+
991
+void glutSpecialFunc(void (*func)(unsigned char key, int x, int y))
992
+{
993
+	gSpecialKey = func;
994
+}
995
+
996
+void glutSpecialUpFunc(void (*func)(unsigned char key, int x, int y))
997
+{
998
+	gSpecialKeyUp = func;
999
+}
1000
+
1001
+void glutPassiveMotionFunc(void (*func)(int x, int y))
1002
+{
1003
+	gMouseMoved = func;
1004
+}
1005
+
1006
+void glutMotionFunc(void (*func)(int x, int y))
1007
+{
1008
+	gMouseDragged = func;
1009
+}
1010
+
1011
+void glutMouseFunc(void (*func)(int button, int state, int x, int y))
1012
+{
1013
+	gMouseFunc = func;
1014
+}
1015
+
1016
+// You can safely skip this
1017
+void glutSwapBuffers()
1018
+{
1019
+//	[m_context flushBuffer];
1020
+	glFlush();
1021
+	glFinish();
1022
+}
1023
+
1024
+int glutGet(int type)
1025
+{
1026
+	struct timeval tv;
1027
+	
1028
+	switch (type)
1029
+	{
1030
+	case GLUT_QUIT_FLAG:
1031
+		return !gRunning;
1032
+		break;
1033
+	case GLUT_WINDOW_WIDTH:
1034
+		return lastWidth;
1035
+		break;
1036
+	case GLUT_WINDOW_HEIGHT:
1037
+		return lastHeight;
1038
+		break;
1039
+	case GLUT_ELAPSED_TIME:
1040
+		gettimeofday(&tv, NULL);
1041
+		return (tv.tv_usec - timeStart.tv_usec) / 1000 + (tv.tv_sec - timeStart.tv_sec)*1000;
1042
+		break;
1043
+	case GLUT_MOUSE_POSITION_X:
1044
+		return gMousePosition.x;
1045
+		break;
1046
+	case GLUT_MOUSE_POSITION_Y:
1047
+		return gMousePosition.y;
1048
+		break;
1049
+	}
1050
+	return 0;
1051
+}
1052
+
1053
+void glutInitDisplayMode(unsigned int mode)
1054
+{
1055
+	gContextInitMode = mode;
1056
+}
1057
+
1058
+void glutIdleFunc(void (*func)(void))
1059
+{
1060
+// glutIdleFunc not recommended.
1061
+	gIdle = func;
1062
+}
1063
+
1064
+void glutReshapeWindow(int width, int height)
1065
+{
1066
+	NSRect r;
1067
+
1068
+	if (gFullScreen)
1069
+	{
1070
+		[window setFrame: gSavedWindowPosition display: true];
1071
+		gFullScreen = 0;
1072
+	}
1073
+	
1074
+	r = [window frame];
1075
+	r.size.width = width;
1076
+	r.size.height = height;
1077
+// Bug fix 150820
1078
+//	[window setFrame: r display: true];
1079
+	[window setContentSize: r.size];
1080
+}
1081
+
1082
+void glutPositionWindow(int x, int y)
1083
+{
1084
+	NSRect r;
1085
+
1086
+	if (gFullScreen)
1087
+	{
1088
+		[window setFrame: gSavedWindowPosition display: true];
1089
+		gFullScreen = 0;
1090
+	}
1091
+	
1092
+	r = [window frame];
1093
+	r.origin.x = x;
1094
+	r.origin.y = NSScreen.mainScreen.frame.size.height - gWindowPosY - r.size.height;
1095
+	[window setFrame: r display: true];
1096
+}
1097
+
1098
+void glutSetWindowTitle(char *title)
1099
+{
1100
+	strcpy(gTitle, title);
1101
+	[window setTitle: [NSString stringWithUTF8String: title]];
1102
+}
1103
+
1104
+char glutKeyIsDown(unsigned char c)
1105
+{
1106
+	return gKeymap[(unsigned int)c];
1107
+}
1108
+
1109
+char glutMouseIsDown(unsigned char c)
1110
+{
1111
+	return gButtonPressed[(unsigned int)c];
1112
+}
1113
+
1114
+void glutInitContextVersion(int major, int minor)
1115
+{
1116
+	gContextVersionMajor = major;
1117
+	gContextVersionMinor = minor;
1118
+}
1119
+
1120
+// glutInitContextFlags(int flags); Add this?
1121
+
1122
+// Visibility: Just call back immediately and claim we are visible!
1123
+void glutVisibilityFunc(void (*visibility)(int status))
1124
+{
1125
+	visibility(GLUT_VISIBLE);
1126
+}
1127
+
1128
+void PostMouseEvent(CGMouseButton button, CGEventType type, const CGPoint point)
1129
+{
1130
+	CGEventRef theEvent = CGEventCreateMouseEvent(NULL /*event source?*/, type, point, button);
1131
+	CGEventSetType(theEvent, type);
1132
+	CGEventPost(kCGHIDEventTap, theEvent);
1133
+	CFRelease(theEvent);
1134
+}
1135
+
1136
+// Rewritten 140213. Seems to work.
1137
+// 150423: But... why not now??? Rewrote again, and now it works... again!
1138
+// Some debugging junk outcommented below, should tidy up after more testing.
1139
+void glutWarpPointer(int x, int y)
1140
+{
1141
+	NSPoint mp;
1142
+	CGPoint pt;
1143
+	NSRect r;
1144
+	
1145
+	mp.x = 0; mp.y = 0;
1146
+//	mp = [window convertBaseToScreen: mp];
1147
+
1148
+// Deprecation hell below:
1149
+//The NSWindow class provides these methods for converting between window local coordinates and screen global coordinates:
1150
+//	�	convertRectToScreen:
1151
+//	�	convertRectFromScreen:
1152
+//Use them instead of the deprecated convertBaseToScreen: and convertScreenToBase: methods.
1153
+	NSRect mpmp;
1154
+	mpmp.size.height = 0;
1155
+	mpmp.size.width = 0;
1156
+	mpmp.origin = mp;
1157
+	mpmp = [window convertRectToScreen: mpmp];
1158
+	mp = mpmp.origin;
1159
+
1160
+// Flip to downwards Y
1161
+	mp.y = NSScreen.mainScreen.frame.size.height - mp.y;
1162
+
1163
+// Get the view size
1164
+	r = [[window contentView] frame];
1165
+
1166
+// Add the x, y offset, minus the view frame height to move to upper left.
1167
+	pt.x = x + mp.x;
1168
+	pt.y = y - r.size.height + mp.y;
1169
+//	PostMouseEvent( 1, kCGEventMouseMoved, pt);
1170
+	
1171
+//	CGSetLocalEventsSuppressionInterval(0.0); -> glutInit
1172
+
1173
+	CGWarpMouseCursorPosition(pt);
1174
+	CGAssociateMouseAndMouseCursorPosition(true);
1175
+}
1176
+
1177
+// Should be used for auto-show-hide on activate/deactivate
1178
+char hidden = 0;
1179
+
1180
+void glutShowCursor()
1181
+{
1182
+	if (hidden)
1183
+	{
1184
+		[NSCursor unhide];
1185
+		hidden = 0;
1186
+	}
1187
+}
1188
+void glutHideCursor()
1189
+{
1190
+	if (!hidden)
1191
+	{
1192
+		[NSCursor hide];
1193
+		hidden = 1;
1194
+	}
1195
+}
1196
+
1197
+void glutFullScreen()
1198
+{
1199
+	if (gFullScreen == 0)
1200
+	{
1201
+		gFullScreen = 1;
1202
+		
1203
+		gSavedWindowPosition = [window frame];
1204
+		[NSMenu setMenuBarVisible: FALSE];
1205
+		[window setStyleMask: NSWindowStyleMaskBorderless];
1206
+		[window setFrame: NSScreen.mainScreen.frame display: true];
1207
+
1208
+		[window makeKeyAndOrderFront: nil];
1209
+		[window makeFirstResponder: view];
1210
+	}
1211
+}
1212
+
1213
+// Any reason why we should wait with resizing?
1214
+// This page says we should: https://www.opengl.org/documentation/specs/glut/spec3/node24.html
1215
+
1216
+// This call is not in the original GLUT but IMHO better than relying on glutReshapeWindow or glutPositionWindow to exit!
1217
+// (These calls also exit full screen mode though.)
1218
+void glutExitFullScreen()
1219
+{
1220
+	if (gFullScreen != 0)
1221
+	{
1222
+		gFullScreen = 0;
1223
+		[NSMenu setMenuBarVisible: TRUE];
1224
+//		[window setStyleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask]; // Back to normal
1225
+		[window setStyleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable]; // Back to normal
1226
+		[window setFrame: gSavedWindowPosition display: true];
1227
+
1228
+		[window makeKeyAndOrderFront: nil];
1229
+		[window makeFirstResponder: view];
1230
+
1231
+		[window setTitle: [NSString stringWithUTF8String: gTitle]];
1232
+	}
1233
+}
1234
+
1235
+// When I am at it... this is what I really want!
1236
+void glutToggleFullScreen()
1237
+{
1238
+	if (gFullScreen)
1239
+		glutExitFullScreen();
1240
+	else
1241
+		glutFullScreen();
1242
+}
1243
+
1244
+void glutExit()
1245
+{
1246
+	gRunning = 0;
1247
+}
1248
+
1249
+// Placeholders
1250
+void glutSetWindow(int win)
1251
+{}
1252
+int glutGetWindow(void)
1253
+{
1254
+	return 0;
1255
+}