diff --git a/appshell/cef_host_window.cpp b/appshell/cef_host_window.cpp index 14e86d4cc..bd45a9cc7 100644 --- a/appshell/cef_host_window.cpp +++ b/appshell/cef_host_window.cpp @@ -168,7 +168,20 @@ BOOL cef_host_window::HandleSize(BOOL bMinimize) } SetProp(L"WasMinimized", (HANDLE)bMinimize); #endif + NotifyWindowMovedOrResized(); + return FALSE; +} +void cef_host_window::NotifyWindowMovedOrResized() +{ + if (GetBrowser() && GetBrowser()->GetHost()) { + GetBrowser()->GetHost()->NotifyMoveOrResizeStarted(); + } +} + +BOOL cef_host_window::HandleMoveOrMoving() +{ + NotifyWindowMovedOrResized(); return FALSE; } @@ -198,6 +211,11 @@ LRESULT cef_host_window::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) if (HandleInitMenuPopup((HMENU)wParam)) return 0L; break; + case WM_MOVING: + case WM_MOVE: + if (HandleMoveOrMoving()) + return 0L; + break; } diff --git a/appshell/cef_host_window.h b/appshell/cef_host_window.h index 9bca2c40a..932444a4a 100644 --- a/appshell/cef_host_window.h +++ b/appshell/cef_host_window.h @@ -63,6 +63,7 @@ class cef_host_window : public cef_host_window_base // Message Handlers BOOL HandleInitMenuPopup(HMENU hMenuPopup); BOOL HandleSize(BOOL bMinimize); + BOOL HandleMoveOrMoving(); // Command Implementation BOOL DoCommand(UINT commandId, CefRefPtr callback = 0); @@ -70,6 +71,7 @@ class cef_host_window : public cef_host_window_base // Implementation virtual void DoRepaintClientArea(); + void NotifyWindowMovedOrResized(); // Helper to get a command string from command id CefString GetCommandString(UINT commandId); diff --git a/appshell/cef_main_window.cpp b/appshell/cef_main_window.cpp index 1909b55c8..51305c81d 100644 --- a/appshell/cef_main_window.cpp +++ b/appshell/cef_main_window.cpp @@ -99,6 +99,60 @@ LPCWSTR cef_main_window::GetBracketsWindowTitleText() return szTitle; } +void cef_main_window::EnsureWindowRectVisibility(int& left, int& top, int& width, int& height, int showCmd) +{ + static const int kWindowFrameSize = 8; + + // don't check if we're already letting + // Windows determine the window placement + if (left == CW_USEDEFAULT && + top == CW_USEDEFAULT && + width == CW_USEDEFAULT && + height == CW_USEDEFAULT) { + return; + } + + // The virtual display is the bounding rect of all monitors + // see http://msdn.microsoft.com/en-us/library/dd162729(v=vs.85).aspx + + int xScreen = ::GetSystemMetrics(SM_XVIRTUALSCREEN); + int yScreen = ::GetSystemMetrics(SM_YVIRTUALSCREEN); + int cxScreen = ::GetSystemMetrics(SM_CXVIRTUALSCREEN); + int cyScreen = ::GetSystemMetrics(SM_CYVIRTUALSCREEN); + + // make a copy, we need to adjust the comparison + // if it's a maximized window because the OS move the + // origin of the window by 8 pixes to releive the borders + // from the monitor for legacy apps + int xLeft = left; + int xTop = top; + int xWidth = width; + int xHeight = height; + + if (showCmd == SW_MAXIMIZE) { + xLeft += kWindowFrameSize; + xTop += kWindowFrameSize; + xWidth -= kWindowFrameSize * 2; + xHeight -= kWindowFrameSize * 2; + } + + // Make sure the window fits inside the virtual screen. + // If it doesn't then we let windows decide the window placement + if (xLeft < xScreen || + xTop < yScreen || + xLeft + xWidth > xScreen + cxScreen || + xTop + xHeight > yScreen + cyScreen) { + + // something was off-screen so reposition + // to the default window placement + left = CW_USEDEFAULT; + top = CW_USEDEFAULT; + width = CW_USEDEFAULT; + height = CW_USEDEFAULT; + } +} + + // Create Method. Call this to create a cef_main_window instance BOOL cef_main_window::Create() { @@ -108,10 +162,14 @@ BOOL cef_main_window::Create() int top = CW_USEDEFAULT; int width = CW_USEDEFAULT; int height = CW_USEDEFAULT; + int showCmd = SW_SHOW; LoadWindowRestoreRect(left, top, width, height, showCmd); + // make sure the window is visible + EnsureWindowRectVisibility(left, top, width, height, showCmd); + DWORD styles = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_EX_COMPOSITED; if (showCmd == SW_MAXIMIZE) @@ -353,8 +411,32 @@ void cef_main_window::RestoreWindowPlacement(int showCmd) GetRegistryInt(::kWindowPostionFolder, ::kPrefRestoreRight, NULL, (int&)wp.rcNormalPosition.right); GetRegistryInt(::kWindowPostionFolder, ::kPrefRestoreBottom, NULL, (int&)wp.rcNormalPosition.bottom); - // This returns FALSE on failure but not sure what we could do in that case - SetWindowPlacement(&wp); + ::NormalizeRect(wp.rcNormalPosition); + + int left = wp.rcNormalPosition.left; + int top = wp.rcNormalPosition.top; + int width = wp.rcNormalPosition.right - left; + int height = wp.rcNormalPosition.bottom - top; + + EnsureWindowRectVisibility(left, top, width, height, SW_SHOWNORMAL); + + // presumably they would all be set to CW_USEDEFAULT + // but we check for any out-of-bounds value and + // bypass the restore rect as to let Windows decide + if (left != CW_USEDEFAULT && + top != CW_USEDEFAULT && + height != CW_USEDEFAULT && + width != CW_USEDEFAULT) { + + wp.rcNormalPosition.left = left; + wp.rcNormalPosition.top = top; + + wp.rcNormalPosition.right = wp.rcNormalPosition.left + width; + wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + height; + + // This returns FALSE on failure but not sure what we could do in that case + SetWindowPlacement(&wp); + } } ShowWindow(showCmd); diff --git a/appshell/cef_main_window.h b/appshell/cef_main_window.h index a23f798c0..0890af9e7 100644 --- a/appshell/cef_main_window.h +++ b/appshell/cef_main_window.h @@ -47,6 +47,7 @@ class cef_main_window : public cef_host_window void SaveWindowRestoreRect(); void LoadWindowRestoreRect(int& left, int& top, int& width, int& height, int& showCmd); void RestoreWindowPlacement(int showCmd); + void EnsureWindowRectVisibility(int& left, int& top, int& width, int& height, int showCmd); // Message Handlers BOOL HandleEraseBackground(HDC hdc);