/* readonly attribute boolean isCompositionEnabled; */ NS_IMETHODIMP sbWindowChromeService::GetIsCompositionEnabled(bool *aIsCompositionEnabled) { NS_ENSURE_ARG_POINTER(aIsCompositionEnabled); *aIsCompositionEnabled = IsCompositionEnabled(this); return NS_OK; }
bool DwmFunctions::is_composition_enabled() { if (IsCompositionEnabled) { BOOL is_enabled = FALSE; HRESULT result = IsCompositionEnabled(&is_enabled); return SUCCEEDED(result) && is_enabled == TRUE; } else { return false; } }
bool FD3D11Viewport::Present(bool bLockToVsync) { bool bNativelyPresented = true; #if D3D11_WITH_DWMAPI // We can't call Present if !bIsValid, as it waits a window message to be processed, but the main thread may not be pumping the message handler. if(bIsValid) { // Check if the viewport's swap chain has been invalidated by DXGI. BOOL bSwapChainFullscreenState; TRefCountPtr<IDXGIOutput> SwapChainOutput; VERIFYD3D11RESULT(SwapChain->GetFullscreenState(&bSwapChainFullscreenState,SwapChainOutput.GetInitReference())); // Can't compare BOOL with bool... if ( (!!bSwapChainFullscreenState) != bIsFullscreen ) { bIsValid = false; // Minimize the window. // use SW_FORCEMINIMIZE if the messaging thread is likely to be blocked for a sizeable period. // SW_FORCEMINIMIZE also prevents the minimize animation from playing. ::ShowWindow(WindowHandle,SW_MINIMIZE); } } // When desktop composition is enabled, locking to vsync via the Present // call is unreliable. Instead, communicate with the desktop window manager // directly to enable vsync. const bool bSyncWithDWM = bLockToVsync && !bIsFullscreen && RHIConsoleVariables::bSyncWithDWM && IsCompositionEnabled(); if (bSyncWithDWM) { PresentWithVsyncDWM(); } else #endif //D3D11_WITH_DWMAPI { // Present the back buffer to the viewport window. bNativelyPresented = PresentChecked(bLockToVsync ? RHIConsoleVariables::SyncInterval : 0); } return bNativelyPresented; }
bool EventFilter::mainWindowEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result) { using ShadowsChange = MainWindow::ShadowsChange; if (auto tbCreatedMsgId = Platform::MainWindow::TaskbarCreatedMsgId()) { if (msg == tbCreatedMsgId) { Platform::MainWindow::TaskbarCreated(); } } switch (msg) { case WM_TIMECHANGE: { if (AuthSession::Exists()) { Auth().checkAutoLockIn(100); } } return false; case WM_WTSSESSION_CHANGE: { if (wParam == WTS_SESSION_LOGOFF || wParam == WTS_SESSION_LOCK) { setSessionLoggedOff(true); } else if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_UNLOCK) { setSessionLoggedOff(false); } } return false; case WM_DESTROY: { App::quit(); } return false; case WM_ACTIVATE: { if (LOWORD(wParam) == WA_CLICKACTIVE) { App::wnd()->setInactivePress(true); } if (LOWORD(wParam) != WA_INACTIVE) { App::wnd()->shadowsActivate(); } else { App::wnd()->shadowsDeactivate(); } if (Global::started()) { App::wnd()->update(); } } return false; case WM_NCPAINT: { if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false; if (result) *result = 0; } return true; case WM_NCCALCSIZE: { WINDOWPLACEMENT wp; wp.length = sizeof(WINDOWPLACEMENT); if (GetWindowPlacement(hWnd, &wp) && wp.showCmd == SW_SHOWMAXIMIZED) { LPNCCALCSIZE_PARAMS params = (LPNCCALCSIZE_PARAMS)lParam; LPRECT r = (wParam == TRUE) ? ¶ms->rgrc[0] : (LPRECT)lParam; HMONITOR hMonitor = MonitorFromPoint({ (r->left + r->right) / 2, (r->top + r->bottom) / 2 }, MONITOR_DEFAULTTONEAREST); if (hMonitor) { MONITORINFO mi; mi.cbSize = sizeof(mi); if (GetMonitorInfo(hMonitor, &mi)) { *r = mi.rcWork; } } } if (result) *result = 0; return true; } case WM_NCACTIVATE: { if (IsCompositionEnabled()) { const auto res = DefWindowProc(hWnd, msg, wParam, -1); if (result) *result = res; } else { // Thanks https://github.com/melak47/BorderlessWindow if (result) *result = 1; } } return true; case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: { WINDOWPLACEMENT wp; wp.length = sizeof(WINDOWPLACEMENT); if (GetWindowPlacement(hWnd, &wp) && (wp.showCmd == SW_SHOWMAXIMIZED || wp.showCmd == SW_SHOWMINIMIZED)) { App::wnd()->shadowsUpdate(ShadowsChange::Hidden); } else { App::wnd()->shadowsUpdate(ShadowsChange::Moved | ShadowsChange::Resized, (WINDOWPOS*)lParam); } } return false; case WM_SIZE: { if (App::wnd()) { if (wParam == SIZE_MAXIMIZED || wParam == SIZE_RESTORED || wParam == SIZE_MINIMIZED) { if (wParam != SIZE_RESTORED || App::wnd()->windowState() != Qt::WindowNoState) { Qt::WindowState state = Qt::WindowNoState; if (wParam == SIZE_MAXIMIZED) { state = Qt::WindowMaximized; } else if (wParam == SIZE_MINIMIZED) { state = Qt::WindowMinimized; } emit App::wnd()->windowHandle()->windowStateChanged(state); } else { App::wnd()->positionUpdated(); } App::wnd()->psUpdateMargins(); MainWindow::ShadowsChanges changes = (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXIMIZED) ? ShadowsChange::Hidden : (ShadowsChange::Resized | ShadowsChange::Shown); App::wnd()->shadowsUpdate(changes); } } } return false; case WM_SHOWWINDOW: { LONG style = GetWindowLong(hWnd, GWL_STYLE); auto changes = ShadowsChange::Resized | ((wParam && !(style & (WS_MAXIMIZE | WS_MINIMIZE))) ? ShadowsChange::Shown : ShadowsChange::Hidden); App::wnd()->shadowsUpdate(changes); } return false; case WM_MOVE: { App::wnd()->shadowsUpdate(ShadowsChange::Moved); App::wnd()->positionUpdated(); } return false; case WM_NCHITTEST: { if (!result) return false; POINTS p = MAKEPOINTS(lParam); RECT r; GetWindowRect(hWnd, &r); auto res = App::wnd()->hitTest(QPoint(p.x - r.left + App::wnd()->deltaLeft(), p.y - r.top + App::wnd()->deltaTop())); switch (res) { case Window::HitTestResult::Client: case Window::HitTestResult::SysButton: *result = HTCLIENT; break; case Window::HitTestResult::Caption: *result = HTCAPTION; break; case Window::HitTestResult::Top: *result = HTTOP; break; case Window::HitTestResult::TopRight: *result = HTTOPRIGHT; break; case Window::HitTestResult::Right: *result = HTRIGHT; break; case Window::HitTestResult::BottomRight: *result = HTBOTTOMRIGHT; break; case Window::HitTestResult::Bottom: *result = HTBOTTOM; break; case Window::HitTestResult::BottomLeft: *result = HTBOTTOMLEFT; break; case Window::HitTestResult::Left: *result = HTLEFT; break; case Window::HitTestResult::TopLeft: *result = HTTOPLEFT; break; case Window::HitTestResult::None: default: *result = HTTRANSPARENT; break; }; } return true; case WM_NCRBUTTONUP: { SendMessage(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam); } return true; case WM_SYSCOMMAND: { if (wParam == SC_MOUSEMENU) { POINTS p = MAKEPOINTS(lParam); App::wnd()->updateSystemMenu(App::wnd()->windowHandle()->windowState()); TrackPopupMenu(App::wnd()->psMenu(), TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, p.x, p.y, 0, hWnd, 0); } } return false; case WM_COMMAND: { if (HIWORD(wParam)) return false; int cmd = LOWORD(wParam); switch (cmd) { case SC_CLOSE: App::wnd()->close(); return true; case SC_MINIMIZE: App::wnd()->setWindowState(Qt::WindowMinimized); return true; case SC_MAXIMIZE: App::wnd()->setWindowState(Qt::WindowMaximized); return true; case SC_RESTORE: App::wnd()->setWindowState(Qt::WindowNoState); return true; } } return true; } return false; }
/* static */ LRESULT sbWindowChromeService::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { if (uIdSubclass != gSubclassId) { // We're majorly screwed up somehow; do nothing return DefSubclassProc(hWnd, uMsg, wParam, lParam); } TRACE(("%s: WndProc(%p, %08x)", __FUNCTION__, hWnd, uMsg)); switch (uMsg) { case WM_NCDESTROY: { // clean up RemoveWindowSubclass(hWnd, &sbWindowChromeService::WndProc, uIdSubclass); break; } case WM_NCCALCSIZE: { if (!(BOOL)wParam) { // we do not need to do anything special for this case break; } NCCALCSIZE_PARAMS* params = (NCCALCSIZE_PARAMS*)lParam; bool willMinimize = (params->rgrc[0].left == -32000) && (params->rgrc[0].top == -32000); if (willMinimize) { // we are going to minimize; don't touch anything break; } if (IsZoomed(hWnd)) { // On Windows 7, Windows will adjust the size of the maximized windows // so that they're larger than the screen to account for the window // border (even with Aero disabled). On XP, however, it does _not_ do // that. So, figure out how big the window wants to be, and how big the // screen is, and go for the closest solution. RECT* rectWindow = ¶ms->rgrc[0]; // shorthand RECT rectMon = {0}; int xSize = ::GetSystemMetrics(SM_CXSIZEFRAME); int ySize = ::GetSystemMetrics(SM_CYSIZEFRAME); // Bug 21344 - HMONITOR's are not handles HMONITOR hMon = ::MonitorFromRect(rectWindow, MONITOR_DEFAULTTONULL); if (hMon) { MONITORINFO monInfo = {0}; monInfo.cbSize = sizeof(monInfo); BOOL success = ::GetMonitorInfo(hMon, &monInfo); if (success) { ::CopyRect(&rectMon, &monInfo.rcWork); } else { ::CopyRect(&rectMon, rectWindow); } } else { // no monitor!? ::CopyRect(&rectMon, rectWindow); } const LONG TOLERANCE = 2; if (rectMon.top > rectWindow->top && rectMon.top - rectWindow->top < ySize + TOLERANCE) { rectWindow->top += ySize; } if (rectWindow->bottom > rectMon.bottom && rectWindow->bottom - rectMon.bottom < ySize + TOLERANCE) { rectWindow->bottom -= ySize; } if (rectMon.left > rectWindow->left && rectMon.left - rectWindow->left < xSize + TOLERANCE) { rectWindow->left += xSize; } if (rectWindow->right > rectMon.right && rectWindow->right - rectMon.right < xSize + TOLERANCE) { rectWindow->right -= xSize; } // Chop off one pixel on any edge with auto-hidden taskbars (deskbars, // really). This is required to make sure those taskbars will remain // functional (i.e. pop up) when the mouse goes near them - otherwise // Windows assumes we really meant to be a full screen window instead. APPBARDATA appbarData = {sizeof(APPBARDATA)}; appbarData.hWnd = hWnd; HWND wnd; // Bug 21344 - HMONITOR's are not handles HMONITOR selfMon = ::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST), targetMon; appbarData.uEdge = ABE_TOP; wnd = (HWND)::SHAppBarMessage(ABM_GETAUTOHIDEBAR, &appbarData); if (wnd) { targetMon = ::MonitorFromWindow(wnd, MONITOR_DEFAULTTONEAREST); if (targetMon == selfMon) { // instead of bumping the window down, subtract a pixel from the // bottom instead - otherwise we end up exposing a pixel of the // top which 1) can lead to clicking on nearly-invisible widgets (e.g. // the close button), 2) loses fitt's law gains of having things at top params->rgrc[0].bottom -= 1; } } appbarData.uEdge = ABE_RIGHT; wnd = (HWND)::SHAppBarMessage(ABM_GETAUTOHIDEBAR, &appbarData); if (wnd) { targetMon = ::MonitorFromWindow(wnd, MONITOR_DEFAULTTONEAREST); if (targetMon == selfMon) { params->rgrc[0].right -= 1; } } appbarData.uEdge = ABE_BOTTOM; wnd = (HWND)::SHAppBarMessage(ABM_GETAUTOHIDEBAR, &appbarData); if (wnd) { targetMon = ::MonitorFromWindow(wnd, MONITOR_DEFAULTTONEAREST); if (targetMon == selfMon) { params->rgrc[0].bottom -= 1; } } appbarData.uEdge = ABE_LEFT; wnd = (HWND)::SHAppBarMessage(ABM_GETAUTOHIDEBAR, &appbarData); if (wnd) { targetMon = ::MonitorFromWindow(wnd, MONITOR_DEFAULTTONEAREST); if (targetMon == selfMon) { params->rgrc[0].left += 1; } } return 0; } // we have a window we want to hook, but it's not maximized; leave the // rectangles as-is, meaning that there should be no non-client area (i.e. // no chrome at all). return 0; } case WM_NCACTIVATE: { if (IsCompositionEnabled((sbWindowChromeService*)uIdSubclass)) { // When DWM composition is enabled, call the default handler so that // it draws the window shadow. In this case the window is also double // buffered (by the DWM), so we don't have to worry about flickering. // We skip doing this if we're maximized (or look like we are, since that // is how Mozilla implemented full screen) to avoid problems with the // video window showing the (win9x) non-client area. We don't need to // have shadows in that case anyway. RECT rectMon = {0}, rectWindow; BOOL success = ::GetWindowRect(hWnd, &rectWindow); if (!success) { ::SetRect(&rectWindow, -1, -1, -1, -1); } // Bug 21344 - HMONITOR's are not handles HMONITOR hMon = ::MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL); if (hMon) { MONITORINFO monInfo = {0}; monInfo.cbSize = sizeof(monInfo); success = ::GetMonitorInfo(hMon, &monInfo); if (success) { ::CopyRect(&rectMon, &monInfo.rcMonitor); } } if (!::EqualRect(&rectMon, &rectWindow)) { return DefSubclassProc(hWnd, uMsg, wParam, lParam); } } else { // Let's turn off themes to make sure our borders don't get rounded! ::SetWindowTheme(hWnd, L"", L""); } // No DWM, don't do anything to avoid extra paints of the non-client area // which causes bad flickering. return TRUE; } case WM_NCPAINT: { TRACE(("WM_NCPAINT(%p)", hWnd)); // We need to call the default implementation in order to get window shadow. // Since that only works when DWM is enabled anyway, check if it is - if it // is not, do not call the default implementation since that causes flicker // on systems with theming but not DWM (e.g. XP, or Vista with 16bpp). if (!IsCompositionEnabled((sbWindowChromeService*)uIdSubclass)) { // no need to do anything; however, invalidate the window anyway in case // this paint was caused by invalidation. InvalidateRgn(hWnd, NULL, FALSE); return 0; } return DefSubclassProc(hWnd, uMsg, wParam, lParam); } case 0xAE: /* undocumented: WM_NCUAHDRAWCAPTION */ case 0xAF: /* undocumented: WM_NCUAHDRAWFRAME */ // these messages, according to chromium.org, are sent by Windows to redraw // the caption / frame at unpredictable times. Intercept these and don't // use the default behaviour. return 0; } return DefSubclassProc(hWnd, uMsg, wParam, lParam); }