backing out bug 347743 due to major crasher in 386332
[mozilla-central.git] / widget / src / xpwidgets / nsBaseWidget.cpp
blob466e1f4727a5df0e507c17db7efbdd366f801d32
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Dean Tessman <dean_tessman@hotmail.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsBaseWidget.h"
40 #include "nsIDeviceContext.h"
41 #include "nsCOMPtr.h"
42 #include "nsIMenuListener.h"
43 #include "nsGfxCIID.h"
44 #include "nsWidgetsCID.h"
45 #include "nsIFullScreen.h"
46 #include "nsServiceManagerUtils.h"
47 #include "nsIScreenManager.h"
48 #include "nsAppDirectoryServiceDefs.h"
49 #include "nsISimpleEnumerator.h"
51 #ifdef DEBUG
52 #include "nsIServiceManager.h"
53 #include "nsIPrefService.h"
54 #include "nsIPrefBranch2.h"
55 #include "nsIObserver.h"
57 static void debug_RegisterPrefCallbacks();
59 #endif
61 #ifdef NOISY_WIDGET_LEAKS
62 static PRInt32 gNumWidgets;
63 #endif
65 // nsBaseWidget
66 NS_IMPL_ISUPPORTS1(nsBaseWidget, nsIWidget)
69 //-------------------------------------------------------------------------
71 // nsBaseWidget constructor
73 //-------------------------------------------------------------------------
75 nsBaseWidget::nsBaseWidget()
76 : mClientData(nsnull)
77 , mEventCallback(nsnull)
78 , mContext(nsnull)
79 , mToolkit(nsnull)
80 , mMouseListener(nsnull)
81 , mEventListener(nsnull)
82 , mMenuListener(nsnull)
83 , mCursor(eCursor_standard)
84 , mWindowType(eWindowType_child)
85 , mBorderStyle(eBorderStyle_none)
86 , mIsShiftDown(PR_FALSE)
87 , mIsControlDown(PR_FALSE)
88 , mIsAltDown(PR_FALSE)
89 , mIsDestroying(PR_FALSE)
90 , mOnDestroyCalled(PR_FALSE)
91 , mBounds(0,0,0,0)
92 , mOriginalBounds(nsnull)
93 , mZIndex(0)
94 , mSizeMode(nsSizeMode_Normal)
96 #ifdef NOISY_WIDGET_LEAKS
97 gNumWidgets++;
98 printf("WIDGETS+ = %d\n", gNumWidgets);
99 #endif
101 #ifdef DEBUG
102 debug_RegisterPrefCallbacks();
103 #endif
107 //-------------------------------------------------------------------------
109 // nsBaseWidget destructor
111 //-------------------------------------------------------------------------
112 nsBaseWidget::~nsBaseWidget()
114 #ifdef NOISY_WIDGET_LEAKS
115 gNumWidgets--;
116 printf("WIDGETS- = %d\n", gNumWidgets);
117 #endif
119 NS_IF_RELEASE(mMenuListener);
120 NS_IF_RELEASE(mToolkit);
121 NS_IF_RELEASE(mContext);
122 if (mOriginalBounds)
123 delete mOriginalBounds;
127 //-------------------------------------------------------------------------
129 // Basic create.
131 //-------------------------------------------------------------------------
132 void nsBaseWidget::BaseCreate(nsIWidget *aParent,
133 const nsRect &aRect,
134 EVENT_CALLBACK aHandleEventFunction,
135 nsIDeviceContext *aContext,
136 nsIAppShell *aAppShell,
137 nsIToolkit *aToolkit,
138 nsWidgetInitData *aInitData)
140 if (nsnull == mToolkit) {
141 if (nsnull != aToolkit) {
142 mToolkit = (nsIToolkit*)aToolkit;
143 NS_ADDREF(mToolkit);
145 else {
146 if (nsnull != aParent) {
147 mToolkit = (nsIToolkit*)(aParent->GetToolkit()); // the call AddRef's, we don't have to
149 // it's some top level window with no toolkit passed in.
150 // Create a default toolkit with the current thread
151 #if !defined(USE_TLS_FOR_TOOLKIT)
152 else {
153 static NS_DEFINE_CID(kToolkitCID, NS_TOOLKIT_CID);
155 nsresult res;
156 res = CallCreateInstance(kToolkitCID, &mToolkit);
157 NS_ASSERTION(NS_SUCCEEDED(res), "Can not create a toolkit in nsBaseWidget::Create");
158 if (mToolkit)
159 mToolkit->Init(PR_GetCurrentThread());
161 #else /* USE_TLS_FOR_TOOLKIT */
162 else {
163 nsresult rv;
165 rv = NS_GetCurrentToolkit(&mToolkit);
167 #endif /* USE_TLS_FOR_TOOLKIT */
172 // save the event callback function
173 mEventCallback = aHandleEventFunction;
175 // keep a reference to the device context
176 if (aContext) {
177 mContext = aContext;
178 NS_ADDREF(mContext);
180 else {
181 nsresult res;
183 static NS_DEFINE_CID(kDeviceContextCID, NS_DEVICE_CONTEXT_CID);
185 res = CallCreateInstance(kDeviceContextCID, &mContext);
187 if (NS_SUCCEEDED(res))
188 mContext->Init(nsnull);
191 if (nsnull != aInitData) {
192 PreCreateWidget(aInitData);
195 if (aParent) {
196 aParent->AddChild(this);
200 NS_IMETHODIMP nsBaseWidget::CaptureMouse(PRBool aCapture)
202 return NS_OK;
205 NS_IMETHODIMP nsBaseWidget::Validate()
207 return NS_OK;
210 NS_IMETHODIMP nsBaseWidget::InvalidateRegion(const nsIRegion *aRegion, PRBool aIsSynchronous)
212 return NS_ERROR_FAILURE;
215 //-------------------------------------------------------------------------
217 // Accessor functions to get/set the client data
219 //-------------------------------------------------------------------------
221 NS_IMETHODIMP nsBaseWidget::GetClientData(void*& aClientData)
223 aClientData = mClientData;
224 return NS_OK;
227 NS_IMETHODIMP nsBaseWidget::SetClientData(void* aClientData)
229 mClientData = aClientData;
230 return NS_OK;
233 //-------------------------------------------------------------------------
235 // Close this nsBaseWidget
237 //-------------------------------------------------------------------------
238 NS_METHOD nsBaseWidget::Destroy()
240 // Just in case our parent is the only ref to us
241 nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
243 // disconnect from the parent
244 nsIWidget *parent = GetParent();
245 if (parent) {
246 parent->RemoveChild(this);
248 // disconnect listeners.
249 NS_IF_RELEASE(mMouseListener);
250 NS_IF_RELEASE(mEventListener);
251 NS_IF_RELEASE(mMenuListener);
253 return NS_OK;
257 //-------------------------------------------------------------------------
259 // Set this nsBaseWidget's parent
261 //-------------------------------------------------------------------------
262 NS_IMETHODIMP nsBaseWidget::SetParent(nsIWidget* aNewParent)
264 return NS_ERROR_NOT_IMPLEMENTED;
268 //-------------------------------------------------------------------------
270 // Get this nsBaseWidget parent
272 //-------------------------------------------------------------------------
273 nsIWidget* nsBaseWidget::GetParent(void)
275 return nsnull;
278 //-------------------------------------------------------------------------
280 // Add a child to the list of children
282 //-------------------------------------------------------------------------
283 void nsBaseWidget::AddChild(nsIWidget* aChild)
285 NS_PRECONDITION(!aChild->GetNextSibling() && !aChild->GetPrevSibling(),
286 "aChild not properly removed from its old child list");
288 if (!mFirstChild) {
289 mFirstChild = mLastChild = aChild;
290 } else {
291 // append to the list
292 NS_ASSERTION(mLastChild, "Bogus state");
293 NS_ASSERTION(!mLastChild->GetNextSibling(), "Bogus state");
294 mLastChild->SetNextSibling(aChild);
295 aChild->SetPrevSibling(mLastChild);
296 mLastChild = aChild;
301 //-------------------------------------------------------------------------
303 // Remove a child from the list of children
305 //-------------------------------------------------------------------------
306 void nsBaseWidget::RemoveChild(nsIWidget* aChild)
308 NS_ASSERTION(aChild->GetParent() == this, "Not one of our kids!");
310 if (mLastChild == aChild) {
311 mLastChild = mLastChild->GetPrevSibling();
313 if (mFirstChild == aChild) {
314 mFirstChild = mFirstChild->GetNextSibling();
317 // Now remove from the list. Make sure that we pass ownership of the tail
318 // of the list correctly before we have aChild let go of it.
319 nsIWidget* prev = aChild->GetPrevSibling();
320 nsIWidget* next = aChild->GetNextSibling();
321 if (prev) {
322 prev->SetNextSibling(next);
324 if (next) {
325 next->SetPrevSibling(prev);
328 aChild->SetNextSibling(nsnull);
329 aChild->SetPrevSibling(nsnull);
333 //-------------------------------------------------------------------------
335 // Sets widget's position within its parent's child list.
337 //-------------------------------------------------------------------------
338 NS_IMETHODIMP nsBaseWidget::SetZIndex(PRInt32 aZIndex)
340 // Hold a ref to ourselves just in case, since we're going to remove
341 // from our parent.
342 nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
344 mZIndex = aZIndex;
346 // reorder this child in its parent's list.
347 nsBaseWidget* parent = NS_STATIC_CAST(nsBaseWidget*, GetParent());
348 if (parent) {
349 parent->RemoveChild(this);
350 // Scope sib outside the for loop so we can check it afterward
351 nsIWidget* sib = parent->GetFirstChild();
352 for ( ; sib; sib = sib->GetNextSibling()) {
353 PRInt32 childZIndex;
354 if (NS_SUCCEEDED(sib->GetZIndex(&childZIndex))) {
355 if (aZIndex < childZIndex) {
356 // Insert ourselves before sib
357 nsIWidget* prev = sib->GetPrevSibling();
358 mNextSibling = sib;
359 mPrevSibling = prev;
360 sib->SetPrevSibling(this);
361 if (prev) {
362 prev->SetNextSibling(this);
363 } else {
364 NS_ASSERTION(sib == parent->mFirstChild, "Broken child list");
365 // We've taken ownership of sib, so it's safe to have parent let
366 // go of it
367 parent->mFirstChild = this;
369 PlaceBehind(eZPlacementBelow, sib, PR_FALSE);
370 break;
374 // were we added to the list?
375 if (!sib) {
376 parent->AddChild(this);
379 return NS_OK;
382 //-------------------------------------------------------------------------
384 // Gets widget's position within its parent's child list.
386 //-------------------------------------------------------------------------
387 NS_IMETHODIMP nsBaseWidget::GetZIndex(PRInt32* aZIndex)
389 *aZIndex = mZIndex;
390 return NS_OK;
393 //-------------------------------------------------------------------------
395 // Places widget behind the given widget (platforms must override)
397 //-------------------------------------------------------------------------
398 NS_IMETHODIMP nsBaseWidget::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
399 nsIWidget *aWidget, PRBool aActivate)
401 return NS_OK;
404 //-------------------------------------------------------------------------
406 // Maximize, minimize or restore the window. The BaseWidget implementation
407 // merely stores the state.
409 //-------------------------------------------------------------------------
410 NS_IMETHODIMP nsBaseWidget::SetSizeMode(PRInt32 aMode) {
412 if (aMode == nsSizeMode_Normal || aMode == nsSizeMode_Minimized ||
413 aMode == nsSizeMode_Maximized) {
415 mSizeMode = (nsSizeMode) aMode;
416 return NS_OK;
418 return NS_ERROR_ILLEGAL_VALUE;
421 //-------------------------------------------------------------------------
423 // Get the size mode (minimized, maximized, that sort of thing...)
425 //-------------------------------------------------------------------------
426 NS_IMETHODIMP nsBaseWidget::GetSizeMode(PRInt32* aMode) {
428 *aMode = mSizeMode;
429 return NS_OK;
432 //-------------------------------------------------------------------------
434 // Get the foreground color
436 //-------------------------------------------------------------------------
437 nscolor nsBaseWidget::GetForegroundColor(void)
439 return mForeground;
443 //-------------------------------------------------------------------------
445 // Set the foreground color
447 //-------------------------------------------------------------------------
448 NS_METHOD nsBaseWidget::SetForegroundColor(const nscolor &aColor)
450 mForeground = aColor;
451 return NS_OK;
455 //-------------------------------------------------------------------------
457 // Get the background color
459 //-------------------------------------------------------------------------
460 nscolor nsBaseWidget::GetBackgroundColor(void)
462 return mBackground;
465 //-------------------------------------------------------------------------
467 // Set the background color
469 //-------------------------------------------------------------------------
470 NS_METHOD nsBaseWidget::SetBackgroundColor(const nscolor &aColor)
472 mBackground = aColor;
473 return NS_OK;
476 //-------------------------------------------------------------------------
478 // Get this component cursor
480 //-------------------------------------------------------------------------
481 nsCursor nsBaseWidget::GetCursor()
483 return mCursor;
486 NS_METHOD nsBaseWidget::SetCursor(nsCursor aCursor)
488 mCursor = aCursor;
489 return NS_OK;
492 NS_IMETHODIMP nsBaseWidget::SetCursor(imgIContainer* aCursor,
493 PRUint32 aHotspotX, PRUint32 aHotspotY)
495 return NS_ERROR_NOT_IMPLEMENTED;
498 //-------------------------------------------------------------------------
500 // Get the window type for this widget
502 //-------------------------------------------------------------------------
503 NS_IMETHODIMP nsBaseWidget::GetWindowType(nsWindowType& aWindowType)
505 aWindowType = mWindowType;
506 return NS_OK;
509 NS_IMETHODIMP nsBaseWidget::SetWindowType(nsWindowType aWindowType)
511 mWindowType = aWindowType;
512 return NS_OK;
515 //-------------------------------------------------------------------------
517 // Window transparency methods
519 //-------------------------------------------------------------------------
521 NS_IMETHODIMP nsBaseWidget::SetWindowTranslucency(PRBool aTranslucent) {
522 return NS_ERROR_NOT_IMPLEMENTED;
525 NS_IMETHODIMP nsBaseWidget::GetWindowTranslucency(PRBool& aTranslucent) {
526 aTranslucent = PR_FALSE;
527 return NS_OK;
530 NS_IMETHODIMP nsBaseWidget::UpdateTranslucentWindowAlpha(const nsRect& aRect, PRUint8* aAlphas) {
531 NS_ASSERTION(PR_FALSE, "Window is not translucent");
532 return NS_ERROR_NOT_IMPLEMENTED;
535 //-------------------------------------------------------------------------
537 // Hide window borders/decorations for this widget
539 //-------------------------------------------------------------------------
540 NS_IMETHODIMP nsBaseWidget::HideWindowChrome(PRBool aShouldHide)
542 return NS_ERROR_NOT_IMPLEMENTED;
545 //-------------------------------------------------------------------------
547 // Put the window into full-screen mode
549 //-------------------------------------------------------------------------
550 NS_IMETHODIMP nsBaseWidget::MakeFullScreen(PRBool aFullScreen)
552 HideWindowChrome(aFullScreen);
553 return MakeFullScreenInternal(aFullScreen);
556 nsresult nsBaseWidget::MakeFullScreenInternal(PRBool aFullScreen)
558 nsCOMPtr<nsIFullScreen> fullScreen = do_GetService("@mozilla.org/browser/fullscreen;1");
560 if (aFullScreen) {
561 if (!mOriginalBounds)
562 mOriginalBounds = new nsRect();
563 GetScreenBounds(*mOriginalBounds);
565 // Move to top-left corner of screen and size to the screen dimensions
566 nsCOMPtr<nsIScreenManager> screenManager;
567 screenManager = do_GetService("@mozilla.org/gfx/screenmanager;1");
568 NS_ASSERTION(screenManager, "Unable to grab screenManager.");
569 if (screenManager) {
570 nsCOMPtr<nsIScreen> screen;
571 screenManager->ScreenForRect(mOriginalBounds->x, mOriginalBounds->y,
572 mOriginalBounds->width, mOriginalBounds->height,
573 getter_AddRefs(screen));
574 if (screen) {
575 PRInt32 left, top, width, height;
576 if (NS_SUCCEEDED(screen->GetRect(&left, &top, &width, &height))) {
577 SetSizeMode(nsSizeMode_Normal);
578 Resize(left, top, width, height, PR_TRUE);
580 // Hide all of the OS chrome
581 if (fullScreen)
582 fullScreen->HideAllOSChrome();
587 } else if (mOriginalBounds) {
588 Resize(mOriginalBounds->x, mOriginalBounds->y, mOriginalBounds->width,
589 mOriginalBounds->height, PR_TRUE);
591 // Show all of the OS chrome
592 if (fullScreen)
593 fullScreen->ShowAllOSChrome();
596 return NS_OK;
599 //-------------------------------------------------------------------------
601 // Create a rendering context from this nsBaseWidget
603 //-------------------------------------------------------------------------
604 nsIRenderingContext* nsBaseWidget::GetRenderingContext()
606 nsresult rv;
607 nsCOMPtr<nsIRenderingContext> renderingCtx;
609 if (mOnDestroyCalled)
610 return nsnull;
612 rv = mContext->CreateRenderingContextInstance(*getter_AddRefs(renderingCtx));
613 if (NS_SUCCEEDED(rv)) {
614 #if defined(MOZ_CAIRO_GFX)
615 rv = renderingCtx->Init(mContext, GetThebesSurface());
616 #else
617 rv = renderingCtx->Init(mContext, this);
618 #endif
619 if (NS_SUCCEEDED(rv)) {
620 nsIRenderingContext *ret = renderingCtx;
621 /* Increment object refcount that the |ret| object is still a valid one
622 * after we leave this function... */
623 NS_ADDREF(ret);
624 return ret;
626 else {
627 NS_WARNING("GetRenderingContext: nsIRenderingContext::Init() failed.");
630 else {
631 NS_WARNING("GetRenderingContext: Cannot create RenderingContext.");
634 return nsnull;
637 //-------------------------------------------------------------------------
639 // Return the toolkit this widget was created on
641 //-------------------------------------------------------------------------
642 nsIToolkit* nsBaseWidget::GetToolkit()
644 NS_IF_ADDREF(mToolkit);
645 return mToolkit;
649 //-------------------------------------------------------------------------
651 // Return the used device context
653 //-------------------------------------------------------------------------
654 nsIDeviceContext* nsBaseWidget::GetDeviceContext()
656 return mContext;
659 #ifdef MOZ_CAIRO_GFX
660 //-------------------------------------------------------------------------
662 // Get the thebes surface
664 //-------------------------------------------------------------------------
665 gfxASurface *nsBaseWidget::GetThebesSurface()
667 nsIWidget *parent = GetParent();
668 if (!parent)
669 return nsnull;
671 // in theory we should get our parent's surface,
672 // clone it, and set a device offset before returning
673 return nsnull;
675 #endif
677 //-------------------------------------------------------------------------
679 // Destroy the window
681 //-------------------------------------------------------------------------
682 void nsBaseWidget::OnDestroy()
684 // release references to device context, toolkit, and app shell
685 NS_IF_RELEASE(mContext);
686 NS_IF_RELEASE(mToolkit);
689 NS_METHOD nsBaseWidget::SetWindowClass(const nsAString& xulWinType)
691 return NS_ERROR_NOT_IMPLEMENTED;
694 NS_METHOD nsBaseWidget::SetBorderStyle(nsBorderStyle aBorderStyle)
696 mBorderStyle = aBorderStyle;
697 return NS_OK;
702 * Processes a mouse pressed event
705 NS_METHOD nsBaseWidget::AddMouseListener(nsIMouseListener * aListener)
707 NS_PRECONDITION(mMouseListener == nsnull, "Null mouse listener");
708 NS_IF_RELEASE(mMouseListener);
709 NS_ADDREF(aListener);
710 mMouseListener = aListener;
711 return NS_OK;
715 * Processes a mouse pressed event
718 NS_METHOD nsBaseWidget::AddEventListener(nsIEventListener * aListener)
720 NS_PRECONDITION(mEventListener == nsnull, "Null mouse listener");
721 NS_IF_RELEASE(mEventListener);
722 NS_ADDREF(aListener);
723 mEventListener = aListener;
724 return NS_OK;
728 * Add a menu listener
729 * This interface should only be called by the menu services manager
730 * This will AddRef() the menu listener
731 * This will Release() a previously set menu listener
735 NS_METHOD nsBaseWidget::AddMenuListener(nsIMenuListener * aListener)
737 NS_IF_RELEASE(mMenuListener);
738 NS_IF_ADDREF(aListener);
739 mMenuListener = aListener;
740 return NS_OK;
745 * If the implementation of nsWindow supports borders this method MUST be overridden
748 NS_METHOD nsBaseWidget::GetClientBounds(nsRect &aRect)
750 return GetBounds(aRect);
754 * If the implementation of nsWindow supports borders this method MUST be overridden
757 NS_METHOD nsBaseWidget::GetBounds(nsRect &aRect)
759 aRect = mBounds;
760 return NS_OK;
764 * If the implementation of nsWindow uses a local coordinate system within the window,
765 * this method must be overridden
768 NS_METHOD nsBaseWidget::GetScreenBounds(nsRect &aRect)
770 return GetBounds(aRect);
777 NS_METHOD nsBaseWidget::SetBounds(const nsRect &aRect)
779 mBounds = aRect;
781 return NS_OK;
787 * Calculates the border width and height
790 NS_METHOD nsBaseWidget::GetBorderSize(PRInt32 &aWidth, PRInt32 &aHeight)
792 nsRect rectWin;
793 nsRect rect;
794 GetBounds(rectWin);
795 GetClientBounds(rect);
797 aWidth = (rectWin.width - rect.width) / 2;
798 aHeight = (rectWin.height - rect.height) / 2;
800 return NS_OK;
803 NS_IMETHODIMP nsBaseWidget::ScrollWidgets(PRInt32 aDx, PRInt32 aDy)
805 return NS_ERROR_FAILURE;
808 NS_IMETHODIMP nsBaseWidget::ScrollRect(nsRect &aRect, PRInt32 aDx, PRInt32 aDy)
810 return NS_ERROR_FAILURE;
813 NS_METHOD nsBaseWidget::EnableDragDrop(PRBool aEnable)
815 return NS_OK;
818 NS_METHOD nsBaseWidget::SetModal(PRBool aModal)
820 return NS_ERROR_FAILURE;
823 // generic xp assumption is that events should be processed
824 NS_METHOD nsBaseWidget::ModalEventFilter(PRBool aRealEvent, void *aEvent,
825 PRBool *aForWindow)
827 *aForWindow = PR_TRUE;
828 return NS_OK;
831 NS_IMETHODIMP
832 nsBaseWidget::GetAttention(PRInt32 aCycleCount) {
833 return NS_OK;
836 NS_IMETHODIMP
837 nsBaseWidget::GetLastInputEventTime(PRUint32& aTime) {
838 return NS_ERROR_NOT_IMPLEMENTED;
841 NS_IMETHODIMP
842 nsBaseWidget::SetIcon(const nsAString&)
844 return NS_OK;
847 NS_IMETHODIMP
848 nsBaseWidget::SetAnimatedResize(PRUint16 aAnimation)
850 return NS_ERROR_NOT_IMPLEMENTED;
853 NS_IMETHODIMP
854 nsBaseWidget::GetAnimatedResize(PRUint16* aAnimation)
856 return NS_ERROR_NOT_IMPLEMENTED;
860 * Modifies aFile to point at an icon file with the given name and suffix. The
861 * suffix may correspond to a file extension with leading '.' if appropriate.
862 * Returns true if the icon file exists and can be read.
864 static PRBool
865 ResolveIconNameHelper(nsILocalFile *aFile,
866 const nsAString &aIconName,
867 const nsAString &aIconSuffix)
869 aFile->Append(NS_LITERAL_STRING("icons"));
870 aFile->Append(NS_LITERAL_STRING("default"));
871 aFile->Append(aIconName + aIconSuffix);
873 PRBool readable;
874 return NS_SUCCEEDED(aFile->IsReadable(&readable)) && readable;
878 * Resolve the given icon name into a local file object. This method is
879 * intended to be called by subclasses of nsBaseWidget. aIconSuffix is a
880 * platform specific icon file suffix (e.g., ".ico" under Win32).
882 * If no file is found matching the given parameters, then null is returned.
884 void
885 nsBaseWidget::ResolveIconName(const nsAString &aIconName,
886 const nsAString &aIconSuffix,
887 nsILocalFile **aResult)
889 *aResult = nsnull;
891 nsCOMPtr<nsIProperties> dirSvc = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
892 if (!dirSvc)
893 return;
895 // first check auxilary chrome directories
897 nsCOMPtr<nsISimpleEnumerator> dirs;
898 dirSvc->Get(NS_APP_CHROME_DIR_LIST, NS_GET_IID(nsISimpleEnumerator),
899 getter_AddRefs(dirs));
900 if (dirs) {
901 PRBool hasMore;
902 while (NS_SUCCEEDED(dirs->HasMoreElements(&hasMore)) && hasMore) {
903 nsCOMPtr<nsISupports> element;
904 dirs->GetNext(getter_AddRefs(element));
905 if (!element)
906 continue;
907 nsCOMPtr<nsILocalFile> file = do_QueryInterface(element);
908 if (!file)
909 continue;
910 if (ResolveIconNameHelper(file, aIconName, aIconSuffix)) {
911 NS_ADDREF(*aResult = file);
912 return;
917 // then check the main app chrome directory
919 nsCOMPtr<nsILocalFile> file;
920 dirSvc->Get(NS_APP_CHROME_DIR, NS_GET_IID(nsILocalFile),
921 getter_AddRefs(file));
922 if (file && ResolveIconNameHelper(file, aIconName, aIconSuffix))
923 NS_ADDREF(*aResult = file);
926 #ifdef DEBUG
927 //////////////////////////////////////////////////////////////
929 // Convert a GUI event message code to a string.
930 // Makes it a lot easier to debug events.
932 // See gtk/nsWidget.cpp and windows/nsWindow.cpp
933 // for a DebugPrintEvent() function that uses
934 // this.
936 //////////////////////////////////////////////////////////////
937 /* static */ nsAutoString
938 nsBaseWidget::debug_GuiEventToString(nsGUIEvent * aGuiEvent)
940 NS_ASSERTION(nsnull != aGuiEvent,"cmon, null gui event.");
942 nsAutoString eventName(NS_LITERAL_STRING("UNKNOWN"));
944 #define _ASSIGN_eventName(_value,_name)\
945 case _value: eventName.AssignWithConversion(_name) ; break
947 switch(aGuiEvent->message)
949 _ASSIGN_eventName(NS_BLUR_CONTENT,"NS_BLUR_CONTENT");
950 _ASSIGN_eventName(NS_CONTROL_CHANGE,"NS_CONTROL_CHANGE");
951 _ASSIGN_eventName(NS_CREATE,"NS_CREATE");
952 _ASSIGN_eventName(NS_DESTROY,"NS_DESTROY");
953 _ASSIGN_eventName(NS_DRAGDROP_GESTURE,"NS_DND_GESTURE");
954 _ASSIGN_eventName(NS_DRAGDROP_DROP,"NS_DND_DROP");
955 _ASSIGN_eventName(NS_DRAGDROP_ENTER,"NS_DND_ENTER");
956 _ASSIGN_eventName(NS_DRAGDROP_EXIT,"NS_DND_EXIT");
957 _ASSIGN_eventName(NS_DRAGDROP_OVER,"NS_DND_OVER");
958 _ASSIGN_eventName(NS_FOCUS_CONTENT,"NS_FOCUS_CONTENT");
959 _ASSIGN_eventName(NS_FORM_SELECTED,"NS_FORM_SELECTED");
960 _ASSIGN_eventName(NS_FORM_CHANGE,"NS_FORM_CHANGE");
961 _ASSIGN_eventName(NS_FORM_INPUT,"NS_FORM_INPUT");
962 _ASSIGN_eventName(NS_FORM_RESET,"NS_FORM_RESET");
963 _ASSIGN_eventName(NS_FORM_SUBMIT,"NS_FORM_SUBMIT");
964 _ASSIGN_eventName(NS_GOTFOCUS,"NS_GOTFOCUS");
965 _ASSIGN_eventName(NS_IMAGE_ABORT,"NS_IMAGE_ABORT");
966 _ASSIGN_eventName(NS_LOAD_ERROR,"NS_LOAD_ERROR");
967 _ASSIGN_eventName(NS_KEY_DOWN,"NS_KEY_DOWN");
968 _ASSIGN_eventName(NS_KEY_PRESS,"NS_KEY_PRESS");
969 _ASSIGN_eventName(NS_KEY_UP,"NS_KEY_UP");
970 _ASSIGN_eventName(NS_LOSTFOCUS,"NS_LOSTFOCUS");
971 _ASSIGN_eventName(NS_MENU_SELECTED,"NS_MENU_SELECTED");
972 _ASSIGN_eventName(NS_MOUSE_ENTER,"NS_MOUSE_ENTER");
973 _ASSIGN_eventName(NS_MOUSE_EXIT,"NS_MOUSE_EXIT");
974 _ASSIGN_eventName(NS_MOUSE_BUTTON_DOWN,"NS_MOUSE_BUTTON_DOWN");
975 _ASSIGN_eventName(NS_MOUSE_BUTTON_UP,"NS_MOUSE_BUTTON_UP");
976 _ASSIGN_eventName(NS_MOUSE_CLICK,"NS_MOUSE_CLICK");
977 _ASSIGN_eventName(NS_MOUSE_DOUBLECLICK,"NS_MOUSE_DBLCLICK");
978 _ASSIGN_eventName(NS_MOUSE_MOVE,"NS_MOUSE_MOVE");
979 _ASSIGN_eventName(NS_MOVE,"NS_MOVE");
980 _ASSIGN_eventName(NS_LOAD,"NS_LOAD");
981 _ASSIGN_eventName(NS_PAGE_UNLOAD,"NS_PAGE_UNLOAD");
982 _ASSIGN_eventName(NS_PAINT,"NS_PAINT");
983 _ASSIGN_eventName(NS_XUL_BROADCAST, "NS_XUL_BROADCAST");
984 _ASSIGN_eventName(NS_XUL_COMMAND_UPDATE, "NS_XUL_COMMAND_UPDATE");
985 _ASSIGN_eventName(NS_SCROLLBAR_LINE_NEXT,"NS_SB_LINE_NEXT");
986 _ASSIGN_eventName(NS_SCROLLBAR_LINE_PREV,"NS_SB_LINE_PREV");
987 _ASSIGN_eventName(NS_SCROLLBAR_PAGE_NEXT,"NS_SB_PAGE_NEXT");
988 _ASSIGN_eventName(NS_SCROLLBAR_PAGE_PREV,"NS_SB_PAGE_PREV");
989 _ASSIGN_eventName(NS_SCROLLBAR_POS,"NS_SB_POS");
990 _ASSIGN_eventName(NS_SIZE,"NS_SIZE");
992 #undef _ASSIGN_eventName
994 default:
996 char buf[32];
998 sprintf(buf,"UNKNOWN: %d",aGuiEvent->message);
1000 eventName.AssignWithConversion(buf);
1002 break;
1005 return nsAutoString(eventName);
1007 //////////////////////////////////////////////////////////////
1009 // Code to deal with paint and event debug prefs.
1011 //////////////////////////////////////////////////////////////
1012 struct PrefPair
1014 const char * name;
1015 PRBool value;
1018 static PrefPair debug_PrefValues[] =
1020 { "nglayout.debug.crossing_event_dumping", PR_FALSE },
1021 { "nglayout.debug.event_dumping", PR_FALSE },
1022 { "nglayout.debug.invalidate_dumping", PR_FALSE },
1023 { "nglayout.debug.motion_event_dumping", PR_FALSE },
1024 { "nglayout.debug.paint_dumping", PR_FALSE },
1025 { "nglayout.debug.paint_flashing", PR_FALSE }
1028 static PRUint32 debug_NumPrefValues =
1029 (sizeof(debug_PrefValues) / sizeof(debug_PrefValues[0]));
1032 //////////////////////////////////////////////////////////////
1033 static PRBool debug_GetBoolPref(nsIPrefBranch * aPrefs,const char * aPrefName)
1035 NS_ASSERTION(nsnull != aPrefName,"cmon, pref name is null.");
1036 NS_ASSERTION(nsnull != aPrefs,"cmon, prefs are null.");
1038 PRBool value = PR_FALSE;
1040 if (aPrefs)
1042 aPrefs->GetBoolPref(aPrefName,&value);
1045 return value;
1047 //////////////////////////////////////////////////////////////
1048 PRBool
1049 nsBaseWidget::debug_GetCachedBoolPref(const char * aPrefName)
1051 NS_ASSERTION(nsnull != aPrefName,"cmon, pref name is null.");
1053 for (PRUint32 i = 0; i < debug_NumPrefValues; i++)
1055 if (strcmp(debug_PrefValues[i].name, aPrefName) == 0)
1057 return debug_PrefValues[i].value;
1061 return PR_FALSE;
1063 //////////////////////////////////////////////////////////////
1064 static void debug_SetCachedBoolPref(const char * aPrefName,PRBool aValue)
1066 NS_ASSERTION(nsnull != aPrefName,"cmon, pref name is null.");
1068 for (PRUint32 i = 0; i < debug_NumPrefValues; i++)
1070 if (strcmp(debug_PrefValues[i].name, aPrefName) == 0)
1072 debug_PrefValues[i].value = aValue;
1074 return;
1078 NS_ASSERTION(PR_FALSE, "cmon, this code is not reached dude.");
1081 //////////////////////////////////////////////////////////////
1082 class Debug_PrefObserver : public nsIObserver {
1083 public:
1084 NS_DECL_ISUPPORTS
1085 NS_DECL_NSIOBSERVER
1088 NS_IMPL_ISUPPORTS1(Debug_PrefObserver, nsIObserver)
1090 NS_IMETHODIMP
1091 Debug_PrefObserver::Observe(nsISupports* subject, const char* topic,
1092 const PRUnichar* data)
1094 nsCOMPtr<nsIPrefBranch> branch(do_QueryInterface(subject));
1095 NS_ASSERTION(branch, "must implement nsIPrefBranch");
1097 NS_ConvertUTF16toUTF8 prefName(data);
1099 PRBool value = PR_FALSE;
1100 branch->GetBoolPref(prefName.get(), &value);
1101 debug_SetCachedBoolPref(prefName.get(), value);
1102 return NS_OK;
1105 //////////////////////////////////////////////////////////////
1106 /* static */ void
1107 debug_RegisterPrefCallbacks()
1109 static PRBool once = PR_TRUE;
1111 if (once)
1113 once = PR_FALSE;
1115 nsCOMPtr<nsIPrefBranch2> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
1117 NS_ASSERTION(prefs, "Prefs services is null.");
1119 if (prefs)
1121 nsCOMPtr<nsIObserver> obs(new Debug_PrefObserver());
1122 for (PRUint32 i = 0; i < debug_NumPrefValues; i++)
1124 // Initialize the pref values
1125 debug_PrefValues[i].value =
1126 debug_GetBoolPref(prefs,debug_PrefValues[i].name);
1128 if (obs) {
1129 // Register callbacks for when these change
1130 prefs->AddObserver(debug_PrefValues[i].name, obs, PR_FALSE);
1136 //////////////////////////////////////////////////////////////
1137 static PRInt32
1138 _GetPrintCount()
1140 static PRInt32 sCount = 0;
1142 return ++sCount;
1144 //////////////////////////////////////////////////////////////
1145 /* static */ PRBool
1146 nsBaseWidget::debug_WantPaintFlashing()
1148 return debug_GetCachedBoolPref("nglayout.debug.paint_flashing");
1150 //////////////////////////////////////////////////////////////
1151 /* static */ void
1152 nsBaseWidget::debug_DumpEvent(FILE * aFileOut,
1153 nsIWidget * aWidget,
1154 nsGUIEvent * aGuiEvent,
1155 const nsCAutoString & aWidgetName,
1156 PRInt32 aWindowID)
1158 // NS_PAINT is handled by debug_DumpPaintEvent()
1159 if (aGuiEvent->message == NS_PAINT)
1160 return;
1162 if (aGuiEvent->message == NS_MOUSE_MOVE)
1164 if (!debug_GetCachedBoolPref("nglayout.debug.motion_event_dumping"))
1165 return;
1168 if (aGuiEvent->message == NS_MOUSE_ENTER ||
1169 aGuiEvent->message == NS_MOUSE_EXIT)
1171 if (!debug_GetCachedBoolPref("nglayout.debug.crossing_event_dumping"))
1172 return;
1175 if (!debug_GetCachedBoolPref("nglayout.debug.event_dumping"))
1176 return;
1178 nsCAutoString tempString; tempString.AssignWithConversion(debug_GuiEventToString(aGuiEvent).get());
1180 fprintf(aFileOut,
1181 "%4d %-26s widget=%-8p name=%-12s id=%-8p refpt=%d,%d\n",
1182 _GetPrintCount(),
1183 tempString.get(),
1184 (void *) aWidget,
1185 aWidgetName.get(),
1186 (void *) (aWindowID ? aWindowID : 0x0),
1187 aGuiEvent->refPoint.x,
1188 aGuiEvent->refPoint.y);
1190 //////////////////////////////////////////////////////////////
1191 /* static */ void
1192 nsBaseWidget::debug_DumpPaintEvent(FILE * aFileOut,
1193 nsIWidget * aWidget,
1194 nsPaintEvent * aPaintEvent,
1195 const nsCAutoString & aWidgetName,
1196 PRInt32 aWindowID)
1198 NS_ASSERTION(nsnull != aFileOut,"cmon, null output FILE");
1199 NS_ASSERTION(nsnull != aWidget,"cmon, the widget is null");
1200 NS_ASSERTION(nsnull != aPaintEvent,"cmon, the paint event is null");
1202 if (!debug_GetCachedBoolPref("nglayout.debug.paint_dumping"))
1203 return;
1205 fprintf(aFileOut,
1206 "%4d PAINT widget=%p name=%-12s id=%-8p rect=",
1207 _GetPrintCount(),
1208 (void *) aWidget,
1209 aWidgetName.get(),
1210 (void *) aWindowID);
1212 if (aPaintEvent->rect)
1214 fprintf(aFileOut,
1215 "%3d,%-3d %3d,%-3d",
1216 aPaintEvent->rect->x,
1217 aPaintEvent->rect->y,
1218 aPaintEvent->rect->width,
1219 aPaintEvent->rect->height);
1221 else
1223 fprintf(aFileOut,"none");
1226 fprintf(aFileOut,"\n");
1228 //////////////////////////////////////////////////////////////
1229 /* static */ void
1230 nsBaseWidget::debug_DumpInvalidate(FILE * aFileOut,
1231 nsIWidget * aWidget,
1232 const nsRect * aRect,
1233 PRBool aIsSynchronous,
1234 const nsCAutoString & aWidgetName,
1235 PRInt32 aWindowID)
1237 if (!debug_GetCachedBoolPref("nglayout.debug.invalidate_dumping"))
1238 return;
1240 NS_ASSERTION(nsnull != aFileOut,"cmon, null output FILE");
1241 NS_ASSERTION(nsnull != aWidget,"cmon, the widget is null");
1243 fprintf(aFileOut,
1244 "%4d Invalidate widget=%p name=%-12s id=%-8p",
1245 _GetPrintCount(),
1246 (void *) aWidget,
1247 aWidgetName.get(),
1248 (void *) aWindowID);
1250 if (aRect)
1252 fprintf(aFileOut,
1253 " rect=%3d,%-3d %3d,%-3d",
1254 aRect->x,
1255 aRect->y,
1256 aRect->width,
1257 aRect->height);
1259 else
1261 fprintf(aFileOut,
1262 " rect=%-15s",
1263 "none");
1266 fprintf(aFileOut,
1267 " sync=%s",
1268 (const char *) (aIsSynchronous ? "yes" : "no "));
1270 fprintf(aFileOut,"\n");
1272 //////////////////////////////////////////////////////////////
1274 #endif // DEBUG