framework2

Форк
0
1771 строка · 53.1 Кб
1
#include "ofAppGLFWWindow.h"
2

3
#include "ofGLRenderer.h"
4
#include "ofGLProgrammableRenderer.h"
5

6
#define GLFW_INCLUDE_NONE
7
#include "GLFW/glfw3.h"
8

9
#ifdef TARGET_LINUX
10
    #include "ofIcon.h"
11
    #include "ofImage.h"
12
    #define GLFW_EXPOSE_NATIVE_X11
13
    #ifndef TARGET_OPENGLES
14
        #define GLFW_EXPOSE_NATIVE_GLX
15
    #else
16
        #define GLFW_EXPOSE_NATIVE_EGL
17
    #endif
18
    #include <X11/extensions/Xrandr.h>
19
    #include <X11/XKBlib.h>
20
    #include "GLFW/glfw3native.h"
21
    #include <X11/Xatom.h>
22
    #include <xcb/xcb.h>
23
    #include <xcb/xcbext.h>
24
#elif defined(TARGET_OSX)
25
    #include <Cocoa/Cocoa.h>
26
    #define GLFW_EXPOSE_NATIVE_COCOA
27
    #define GLFW_EXPOSE_NATIVE_NSGL
28
    #include "GLFW/glfw3native.h"
29
#elif defined(TARGET_WIN32)
30
    #define GLFW_EXPOSE_NATIVE_WIN32
31
    #define GLFW_EXPOSE_NATIVE_WGL
32
    #include <GLFW/glfw3native.h>
33
#endif
34

35
using std::vector;
36
using std::shared_ptr;
37
using std::numeric_limits;
38

39
//-------------------------------------------------------
40
ofAppGLFWWindow::ofAppGLFWWindow()
41
:coreEvents(new ofCoreEvents) {
42
	bEnableSetupScreen	= true;
43
	buttonInUse			= 0;
44
	buttonPressed		= false;
45
	bWindowNeedsShowing	= true;
46

47
	orientation 		= OF_ORIENTATION_DEFAULT;
48
	targetWindowMode	= OF_WINDOW;
49

50
	ofAppPtr			= nullptr;
51

52
	pixelScreenCoordScale = 1;
53
	nFramesSinceWindowResized = 0;
54
	iconSet = false;
55
	windowP = nullptr;
56
	windowW = 0;
57
	windowH = 0;
58
	currentW = 0;
59
	currentH = 0;
60

61
	glfwSetErrorCallback(error_cb);
62
}
63

64
ofAppGLFWWindow::~ofAppGLFWWindow(){
65
	close();
66
}
67

68
void ofAppGLFWWindow::close(){
69
	if(windowP){
70

71

72
		glfwSetMouseButtonCallback( windowP, nullptr );
73
		glfwSetCursorPosCallback( windowP, nullptr );
74
		glfwSetCursorEnterCallback( windowP, nullptr );
75
		glfwSetKeyCallback( windowP, nullptr );
76
		glfwSetWindowSizeCallback( windowP, nullptr );
77
		glfwSetFramebufferSizeCallback( windowP, nullptr);
78
		glfwSetWindowCloseCallback( windowP, nullptr );
79
		glfwSetScrollCallback( windowP, nullptr );
80
		glfwSetDropCallback( windowP, nullptr );
81

82
		//hide the window before we destroy it stops a flicker on OS X on exit.
83
		glfwHideWindow(windowP);
84

85
		// We must ensure renderer is destroyed *before* glfw destroys the window in glfwDestroyWindow,
86
		// as `glfwDestroyWindow` at least on Windows has the effect of unloading OpenGL, making all
87
		// calls to OpenGL illegal.
88
		currentRenderer.reset();
89

90
		glfwDestroyWindow(windowP);
91
		windowP = nullptr;
92
		events().disable();
93
		bWindowNeedsShowing = true;
94
	}
95
}
96

97
//------------------------------------------------------------
98
void ofAppGLFWWindow::setNumSamples(int _samples){
99
	settings.numSamples=_samples;
100
}
101

102
//------------------------------------------------------------
103
void ofAppGLFWWindow::setMultiDisplayFullscreen(bool bMultiFullscreen){
104
	settings.multiMonitorFullScreen = bMultiFullscreen;
105
}
106

107
//------------------------------------------------------------
108
void ofAppGLFWWindow::setDoubleBuffering(bool doubleBuff){
109
	settings.doubleBuffering = doubleBuff;
110
}
111

112
//------------------------------------------------------------
113
void ofAppGLFWWindow::setColorBits(int r, int g, int b){
114
	settings.redBits=r;
115
	settings.greenBits=g;
116
	settings.blueBits=b;
117
}
118

119
//------------------------------------------------------------
120
void ofAppGLFWWindow::setAlphaBits(int a){
121
	settings.alphaBits=a;
122
}
123

124
//------------------------------------------------------------
125
void ofAppGLFWWindow::setDepthBits(int depth){
126
	settings.depthBits=depth;
127
}
128

129
//------------------------------------------------------------
130
void ofAppGLFWWindow::setStencilBits(int stencil){
131
	settings.stencilBits=stencil;
132
}
133

134
//------------------------------------------------------------
135
#ifdef TARGET_OPENGLES
136
void ofAppGLFWWindow::setup(const ofGLESWindowSettings & settings){
137
#else
138
void ofAppGLFWWindow::setup(const ofGLWindowSettings & settings){
139
#endif
140
	const ofGLFWWindowSettings * glSettings = dynamic_cast<const ofGLFWWindowSettings*>(&settings);
141
	if(glSettings){
142
		setup(*glSettings);
143
	}else{
144
		setup(ofGLFWWindowSettings(settings));
145
	}
146
}
147

148
void ofAppGLFWWindow::setup(const ofGLFWWindowSettings & _settings){
149
	if(windowP){
150
		ofLogError() << "window already setup, probably you are mixing old and new style setup";
151
		ofLogError() << "call only ofCreateWindow(settings) or ofSetupOpenGL(...)";
152
		ofLogError() << "calling window->setup() after ofCreateWindow() is not necessary and won't do anything";
153
		return;
154
	}
155
	settings = _settings;
156

157
	if(!glfwInit( )){
158
		ofLogError("ofAppGLFWWindow") << "couldn't init GLFW";
159
		return;
160
	}
161

162
//	ofLogNotice("ofAppGLFWWindow") << "WINDOW MODE IS " << screenMode;
163

164
	glfwDefaultWindowHints();
165
	glfwWindowHint(GLFW_RED_BITS, settings.redBits);
166
	glfwWindowHint(GLFW_GREEN_BITS, settings.greenBits);
167
	glfwWindowHint(GLFW_BLUE_BITS, settings.blueBits);
168
	glfwWindowHint(GLFW_ALPHA_BITS, settings.alphaBits);
169
	glfwWindowHint(GLFW_DEPTH_BITS, settings.depthBits);
170
	glfwWindowHint(GLFW_STENCIL_BITS, settings.stencilBits);
171
	glfwWindowHint(GLFW_STEREO, settings.stereo);
172
	glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
173
#ifndef TARGET_OSX
174
	glfwWindowHint(GLFW_AUX_BUFFERS, settings.doubleBuffering?1:0);
175
#else
176
    glfwWindowHint(GLFW_DOUBLEBUFFER, settings.doubleBuffering?1:0);
177
#endif
178
	glfwWindowHint(GLFW_SAMPLES, settings.numSamples);
179
	glfwWindowHint(GLFW_RESIZABLE, settings.resizable);
180
	glfwWindowHint(GLFW_DECORATED, settings.decorated);
181
	
182
    #ifdef TARGET_OPENGLES
183
	    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, settings.glesVersion);
184
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
185
		glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
186
		if(settings.glesVersion>=2){
187
			currentRenderer = std::make_shared<ofGLProgrammableRenderer>(this);
188
		}else{
189
			currentRenderer = std::make_shared<ofGLRenderer>(this);
190
		}
191
    #else
192
	    glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
193
		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, settings.glVersionMajor);
194
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, settings.glVersionMinor);
195
		if((settings.glVersionMajor==3 && settings.glVersionMinor>=2) || settings.glVersionMajor>=4){
196
			glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
197
		}
198
		if(settings.glVersionMajor>=3){
199
			glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
200
#if (GLFW_VERSION_MAJOR >= 3 && GLFW_VERSION_MINOR > 2) || (GLFW_VERSION_MAJOR > 3 )
201
			glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, settings.transparent);
202
#endif
203
			currentRenderer = std::make_shared<ofGLProgrammableRenderer>(this);
204
		}else{
205
			currentRenderer = std::make_shared<ofGLRenderer>(this);
206
		}
207
    #endif
208

209
	GLFWwindow * sharedContext = nullptr;
210
	if(settings.shareContextWith){
211
		sharedContext = (GLFWwindow*)settings.shareContextWith->getWindowContext();
212
	}
213

