michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* ***** BEGIN LICENSE BLOCK ***** michael@0: * Version: Mozilla-sample-code 1.0 michael@0: * michael@0: * Copyright (c) 2002 Netscape Communications Corporation and michael@0: * other contributors michael@0: * michael@0: * Permission is hereby granted, free of charge, to any person obtaining a michael@0: * copy of this Mozilla sample software and associated documentation files michael@0: * (the "Software"), to deal in the Software without restriction, including michael@0: * without limitation the rights to use, copy, modify, merge, publish, michael@0: * distribute, sublicense, and/or sell copies of the Software, and to permit michael@0: * persons to whom the Software is furnished to do so, subject to the michael@0: * following conditions: michael@0: * michael@0: * The above copyright notice and this permission notice shall be included michael@0: * in all copies or substantial portions of the Software. michael@0: * michael@0: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS michael@0: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, michael@0: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL michael@0: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER michael@0: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING michael@0: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER michael@0: * DEALINGS IN THE SOFTWARE. michael@0: * michael@0: * Contributor(s): michael@0: * Doug Turner michael@0: * Adam Lock michael@0: * michael@0: * ***** END LICENSE BLOCK ***** */ michael@0: michael@0: // C RunTime Header Files michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: // Win32 header files michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: // Mozilla Frozen APIs michael@0: #include "nsXULAppAPI.h" michael@0: michael@0: XRE_InitEmbedding2Type XRE_InitEmbedding2; michael@0: XRE_TermEmbeddingType XRE_TermEmbedding; michael@0: michael@0: #include "nsAppDirectoryServiceDefs.h" michael@0: #include "nsDirectoryServiceDefs.h" michael@0: #include "nsProfileDirServiceProvider.h" michael@0: #include "nsStringAPI.h" michael@0: #include "nsXPCOMGlue.h" michael@0: michael@0: #include "nsIClipboardCommands.h" michael@0: #include "nsIInterfaceRequestor.h" michael@0: #include "nsIObserverService.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsIURI.h" michael@0: #include "nsIWebBrowserFocus.h" michael@0: #include "nsIWindowWatcher.h" michael@0: michael@0: // NON-FROZEN APIs! michael@0: #include "nsIBaseWindow.h" michael@0: #include "nsIWebNavigation.h" michael@0: michael@0: // Local header files michael@0: #include "winEmbed.h" michael@0: #include "WebBrowserChrome.h" michael@0: #include "WindowCreator.h" michael@0: #include "resource.h" michael@0: michael@0: #define MAX_LOADSTRING 100 michael@0: michael@0: const TCHAR *szWindowClass = _T("WINEMBED"); michael@0: michael@0: // Foward declarations of functions included in this code module: michael@0: static ATOM MyRegisterClass(HINSTANCE hInstance); michael@0: static LRESULT CALLBACK BrowserWndProc(HWND, UINT, WPARAM, LPARAM); michael@0: static INT_PTR CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); michael@0: michael@0: static nsresult InitializeWindowCreator(); michael@0: static nsresult OpenWebPage(const char * url); michael@0: static nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome); michael@0: michael@0: // Profile chooser stuff michael@0: static nsresult StartupProfile(); michael@0: michael@0: // Global variables michael@0: static UINT gDialogCount = 0; michael@0: static HINSTANCE ghInstanceApp = nullptr; michael@0: static char gFirstURL[1024]; michael@0: michael@0: // like strpbrk but finds the *last* char, not the first michael@0: static char* michael@0: ns_strrpbrk(char *string, const char *strCharSet) michael@0: { michael@0: char *found = nullptr; michael@0: for (; *string; ++string) { michael@0: for (const char *search = strCharSet; *search; ++search) { michael@0: if (*search == *string) { michael@0: found = string; michael@0: // Since we're looking for the last char, we save "found" michael@0: // until we're at the end of the string. michael@0: } michael@0: } michael@0: } michael@0: michael@0: return found; michael@0: } michael@0: michael@0: // A list of URLs to populate the URL drop down list with michael@0: static const TCHAR *gDefaultURLs[] = michael@0: { michael@0: _T("http://www.mozilla.org/"), michael@0: _T("http://www.netscape.com/"), michael@0: _T("http://browsertest.web.aol.com/tests/javascript/javascpt/index.htm"), michael@0: _T("http://127.0.0.1/"), michael@0: _T("http://www.yahoo.com/"), michael@0: _T("http://www.travelocity.com/"), michael@0: _T("http://www.disney.com/"), michael@0: _T("http://www.go.com/"), michael@0: _T("http://www.google.com/"), michael@0: _T("http://www.ebay.com/"), michael@0: _T("http://www.shockwave.com/"), michael@0: _T("http://www.slashdot.org/"), michael@0: _T("http://www.quicken.com/"), michael@0: _T("http://www.hotmail.com/"), michael@0: _T("http://www.cnn.com/"), michael@0: _T("http://www.javasoft.com/") michael@0: }; michael@0: michael@0: int main(int argc, char *argv[]) michael@0: { michael@0: nsresult rv; michael@0: michael@0: printf("You are embedded, man!\n\n"); michael@0: printf("******************************************************************\n"); michael@0: printf("* *\n"); michael@0: printf("* IMPORTANT NOTE: *\n"); michael@0: printf("* *\n"); michael@0: printf("* WinEmbed is not supported!!! Do not raise bugs on it unless *\n"); michael@0: printf("* it is badly broken (e.g. crash on start/exit, build errors) *\n"); michael@0: printf("* or you have the patch to make it better! MFCEmbed is now our *\n"); michael@0: printf("* embedding test application on Win32 and all testing should *\n"); michael@0: printf("* be done on that. *\n"); michael@0: printf("* *\n"); michael@0: printf("******************************************************************\n"); michael@0: printf("\n\n"); michael@0: michael@0: // Sophisticated command-line parsing in action michael@0: char *szFirstURL = "http://www.mozilla.org/projects/embedding/"; michael@0: int argn; michael@0: for (argn = 1; argn < argc; argn++) michael@0: { michael@0: szFirstURL = argv[argn]; michael@0: } michael@0: strncpy(gFirstURL, szFirstURL, sizeof(gFirstURL) - 1); michael@0: michael@0: ghInstanceApp = GetModuleHandle(nullptr); michael@0: michael@0: // Initialize global strings michael@0: TCHAR szTitle[MAX_LOADSTRING]; michael@0: LoadString(ghInstanceApp, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); michael@0: MyRegisterClass(ghInstanceApp); michael@0: michael@0: char path[_MAX_PATH]; michael@0: GetModuleFileName(ghInstanceApp, path, sizeof(path)); michael@0: char* lastslash = ns_strrpbrk(path, "/\\"); michael@0: if (!lastslash) michael@0: return 7; michael@0: michael@0: strcpy(lastslash, "\\xulrunner\\xpcom.dll"); michael@0: michael@0: rv = XPCOMGlueStartup(path); michael@0: if (NS_FAILED(rv)) michael@0: return 3; michael@0: michael@0: strcpy(lastslash, "\\xulrunner\\xul.dll"); michael@0: michael@0: HINSTANCE xulModule = LoadLibraryEx(path, nullptr, 0); michael@0: if (!xulModule) michael@0: return 4; michael@0: michael@0: XRE_InitEmbedding2 = michael@0: (XRE_InitEmbedding2Type) GetProcAddress(xulModule, "XRE_InitEmbedding2"); michael@0: if (!XRE_InitEmbedding2) { michael@0: fprintf(stderr, "Error: %i\n", GetLastError()); michael@0: return 5; michael@0: } michael@0: michael@0: XRE_TermEmbedding = michael@0: (XRE_TermEmbeddingType) GetProcAddress(xulModule, "XRE_TermEmbedding"); michael@0: if (!XRE_TermEmbedding) { michael@0: fprintf(stderr, "Error: %i\n", GetLastError()); michael@0: return 5; michael@0: } michael@0: michael@0: int result = 0; michael@0: michael@0: // Scope all the XPCOM stuff michael@0: { michael@0: strcpy(lastslash, "\\xulrunner"); michael@0: michael@0: nsCOMPtr xuldir; michael@0: rv = NS_NewNativeLocalFile(nsCString(path), false, michael@0: getter_AddRefs(xuldir)); michael@0: if (NS_FAILED(rv)) michael@0: return 6; michael@0: michael@0: *lastslash = '\0'; michael@0: michael@0: nsCOMPtr appdir; michael@0: rv = NS_NewNativeLocalFile(nsCString(path), false, michael@0: getter_AddRefs(appdir)); michael@0: if (NS_FAILED(rv)) michael@0: return 8; michael@0: michael@0: rv = XRE_InitEmbedding2(xuldir, appdir, nullptr); michael@0: if (NS_FAILED(rv)) michael@0: return 9; michael@0: michael@0: if (NS_FAILED(StartupProfile())) { michael@0: result = 8; michael@0: } michael@0: else { michael@0: InitializeWindowCreator(); michael@0: michael@0: // Open the initial browser window michael@0: OpenWebPage(gFirstURL); michael@0: michael@0: // Main message loop. michael@0: // NOTE: We use a fake event and a timeout in order to process idle stuff for michael@0: // Mozilla every 1/10th of a second. michael@0: bool runCondition = true; michael@0: michael@0: result = AppCallbacks::RunEventLoop(runCondition); michael@0: } michael@0: } michael@0: XRE_TermEmbedding(); michael@0: michael@0: return result; michael@0: } michael@0: michael@0: /* InitializeWindowCreator creates and hands off an object with a callback michael@0: to a window creation function. This is how all new windows are opened, michael@0: except any created directly by the embedding app. */ michael@0: nsresult michael@0: InitializeWindowCreator() michael@0: { michael@0: // create an nsWindowCreator and give it to the WindowWatcher service michael@0: nsCOMPtr creator(new WindowCreator()); michael@0: if (!creator) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: nsCOMPtr wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); michael@0: if (!wwatch) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: return wwatch->SetWindowCreator(creator); michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: // michael@0: // FUNCTION: OpenWebPage() michael@0: // michael@0: // PURPOSE: Opens a new browser dialog and starts it loading to the michael@0: // specified url. michael@0: // michael@0: nsresult OpenWebPage(const char *url) michael@0: { michael@0: nsresult rv; michael@0: michael@0: // Create the chrome object. Note that it leaves this function michael@0: // with an extra reference so that it can released correctly during michael@0: // destruction (via Win32UI::Destroy) michael@0: michael@0: nsCOMPtr chrome; michael@0: rv = AppCallbacks::CreateBrowserWindow(nsIWebBrowserChrome::CHROME_ALL, michael@0: nullptr, getter_AddRefs(chrome)); michael@0: if (NS_SUCCEEDED(rv)) michael@0: { michael@0: // Start loading a page michael@0: nsCOMPtr newBrowser; michael@0: chrome->GetWebBrowser(getter_AddRefs(newBrowser)); michael@0: nsCOMPtr webNav(do_QueryInterface(newBrowser)); michael@0: michael@0: return webNav->LoadURI(NS_ConvertASCIItoUTF16(url).get(), michael@0: nsIWebNavigation::LOAD_FLAGS_NONE, michael@0: nullptr, michael@0: nullptr, michael@0: nullptr); michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: // michael@0: // FUNCTION: GetBrowserFromChrome() michael@0: // michael@0: // PURPOSE: Returns the HWND for the webbrowser container associated michael@0: // with the specified chrome. michael@0: // michael@0: HWND GetBrowserFromChrome(nsIWebBrowserChrome *aChrome) michael@0: { michael@0: if (!aChrome) michael@0: { michael@0: return nullptr; michael@0: } michael@0: nsCOMPtr baseWindow = do_QueryInterface(aChrome); michael@0: HWND hwnd = nullptr; michael@0: baseWindow->GetSiteWindow((void **) & hwnd); michael@0: return hwnd; michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: GetBrowserDlgFromChrome() michael@0: // michael@0: // PURPOSE: Returns the HWND for the browser dialog associated with michael@0: // the specified chrome. michael@0: // michael@0: HWND GetBrowserDlgFromChrome(nsIWebBrowserChrome *aChrome) michael@0: { michael@0: return GetParent(GetBrowserFromChrome(aChrome)); michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: ResizeEmbedding() michael@0: // michael@0: // PURPOSE: Resizes the webbrowser window to fit its container. michael@0: // michael@0: nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome) michael@0: { michael@0: if (!chrome) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: nsCOMPtr embeddingSite = do_QueryInterface(chrome); michael@0: HWND hWnd; michael@0: embeddingSite->GetSiteWindow((void **) & hWnd); michael@0: michael@0: if (!hWnd) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: RECT rect; michael@0: GetClientRect(hWnd, &rect); michael@0: michael@0: // Make sure the browser is visible and sized michael@0: nsCOMPtr webBrowser; michael@0: chrome->GetWebBrowser(getter_AddRefs(webBrowser)); michael@0: nsCOMPtr webBrowserAsWin = do_QueryInterface(webBrowser); michael@0: if (webBrowserAsWin) michael@0: { michael@0: webBrowserAsWin->SetPositionAndSize(rect.left, michael@0: rect.top, michael@0: rect.right - rect.left, michael@0: rect.bottom - rect.top, michael@0: true); michael@0: webBrowserAsWin->SetVisibility(true); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: MyRegisterClass() michael@0: // michael@0: // PURPOSE: Registers the window class. michael@0: // michael@0: // COMMENTS: michael@0: // michael@0: // This function and its usage is only necessary if you want this code michael@0: // to be compatible with Win32 systems prior to the 'RegisterClassEx' michael@0: // function that was added to Windows 95. It is important to call this function michael@0: // so that the application will get 'well formed' small icons associated michael@0: // with it. michael@0: // michael@0: ATOM MyRegisterClass(HINSTANCE hInstance) michael@0: { michael@0: WNDCLASSEX wcex; michael@0: michael@0: memset(&wcex, 0, sizeof(wcex)); michael@0: wcex.cbSize = sizeof(WNDCLASSEX); michael@0: michael@0: wcex.style = CS_HREDRAW | CS_VREDRAW; michael@0: wcex.lpfnWndProc = (WNDPROC) BrowserWndProc; michael@0: wcex.cbClsExtra = 0; michael@0: wcex.cbWndExtra = 0; michael@0: wcex.hInstance = hInstance; michael@0: wcex.hIcon = LoadIcon(ghInstanceApp, (LPCTSTR)IDI_WINEMBED); michael@0: wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); michael@0: wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); michael@0: wcex.lpszClassName = szWindowClass; michael@0: wcex.hIconSm = LoadIcon(ghInstanceApp, (LPCTSTR)IDI_SMALL); michael@0: michael@0: return RegisterClassEx(&wcex); michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: UpdateUI() michael@0: // michael@0: // PURPOSE: Refreshes the buttons and menu items in the browser dialog michael@0: // michael@0: void UpdateUI(nsIWebBrowserChrome *aChrome) michael@0: { michael@0: HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); michael@0: nsCOMPtr webBrowser; michael@0: nsCOMPtr webNavigation; michael@0: aChrome->GetWebBrowser(getter_AddRefs(webBrowser)); michael@0: webNavigation = do_QueryInterface(webBrowser); michael@0: michael@0: bool canGoBack = false; michael@0: bool canGoForward = false; michael@0: if (webNavigation) michael@0: { michael@0: webNavigation->GetCanGoBack(&canGoBack); michael@0: webNavigation->GetCanGoForward(&canGoForward); michael@0: } michael@0: michael@0: bool canCutSelection = false; michael@0: bool canCopySelection = false; michael@0: bool canPaste = false; michael@0: michael@0: nsCOMPtr clipCmds = do_GetInterface(webBrowser); michael@0: if (clipCmds) michael@0: { michael@0: clipCmds->CanCutSelection(&canCutSelection); michael@0: clipCmds->CanCopySelection(&canCopySelection); michael@0: clipCmds->CanPaste(&canPaste); michael@0: } michael@0: michael@0: HMENU hmenu = GetMenu(hwndDlg); michael@0: if (hmenu) michael@0: { michael@0: EnableMenuItem(hmenu, MOZ_GoBack, MF_BYCOMMAND | michael@0: ((canGoBack) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); michael@0: EnableMenuItem(hmenu, MOZ_GoForward, MF_BYCOMMAND | michael@0: ((canGoForward) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); michael@0: michael@0: EnableMenuItem(hmenu, MOZ_Cut, MF_BYCOMMAND | michael@0: ((canCutSelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); michael@0: EnableMenuItem(hmenu, MOZ_Copy, MF_BYCOMMAND | michael@0: ((canCopySelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); michael@0: EnableMenuItem(hmenu, MOZ_Paste, MF_BYCOMMAND | michael@0: ((canPaste) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); michael@0: } michael@0: michael@0: HWND button; michael@0: button = GetDlgItem(hwndDlg, IDC_BACK); michael@0: if (button) michael@0: EnableWindow(button, canGoBack); michael@0: button = GetDlgItem(hwndDlg, IDC_FORWARD); michael@0: if (button) michael@0: EnableWindow(button, canGoForward); michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: BrowserDlgProc() michael@0: // michael@0: // PURPOSE: Browser dialog windows message handler. michael@0: // michael@0: // COMMENTS: michael@0: // michael@0: // The code for handling buttons and menu actions is here. michael@0: // michael@0: INT_PTR CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) michael@0: { michael@0: // Get the browser and other pointers since they are used a lot below michael@0: HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); michael@0: nsIWebBrowserChrome *chrome = nullptr ; michael@0: if (hwndBrowser) michael@0: { michael@0: chrome = (nsIWebBrowserChrome *) GetWindowLongPtr(hwndBrowser, GWLP_USERDATA); michael@0: } michael@0: nsCOMPtr webBrowser; michael@0: nsCOMPtr webNavigation; michael@0: if (chrome) michael@0: { michael@0: chrome->GetWebBrowser(getter_AddRefs(webBrowser)); michael@0: webNavigation = do_QueryInterface(webBrowser); michael@0: } michael@0: michael@0: // Test the message michael@0: switch (uMsg) michael@0: { michael@0: case WM_INITDIALOG: michael@0: return TRUE; michael@0: michael@0: case WM_INITMENU: michael@0: UpdateUI(chrome); michael@0: return TRUE; michael@0: michael@0: case WM_SYSCOMMAND: michael@0: if (wParam == SC_CLOSE) michael@0: { michael@0: WebBrowserChromeUI::Destroy(chrome); michael@0: return TRUE; michael@0: } michael@0: break; michael@0: michael@0: case WM_DESTROY: michael@0: return TRUE; michael@0: michael@0: case WM_COMMAND: michael@0: if (!webBrowser) michael@0: { michael@0: return TRUE; michael@0: } michael@0: michael@0: // Test which command was selected michael@0: switch (LOWORD(wParam)) michael@0: { michael@0: case IDC_ADDRESS: michael@0: if (HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE) michael@0: { michael@0: // User has changed the address field so enable the Go button michael@0: EnableWindow(GetDlgItem(hwndDlg, IDC_GO), TRUE); michael@0: } michael@0: break; michael@0: michael@0: case IDC_GO: michael@0: { michael@0: TCHAR szURL[2048]; michael@0: memset(szURL, 0, sizeof(szURL)); michael@0: GetDlgItemText(hwndDlg, IDC_ADDRESS, szURL, michael@0: sizeof(szURL) / sizeof(szURL[0]) - 1); michael@0: webNavigation->LoadURI( michael@0: NS_ConvertASCIItoUTF16(szURL).get(), michael@0: nsIWebNavigation::LOAD_FLAGS_NONE, michael@0: nullptr, michael@0: nullptr, michael@0: nullptr); michael@0: } michael@0: break; michael@0: michael@0: case IDC_STOP: michael@0: webNavigation->Stop(nsIWebNavigation::STOP_ALL); michael@0: UpdateUI(chrome); michael@0: break; michael@0: michael@0: case IDC_RELOAD: michael@0: webNavigation->Reload(nsIWebNavigation::LOAD_FLAGS_NONE); michael@0: break; michael@0: michael@0: case IDM_EXIT: michael@0: PostMessage(hwndDlg, WM_SYSCOMMAND, SC_CLOSE, 0); michael@0: break; michael@0: michael@0: // File menu commands michael@0: michael@0: case MOZ_NewBrowser: michael@0: OpenWebPage(gFirstURL); michael@0: break; michael@0: michael@0: // Edit menu commands michael@0: michael@0: case MOZ_Cut: michael@0: { michael@0: nsCOMPtr clipCmds = do_GetInterface(webBrowser); michael@0: clipCmds->CutSelection(); michael@0: } michael@0: break; michael@0: michael@0: case MOZ_Copy: michael@0: { michael@0: nsCOMPtr clipCmds = do_GetInterface(webBrowser); michael@0: clipCmds->CopySelection(); michael@0: } michael@0: break; michael@0: michael@0: case MOZ_Paste: michael@0: { michael@0: nsCOMPtr clipCmds = do_GetInterface(webBrowser); michael@0: clipCmds->Paste(); michael@0: } michael@0: break; michael@0: michael@0: case MOZ_SelectAll: michael@0: { michael@0: nsCOMPtr clipCmds = do_GetInterface(webBrowser); michael@0: clipCmds->SelectAll(); michael@0: } michael@0: break; michael@0: michael@0: case MOZ_SelectNone: michael@0: { michael@0: nsCOMPtr clipCmds = do_GetInterface(webBrowser); michael@0: clipCmds->SelectNone(); michael@0: } michael@0: break; michael@0: michael@0: // Go menu commands michael@0: case IDC_BACK: michael@0: case MOZ_GoBack: michael@0: webNavigation->GoBack(); michael@0: UpdateUI(chrome); michael@0: break; michael@0: michael@0: case IDC_FORWARD: michael@0: case MOZ_GoForward: michael@0: webNavigation->GoForward(); michael@0: UpdateUI(chrome); michael@0: break; michael@0: michael@0: // Help menu commands michael@0: case MOZ_About: michael@0: { michael@0: TCHAR szAboutTitle[MAX_LOADSTRING]; michael@0: TCHAR szAbout[MAX_LOADSTRING]; michael@0: LoadString(ghInstanceApp, IDS_ABOUT_TITLE, szAboutTitle, MAX_LOADSTRING); michael@0: LoadString(ghInstanceApp, IDS_ABOUT, szAbout, MAX_LOADSTRING); michael@0: MessageBox(nullptr, szAbout, szAboutTitle, MB_OK); michael@0: } michael@0: break; michael@0: } michael@0: michael@0: return TRUE; michael@0: michael@0: case WM_ACTIVATE: michael@0: { michael@0: nsCOMPtr focus(do_GetInterface(webBrowser)); michael@0: if(focus) michael@0: { michael@0: switch (wParam) michael@0: { michael@0: case WA_ACTIVE: michael@0: focus->Activate(); michael@0: break; michael@0: case WA_INACTIVE: michael@0: focus->Deactivate(); michael@0: break; michael@0: default: michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: break; michael@0: michael@0: case WM_SIZE: michael@0: { michael@0: UINT newDlgWidth = LOWORD(lParam); michael@0: UINT newDlgHeight = HIWORD(lParam); michael@0: michael@0: // TODO Reposition the control bar - for the moment it's fixed size michael@0: michael@0: // Reposition the status area. Status bar michael@0: // gets any space that the fixed size progress bar doesn't use. michael@0: int progressWidth; michael@0: int statusWidth; michael@0: int statusHeight; michael@0: HWND hwndStatus = GetDlgItem(hwndDlg, IDC_STATUS); michael@0: if (hwndStatus) { michael@0: RECT rcStatus; michael@0: GetWindowRect(hwndStatus, &rcStatus); michael@0: statusHeight = rcStatus.bottom - rcStatus.top; michael@0: } else michael@0: statusHeight = 0; michael@0: michael@0: HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS); michael@0: if (hwndProgress) { michael@0: RECT rcProgress; michael@0: GetWindowRect(hwndProgress, &rcProgress); michael@0: progressWidth = rcProgress.right - rcProgress.left; michael@0: } else michael@0: progressWidth = 0; michael@0: statusWidth = newDlgWidth - progressWidth; michael@0: michael@0: if (hwndStatus) michael@0: SetWindowPos(hwndStatus, michael@0: HWND_TOP, michael@0: 0, newDlgHeight - statusHeight, michael@0: statusWidth, michael@0: statusHeight, michael@0: SWP_NOZORDER); michael@0: if (hwndProgress) michael@0: SetWindowPos(hwndProgress, michael@0: HWND_TOP, michael@0: statusWidth, newDlgHeight - statusHeight, michael@0: 0, 0, michael@0: SWP_NOSIZE | SWP_NOZORDER); michael@0: michael@0: // Resize the browser area (assuming the browse is michael@0: // sandwiched between the control bar and status area) michael@0: RECT rcBrowser; michael@0: POINT ptBrowser; michael@0: GetWindowRect(hwndBrowser, &rcBrowser); michael@0: ptBrowser.x = rcBrowser.left; michael@0: ptBrowser.y = rcBrowser.top; michael@0: ScreenToClient(hwndDlg, &ptBrowser); michael@0: int browserHeight = newDlgHeight - ptBrowser.y - statusHeight; michael@0: if (browserHeight < 1) michael@0: { michael@0: browserHeight = 1; michael@0: } michael@0: SetWindowPos(hwndBrowser, michael@0: HWND_TOP, michael@0: 0, 0, michael@0: newDlgWidth, michael@0: newDlgHeight - ptBrowser.y - statusHeight, michael@0: SWP_NOMOVE | SWP_NOZORDER); michael@0: } michael@0: return TRUE; michael@0: } michael@0: return FALSE; michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: BrowserWndProc(HWND, UINT, WRAPAM, LPARAM) michael@0: // michael@0: // PURPOSE: Processes messages for the browser container window. michael@0: // michael@0: LRESULT CALLBACK BrowserWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) michael@0: { michael@0: nsIWebBrowserChrome *chrome = (nsIWebBrowserChrome *) GetWindowLongPtr(hWnd, GWLP_USERDATA); michael@0: switch (message) michael@0: { michael@0: case WM_SIZE: michael@0: // Resize the embedded browser michael@0: ResizeEmbedding(chrome); michael@0: return 0; michael@0: case WM_ERASEBKGND: michael@0: // Reduce flicker by not painting the non-visible background michael@0: return 1; michael@0: } michael@0: return DefWindowProc(hWnd, message, wParam, lParam); michael@0: } michael@0: michael@0: // michael@0: // FUNCTION: StartupProfile() michael@0: // michael@0: // PURPOSE: michael@0: // michael@0: nsresult StartupProfile() michael@0: { michael@0: michael@0: nsCOMPtr appDataDir; michael@0: nsresult rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR, getter_AddRefs(appDataDir)); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: appDataDir->AppendNative(nsCString("winembed")); michael@0: michael@0: nsCOMPtr locProvider; michael@0: NS_NewProfileDirServiceProvider(true, getter_AddRefs(locProvider)); michael@0: if (!locProvider) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: rv = locProvider->Register(); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: return locProvider->SetProfileDir(appDataDir); michael@0: michael@0: } michael@0: michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: // WebBrowserChromeUI michael@0: michael@0: // michael@0: // FUNCTION: CreateNativeWindow() michael@0: // michael@0: // PURPOSE: Creates a new browser dialog. michael@0: // michael@0: // COMMENTS: michael@0: // michael@0: // This function loads the browser dialog from a resource template michael@0: // and returns the HWND for the webbrowser container dialog item michael@0: // to the caller. michael@0: // michael@0: HWND WebBrowserChromeUI::CreateNativeWindow(nsIWebBrowserChrome* chrome) michael@0: { michael@0: // Load the browser dialog from resource michael@0: HWND hwndDialog; michael@0: uint32_t chromeFlags; michael@0: michael@0: chrome->GetChromeFlags(&chromeFlags); michael@0: if ((chromeFlags & nsIWebBrowserChrome::CHROME_ALL) == nsIWebBrowserChrome::CHROME_ALL) michael@0: hwndDialog = CreateDialog(ghInstanceApp, michael@0: MAKEINTRESOURCE(IDD_BROWSER), michael@0: nullptr, michael@0: BrowserDlgProc); michael@0: else michael@0: hwndDialog = CreateDialog(ghInstanceApp, michael@0: MAKEINTRESOURCE(IDD_BROWSER_NC), michael@0: nullptr, michael@0: BrowserDlgProc); michael@0: if (!hwndDialog) michael@0: return nullptr; michael@0: michael@0: // Stick a menu onto it michael@0: if (chromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR) { michael@0: HMENU hmenuDlg = LoadMenu(ghInstanceApp, MAKEINTRESOURCE(IDC_WINEMBED)); michael@0: SetMenu(hwndDialog, hmenuDlg); michael@0: } else michael@0: SetMenu(hwndDialog, 0); michael@0: michael@0: // Add some interesting URLs to the address drop down michael@0: HWND hwndAddress = GetDlgItem(hwndDialog, IDC_ADDRESS); michael@0: if (hwndAddress) { michael@0: for (int i = 0; i < sizeof(gDefaultURLs) / sizeof(gDefaultURLs[0]); i++) michael@0: { michael@0: SendMessage(hwndAddress, CB_ADDSTRING, 0, (LPARAM) gDefaultURLs[i]); michael@0: } michael@0: } michael@0: michael@0: // Fetch the browser window handle michael@0: HWND hwndBrowser = GetDlgItem(hwndDialog, IDC_BROWSER); michael@0: SetWindowLongPtr(hwndBrowser, GWLP_USERDATA, (LONG_PTR)chrome); // save the browser LONG_PTR. michael@0: SetWindowLongPtr(hwndBrowser, GWL_STYLE, GetWindowLongPtr(hwndBrowser, GWL_STYLE) | WS_CLIPCHILDREN); michael@0: michael@0: // Activate the window michael@0: PostMessage(hwndDialog, WM_ACTIVATE, WA_ACTIVE, 0); michael@0: michael@0: gDialogCount++; michael@0: michael@0: return hwndBrowser; michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: Destroy() michael@0: // michael@0: // PURPOSE: Destroy the window specified by the chrome michael@0: // michael@0: void WebBrowserChromeUI::Destroy(nsIWebBrowserChrome* chrome) michael@0: { michael@0: nsCOMPtr webBrowser; michael@0: nsCOMPtr webNavigation; michael@0: michael@0: chrome->GetWebBrowser(getter_AddRefs(webBrowser)); michael@0: webNavigation = do_QueryInterface(webBrowser); michael@0: if (webNavigation) michael@0: webNavigation->Stop(nsIWebNavigation::STOP_ALL); michael@0: michael@0: chrome->ExitModalEventLoop(NS_OK); michael@0: michael@0: HWND hwndDlg = GetBrowserDlgFromChrome(chrome); michael@0: if (hwndDlg == nullptr) michael@0: return; michael@0: michael@0: // Explicitly destroy the embedded browser and then the chrome michael@0: michael@0: // First the browser michael@0: nsCOMPtr browser = nullptr; michael@0: chrome->GetWebBrowser(getter_AddRefs(browser)); michael@0: nsCOMPtr browserAsWin = do_QueryInterface(browser); michael@0: if (browserAsWin) michael@0: browserAsWin->Destroy(); michael@0: michael@0: // Now the chrome michael@0: chrome->SetWebBrowser(nullptr); michael@0: NS_RELEASE(chrome); michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: Called as the final act of a chrome object during its destructor michael@0: // michael@0: void WebBrowserChromeUI::Destroyed(nsIWebBrowserChrome* chrome) michael@0: { michael@0: HWND hwndDlg = GetBrowserDlgFromChrome(chrome); michael@0: if (hwndDlg == nullptr) michael@0: { michael@0: return; michael@0: } michael@0: michael@0: // Clear the window user data michael@0: HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); michael@0: SetWindowLongPtr(hwndBrowser, GWLP_USERDATA, 0); michael@0: DestroyWindow(hwndBrowser); michael@0: DestroyWindow(hwndDlg); michael@0: michael@0: --gDialogCount; michael@0: if (gDialogCount == 0) michael@0: { michael@0: // Quit when there are no more browser objects michael@0: PostQuitMessage(0); michael@0: } michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: Set the input focus onto the browser window michael@0: // michael@0: void WebBrowserChromeUI::SetFocus(nsIWebBrowserChrome *chrome) michael@0: { michael@0: HWND hwndDlg = GetBrowserDlgFromChrome(chrome); michael@0: if (hwndDlg == nullptr) michael@0: { michael@0: return; michael@0: } michael@0: michael@0: HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); michael@0: ::SetFocus(hwndBrowser); michael@0: } michael@0: michael@0: // michael@0: // FUNCTION: UpdateStatusBarText() michael@0: // michael@0: // PURPOSE: Set the status bar text. michael@0: // michael@0: void WebBrowserChromeUI::UpdateStatusBarText(nsIWebBrowserChrome *aChrome, const char16_t* aStatusText) michael@0: { michael@0: HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); michael@0: nsCString status; michael@0: if (aStatusText) { michael@0: nsString wStatusText(aStatusText); michael@0: NS_UTF16ToCString(wStatusText, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM, michael@0: status); michael@0: } michael@0: michael@0: SetDlgItemText(hwndDlg, IDC_STATUS, status.get()); michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: UpdateCurrentURI() michael@0: // michael@0: // PURPOSE: Updates the URL address field michael@0: // michael@0: void WebBrowserChromeUI::UpdateCurrentURI(nsIWebBrowserChrome *aChrome) michael@0: { michael@0: nsCOMPtr webBrowser; michael@0: nsCOMPtr webNavigation; michael@0: aChrome->GetWebBrowser(getter_AddRefs(webBrowser)); michael@0: webNavigation = do_QueryInterface(webBrowser); michael@0: michael@0: nsCOMPtr currentURI; michael@0: webNavigation->GetCurrentURI(getter_AddRefs(currentURI)); michael@0: if (currentURI) michael@0: { michael@0: nsCString uriString; michael@0: currentURI->GetAsciiSpec(uriString); michael@0: HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); michael@0: SetDlgItemText(hwndDlg, IDC_ADDRESS, uriString.get()); michael@0: } michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: UpdateBusyState() michael@0: // michael@0: // PURPOSE: Refreshes the stop/go buttons in the browser dialog michael@0: // michael@0: void WebBrowserChromeUI::UpdateBusyState(nsIWebBrowserChrome *aChrome, bool aBusy) michael@0: { michael@0: HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); michael@0: HWND button; michael@0: button = GetDlgItem(hwndDlg, IDC_STOP); michael@0: if (button) michael@0: EnableWindow(button, aBusy); michael@0: button = GetDlgItem(hwndDlg, IDC_GO); michael@0: if (button) michael@0: EnableWindow(button, !aBusy); michael@0: UpdateUI(aChrome); michael@0: } michael@0: michael@0: michael@0: // michael@0: // FUNCTION: UpdateProgress() michael@0: // michael@0: // PURPOSE: Refreshes the progress bar in the browser dialog michael@0: // michael@0: void WebBrowserChromeUI::UpdateProgress(nsIWebBrowserChrome *aChrome, int32_t aCurrent, int32_t aMax) michael@0: { michael@0: HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); michael@0: HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS); michael@0: if (aCurrent < 0) michael@0: { michael@0: aCurrent = 0; michael@0: } michael@0: if (aCurrent > aMax) michael@0: { michael@0: aMax = aCurrent + 20; // What to do? michael@0: } michael@0: if (hwndProgress) michael@0: { michael@0: SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, aMax)); michael@0: SendMessage(hwndProgress, PBM_SETPOS, aCurrent, 0); michael@0: } michael@0: } michael@0: michael@0: // michael@0: // FUNCTION: ShowContextMenu() michael@0: // michael@0: // PURPOSE: Display a context menu for the given node michael@0: // michael@0: void WebBrowserChromeUI::ShowContextMenu(nsIWebBrowserChrome *aChrome, uint32_t aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode) michael@0: { michael@0: // TODO code to test context flags and display a popup menu should go here michael@0: } michael@0: michael@0: // michael@0: // FUNCTION: ShowTooltip() michael@0: // michael@0: // PURPOSE: Show a tooltip michael@0: // michael@0: void WebBrowserChromeUI::ShowTooltip(nsIWebBrowserChrome *aChrome, int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText) michael@0: { michael@0: // TODO code to show a tooltip should go here michael@0: } michael@0: michael@0: // michael@0: // FUNCTION: HideTooltip() michael@0: // michael@0: // PURPOSE: Hide the tooltip michael@0: // michael@0: void WebBrowserChromeUI::HideTooltip(nsIWebBrowserChrome *aChrome) michael@0: { michael@0: // TODO code to hide a tooltip should go here michael@0: } michael@0: michael@0: void WebBrowserChromeUI::ShowWindow(nsIWebBrowserChrome *aChrome, bool aShow) michael@0: { michael@0: HWND win = GetBrowserDlgFromChrome(aChrome); michael@0: ::ShowWindow(win, aShow ? SW_RESTORE : SW_HIDE); michael@0: } michael@0: michael@0: void WebBrowserChromeUI::SizeTo(nsIWebBrowserChrome *aChrome, int32_t aWidth, int32_t aHeight) michael@0: { michael@0: HWND hchrome = GetBrowserDlgFromChrome(aChrome); michael@0: HWND hbrowser = GetBrowserFromChrome(aChrome); michael@0: RECT chromeRect, browserRect; michael@0: michael@0: ::GetWindowRect(hchrome, &chromeRect); michael@0: ::GetWindowRect(hbrowser, &browserRect); michael@0: michael@0: int32_t decoration_x = (browserRect.left - chromeRect.left) + michael@0: (chromeRect.right - browserRect.right); michael@0: int32_t decoration_y = (browserRect.top - chromeRect.top) + michael@0: (chromeRect.bottom - browserRect.bottom); michael@0: michael@0: ::MoveWindow(hchrome, chromeRect.left, chromeRect.top, michael@0: aWidth+decoration_x, michael@0: aHeight+decoration_y, TRUE); michael@0: } michael@0: michael@0: // michael@0: // FUNCTION: GetResourceStringByID() michael@0: // michael@0: // PURPOSE: Get the resource string for the ID michael@0: // michael@0: void WebBrowserChromeUI::GetResourceStringById(int32_t aID, char ** aReturn) michael@0: { michael@0: char resBuf[MAX_LOADSTRING]; michael@0: int retval = LoadString( ghInstanceApp, aID, (LPTSTR)resBuf, sizeof(resBuf) ); michael@0: if (retval != 0) michael@0: { michael@0: size_t resLen = strlen(resBuf); michael@0: *aReturn = (char *)calloc(resLen+1, sizeof(char *)); michael@0: if (!*aReturn) return; michael@0: strncpy(*aReturn, resBuf, resLen); michael@0: } michael@0: return; michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: // AppCallbacks michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: nsresult AppCallbacks::CreateBrowserWindow(uint32_t aChromeFlags, michael@0: nsIWebBrowserChrome *aParent, michael@0: nsIWebBrowserChrome **aNewWindow) michael@0: { michael@0: WebBrowserChrome * chrome = new WebBrowserChrome(); michael@0: if (!chrome) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: // the interface to return and one addref, which we assume will be michael@0: // immediately released michael@0: *aNewWindow = static_cast(chrome); michael@0: // now an extra addref; the window owns itself (to be released by michael@0: // WebBrowserChromeUI::Destroy) michael@0: NS_ADDREF(*aNewWindow); michael@0: michael@0: chrome->SetChromeFlags(aChromeFlags); michael@0: chrome->SetParent(aParent); michael@0: michael@0: // Insert the browser michael@0: nsCOMPtr newBrowser; michael@0: chrome->CreateBrowser(-1, -1, -1, -1, getter_AddRefs(newBrowser)); michael@0: if (!newBrowser) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: // Place it where we want it. michael@0: ResizeEmbedding(static_cast(chrome)); michael@0: michael@0: // if opened as chrome, it'll be made visible after the chrome has loaded. michael@0: // otherwise, go ahead and show it now. michael@0: if (!(aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) michael@0: WebBrowserChromeUI::ShowWindow(*aNewWindow, true); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void AppCallbacks::EnableChromeWindow(nsIWebBrowserChrome *aWindow, michael@0: bool aEnabled) michael@0: { michael@0: HWND hwnd = GetBrowserDlgFromChrome(aWindow); michael@0: ::EnableWindow(hwnd, aEnabled ? TRUE : FALSE); michael@0: } michael@0: michael@0: uint32_t AppCallbacks::RunEventLoop(bool &aRunCondition) michael@0: { michael@0: MSG msg; michael@0: HANDLE hFakeEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); michael@0: michael@0: while (aRunCondition ) { michael@0: // Process pending messages michael@0: while (::PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) { michael@0: if (!::GetMessage(&msg, nullptr, 0, 0)) { michael@0: // WM_QUIT michael@0: aRunCondition = false; michael@0: break; michael@0: } michael@0: michael@0: ::TranslateMessage(&msg); michael@0: ::DispatchMessage(&msg); michael@0: } michael@0: michael@0: // Do idle stuff michael@0: ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 100, QS_ALLEVENTS); michael@0: } michael@0: ::CloseHandle(hFakeEvent); michael@0: return (uint32_t)msg.wParam; michael@0: }