mirror of https://github.com/roytam1/kmeleon.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
956 lines
29 KiB
956 lines
29 KiB
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
/* ***** BEGIN LICENSE BLOCK ***** |
|
* Version: Mozilla-sample-code 1.0 |
|
* |
|
* Copyright (c) 2002 Netscape Communications Corporation and |
|
* other contributors |
|
* |
|
* Permission is hereby granted, free of charge, to any person obtaining a |
|
* copy of this Mozilla sample software and associated documentation files |
|
* (the "Software"), to deal in the Software without restriction, including |
|
* without limitation the rights to use, copy, modify, merge, publish, |
|
* distribute, sublicense, and/or sell copies of the Software, and to permit |
|
* persons to whom the Software is furnished to do so, subject to the |
|
* following conditions: |
|
* |
|
* The above copyright notice and this permission notice shall be included |
|
* in all copies or substantial portions of the Software. |
|
* |
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
* DEALINGS IN THE SOFTWARE. |
|
* |
|
* Contributor(s): |
|
* Chak Nanga <chak@netscape.com> |
|
* |
|
* ***** END LICENSE BLOCK ***** */ |
|
|
|
// File Overview.... |
|
// |
|
// This file has the IBrowserFrameGlueObj implementation |
|
// This frame glue object is nested inside of the BrowserFrame |
|
// object(See BrowserFrm.h for more info) |
|
// |
|
// This is the place where all the platform specific interaction |
|
// with the browser frame window takes place in response to |
|
// callbacks from Gecko interface methods |
|
// |
|
// The main purpose of this interface is to separate the cross |
|
// platform code in BrowserImpl*.cpp from the platform specific |
|
// code(which is in this file) |
|
// |
|
// You'll also notice the use of a macro named "METHOD_PROLOGUE" |
|
// through out this file. This macro essentially makes the pointer |
|
// to a "containing" class available inside of the class which is |
|
// being contained via a var named "pThis". In our case, the |
|
// BrowserFrameGlue object is contained inside of the BrowserFrame |
|
// object so "pThis" will be a pointer to a BrowserFrame object |
|
// Refer to MFC docs for more info on METHOD_PROLOGUE macro |
|
|
|
|
|
#include "stdafx.h" |
|
#include "MfcEmbed.h" |
|
#include "BrowserFrm.h" |
|
#include "Dialogs.h" |
|
#include "MenuParser.h" |
|
#include "KmeleonConst.h" |
|
#include "nsIDOMHTMLAreaElement.h" |
|
#include "nsIDOMHTMLInputElement.h" |
|
|
|
extern CMfcEmbedApp theApp; |
|
extern nsresult NewURI(nsIURI **result, const nsACString &spec); |
|
|
|
///////////////////////////////////////////////////////////////////////////// |
|
// IBrowserFrameGlue implementation |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::UpdateStatusBarText(const PRUnichar *aMessage) |
|
{ |
|
#ifndef _UNICODE |
|
if (aMessage && (wcslen(aMessage) > 1024)) return; |
|
#endif |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
USES_CONVERSION; |
|
CString str; |
|
if (aMessage && wcslen(aMessage) > 0) |
|
str = W2CT(aMessage); |
|
else |
|
str.LoadString(AFX_IDS_IDLEMESSAGE); |
|
|
|
pThis->m_wndStatusBar.SetPaneText(0, str); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::UpdateProgress(PRInt32 aCurrent, PRInt32 aMax) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
pThis->m_wndProgressBar.SetRange32(0, aMax); |
|
pThis->m_wndProgressBar.SetPos(aCurrent); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::UpdateBusyState(PRBool aBusy) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
// Just notify the view of the busy state |
|
// There's code in there which will take care of |
|
// updating the STOP toolbar btn. etc |
|
|
|
pThis->m_wndBrowserView.UpdateBusyState(aBusy); |
|
//if (!aBusy) |
|
pThis->PostMessage(UWM_UPDATEBUSYSTATE, aBusy == PR_TRUE ? 1 : 0, pThis->m_wndBrowserView.m_hWnd); |
|
|
|
if (!aBusy) { |
|
CString szUrl; |
|
pThis->m_wndUrlBar.GetEnteredURL(szUrl); |
|
if (_tcscmp(szUrl, _T("about:blank"))==0) |
|
pThis->m_wndUrlBar.MaintainFocus(); |
|
|
|
// XXX We have to resize XUL dialog manually. They should have they own |
|
// glue and window object! |
|
if (pThis->m_bSizeOnLoad) { |
|
nsCOMPtr<nsIDOMWindow> domWindow; |
|
pThis->m_wndBrowserView.mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); |
|
if (domWindow) |
|
domWindow->SizeToContent(); |
|
|
|
// It must be repositionned somewhat after the resize. Centering it |
|
// all the time is not that bad. |
|
//if (pThis->m_chromeMask & nsIWebBrowserChrome::CHROME_CENTER_SCREEN) |
|
pThis->CenterWindow(); |
|
|
|
pThis->ShowWindow(SW_SHOW); |
|
pThis->UpdateWindow(); |
|
pThis->m_bSizeOnLoad = FALSE; |
|
} |
|
} |
|
else |
|
pThis->m_wndBrowserView.mbDOMLoaded = FALSE; |
|
|
|
pThis->m_wndBrowserView.m_lastMouseActionNode = nsnull; |
|
} |
|
|
|
// Called from the OnLocationChange() method in the nsIWebProgressListener |
|
// interface implementation in CBrowserImpl to update the current URI |
|
// Will get called after a URI is successfully loaded in the browser |
|
// We use this info to update the URL bar's edit box |
|
// |
|
void CBrowserFrame::BrowserFrameGlueObj::UpdateCurrentURI(nsIURI *aLocation) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
if(aLocation) |
|
{ |
|
USES_CONVERSION; |
|
nsEmbedCString uriString; |
|
aLocation->GetSpec(uriString); |
|
|
|
nsEmbedString uriString2; |
|
NS_CStringToUTF16(uriString, NS_CSTRING_ENCODING_UTF8, uriString2); |
|
|
|
// Reset the popup notification and the icon uri |
|
if (!(pThis->m_wndBrowserView.m_csHostPopupBlocked.IsEmpty())) { |
|
pThis->m_wndStatusBar.RemoveIcon(ID_POPUP_BLOCKED_ICON); |
|
pThis->m_wndBrowserView.m_csHostPopupBlocked.Empty(); |
|
} |
|
#ifdef INTERNAL_SITEICONS |
|
// Must be done here, before testing if we have the same address |
|
// because xul error page have its own icon, and since the address |
|
// doesn't change when retrying, the icon may stay in the urlbar. |
|
pThis->m_wndBrowserView.m_IconUri = nsnull; |
|
#endif |
|
|
|
// Prevent to move the caret in the urlbar |
|
CString currentURL; |
|
pThis->m_wndUrlBar.GetEnteredURL(currentURL); |
|
if (currentURL.Compare(W2CT(uriString2.get())) == 0) |
|
return; |
|
|
|
// XXX Since Mozilla 1.8.0.2 about:blank is always passed here |
|
// before anything else, broking stuffs, so ignore it! |
|
if ( stricmp (uriString.get(), "about:blank") == 0 && |
|
currentURL.GetLength()) |
|
return; |
|
|
|
pThis->m_wndUrlBar.SetCurrentURL(W2CT(uriString2.get())); |
|
|
|
// Add a MRU entry. Note that I'm only only allowing |
|
// http or https uri |
|
|
|
PRBool allowMRU,b; |
|
aLocation->SchemeIs("http", &b); |
|
allowMRU = b; |
|
aLocation->SchemeIs("https", &b); |
|
allowMRU |= b; |
|
|
|
if ( allowMRU ) { |
|
if (theApp.preferences.MRUbehavior == 0){ |
|
nsEmbedCString password; |
|
aLocation->GetUsername(password); |
|
aLocation->SetUserPass(password); |
|
aLocation->GetSpec(uriString); |
|
theApp.m_MRUList->AddURL(A2CT(uriString.get())); |
|
} |
|
else if (theApp.preferences.MRUbehavior == 1){ |
|
nsEmbedCString nsScheme, nsHost; |
|
aLocation->GetScheme(nsScheme); |
|
aLocation->GetHost(nsHost); |
|
nsHost.Insert("://",0); |
|
nsHost.Insert(nsScheme,0); |
|
theApp.m_MRUList->AddURL(A2CT(nsHost.get())); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::GetBrowserFrameTitle(PRUnichar **aTitle) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
CString title; |
|
pThis->GetWindowText(title); |
|
|
|
/* TCHAR psz[256]; |
|
CString appTitle; |
|
appTitle.LoadString(AFX_IDS_APP_TITLE); |
|
theApp.preferences.GetString("kmeleon.display.title", psz, appTitle.GetBuffer(0)); |
|
appTitle = psz; |
|
|
|
title.Replace(_T(" (") + appTitle + _T(')'), _T("")); |
|
*/ |
|
if(!title.IsEmpty()) |
|
{ |
|
USES_CONVERSION; |
|
nsEmbedString nsTitle; |
|
nsTitle.Assign(T2CW(title)); |
|
*aTitle = NS_StringCloneData(nsTitle); |
|
} |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::SetBrowserFrameTitle(const PRUnichar *aTitle) |
|
{ |
|
#ifndef _UNICODE |
|
if (wcslen(aTitle) > 1024) return; |
|
#endif |
|
|
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
TCHAR psz[256]; |
|
CString appTitle; |
|
appTitle.LoadString(AFX_IDS_APP_TITLE); |
|
theApp.preferences.GetString("kmeleon.display.title", psz, appTitle.GetBuffer(0)); |
|
appTitle = psz; |
|
|
|
CString title; |
|
USES_CONVERSION; |
|
title = W2CT(aTitle); |
|
|
|
if (title.IsEmpty()){ |
|
pThis->m_wndUrlBar.GetEnteredURL(title); |
|
} |
|
|
|
if (!appTitle.IsEmpty()) |
|
title += _T(" (") + appTitle + _T(")"); |
|
pThis->SetWindowText(title); |
|
|
|
pThis->PostMessage(UWM_UPDATESESSIONHISTORY, 0, 0); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::SetBrowserFrameSize(PRInt32 aCX, PRInt32 aCY) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
if (pThis->m_ignoreMoveResize > 0) { |
|
pThis->m_ignoreMoveResize--; |
|
return; |
|
} |
|
|
|
WINDOWPLACEMENT wp; |
|
wp.length = sizeof(WINDOWPLACEMENT); |
|
pThis->GetWindowPlacement(&wp); |
|
if (wp.showCmd != SW_SHOWNORMAL) |
|
return; |
|
|
|
pThis->SetWindowPos(NULL, 0, 0, aCX, aCY, |
|
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER |
|
); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::SetBrowserSize(PRInt32 aCX, PRInt32 aCY) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
if (pThis->m_ignoreMoveResize > 0) { |
|
pThis->m_ignoreMoveResize--; |
|
return; |
|
} |
|
|
|
WINDOWPLACEMENT wp; |
|
wp.length = sizeof(WINDOWPLACEMENT); |
|
pThis->GetWindowPlacement(&wp); |
|
if (wp.showCmd != SW_SHOWNORMAL) |
|
return; |
|
|
|
// first we have to figure out how much bigger the frame is than the view |
|
RECT frameRect, viewRect; |
|
pThis->GetWindowRect(&frameRect); |
|
pThis->m_wndBrowserView.GetClientRect(&viewRect); |
|
|
|
int deltax = (frameRect.right - frameRect.left - viewRect.right); |
|
int deltay = (frameRect.bottom - frameRect.top - viewRect.bottom); |
|
|
|
pThis->SetWindowPos(NULL, 0, 0, aCX+deltax, aCY+deltay, |
|
SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER |
|
); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::GetBrowserFrameSize(PRInt32 *aCX, PRInt32 *aCY) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
RECT wndRect; |
|
pThis->GetWindowRect(&wndRect); |
|
|
|
if (aCX) |
|
*aCX = wndRect.right - wndRect.left; |
|
|
|
if (aCY) |
|
*aCY = wndRect.bottom - wndRect.top; |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::GetBrowserSize(PRInt32 *aCX, PRInt32 *aCY) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
RECT wndRect; |
|
pThis->m_wndBrowserView.GetClientRect(&wndRect); |
|
|
|
if (aCX) |
|
*aCX = wndRect.right - wndRect.left; |
|
|
|
if (aCY) |
|
*aCY = wndRect.bottom - wndRect.top; |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::SetBrowserFramePosition(PRInt32 aX, PRInt32 aY) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
if (pThis->m_ignoreMoveResize > 0) { |
|
pThis->m_ignoreMoveResize--; |
|
return; |
|
} |
|
|
|
WINDOWPLACEMENT wp; |
|
wp.length = sizeof(WINDOWPLACEMENT); |
|
pThis->GetWindowPlacement(&wp); |
|
if (wp.showCmd != SW_SHOWNORMAL) |
|
return; |
|
|
|
pThis->SetWindowPos(NULL, aX, aY, 0, 0, |
|
SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::GetBrowserFramePosition(PRInt32 *aX, PRInt32 *aY) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
RECT wndRect; |
|
pThis->GetWindowRect(&wndRect); |
|
|
|
if (aX) |
|
*aX = wndRect.left; |
|
|
|
if (aY) |
|
*aY = wndRect.top; |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::GetBrowserFramePositionAndSize(PRInt32 *aX, PRInt32 *aY, PRInt32 *aCX, PRInt32 *aCY) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
RECT wndRect; |
|
pThis->GetWindowRect(&wndRect); |
|
|
|
if (aX) |
|
*aX = wndRect.left; |
|
|
|
if (aY) |
|
*aY = wndRect.top; |
|
|
|
if (aCX) |
|
*aCX = wndRect.right - wndRect.left; |
|
|
|
if (aCY) |
|
*aCY = wndRect.bottom - wndRect.top; |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::SetBrowserFramePositionAndSize(PRInt32 aX, PRInt32 aY, PRInt32 aCX, PRInt32 aCY, PRBool fRepaint) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
if (pThis->m_ignoreMoveResize > 0) { |
|
pThis->m_ignoreMoveResize--; |
|
return; |
|
} |
|
|
|
WINDOWPLACEMENT wp; |
|
wp.length = sizeof(WINDOWPLACEMENT); |
|
pThis->GetWindowPlacement(&wp); |
|
if (wp.showCmd != SW_SHOWNORMAL) |
|
return; |
|
|
|
pThis->SetWindowPos(NULL, aX, aY, aCX, aCY, |
|
SWP_NOACTIVATE | SWP_NOZORDER); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::SetBrowserPositionAndSize(PRInt32 aX, PRInt32 aY, PRInt32 aCX, PRInt32 aCY, PRBool fRepaint) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
if (pThis->m_ignoreMoveResize > 0) { |
|
pThis->m_ignoreMoveResize--; |
|
return; |
|
} |
|
|
|
WINDOWPLACEMENT wp; |
|
wp.length = sizeof(WINDOWPLACEMENT); |
|
pThis->GetWindowPlacement(&wp); |
|
if (wp.showCmd != SW_SHOWNORMAL) |
|
return; |
|
|
|
// first we have to figure out how much bigger the frame is than the view |
|
RECT frameRect, viewRect; |
|
pThis->GetWindowRect(&frameRect); |
|
pThis->m_wndBrowserView.GetClientRect(&viewRect); |
|
|
|
int deltax = (frameRect.right-frameRect.left)-(viewRect.right-viewRect.left); |
|
int deltay = (frameRect.bottom-frameRect.top)-(viewRect.bottom-viewRect.top); |
|
|
|
pThis->SetWindowPos(NULL, aX, aY, aCX+deltax, aCY+(deltay/2), |
|
SWP_NOACTIVATE | SWP_NOZORDER); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::SetFocus(){ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
//if (!::IsChild(pThis->m_hWnd,::GetFocus())) |
|
// pThis->BringWindowToTop(); |
|
|
|
pThis->m_wndBrowserView.mBaseWindow->SetFocus(); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::FocusAvailable(PRBool *aFocusAvail) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
HWND focusWnd = ::GetFocus(); // GetFocus()->m_hWnd; |
|
|
|
if ((focusWnd == pThis->m_hWnd) || ::IsChild(pThis->m_hWnd, focusWnd)) |
|
*aFocusAvail = PR_TRUE; |
|
else |
|
*aFocusAvail = PR_FALSE; |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::ShowBrowserFrame(PRBool aShow) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
if(aShow) |
|
{ |
|
if (pThis->m_bSizeOnLoad) |
|
return; // Not yet, waiting for resize in UpdateBusyState |
|
|
|
if (pThis->IsIconic()) |
|
return; |
|
|
|
if (!pThis->IsWindowVisible()) { |
|
if (pThis->m_created) |
|
return; |
|
pThis->m_created = true; |
|
} |
|
|
|
pThis->ShowWindow(SW_SHOW); |
|
// pThis->SetActiveWindow(); |
|
pThis->UpdateWindow(); |
|
} |
|
else |
|
{ |
|
pThis->ShowWindow(SW_HIDE); |
|
} |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::GetBrowserFrameVisibility(PRBool *aVisible) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
/*// Is the current BrowserFrame the active one? |
|
CWnd *pWnd = GetActiveWindow(); |
|
if (!pWnd || pWnd->m_hWnd != pThis->m_hWnd) |
|
{ |
|
*aVisible = PR_FALSE; |
|
return; |
|
}*/ |
|
|
|
*aVisible = pThis->IsIconic() || !pThis->IsWindowVisible() ? PR_FALSE : PR_TRUE; |
|
} |
|
|
|
PRBool CBrowserFrame::BrowserFrameGlueObj::CreateNewBrowserFrame(PRUint32 chromeMask, |
|
PRInt32 x, PRInt32 y, |
|
PRInt32 cx, PRInt32 cy, |
|
nsIWebBrowser** aWebBrowser) |
|
{ |
|
NS_ENSURE_ARG_POINTER(aWebBrowser); |
|
|
|
*aWebBrowser = nsnull; |
|
|
|
CMfcEmbedApp *pApp = (CMfcEmbedApp *)AfxGetApp(); |
|
if(!pApp) |
|
return PR_FALSE; |
|
|
|
// Note that we're calling with the last param set to "false" i.e. |
|
// this instructs not to show the frame window |
|
// This is mainly needed when the window size is specified in the window.open() |
|
// JS call. In those cases Gecko calls us to create the browser with a default |
|
// size (all are -1) and then it calls the SizeBrowserTo() method to set |
|
// the proper window size. If this window were to be visible then you'll see |
|
// the window size changes on the screen causing an unappealing flicker |
|
// |
|
|
|
CBrowserFrame* pFrm = pApp->CreateNewBrowserFrame(chromeMask, x, y, cx, cy, PR_FALSE); |
|
if(!pFrm) |
|
return PR_FALSE; |
|
|
|
// At this stage we have a new CBrowserFrame and a new CBrowserView |
|
// objects. The CBrowserView also would have an embedded browser |
|
// object created. Get the mWebBrowser member from the CBrowserView |
|
// and return it. (See CBrowserView's CreateBrowser() on how the |
|
// embedded browser gets created and how it's mWebBrowser member |
|
// gets initialized) |
|
|
|
NS_IF_ADDREF(*aWebBrowser = pFrm->m_wndBrowserView.mWebBrowser); |
|
|
|
return PR_TRUE; |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::DestroyBrowserFrame() |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
pThis->PostMessage(WM_CLOSE, -1, -1); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::ShowContextMenu(PRUint32 aContextFlags, nsIContextMenuInfo *aInfo) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
int nodeHack = pThis->m_wndBrowserView.m_iGetNodeHack; |
|
pThis->m_wndBrowserView.m_iGetNodeHack = 0; |
|
|
|
// No context menu for chrome |
|
if (pThis->m_chromeMask & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) |
|
return; |
|
|
|
BOOL bContentHasFrames = FALSE; |
|
UINT nIDResource = IDR_CTXMENU_DOCUMENT; |
|
|
|
if (nodeHack == 0) { |
|
if (GetKeyState(VK_SHIFT) < 0 || |
|
GetKeyState(VK_CONTROL) < 0 || |
|
GetKeyState(VK_MENU) < 0) |
|
return; |
|
} |
|
|
|
// Reset the values from the last invocation |
|
// Clear image src & link url |
|
nsEmbedString empty; |
|
pThis->m_wndBrowserView.SetCtxMenuImageSrc(empty); |
|
pThis->m_wndBrowserView.SetCtxMenuLinkUrl(empty); |
|
pThis->m_wndBrowserView.SetCurrentFrameURL(empty); |
|
|
|
|
|
/* |
|
!!BAD HACK!! !!BAD HACK!! !!BAD HACK!! !!BAD HACK!! !!BAD HACK!! |
|
|
|
The bGetElementHack flag is part of the GetElementFromPoint function. |
|
Basically, there's no easy way that I've found to get the link |
|
information by point from mozilla, so as a workaround, the function |
|
simply sends a contextmenu notifier with the point we want. It's |
|
our job here to make sure the context menu doesn't get shown. |
|
|
|
!!BAD HACK!! !!BAD HACK!! !!BAD HACK!! !!BAD HACK!! !!BAD HACK!! |
|
*/ |
|
|
|
nsCOMPtr<nsIDOMNode> node; |
|
nsresult rv = aInfo->GetTargetNode(getter_AddRefs(node)); |
|
if (NS_FAILED(rv)) return; |
|
|
|
|
|
if (nodeHack == 1) { |
|
pThis->m_wndBrowserView.m_pGetNode = node; |
|
return; |
|
} |
|
|
|
nsCOMPtr<nsIURI> imgURI; |
|
|
|
// Check if there is a image first |
|
if(aContextFlags & nsIContextMenuListener2::CONTEXT_IMAGE) |
|
{ |
|
nIDResource = IDR_CTXMENU_IMAGE; |
|
|
|
// Get the IMG SRC |
|
aInfo->GetImageSrc(getter_AddRefs(imgURI)); |
|
if(!imgURI) |
|
return; |
|
} |
|
|
|
if(aContextFlags & nsIContextMenuListener2::CONTEXT_DOCUMENT) |
|
{ |
|
nIDResource = IDR_CTXMENU_DOCUMENT; |
|
} |
|
else if(aContextFlags & nsIContextMenuListener2::CONTEXT_TEXT) |
|
{ |
|
nIDResource = IDR_CTXMENU_TEXT; |
|
} |
|
else if (aContextFlags & nsIContextMenuListener2::CONTEXT_INPUT) |
|
{ |
|
if (!(aContextFlags & nsIContextMenuListener2::CONTEXT_IMAGE)) { |
|
// Mozilla don't tell if the input is of type text or password... |
|
nsCOMPtr<nsIDOMHTMLInputElement> inputElement(do_QueryInterface(node)); |
|
if (inputElement) { |
|
nsEmbedString inputElemType; |
|
inputElement->GetType(inputElemType); |
|
if ((wcsicmp(inputElemType.get(), L"text") == 0) || |
|
(wcsicmp(inputElemType.get(), L"password") == 0)) |
|
nIDResource = IDR_CTXMENU_TEXT; |
|
} |
|
} |
|
} |
|
else if(aContextFlags & nsIContextMenuListener2::CONTEXT_LINK) |
|
{ |
|
nIDResource = IDR_CTXMENU_LINK; |
|
|
|
// Since we handle all the browser menu/toolbar commands |
|
// in the View, we basically setup the Link's URL in the |
|
// BrowserView object. When a menu selection in the context |
|
// menu is made, the appropriate command handler in the |
|
// BrowserView will be invoked and the value of the URL |
|
// will be accesible in the view |
|
|
|
nsEmbedString strUrlUcs2; |
|
nsresult rv = aInfo->GetAssociatedLink(strUrlUcs2); |
|
if(NS_FAILED(rv)) |
|
return; |
|
|
|
// Update the view with the new LinkUrl |
|
// Note that this string is in UCS2 format |
|
pThis->m_wndBrowserView.SetCtxMenuLinkUrl(strUrlUcs2); |
|
} |
|
|
|
// Check for a background image if the menu type is document |
|
if ( (nIDResource == IDR_CTXMENU_DOCUMENT) && !imgURI && |
|
(aContextFlags & nsIContextMenuListener2::CONTEXT_BACKGROUND_IMAGE)) |
|
aInfo->GetBackgroundImageSrc(getter_AddRefs(imgURI)); |
|
|
|
if (imgURI) { |
|
nsEmbedCString strImgSrcUtf8; |
|
imgURI->GetSpec(strImgSrcUtf8); |
|
if(!strImgSrcUtf8.IsEmpty()) { |
|
// Set the new Img Src |
|
nsEmbedString strImgSrc; |
|
NS_CStringToUTF16(strImgSrcUtf8, NS_CSTRING_ENCODING_UTF8, strImgSrc); |
|
pThis->m_wndBrowserView.SetCtxMenuImageSrc(strImgSrc); |
|
|
|
nsCOMPtr<imgIContainer> img; |
|
aInfo->GetImageContainer(getter_AddRefs(img)); |
|
//pThis->m_wndBrowserView.SetCtxImage(img); |
|
} |
|
} |
|
|
|
// Determine if we need to add the Frame related context menu items |
|
// such as "View Frame Source" etc. |
|
// node is not set for xml documents, ... but we still |
|
// want the context menu for them. |
|
if (node) |
|
{ |
|
nsCOMPtr<nsIDOMDocument> contextDocument; |
|
rv = node->GetOwnerDocument(getter_AddRefs(contextDocument)); |
|
if (NS_FAILED(rv) || !contextDocument) return; |
|
|
|
nsCOMPtr<nsIDOMWindow> domWindow; |
|
rv = pThis->m_wndBrowserView.mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); |
|
if (NS_FAILED(rv) || !domWindow) return; |
|
|
|
nsCOMPtr<nsIDOMDocument> document; |
|
rv = domWindow->GetDocument(getter_AddRefs(document)); |
|
if (NS_FAILED(rv)) return; |
|
|
|
if(document != contextDocument) |
|
{ |
|
//Determine the current Frame URL |
|
nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(contextDocument, &rv)); |
|
if (NS_SUCCEEDED(rv)) { |
|
nsEmbedString strFrameURL; |
|
rv = htmlDoc->GetURL(strFrameURL); |
|
if (NS_SUCCEEDED(rv)) { |
|
//Set it to the new URL |
|
pThis->m_wndBrowserView.SetCurrentFrameURL(strFrameURL); |
|
bContentHasFrames = TRUE; |
|
} |
|
} |
|
} |
|
} |
|
|
|
TCHAR *menuType = _T("<nothing>"); |
|
|
|
CString selection; |
|
pThis->m_wndBrowserView.GetSelection(selection); |
|
|
|
if ( !(aContextFlags & nsIContextMenuListener2::CONTEXT_LINK) && |
|
!(aContextFlags & nsIContextMenuListener2::CONTEXT_IMAGE) && |
|
selection.GetLength() ) |
|
{ |
|
menuType = _T("SelectedText"); |
|
} |
|
else { |
|
|
|
if (!bContentHasFrames) { |
|
switch (nIDResource) { |
|
case IDR_CTXMENU_DOCUMENT: |
|
menuType = _T("DocumentPopup"); |
|
if (imgURI) |
|
menuType = _T("DocumentImagePopup"); |
|
break; |
|
case IDR_CTXMENU_TEXT: |
|
menuType = _T("TextPopup"); |
|
break; |
|
case IDR_CTXMENU_LINK: |
|
menuType = _T("LinkPopup"); |
|
if (imgURI) |
|
menuType = _T("ImageLinkPopup"); |
|
break; |
|
case IDR_CTXMENU_IMAGE: |
|
menuType = _T("ImagePopup"); |
|
break; |
|
} |
|
} |
|
else { |
|
switch (nIDResource) { |
|
case IDR_CTXMENU_DOCUMENT: |
|
menuType = _T("FrameDocumentPopup"); |
|
if (imgURI) |
|
menuType = _T("FrameDocumentImagePopup"); |
|
break; |
|
case IDR_CTXMENU_TEXT: |
|
menuType = _T("FrameTextPopup"); |
|
break; |
|
case IDR_CTXMENU_LINK: |
|
menuType = _T("FrameLinkPopup"); |
|
if (imgURI) |
|
menuType = _T("FrameImageLinkPopup"); |
|
break; |
|
case IDR_CTXMENU_IMAGE: |
|
menuType = _T("FrameImagePopup"); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
/* !!BAD HACK!! !!BAD HACK!! !!BAD HACK!! !!BAD HACK!! */ |
|
if (nodeHack == 2) { |
|
pThis->m_wndBrowserView.m_pGetNode = node; |
|
return; |
|
} |
|
|
|
|
|
CMenu *ctxMenu = theApp.menus.GetMenu(menuType); |
|
if(ctxMenu) |
|
{ |
|
POINT cursorPos; |
|
GetCursorPos(&cursorPos); |
|
|
|
/* int offset = theApp.menus.GetOffset(ctxMenu); |
|
|
|
RECT desktopRect; |
|
SystemParametersInfo(SPI_GETWORKAREA, NULL, &desktopRect, 0); |
|
int menuHeight = 0; |
|
unsigned int i; |
|
MENUITEMINFO info; |
|
for (i=0; i<ctxMenu->GetMenuItemCount(); i++) { |
|
ctxMenu->GetMenuItemInfo(i, &info, TRUE); |
|
if (info.fType & MFT_SEPARATOR) |
|
menuHeight += 0; |
|
else |
|
menuHeight += GetSystemMetrics(SM_CYMENUSIZE); |
|
} |
|
if ( (int)(cursorPos.y - offset) < (int)(desktopRect.bottom - menuHeight) ){ |
|
// we only do this if we're not too close to the bottom of the screen |
|
cursorPos.y -= offset; |
|
if (cursorPos.y < 0){ |
|
cursorPos.y = 0; |
|
} |
|
} else if (cursorPos.y + menuHeight > desktopRect.bottom) { |
|
cursorPos.y = desktopRect.bottom - menuHeight; |
|
}*/ |
|
|
|
ctxMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, cursorPos.x, cursorPos.y, pThis); |
|
|
|
} |
|
} |
|
|
|
HWND CBrowserFrame::BrowserFrameGlueObj::GetBrowserFrameNativeWnd() |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
return pThis->m_hWnd; |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::UpdateSecurityStatus(PRInt32 aState) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
pThis->UpdateSecurityStatus(aState); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::ShowTooltip(PRInt32 x, PRInt32 y, const TCHAR *text) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
if (!text) { |
|
pThis->m_wndToolTip.Hide(); |
|
// WORKAROUND: Because the tooltip is not erased correctly when using the mouse wheel |
|
pThis->m_wndBrowserView.mBaseWindow->Repaint(PR_FALSE); |
|
return; |
|
} |
|
|
|
POINT point; |
|
::GetCursorPos(&point); |
|
|
|
pThis->m_wndBrowserView.ScreenToClient(&point); |
|
point.y += GetSystemMetrics(SM_CYCURSOR)/2 + 4; // jump to below the cursor, otherwise we appear right on top of the cursor |
|
|
|
pThis->m_wndToolTip.Show(text, point.x, point.y); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::FocusNextElement() { |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
nsCOMPtr<nsIWebBrowserFocus> focus = pThis->m_wndBrowserView.mWebBrowserFocus; |
|
if (!focus) return; |
|
|
|
if (pThis->m_wndFindBar){ |
|
focus->Deactivate(); |
|
pThis->m_wndFindBar->SetFocus(); |
|
} |
|
else if (pThis->m_wndUrlBar.IsWindowVisible()) { |
|
focus->Deactivate(); |
|
::SetFocus(pThis->m_wndUrlBar.m_hwndEdit); |
|
} |
|
else |
|
focus->SetFocusAtFirstElement(); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::FocusPrevElement() { |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
nsCOMPtr<nsIWebBrowserFocus> focus = pThis->m_wndBrowserView.mWebBrowserFocus; |
|
if (!focus) return; |
|
|
|
if (pThis->m_wndUrlBar.IsWindowVisible()) { |
|
focus->Deactivate(); |
|
::SetFocus(pThis->m_wndUrlBar.m_hwndEdit); |
|
} |
|
else |
|
focus->SetFocusAtLastElement(); |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::MouseAction(nsIDOMNode *node) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
pThis->m_wndBrowserView.m_lastMouseActionNode = node; |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::PopupBlocked(const char* uri) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj) |
|
|
|
// Do nothing if an icon was set already or if the user |
|
// don't want popup notification |
|
if (!theApp.preferences.GetBool("browser.popups.showPopupBlocker", PR_TRUE) |
|
|| !pThis->m_wndBrowserView.m_csHostPopupBlocked.IsEmpty()) |
|
return; |
|
|
|
pThis->m_wndStatusBar.AddIcon(ID_POPUP_BLOCKED_ICON); |
|
HICON hTmpPopupIcon = |
|
(HICON)::LoadImage(AfxGetResourceHandle(), |
|
MAKEINTRESOURCE(IDI_POPUP_BLOCKED), IMAGE_ICON, 16,16,LR_LOADMAP3DCOLORS); |
|
|
|
CString tpText; |
|
USES_CONVERSION; |
|
const TCHAR* turi = A2CT(uri); |
|
|
|
tpText.Format(IDS_POPUP_BLOCKED, turi); |
|
pThis->m_wndStatusBar.SetIconInfo(ID_POPUP_BLOCKED_ICON, hTmpPopupIcon, tpText); |
|
|
|
pThis->m_wndBrowserView.m_csHostPopupBlocked = turi; |
|
} |
|
|
|
void CBrowserFrame::BrowserFrameGlueObj::SetFavIcon(nsIURI* favUri) |
|
{ |
|
METHOD_PROLOGUE(CBrowserFrame, BrowserFrameGlueObj); |
|
#ifdef INTERNAL_SITEICONS |
|
if (favUri == nsnull) |
|
{ |
|
// XXX Temporary set m_bDOMLoaded here |
|
pThis->m_wndBrowserView.mbDOMLoaded = TRUE; |
|
|
|
// No site icon found then we're looking for a IE favicon |
|
// Note that this can be called twice, when DOMContentLoaded |
|
// is fired, and when the page finished to load. |
|
// DOMContentLoaded is not fired when page are loaded from cache |
|
// so I'm calling it also when the page is loaded to be sure we |
|
// checked for an IE icon. |
|
|
|
if (pThis->m_wndBrowserView.m_IconUri!=nsnull) return; |
|
|
|
nsCOMPtr<nsIURI> currentURI; |
|
nsresult rv = pThis->m_wndBrowserView.mWebNav->GetCurrentURI(getter_AddRefs(currentURI)); |
|
if(NS_FAILED(rv) || !currentURI) return; |
|
|
|
if (theApp.preferences.GetBool("browser.chrome.favicons", PR_TRUE)) |
|
{ |
|
nsCOMPtr<nsIURI> currentURI; |
|
nsEmbedCString nsUri; |
|
rv = pThis->m_wndBrowserView.mWebNav->GetCurrentURI(getter_AddRefs(currentURI)); |
|
if (NS_FAILED(rv)) return; |
|
|
|
PRBool ishttp, b; |
|
currentURI->SchemeIs("http", &b); |
|
ishttp = b; |
|
currentURI->SchemeIs("https", &b); |
|
ishttp |= b; |
|
|
|
if (ishttp) |
|
{ |
|
currentURI->Resolve(NS_LITERAL_CSTRING("/favicon.ico"), nsUri); |
|
|
|
nsCOMPtr<nsIURI> iconURI; |
|
rv = NewURI(getter_AddRefs(iconURI), nsUri); |
|
if(NS_FAILED(rv) || !iconURI) return; |
|
|
|
pThis->m_wndBrowserView.m_IconUri = iconURI; |
|
pThis->SetFavIcon(theApp.favicons.GetIcon(iconURI, TRUE)); |
|
} |
|
else |
|
pThis->SetFavIcon(theApp.favicons.GetDefaultIcon()); |
|
} |
|
else |
|
pThis->SetFavIcon(theApp.favicons.GetDefaultIcon()); |
|
} |
|
else |
|
{ |
|
pThis->m_wndBrowserView.m_IconUri = favUri; |
|
pThis->SetFavIcon(theApp.favicons.GetIcon(favUri, TRUE)); |
|
} |
|
#endif |
|
}
|
|
|