214
	if(settings.windowMode==OF_GAME_MODE){
215
		int count;
216
		GLFWmonitor** monitors = glfwGetMonitors(&count);
217
		if( settings.monitor >= count ){
218
			ofLogError("ofAppGLFWWindow") << "requested game mode monitor is: " << settings.monitor << " monitor count is: " << count;
219
		}
220
		settings.monitor = ofClamp(settings.monitor,0,count-1);
221
		if(settings.isSizeSet()){
222
			currentW = settings.getWidth();
223
			currentH = settings.getHeight();
224
		}else{
225
			auto mode = glfwGetVideoMode(monitors[settings.monitor]);
226
			currentW = mode->width;
227
			currentH = mode->height;
228
		}
229
		if(count>settings.monitor){
230
			windowP = glfwCreateWindow(currentW, currentH, settings.title.c_str(), monitors[settings.monitor], sharedContext);
231
		}else{
232
			ofLogError("ofAppGLFWWindow") << "couldn't find any monitors";
233
			return;
234
		}
235
	}else{
236
		windowP = glfwCreateWindow(settings.getWidth(), settings.getHeight(), settings.title.c_str(), nullptr, sharedContext);
237
		if(!windowP){
238
			ofLogError("ofAppGLFWWindow") << "couldn't create GLFW window";
239
			return;
240
		}
241
		if(settings.windowMode==OF_FULLSCREEN){
242
			int count = 0;
243
			auto monitors = glfwGetMonitors(&count);
244
			if( settings.monitor >= count ){
245
				ofLogError("ofAppGLFWWindow") << "requested fullscreen monitor is: " << settings.monitor << " monitor count is: " << count;
246
			}
247
			settings.monitor = ofClamp(settings.monitor,0,count-1);
248
			
249
			auto mode = glfwGetVideoMode(monitors[settings.monitor]);
250
			currentW = mode->width;
251
			currentH = mode->height;
252
			if(!settings.isPositionSet()){
253
				if(count > 0){
254
					int x = 0, y = 0;
255
					glfwGetMonitorPos(monitors[settings.monitor],&x,&y);
256
					settings.setPosition(glm::vec2(x,y));
257
					setWindowPosition(settings.getPosition().x,settings.getPosition().y);
258
					auto mode = glfwGetVideoMode(monitors[settings.monitor]);
259
                    #ifdef TARGET_OSX
260
					    //for OS X we need to set this first as the window size affects the window positon
261
					    settings.setSize(mode->width, mode->height);
262
                    #endif
263
					setWindowPosition(settings.getPosition().x,settings.getPosition().y);
264
					currentW = mode->width;
265
					currentH = mode->height;
266
				}
267
			}else{
268
				setWindowPosition(settings.getPosition().x,settings.getPosition().y);
269
                #ifdef TARGET_OSX
270
				    auto size = getScreenSize();
271
					settings.setSize(size.x, size.y);
272
                #endif
273
					currentW = settings.getWidth();
274
					currentH = settings.getHeight();
275
					for(int i = 0; i < count; i++){
276
						int x = 0, y = 0;
277
						glfwGetMonitorPos(monitors[i],&x,&y);
278
						auto mode = glfwGetVideoMode(monitors[i]);
279
						int w = mode->width;
280
						int h = mode->height;
281
						ofRectangle rect(x-1,y-1,w+1,h+1);
282
						if(rect.inside(settings.getPosition())){
283
							currentW = mode->width;
284
							currentH = mode->height;
285
							break;
286
						}
287
					}
288
			}
289
			targetWindowMode = settings.windowMode;
290
			settings.windowMode = OF_WINDOW;
291
		}else{
292
			if (settings.isPositionSet()) {
293
				setWindowPosition(settings.getPosition().x,settings.getPosition().y);
294
			}
295
			glfwGetWindowSize( windowP, &currentW, &currentH );
296
		}
297
        #ifdef TARGET_LINUX
298
		    if(!iconSet){
299
				ofPixels iconPixels;
300
                #ifdef DEBUG
301
				    iconPixels.allocate(ofIconDebug.width,ofIconDebug.height,ofIconDebug.bytes_per_pixel);
302
					GIMP_IMAGE_RUN_LENGTH_DECODE(iconPixels.getData(),ofIconDebug.rle_pixel_data,iconPixels.getWidth()*iconPixels.getHeight(),ofIconDebug.bytes_per_pixel);
303
                #else
304
				    iconPixels.allocate(ofIcon.width,ofIcon.height,ofIcon.bytes_per_pixel);
305
					GIMP_IMAGE_RUN_LENGTH_DECODE(iconPixels.getData(),ofIcon.rle_pixel_data,iconPixels.getWidth()*iconPixels.getHeight(),ofIcon.bytes_per_pixel);
306
                #endif
307
				setWindowIcon(iconPixels);
308
			}
309
        #endif
310
		if(settings.iconified){
311
			iconify(true);
312
		}
313
	}
314

315
	//don't try and show a window if its been requsted to be hidden
316
	bWindowNeedsShowing = settings.visible;
317

318
	glfwSetWindowUserPointer(windowP,this);
319

320
	windowW = settings.getWidth();
321
	windowH = settings.getHeight();
322
	
323
#ifdef TARGET_RASPBERRY_PI
324
	windowRect.width = windowW;
325
	windowRect.height = windowH;
326
#endif 
327

328
	glfwMakeContextCurrent(windowP);
329

330
	int framebufferW, framebufferH, tmpWindowW, tmpWindowH;
331
	glfwGetFramebufferSize(windowP, &framebufferW, &framebufferH);
332
	glfwGetWindowSize( windowP, &tmpWindowW, &tmpWindowH );
333

334
	//this lets us detect if the window is running in a retina mode
335
	if( framebufferW != tmpWindowW){
336
		pixelScreenCoordScale = (float)framebufferW / (float)tmpWindowW;
337
		if( pixelScreenCoordScale < 1 ){
338
			pixelScreenCoordScale = 1;
339
		}
340

341
		if(targetWindowMode == OF_WINDOW){
342
			auto position = getWindowPosition();
343
			setWindowShape(windowW, windowH);
344
			setWindowPosition(position.x, position.y);
345
		}
346
	}
347

348
#ifndef TARGET_OPENGLES
349
	static bool inited = false;
350
	if(!inited){
351
		glewExperimental = GL_TRUE;
352
		GLenum err = glewInit();
353
		if (GLEW_OK != err)
354
		{
355
			/* Problem: glewInit failed, something is seriously wrong. */
356
			ofLogError("ofAppRunner") << "couldn't init GLEW: " << glewGetErrorString(err);
357
			return;
358
		}
359
		inited = true;
360
	}
361
#endif
362

363
	ofLogVerbose() << "GL Version: " << glGetString(GL_VERSION);
364

365
	if(currentRenderer->getType()==ofGLProgrammableRenderer::TYPE){
366
#ifndef TARGET_OPENGLES
367
		static_cast<ofGLProgrammableRenderer*>(currentRenderer.get())->setup(settings.glVersionMajor,settings.glVersionMinor);
368
#else
369
		static_cast<ofGLProgrammableRenderer*>(currentRenderer.get())->setup(settings.glesVersion,0);
370
#endif
371
	}else{
372
		static_cast<ofGLRenderer*>(currentRenderer.get())->setup();
373
	}
374

375
	setVerticalSync(true);
376
	glfwSetMouseButtonCallback(windowP, mouse_cb);
377
	glfwSetCursorPosCallback(windowP, motion_cb);
378
	glfwSetCursorEnterCallback(windowP, entry_cb);
379
	glfwSetKeyCallback(windowP, keyboard_cb);
380
	glfwSetCharCallback(windowP, char_cb);
381
	glfwSetWindowSizeCallback(windowP, resize_cb);
382
	glfwSetFramebufferSizeCallback(windowP, framebuffer_size_cb);
383
	glfwSetWindowCloseCallback(windowP, exit_cb);
384
	glfwSetScrollCallback(windowP, scroll_cb);
385
	glfwSetDropCallback(windowP, drop_cb );
386

387

388
#ifdef TARGET_LINUX
389
	XSetLocaleModifiers("");
390
	xim = XOpenIM(getX11Display(), 0, 0, 0);
391
	if(!xim){
392
		// fallback to internal input method
393
		XSetLocaleModifiers("@im=none");
394
		xim = XOpenIM(getX11Display(), 0, 0, 0);
395
	}
396
	xic = XCreateIC(xim,
397
	        XNInputStyle,   XIMPreeditNothing | XIMStatusNothing,
398
	        XNClientWindow, getX11Window(),
399
	        XNFocusWindow,  getX11Window(),
400
	    NULL);
401
#endif
402
}
403

404
#ifdef TARGET_LINUX
405
//------------------------------------------------------------
406
void ofAppGLFWWindow::setWindowIcon(const std::string & path){
407
	ofPixels iconPixels;
408
	ofLoadImage(iconPixels,path);
409
	setWindowIcon(iconPixels);
410
}
411

412
//------------------------------------------------------------
413
void ofAppGLFWWindow::setWindowIcon(const ofPixels & iconPixels){
414
	iconSet = true;
415
	int length = 2+iconPixels.getWidth()*iconPixels.getHeight();
416
	vector<unsigned long> buffer(length);
417
	buffer[0]=iconPixels.getWidth();
418
	buffer[1]=iconPixels.getHeight();
419
	for(size_t i=0;i<iconPixels.getWidth()*iconPixels.getHeight();i++){
420
		buffer[i+2]  = iconPixels[i*4+3]<<24;
421
		buffer[i+2] += iconPixels[i*4+0]<<16;
422
		buffer[i+2] += iconPixels[i*4+1]<<8;
423
		buffer[i+2] += iconPixels[i*4+2];
424
	}
425

426
	XChangeProperty(getX11Display(), getX11Window(), XInternAtom(getX11Display(), "_NET_WM_ICON", False), XA_CARDINAL, 32,
427
	                     PropModeReplace,  (const unsigned char*)buffer.data(),  length);
428
	XFlush(getX11Display());
429
}
430
#endif
431

