/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Simon Fraser * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include #include "nsCommandLineServiceMac.h" #include "nsCOMPtr.h" #include "nsIBaseWindow.h" #include "nsIBrowserDOMWindow.h" #include "nsIContent.h" #include "nsIDocShell.h" #include "nsIDocShellTreeItem.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" #include "nsIDOMWindow.h" #include "nsIDOMChromeWindow.h" #include "nsIDOMWindowInternal.h" #include "nsIDOMElement.h" #include "nsIDOMNode.h" #include "nsIServiceManager.h" #include "nsIWebNavigation.h" #include "nsIWidget.h" #include "nsIWindowMediator.h" #include "nsIURI.h" #include "nsIXULWindow.h" #include "nsString.h" #include "nsNetUtil.h" #include "nsWindowUtils.h" #include "nsMacUtils.h" #include "nsXPIDLString.h" #include "nsIXULWindow.h" #include "nsWindowUtils.h" #include "nsReadableUtils.h" #include "nsAEUtils.h" using namespace nsWindowUtils; // CIDs static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID); /*---------------------------------------------------------------------------- GetXULWindowFromWindowPtr Get an nsIXULWindow from a WindowPtr. Returns an ADDREFFED xulWindow, which you must release (hint: use an nsCOMPtr). Throws on error. ----------------------------------------------------------------------------*/ static void GetXULWindowFromWindowPtr(WindowPtr inWindowPtr, nsIXULWindow **outXULWindow) { *outXULWindow = NULL; if (!inWindowPtr) ThrowOSErr(paramErr); nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); ThrowErrIfNil(windowMediator, paramErr); nsCOMPtr windowEnumerator; if (NS_FAILED(windowMediator->GetXULWindowEnumerator(nsnull, getter_AddRefs(windowEnumerator)))) ThrowOSErr(paramErr); // need a better error // Find the window while (true) { PRBool more = false; windowEnumerator->HasMoreElements(&more); if (!more) break; nsCOMPtr nextWindow = nsnull; windowEnumerator->GetNext(getter_AddRefs(nextWindow)); nsCOMPtr baseWindow(do_QueryInterface(nextWindow)); if (NULL == baseWindow) continue; nsCOMPtr widget = nsnull; baseWindow->GetMainWidget(getter_AddRefs(widget)); if (NULL == widget) continue; WindowRef windowRef = (WindowRef)widget->GetNativeData(NS_NATIVE_DISPLAY); if ((WindowPtr)windowRef == inWindowPtr) { // !!! There really must be an easier way to do this. JavaScript? nsCOMPtr xulWindow(do_QueryInterface(nextWindow)); if (!xulWindow) break; NS_ADDREF(*outXULWindow = xulWindow); return; } } // if we got here, we didn't find the window ThrowOSErr(paramErr); } /*---------------------------------------------------------------------------- GetXULWindowTypeString Get the type string for a XUL window ----------------------------------------------------------------------------*/ static void GetXULWindowTypeString(nsIXULWindow *inXULWindow, nsString& outWindowType) { outWindowType.Truncate(); if (inXULWindow) { nsCOMPtr contentShell; inXULWindow->GetPrimaryContentShell(getter_AddRefs(contentShell)); nsCOMPtr webNav(do_QueryInterface(contentShell)); ThrowErrIfNil(webNav, paramErr); nsCOMPtr domDoc; webNav->GetDocument(getter_AddRefs(domDoc)); if (domDoc) { nsCOMPtr element; domDoc->GetDocumentElement(getter_AddRefs(element)); if (element) element->GetAttribute(NS_LITERAL_STRING("windowtype"), outWindowType); } } } /*---------------------------------------------------------------------------- WindowKindFromTypeString ----------------------------------------------------------------------------*/ static TWindowKind WindowKindFromTypeString(const nsString& inWindowType) { if (inWindowType.IsEmpty()) return kAnyWindowKind; if (inWindowType.EqualsLiteral("navigator:browser")) return kBrowserWindowKind; if (inWindowType.EqualsLiteral("mail:3pane")) return kMailWindowKind; if (inWindowType.EqualsLiteral("msgcompose")) return kMailComposeWindowKind; if (inWindowType.EqualsLiteral("mail:addressbook")) return kAddressBookWindowKind; if (inWindowType.EqualsLiteral("composer:html")) return kComposerWindowKind; if (inWindowType.EqualsLiteral("composer:text")) return kComposerWindowKind; return kOtherWindowKind; } /*---------------------------------------------------------------------------- GetXULWindowKind ----------------------------------------------------------------------------*/ static TWindowKind GetXULWindowKind(nsIXULWindow *inXULWindow) { nsAutoString windowType; GetXULWindowTypeString(inXULWindow, windowType); return WindowKindFromTypeString(windowType); } /*---------------------------------------------------------------------------- CountWindowsOfKind ----------------------------------------------------------------------------*/ long nsWindowUtils::CountWindowsOfKind(TWindowKind windowKind) { nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); ThrowErrIfNil(windowMediator, paramErr); nsCOMPtr windowEnumerator; if (NS_FAILED(windowMediator->GetXULWindowEnumerator(nsnull, getter_AddRefs(windowEnumerator)))) ThrowOSErr(paramErr); // need a better error long windowCount = 0L; PRBool more; windowEnumerator->HasMoreElements(&more); while (more) { nsCOMPtr nextWindow = nsnull; windowEnumerator->GetNext(getter_AddRefs(nextWindow)); nsCOMPtr xulWindow(do_QueryInterface(nextWindow)); if (!xulWindow) break; if (kAnyWindowKind == windowKind) ++windowCount; else { // Test window kind. TWindowKind thisWindowKind = GetXULWindowKind(xulWindow); if (thisWindowKind == windowKind) ++windowCount; } windowEnumerator->HasMoreElements(&more); } return windowCount; } WindowPtr nsWindowUtils::GetNamedOrFrontmostWindow(TWindowKind windowKind, const char* windowName) { // Search for window with the desired kind and name. nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); ThrowErrIfNil(windowMediator, paramErr); nsCOMPtr windowEnumerator; if (NS_FAILED(windowMediator->GetXULWindowEnumerator(nsnull, getter_AddRefs(windowEnumerator)))) ThrowOSErr(paramErr); // need a better error WindowPtr windowPtr = NULL; PRBool more; nsCString windowNameString(windowName); windowEnumerator->HasMoreElements(&more); while (more) { nsCOMPtr nextWindow = nsnull; windowEnumerator->GetNext(getter_AddRefs(nextWindow)); nsCOMPtr xulWindow(do_QueryInterface(nextWindow)); if (!xulWindow) break; nsCOMPtr baseWindow(do_QueryInterface(xulWindow)); ThrowErrIfNil(baseWindow, paramErr); nsCOMPtr widget = nsnull; baseWindow->GetMainWidget(getter_AddRefs(widget)); ThrowErrIfNil(widget, paramErr); WindowRef windowRef = (WindowRef)widget->GetNativeData(NS_NATIVE_DISPLAY); TWindowKind thisWindowKind = GetXULWindowKind(xulWindow); // If this is the kind of window we are looking for... if (kAnyWindowKind == windowKind || (thisWindowKind == windowKind)) { if (NULL == windowName) { // ...see if its the frontmost of this kind. PRInt32 zIndex; widget->GetZIndex(&zIndex); if (0L == zIndex) { windowPtr = (WindowPtr)windowRef; break; } } else { // ...see if its name is the desired one. Str255 pascalTitle; GetWTitle(windowRef, pascalTitle); if (windowNameString.Compare((const char*)&pascalTitle[1], PR_FALSE, pascalTitle[0]) == 0) { windowPtr = (WindowPtr)windowRef; // WindowRef is the WindowPtr. break; } } } windowEnumerator->HasMoreElements(&more); } return windowPtr; } WindowPtr nsWindowUtils::GetIndexedWindowOfKind(TWindowKind windowKind, TAEListIndex index) { nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); ThrowErrIfNil(windowMediator, paramErr); nsCOMPtr windowEnumerator; if (NS_FAILED(windowMediator->GetZOrderXULWindowEnumerator(nsnull, PR_TRUE, getter_AddRefs(windowEnumerator)))) ThrowOSErr(paramErr); // need a better error WindowPtr windowPtr = NULL; PRBool more; windowEnumerator->HasMoreElements(&more); while (more) { nsCOMPtr nextWindow = nsnull; windowEnumerator->GetNext(getter_AddRefs(nextWindow)); nsCOMPtr xulWindow(do_QueryInterface(nextWindow)); if (!xulWindow) break; nsCOMPtr baseWindow(do_QueryInterface(xulWindow)); ThrowErrIfNil(baseWindow, paramErr); nsCOMPtr widget = nsnull; baseWindow->GetMainWidget(getter_AddRefs(widget)); ThrowErrIfNil(widget, paramErr); WindowRef windowRef = (WindowRef)widget->GetNativeData(NS_NATIVE_DISPLAY); TWindowKind thisWindowKind = GetXULWindowKind(xulWindow); // If this is the kind of window we are looking for... if (kAnyWindowKind == windowKind || (thisWindowKind == windowKind)) { // ...decrement index and test if this is the window at that index. if (0L == --index) { windowPtr = (WindowPtr)windowRef; // WindowRef is the WindowPtr. break; } } windowEnumerator->HasMoreElements(&more); } return windowPtr; } TAEListIndex nsWindowUtils::GetWindowIndex(TWindowKind windowKind, WindowPtr theWindow) { nsCOMPtr windowMediator(do_GetService(kWindowMediatorCID)); ThrowErrIfNil(windowMediator, paramErr); nsCOMPtr windowEnumerator; if (NS_FAILED(windowMediator->GetZOrderXULWindowEnumerator(nsnull, PR_TRUE, getter_AddRefs(windowEnumerator)))) ThrowOSErr(paramErr); // need a better error TAEListIndex index = 0L; PRBool more; windowEnumerator->HasMoreElements(&more); while (more) { nsCOMPtr nextWindow = nsnull; windowEnumerator->GetNext(getter_AddRefs(nextWindow)); nsCOMPtr xulWindow(do_QueryInterface(nextWindow)); if (!xulWindow) break; nsCOMPtr baseWindow(do_QueryInterface(xulWindow)); ThrowErrIfNil(baseWindow, paramErr); nsCOMPtr widget = nsnull; baseWindow->GetMainWidget(getter_AddRefs(widget)); ThrowErrIfNil(widget, paramErr); WindowRef windowRef = (WindowRef)widget->GetNativeData(NS_NATIVE_DISPLAY); TWindowKind thisWindowKind = GetXULWindowKind(xulWindow); if (kAnyWindowKind == windowKind || (thisWindowKind == windowKind)) { ++index; if ((WindowPtr)windowRef == theWindow) return index; } windowEnumerator->HasMoreElements(&more); } return 0L; // error: theWindow wasn't found. Return an invalid index. } //--------------------------------------------------------- void nsWindowUtils::GetCleanedWindowName(WindowPtr wind, char* outName, long maxLen) { Str255 uncleanName; GetWTitle(wind, uncleanName); CopyPascalToCString(uncleanName, outName, maxLen); } //--------------------------------------------------------- void nsWindowUtils::GetWindowUrlString(WindowPtr wind, char** outUrlStringPtr) { *outUrlStringPtr = NULL; nsCOMPtr xulWindow; GetXULWindowFromWindowPtr(wind, getter_AddRefs(xulWindow)); ThrowErrIfNil(xulWindow, paramErr); nsCOMPtr contentShell; xulWindow->GetPrimaryContentShell(getter_AddRefs(contentShell)); nsCOMPtr webNav(do_QueryInterface(contentShell)); ThrowErrIfNil(webNav, paramErr); nsCOMPtr sourceURL; webNav->GetCurrentURI(getter_AddRefs(sourceURL)); ThrowErrIfNil(sourceURL, paramErr); // Now get the string; nsCAutoString spec; sourceURL->GetSpec(spec); *outUrlStringPtr = ToNewCString(spec); } //--------------------------------------------------------- inline void GetWindowPortRect(WindowPtr wind, Rect *outRect) { #if OPAQUE_TOOLBOX_STRUCTS ::GetPortBounds(GetWindowPort(wind), outRect); #else *outRect = wind->portRect; #endif } /*---------------------------------------------------------------------------- LocalToGlobalRect Convert a rectangle from local to global coordinates. Entry: r = pointer to rectangle. ----------------------------------------------------------------------------*/ static void LocalToGlobalRect (Rect *r) { LocalToGlobal((Point*)&r->top); LocalToGlobal((Point*)&r->bottom); } void nsWindowUtils::GetWindowGlobalBounds(WindowPtr wind, Rect* outBounds) { GrafPtr curPort; GetWindowPortRect(wind, outBounds); GetPort(&curPort); SetPortWindowPort(wind); LocalToGlobalRect(outBounds); SetPort(curPort); } /*---------------------------------------------------------------------------- LoadURLInWindow ----------------------------------------------------------------------------*/ void nsWindowUtils::LoadURLInWindow(WindowPtr wind, const char* urlString) { OSErr err = noErr; if ( !wind ) { // this makes a new window nsMacCommandLine& cmdLine = nsMacCommandLine::GetMacCommandLine(); err = cmdLine.DispatchURLToNewBrowser(urlString); ThrowIfOSErr(err); } else { // existing window. Go through hoops to load a URL in it nsCOMPtr xulWindow; GetXULWindowFromWindowPtr(wind, getter_AddRefs(xulWindow)); ThrowErrIfNil(xulWindow, paramErr); LoadURLInXULWindow(xulWindow, urlString); } } void nsWindowUtils::LoadURLInXULWindow(nsIXULWindow* inWindow, const char* urlString) { nsCOMPtr docShell; nsCOMPtr docItem; nsCOMPtr bwin; // first try the nsIBrowserDOMWindow helper object // note the actual window used depends on user prefs. this may end up // using a different window! inWindow->GetDocShell(getter_AddRefs(docShell)); docItem = do_QueryInterface(docShell); if (docItem) { nsCOMPtr rootItem; docItem->GetRootTreeItem(getter_AddRefs(rootItem)); nsCOMPtr rootWin(do_GetInterface(rootItem)); nsCOMPtr chromeWin(do_QueryInterface(rootWin)); if (chromeWin) chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin)); } if (bwin) { nsCOMPtr uri; nsDependentCString urlStr(urlString); NS_NewURI(getter_AddRefs(uri), urlStr, 0, 0); if (uri) { nsCOMPtr newBrowserWindow; bwin->OpenURI(uri, 0, nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW, nsIBrowserDOMWindow::OPEN_EXTERNAL, getter_AddRefs(newBrowserWindow)); if (newBrowserWindow) return; } } // fallback: navigate the XULWindow's content shell directly inWindow->GetPrimaryContentShell(getter_AddRefs(docItem)); ThrowErrIfNil(docItem, paramErr); nsCOMPtr webNav(do_QueryInterface(docItem)); ThrowErrIfNil(webNav, paramErr); nsAutoString urlWString; urlWString.AssignWithConversion(urlString); webNav->LoadURI(urlWString.get(), nsIWebNavigation::LOAD_FLAGS_NONE, nsnull, nsnull, nsnull); } #pragma mark - /*---------------------------------------------------------------------------- WindowIsResizeable ----------------------------------------------------------------------------*/ Boolean nsWindowUtils::WindowIsResizeable(WindowPtr wind) { OSStatus status; UInt32 features; status = GetWindowFeatures(wind, &features); return ((status == noErr) && ((features & kWindowCanGrow) != 0)); } /*---------------------------------------------------------------------------- WindowIsZoomable ----------------------------------------------------------------------------*/ Boolean nsWindowUtils::WindowIsZoomable(WindowPtr wind) { OSStatus status; UInt32 features; status = GetWindowFeatures(wind, &features); return ((status == noErr) && ((features & kWindowCanZoom) != 0)); } /*---------------------------------------------------------------------------- WindowIsZoomed ----------------------------------------------------------------------------*/ Boolean nsWindowUtils::WindowIsZoomed(WindowPtr wind) { Rect r, userRect; GetWindowUserState(wind, &userRect); GetWindowPortRect(wind, &r); OffsetRect(&userRect, -userRect.left, -userRect.top); return EqualRect(&userRect, &r); } /*---------------------------------------------------------------------------- WindowHasTitleBar This stuff only works in 8.0 and later (Appearance Mgr) ----------------------------------------------------------------------------*/ Boolean nsWindowUtils::WindowHasTitleBar(WindowPtr wind) { OSStatus status; UInt32 features; status = GetWindowFeatures(wind, &features); return ((status == noErr) && ((features & kWindowHasTitleBar) != 0)); } /*---------------------------------------------------------------------------- WindowIsCloseable This stuff only works in 8.5 and later (Appearance Mgr) ----------------------------------------------------------------------------*/ Boolean nsWindowUtils::WindowIsCloseable(WindowPtr wind) { if ((long)GetWindowAttributes != kUnresolvedCFragSymbolAddress) { OSStatus status; UInt32 attributes; status = GetWindowAttributes(wind, &attributes); return ((status == noErr) && ((attributes & kWindowCloseBoxAttribute) != 0)); } return true; } /*---------------------------------------------------------------------------- WindowIsModal This stuff only works in 8.0 and later (Appearance Mgr) ----------------------------------------------------------------------------*/ Boolean nsWindowUtils::WindowIsModal(WindowPtr wind) { OSStatus status; UInt32 features; status = GetWindowFeatures(wind, &features); return ((status == noErr) && ((features & kWindowIsModal) != 0)); } /*---------------------------------------------------------------------------- WindowIsFloating ----------------------------------------------------------------------------*/ Boolean nsWindowUtils::WindowIsFloating(WindowPtr wind) { WindowClass windClass; if (GetWindowClass(wind, &windClass) == noErr) { return (windClass == kFloatingWindowClass); } return false; } /*---------------------------------------------------------------------------- WindowIsModified ----------------------------------------------------------------------------*/ Boolean nsWindowUtils::WindowIsModified(WindowPtr wind) { // еее write me return false; }