void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) { if (!window->resizable) { // Update window size restrictions to match new window size XSizeHints* hints = XAllocSizeHints(); hints->flags |= (PMinSize | PMaxSize); hints->min_width = hints->max_width = width; hints->min_height = hints->max_height = height; XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints); XFree(hints); } if (window->monitor) { if (window->x11.overrideRedirect) { GLFWvidmode mode; _glfwPlatformGetVideoMode(window->monitor, &mode); XResizeWindow(_glfw.x11.display, window->x11.handle, window->videoMode.width, window->videoMode.height); } _glfwSetVideoMode(window->monitor, &window->videoMode); } else XResizeWindow(_glfw.x11.display, window->x11.handle, width, height); }
int _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* mode) { GLFWvidmode current; const GLFWvidmode* best; DEVMODE dm; best = _glfwChooseVideoMode(monitor, mode); _glfwPlatformGetVideoMode(monitor, ¤t); if (_glfwCompareVideoModes(¤t, best) == 0) return GL_TRUE; dm.dmSize = sizeof(DEVMODE); dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; dm.dmPelsWidth = best->width; dm.dmPelsHeight = best->height; dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits; if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24) dm.dmBitsPerPel = 32; if (ChangeDisplaySettingsEx(monitor->win32.name, &dm, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL) { _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode"); return GL_FALSE; } return GL_TRUE; }
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) { GLFWvidmode* result; *found = 0; // Build array of available resolutions if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { int i, j; XRRScreenResources* sr; XRROutputInfo* oi; sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output); result = calloc(oi->nmode, sizeof(GLFWvidmode)); for (i = 0; i < oi->nmode; i++) { const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]); if (!modeIsGood(mi)) continue; const GLFWvidmode mode = vidmodeFromModeInfo(mi); for (j = 0; j < *found; j++) { if (result[j].width == mode.width && result[j].height == mode.height && result[j].refreshRate == mode.refreshRate) { break; } } if (j < *found) { // This is a duplicate, so skip it continue; } result[*found] = mode; (*found)++; } XRRFreeOutputInfo(oi); XRRFreeScreenResources(sr); } else { *found = 1; result = calloc(1, sizeof(GLFWvidmode)); _glfwPlatformGetVideoMode(monitor, result); } return result; }
// Change the current video mode // GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired) { GLFWvidmode current; const GLFWvidmode* best; DEVMODEW dm; LONG result; best = _glfwChooseVideoMode(monitor, desired); _glfwPlatformGetVideoMode(monitor, ¤t); if (_glfwCompareVideoModes(¤t, best) == 0) return GLFW_TRUE; ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(dm); dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; dm.dmPelsWidth = best->width; dm.dmPelsHeight = best->height; dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits; dm.dmDisplayFrequency = best->refreshRate; if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24) dm.dmBitsPerPel = 32; result = ChangeDisplaySettingsExW(monitor->win32.adapterName, &dm, NULL, CDS_FULLSCREEN, NULL); if (result != DISP_CHANGE_SUCCESSFUL) { const char* description = "Unknown error"; if (result == DISP_CHANGE_BADDUALVIEW) description = "The system uses DualView"; else if (result == DISP_CHANGE_BADFLAGS) description = "Invalid flags"; else if (result == DISP_CHANGE_BADMODE) description = "Graphics mode not supported"; else if (result == DISP_CHANGE_BADPARAM) description = "Invalid parameter"; else if (result == DISP_CHANGE_FAILED) description = "Graphics mode failed"; else if (result == DISP_CHANGE_NOTUPDATED) description = "Failed to write to registry"; else if (result == DISP_CHANGE_RESTART) description = "Computer restart required"; _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode: %s", description); return GLFW_FALSE; } monitor->win32.modeChanged = GLFW_TRUE; return GLFW_TRUE; }
GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _glfwPlatformGetVideoMode(monitor, &monitor->currentMode); return &monitor->currentMode; }
// Set the current video mode for the specified monitor // void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired) { if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { XRRScreenResources* sr; XRRCrtcInfo* ci; XRROutputInfo* oi; GLFWvidmode current; const GLFWvidmode* best; RRMode native = None; int i; best = _glfwChooseVideoMode(monitor, desired); _glfwPlatformGetVideoMode(monitor, ¤t); if (_glfwCompareVideoModes(¤t, best) == 0) return; sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output); for (i = 0; i < oi->nmode; i++) { const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]); if (!modeIsGood(mi)) continue; const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci); if (_glfwCompareVideoModes(best, &mode) == 0) { native = mi->id; break; } } if (native) { if (monitor->x11.oldMode == None) monitor->x11.oldMode = ci->mode; XRRSetCrtcConfig(_glfw.x11.display, sr, monitor->x11.crtc, CurrentTime, ci->x, ci->y, native, ci->rotation, ci->outputs, ci->noutput); } XRRFreeOutputInfo(oi); XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); } }
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { GLFWvidmode* result; *count = 0; if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) { int i, j; XRRScreenResources* sr; XRRCrtcInfo* ci; XRROutputInfo* oi; sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output); result = calloc(oi->nmode, sizeof(GLFWvidmode)); for (i = 0; i < oi->nmode; i++) { const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]); if (!modeIsGood(mi)) continue; const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci); for (j = 0; j < *count; j++) { if (_glfwCompareVideoModes(result + j, &mode) == 0) break; } // Skip duplicate modes if (j < *count) continue; (*count)++; result[*count - 1] = mode; } XRRFreeOutputInfo(oi); XRRFreeCrtcInfo(ci); XRRFreeScreenResources(sr); } else { *count = 1; result = calloc(1, sizeof(GLFWvidmode)); _glfwPlatformGetVideoMode(monitor, result); } return result; }
GLFWAPI GLFWvidmode glfwGetVideoMode(GLFWmonitor* handle) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle; GLFWvidmode mode = { 0, 0, 0, 0, 0 }; if (!_glfwInitialized) { _glfwInputError(GLFW_NOT_INITIALIZED, NULL); return mode; } _glfwPlatformGetVideoMode(monitor, &mode); return mode; }
// Enter full screen mode // static GLboolean enterFullscreenMode(_GLFWwindow* window) { GLFWvidmode mode; GLboolean status; int xpos, ypos; status = _glfwSetVideoMode(window->monitor, &window->videoMode); _glfwPlatformGetVideoMode(window->monitor, &mode); _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos); SetWindowPos(window->win32.handle, HWND_TOPMOST, xpos, ypos, mode.width, mode.height, SWP_NOCOPYBITS); return status; }
// Make the specified window and its video mode active on its monitor // static GLFWbool acquireMonitor(_GLFWwindow* window) { GLFWvidmode mode; GLFWbool status; int xpos, ypos; status = _glfwSetVideoModeWin32(window->monitor, &window->videoMode); _glfwPlatformGetVideoMode(window->monitor, &mode); _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos); SetWindowPos(window->win32.handle, HWND_TOPMOST, xpos, ypos, mode.width, mode.height, SWP_NOACTIVATE | SWP_NOCOPYBITS); _glfwInputMonitorWindowChange(window->monitor, window); return status; }
int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { if (window->monitor) { GLFWvidmode mode; _glfwPlatformGetVideoMode(window->monitor, &mode); mir_surface_set_state(window->mir.surface, mir_surface_state_fullscreen); if (wndconfig->width > mode.width || wndconfig->height > mode.height) { _glfwInputError(GLFW_PLATFORM_ERROR, "Mir: Requested surface size too large: %ix%i", wndconfig->width, wndconfig->height); return GLFW_FALSE; } } window->mir.width = wndconfig->width; window->mir.height = wndconfig->height; window->mir.currentCursor = NULL; if (!createSurface(window)) return GLFW_FALSE; window->mir.window = mir_buffer_stream_get_egl_native_window( mir_surface_get_buffer_stream(window->mir.surface)); if (ctxconfig->client != GLFW_NO_API) { if (!_glfwInitEGL()) return GLFW_FALSE; if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) return GLFW_FALSE; } return GLFW_TRUE; }
// Change the current video mode // GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired) { GLFWvidmode current; const GLFWvidmode* best; DEVMODEW dm; best = _glfwChooseVideoMode(monitor, desired); _glfwPlatformGetVideoMode(monitor, ¤t); if (_glfwCompareVideoModes(¤t, best) == 0) return GLFW_TRUE; ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(DEVMODEW); dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; dm.dmPelsWidth = best->width; dm.dmPelsHeight = best->height; dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits; dm.dmDisplayFrequency = best->refreshRate; if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24) dm.dmBitsPerPel = 32; if (ChangeDisplaySettingsExW(monitor->win32.adapterName, &dm, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL) { _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode"); return GLFW_FALSE; } monitor->win32.modeChanged = GLFW_TRUE; return GLFW_TRUE; }
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate) { if (window->monitor == monitor) { if (monitor) { if (monitor->window == window) acquireMonitor(window); } else { RECT rect = { xpos, ypos, xpos + width, ypos + height }; AdjustWindowRectEx(&rect, getWindowStyle(window), FALSE, getWindowExStyle(window)); SetWindowPos(window->win32.handle, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER); } return; } if (window->monitor) releaseMonitor(window); _glfwInputWindowMonitorChange(window, monitor); if (monitor) { GLFWvidmode mode; DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE); UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS; if (window->decorated) { style &= ~WS_OVERLAPPEDWINDOW; style |= getWindowStyle(window); SetWindowLongW(window->win32.handle, GWL_STYLE, style); flags |= SWP_FRAMECHANGED; } _glfwPlatformGetVideoMode(monitor, &mode); _glfwPlatformGetMonitorPos(monitor, &xpos, &ypos); SetWindowPos(window->win32.handle, HWND_TOPMOST, xpos, ypos, mode.width, mode.height, flags); acquireMonitor(window); } else { HWND after; RECT rect = { xpos, ypos, xpos + width, ypos + height }; DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE); UINT flags = SWP_NOACTIVATE | SWP_NOCOPYBITS; if (window->decorated) { style &= ~WS_POPUP; style |= getWindowStyle(window); SetWindowLongW(window->win32.handle, GWL_STYLE, style); flags |= SWP_FRAMECHANGED; } if (window->floating) after = HWND_TOPMOST; else after = HWND_NOTOPMOST; AdjustWindowRectEx(&rect, getWindowStyle(window), FALSE, getWindowExStyle(window)); SetWindowPos(window->win32.handle, after, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, flags); } }
// Enter fullscreen mode // static void enterFullscreenMode(_GLFWwindow* window) { if (!_glfw.x11.saver.changed) { // Remember old screen saver settings XGetScreenSaver(_glfw.x11.display, &_glfw.x11.saver.timeout, &_glfw.x11.saver.interval, &_glfw.x11.saver.blanking, &_glfw.x11.saver.exposure); // Disable screen saver XSetScreenSaver(_glfw.x11.display, 0, 0, DontPreferBlanking, DefaultExposures); _glfw.x11.saver.changed = GL_TRUE; } _glfwSetVideoMode(window->monitor, &window->videoMode); if (_glfw.x11.hasEWMH && _glfw.x11.NET_WM_STATE != None && _glfw.x11.NET_WM_STATE_FULLSCREEN != None) { if (_glfw.x11.NET_ACTIVE_WINDOW != None) { // Ask the window manager to raise and focus the GLFW window // Only focused windows with the _NET_WM_STATE_FULLSCREEN state end // up on top of all other windows ("Stacking order" in EWMH spec) XEvent event; memset(&event, 0, sizeof(event)); event.type = ClientMessage; event.xclient.window = window->x11.handle; event.xclient.format = 32; // Data is 32-bit longs event.xclient.message_type = _glfw.x11.NET_ACTIVE_WINDOW; event.xclient.data.l[0] = 1; // Sender is a normal application event.xclient.data.l[1] = 0; // We don't really know the timestamp XSendEvent(_glfw.x11.display, _glfw.x11.root, False, SubstructureNotifyMask | SubstructureRedirectMask, &event); } // Ask the window manager to make the GLFW window a fullscreen window // Fullscreen windows are undecorated and, when focused, are kept // on top of all other windows XEvent event; memset(&event, 0, sizeof(event)); event.type = ClientMessage; event.xclient.window = window->x11.handle; event.xclient.format = 32; // Data is 32-bit longs event.xclient.message_type = _glfw.x11.NET_WM_STATE; event.xclient.data.l[0] = _NET_WM_STATE_ADD; event.xclient.data.l[1] = _glfw.x11.NET_WM_STATE_FULLSCREEN; event.xclient.data.l[2] = 0; // No secondary property event.xclient.data.l[3] = 1; // Sender is a normal application XSendEvent(_glfw.x11.display, _glfw.x11.root, False, SubstructureNotifyMask | SubstructureRedirectMask, &event); } else if (window->x11.overrideRedirect) { // In override-redirect mode we have divorced ourselves from the // window manager, so we need to do everything manually GLFWvidmode mode; _glfwPlatformGetVideoMode(window->monitor, &mode); XRaiseWindow(_glfw.x11.display, window->x11.handle); XSetInputFocus(_glfw.x11.display, window->x11.handle, RevertToParent, CurrentTime); XMoveWindow(_glfw.x11.display, window->x11.handle, 0, 0); XResizeWindow(_glfw.x11.display, window->x11.handle, mode.width, mode.height); } }
// Creates the GLFW window and rendering context // static GLFWbool createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { int xpos, ypos, fullWidth, fullHeight; WCHAR* wideTitle; if (wndconfig->monitor) { GLFWvidmode mode; // NOTE: This window placement is temporary and approximate, as the // correct position and size cannot be known until the monitor // video mode has been set _glfwPlatformGetMonitorPos(wndconfig->monitor, &xpos, &ypos); _glfwPlatformGetVideoMode(wndconfig->monitor, &mode); fullWidth = mode.width; fullHeight = mode.height; } else { xpos = CW_USEDEFAULT; ypos = CW_USEDEFAULT; getFullWindowSize(getWindowStyle(window), getWindowExStyle(window), wndconfig->width, wndconfig->height, &fullWidth, &fullHeight); } wideTitle = _glfwCreateWideStringFromUTF8(wndconfig->title); if (!wideTitle) { _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to convert window title to UTF-16"); return GLFW_FALSE; } window->win32.handle = CreateWindowExW(getWindowExStyle(window), _GLFW_WNDCLASSNAME, wideTitle, getWindowStyle(window), xpos, ypos, fullWidth, fullHeight, NULL, // No parent window NULL, // No window menu GetModuleHandleW(NULL), window); // Pass object to WM_CREATE free(wideTitle); if (!window->win32.handle) { _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create window"); return GLFW_FALSE; } if (_glfw_ChangeWindowMessageFilterEx) { _glfw_ChangeWindowMessageFilterEx(window->win32.handle, WM_DROPFILES, MSGFLT_ALLOW, NULL); _glfw_ChangeWindowMessageFilterEx(window->win32.handle, WM_COPYDATA, MSGFLT_ALLOW, NULL); _glfw_ChangeWindowMessageFilterEx(window->win32.handle, WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL); } if (wndconfig->floating && !wndconfig->monitor) { SetWindowPos(window->win32.handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } DragAcceptFiles(window->win32.handle, TRUE); if (!_glfwCreateContext(window, ctxconfig, fbconfig)) return GLFW_FALSE; window->win32.minwidth = GLFW_DONT_CARE; window->win32.minheight = GLFW_DONT_CARE; window->win32.maxwidth = GLFW_DONT_CARE; window->win32.maxheight = GLFW_DONT_CARE; window->win32.numer = GLFW_DONT_CARE; window->win32.denom = GLFW_DONT_CARE; return GLFW_TRUE; }
// Creates the GLFW window // static int createNativeWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig) { int xpos, ypos, fullWidth, fullHeight; WCHAR* wideTitle; DWORD style = getWindowStyle(window); DWORD exStyle = getWindowExStyle(window); if (window->monitor) { GLFWvidmode mode; // NOTE: This window placement is temporary and approximate, as the // correct position and size cannot be known until the monitor // video mode has been set _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos); _glfwPlatformGetVideoMode(window->monitor, &mode); fullWidth = mode.width; fullHeight = mode.height; } else { xpos = CW_USEDEFAULT; ypos = CW_USEDEFAULT; if (wndconfig->maximized) style |= WS_MAXIMIZE; getFullWindowSize(style, exStyle, wndconfig->width, wndconfig->height, &fullWidth, &fullHeight); } wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title); if (!wideTitle) { _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to convert window title to UTF-16"); return GLFW_FALSE; } window->win32.handle = CreateWindowExW(exStyle, _GLFW_WNDCLASSNAME, wideTitle, style, xpos, ypos, fullWidth, fullHeight, NULL, // No parent window NULL, // No window menu GetModuleHandleW(NULL), NULL); free(wideTitle); if (!window->win32.handle) { _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create window"); return GLFW_FALSE; } SetPropW(window->win32.handle, L"GLFW", window); if (_glfw_ChangeWindowMessageFilterEx) { _glfw_ChangeWindowMessageFilterEx(window->win32.handle, WM_DROPFILES, MSGFLT_ALLOW, NULL); _glfw_ChangeWindowMessageFilterEx(window->win32.handle, WM_COPYDATA, MSGFLT_ALLOW, NULL); _glfw_ChangeWindowMessageFilterEx(window->win32.handle, WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL); } DragAcceptFiles(window->win32.handle, TRUE); return GLFW_TRUE; }
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { int modeIndex = 0, size = 0; GLFWvidmode* result = NULL; *count = 0; for (;;) { int i; GLFWvidmode mode; DEVMODEW dm; ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(dm); if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm)) break; modeIndex++; // Skip modes with less than 15 BPP if (dm.dmBitsPerPel < 15) continue; mode.width = dm.dmPelsWidth; mode.height = dm.dmPelsHeight; mode.refreshRate = dm.dmDisplayFrequency; _glfwSplitBPP(dm.dmBitsPerPel, &mode.redBits, &mode.greenBits, &mode.blueBits); for (i = 0; i < *count; i++) { if (_glfwCompareVideoModes(result + i, &mode) == 0) break; } // Skip duplicate modes if (i < *count) continue; if (monitor->win32.modesPruned) { // Skip modes not supported by the connected displays if (ChangeDisplaySettingsExW(monitor->win32.adapterName, &dm, NULL, CDS_TEST, NULL) != DISP_CHANGE_SUCCESSFUL) { continue; } } if (*count == size) { size += 128; result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode)); } (*count)++; result[*count - 1] = mode; } if (!*count) { // HACK: Report the current mode if no valid modes were found result = calloc(1, sizeof(GLFWvidmode)); _glfwPlatformGetVideoMode(monitor, result); *count = 1; } return result; }