432
//--------------------------------------------
433
ofCoreEvents & ofAppGLFWWindow::events(){
434
	return *coreEvents;
435
}
436

437
//--------------------------------------------
438
shared_ptr<ofBaseRenderer> & ofAppGLFWWindow::renderer(){
439
	return currentRenderer;
440
}
441

442
//--------------------------------------------
443
void ofAppGLFWWindow::update(){
444
	events().notifyUpdate();
445

446
	//show the window right before the first draw call.
447
	if( bWindowNeedsShowing && windowP ){
448
		glfwShowWindow(windowP);
449
		bWindowNeedsShowing = false;
450
		if(targetWindowMode==OF_FULLSCREEN){
451
			setFullscreen(true);
452
		}
453
	}
454

455
#ifdef TARGET_RASPBERRY_PI
456
    //needed for rpi. as good values don't come into resize_cb when coming out of fullscreen
457
    if( needsResizeCheck && windowP ){
458
        int winW, winH;
459
        glfwGetWindowSize(windowP, &winW, &winH);
460
        
461
        //wait until the window size is the size it was before going fullscreen
462
        //then stop the resize check
463
        if( winW == windowRect.getWidth() && winH == windowRect.getHeight() ){
464
            resize_cb(windowP, currentW, currentH);
465
            needsResizeCheck = false;
466
        }
467
    }
468
#endif
469
}
470

471
//--------------------------------------------
472
void ofAppGLFWWindow::pollEvents(){
473
	glfwPollEvents();
474
}
475

476
//--------------------------------------------
477
void ofAppGLFWWindow::draw(){
478
	currentRenderer->startRender();
479
	if( bEnableSetupScreen ) currentRenderer->setupScreen();
480

481
	events().notifyDraw();
482

483
    #ifdef TARGET_WIN32
484
	if (currentRenderer->getBackgroundAuto() == false){
485
		// on a PC resizing a window with this method of accumulation (essentially single buffering)
486
		// is BAD, so we clear on resize events.
487
		if (nFramesSinceWindowResized < 3){
488
			currentRenderer->clear();
489
		} else {
490
			if ( (events().getFrameNum() < 3 || nFramesSinceWindowResized < 3) && settings.doubleBuffering){
491
				glfwSwapBuffers(windowP);
492
			}else{
493
				glFlush();
494
			}
495
		}
496
	} else {
497
		if(settings.doubleBuffering){
498
			glfwSwapBuffers(windowP);
499
		} else {
500
			glFlush();
501
		}
502
	}
503
    #else
504
	    if (currentRenderer->getBackgroundAuto() == false){
505
			// in accum mode resizing a window is BAD, so we clear on resize events.
506
			if (nFramesSinceWindowResized < 3){
507
				currentRenderer->clear();
508
			}
509
		}
510
		if(settings.doubleBuffering){
511
			glfwSwapBuffers(windowP);
512
		} else{
513
			glFlush();
514
		}
515
    #endif
516

517
	currentRenderer->finishRender();
518

519
	nFramesSinceWindowResized++;
520
}
521

522

523
//--------------------------------------------
524
void ofAppGLFWWindow::swapBuffers() {
525
	glfwSwapBuffers(windowP);
526
}
527

528
//--------------------------------------------
529
void ofAppGLFWWindow::startRender() {
530
	renderer()->startRender();
531
}
532

533
//--------------------------------------------
534
void ofAppGLFWWindow::finishRender() {
535
	renderer()->finishRender();
536
}
537

538
//--------------------------------------------
539
bool ofAppGLFWWindow::getWindowShouldClose(){
540
	return glfwWindowShouldClose(windowP);
541
}
542

543
//--------------------------------------------
544
void ofAppGLFWWindow::setWindowShouldClose(){
545
	glfwSetWindowShouldClose(windowP,1);
546
}
547

548
//------------------------------------------------------------
549
void ofAppGLFWWindow::setWindowTitle(std::string title){
550
	settings.title = title;
551
	glfwSetWindowTitle(windowP,settings.title.c_str());
552
}
553

554
//------------------------------------------------------------
555
int ofAppGLFWWindow::getPixelScreenCoordScale(){
556
    return pixelScreenCoordScale;
557
}
558

559
//------------------------------------------------------------
560
glm::vec2 ofAppGLFWWindow::getWindowSize(){
561
	if(settings.windowMode == OF_GAME_MODE)
562
	{
563
		const GLFWvidmode * desktopMode = glfwGetVideoMode(glfwGetWindowMonitor(windowP));
564
		if(desktopMode){
565
			return {desktopMode->width*pixelScreenCoordScale, desktopMode->height*pixelScreenCoordScale};
566
		}else{
567
			return {currentW*pixelScreenCoordScale, currentH*pixelScreenCoordScale};
568
		}
569
	}else{
570
		return {currentW*pixelScreenCoordScale, currentH*pixelScreenCoordScale};
571
	}
572
}
573

574
//------------------------------------------------------------
575
glm::vec2 ofAppGLFWWindow::getWindowPosition(){
576
	int x, y;
577
	glfwGetWindowPos(windowP, &x, &y);
578
    
579
    x *= pixelScreenCoordScale;
580
    y *= pixelScreenCoordScale;
581

582
	if( orientation == OF_ORIENTATION_DEFAULT || orientation == OF_ORIENTATION_180 ){
583
		return glm::vec2{x,y};
584
	}else{
585
		return glm::vec2(x,y); //NOTE: shouldn't this be (y,x) ??????
586
	}
587
}
588

589
//------------------------------------------------------------
590
int ofAppGLFWWindow::getCurrentMonitor(){
591
	int numberOfMonitors;
592
	GLFWmonitor** monitors = glfwGetMonitors(&numberOfMonitors);
593

594
	int xW;	int yW;
595
	glfwGetWindowPos(windowP, &xW, &yW);
596

597
	for (int iC=0; iC < numberOfMonitors; iC++){
598
		int xM; int yM;
599
		glfwGetMonitorPos(monitors[iC], &xM, &yM);
600
		const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[iC]);
601
		ofRectangle monitorRect(xM, yM, desktopMode->width, desktopMode->height);
602
		bool bPointMatch = xW >= monitorRect.getMinX() && yW >= monitorRect.getMinY() && xW < monitorRect.getMaxX() && yW < monitorRect.getMaxY();
603
		//		if (monitorRect.inside(xW, yW)){
604
		if( bPointMatch ) {
605
			return iC;
606
			break;
607
		}
608
	}
609
	return 0;
610
}
611

612

613
//------------------------------------------------------------
614
glm::vec2 ofAppGLFWWindow::getScreenSize(){
615
	int count;
616
	GLFWmonitor** monitors = glfwGetMonitors(&count);
617
	if(count>0){
618
		int currentMonitor = getCurrentMonitor();
619
		const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[currentMonitor]);
620
		if(desktopMode){
621
			if( orientation == OF_ORIENTATION_DEFAULT || orientation == OF_ORIENTATION_180 ){
622
				return {desktopMode->width*pixelScreenCoordScale, desktopMode->height*pixelScreenCoordScale};
623
			}else{
624
				return {desktopMode->height*pixelScreenCoordScale, desktopMode->width*pixelScreenCoordScale};
625
			}
626
		}
627
	}
628
	return glm::vec2();
629
}
630

631
//------------------------------------------------------------
632
int ofAppGLFWWindow::getWidth(){
633
	if( orientation == OF_ORIENTATION_DEFAULT || orientation == OF_ORIENTATION_180 ){
634
		return currentW * pixelScreenCoordScale;
635
	}else{
636
		return currentH * pixelScreenCoordScale;
637
	}
638
}
639

640
//------------------------------------------------------------
641
int ofAppGLFWWindow::getHeight(){
642
	if( orientation == OF_ORIENTATION_DEFAULT || orientation == OF_ORIENTATION_180 ){
643
		return currentH * pixelScreenCoordScale;
644
	}else{
645
		return currentW * pixelScreenCoordScale;
646
	}
647
}
648

649
//------------------------------------------------------------
650
GLFWwindow* ofAppGLFWWindow::getGLFWWindow(){
651
	return windowP;
652
}
653

654
//------------------------------------------------------------
655
ofWindowMode ofAppGLFWWindow::getWindowMode(){
656
	return settings.windowMode;
657
}
658

659
//------------------------------------------------------------
660
void ofAppGLFWWindow::setWindowPosition(int x, int y){
661
	glfwSetWindowPos(windowP,x/pixelScreenCoordScale,y/pixelScreenCoordScale);
662
}
663

