Created
August 7, 2013 15:06
-
-
Save ofTheo/6174869 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void ofAppGLFWWindow::setFullscreen(bool fullscreen){ | |
int curWindowMode = windowMode; | |
if (fullscreen){ | |
windowMode = OF_FULLSCREEN; | |
}else{ | |
windowMode = OF_WINDOW; | |
} | |
//we only want to change window mode if the requested window is different to the current one. | |
bool bChanged = windowMode != curWindowMode; | |
if( !bChanged ){ | |
return; | |
} | |
#ifdef TARGET_LINUX | |
#include <X11/Xatom.h> | |
Window nativeWin = glfwGetX11Window(windowP); | |
Display* display = glfwGetX11Display(); | |
int monitorCount; | |
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount); | |
if( bMultiWindowFullscreen && monitorCount > 1 ){ | |
// find the monitors at the edges of the virtual desktop | |
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); | |
glfwGetMonitorPhysicalSize(monitors[i],&w,&h); | |
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; | |
} | |
} | |
// send fullscreen_monitors event with the edges monitors | |
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); | |
} | |
// send fullscreen event | |
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); | |
// tell the window manager to bypass composition for this window in fullscreen for speed | |
// it'll probably help solving vsync issues | |
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); | |
#elif defined(TARGET_OSX) | |
if( windowMode == OF_FULLSCREEN){ | |
nonFullScreenX = getWindowPosition().x; | |
nonFullScreenY = getWindowPosition().y; | |
nonFullScreenW = getWindowSize().x; | |
nonFullScreenH = getWindowSize().y; | |
//---------------------------------------------------- | |
SetSystemUIMode(kUIModeAllHidden,NULL); | |
NSWindow * cocoaWindow = glfwGetCocoaWindow(windowP); | |
[cocoaWindow setStyleMask:NSBorderlessWindowMask]; | |
int monitorCount; | |
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount); | |
int currentMonitor = getCurrentMonitor(); | |
ofVec3f screenSize = getScreenSize(); | |
ofRectangle allScreensSpace; | |
if( bMultiWindowFullscreen && monitorCount > 1 ){ | |
//calc the sum Rect of all the monitors | |
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); | |
} | |
//for OS X we need to set this first as the window size affects the window positon | |
setWindowShape(allScreensSpace.width, allScreensSpace.height); | |
setWindowPosition(allScreensSpace.x, allScreensSpace.y); | |
}else if (monitorCount > 1 && currentMonitor < monitorCount){ | |
int xpos; | |
int ypos; | |
glfwGetMonitorPos(monitors[currentMonitor], &xpos, &ypos); | |
//we do this as setWindowShape affects the position of the monitor | |
//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. | |
//this first moves it over in X, does the screen resize and then by calling it again its set correctly in y. | |
setWindowPosition(xpos, ypos); | |
setWindowShape(screenSize.x, screenSize.y); | |
setWindowPosition(xpos, ypos); | |
}else{ | |
//for OS X we need to set this first as the window size affects the window positon | |
setWindowShape(screenSize.x, screenSize.y); | |
setWindowPosition(0,0); | |
} | |
//make sure the window is getting the mouse/key events | |
[cocoaWindow makeFirstResponder:cocoaWindow.contentView]; | |
}else if( windowMode == OF_WINDOW ){ | |
SetSystemUIMode(kUIModeNormal,NULL); | |
NSWindow * cocoaWindow = glfwGetCocoaWindow(windowP); | |
[cocoaWindow setStyleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask]; | |
setWindowShape(nonFullScreenW, nonFullScreenH); | |
//---------------------------------------------------- | |
// if we have recorded the screen posion, put it there | |
// if not, better to let the system do it (and put it where it wants) | |
if (ofGetFrameNum() > 0){ | |
setWindowPosition(nonFullScreenX,nonFullScreenY); | |
} | |
//---------------------------------------------------- | |
//make sure the window is getting the mouse/key events | |
[cocoaWindow makeFirstResponder:cocoaWindow.contentView]; | |
} | |
#elif defined(TARGET_WIN32) | |
if( windowMode == OF_FULLSCREEN){ | |
nonFullScreenX = getWindowPosition().x; | |
nonFullScreenY = getWindowPosition().y; | |
nonFullScreenW = getWindowSize().x; | |
nonFullScreenH = getWindowSize().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; | |
int xpos = 0; | |
int ypos = 0; | |
if( bMultiWindowFullscreen ){ | |
float totalWidth = 0.0; | |
float maxHeight = 0.0; | |
int monitorCount; | |
GLFWmonitor** monitors = glfwGetMonitors(&monitorCount); | |
//lets find the total width of all the monitors | |
//and we'll make the window height the height of the largest monitor. | |
for(int i = 0; i < monitorCount; i++){ | |
const GLFWvidmode * desktopMode = glfwGetVideoMode(monitors[i]); | |
totalWidth += desktopMode->width; | |
if( i == 0 || desktopMode->height > maxHeight ){ | |
maxHeight = desktopMode->height; | |
} | |
} | |
fullscreenW = totalWidth; | |
fullscreenH = maxHeight; | |
}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); | |
}else if( windowMode == OF_WINDOW ){ | |
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; | |
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); | |
//not sure why this is - but if we don't do this the window shrinks by 4 pixels in x and y | |
//should look for a better fix. | |
setWindowPosition(nonFullScreenX-2, nonFullScreenY-2); | |
setWindowShape(nonFullScreenW+4, nonFullScreenH+4); | |
} | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment