Skip to content
This repository was archived by the owner on Sep 2, 2021. It is now read-only.
149 changes: 145 additions & 4 deletions appshell/cefclient_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,23 @@ extern CefRefPtr<ClientHandler> g_handler;
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") // NOLINT(whitespace/line_length)
#endif

// Registry access functions
void GetKey(LPCWSTR pBase, LPCWSTR pGroup, LPCWSTR pApp, LPCWSTR pFolder, LPWSTR pRet);
bool GetRegistryInt(LPCWSTR pFolder, LPCWSTR pEntry, int* pDefault, int& ret);
bool WriteRegistryInt (LPCWSTR pFolder, LPCWSTR pEntry, int val);

// Registry key strings
#define PREF_APPSHELL_BASE L"Software"
#define PREF_WINPOS_FOLDER L"Window Position"
#define PREF_LEFT L"Left"
#define PREF_TOP L"Top"
#define PREF_WIDTH L"Width"
#define PREF_HEIGHT L"Height"

// Window state functions
void SaveWindowRect();
void RestoreWindowRect(int& left, int& top, int& width, int& height);

// Program entry point function.
int APIENTRY wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
Expand Down Expand Up @@ -190,6 +207,119 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
return result;
}

// Helper method to build Registry Key string
void GetKey(LPCWSTR pBase, LPCWSTR pGroup, LPCWSTR pApp, LPCWSTR pFolder, LPWSTR pRet)
{
// Check for required params
ASSERT(pBase && pApp && pRet);
if (!pBase || !pApp || !pRet)
return;

// Base
wcscpy(pRet, pBase);

// Group (optional)
if (pGroup && (pGroup[0] != '\0'))
{
wcscat(pRet, L"\\");
wcscat(pRet, pGroup);
}

// App name
wcscat(pRet, L"\\");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the GROUP_NAME macro, if defined, already has a backslash at the end of it (see config.h for edge code). In that case, you'll either need to omit the backslash when copying from pGroup, or omit it here before appending pApp.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. I made it so any string passed to this function works with or without a trailing backslash.

wcscat(pRet, pApp);

// Folder (optional)
if (pFolder && (pFolder[0] != '\0'))
{
wcscat(pRet, L"\\");
wcscat(pRet, pFolder);
}
}

// get integer value from registry key
// caller can either use return value to determine success/fail, or pass a default to be used on fail
bool GetRegistryInt(LPCWSTR pFolder, LPCWSTR pEntry, int* pDefault, int& ret)
{
HKEY hKey;
bool result = false;

wchar_t key[MAX_PATH];
key[0] = '\0';
GetKey(PREF_APPSHELL_BASE, GROUP_NAME, APP_NAME, pFolder, (LPWSTR)&key);

if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, (LPCWSTR)key, 0, KEY_READ, &hKey))
{
DWORD dwValue = 0;
DWORD dwType = 0;
DWORD dwCount = sizeof(DWORD);
if (ERROR_SUCCESS == RegQueryValueEx(hKey, pEntry, NULL, &dwType, (LPBYTE)&dwValue, &dwCount))
{
result = true;
ASSERT(dwType == REG_DWORD);
ASSERT(dwCount == sizeof(dwValue));
ret = (int)dwValue;
}
RegCloseKey(hKey);
}

if (!result)
{
// couldn't read value, so use default, if specified
if (pDefault)
ret = *pDefault;
}

return result;
}

// write integer value to registry key
bool WriteRegistryInt(LPCWSTR pFolder, LPCWSTR pEntry, int val)
{
HKEY hKey;
bool result = false;

wchar_t key[MAX_PATH];
key[0] = '\0';
GetKey(PREF_APPSHELL_BASE, GROUP_NAME, APP_NAME, pFolder, (LPWSTR)&key);

if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, (LPCWSTR)key, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL))
{
DWORD dwCount = sizeof(int);
if (ERROR_SUCCESS == RegSetValueEx(hKey, pEntry, 0, REG_DWORD, (LPBYTE)&val, dwCount))
result = true;
RegCloseKey(hKey);
}

return result;
}

void SaveWindowRect()
{
// Save position of active window
HWND hWnd = GetActiveWindow();
if (hWnd)
{
RECT rect;
if (GetWindowRect(hWnd, &rect))
{
WriteRegistryInt(PREF_WINPOS_FOLDER, PREF_LEFT, rect.left);
WriteRegistryInt(PREF_WINPOS_FOLDER, PREF_TOP, rect.top);
WriteRegistryInt(PREF_WINPOS_FOLDER, PREF_WIDTH, rect.right - rect.left);
WriteRegistryInt(PREF_WINPOS_FOLDER, PREF_HEIGHT, rect.bottom - rect.top);
}
}
}

void RestoreWindowRect(int& left, int& top, int& width, int& height)
{
GetRegistryInt(PREF_WINPOS_FOLDER, PREF_LEFT, NULL, left);
GetRegistryInt(PREF_WINPOS_FOLDER, PREF_TOP, NULL, top);
GetRegistryInt(PREF_WINPOS_FOLDER, PREF_WIDTH, NULL, width);
GetRegistryInt(PREF_WINPOS_FOLDER, PREF_HEIGHT, NULL, height);
}


//
// FUNCTION: MyRegisterClass()
//
Expand Down Expand Up @@ -247,9 +377,17 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {

hInst = hInstance; // Store instance handle in our global variable

hWnd = CreateWindow(szWindowClass, szTitle,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
// TODO: test this cases:
// - window in secondary monitor when shutdown, disconnect secondary monitor, restart

int left = CW_USEDEFAULT;
int top = 0;
int width = CW_USEDEFAULT;
int height = 0;
RestoreWindowRect(left, top, width, height);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will restore the window rect, but doesn't restore the maximized flag or the "normal" size. If you maximize the window, quit, then restart, the window size is set to the maximized size, but it isn't maximized (and, at least on my Win 7 machine, the top of the titlebar is a bit off the top of the screen). You may need to use GetWindowPlacement/SetWindowPlacement and save/restore the whole WINDOWPLACEMENT structure.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. This is how window states should be restored:

restored - Size & position should be remembered on any monitor.

maximized - Should be remembered for any monitor. Also, switching back to "restored" size should remember previous size & position.

minimized - It seems like we didn't want to open Brackets into a minimized state, so it should use state from previous startup.


hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
left, top, width, height, NULL, NULL, hInstance, NULL);

if (!hWnd)
return FALSE;
Expand Down Expand Up @@ -509,6 +647,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,

case WM_CLOSE:
if (g_handler.get()) {

SaveWindowRect();

// If we already initiated the browser closing, then let default window proc handle it.
HWND browserHwnd = g_handler->GetBrowser()->GetHost()->GetWindowHandle();
HANDLE closing = GetProp(browserHwnd, CLOSING_PROP);
Expand Down Expand Up @@ -566,4 +707,4 @@ CefString AppGetCachePath() {
cachePath += L"\\" GROUP_NAME APP_NAME L"\\cef_data";

return CefString(cachePath);
}
}