664
//------------------------------------------------------------
665
void ofAppGLFWWindow::setWindowShape(int w, int h){
666
	if(settings.windowMode == OF_WINDOW){
667
		windowW = w;
668
		windowH = h;
669
	}
670
	currentW = w/pixelScreenCoordScale;
671
	currentH = h/pixelScreenCoordScale;
672

673
    #ifdef TARGET_OSX
674
	    auto pos = getWindowPosition();
675
		glfwSetWindowSize(windowP,currentW,currentH);
676
		if( pos != getWindowPosition() ){
677
			setWindowPosition(pos.x, pos.y);
678
		}
679
    #else
680
	    glfwSetWindowSize(windowP,currentW,currentH);
681
    #endif
682
}
683

684
//------------------------------------------------------------
685
void ofAppGLFWWindow::hideCursor(){
686
	if(settings.windowMode == OF_FULLSCREEN || settings.windowMode == OF_GAME_MODE){
687
		glfwSetInputMode(windowP,GLFW_CURSOR,GLFW_CURSOR_DISABLED);
688
	}else{
689
		glfwSetInputMode(windowP,GLFW_CURSOR,GLFW_CURSOR_HIDDEN);
690
	}
691
};
692

693
//------------------------------------------------------------
694
void ofAppGLFWWindow::showCursor(){
695
	glfwSetInputMode(windowP,GLFW_CURSOR,GLFW_CURSOR_NORMAL);
696
};
697

698
//------------------------------------------------------------
699
void ofAppGLFWWindow::enableSetupScreen(){
700
	bEnableSetupScreen = true;
701
};
702

703
//------------------------------------------------------------
704
void ofAppGLFWWindow::disableSetupScreen(){
705
	bEnableSetupScreen = false;
706
};
707

