Skip to content

Instantly share code, notes, and snippets.

@ofTheo
Created August 7, 2013 15:06
Show Gist options
  • Save ofTheo/6174869 to your computer and use it in GitHub Desktop.
Save ofTheo/6174869 to your computer and use it in GitHub Desktop.
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