Back to index

lightning-sunbird  0.9+nobinonly
nsWidget.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Peter Hartshorn <peter@igelaus.com.au>
00024  *   Ken Faulkner <faulkner@igelaus.com.au>
00025  *   Quy Tonthat <quy@igelaus.com.au>
00026  *   B.J. Rossiter <bj@igelaus.com.au>
00027  *   Tony Tsui <tony@igelaus.com.au>
00028  *   L. David Baron <dbaron@dbaron.org>
00029  *   Tim Copperfield <timecop@network.email.ne.jp>
00030  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
00031  *
00032  * Alternatively, the contents of this file may be used under the terms of
00033  * either the GNU General Public License Version 2 or later (the "GPL"), or
00034  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00035  * in which case the provisions of the GPL or the LGPL are applicable instead
00036  * of those above. If you wish to allow use of your version of this file only
00037  * under the terms of either the GPL or the LGPL, and not to allow others to
00038  * use your version of this file under the terms of the MPL, indicate your
00039  * decision by deleting the provisions above and replace them with the notice
00040  * and other provisions required by the GPL or the LGPL. If you do not delete
00041  * the provisions above, a recipient may use your version of this file under
00042  * the terms of any one of the MPL, the GPL or the LGPL.
00043  *
00044  * ***** END LICENSE BLOCK ***** */
00045 
00046 #undef DEBUG_CURSORCACHE
00047 
00048 #include "nsWidget.h"
00049 #include "nsIServiceManager.h"
00050 #include "nsAppShell.h"
00051 
00052 #include <X11/Xatom.h>
00053 #include <X11/cursorfont.h>
00054 #include "nsXlibCursors.h"
00055 
00056 #include "nsIEventListener.h"
00057 #include "nsIMenuListener.h"
00058 #include "nsIMouseListener.h"
00059 #include "nsIRollupListener.h"
00060 #include "nsGfxCIID.h"
00061 #include "nsIMenuRollup.h"
00062 #include "nsIRenderingContext.h"
00063 #include "nsToolkit.h"
00064 
00065 #include "xlibrgb.h"
00066 
00067 static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
00068 
00069 PRLogModuleInfo *XlibWidgetsLM   = PR_NewLogModule("XlibWidgets");
00070 PRLogModuleInfo *XlibScrollingLM = PR_NewLogModule("XlibScrolling");
00071 
00072 // set up our static members here.
00073 nsHashtable *nsWidget::gsWindowList = nsnull; // WEAK references to nsWidget*
00074 
00075 // cursors hash table
00076 Cursor nsWidget::gsXlibCursorCache[eCursorCount];
00077 
00078 // this is for implemention the WM_PROTOCOL code
00079 PRBool nsWidget::WMProtocolsInitialized = PR_FALSE;
00080 Atom   nsWidget::WMDeleteWindow = 0;
00081 Atom   nsWidget::WMTakeFocus    = 0;
00082 Atom   nsWidget::WMSaveYourself = 0;
00083 
00084 // this is the window that has the focus
00085 Window nsWidget::mFocusWindow = 0;
00086 
00087 // For popup handling
00088 nsCOMPtr<nsIRollupListener> nsWidget::gRollupListener;
00089 nsWeakPtr          nsWidget::gRollupWidget;
00090 PRBool             nsWidget::gRollupConsumeRollupEvent = PR_FALSE;
00091 
00092 class nsWindowKey : public nsHashKey {
00093 protected:
00094   Window mKey;
00095 
00096 public:
00097   nsWindowKey(Window key) {
00098     mKey = key;
00099   }
00100   ~nsWindowKey(void) {
00101   }
00102   PRUint32 HashCode(void) const {
00103     return (PRUint32)mKey;
00104   }
00105 
00106   PRBool Equals(const nsHashKey *aKey) const {
00107     return (mKey == ((nsWindowKey *)aKey)->mKey);
00108   }
00109 
00110   nsHashKey *Clone(void) const {
00111     return new nsWindowKey(mKey);
00112   }
00113 };
00114 
00115 nsWidget::nsWidget() // : nsBaseWidget()
00116 {
00117   mPreferredWidth = 0;
00118   mPreferredHeight = 0;
00119 
00120   mDisplay = 0;
00121   mScreen = 0;
00122   mVisual = 0;
00123   mDepth = 0;
00124 
00125   mBaseWindow = 0;
00126   mBackground = NS_RGB(192, 192, 192);
00127   mBorderRGB = NS_RGB(192, 192, 192);
00128   /* |xxlib_find_handle(XXLIBRGB_DEFAULT_HANDLE)| would be the official 
00129    * way - but |nsAppShell::GetXlibRgbHandle()| one is little bit faster...*/
00130   mXlibRgbHandle = nsAppShell::GetXlibRgbHandle();
00131   mBackgroundPixel = xxlib_rgb_xpixel_from_rgb(mXlibRgbHandle, mBackground);
00132   mBackground = NS_RGB(192, 192, 192);
00133   mBorderPixel = xxlib_rgb_xpixel_from_rgb(mXlibRgbHandle, mBorderRGB);
00134   mParentWidget = nsnull;
00135   mName.AssignLiteral("unnamed");
00136   mIsShown = PR_FALSE;
00137   mIsToplevel = PR_FALSE;
00138   mVisibility = VisibilityFullyObscured; // this is an X constant.
00139   mWindowType = eWindowType_child;
00140   mBorderStyle = eBorderStyle_default;
00141 
00142   // added KenF 
00143   mIsDestroying = PR_FALSE;
00144   mOnDestroyCalled = PR_FALSE;
00145   mListenForResizes = PR_FALSE; // If we're native we need to listen.
00146   mMapped = PR_FALSE;
00147 
00148 
00149   mUpdateArea = do_CreateInstance(kRegionCID);
00150   if (mUpdateArea) {
00151     mUpdateArea->Init();
00152     mUpdateArea->SetTo(0, 0, 0, 0);
00153   }
00154 }
00155 
00156 // FIXME:
00157 // Heavily modifying so functionally similar as gtk version. KenF
00158 nsWidget::~nsWidget()
00159 {
00160   //mIsDestroying = TRUE;
00161 
00162   if (mBaseWindow)
00163     Destroy();
00164 }
00165 
00166 // Borrowed heavily from GTK. This should go through heirarchy of XWindow
00167 // windows, and destroy the appropriate children. 
00168 // KenF
00169 void
00170 nsWidget::DestroyNativeChildren(Display *aDisplay, Window aWindow)
00171 {
00172   Window       root_return;
00173   Window       parent_return;
00174   Window      *children_return = nsnull;
00175   unsigned int nchildren_return = 0;
00176   unsigned int i = 0;
00177   
00178   XQueryTree(aDisplay, aWindow, &root_return, &parent_return,
00179              &children_return, &nchildren_return);
00180   // walk the list of children
00181   for (i=0; i < nchildren_return; i++) {
00182     nsWidget *thisWidget = GetWidgetForWindow(children_return[i]);
00183     if (thisWidget) {
00184       thisWidget->Destroy();
00185     }
00186   }      
00187 
00188   // free up this struct
00189   if (children_return)
00190     XFree(children_return);
00191 }
00192 
00193 void
00194 nsWidget::DestroyNative()
00195 {
00196   NS_ASSERTION(mBaseWindow, "no native window");
00197 
00198   // We have to destroy the children ourselves before we call XDestroyWindow
00199   // because otherwise XDestroyWindow will destroy the windows and leave us
00200   // with dangling references.
00201   DestroyNativeChildren(mDisplay, mBaseWindow);
00202 
00203   XDestroyWindow(mDisplay, mBaseWindow);
00204   DeleteWindowCallback(mBaseWindow);
00205 }
00206 
00207 // Stub in nsWidget, real in nsWindow. KenF
00208 void * nsWidget::CheckParent(long ThisWindow)
00209 {
00210   return (void*)-1;
00211 }
00212 
00213 NS_IMETHODIMP nsWidget::Create(nsIWidget *aParent,
00214                                const nsRect &aRect,
00215                                EVENT_CALLBACK aHandleEventFunction,
00216                                nsIDeviceContext *aContext,
00217                                nsIAppShell *aAppShell,
00218                                nsIToolkit *aToolkit,
00219                                nsWidgetInitData *aInitData)
00220 {
00221   // Do adding in SWC() KenF
00222   //mParentWidget = aParent;
00223   //NS_IF_ADDREF(mParentWidget); // KenF FIXME
00224 
00225   return StandardWidgetCreate(aParent, aRect, aHandleEventFunction,
00226                               aContext, aAppShell, aToolkit, aInitData,
00227                               nsnull);
00228 }
00229 
00230 NS_IMETHODIMP nsWidget::Create(nsNativeWidget aParent,
00231                                const nsRect &aRect,
00232                                EVENT_CALLBACK aHandleEventFunction,
00233                                nsIDeviceContext *aContext,
00234                                nsIAppShell *aAppShell,
00235                                nsIToolkit *aToolkit,
00236                                nsWidgetInitData *aInitData)
00237 {
00238   return(StandardWidgetCreate(nsnull, aRect, aHandleEventFunction,
00239                               aContext, aAppShell, aToolkit, aInitData,
00240                               aParent));
00241 }
00242 
00243 nsresult
00244 nsWidget::StandardWidgetCreate(nsIWidget *aParent,
00245                                const nsRect &aRect,
00246                                EVENT_CALLBACK aHandleEventFunction,
00247                                nsIDeviceContext *aContext,
00248                                nsIAppShell *aAppShell,
00249                                nsIToolkit *aToolkit,
00250                                nsWidgetInitData *aInitData,
00251                                nsNativeWidget aNativeParent)
00252 {
00253   unsigned long attr_mask;
00254   XSetWindowAttributes attr;
00255   Window parent=nsnull;
00256 
00257   NS_ASSERTION(!mBaseWindow, "already initialized");
00258   if (mBaseWindow) return NS_ERROR_ALREADY_INITIALIZED;
00259 
00260   mDisplay = xxlib_rgb_get_display(mXlibRgbHandle);
00261   mScreen = xxlib_rgb_get_screen(mXlibRgbHandle);
00262   mVisual = xxlib_rgb_get_visual(mXlibRgbHandle);
00263   mDepth = xxlib_rgb_get_depth(mXlibRgbHandle);
00264 
00265   mParentWidget = aParent;
00266 
00267   NS_IF_ADDREF(mParentWidget);
00268 
00269   mBounds = aRect;
00270 
00271   if (mBounds.width <= 0)
00272     mBounds.width = 1;
00273   if (mBounds.height <= 0)
00274     mBounds.height = 1;
00275 
00276   BaseCreate(mParentWidget, mBounds, aHandleEventFunction, aContext,
00277              aAppShell, aToolkit, aInitData);
00278 
00279   if (aNativeParent) {
00280     parent = (Window)aNativeParent;
00281     mListenForResizes = PR_TRUE;
00282   } else if (aParent) {
00283     parent = (Window)aParent->GetNativeData(NS_NATIVE_WINDOW);
00284   } else {
00285     parent = XRootWindowOfScreen(mScreen);
00286   }
00287 
00288   if (nsnull != aInitData) {
00289     mWindowType = aInitData->mWindowType;
00290   }
00291 
00292   mParentWindow = parent;
00293 
00294   attr.bit_gravity       = NorthWestGravity;
00295   attr.event_mask        = GetEventMask();
00296   attr.colormap          = xxlib_rgb_get_cmap(mXlibRgbHandle);
00297   attr.background_pixel  = mBackgroundPixel;
00298   attr.border_pixel      = mBorderPixel;
00299   attr_mask = CWBitGravity | CWEventMask | CWBorderPixel | CWBackPixel;
00300 
00301   if (attr.colormap)
00302     attr_mask |= CWColormap;
00303 
00304   switch (mWindowType) {
00305   case eWindowType_dialog:
00306     mIsToplevel = PR_TRUE;
00307     parent = XRootWindowOfScreen(mScreen);
00308     mBaseWindow = XCreateWindow(mDisplay, parent, mBounds.x, mBounds.y,
00309                                 mBounds.width, mBounds.height, 0,
00310                                 mDepth, InputOutput, mVisual,
00311                                 attr_mask, &attr);
00312     XSetWindowBackgroundPixmap(mDisplay, mBaseWindow, None);
00313     AddWindowCallback(mBaseWindow, this);
00314     SetUpWMHints();
00315     XSetTransientForHint(mDisplay, mBaseWindow, mParentWindow);
00316     break;
00317 
00318   case eWindowType_popup:
00319     mIsToplevel = PR_TRUE;
00320     attr_mask |= CWOverrideRedirect | CWSaveUnder;
00321     attr.save_under = True;
00322     attr.override_redirect = True;
00323     parent = XRootWindowOfScreen(mScreen);
00324     mBaseWindow = XCreateWindow(mDisplay, parent,
00325                                 mBounds.x, mBounds.y,
00326                                 mBounds.width, mBounds.height, 0,
00327                                 mDepth, InputOutput, mVisual,
00328                                 attr_mask, &attr);
00329     XSetWindowBackgroundPixmap(mDisplay, mBaseWindow, None);
00330     AddWindowCallback(mBaseWindow, this);
00331     SetUpWMHints();
00332     XSetTransientForHint(mDisplay, mBaseWindow, mParentWindow);
00333     break;
00334 
00335   case eWindowType_toplevel:
00336   case eWindowType_invisible:
00337     mIsToplevel = PR_TRUE;
00338     parent = XRootWindowOfScreen(mScreen);
00339     mBaseWindow = XCreateWindow(mDisplay, parent, mBounds.x, mBounds.y,
00340                                 mBounds.width, mBounds.height, 0,
00341                                 mDepth, InputOutput, mVisual,
00342                                 attr_mask, &attr);
00343     XSetWindowBackgroundPixmap(mDisplay, mBaseWindow, None);
00344     AddWindowCallback(mBaseWindow, this);
00345     SetUpWMHints();
00346     break;
00347 
00348   case eWindowType_child:
00349     mIsToplevel = PR_FALSE;
00350     // for some reason I need to do this, as opposed to the other cases. FIXME
00351     CreateNative(parent, mBounds);
00352     break;
00353 
00354   default:
00355     break;
00356   }
00357   
00358   return NS_OK;
00359 }
00360 
00361 // FIXME: Being heavily modified so functionally similar to gtk version.
00362 // (just a test) KenF
00363 NS_IMETHODIMP nsWidget::Destroy()
00364 {
00365 
00366   // Dont reenter.
00367   if (mIsDestroying)
00368     return NS_OK;
00369 
00370   mIsDestroying = PR_TRUE;
00371 
00372   nsBaseWidget::Destroy();
00373   NS_IF_RELEASE(mParentWidget); //????
00374   
00375 
00376   if (mBaseWindow) {
00377     DestroyNative();
00378     //mBaseWindow = nsnull;
00379     if (PR_FALSE == mOnDestroyCalled)
00380       OnDestroy();
00381     mBaseWindow = nsnull;
00382     mEventCallback = nsnull;
00383   }
00384 
00385   return NS_OK;
00386 
00387 }
00388 
00389 NS_IMETHODIMP nsWidget::ConstrainPosition(PRBool aAllowSlop,
00390                                           PRInt32 *aX, PRInt32 *aY)
00391 {
00392   return NS_OK;
00393 }
00394 
00395 NS_IMETHODIMP nsWidget::Move(PRInt32 aX, PRInt32 aY)
00396 {
00397   //printf("nsWidget::Move aX=%i, aY=%i\n", aX, aY);
00398   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::Move(x, y)\n"));
00399   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Moving window 0x%lx to %d, %d\n", mBaseWindow, aX, aY));
00400 
00401   if((aX == mBounds.x) && (aY == mBounds.y) && !mIsToplevel) {
00402     //printf("discard this move\n");
00403     return NS_OK;
00404   }
00405 
00406 
00407   mBounds.x = aX;
00408   mBounds.y = aY;
00409 
00410   if (mWindowType == eWindowType_popup) {
00411     nsRect aRect, transRect;
00412     PRInt32 screenWidth = WidthOfScreen(mScreen);
00413     PRInt32 screenHeight = HeightOfScreen(mScreen);
00414 
00415     if (aX >= screenWidth)
00416       aX = screenWidth - mBounds.width;
00417     if (aY >= screenHeight)
00418       aY = screenHeight - mBounds.height;
00419 
00420     aRect.x = aX;
00421     aRect.y = aY;
00422 
00423     if (mParentWidget) {
00424       mParentWidget->WidgetToScreen(aRect, transRect);
00425     } else if (mParentWindow) {
00426       Window child;
00427       XTranslateCoordinates(mDisplay, mParentWindow,
00428                             XRootWindowOfScreen(mScreen),
00429                             aX, aY, &transRect.x, &transRect.y,
00430                             &child);
00431     }
00432     aX = transRect.x;
00433     aY = transRect.y;
00434   }
00435 
00436   mRequestedSize.x = aX;
00437   mRequestedSize.y = aY;
00438   if (mParentWidget) {
00439     ((nsWidget*)mParentWidget)->WidgetMove(this);
00440   } else {
00441     /* Workaround for bug 77344. I am not sure whether this is mandatory or not. */
00442     if (mDisplay)
00443       XMoveWindow(mDisplay, mBaseWindow, aX, aY);
00444   }
00445   return NS_OK;
00446 }
00447 
00448 NS_IMETHODIMP nsWidget::Resize(PRInt32 aWidth,
00449                                PRInt32 aHeight,
00450                                PRBool   aRepaint)
00451 {
00452   //printf("nsWidget::Resize aWidth=%i, Height=%i\n",aWidth, aHeight);
00453   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::Resize(width, height)\n"));
00454 
00455   if (aWidth <= 0) {
00456     PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("*** width is %d, fixing.\n", aWidth));
00457     aWidth = 1;
00458 
00459   }
00460   if (aHeight <= 0) {
00461     PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("*** height is %d, fixing.\n", aHeight));
00462     aHeight = 1;
00463   }
00464 
00465   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Resizing window 0x%lx to %d, %d\n", mBaseWindow, aWidth, aHeight));
00466   mRequestedSize.width = mBounds.width = aWidth;
00467   mRequestedSize.height = mBounds.height = aHeight;
00468 
00469   if (mParentWidget) {
00470     ((nsWidget *)mParentWidget)->WidgetResize(this);
00471   } else {
00472      /* Workaround for bug 77344. I am not sure whether this is mandatory or not. */
00473     if (mDisplay)
00474       XResizeWindow(mDisplay, mBaseWindow, aWidth, aHeight);
00475   }
00476 
00477   return NS_OK;
00478 }
00479 
00480 NS_IMETHODIMP nsWidget::Resize(PRInt32 aX,
00481                                PRInt32 aY,
00482                                PRInt32 aWidth,
00483                                PRInt32 aHeight,
00484                                PRBool   aRepaint)
00485 {
00486   //printf("nsWidget::Resize aX=%i, aY=%i, aWidth=%i, aHeight=%i\n", aX, aY, aWidth, aHeight);
00487   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::Resize(x, y, width, height)\n"));
00488 
00489   if (aWidth <= 0) {
00490     PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("*** width is %d, fixing.\n", aWidth));
00491     aWidth = 1;
00492   }
00493   if (aHeight <= 0) {
00494     PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("*** height is %d, fixing.\n", aHeight));
00495     aHeight = 1;
00496   }
00497   if (aX < 0) {
00498     PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("*** x is %d, fixing.\n", aX));
00499     aX = 0;
00500   }
00501   if (aY < 0) {
00502     PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("*** y is %d, fixing.\n", aY));
00503     aY = 0;
00504   }
00505   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG,
00506          ("Resizing window 0x%lx to %d, %d\n", mBaseWindow, aWidth, aHeight));
00507   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, 
00508          ("Moving window 0x%lx to %d, %d\n", mBaseWindow, aX, aY));
00509   mRequestedSize.x = aX;
00510   mRequestedSize.y = aY;
00511   mRequestedSize.width = mBounds.width = aWidth;
00512   mRequestedSize.height = mBounds.height = aHeight;
00513   if (mParentWidget) {
00514     ((nsWidget *)mParentWidget)->WidgetMoveResize(this);
00515   } else {
00516     XMoveResizeWindow(mDisplay, mBaseWindow, aX, aY, aWidth, aHeight);
00517   }
00518   return NS_OK;
00519 }
00520 
00521 NS_IMETHODIMP nsWidget::Enable(PRBool aState)
00522 {
00523   return NS_OK;
00524 }
00525 
00526 NS_IMETHODIMP nsWidget::IsEnabled(PRBool *aState)
00527 {
00528   NS_ENSURE_ARG_POINTER(aState);
00529   *aState = PR_TRUE;
00530   return NS_ERROR_NOT_IMPLEMENTED;
00531 }
00532 
00533 NS_IMETHODIMP nsWidget::SetFocus(PRBool aRaise)
00534 {
00535 
00536   if (mBaseWindow) {
00537     PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::SetFocus() setting focus to 0x%lx\n", mBaseWindow));
00538     mFocusWindow = mBaseWindow;
00539   }
00540   return NS_OK;
00541 }
00542 
00543 NS_IMETHODIMP nsWidget::SetName(const char * aName)
00544 {
00545   mName.AssignWithConversion(aName);
00546 
00547   return NS_OK;
00548 }
00549 
00550 Window
00551 nsWidget::GetFocusWindow(void)
00552 {
00553   return mFocusWindow;
00554 }
00555 
00556 NS_IMETHODIMP nsWidget::Invalidate(PRBool aIsSynchronous)
00557 {
00558   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::Invalidate(sync)\n"));
00559   return NS_OK;
00560 }
00561 
00562 NS_IMETHODIMP nsWidget::Invalidate(const nsRect & aRect, PRBool aIsSynchronous)
00563 {
00564   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::Invalidate(rect, sync)\n"));
00565   return NS_OK;
00566 }
00567 
00568 nsIFontMetrics* nsWidget::GetFont(void)
00569 {
00570   return nsnull;
00571 }
00572 
00573 NS_IMETHODIMP nsWidget::GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight)
00574 {
00575   return NS_OK;
00576 }
00577 
00578 NS_IMETHODIMP nsWidget::SetMenuBar(nsIMenuBar * aMenuBar)
00579 {
00580   return NS_OK;
00581 }
00582 
00583 NS_IMETHODIMP nsWidget::ShowMenuBar(PRBool aShow)
00584 {
00585   return NS_OK;
00586 }
00587 
00588 void * nsWidget::GetNativeData(PRUint32 aDataType)
00589 {
00590   switch (aDataType) {
00591   case NS_NATIVE_WIDGET:
00592   case NS_NATIVE_WINDOW:
00593   case NS_NATIVE_PLUGIN_PORT:
00594     return (void *)mBaseWindow;
00595     break;
00596   case NS_NATIVE_DISPLAY:
00597     return (void *)mDisplay;
00598     break;
00599   case NS_NATIVE_GRAPHIC:
00600     NS_ASSERTION(nsnull != mToolkit, "NULL toolkit, unable to get a GC");
00601     return (void *)NS_STATIC_CAST(nsToolkit*,mToolkit)->GetSharedGC();
00602     break;
00603   default:
00604     fprintf(stderr, "nsWidget::GetNativeData(%d) called with crap value.\n",
00605             aDataType);
00606     return nsnull;
00607     break;
00608   }
00609 }
00610 
00611 NS_IMETHODIMP nsWidget::SetTooltips(PRUint32 aNumberOfTips,
00612                                     nsRect* aTooltipAreas[])
00613 {
00614   return NS_OK;
00615 }
00616 
00617 NS_IMETHODIMP nsWidget::UpdateTooltips(nsRect* aNewTips[])
00618 {
00619   return NS_OK;
00620 }
00621 
00622 NS_IMETHODIMP nsWidget::RemoveTooltips()
00623 {
00624   return NS_OK;
00625 }
00626 
00627 NS_IMETHODIMP nsWidget::SetFont(const nsFont &aFont)
00628 {
00629   return NS_OK;
00630 }
00631 
00632 NS_IMETHODIMP nsWidget::BeginResizingChildren(void)
00633 {
00634   return NS_OK;
00635 }
00636 
00637 NS_IMETHODIMP nsWidget::EndResizingChildren(void)
00638 {
00639   return NS_OK;
00640 }
00641 
00642 NS_IMETHODIMP nsWidget::SetColorMap(nsColorMap *aColorMap)
00643 {
00644   return NS_OK;
00645 }
00646 
00647 NS_IMETHODIMP nsWidget::Show(PRBool bState)
00648 {
00649   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::Show()\n"));
00650   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("state is %d\n", bState));
00651 
00652   if (bState) {
00653         Map();
00654   } else {
00655       Unmap();
00656     }
00657   return NS_OK;
00658 }
00659 
00660 NS_IMETHODIMP nsWidget::IsVisible(PRBool &aState)
00661 {
00662   if (mVisibility != VisibilityFullyObscured) {
00663   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::IsVisible: yes\n"));
00664     aState = PR_TRUE;
00665   }
00666   else {
00667     PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::IsVisible: no\n"));
00668     aState = PR_FALSE;
00669   }
00670   return NS_OK;
00671 }
00672 
00673 NS_IMETHODIMP nsWidget::SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight)
00674 {
00675   return NS_OK;
00676 }
00677 
00678 NS_IMETHODIMP nsWidget::Update()
00679 {
00680   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::Update()\n"));
00681   return NS_OK;
00682 }
00683 
00684 NS_IMETHODIMP nsWidget::SetBackgroundColor(const nscolor &aColor)
00685 {
00686   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("nsWidget::SetBackgroundColor()\n"));
00687 
00688   nsBaseWidget::SetBackgroundColor(aColor);
00689   mBackgroundPixel = xxlib_rgb_xpixel_from_rgb(mXlibRgbHandle, mBackground);
00690   // set the window attrib
00691   XSetWindowBackground(mDisplay, mBaseWindow, mBackgroundPixel);
00692   return NS_OK;
00693 }
00694 
00695 NS_IMETHODIMP nsWidget::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
00696 {
00697   return NS_OK;
00698 }
00699 
00700 NS_IMPL_ISUPPORTS_INHERITED1(nsWidget, nsBaseWidget, nsISupportsWeakReference)
00701 
00702 NS_IMETHODIMP nsWidget::WidgetToScreen(const nsRect& aOldRect,
00703                                        nsRect& aNewRect)
00704 {
00705   Window child;
00706   XTranslateCoordinates(mDisplay,
00707                         mBaseWindow,
00708                         XRootWindowOfScreen(mScreen),
00709                         aOldRect.x, aOldRect.y,
00710                         &aNewRect.x, &aNewRect.y,
00711                         &child);
00712   return NS_OK;
00713 }
00714 
00715 NS_IMETHODIMP nsWidget::ScreenToWidget(const nsRect& aOldRect,
00716                                        nsRect& aNewRect)
00717 {
00718   return NS_OK;
00719 }
00720 
00721 NS_IMETHODIMP nsWidget::SetCursor(nsCursor aCursor)
00722 {
00723 
00724   if (!mBaseWindow)
00725     return NS_ERROR_FAILURE;
00726 
00727   /* don't bother setting if it it isnt mapped, duh */
00728   if (!mMapped)
00729     return NS_OK;
00730   
00731   // Only change cursor if it's changing
00732   if (aCursor != mCursor) {
00733     Cursor newCursor = None;
00734 
00735     newCursor = XlibCreateCursor(aCursor);
00736 
00737     if (None != newCursor) {
00738       mCursor = aCursor;
00739       XDefineCursor(mDisplay, mBaseWindow, newCursor);
00740       XFlush(mDisplay);
00741     }
00742   }
00743   return NS_OK;
00744 }
00745 
00746 NS_IMETHODIMP nsWidget::PreCreateWidget(nsWidgetInitData *aInitData)
00747 {
00748   if (nsnull != aInitData) {
00749     SetWindowType(aInitData->mWindowType);
00750     SetBorderStyle(aInitData->mBorderStyle);
00751     
00752     return NS_OK;
00753   }
00754   return NS_ERROR_FAILURE;
00755 }
00756 
00757 nsIWidget *nsWidget::GetParent(void)
00758 {
00759   if (nsnull != mParentWidget) {
00760     NS_ADDREF(mParentWidget);
00761   }
00762   return mParentWidget;
00763 }
00764 
00765 void nsWidget::CreateNative(Window aParent, nsRect aRect)
00766 {
00767   XSetWindowAttributes attr;
00768   unsigned long attr_mask;
00769 
00770   attr.bit_gravity       = NorthWestGravity;
00771   attr.event_mask        = GetEventMask();
00772   attr.colormap          = xxlib_rgb_get_cmap(mXlibRgbHandle);
00773   attr.background_pixel  = mBackgroundPixel;
00774   attr.border_pixel      = mBorderPixel;
00775   attr_mask = CWBitGravity | CWEventMask | CWBorderPixel | CWBackPixel;
00776 
00777   if (attr.colormap)
00778     attr_mask |= CWColormap;
00779 
00780   CreateNativeWindow(aParent, mBounds, attr, attr_mask);
00781 }
00782 
00783 /* virtual */ long
00784 nsWidget::GetEventMask()
00785 {
00786   long event_mask;
00787 
00788   event_mask = 
00789     ButtonMotionMask |
00790     Button1MotionMask |
00791     ButtonPressMask |
00792     ButtonReleaseMask |
00793     EnterWindowMask |
00794     ExposureMask |
00795     KeyPressMask |
00796     KeyReleaseMask |
00797     LeaveWindowMask |
00798     PointerMotionMask |
00799     StructureNotifyMask |
00800     VisibilityChangeMask |
00801     FocusChangeMask |
00802     OwnerGrabButtonMask;
00803 
00804   return event_mask;
00805 }
00806 
00807 void nsWidget::CreateNativeWindow(Window aParent, nsRect aRect,
00808                                   XSetWindowAttributes aAttr, unsigned long aMask)
00809 {
00810   NS_ASSERTION(!mBaseWindow, "already initialized");
00811   if (mBaseWindow) return;
00812 
00813   mBaseWindow = XCreateWindow(mDisplay,
00814                               aParent,
00815                               aRect.x, aRect.y,
00816                               aRect.width, aRect.height,
00817                               0,                // border width
00818                               mDepth,           // depth
00819                               InputOutput,      // class
00820                               mVisual,          // visual
00821                               aMask,
00822                               &aAttr);
00823   XSetWindowBackgroundPixmap(mDisplay, mBaseWindow, None);
00824 
00825   mRequestedSize.height = mBounds.height = aRect.height;
00826   mRequestedSize.width = mBounds.width = aRect.width;
00827   AddWindowCallback(mBaseWindow, this);
00828 }
00829 
00830 nsWidget *
00831 nsWidget::GetWidgetForWindow(Window aWindow)
00832 {
00833   if (gsWindowList == nsnull) {
00834     return nsnull;
00835   }
00836   nsWindowKey window_key(aWindow);
00837   nsWidget *retval = (nsWidget *)gsWindowList->Get(&window_key);
00838   return retval;
00839 }
00840 
00841 void
00842 nsWidget::AddWindowCallback(Window aWindow, nsWidget *aWidget)
00843 {
00844   // make sure that the list has been initialized
00845   if (gsWindowList == nsnull) {
00846     gsWindowList = new nsHashtable();
00847   }
00848   nsWindowKey window_key(aWindow);
00849   gsWindowList->Put(&window_key, aWidget);
00850 }
00851 
00852 void
00853 nsWidget::DeleteWindowCallback(Window aWindow)
00854 {
00855   nsWindowKey window_key(aWindow);
00856   gsWindowList->Remove(&window_key);
00857 
00858   if (gsWindowList->Count() == 0) {
00859     delete gsWindowList;
00860     gsWindowList = nsnull;
00861 
00862     /* clear out the cursor cache */
00863 #ifdef DEBUG_CURSORCACHE
00864     printf("freeing cursor cache\n");
00865 #endif
00866     for (int i = 0; i < eCursorCount; i++)
00867       if (gsXlibCursorCache[i])
00868         XFreeCursor(nsAppShell::mDisplay, gsXlibCursorCache[i]);
00869   }
00870 }
00871 
00872 #undef TRACE_PAINT
00873 #undef TRACE_PAINT_FLASH
00874 
00875 #ifdef TRACE_PAINT_FLASH
00876 #include "nsXUtils.h" // for nsXUtils::XFlashWindow()
00877 #endif
00878 
00879 PRBool
00880 nsWidget::OnPaint(nsPaintEvent &event)
00881 {
00882   nsresult result = PR_FALSE;
00883   if (mEventCallback) {
00884     event.renderingContext = GetRenderingContext();
00885     if (event.renderingContext) {
00886       result = DispatchWindowEvent(event);
00887       NS_RELEASE(event.renderingContext);
00888     }
00889   }
00890   
00891 #ifdef TRACE_PAINT
00892   static PRInt32 sPrintCount = 0;
00893 
00894   if (event.rect) 
00895   {
00896     printf("%4d nsWidget::OnPaint   (this=%p,name=%s,xid=%p,rect=%d,%d,%d,%d)\n", 
00897            sPrintCount++,
00898            (void *) this,
00899            (const char *) nsCAutoString(mName),
00900            (void *) mBaseWindow,
00901            event.rect->x, 
00902            event.rect->y,
00903            event.rect->width, 
00904            event.rect->height);
00905   }
00906   else 
00907   {
00908     printf("%4d nsWidget::OnPaint   (this=%p,name=%s,xid=%p,rect=none)\n", 
00909            sPrintCount++,
00910            (void *) this,
00911            (const char *) nsCAutoString(mName),
00912            (void *) mBaseWindow);
00913   }
00914 #endif
00915 
00916 #ifdef TRACE_PAINT_FLASH
00917     XRectangle ar;
00918     XRectangle * area = nsnull;
00919 
00920     if (event.rect)
00921     {
00922       ar.x = event.rect->x;
00923       ar.y = event.rect->y;
00924 
00925       ar.width = event.rect->width;
00926       ar.height = event.rect->height;
00927 
00928       area = &ar;
00929     }
00930 
00931     nsXUtils::XFlashWindow(mDisplay,mBaseWindow,1,100000,area);
00932 #endif
00933 
00934 
00935   return result;
00936 }
00937 
00938 PRBool nsWidget::IsMouseInWindow(Window window, PRInt32 inMouseX, PRInt32 inMouseY)
00939 {
00940   XWindowAttributes inWindowAttributes;
00941 
00942   /* sometimes we get NULL window */
00943   if (!window)
00944     return PR_FALSE;
00945 
00946   /* Get the origin (top left corner) coordinate and window's size */
00947   if (XGetWindowAttributes(mDisplay, window, &inWindowAttributes) == 0) {
00948     fprintf(stderr, "Failed calling XGetWindowAttributes in nsWidget::IsMouseInWindow");
00949     return PR_FALSE;
00950   }
00951 
00952   // Note: These coordinates are now relative to the root window as popups are now created
00953   // with the root window as parent
00954 
00955   // Must get mouse click coordinates relative to root window
00956   int root_inMouse_x,
00957       root_inMouse_y;
00958   Window returnedChild;
00959   Window rootWindow;
00960   rootWindow = XRootWindow(mDisplay, XDefaultScreen(mDisplay));
00961   if (!XTranslateCoordinates(mDisplay, mBaseWindow, rootWindow,
00962     inMouseX, inMouseY,
00963     &root_inMouse_x, &root_inMouse_y, &returnedChild)){
00964     fprintf(stderr, "Could not get coordinates for origin coordinates for mouseclick\n");
00965     // should we return true or false??????
00966     return PR_FALSE;
00967   }
00968   //fprintf(stderr, "Here are the mouse click coordinates x:%i y%i\n", root_inMouse_x, root_inMouse_y);
00969 
00970   // Test using coordinates relative to root window if click was inside passed popup window
00971   if (root_inMouse_x > inWindowAttributes.x &&
00972       root_inMouse_x < (inWindowAttributes.x + inWindowAttributes.width) &&
00973       root_inMouse_y > inWindowAttributes.y &&
00974       root_inMouse_y < (inWindowAttributes.y + inWindowAttributes.height)) {
00975 #ifdef DEBUG_whoemeveraddedthatprintforginally
00976     //fprintf(stderr, "Mouse click INSIDE passed popup\n");
00977 #endif
00978     return PR_TRUE;
00979   }
00980   
00981 #ifdef DEBUG_whoemeveraddedthatprintforginally
00982   //fprintf(stderr, "Mouse click OUTSIDE of passed popup\n");
00983 #endif
00984   return PR_FALSE;
00985 }
00986 
00987 
00988 //
00989 // HandlePopup
00990 //
00991 // Deal with rollup of popups (xpmenus, etc)
00992 // 
00993 PRBool nsWidget::HandlePopup ( PRInt32 inMouseX, PRInt32 inMouseY )
00994 {
00995   PRBool retVal = PR_FALSE;
00996   PRBool rollup = PR_FALSE;
00997 
00998   // The gRollupListener and gRollupWidget are both set to nsnull when a popup is no
00999   // longer visible
01000 
01001   nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWidget);
01002 
01003   if (rollupWidget && gRollupListener) {
01004     Window currentPopup = (Window)rollupWidget->GetNativeData(NS_NATIVE_WINDOW);
01005 
01006     if (!IsMouseInWindow(currentPopup, inMouseX, inMouseY)) {
01007       rollup = PR_TRUE;
01008       nsCOMPtr<nsIMenuRollup> menuRollup ( do_QueryInterface(gRollupListener) );
01009       
01010       if ( menuRollup ) {
01011         nsCOMPtr<nsISupportsArray> widgetChain;
01012         menuRollup->GetSubmenuWidgetChain ( getter_AddRefs(widgetChain) );
01013         if ( widgetChain ) {
01014           PRUint32 count = 0;
01015           widgetChain->Count ( &count );
01016           for ( PRUint32 i = 0; i < count; ++i ) {
01017             nsCOMPtr<nsISupports> genericWidget;
01018             widgetChain->GetElementAt ( i, getter_AddRefs(genericWidget) );
01019             nsCOMPtr<nsIWidget> widget ( do_QueryInterface(genericWidget) );
01020             if ( widget ) {
01021               Window currWindow = (Window)widget->GetNativeData(NS_NATIVE_WINDOW);
01022               if ( IsMouseInWindow(currWindow, inMouseX, inMouseY) ) {
01023                 rollup = PR_FALSE;
01024                 break;
01025               }
01026             }
01027           } // foreach parent menu widget
01028         }
01029       }
01030     }
01031   }
01032 
01033   if (rollup) {
01034     gRollupListener->Rollup();
01035     retVal = PR_TRUE;
01036   }
01037   return retVal;
01038 }
01039 
01040 
01041 // Added KenF FIXME
01042 void nsWidget::OnDestroy()
01043 {
01044   mOnDestroyCalled = PR_TRUE;
01045   nsBaseWidget::OnDestroy();
01046 
01047   // M14/GTK creates a widget which is called kungFuDeathGrip
01048   // and assigns it "this". This might be because its making sure that this 
01049   // widget isn't destroyed? (still has a reference to it?)
01050   // Check into it. FIXME KenF
01051   DispatchDestroyEvent();
01052 }
01053 
01054 PRBool nsWidget::OnDeleteWindow(void)
01055 {
01056 #ifdef DEBUG
01057   printf("nsWidget::OnDeleteWindow()\n");
01058 #endif /* DEBUUG */  
01059   nsBaseWidget::OnDestroy();
01060   // emit a destroy signal
01061   return DispatchDestroyEvent();
01062 }
01063 
01064 PRBool nsWidget::DispatchDestroyEvent(void) {
01065   PRBool result = PR_FALSE;
01066   if (nsnull != mEventCallback) {
01067     nsGUIEvent event(PR_TRUE, NS_DESTROY, this);
01068     AddRef();
01069     result = DispatchWindowEvent(event);
01070     Release();
01071   }
01072   return result;
01073 }
01074 
01075 PRBool nsWidget::DispatchMouseEvent(nsMouseEvent& aEvent) 
01076 {
01077   PRBool result = PR_FALSE;
01078   if (nsnull == mEventCallback && nsnull == mMouseListener) {
01079     return result;
01080   }
01081 
01082   /* If there was a mouse down event, check if any popups need to be notified */
01083   switch (aEvent.message) {
01084     case NS_MOUSE_LEFT_BUTTON_DOWN:
01085     case NS_MOUSE_MIDDLE_BUTTON_DOWN:
01086     case NS_MOUSE_RIGHT_BUTTON_DOWN:
01087       if (HandlePopup(aEvent.point.x, aEvent.point.y)){
01088         // Should we return here as GTK does?
01089         return PR_TRUE;
01090       }
01091       break;
01092   }
01093 
01094   if (nsnull != mEventCallback) {
01095     result = DispatchWindowEvent(aEvent);
01096     return result;
01097   }
01098   if (nsnull != mMouseListener) {
01099     switch (aEvent.message) {
01100     case NS_MOUSE_MOVE:
01101       // XXX this isn't handled in gtk for some reason.
01102       break;
01103     case NS_MOUSE_LEFT_BUTTON_DOWN:
01104     case NS_MOUSE_MIDDLE_BUTTON_DOWN:
01105     case NS_MOUSE_RIGHT_BUTTON_DOWN:
01106       result = ConvertStatus(mMouseListener->MousePressed(aEvent));
01107       break;
01108     case NS_MOUSE_LEFT_BUTTON_UP:
01109     case NS_MOUSE_MIDDLE_BUTTON_UP:
01110     case NS_MOUSE_RIGHT_BUTTON_UP:
01111       result = ConvertStatus(mMouseListener->MouseReleased(aEvent));
01112       result = ConvertStatus(mMouseListener->MouseClicked(aEvent));
01113       break;
01114     }
01115   }
01116   return result;
01117 }
01118 
01119 PRBool
01120 nsWidget::OnResize(nsSizeEvent &event)
01121 {
01122   mBounds.width = event.mWinWidth;
01123   mBounds.height = event.mWinHeight;
01124 
01125   nsresult result = PR_FALSE;
01126   if (mEventCallback) {
01127       result = DispatchWindowEvent(event);
01128   }
01129   return result;
01130 }
01131 
01132 PRBool nsWidget::DispatchWindowEvent(nsGUIEvent & aEvent)
01133 {
01134   nsEventStatus status;
01135   DispatchEvent(&aEvent, status);
01136   return ConvertStatus(status);
01137 }
01138 
01139 PRBool nsWidget::DispatchKeyEvent(nsKeyEvent & aKeyEvent)
01140 {
01141   if (mEventCallback) 
01142   {
01143     return DispatchWindowEvent(aKeyEvent);
01144   }
01145 
01146   return PR_FALSE;
01147 }
01148 
01150 //
01151 // Turning TRACE_EVENTS on will cause printfs for all
01152 // mouse events that are dispatched.
01153 //
01154 // These are extra noisy, and thus have their own switch:
01155 //
01156 // NS_MOUSE_MOVE
01157 // NS_PAINT
01158 // NS_MOUSE_ENTER, NS_MOUSE_EXIT
01159 //
01161 
01162 #undef TRACE_EVENTS
01163 #undef TRACE_EVENTS_MOTION
01164 #undef TRACE_EVENTS_PAINT
01165 #undef TRACE_EVENTS_CROSSING
01166 #undef DEBUG
01167 
01168 #ifdef DEBUG
01169 void
01170 nsWidget::DebugPrintEvent(nsGUIEvent &   aEvent,
01171                           Window         aWindow)
01172 {
01173 #ifndef TRACE_EVENTS_MOTION
01174   if (aEvent.message == NS_MOUSE_MOVE)
01175   {
01176     return;
01177   }
01178 #endif
01179 
01180 #ifndef TRACE_EVENTS_PAINT
01181   if (aEvent.message == NS_PAINT)
01182   {
01183     return;
01184   }
01185 #endif
01186 
01187 #ifndef TRACE_EVENTS_CROSSING
01188   if (aEvent.message == NS_MOUSE_ENTER || aEvent.message == NS_MOUSE_EXIT)
01189   {
01190     return;
01191   }
01192 #endif
01193 
01194   static int sPrintCount=0;
01195 
01196   nsCAutoString eventString;
01197   eventString.AssignWithConversion(debug_GuiEventToString(&aEvent));
01198   printf("%4d %-26s(this=%-8p , window=%-8p",
01199          sPrintCount++,
01200          (const char *) eventString,
01201          (void *) this,
01202          (void *) aWindow);
01203          
01204   printf(" , x=%-3d, y=%d)",aEvent.point.x,aEvent.point.y);
01205 
01206   printf("\n");
01207 }
01208 #endif // DEBUG
01209 
01210 
01211 
01212 NS_IMETHODIMP nsWidget::DispatchEvent(nsGUIEvent * aEvent,
01213                                       nsEventStatus &aStatus)
01214 {
01215 #ifdef TRACE_EVENTS
01216   DebugPrintEvent(*aEvent,mBaseWindow);
01217 #endif
01218 
01219   NS_ADDREF(aEvent->widget);
01220 
01221   if (nsnull != mMenuListener) {
01222     if (NS_MENU_EVENT == aEvent->eventStructType)
01223       aStatus = mMenuListener->MenuSelected(NS_STATIC_CAST(nsMenuEvent&, *aEvent));
01224   }
01225 
01226   aStatus = nsEventStatus_eIgnore;
01227   if (nsnull != mEventCallback) {
01228     aStatus = (*mEventCallback)(aEvent);
01229   }
01230 
01231   // Dispatch to event listener if event was not consumed
01232   if ((aStatus != nsEventStatus_eIgnore) && (nsnull != mEventListener)) {
01233     aStatus = mEventListener->ProcessEvent(*aEvent);
01234   }
01235 
01236   NS_IF_RELEASE(aEvent->widget);
01237 
01238   return NS_OK;
01239 }
01240 
01241 PRBool nsWidget::ConvertStatus(nsEventStatus aStatus)
01242 {
01243   switch(aStatus) {
01244     case nsEventStatus_eIgnore:
01245       return(PR_FALSE);
01246     case nsEventStatus_eConsumeNoDefault:
01247       return(PR_TRUE);
01248     case nsEventStatus_eConsumeDoDefault:
01249       return(PR_FALSE);
01250     default:
01251       NS_WARNING("Illegal nsEventStatus enumeration value\n");
01252       break;
01253   }
01254   return(PR_FALSE);
01255 }
01256 
01257 void nsWidget::WidgetPut(nsWidget *aWidget)
01258 {
01259 }
01260 
01261 void nsWidget::WidgetMove(nsWidget *aWidget)
01262 {
01263   PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWidget::WidgetMove()\n"));
01264   XMoveWindow(aWidget->mDisplay, aWidget->mBaseWindow,
01265               aWidget->mRequestedSize.x, aWidget->mRequestedSize.y);
01266 }
01267 
01268 void nsWidget::WidgetResize(nsWidget *aWidget)
01269 {
01270   PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWidget::WidgetResize()\n"));
01271   XResizeWindow(aWidget->mDisplay, aWidget->mBaseWindow,
01272                 aWidget->mRequestedSize.width,
01273                 aWidget->mRequestedSize.height);
01274 }
01275 
01276 void nsWidget::WidgetMoveResize(nsWidget *aWidget)
01277 {
01278   PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWidget::WidgetMoveResize()\n"));
01279   XMoveResizeWindow(aWidget->mDisplay,
01280                     aWidget->mBaseWindow,
01281                     aWidget->mRequestedSize.x,
01282                     aWidget->mRequestedSize.y,
01283                     aWidget->mRequestedSize.width,
01284                     aWidget->mRequestedSize.height);
01285 }
01286 
01287 void nsWidget::WidgetShow(nsWidget *aWidget)
01288 {
01289   aWidget->Map();
01290 }
01291 
01292 PRBool nsWidget::WidgetVisible(nsRect &aBounds)
01293 {
01294   nsRect scrollArea;
01295   scrollArea.x = 0;
01296   scrollArea.y = 0;
01297   scrollArea.width = mRequestedSize.width + 1;
01298   scrollArea.height = mRequestedSize.height + 1;
01299   if (scrollArea.Intersects(aBounds)) {
01300     PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWidget::WidgetVisible(): widget is visible\n"));
01301     return PR_TRUE;
01302   }
01303   PR_LOG(XlibScrollingLM, PR_LOG_DEBUG, ("nsWidget::WidgetVisible(): widget is not visible\n"));
01304   return PR_FALSE;
01305 }
01306 
01307 void nsWidget::Map(void)
01308 {
01309   if (!mMapped) {
01310      /* Workaround for bug 77344. I am not sure whether this is mandatory or not. */
01311     if (mDisplay)
01312       XMapWindow(mDisplay, mBaseWindow);
01313     mMapped = PR_TRUE;
01314   }
01315 }
01316 
01317 void nsWidget::Unmap(void)
01318 {
01319   if (mMapped) {
01320      /* Workaround for bug 77344. I am not sure whether this is mandatory or not. */
01321     if (mDisplay)
01322       XUnmapWindow(mDisplay, mBaseWindow);
01323     mMapped = PR_FALSE;
01324   }
01325 }
01326 
01327 void nsWidget::SetVisibility(int aState)
01328 {
01329   mVisibility = aState;
01330 }
01331 
01332 // create custom pixmap cursor from cursors in nsXlibCursors.h
01333 Cursor nsWidget::XlibCreateCursor(nsCursor aCursorType)
01334 {
01335   Pixmap cursor = None;
01336   Pixmap mask = None;
01337   XColor fg, bg;
01338   Cursor xcursor = None;
01339   PRUint8 newType = 0xff;
01340 
01341   fg.pixel = 0;
01342   fg.red = 0;
01343   fg.green = 0;
01344   fg.blue = 0;
01345   fg.flags = 0xf;
01346 
01347   bg.pixel = 0xffffffff;
01348   bg.red = 0xffff;
01349   bg.green = 0xffff;
01350   bg.blue = 0xffff;
01351   bg.flags = 0xf;
01352 
01353   /* lookup the cursor in cache */
01354   if ((xcursor = gsXlibCursorCache[aCursorType])) {
01355 #ifdef DEBUG_CURSORCACHE
01356     printf("cached cursor found: %lx\n", xcursor);
01357 #endif
01358     return xcursor;
01359   }
01360 
01361   /* handle cursor type */
01362   switch (aCursorType) {
01363     case eCursor_select:
01364       xcursor = XCreateFontCursor(mDisplay, XC_xterm);
01365       break;
01366     case eCursor_wait:
01367       xcursor = XCreateFontCursor(mDisplay, XC_watch);
01368       break;
01369     case eCursor_hyperlink:
01370       xcursor = XCreateFontCursor(mDisplay, XC_hand2);
01371       break;
01372     case eCursor_standard:
01373       xcursor = XCreateFontCursor(mDisplay, XC_left_ptr);
01374       break;
01375     case eCursor_n_resize:
01376       xcursor = XCreateFontCursor(mDisplay, XC_top_side);
01377       break;
01378     case eCursor_s_resize:
01379       xcursor = XCreateFontCursor(mDisplay, XC_bottom_side);
01380       break;
01381     case eCursor_w_resize:
01382       xcursor = XCreateFontCursor(mDisplay, XC_left_side);
01383       break;
01384     case eCursor_e_resize:
01385       xcursor = XCreateFontCursor(mDisplay, XC_right_side);
01386       break;
01387     case eCursor_nw_resize:
01388       xcursor = XCreateFontCursor(mDisplay, XC_top_left_corner);
01389       break;
01390     case eCursor_se_resize:
01391       xcursor = XCreateFontCursor(mDisplay, XC_bottom_right_corner);
01392       break;
01393     case eCursor_ne_resize:
01394       xcursor = XCreateFontCursor(mDisplay, XC_top_right_corner);
01395       break;
01396     case eCursor_sw_resize:
01397       xcursor = XCreateFontCursor(mDisplay, XC_bottom_left_corner);
01398       break;
01399     case eCursor_crosshair:
01400       xcursor = XCreateFontCursor(mDisplay, XC_crosshair);
01401       break;
01402     case eCursor_move:
01403       xcursor = XCreateFontCursor(mDisplay, XC_fleur);
01404       break;
01405     case eCursor_help:
01406       newType = XLIB_QUESTION_ARROW;
01407       break;
01408     case eCursor_copy:
01409       newType = XLIB_COPY;
01410       break;
01411     case eCursor_alias:
01412       newType = XLIB_ALIAS;
01413       break;
01414     case eCursor_context_menu:
01415       newType = XLIB_CONTEXT_MENU;
01416       break;
01417     case eCursor_cell:
01418       xcursor = XCreateFontCursor(mDisplay, XC_plus);
01419       break;
01420     case eCursor_grab:
01421       newType = XLIB_HAND_GRAB;
01422       break;
01423     case eCursor_grabbing:
01424       newType = XLIB_HAND_GRABBING;
01425       break;
01426     case eCursor_spinning:
01427       newType = XLIB_SPINNING;
01428       break;
01429     case eCursor_zoom_in:
01430       newType = XLIB_ZOOM_IN;
01431       break;
01432     case eCursor_zoom_out:
01433       newType = XLIB_ZOOM_OUT;
01434       break;
01435     case eCursor_not_allowed:
01436     case eCursor_no_drop:
01437       newType = XLIB_NOT_ALLOWED;
01438       break;
01439     case eCursor_col_resize:
01440       newType = XLIB_COL_RESIZE;
01441       break;
01442     case eCursor_row_resize:
01443       newType = XLIB_ROW_RESIZE;
01444       break;
01445     case eCursor_vertical_text:
01446       newType = XLIB_VERTICAL_TEXT;
01447       break;
01448     case eCursor_all_scroll:
01449       xcursor = XCreateFontCursor(mDisplay, XC_fleur);
01450       break;
01451     case eCursor_nesw_resize:
01452       newType = XLIB_NESW_RESIZE;
01453       break;
01454     case eCursor_nwse_resize:
01455       newType = XLIB_NWSE_RESIZE;
01456       break;
01457     case eCursor_ns_resize:
01458       xcursor = XCreateFontCursor(mDisplay, XC_sb_v_double_arrow);
01459       break;
01460     case eCursor_ew_resize:
01461       xcursor = XCreateFontCursor(mDisplay, XC_sb_h_double_arrow);
01462       break;
01463     default:
01464       break;
01465   }
01466 
01467   /* if by now we dont have a xcursor, this means we have to make a custom one */
01468   if (!xcursor) {
01469     NS_ASSERTION(newType != 0xff, "Unknown cursor type and no standard cursor");
01470     
01471     /* we can use mBaseWindow for the pixmaps because SetCursor checks this
01472      * before calling here */
01473     cursor = XCreatePixmapFromBitmapData(mDisplay, mBaseWindow,
01474                         (char *)XlibCursors[newType].bits,
01475                         32, 32, 0xffffffff, 0x0, 1);
01476 
01477     mask = XCreatePixmapFromBitmapData(mDisplay, mBaseWindow,
01478                         (char *)XlibCursors[newType].mask_bits,
01479                         32, 32, 0xffffffff, 0x0, 1);
01480 
01481     xcursor = XCreatePixmapCursor(mDisplay, cursor, mask, &fg, &bg,
01482                                   XlibCursors[newType].hot_x,
01483                                   XlibCursors[newType].hot_y);
01484 
01485     XFreePixmap(mDisplay, mask);
01486     XFreePixmap(mDisplay, cursor);
01487   }
01488 
01489 #ifdef DEBUG_CURSORCACHE
01490   printf("inserting cursor into the cache: %lx\n", xcursor);
01491 #endif
01492   gsXlibCursorCache[aCursorType] = xcursor;
01493   
01494   return xcursor;
01495 }
01496 
01497 void
01498 nsWidget::SetUpWMHints(void) {
01499   // check to see if we need to get the atoms for the protocols
01500   if (WMProtocolsInitialized == PR_FALSE) {
01501     WMDeleteWindow = XInternAtom(mDisplay, "WM_DELETE_WINDOW", True);
01502     WMTakeFocus = XInternAtom(mDisplay, "WM_TAKE_FOCUS", True);
01503     WMSaveYourself = XInternAtom(mDisplay, "WM_SAVE_YOURSELF", True);
01504     WMProtocolsInitialized = PR_TRUE;
01505   }
01506   Atom WMProtocols[2];
01507   WMProtocols[0] = WMDeleteWindow;
01508   WMProtocols[1] = WMTakeFocus;
01509   // note that we only set two of the above protocols
01510   PR_LOG(XlibWidgetsLM, PR_LOG_DEBUG, ("Setting up wm hints for window 0x%lx\n",
01511                                        mBaseWindow));
01512   XSetWMProtocols(mDisplay, mBaseWindow, WMProtocols, 2);
01513 }
01514 
01515 NS_METHOD nsWidget::SetBounds(const nsRect &aRect)
01516 {
01517   mRequestedSize = aRect;
01518   return nsBaseWidget::SetBounds(aRect);
01519 }
01520 
01521 NS_METHOD nsWidget::GetRequestedBounds(nsRect &aRect)
01522 {
01523   aRect = mRequestedSize;
01524   return NS_OK;
01525 }
01526 
01527 NS_IMETHODIMP
01528 nsWidget::SetTitle(const nsAString& title)
01529 {
01530   return NS_OK;
01531 }
01532 
01533 NS_IMETHODIMP nsWidget::CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent)
01534 {
01535   return NS_OK;
01536 }
01537