#include "ofAppGLFWWindow.h"
#include "ofEvents.h"
#include "ofBaseApp.h"
#include "ofGLRenderer.h"
#include "ofGLProgrammableRenderer.h"
#include "ofAppRunner.h"
#include "ofFileUtils.h"
#include "ofEvents.h"
#include "ofPixels.h"
#define GLFW_INCLUDE_NONE
#include "GLFW/glfw3.h"
#ifdef TARGET_LINUX
#include "ofIcon.h"
#include "ofImage.h"
#define GLFW_EXPOSE_NATIVE_X11
#ifndef TARGET_OPENGLES
#define GLFW_EXPOSE_NATIVE_GLX
#else
#define GLFW_EXPOSE_NATIVE_EGL
#endif
#include <X11/extensions/Xrandr.h>
#include <X11/XKBlib.h>
#include "GLFW/glfw3native.h"
#include <X11/Xatom.h>
#include <xcb/xcb.h>
#include <xcb/xcbext.h>
#elif defined(TARGET_OSX)
#include <Cocoa/Cocoa.h>
#define GLFW_EXPOSE_NATIVE_COCOA
#define GLFW_EXPOSE_NATIVE_NSGL
#include "GLFW/glfw3native.h"
#elif defined(TARGET_WIN32)
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
#include <GLFW/glfw3native.h>
#endif
using namespace std;
ofAppGLFWWindow::ofAppGLFWWindow()
:coreEvents(new ofCoreEvents) {
bEnableSetupScreen = true;
buttonInUse = 0;
buttonPressed = false;
bWindowNeedsShowing = true;
orientation = OF_ORIENTATION_DEFAULT;
targetWindowMode = OF_WINDOW;
ofAppPtr = nullptr;
pixelScreenCoordScale = 1;
nFramesSinceWindowResized = 0;
iconSet = false;
windowP = nullptr;
windowW = 0;
windowH = 0;
currentW = 0;
currentH = 0;
glfwSetErrorCallback(error_cb);
}
ofAppGLFWWindow::~ofAppGLFWWindow(){
close();
}
void ofAppGLFWWindow::close(){
if(windowP){
glfwSetMouseButtonCallback( windowP, nullptr );
glfwSetCursorPosCallback( windowP, nullptr );
glfwSetCursorEnterCallback( windowP, nullptr );
glfwSetKeyCallback( windowP, nullptr );
glfwSetWindowSizeCallback( windowP, nullptr );
glfwSetFramebufferSizeCallback( windowP, nullptr);
glfwSetWindowCloseCallback( windowP, nullptr );
glfwSetScrollCallback( windowP, nullptr );
#if GLFW_VERSION_MAJOR>3 || GLFW_VERSION_MINOR>=1
glfwSetDropCallback( windowP, nullptr );
#endif
glfwHideWindow(windowP);
currentRenderer.reset();
glfwDestroyWindow(windowP);
windowP = nullptr;
events().disable();
bWindowNeedsShowing = true;
}
}
void ofAppGLFWWindow::setNumSamples(int _samples){
settings.numSamples=_samples;
}
void ofAppGLFWWindow::setMultiDisplayFullscreen(bool bMultiFullscreen){
settings.multiMonitorFullScreen = bMultiFullscreen;
}
void ofAppGLFWWindow::setDoubleBuffering(bool doubleBuff){
settings.doubleBuffering = doubleBuff;
}
void ofAppGLFWWindow::setColorBits(int r, int g, int b){
settings.redBits=r;
settings.greenBits=g;
settings.blueBits=b;
}
void ofAppGLFWWindow::setAlphaBits(int a){
settings.alphaBits=a;
}
void ofAppGLFWWindow::setDepthBits(int depth){
settings.depthBits=depth;
}
void ofAppGLFWWindow::setStencilBits(int stencil){
settings.stencilBits=stencil;
}
#ifdef TARGET_OPENGLES
void ofAppGLFWWindow::setup(const ofGLESWindowSettings & settings){
#else
void ofAppGLFWWindow::setup(const ofGLWindowSettings & settings){
#endif
const ofGLFWWindowSettings * glSettings = dynamic_cast<const ofGLFWWindowSettings*>(&settings);
if(glSettings){
setup(*glSettings);
}else{
setup(ofGLFWWindowSettings(settings));
}
}
void ofAppGLFWWindow::setup(const ofGLFWWindowSettings & _settings){
if(windowP){
ofLogError() << "window already setup, probably you are mixing old and new style setup";
ofLogError() << "call only ofCreateWindow(settings) or ofSetupOpenGL(...)";
ofLogError() << "calling window->setup() after ofCreateWindow() is not necesary and won't do anything";
return;
}
settings = _settings;
if(!glfwInit( )){
ofLogError("ofAppGLFWWindow") << "couldn't init GLFW";
return;
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_RED_BITS, settings.redBits);
glfwWindowHint(GLFW_GREEN_BITS, settings.greenBits);
glfwWindowHint(GLFW_BLUE_BITS, settings.blueBits);
glfwWindowHint(GLFW_ALPHA_BITS, settings.alphaBits);
glfwWindowHint(GLFW_DEPTH_BITS, settings.depthBits);
glfwWindowHint(GLFW_STENCIL_BITS, settings.stencilBits);
glfwWindowHint(GLFW_STEREO, settings.stereo);
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
#ifndef TARGET_OSX
glfwWindowHint(GLFW_AUX_BUFFERS, settings.doubleBuffering?1:0);
#endif
glfwWindowHint(GLFW_SAMPLES, settings.numSamples);
glfwWindowHint(GLFW_RESIZABLE, settings.resizable);
glfwWindowHint(GLFW_DECORATED, settings.decorated);
#ifdef TARGET_OPENGLES
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, settings.glesVersion);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
if(settings.glesVersion>=2){
currentRenderer = std::make_shared<ofGLProgrammableRenderer>(this);
}else{
currentRenderer = std::make_shared<ofGLRenderer>(this);
}
#else
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, settings.glVersionMajor);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, settings.glVersionMinor);
if((settings.glVersionMajor==3 && settings.glVersionMinor>=2) || settings.glVersionMajor>=4){
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
}
if(settings.glVersionMajor>=3){
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
currentRenderer = std::make_shared<ofGLProgrammableRenderer>(this);
}else{
currentRenderer = std::make_shared<ofGLRenderer>(this);
}
#endif
GLFWwindow * sharedContext = nullptr;
if(settings.shareContextWith){
sharedContext = (GLFWwindow*)settings.shareContextWith->getWindowContext();
}
if(settings.windowMode==OF_GAME_MODE){
int count;
GLFWmonitor** monitors = glfwGetMonitors(&count);
if(settings.isSizeSet()){
currentW = settings.getWidth();
currentH = settings.getHeight();
}else{
auto mode = glfwGetVideoMode(monitors[settings.monitor]);
currentW = mode->width;
currentH = mode->height;
}
if(count>settings.monitor){
windowP = glfwCreateWindow(currentW, currentH, settings.title.c_str(), monitors[settings.monitor], sharedContext);
}else{
ofLogError("ofAppGLFWWindow") << "couldn't find any monitors";
return;
}
}else{
windowP = glfwCreateWindow(settings.getWidth(), settings.getHeight(), settings.title.c_str(), nullptr, sharedContext);
if(!windowP){
ofLogError("ofAppGLFWWindow") << "couldn't create GLFW window";
return;
}
if(settings.windowMode==OF_FULLSCREEN){
int count = 0;
auto monitors = glfwGetMonitors(&count);
auto mode = glfwGetVideoMode(monitors[settings.monitor]);
currentW = mode->width;
currentH = mode->height;
if(!settings.isPositionSet()){
if(count > 0){
int x = 0, y = 0;
settings.monitor = ofClamp(settings.monitor,0,count-1);
glfwGetMonitorPos(monitors[settings.monitor],&x,&y);
settings.setPosition(glm::vec2(x,y));
setWindowPosition(settings.getPosition().x,settings.getPosition().y);
auto mode = glfwGetVideoMode(monitors[settings.monitor]);
#ifdef TARGET_OSX
settings.setSize(mode->width, mode->height);
setWindowShape(settings.getWidth(), settings.getHeight());
#endif
setWindowPosition(settings.getPosition().x,settings.getPosition().y);
currentW = mode->width;
currentH = mode->height;
}
}else{
setWindowPosition(settings.getPosition().x,settings.getPosition().y);
#ifdef TARGET_OSX
auto size = getScreenSize();
settings.setSize(size.x, size.y);
setWindowShape(settings.getWidth(), settings.getHeight());
#endif
currentW = settings.getWidth();
currentH = settings.getHeight();
for(int i = 0; i < count; i++){
int x = 0, y = 0;
glfwGetMonitorPos(monitors[i],&x,&y);
auto mode = glfwGetVideoMode(monitors[i]);
int w = mode->width;
int h = mode->height;
ofRectangle rect(x-1,y-1,w+1,h+1);
if(rect.inside(settings.getPosition())){
currentW = mode->width;
currentH = mode->height;
break;
}
}
}
targetWindowMode = settings.windowMode;
settings.windowMode = OF_WINDOW;
}else{
if (settings.isPositionSet()) {
setWindowPosition(settings.getPosition().x,settings.getPosition().y);
}
glfwGetWindowSize( windowP, ¤tW, ¤tH );
}
#ifdef TARGET_LINUX
if(!iconSet){
ofPixels iconPixels;
#ifdef DEBUG
iconPixels.allocate(ofIconDebug.width,ofIconDebug.height,ofIconDebug.bytes_per_pixel);
GIMP_IMAGE_RUN_LENGTH_DECODE(iconPixels.getData(),ofIconDebug.rle_pixel_data,iconPixels.getWidth()*iconPixels.getHeight(),ofIconDebug.bytes_per_pixel);
#else
iconPixels.allocate(ofIcon.width,ofIcon.height,ofIcon.bytes_per_pixel);
GIMP_IMAGE_RUN_LENGTH_DECODE(iconPixels.getData(),ofIcon.rle_pixel_data,iconPixels.getWidth()*iconPixels.getHeight(),ofIcon.bytes_per_pixel);
#endif
setWindowIcon(iconPixels);
}
#endif
if(settings.iconified){
iconify(true);
}
}
bWindowNeedsShowing = settings.visible;
glfwSetWindowUserPointer(windowP,this);
windowW = settings.getWidth();
windowH = settings.getHeight();
#ifdef TARGET_RASPBERRY_PI
windowRect.width = windowW;
windowRect.height = windowH;
#endif
glfwMakeContextCurrent(windowP);
int framebufferW, framebufferH, tmpWindowW, tmpWindowH;
glfwGetFramebufferSize(windowP, &framebufferW, &framebufferH);
glfwGetWindowSize( windowP, &tmpWindowW, &tmpWindowH );
if( framebufferW != tmpWindowW){
pixelScreenCoordScale = (float)framebufferW / (float)windowW;
if( pixelScreenCoordScale < 1 ){
pixelScreenCoordScale = 1;
}
if(targetWindowMode == OF_WINDOW){
auto position = getWindowPosition();
setWindowShape(windowW, windowH);
setWindowPosition(position.x, position.y);
}
}
#ifndef TARGET_OPENGLES
static bool inited = false;
if(!inited){
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
ofLogError("ofAppRunner") << "couldn't init GLEW: " << glewGetErrorString(err);
return;
}
inited = true;
}
#endif
ofLogVerbose() << "GL Version:" << glGetString(GL_VERSION);
if(currentRenderer->getType()==ofGLProgrammableRenderer::TYPE){
#ifndef TARGET_OPENGLES
static_cast<ofGLProgrammableRenderer*>(currentRenderer.get())->setup(settings.glVersionMajor,settings.glVersionMinor);
#else
static_cast<ofGLProgrammableRenderer*>(currentRenderer.get())->setup(settings.glesVersion,0);
#endif
}else{
static_cast<ofGLRenderer*>(currentRenderer.get())->setup();
}
setVerticalSync(true);
glfwSetMouseButtonCallback(windowP, mouse_cb);
glfwSetCursorPosCallback(windowP, motion_cb);
glfwSetCursorEnterCallback(windowP, entry_cb);
glfwSetKeyCallback(windowP, keyboard_cb);
glfwSetCharCallback(windowP, char_cb);
glfwSetWindowSizeCallback(windowP, resize_cb);
glfwSetFramebufferSizeCallback( windowP, framebuffer_size_cb);
glfwSetWindowCloseCallback(windowP, exit_cb);
glfwSetScrollCallback(windowP, scroll_cb);
#if GLFW_VERSION_MAJOR>3 || GLFW_VERSION_MINOR>=1
glfwSetDropCallback( windowP, drop_cb );
#endif
#ifdef TARGET_LINUX
XSetLocaleModifiers("");
xim = XOpenIM(getX11Display(), 0, 0, 0);
if(!xim){
XSetLocaleModifiers("@im=none");
xim = XOpenIM(getX11Display(), 0, 0, 0);
}
xic = XCreateIC(xim,
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
XNClientWindow, getX11Window(),
XNFocusWindow, getX11Window(),
NULL);
#endif
}
#ifdef TARGET_LINUX
void ofAppGLFWWindow::setWindowIcon(const string & path){
ofPixels iconPixels;
ofLoadImage(iconPixels,path);
setWindowIcon(iconPixels);
}
void ofAppGLFWWindow::setWindowIcon(const ofPixels & iconPixels){
iconSet = true;
int length = 2+iconPixels.getWidth()*iconPixels.getHeight();
vector<unsigned long> buffer(length);
buffer[0]=iconPixels.getWidth();
buffer[1]=iconPixels.getHeight();
for(size_t i=0;i<iconPixels.getWidth()*iconPixels.getHeight();i++){
buffer[i+2] = iconPixels[i*4+3]<<24;
buffer[i+2] += iconPixels[i*4+0]<<16;
buffer[i+2] += iconPixels[i*4+1]<<8;
buffer[i+2] += iconPixels[i*4+2];
}
XChangeProperty(getX11Display(), getX11Window(), XInternAtom(getX11Display(), "_NET_WM_ICON", False), XA_CARDINAL, 32,
PropModeReplace, (const unsigned char*)buffer.data(), length);
XFlush(getX11Display());
}
#endif
ofCoreEvents & ofAppGLFWWindow::events(){
return *coreEvents;
}
shared_ptr<ofBaseRenderer> & ofAppGLFWWindow::renderer(){
return currentRenderer;
}
void ofAppGLFWWindow::update(){
events().notifyUpdate();
if( bWindowNeedsShowing && windowP ){
glfwShowWindow(windowP);
bWindowNeedsShowing = false;
if(targetWindowMode==OF_FULLSCREEN){
setFullscreen(true);
}
}
#ifdef TARGET_RASPBERRY_PI
if( needsResizeCheck && windowP ){
int winW, winH;
glfwGetWindowSize(windowP, &winW, &winH);
if( winW == windowRect.getWidth() && winH == windowRect.getHeight() ){
resize_cb(windowP, currentW, currentH);
needsResizeCheck = false;
}
}
#endif
}
void ofAppGLFWWindow::pollEvents(){
glfwPollEvents();
}
void ofAppGLFWWindow::draw(){
currentRenderer->startRender();
if( bEnableSetupScreen ) currentRenderer->setupScreen();
events().notifyDraw();
#ifdef TARGET_WIN32
if (currentRenderer->getBackgroundAuto() == false){
if (nFramesSinceWindowResized < 3){
currentRenderer->clear();
} else {
if ( (events().getFrameNum() < 3 || nFramesSinceWindowResized < 3) && settings.doubleBuffering){
glfwSwapBuffers(windowP);
}else{
glFlush();
}
}
} else {
if(settings.doubleBuffering){
glfwSwapBuffers(windowP);
} else {
glFlush();
}
}
#else
if (currentRenderer->getBackgroundAuto() == false){
if (nFramesSinceWindowResized < 3){
currentRenderer->clear();
}
}
if(settings.doubleBuffering){
glfwSwapBuffers(windowP);
} else{
glFlush();
}
#endif
currentRenderer->finishRender();
nFramesSinceWindowResized++;
}
void ofAppGLFWWindow::swapBuffers() {
glfwSwapBuffers(windowP);
}
void ofAppGLFWWindow::startRender() {
renderer()->startRender();
}
void ofAppGLFWWindow::finishRender() {
renderer()->finishRender();
}
bool ofAppGLFWWindow::getWindowShouldClose(){
return glfwWindowShouldClose(windowP);
}
void ofAppGLFWWindow::setWindowShouldClose(){
glfwSetWindowShouldClose(windowP,1);
}
void ofAppGLFWWindow::setWindowTitle(string title){
settings.title = title;
glfwSetWindowTitle(windowP,settings.title.c_str());
}
int ofAppGLFWWindow::getPixelScreenCoordScale(){
return pixelScreenCoordScale;
}
glm::vec2 ofAppGLFWWindow::getWindowSize(){
if(settings.windowMode == OF_GAME_MODE)
{
const GLFWvidmode * desktopMode = glfwGetVideoMode(glfwGetWindowMonitor(windowP));
if(desktopMode){
return {desktopMode->width*pixelScreenCoordScale, desktopMode->height*pixelScreenCoordScale};
}else{
return {currentW*pixelScreenCoordScale, currentH*pixelScreenCoordScale};
}
}else{
return {currentW*pixelScreenCoordScale, currentH*pixelScreenCoordScale};
}
}
glm::vec2 ofAppGLFWWindow::getWindowPosition(){
int x, y;
glfwGetWindowPos(windowP, &x, &y);
x *= pixelScreenCoordScale;
y *= pixelScreenCoordScale;
if( orientation == OF_ORIENTATION_DEFAULT || orientation == OF_ORIENTATION_180 ){
return glm::vec2{x,y};
}else{
return glm::vec2(x,y);
}
}
int ofAppGLFWWindow::getCurrentMonitor(){
int numberOfMonitors;
GLFWmonitor** monitors = glfwGetMonitors(&numberOfMonitors);
int xW; int yW;
glfwGetWindowPos(windowP, &xW, &yW);
for (int iC=0; iC < numberOfMonitors; iC++){
int xM; int yM;
glfwGetMonitorPos(monitors[iC], &xM, &yM);
const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[iC]);
ofRectangle monitorRect(xM, yM, desktopMode->width, desktopMode->height);
bool bPointMatch = xW >= monitorRect.getMinX() && yW >= monitorRect.getMinY() && xW < monitorRect.getMaxX() && yW < monitorRect.getMaxY();
if( bPointMatch ) {
return iC;
break;
}
}
return 0;
}
glm::vec2 ofAppGLFWWindow::getScreenSize(){
int count;
GLFWmonitor** monitors = glfwGetMonitors(&count);
if(count>0){
int currentMonitor = getCurrentMonitor();
const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[currentMonitor]);
if(desktopMode){
if( orientation == OF_ORIENTATION_DEFAULT || orientation == OF_ORIENTATION_180 ){
return {desktopMode->width*pixelScreenCoordScale, desktopMode->height*pixelScreenCoordScale};
}else{
return {desktopMode->height*pixelScreenCoordScale, desktopMode->width*pixelScreenCoordScale};
}
}
}
return glm::vec2();
}
int ofAppGLFWWindow::getWidth(){
if( orientation == OF_ORIENTATION_DEFAULT || orientation == OF_ORIENTATION_180 ){
return currentW * pixelScreenCoordScale;
}else{
return currentH * pixelScreenCoordScale;
}
}
int ofAppGLFWWindow::getHeight(){
if( orientation == OF_ORIENTATION_DEFAULT || orientation == OF_ORIENTATION_180 ){
return currentH * pixelScreenCoordScale;
}else{
return currentW * pixelScreenCoordScale;
}
}
GLFWwindow* ofAppGLFWWindow::getGLFWWindow(){
return windowP;
}
ofWindowMode ofAppGLFWWindow::getWindowMode(){
return settings.windowMode;
}
void ofAppGLFWWindow::setWindowPosition(int x, int y){
glfwSetWindowPos(windowP,x/pixelScreenCoordScale,y/pixelScreenCoordScale);
}
void ofAppGLFWWindow::setWindowShape(int w, int h){
if(settings.windowMode == OF_WINDOW){
windowW = w;
windowH = h;
}
currentW = w/pixelScreenCoordScale;
currentH = h/pixelScreenCoordScale;
#ifdef TARGET_OSX
auto pos = getWindowPosition();
glfwSetWindowSize(windowP,currentW,currentH);
if( pos != getWindowPosition() ){
setWindowPosition(pos.x, pos.y);
}
#else
glfwSetWindowSize(windowP,currentW,currentH);
#endif
}
void ofAppGLFWWindow::hideCursor(){
if(settings.windowMode == OF_FULLSCREEN || settings.windowMode == OF_GAME_MODE){
glfwSetInputMode(windowP,GLFW_CURSOR,GLFW_CURSOR_DISABLED);
}else{
glfwSetInputMode(windowP,GLFW_CURSOR,GLFW_CURSOR_HIDDEN);
}
};
void ofAppGLFWWindow::showCursor(){
glfwSetInputMode(windowP,GLFW_CURSOR,GLFW_CURSOR_NORMAL);
};
void ofAppGLFWWindow::enableSetupScreen(){
bEnableSetupScreen = true;
};
void ofAppGLFWWindow::disableSetupScreen(){
bEnableSetupScreen = false;
};
void ofAppGLFWWindow::setFullscreen(bool fullscreen){
if (fullscreen){
targetWindowMode = OF_FULLSCREEN;
}else{
targetWindowMode = OF_WINDOW;
}
bool bChanged = targetWindowMode != settings.windowMode;
if( !bChanged ){
return;
}
#ifdef TARGET_LINUX
#include <X11/Xatom.h>
Window nativeWin = glfwGetX11Window(windowP);
Display* display = glfwGetX11Display();
if(targetWindowMode==OF_FULLSCREEN){
#ifdef TARGET_RASPBERRY_PI
if( windowP ){
int tmpW, tmpH;
glfwGetWindowSize(windowP, &tmpW, &tmpH);
windowRect.setSize(tmpW, tmpH);
}
#endif
int monitorCount;
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
if( settings.multiMonitorFullScreen && monitorCount > 1 ){
int minx=numeric_limits<int>::max();
int miny=numeric_limits<int>::max();
int maxx=numeric_limits<int>::min();
int maxy=numeric_limits<int>::min();
int x,y,w,h;
int monitorLeft=0, monitorRight=0, monitorTop=0, monitorBottom=0;
for(int i = 0; i < monitorCount; i++){
glfwGetMonitorPos(monitors[i],&x,&y);
auto videoMode = glfwGetVideoMode(monitors[i]);
w = videoMode->width;
h = videoMode->height;
if(x<minx){
monitorLeft = i;
minx = x;
}
if(y<miny){
monitorTop = i;
miny = y;
}
if(x+w>maxx){
monitorRight = i;
maxx = x+w;
}
if(y+h>maxy){
monitorBottom = i;
maxy = y+h;
}
}
Atom m_net_fullscreen_monitors= XInternAtom(display, "_NET_WM_FULLSCREEN_MONITORS", false);
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = nativeWin;
xev.xclient.message_type = m_net_fullscreen_monitors;
xev.xclient.format = 32;
xev.xclient.data.l[0] = monitorTop;
xev.xclient.data.l[1] = monitorBottom;
xev.xclient.data.l[2] = monitorLeft;
xev.xclient.data.l[3] = monitorRight;
xev.xclient.data.l[4] = 1;
XSendEvent(display, RootWindow(display, DefaultScreen(display)),
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
currentW = maxx - minx;
currentH = maxy - minx;
}else{
auto monitor = glfwGetWindowMonitor(windowP);
if(monitor){
auto videoMode = glfwGetVideoMode(monitor);
if(videoMode){
currentW = videoMode->width;
currentH = videoMode->height;
}
}
}
}
Atom m_net_state= XInternAtom(display, "_NET_WM_STATE", false);
Atom m_net_fullscreen= XInternAtom(display, "_NET_WM_STATE_FULLSCREEN", false);
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.window = nativeWin;
xev.xclient.message_type = m_net_state;
xev.xclient.format = 32;
if (fullscreen)
xev.xclient.data.l[0] = 1;
else
xev.xclient.data.l[0] = 0;
xev.xclient.data.l[1] = m_net_fullscreen;
xev.xclient.data.l[2] = 0;
xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0;
XSendEvent(display, RootWindow(display, DefaultScreen(display)),
False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
Atom m_bypass_compositor = XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
unsigned long value = fullscreen ? 1 : 0;
XChangeProperty(display, nativeWin, m_bypass_compositor, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1);
XFlush(display);
#ifdef TARGET_RASPBERRY_PI
if( !fullscreen ){
needsResizeCheck = true;
}
#endif
#elif defined(TARGET_OSX)
if( targetWindowMode == OF_FULLSCREEN){
[NSApp setPresentationOptions:NSApplicationPresentationHideMenuBar | NSApplicationPresentationHideDock];
NSWindow * cocoaWindow = glfwGetCocoaWindow(windowP);
[cocoaWindow setStyleMask:NSBorderlessWindowMask];
int monitorCount;
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
int currentMonitor = getCurrentMonitor();
ofVec3f screenSize = getScreenSize();
if( orientation == OF_ORIENTATION_90_LEFT || orientation == OF_ORIENTATION_90_RIGHT ){
std::swap(screenSize.x, screenSize.y);
}
ofRectangle allScreensSpace;
auto pos = getWindowPosition();
auto size = getWindowSize();
windowRect.x = pos.x;
windowRect.y = pos.y;
windowRect.width = size.x;
windowRect.height = size.y;
if( settings.multiMonitorFullScreen && monitorCount > 1 ){
for(int i = 0; i < monitorCount; i++){
const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[i]);
int x, y;
glfwGetMonitorPos(monitors[i], &x, &y);
ofRectangle screen = ofRectangle( x, y, desktopMode->width, desktopMode->height );
allScreensSpace = allScreensSpace.getUnion(screen);
}
setWindowShape(allScreensSpace.width*pixelScreenCoordScale, allScreensSpace.height*pixelScreenCoordScale);
setWindowPosition(allScreensSpace.x, allScreensSpace.y);
}else if (monitorCount > 1 && currentMonitor < monitorCount){
int xpos;
int ypos;
glfwGetMonitorPos(monitors[currentMonitor], &xpos, &ypos);
xpos *= pixelScreenCoordScale;
ypos *= pixelScreenCoordScale;
setWindowPosition(xpos, ypos);
setWindowShape(screenSize.x, screenSize.y);
setWindowPosition(xpos, ypos);
}else{
setWindowShape(screenSize.x, screenSize.y);
setWindowPosition(0,0);
}
if( settings.isPositionSet() ) {
ofVec3f pos = getWindowPosition();
settings.setPosition(ofVec2f(pos.x, pos.y));
}
[cocoaWindow makeFirstResponder:cocoaWindow.contentView];
}else if( targetWindowMode == OF_WINDOW ){
if(windowRect.width == 0 && windowRect.height == 0) {
windowRect.x = getWindowPosition().x;
windowRect.y = getWindowPosition().y;
windowRect.width = getWindowSize().x;
windowRect.height = getWindowSize().y;
}
[NSApp setPresentationOptions:NSApplicationPresentationDefault];
NSWindow * cocoaWindow = glfwGetCocoaWindow(windowP);
[cocoaWindow setStyleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask];
setWindowShape(windowRect.width, windowRect.height);
setWindowTitle(settings.title);
if (ofGetFrameNum() > 0){
setWindowPosition(windowRect.x, windowRect.y);
}
[cocoaWindow makeFirstResponder:cocoaWindow.contentView];
}
#elif defined(TARGET_WIN32)
if( targetWindowMode == OF_FULLSCREEN){
auto pos = getWindowPosition();
auto size = getWindowSize();
windowRect.x = pos.x;
windowRect.y = pos.y;
windowRect.width = size.x;
windowRect.height = size.y;
HWND hwnd = glfwGetWin32Window(windowP);
SetWindowLong(hwnd, GWL_EXSTYLE, 0);
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
float fullscreenW = getScreenSize().x;
float fullscreenH = getScreenSize().y;
if( orientation == OF_ORIENTATION_90_LEFT || orientation == OF_ORIENTATION_90_RIGHT ){
std::swap(fullscreenW, fullscreenH);
}
int xpos = 0;
int ypos = 0;
if( settings.multiMonitorFullScreen ){
int minX = 0;
int maxX = 0;
int minY = 0;
int maxY = 0;
int monitorCount;
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
int tempXPos = 0;
int tempYPos = 0;
for(int i = 0; i < monitorCount; i++){
const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[i]);
glfwGetMonitorPos(monitors[i], &tempXPos, &tempYPos);
minX = min(tempXPos,minX);
minY = min(tempYPos,minY);
maxX = max(maxX,tempXPos + desktopMode->width);
maxY = max(maxY,tempYPos + desktopMode->height);
xpos = min(xpos,tempXPos);
ypos = min(ypos,tempYPos);
}
fullscreenW = maxX-minX;
fullscreenH = maxY-minY;
}else{
int monitorCount;
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount);
int currentMonitor = getCurrentMonitor();
glfwGetMonitorPos(monitors[currentMonitor], &xpos, &ypos);
}
SetWindowPos(hwnd, HWND_TOPMOST, xpos, ypos, fullscreenW, fullscreenH, SWP_SHOWWINDOW);
currentW = fullscreenW;
currentH = fullscreenH;
}else if( targetWindowMode == OF_WINDOW ){
if(windowRect.width == 0 && windowRect.height == 0) {
windowRect.x = getWindowPosition().x;
windowRect.y = getWindowPosition().y;
windowRect.width = getWindowSize().x;
windowRect.height = getWindowSize().y;
}
HWND hwnd = glfwGetWin32Window(windowP);
DWORD EX_STYLE = WS_EX_OVERLAPPEDWINDOW;
DWORD STYLE = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_SIZEBOX;
ChangeDisplaySettings(0, 0);
SetWindowLong(hwnd, GWL_EXSTYLE, EX_STYLE);
SetWindowLong(hwnd, GWL_STYLE, STYLE);
SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
setWindowPosition(windowRect.x-2, windowRect.y-2);
setWindowShape(windowRect.width+4, windowRect.height+4);
}
#endif
settings.windowMode = targetWindowMode;
}
void ofAppGLFWWindow::toggleFullscreen(){
if (settings.windowMode == OF_GAME_MODE) return;
if (settings.windowMode == OF_WINDOW){
setFullscreen(true);
} else {
setFullscreen(false);
}
}
void ofAppGLFWWindow::setOrientation(ofOrientation orientation){
this->orientation = orientation;
}
ofOrientation ofAppGLFWWindow::getOrientation(){
return orientation;
}
static void rotateMouseXY(ofOrientation orientation, int w, int h, double &x, double &y) {
int savedY;
switch(orientation) {
case OF_ORIENTATION_180:
x = w - x;
y = h - y;
break;
case OF_ORIENTATION_90_RIGHT:
savedY = y;
y = x;
x = w-savedY;
break;
case OF_ORIENTATION_90_LEFT:
savedY = y;
y = h - x;
x = savedY;
break;
case OF_ORIENTATION_DEFAULT:
default:
break;
}
}
ofAppGLFWWindow * ofAppGLFWWindow::setCurrent(GLFWwindow* windowP){
ofAppGLFWWindow * instance = static_cast<ofAppGLFWWindow *>(glfwGetWindowUserPointer(windowP));
shared_ptr<ofMainLoop> mainLoop = ofGetMainLoop();
if(mainLoop){
mainLoop->setCurrentWindow(instance);
}
instance->makeCurrent();
return instance;
}
namespace{
int glfwtToOFModifiers(int mods){
int modifiers = 0;
if(mods & GLFW_MOD_SHIFT){
modifiers |= OF_KEY_SHIFT;
}
if(mods & GLFW_MOD_ALT){
modifiers |= OF_KEY_ALT;
}
if(mods & GLFW_MOD_CONTROL){
modifiers |= OF_KEY_CONTROL;
}
if(mods & GLFW_MOD_SUPER){
modifiers |= OF_KEY_SUPER;
}
return modifiers;
}
unsigned long keycodeToUnicode(ofAppGLFWWindow * window, int scancode, int modifier){
#ifdef TARGET_LINUX
XkbStateRec xkb_state = {};
XkbGetState(window->getX11Display(), XkbUseCoreKbd, &xkb_state);
XEvent ev = {0};
ev.xkey.keycode = scancode;
ev.xkey.state = xkb_state.mods & ~ControlMask;
ev.xkey.display = window->getX11Display();
ev.xkey.type = KeyPress;
KeySym keysym = NoSymbol;
int status;
char buffer[32] = {0};
char* chars = buffer;
auto count = Xutf8LookupString(window->getX11XIC(), &ev.xkey, chars, sizeof(buffer) - 1, &keysym, &status);
if ((count > 0 && (status == XLookupChars || status == XLookupBoth)) || status == XLookupKeySym){
char ** c = &chars;
unsigned int ch = 0, count = 0;
static const unsigned int offsets[] =
{
0x00000000u, 0x00003080u, 0x000e2080u,
0x03c82080u, 0xfa082080u, 0x82082080u
};
do
{
ch = (ch << 6) + (unsigned char) **c;
(*c)++;
count++;
} while ((**c & 0xc0) == 0x80);
if(count>6){
return 0;
}else{
return ch - offsets[count - 1];
}
}else{
return 0;
}
#endif
#ifdef TARGET_WIN32
static WCHAR buf[2];
static BYTE keyboardState[256];
GetKeyboardState( keyboardState );
UINT fakeVirtualKey = MapVirtualKey( scancode, MAPVK_VSC_TO_VK_EX );
int ret = ToUnicode( fakeVirtualKey, scancode, keyboardState, buf , 2, 0);
if ( ret == 1 ){
return buf[0];
} else {
return 0;
}
#endif
#ifdef TARGET_OSX
static UInt32 deadKeyState = 0;
static UniChar characters[8];
static UniCharCount characterCount = 0;
typedef struct __TISInputSource* TISInputSourceRef;
typedef TISInputSourceRef (*pFnGetInputSource)(void);
typedef void* (*pFnGetInputSourceProperty)(TISInputSourceRef,CFStringRef);
typedef UInt8 (*pFnGetKeyboardType)(void);
static const CFBundleRef tisBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
static pFnGetInputSource getInputSource = (pFnGetInputSource)CFBundleGetFunctionPointerForName(tisBundle, CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
static pFnGetKeyboardType getKeyboardType = (pFnGetKeyboardType)CFBundleGetFunctionPointerForName(tisBundle,CFSTR("LMGetKbdType"));
static pFnGetInputSourceProperty getInputSourceProperty = (pFnGetInputSourceProperty)CFBundleGetFunctionPointerForName(tisBundle, CFSTR("TISGetInputSourceProperty"));
static const TISInputSourceRef sourceRef = getInputSource();
static const CFStringRef* kPropertyUnicodeKeyLayoutData = (CFStringRef*)CFBundleGetDataPointerForName(tisBundle, CFSTR("kTISPropertyUnicodeKeyLayoutData"));
static const CFStringRef kTISPropertyUnicodeKeyLayoutData = * kPropertyUnicodeKeyLayoutData;
static const CFDataRef UnicodeKeyLayoutData = (CFDataRef)getInputSourceProperty(sourceRef, kTISPropertyUnicodeKeyLayoutData);
static const UCKeyboardLayout* pKeyboardLayout = (UCKeyboardLayout*)CFDataGetBytePtr(UnicodeKeyLayoutData);
UInt32 mod_OSX = 0;
{
if (modifier & GLFW_MOD_SHIFT)
mod_OSX |= 512;
if (modifier & GLFW_MOD_CONTROL)
mod_OSX |= 4096;
if (modifier & GLFW_MOD_ALT)
mod_OSX |= 2048;
if (modifier & GLFW_MOD_SUPER)
mod_OSX |= 256;
mod_OSX = (mod_OSX >> 8) & 0xFF;
}
if (noErr == UCKeyTranslate(pKeyboardLayout,
scancode,
kUCKeyActionDisplay,
mod_OSX,
getKeyboardType(),
kUCKeyTranslateNoDeadKeysBit,
&deadKeyState,
sizeof(characters) / sizeof(characters[0]),
&characterCount,
characters))
{
return characters[0];
} else {
return 0;
}
#endif
return 0;
}
}
void ofAppGLFWWindow::mouse_cb(GLFWwindow* windowP_, int button, int state, int mods) {
ofAppGLFWWindow * instance = setCurrent(windowP_);
#ifdef TARGET_OSX
if( instance->events().getKeyPressed(OF_KEY_CONTROL) && button == GLFW_MOUSE_BUTTON_LEFT){
button = GLFW_MOUSE_BUTTON_RIGHT;
}
if( instance->events().getKeyPressed(OF_KEY_ALT) && button == GLFW_MOUSE_BUTTON_LEFT){
button = GLFW_MOUSE_BUTTON_MIDDLE;
}
#endif
switch(button){
case GLFW_MOUSE_BUTTON_LEFT:
button = OF_MOUSE_BUTTON_LEFT;
break;
case GLFW_MOUSE_BUTTON_RIGHT:
button = OF_MOUSE_BUTTON_RIGHT;
break;
case GLFW_MOUSE_BUTTON_MIDDLE:
button = OF_MOUSE_BUTTON_MIDDLE;
break;
}
instance->buttonInUse = button;
ofMouseEventArgs::Type action;
if (state == GLFW_PRESS) {
action = ofMouseEventArgs::Pressed;
instance->buttonPressed=true;
} else {
action = ofMouseEventArgs::Released;
instance->buttonPressed=false;
}
int modifiers = glfwtToOFModifiers(mods);
ofMouseEventArgs args(action, instance->events().getMouseX(), instance->events().getMouseY(), button, modifiers);
instance->events().notifyMouseEvent(args);
}
void ofAppGLFWWindow::motion_cb(GLFWwindow* windowP_, double x, double y) {
ofAppGLFWWindow * instance = setCurrent(windowP_);
rotateMouseXY(instance->orientation, instance->getWidth(), instance->getHeight(), x, y);
ofMouseEventArgs::Type action;
if(!instance->buttonPressed){
action = ofMouseEventArgs::Moved;
}else{
action = ofMouseEventArgs::Dragged;
}
ofMouseEventArgs args(action,
x*instance->pixelScreenCoordScale,
y*instance->pixelScreenCoordScale,
instance->buttonInUse,
instance->events().getModifiers());
instance->events().notifyMouseEvent(args);
}
void ofAppGLFWWindow::entry_cb(GLFWwindow *windowP_, int entered) {
ofAppGLFWWindow * instance = setCurrent(windowP_);
ofMouseEventArgs::Type action;
if(entered){
action = ofMouseEventArgs::Entered;
}else{
action = ofMouseEventArgs::Exited;
}
ofMouseEventArgs args(action,
instance->events().getMouseX(),
instance->events().getMouseY(),
instance->buttonInUse,
instance->events().getModifiers());
instance->events().notifyMouseEvent(args);
}
void ofAppGLFWWindow::scroll_cb(GLFWwindow* windowP_, double x, double y) {
ofAppGLFWWindow * instance = setCurrent(windowP_);
rotateMouseXY(instance->orientation, instance->getWidth(), instance->getHeight(), x, y);
ofMouseEventArgs args(ofMouseEventArgs::Scrolled,
instance->events().getMouseX(),
instance->events().getMouseY(),
instance->buttonInUse,
instance->events().getModifiers());
args.scrollX = x;
args.scrollY = y;
instance->events().notifyMouseEvent(args);
}
void ofAppGLFWWindow::drop_cb(GLFWwindow* windowP_, int numFiles, const char** dropString) {
ofAppGLFWWindow * instance = setCurrent(windowP_);
ofDragInfo drag;
drag.position = {instance->events().getMouseX(), instance->events().getMouseY()};
drag.files.resize(numFiles);
for(int i=0; i<(int)drag.files.size(); i++){
drag.files[i] = std::filesystem::path(dropString[i]).string();
}
instance->events().notifyDragEvent(drag);
}
void ofAppGLFWWindow::error_cb(int errorCode, const char* errorDescription){
ofLogError("ofAppGLFWWindow") << errorCode << ": " << errorDescription;
}
void ofAppGLFWWindow::keyboard_cb(GLFWwindow* windowP_, int keycode, int scancode, int action, int mods) {
int key = 0;
uint32_t codepoint = 0;
ofAppGLFWWindow * instance = setCurrent(windowP_);
switch (keycode) {
case GLFW_KEY_ESCAPE:
key = OF_KEY_ESC;
break;
case GLFW_KEY_F1:
key = OF_KEY_F1;
break;
case GLFW_KEY_F2:
key = OF_KEY_F2;
break;
case GLFW_KEY_F3:
key = OF_KEY_F3;
break;
case GLFW_KEY_F4:
key = OF_KEY_F4;
break;
case GLFW_KEY_F5:
key = OF_KEY_F5;
break;
case GLFW_KEY_F6:
key = OF_KEY_F6;
break;
case GLFW_KEY_F7:
key = OF_KEY_F7;
break;
case GLFW_KEY_F8:
key = OF_KEY_F8;
break;
case GLFW_KEY_F9:
key = OF_KEY_F9;
break;
case GLFW_KEY_F10:
key = OF_KEY_F10;
break;
case GLFW_KEY_F11:
key = OF_KEY_F11;
break;
case GLFW_KEY_F12:
key = OF_KEY_F12;
break;
case GLFW_KEY_LEFT:
key = OF_KEY_LEFT;
break;
case GLFW_KEY_RIGHT:
key = OF_KEY_RIGHT;
break;
case GLFW_KEY_UP:
key = OF_KEY_UP;
break;
case GLFW_KEY_DOWN:
key = OF_KEY_DOWN;
break;
case GLFW_KEY_PAGE_UP:
key = OF_KEY_PAGE_UP;
break;
case GLFW_KEY_PAGE_DOWN:
key = OF_KEY_PAGE_DOWN;
break;
case GLFW_KEY_HOME:
key = OF_KEY_HOME;
break;
case GLFW_KEY_END:
key = OF_KEY_END;
break;
case GLFW_KEY_INSERT:
key = OF_KEY_INSERT;
break;
case GLFW_KEY_LEFT_SHIFT:
key = OF_KEY_LEFT_SHIFT;
break;
case GLFW_KEY_LEFT_CONTROL:
key = OF_KEY_LEFT_CONTROL;
break;
case GLFW_KEY_LEFT_ALT:
key = OF_KEY_LEFT_ALT;
break;
case GLFW_KEY_LEFT_SUPER:
key = OF_KEY_LEFT_SUPER;
break;
case GLFW_KEY_RIGHT_SHIFT:
key = OF_KEY_RIGHT_SHIFT;
break;
case GLFW_KEY_RIGHT_CONTROL:
key = OF_KEY_RIGHT_CONTROL;
break;
case GLFW_KEY_RIGHT_ALT:
key = OF_KEY_RIGHT_ALT;
break;
case GLFW_KEY_RIGHT_SUPER:
key = OF_KEY_RIGHT_SUPER;
break;
case GLFW_KEY_BACKSPACE:
key = OF_KEY_BACKSPACE;
break;
case GLFW_KEY_DELETE:
key = OF_KEY_DEL;
break;
case GLFW_KEY_ENTER:
key = OF_KEY_RETURN;
codepoint = '\n';
break;
case GLFW_KEY_KP_ENTER:
key = OF_KEY_RETURN;
codepoint = '\n';
break;
case GLFW_KEY_TAB:
key = OF_KEY_TAB;
codepoint = '\t';
break;
case GLFW_KEY_KP_0:
key = codepoint = '0';
break;
case GLFW_KEY_KP_1:
key = codepoint = '1';
break;
case GLFW_KEY_KP_2:
key = codepoint = '2';
break;
case GLFW_KEY_KP_3:
key = codepoint = '3';
break;
case GLFW_KEY_KP_4:
key = codepoint = '4';
break;
case GLFW_KEY_KP_5:
key = codepoint = '5';
break;
case GLFW_KEY_KP_6:
key = codepoint = '6';
break;
case GLFW_KEY_KP_7:
key = codepoint = '7';
break;
case GLFW_KEY_KP_8:
key = codepoint = '8';
break;
case GLFW_KEY_KP_9:
key = codepoint = '9';
break;
case GLFW_KEY_KP_DIVIDE:
key = codepoint = '/';
break;
case GLFW_KEY_KP_MULTIPLY:
key = codepoint = '*';
break;
case GLFW_KEY_KP_SUBTRACT:
key = codepoint = '-';
break;
case GLFW_KEY_KP_ADD:
key = codepoint = '+';
break;
case GLFW_KEY_KP_DECIMAL:
key = codepoint = '.';
break;
case GLFW_KEY_KP_EQUAL:
key = codepoint = '=';
break;
default:
codepoint = keycodeToUnicode(instance, scancode, mods);
key = codepoint;
break;
}
int modifiers = glfwtToOFModifiers(mods);
if(action == GLFW_PRESS){
ofKeyEventArgs keyE(ofKeyEventArgs::Pressed,key,keycode,scancode,codepoint,modifiers);
instance->events().notifyKeyEvent(keyE);
}else if(action == GLFW_REPEAT){
ofKeyEventArgs keyE(ofKeyEventArgs::Pressed,key,keycode,scancode,codepoint,modifiers);
keyE.isRepeat = true;
instance->events().notifyKeyEvent(keyE);
}else if (action == GLFW_RELEASE){
ofKeyEventArgs keyE(ofKeyEventArgs::Released,key,keycode,scancode,codepoint,modifiers);
instance->events().notifyKeyEvent(keyE);
}
}
void ofAppGLFWWindow::char_cb(GLFWwindow* windowP_, uint32_t key){
ofAppGLFWWindow * instance = setCurrent(windowP_);
instance->events().charEvent.notify(key);
}
void ofAppGLFWWindow::resize_cb(GLFWwindow* windowP_, int w, int h) {
ofAppGLFWWindow * instance = setCurrent(windowP_);
int framebufferW, framebufferH;
glfwGetFramebufferSize(windowP_, &framebufferW, &framebufferH);
int windowW, windowH;
glfwGetWindowSize(windowP_, &windowW, &windowH);
instance->pixelScreenCoordScale = (float)framebufferW / (float)windowW;
if(instance->settings.windowMode == OF_WINDOW){
instance->windowW = framebufferW;
instance->windowH = framebufferH;
}
instance->currentW = windowW;
instance->currentH = windowH;
instance->events().notifyWindowResized(framebufferW, framebufferH);
instance->nFramesSinceWindowResized = 0;
}
void ofAppGLFWWindow::framebuffer_size_cb(GLFWwindow* windowP_, int w, int h){
resize_cb(windowP_, w, h);
}
void ofAppGLFWWindow::exit_cb(GLFWwindow* windowP_){
ofAppGLFWWindow * instance = setCurrent(windowP_);
instance->events().notifyExit();
}
void ofAppGLFWWindow::setVerticalSync(bool bVerticalSync){
if(bVerticalSync){
glfwSwapInterval( 1);
}else{
glfwSwapInterval(0);
}
}
void ofAppGLFWWindow::setClipboardString(const string& text) {
glfwSetClipboardString(ofAppGLFWWindow::windowP, text.c_str());
}
string ofAppGLFWWindow::getClipboardString() {
const char* clipboard = glfwGetClipboardString(ofAppGLFWWindow::windowP);
if (clipboard) {
return clipboard;
} else {
return "";
}
}
void ofAppGLFWWindow::listVideoModes(){
glfwInit();
int numModes;
const GLFWvidmode * vidModes = glfwGetVideoModes(nullptr, &numModes );
for(int i=0; i<numModes; i++){
ofLogNotice() << vidModes[i].width << " x " << vidModes[i].height
<< vidModes[i].redBits+vidModes[i].greenBits+vidModes[i].blueBits << "bit";
}
}
void ofAppGLFWWindow::listMonitors(){
glfwInit();
int count;
const auto monitors = glfwGetMonitors(&count);
for(int i = 0; i<count; i++){
auto monitor = monitors[i];
int w,h,x,y;
glfwGetMonitorPhysicalSize(monitor,&w,&h);
glfwGetMonitorPos(monitor,&x,&y);
ofLogNotice() << i << ": " << glfwGetMonitorName(monitor) << ", physical size: " << w << "x" << h << "mm at " << x << ", " << y;
}
}
bool ofAppGLFWWindow::isWindowIconified(){
return glfwGetWindowAttrib(windowP, GLFW_ICONIFIED);
}
bool ofAppGLFWWindow::isWindowActive(){
return true;
}
bool ofAppGLFWWindow::isWindowResizeable(){
return !glfwGetWindowAttrib(windowP, GLFW_RESIZABLE);
}
void ofAppGLFWWindow::iconify(bool bIconify){
if(bIconify)
glfwIconifyWindow(windowP);
else
glfwRestoreWindow(windowP);
}
void ofAppGLFWWindow::makeCurrent(){
glfwMakeContextCurrent(windowP);
}
#if defined(TARGET_LINUX)
Display* ofAppGLFWWindow::getX11Display(){
return glfwGetX11Display();
}
Window ofAppGLFWWindow::getX11Window(){
return glfwGetX11Window(windowP);
}
XIC ofAppGLFWWindow::getX11XIC(){
return xic;
}
#endif
#if defined(TARGET_LINUX) && !defined(TARGET_OPENGLES)
GLXContext ofAppGLFWWindow::getGLXContext(){
return glfwGetGLXContext(windowP);
}
#endif
#if defined(TARGET_LINUX) && defined(TARGET_OPENGLES)
EGLDisplay ofAppGLFWWindow::getEGLDisplay(){
return glfwGetEGLDisplay();
}
EGLContext ofAppGLFWWindow::getEGLContext(){
return glfwGetEGLContext(windowP);
}
EGLSurface ofAppGLFWWindow::getEGLSurface(){
return glfwGetEGLSurface(windowP);
}
#endif
#if defined(TARGET_OSX)
void * ofAppGLFWWindow::getNSGLContext(){
return glfwGetNSGLContext(windowP);
}
void * ofAppGLFWWindow::getCocoaWindow(){
return glfwGetCocoaWindow(windowP);
}
#endif
#if defined(TARGET_WIN32)
HGLRC ofAppGLFWWindow::getWGLContext(){
return glfwGetWGLContext(windowP);
}
HWND ofAppGLFWWindow::getWin32Window(){
return glfwGetWin32Window(windowP);
}
#endif
Comments