708
//------------------------------------------------------------
709
void ofAppGLFWWindow::setFullscreen(bool fullscreen){
710
	if (fullscreen){
711
		targetWindowMode = OF_FULLSCREEN;
712
	}else{
713
		targetWindowMode = OF_WINDOW;
714
	}
715
 
716
    #if defined(TARGET_OSX)
717
	NSWindow * cocoaWindow = glfwGetCocoaWindow(windowP);
718
 	if (([cocoaWindow styleMask] & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen) {
719
		settings.windowMode = OF_FULLSCREEN;
720
		if (targetWindowMode == OF_WINDOW) {
721
			[cocoaWindow toggleFullScreen:nil];
722
		}
723
	} else {
724
		[cocoaWindow setHasShadow:NO];
725
	}
726
    #endif
727

728
	//we only want to change window mode if the requested window is different to the current one.
729
	bool bChanged = targetWindowMode != settings.windowMode;
730
	if( !bChanged ){
731
		return;
732
	}
733

734
#ifdef TARGET_LINUX
735
#include <X11/Xatom.h>
736

737
	Window nativeWin = glfwGetX11Window(windowP);
738
	Display* display = glfwGetX11Display();
739
	if(targetWindowMode==OF_FULLSCREEN){
740
		
741
#ifdef TARGET_RASPBERRY_PI
742
		// save window shape before going fullscreen
743
		if( windowP ){
744
			int tmpW, tmpH;
745
			glfwGetWindowSize(windowP, &tmpW, &tmpH);
746
			windowRect.setSize(tmpW, tmpH); 
747
		}
748
#endif 
749
		
750
		int monitorCount;
751
		GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
752
		if( settings.multiMonitorFullScreen && monitorCount > 1 ){
753
			// find the monitors at the edges of the virtual desktop
754
			int minx=numeric_limits<int>::max();
755
			int miny=numeric_limits<int>::max();
756
			int maxx=numeric_limits<int>::min();
757
			int maxy=numeric_limits<int>::min();
758
			int x,y,w,h;
759
			int monitorLeft=0, monitorRight=0, monitorTop=0, monitorBottom=0;
760
			for(int i = 0; i < monitorCount; i++){
761
				glfwGetMonitorPos(monitors[i],&x,&y);
762
				auto videoMode = glfwGetVideoMode(monitors[i]);
763
				w = videoMode->width;
764
				h = videoMode->height;
765
				if(x<minx){
766
					monitorLeft = i;
767
					minx = x;
768
				}
769
				if(y<miny){
770
					monitorTop = i;
771
					miny = y;
772
				}
773
				if(x+w>maxx){
774
					monitorRight = i;
775
					maxx = x+w;
776
				}
777
				if(y+h>maxy){
778
					monitorBottom = i;
779
					maxy = y+h;
780
				}
781
			}
782

783
			// send fullscreen_monitors event with the edges monitors
784
			Atom m_net_fullscreen_monitors= XInternAtom(display, "_NET_WM_FULLSCREEN_MONITORS", false);
785

786
			XEvent xev;
787

788
			xev.xclient.type = ClientMessage;
789
			xev.xclient.serial = 0;
790
			xev.xclient.send_event = True;
791
			xev.xclient.window = nativeWin;
792
			xev.xclient.message_type = m_net_fullscreen_monitors;
793
			xev.xclient.format = 32;
794

795
			xev.xclient.data.l[0] = monitorTop;
796
			xev.xclient.data.l[1] = monitorBottom;
797
			xev.xclient.data.l[2] = monitorLeft;
798
			xev.xclient.data.l[3] = monitorRight;
799
			xev.xclient.data.l[4] = 1;
800
			XSendEvent(display, RootWindow(display, DefaultScreen(display)),
801
			           False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
802
			currentW = maxx - minx;
803
			currentH = maxy - minx;
804
		}else{
805
			auto monitor = glfwGetWindowMonitor(windowP);
806
			if(monitor){
807
				auto videoMode = glfwGetVideoMode(monitor);
808
				if(videoMode){
809
					currentW = videoMode->width;
810
					currentH = videoMode->height;
811
				}
812
			}
813
		}
814
	}
815

816
	// send fullscreen event
817
	Atom m_net_state= XInternAtom(display, "_NET_WM_STATE", false);
818
	Atom m_net_fullscreen= XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", false);
819

820
	XEvent xev;
821

822
	xev.xclient.type = ClientMessage;
823
	xev.xclient.serial = 0;
824
	xev.xclient.send_event = True;
825
	xev.xclient.window = nativeWin;
826
	xev.xclient.message_type = m_net_state;
827
	xev.xclient.format = 32;
828

829
	if (fullscreen)
830
		xev.xclient.data.l[0] = 1;
831
	else
832
		xev.xclient.data.l[0] = 0;
833

834
	xev.xclient.data.l[1] = m_net_fullscreen;
835
	xev.xclient.data.l[2] = 0;
836
	xev.xclient.data.l[3] = 0;
837
	xev.xclient.data.l[4] = 0;
838
	XSendEvent(display, RootWindow(display, DefaultScreen(display)),
839
	           False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
840

841
	// tell the window manager to bypass composition for this window in fullscreen for speed
842
	// it'll probably help solving vsync issues
843
	Atom m_bypass_compositor = XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
844
	unsigned long value = fullscreen ? 1 : 0;
845
	XChangeProperty(display, nativeWin, m_bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1);
846

847
	XFlush(display);
848
	
849
#ifdef TARGET_RASPBERRY_PI 
850
	if( !fullscreen ){
851
		needsResizeCheck = true; 
852
	}
853
#endif 
854
	
855
//	setWindowShape(windowW, windowH);
856

857
#elif defined(TARGET_OSX)
858

859
	if( targetWindowMode == OF_FULLSCREEN){
860
		//----------------------------------------------------
861
		[NSApp setPresentationOptions:NSApplicationPresentationHideMenuBar | NSApplicationPresentationHideDock];
862
		NSWindow * cocoaWindow = glfwGetCocoaWindow(windowP);
863

864
		[cocoaWindow setStyleMask:NSWindowStyleMaskBorderless];
865

866
		int monitorCount;
867
		GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
868

869
		int currentMonitor = getCurrentMonitor();
870
		auto screenSize = getScreenSize();
871

872
		if( orientation == OF_ORIENTATION_90_LEFT || orientation == OF_ORIENTATION_90_RIGHT ){
873
			std::swap(screenSize.x, screenSize.y);
874
		}
875

876
		ofRectangle allScreensSpace;
877

878
		// save window shape before going fullscreen
879
		auto pos = getWindowPosition();
880
		auto size = getWindowSize();
881
		windowRect.x = pos.x;
882
		windowRect.y = pos.y;
883
		windowRect.width = size.x;
884
		windowRect.height = size.y;
885

886
		if( settings.multiMonitorFullScreen && monitorCount > 1 ){
887

888
			//calc the sum Rect of all the monitors
889
			for(int i = 0; i < monitorCount; i++){
890
				const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[i]);
891
				int x, y;
892
				glfwGetMonitorPos(monitors[i], &x, &y);
893
				ofRectangle screen = ofRectangle( x, y, desktopMode->width, desktopMode->height );
894
				allScreensSpace = allScreensSpace.getUnion(screen);
895
			}
896
			//for OS X we need to set this first as the window size affects the window positon
897
			//need to account for the pixel density factor when we're getting the values from glfw
898
			setWindowShape(allScreensSpace.width*pixelScreenCoordScale, allScreensSpace.height*pixelScreenCoordScale);
899
			setWindowPosition(allScreensSpace.x, allScreensSpace.y);
900

901
		}else if (monitorCount > 1 && currentMonitor < monitorCount){
902
			int xpos;
903
			int ypos;
904
			glfwGetMonitorPos(monitors[currentMonitor], &xpos, &ypos);
905

906
			// Scale (if needed) to physical pixels size, since setWindowPosition
907
			// uses physical pixel dimensions. On HIDPI screens pixelScreenCoordScale
908
			// is likely to be 2, on "normal" screens pixelScreenCoordScale will be 1:
909
			xpos *= pixelScreenCoordScale;
910
			ypos *= pixelScreenCoordScale;
911

912
			//we do this as setWindowShape affects the position of the monitor
913
			//normally we would just call setWindowShape first, but on multi monitor you see the window bleed onto the second monitor as it first changes shape and is then repositioned.
914
			//this first moves it over in X, does the screen resize and then by calling it again its set correctly in y.
915
			setWindowPosition(xpos, ypos);
916
			setWindowShape(screenSize.x, screenSize.y);
917
			setWindowPosition(xpos, ypos);
918
		}else{
919
			//for OS X we need to set this first as the window size affects the window positon
920
			setWindowShape(screenSize.x, screenSize.y);
921
			setWindowPosition(0,0);
922
		}
923

924
		// make sure to save current pos if not specified in settings
925
		if( settings.isPositionSet() ) {
926
			auto pos = getWindowPosition();
927
			settings.setPosition(ofVec2f(pos.x, pos.y));
928
		}
929

930
		//make sure the window is getting the mouse/key events
931
		[cocoaWindow makeFirstResponder:cocoaWindow.contentView];
932

933
	}else if( targetWindowMode == OF_WINDOW ){
934

935
		// set window shape if started in fullscreen
936
		if(windowRect.width == 0 && windowRect.height == 0) {
937
			windowRect.x = getWindowPosition().x;
938
			windowRect.y = getWindowPosition().y;
939
			windowRect.width = getWindowSize().x;
940
			windowRect.height = getWindowSize().y;
941
		}
942

943
		setWindowShape(windowRect.width, windowRect.height);
944
		setWindowTitle(settings.title);
945

946
		[NSApp setPresentationOptions:NSApplicationPresentationDefault];
947
		NSWindow * cocoaWindow = glfwGetCocoaWindow(windowP);
948
		[cocoaWindow setStyleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable];
949

950
		//----------------------------------------------------
951
		// if we have recorded the screen position, put it there
952
		// if not, better to let the system do it (and put it where it wants)
953
		if (ofGetFrameNum() > 0){
954
			setWindowPosition(windowRect.x, windowRect.y);
955
		}
956

957
		//----------------------------------------------------
958
		//make sure the window is getting the mouse/key events
959
		[cocoaWindow makeFirstResponder:cocoaWindow.contentView];
960
	}
961
#elif defined(TARGET_WIN32)
962
	if( targetWindowMode == OF_FULLSCREEN){
963
		// save window shape before going fullscreen
964
		auto pos = getWindowPosition();
965
		auto size = getWindowSize();
966
		windowRect.x = pos.x;
967
		windowRect.y = pos.y;
968
		windowRect.width = size.x;
969
		windowRect.height = size.y;
970

971
		//----------------------------------------------------
972
		HWND hwnd = glfwGetWin32Window(windowP);
973

974
		SetWindowLong(hwnd, GWL_EXSTYLE, 0);
975
		SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
976
		SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
977

978
		float fullscreenW = getScreenSize().x;
979
		float fullscreenH = getScreenSize().y;
980

981
		if( orientation == OF_ORIENTATION_90_LEFT || orientation == OF_ORIENTATION_90_RIGHT ){
982
			std::swap(fullscreenW, fullscreenH);
983
		}
984

985
		int xpos = 0;
986
		int ypos = 0;
987

988
		if( settings.multiMonitorFullScreen ){
989

990
			int minX = 0;
991
			int maxX = 0;
992
			int minY = 0;
993
			int maxY = 0;
994
			int monitorCount;
995
			GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
996
			int tempXPos = 0;
997
			int tempYPos = 0;
998
			//lets find the total width of all the monitors
999
			//and we'll make the window height the height of the largest monitor.
1000
			for(int i = 0; i < monitorCount; i++){
1001
				const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[i]);
1002
				glfwGetMonitorPos(monitors[i], &tempXPos, &tempYPos);
1003
				minX = std::min(tempXPos,minX);
1004
				minY = std::min(tempYPos,minY);
1005
				maxX = std::max(maxX,tempXPos + desktopMode->width);
1006
				maxY = std::max(maxY,tempYPos + desktopMode->height);
1007

1008
				xpos = std::min(xpos,tempXPos);
1009
				ypos = std::min(ypos,tempYPos);
1010
			}
1011

1012
			fullscreenW = maxX-minX;
1013
			fullscreenH = maxY-minY;
1014
		}else{
1015

1016
			int monitorCount;
1017
			GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
1018
			int currentMonitor = getCurrentMonitor();
1019
			glfwGetMonitorPos(monitors[currentMonitor], &xpos, &ypos);
1020

1021
		}
1022

1023
		SetWindowPos(hwnd, HWND_TOPMOST, xpos, ypos, fullscreenW, fullscreenH, SWP_SHOWWINDOW);
1024
		currentW = fullscreenW;
1025
		currentH = fullscreenH;
1026

1027
	}else if( targetWindowMode == OF_WINDOW ){
1028
		// set window shape if started in fullscreen
1029
		if(windowRect.width == 0 && windowRect.height == 0) {
1030
			windowRect.x = getWindowPosition().x;
1031
			windowRect.y = getWindowPosition().y;
1032
			windowRect.width = getWindowSize().x;
1033
			windowRect.height = getWindowSize().y;
1034
		}
1035

1036
		HWND hwnd = glfwGetWin32Window(windowP);
1037

1038
		DWORD EX_STYLE = WS_EX_OVERLAPPEDWINDOW;
1039
		DWORD STYLE = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_SIZEBOX;
1040

1041
		ChangeDisplaySettings(0, 0);
1042
		SetWindowLong(hwnd, GWL_EXSTYLE, EX_STYLE);
1043
		SetWindowLong(hwnd, GWL_STYLE, STYLE);
1044
		SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
1045

1046
		//not sure why this is - but if we don't do this the window shrinks by 4 pixels in x and y
1047
		//should look for a better fix.
1048
		setWindowPosition(windowRect.x-2, windowRect.y-2);
1049
		setWindowShape(windowRect.width+4, windowRect.height+4);
1050
	}
1051
#endif
1052

1053
	settings.windowMode = targetWindowMode;
1054
}
1055

1056
//------------------------------------------------------------
1057
void ofAppGLFWWindow::toggleFullscreen(){
1058
	if (settings.windowMode == OF_GAME_MODE) return;
1059

1060

1061
	if (settings.windowMode == OF_WINDOW){
1062
		setFullscreen(true);
1063
	} else {
1064
		setFullscreen(false);
1065
	}
1066
}
1067

1068
//------------------------------------------------------------
1069
void ofAppGLFWWindow::setOrientation(ofOrientation orientation){
1070
	this->orientation = orientation;
1071
}
1072

1073
//------------------------------------------------------------
1074
ofOrientation ofAppGLFWWindow::getOrientation(){
1075
	return orientation;
1076
}
1077

1078
//------------------------------------------------------------
1079
static void rotateMouseXY(ofOrientation orientation, int w, int h, double &x, double &y) {
1080
	int savedY;
1081
	switch(orientation) {
1082
		case OF_ORIENTATION_180:
1083
			x = w - x;
1084
			y = h - y;
1085
		    break;
1086

1087
		case OF_ORIENTATION_90_RIGHT:
1088
			savedY = y;
1089
			y = x;
1090
			x = w-savedY;
1091
		    break;
1092

1093
		case OF_ORIENTATION_90_LEFT:
1094
			savedY = y;
1095
			y = h - x;
1096
			x = savedY;
1097
		    break;
1098

1099
		case OF_ORIENTATION_DEFAULT:
1100
		default:
1101
		    break;
1102
	}
1103
}
1104

1105
//------------------------------------------------------------
1106
ofAppGLFWWindow * ofAppGLFWWindow::setCurrent(GLFWwindow* windowP){
1107
	ofAppGLFWWindow * instance = static_cast<ofAppGLFWWindow *>(glfwGetWindowUserPointer(windowP));
1108
	shared_ptr<ofMainLoop> mainLoop = ofGetMainLoop();
1109
	if(mainLoop){
1110
		mainLoop->setCurrentWindow(instance);
1111
	}
1112
	instance->makeCurrent();
1113
	return instance;
1114
}
1115

1116

1117
namespace{
1118
int glfwtToOFModifiers(int mods){
1119
	int modifiers = 0;
1120
	if(mods & GLFW_MOD_SHIFT){
1121
		modifiers |= OF_KEY_SHIFT;
1122
	}
1123
	if(mods & GLFW_MOD_ALT){
1124
		modifiers |= OF_KEY_ALT;
1125
	}
1126
	if(mods & GLFW_MOD_CONTROL){
1127
		modifiers |= OF_KEY_CONTROL;
1128
	}
1129
	if(mods & GLFW_MOD_SUPER){
1130
		modifiers |= OF_KEY_SUPER;
1131
	}
1132
	return modifiers;
1133
}
1134

1135
unsigned long keycodeToUnicode(ofAppGLFWWindow * window, int scancode, int modifier){
1136
#ifdef TARGET_LINUX
1137
	XkbStateRec xkb_state = {};
1138
	XkbGetState(window->getX11Display(), XkbUseCoreKbd, &xkb_state);
1139
	XEvent ev = {0};
1140
	ev.xkey.keycode = scancode;
1141
	ev.xkey.state = xkb_state.mods & ~ControlMask;
1142
	ev.xkey.display = window->getX11Display();
1143
	ev.xkey.type = KeyPress;
1144
	KeySym keysym = NoSymbol;
1145
	int status;
1146
	char buffer[32] = {0};
1147
	char* chars = buffer;
1148
	auto count = Xutf8LookupString(window->getX11XIC(), &ev.xkey, chars, sizeof(buffer) - 1, &keysym, &status);
1149
	if ((count > 0 && (status == XLookupChars || status == XLookupBoth)) || status == XLookupKeySym){
1150
		char ** c = &chars;
1151
		unsigned int ch = 0, count = 0;
1152
		static const unsigned int offsets[] =
1153
		{
1154
		    0x00000000u, 0x00003080u, 0x000e2080u,
1155
		    0x03c82080u, 0xfa082080u, 0x82082080u
1156
		};
1157

1158
		do
1159
		{
1160
			ch = (ch << 6) + (unsigned char) **c;
1161
			(*c)++;
1162
			count++;
1163
		} while ((**c & 0xc0) == 0x80);
1164

1165
		if(count>6){
1166
			return 0;
1167
		}else{
1168
			return ch - offsets[count - 1];
1169
		}
1170
	}else{
1171
		return 0;
1172
	}
1173
#endif
1174
#ifdef TARGET_WIN32
1175
	static WCHAR buf[2];
1176
	static BYTE keyboardState[256];
1177
	GetKeyboardState( keyboardState );
1178

1179
	// Careful: keycode arrives translated into GLFW key codes,
1180
	// but keycode needs to be a virtual key (VK_...) so we're
1181
	// in deep troble, since this information has been removed
1182
	// by GLFW...
1183
	//
1184
	// The way around this is to ask the operating system
1185
	// nicely to create a virtual key for us, based on
1186
	// the scancode and the currently bound keyboard layout.
1187
	// https://msdn.microsoft.com/en-us/library/windows/desktop/ms646306(v=vs.85).aspx
1188
	//
1189
	// create a "fake" virtual key
1190

1191
	UINT fakeVirtualKey = MapVirtualKey( scancode, MAPVK_VSC_TO_VK_EX );
1192

1193
	int ret = ToUnicode( fakeVirtualKey, scancode, keyboardState, buf , 2, 0);
1194

1195
	if ( ret == 1 ){
1196
		return buf[0];
1197
	} else {
1198
		return 0;
1199
	}
1200
#endif
1201
#ifdef TARGET_OSX
1202
	static UInt32 deadKeyState = 0;
1203
	static UniChar characters[8];
1204
	static UniCharCount characterCount = 0;
1205

1206
	typedef struct __TISInputSource*  TISInputSourceRef;
1207
	typedef TISInputSourceRef (*pFnGetInputSource)(void); // define function pointer that may return a input source ref, no arguments
1208
	typedef void* (*pFnGetInputSourceProperty)(TISInputSourceRef,CFStringRef);
1209
	typedef UInt8 (*pFnGetKeyboardType)(void);
1210

1211
	static const CFBundleRef tisBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
1212

1213
	// We need to call some system methods, following GLFW's example
1214
	// in their OS X version of ```_glfwPlatformGetKeyName```.
1215
	//
1216
	// We know these methods must be available, since GLFW uses them
1217
	// internally.
1218
	//
1219
	// The most important method is ```UCKeyTranslate``` - everything
1220
	// else here is just a royal preparation party to feed it with the
1221
	// correct parameters.
1222
	//
1223
	// Since these methods are hidden deep within Carbon,
1224
	// we have to first request function pointers to make
1225
	// them callable.
1226
	//
1227
	// We do this only the first time, then we're re-using them,
1228
	// that's why these elements are marked static, and static const.
1229
	//
1230
	static pFnGetInputSource         getInputSource         = (pFnGetInputSource)CFBundleGetFunctionPointerForName(tisBundle, CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
1231
	static pFnGetKeyboardType        getKeyboardType        = (pFnGetKeyboardType)CFBundleGetFunctionPointerForName(tisBundle,CFSTR("LMGetKbdType"));
1232
	static pFnGetInputSourceProperty getInputSourceProperty = (pFnGetInputSourceProperty)CFBundleGetFunctionPointerForName(tisBundle, CFSTR("TISGetInputSourceProperty"));
1233

1234
	static const TISInputSourceRef sourceRef = getInputSource(); // note that for the first time, this creates a copy on the heap, then we're re-using it.
1235

1236
	static const CFStringRef* kPropertyUnicodeKeyLayoutData = (CFStringRef*)CFBundleGetDataPointerForName(tisBundle, CFSTR("kTISPropertyUnicodeKeyLayoutData"));
1237
	static const CFStringRef kTISPropertyUnicodeKeyLayoutData = * kPropertyUnicodeKeyLayoutData;
1238
	static const CFDataRef UnicodeKeyLayoutData = (CFDataRef)getInputSourceProperty(sourceRef, kTISPropertyUnicodeKeyLayoutData);
1239

1240
	static const UCKeyboardLayout* pKeyboardLayout = (UCKeyboardLayout*)CFDataGetBytePtr(UnicodeKeyLayoutData);
1241

1242
	UInt32 mod_OSX = 0;
1243
	{
1244
		// We have to translate the GLFW modifier bitflags back to OS X,
1245
		// so that SHIFT, CONTROL, etc can be taken into account when
1246
		// calculating the unicode codepoint.
1247

1248
		// UCKeyTranslate expects the Carbon-era modifier mask values,
1249
		// so use these instead of the NSEventModifierFlag enums
1250
		if (modifier & GLFW_MOD_SHIFT)
1251
			mod_OSX |= 512; // Carbon shiftKey value
1252
		if (modifier & GLFW_MOD_CONTROL)
1253
			mod_OSX |= 4096; // Carbon controlKey value
1254
		if (modifier & GLFW_MOD_ALT)
1255
			mod_OSX |= 2048; // Carbon optionKey value
1256
		if (modifier & GLFW_MOD_SUPER)
1257
			mod_OSX |= 256; // Carbon cmdKey
1258

1259
		// shift into 1 byte as per the Apple docs
1260
		mod_OSX = (mod_OSX >> 8) & 0xFF;
1261
	}
1262

1263
	// All this yak shaving was necessary to feed this diva of a function call:
1264
	// https://developer.apple.com/library/mac/documentation/Carbon/Reference/Unicode_Utilities_Ref/index.html#//apple_ref/c/func/UCKeyTranslate
1265

1266
	if (noErr == UCKeyTranslate(pKeyboardLayout,
1267
	                   scancode,
1268
	                   kUCKeyActionDisplay,
1269
	                   mod_OSX,
1270
	                   getKeyboardType(),
1271
	                   kUCKeyTranslateNoDeadKeysBit,
1272
	                   &deadKeyState,
1273
	                   sizeof(characters) / sizeof(characters[0]),
1274
	                   &characterCount,
1275
	                   characters))
1276
	{
1277
		// if successful, first character contains codepoint
1278
		return characters[0];
1279
	} else {
1280
		return 0;
1281
	}
1282

1283
#endif
1284
	return 0;
1285
}
1286
}
1287

1288
//------------------------------------------------------------
1289
void ofAppGLFWWindow::mouse_cb(GLFWwindow* windowP_, int button, int state, int mods) {
1290
	ofAppGLFWWindow * instance = setCurrent(windowP_);
1291

1292
#ifdef TARGET_OSX
1293
	//we do this as unlike glut, glfw doesn't report right click for ctrl click or middle click for alt click
1294
	if( instance->events().getKeyPressed(OF_KEY_CONTROL) && button == GLFW_MOUSE_BUTTON_LEFT){
1295
		button = GLFW_MOUSE_BUTTON_RIGHT;
1296
	}
1297
	if( instance->events().getKeyPressed(OF_KEY_ALT) && button == GLFW_MOUSE_BUTTON_LEFT){
1298
		button = GLFW_MOUSE_BUTTON_MIDDLE;
1299
	}
1300
#endif
1301

1302
	switch(button){
1303
	case GLFW_MOUSE_BUTTON_LEFT:
1304
		button = OF_MOUSE_BUTTON_LEFT;
1305
		break;
1306
	case GLFW_MOUSE_BUTTON_RIGHT:
1307
		button = OF_MOUSE_BUTTON_RIGHT;
1308
		break;
1309
	case GLFW_MOUSE_BUTTON_MIDDLE:
1310
		button = OF_MOUSE_BUTTON_MIDDLE;
1311
		break;
1312
	}
1313
	instance->buttonInUse = button;
1314

1315

1316
	ofMouseEventArgs::Type action;
1317
	if (state == GLFW_PRESS) {
1318
		action = ofMouseEventArgs::Pressed;
1319
		instance->buttonPressed=true;
1320
	} else {
1321
		action = ofMouseEventArgs::Released;
1322
		instance->buttonPressed=false;
1323
	}
1324

1325
	int modifiers = glfwtToOFModifiers(mods);
1326

1327
	ofMouseEventArgs args(action, instance->events().getMouseX(), instance->events().getMouseY(), button, modifiers);
1328

1329
	instance->events().notifyMouseEvent(args);
1330
}
1331

1332
//------------------------------------------------------------
1333
void ofAppGLFWWindow::motion_cb(GLFWwindow* windowP_, double x, double y) {
1334
	ofAppGLFWWindow * instance = setCurrent(windowP_);
1335
	rotateMouseXY(instance->orientation, instance->getWidth(), instance->getHeight(), x, y);
1336

1337
	ofMouseEventArgs::Type action;
1338
	if(!instance->buttonPressed){
1339
		action = ofMouseEventArgs::Moved;
1340
	}else{
1341
		action = ofMouseEventArgs::Dragged;
1342
	}
1343

1344
	ofMouseEventArgs args(action,
1345
	    x*instance->pixelScreenCoordScale,
1346
	    y*instance->pixelScreenCoordScale,
1347
	    instance->buttonInUse,
1348
	    instance->events().getModifiers());
1349
	instance->events().notifyMouseEvent(args);
1350
}
1351

1352
//------------------------------------------------------------
1353
void ofAppGLFWWindow::entry_cb(GLFWwindow *windowP_, int entered) {
1354
	ofAppGLFWWindow * instance = setCurrent(windowP_);
1355
	ofMouseEventArgs::Type action;
1356
	if(entered){
1357
		action = ofMouseEventArgs::Entered;
1358
	}else{
1359
		action = ofMouseEventArgs::Exited;
1360
	}
1361

1362
	ofMouseEventArgs args(action,
1363
	    instance->events().getMouseX(),
1364
	    instance->events().getMouseY(),
1365
	    instance->buttonInUse,
1366
	    instance->events().getModifiers());
1367
	instance->events().notifyMouseEvent(args);
1368
}
1369

1370
//------------------------------------------------------------
1371
void ofAppGLFWWindow::scroll_cb(GLFWwindow* windowP_, double x, double y) {
1372
	ofAppGLFWWindow * instance = setCurrent(windowP_);
1373
	rotateMouseXY(instance->orientation, instance->getWidth(), instance->getHeight(), x, y);
1374

1375
	ofMouseEventArgs args(ofMouseEventArgs::Scrolled,
1376
	    instance->events().getMouseX(),
1377
	    instance->events().getMouseY(),
1378
	    instance->buttonInUse,
1379
	    instance->events().getModifiers());
1380
	args.scrollX = x;
1381
	args.scrollY = y;
1382
	instance->events().notifyMouseEvent(args);
1383
}
1384

1385
//------------------------------------------------------------
1386
void ofAppGLFWWindow::drop_cb(GLFWwindow* windowP_, int numFiles, const char** dropString) {
1387
	ofAppGLFWWindow * instance = setCurrent(windowP_);
1388
	ofDragInfo drag;
1389
	drag.position = {instance->events().getMouseX(), instance->events().getMouseY()};
1390
	drag.files.resize(numFiles);
1391
	for(int i=0; i<(int)drag.files.size(); i++){
1392
		drag.files[i] = of::filesystem::path(dropString[i]).string();
1393
	}
1394
	instance->events().notifyDragEvent(drag);
1395
}
1396

1397
//------------------------------------------------------------
1398
void ofAppGLFWWindow::error_cb(int errorCode, const char* errorDescription){
1399
	ofLogError("ofAppGLFWWindow") << errorCode << ": " << errorDescription;
1400
}
1401

1402
//------------------------------------------------------------
1403
void ofAppGLFWWindow::keyboard_cb(GLFWwindow* windowP_, int keycode, int scancode, int action, int mods) {
1404
	int key = 0;
1405
	uint32_t codepoint = 0;
1406
	ofAppGLFWWindow * instance = setCurrent(windowP_);
1407
	switch (keycode) {
1408
		case GLFW_KEY_ESCAPE:
1409
			key = OF_KEY_ESC;
1410
		    break;
1411
		case GLFW_KEY_F1:
1412
			key = OF_KEY_F1;
1413
		    break;
1414
		case GLFW_KEY_F2:
1415
			key = OF_KEY_F2;
1416
		    break;
1417
		case GLFW_KEY_F3:
1418
			key = OF_KEY_F3;
1419
		    break;
1420
		case GLFW_KEY_F4:
1421
			key = OF_KEY_F4;
1422
		    break;
1423
		case GLFW_KEY_F5:
1424
			key = OF_KEY_F5;
1425
		    break;
1426
		case GLFW_KEY_F6:
1427
			key = OF_KEY_F6;
1428
		    break;
1429
		case GLFW_KEY_F7:
1430
			key = OF_KEY_F7;
1431
		    break;
1432
		case GLFW_KEY_F8:
1433
			key = OF_KEY_F8;
1434
		    break;
1435
		case GLFW_KEY_F9:
1436
			key = OF_KEY_F9;
1437
		    break;
1438
		case GLFW_KEY_F10:
1439
			key = OF_KEY_F10;
1440
		    break;
1441
		case GLFW_KEY_F11:
1442
			key = OF_KEY_F11;
1443
		    break;
1444
		case GLFW_KEY_F12:
1445
			key = OF_KEY_F12;
1446
		    break;
1447
		case GLFW_KEY_LEFT:
1448
			key = OF_KEY_LEFT;
1449
		    break;
1450
		case GLFW_KEY_RIGHT:
1451
			key = OF_KEY_RIGHT;
1452
		    break;
1453
		case GLFW_KEY_UP:
1454
			key = OF_KEY_UP;
1455
		    break;
1456
		case GLFW_KEY_DOWN:
1457
			key = OF_KEY_DOWN;
1458
		    break;
1459
		case GLFW_KEY_PAGE_UP:
1460
			key = OF_KEY_PAGE_UP;
1461
		    break;
1462
		case GLFW_KEY_PAGE_DOWN:
1463
			key = OF_KEY_PAGE_DOWN;
1464
		    break;
1465
		case GLFW_KEY_HOME:
1466
			key = OF_KEY_HOME;
1467
		    break;
1468
		case GLFW_KEY_END:
1469
			key = OF_KEY_END;
1470
		    break;
1471
		case GLFW_KEY_INSERT:
1472
			key = OF_KEY_INSERT;
1473
		    break;
1474
		case GLFW_KEY_LEFT_SHIFT:
1475
			key = OF_KEY_LEFT_SHIFT;
1476
		    break;
1477
		case GLFW_KEY_LEFT_CONTROL:
1478
			key = OF_KEY_LEFT_CONTROL;
1479
		    break;
1480
		case GLFW_KEY_LEFT_ALT:
1481
			key = OF_KEY_LEFT_ALT;
1482
		    break;
1483
		case GLFW_KEY_LEFT_SUPER:
1484
			key = OF_KEY_LEFT_SUPER;
1485
		    break;
1486
		case GLFW_KEY_RIGHT_SHIFT:
1487
			key = OF_KEY_RIGHT_SHIFT;
1488
		    break;
1489
		case GLFW_KEY_RIGHT_CONTROL:
1490
			key = OF_KEY_RIGHT_CONTROL;
1491
		    break;
1492
		case GLFW_KEY_RIGHT_ALT:
1493
			key = OF_KEY_RIGHT_ALT;
1494
		    break;
1495
		case GLFW_KEY_RIGHT_SUPER:
1496
			key = OF_KEY_RIGHT_SUPER;
1497
		    break;
1498
		case GLFW_KEY_BACKSPACE:
1499
			key = OF_KEY_BACKSPACE;
1500
		    break;
1501
		case GLFW_KEY_DELETE:
1502
			key = OF_KEY_DEL;
1503
		    break;
1504
		case GLFW_KEY_ENTER:
1505
			key = OF_KEY_RETURN;
1506
			codepoint = '\n';
1507
		    break;
1508
		case GLFW_KEY_KP_ENTER:
1509
			key = OF_KEY_RETURN;
1510
			codepoint = '\n';
1511
		    break;
1512
		case GLFW_KEY_TAB:
1513
			key = OF_KEY_TAB;
1514
			codepoint = '\t';
1515
		    break;
1516
		case GLFW_KEY_KP_0:
1517
			key = codepoint = '0';
1518
		    break;
1519
		case GLFW_KEY_KP_1:
1520
			key = codepoint = '1';
1521
		    break;
1522
		case GLFW_KEY_KP_2:
1523
			key = codepoint = '2';
1524
		    break;
1525
		case GLFW_KEY_KP_3:
1526
			key = codepoint = '3';
1527
		    break;
1528
		case GLFW_KEY_KP_4:
1529
			key = codepoint = '4';
1530
		    break;
1531
		case GLFW_KEY_KP_5:
1532
			key = codepoint = '5';
1533
		    break;
1534
		case GLFW_KEY_KP_6:
1535
			key = codepoint = '6';
1536
		    break;
1537
		case GLFW_KEY_KP_7:
1538
			key = codepoint = '7';
1539
		    break;
1540
		case GLFW_KEY_KP_8:
1541
			key = codepoint = '8';
1542
		    break;
1543
		case GLFW_KEY_KP_9:
1544
			key = codepoint = '9';
1545
		    break;
1546
		case GLFW_KEY_KP_DIVIDE:
1547
			key = codepoint = '/';
1548
		    break;
1549
		case GLFW_KEY_KP_MULTIPLY:
1550
			key = codepoint = '*';
1551
		    break;
1552
		case GLFW_KEY_KP_SUBTRACT:
1553
			key = codepoint = '-';
1554
		    break;
1555
		case GLFW_KEY_KP_ADD:
1556
			key = codepoint = '+';
1557
		    break;
1558
		case GLFW_KEY_KP_DECIMAL:
1559
			key = codepoint = '.';
1560
		    break;
1561
		case GLFW_KEY_KP_EQUAL:
1562
			key = codepoint = '=';
1563
		    break;
1564
		default:
1565
			codepoint = keycodeToUnicode(instance, scancode, mods);
1566
			key = codepoint;
1567
		    break;
1568
	}
1569

1570
	int modifiers = glfwtToOFModifiers(mods);
1571

1572
	if(action == GLFW_PRESS){
1573
		ofKeyEventArgs keyE(ofKeyEventArgs::Pressed,key,keycode,scancode,codepoint,modifiers);
1574
		instance->events().notifyKeyEvent(keyE);
1575
	}else if(action == GLFW_REPEAT){
1576
		ofKeyEventArgs keyE(ofKeyEventArgs::Pressed,key,keycode,scancode,codepoint,modifiers);
1577
		keyE.isRepeat = true;
1578
		instance->events().notifyKeyEvent(keyE);
1579
	}else if (action == GLFW_RELEASE){
1580
		ofKeyEventArgs keyE(ofKeyEventArgs::Released,key,keycode,scancode,codepoint,modifiers);
1581
		instance->events().notifyKeyEvent(keyE);
1582
	}
1583
}
1584

1585
//------------------------------------------------------------
1586
void ofAppGLFWWindow::char_cb(GLFWwindow* windowP_, uint32_t key){
1587
	ofAppGLFWWindow * instance = setCurrent(windowP_);
1588
	instance->events().charEvent.notify(key);
1589
}
1590

1591
//------------------------------------------------------------
1592
void ofAppGLFWWindow::resize_cb(GLFWwindow* windowP_, int w, int h) {
1593
	ofAppGLFWWindow * instance = setCurrent(windowP_);
1594

1595
	// Detect if the window is running in a retina mode
1596

1597
	int framebufferW, framebufferH; // <- physical pixel extents
1598
	glfwGetFramebufferSize(windowP_, &framebufferW, &framebufferH);
1599

1600
	int windowW, windowH; // <- screen coordinates, which may be scaled
1601
	glfwGetWindowSize(windowP_, &windowW, &windowH);
1602

1603
	// Find scale factor needed to transform from screen coordinates
1604
	// to physical pixel coordinates
1605
	instance->pixelScreenCoordScale = (float)framebufferW / (float)windowW;
1606

1607
	if(instance->settings.windowMode == OF_WINDOW){
1608
		instance->windowW = framebufferW;
1609
		instance->windowH = framebufferH;
1610
	}
1611

1612
	instance->currentW = windowW;
1613
	instance->currentH = windowH;
1614
	instance->events().notifyWindowResized(framebufferW, framebufferH);
1615
	instance->nFramesSinceWindowResized = 0;
1616
 
1617
         #if defined(TARGET_OSX)
1618
            NSWindow * cocoaWindow = glfwGetCocoaWindow(windowP_);
1619
            if (([cocoaWindow styleMask] & NSWindowStyleMaskFullScreen) == NSWindowStyleMaskFullScreen) {
1620
                instance->settings.windowMode = OF_FULLSCREEN;
1621
            }else{
1622
                instance->settings.windowMode = OF_WINDOW;
1623
            }
1624
        #endif
1625
}
1626

1627
//------------------------------------------------------------
1628
void ofAppGLFWWindow::framebuffer_size_cb(GLFWwindow* windowP_, int w, int h){
1629
	resize_cb(windowP_, w, h);
1630
}
1631

1632
//--------------------------------------------
1633
void ofAppGLFWWindow::exit_cb(GLFWwindow* windowP_){
1634
	ofAppGLFWWindow * instance = setCurrent(windowP_);
1635
	instance->events().notifyExit();
1636
}
1637

1638
//------------------------------------------------------------
1639
void ofAppGLFWWindow::setVerticalSync(bool bVerticalSync){
1640
	if(bVerticalSync){
1641
		glfwSwapInterval( 1);
1642
	}else{
1643
		glfwSwapInterval(0);
1644
	}
1645
}
1646

1647
//------------------------------------------------------------
1648
void ofAppGLFWWindow::setClipboardString(const std::string& text) {
1649
	glfwSetClipboardString(ofAppGLFWWindow::windowP, text.c_str());
1650
}
1651

1652
//------------------------------------------------------------
1653
std::string ofAppGLFWWindow::getClipboardString() {
1654
	const char* clipboard = glfwGetClipboardString(ofAppGLFWWindow::windowP);
1655

1656
	if (clipboard) {
1657
		return clipboard;
1658
	} else {
1659
		return "";
1660
	}
1661
}
1662

1663
//------------------------------------------------------------
1664
void ofAppGLFWWindow::listVideoModes(){
1665
	glfwInit();
1666
	int numModes;
1667
	const GLFWvidmode * vidModes = glfwGetVideoModes(nullptr, &numModes );
1668
	for(int i=0; i<numModes; i++){
1669
		ofLogNotice() << vidModes[i].width << " x " << vidModes[i].height
1670
		<< vidModes[i].redBits+vidModes[i].greenBits+vidModes[i].blueBits << "bit";
1671
	}
1672
}
1673

1674
//------------------------------------------------------------
1675
void ofAppGLFWWindow::listMonitors(){
1676
	glfwInit();
1677
	int count;
1678
	const auto monitors = glfwGetMonitors(&count);
1679
	for(int i = 0; i<count; i++){
1680
		auto monitor = monitors[i];
1681
		int w,h,x,y;
1682
		glfwGetMonitorPhysicalSize(monitor,&w,&h);
1683
		glfwGetMonitorPos(monitor,&x,&y);
1684
		ofLogNotice() << i << ": " << glfwGetMonitorName(monitor) << ", physical size: " << w << "x" << h << "mm at " << x << ", " << y;
1685
	}
1686
}
1687

1688
//------------------------------------------------------------
1689
bool ofAppGLFWWindow::isWindowIconified(){
1690
	return glfwGetWindowAttrib(windowP, GLFW_ICONIFIED);
1691
}
1692

1693
//------------------------------------------------------------
1694
bool ofAppGLFWWindow::isWindowActive(){
1695
//	return glfwGetWindowParam(GLFW_ACTIVE);
1696
	return true;
1697
}
1698

1699
//------------------------------------------------------------
1700
bool ofAppGLFWWindow::isWindowResizeable(){
1701
	return !glfwGetWindowAttrib(windowP, GLFW_RESIZABLE);
1702
}
1703

1704
//------------------------------------------------------------
1705
void ofAppGLFWWindow::iconify(bool bIconify){
1706
	if(bIconify)
1707
		glfwIconifyWindow(windowP);
1708
	else
1709
		glfwRestoreWindow(windowP);
1710
}
1711

1712

1713

1714
void ofAppGLFWWindow::makeCurrent(){
1715
	glfwMakeContextCurrent(windowP);
1716
}
1717

1718
#if defined(TARGET_LINUX)
1719
Display* ofAppGLFWWindow::getX11Display(){
1720
	return glfwGetX11Display();
1721
}
1722

1723
Window ofAppGLFWWindow::getX11Window(){
1724
	return glfwGetX11Window(windowP);
1725
}
1726

1727
XIC	ofAppGLFWWindow::getX11XIC(){
1728
	return xic;
1729
}
1730
#endif
1731

1732
#if defined(TARGET_LINUX) && !defined(TARGET_OPENGLES)
1733
GLXContext ofAppGLFWWindow::getGLXContext(){
1734
	return glfwGetGLXContext(windowP);
1735
}
1736
#endif
1737

1738
#if defined(TARGET_LINUX) && defined(TARGET_OPENGLES)
1739
EGLDisplay ofAppGLFWWindow::getEGLDisplay(){
1740
	return glfwGetEGLDisplay();
1741
}
1742

1743
EGLContext ofAppGLFWWindow::getEGLContext(){
1744
	return glfwGetEGLContext(windowP);
1745
}
1746

1747
EGLSurface ofAppGLFWWindow::getEGLSurface(){
1748
	return glfwGetEGLSurface(windowP);
1749
}
1750
#endif
1751

1752
#if defined(TARGET_OSX)
1753
void * ofAppGLFWWindow::getNSGLContext(){
1754
	return (__bridge void *)glfwGetNSGLContext(windowP);
1755
}
1756

1757
void * ofAppGLFWWindow::getCocoaWindow(){
1758
	return (__bridge void *)glfwGetCocoaWindow(windowP);
1759
}
1760
#endif
1761

1762
#if defined(TARGET_WIN32)
1763
HGLRC ofAppGLFWWindow::getWGLContext(){
1764
	return glfwGetWGLContext(windowP);
1765
}
1766

1767
HWND ofAppGLFWWindow::getWin32Window(){
1768
	return glfwGetWin32Window(windowP);
1769
}
1770

1771
#endif
1772

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.