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  *   Andrew Wellington <proton@wiretapped.net>
00024  *   Graham Dennis <u3952328@anu.edu.au>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 
00041 #include "nsWidget.h"
00042 
00043 #include "nsGtkEventHandler.h"
00044 #include "nsIAppShell.h"
00045 #include "nsIComponentManager.h"
00046 #include "nsIDeviceContext.h"
00047 #include "nsIFontMetrics.h"
00048 #include "nsToolkit.h"
00049 #include "nsWidgetsCID.h"
00050 #include "nsGfxCIID.h"
00051 #include <gdk/gdkx.h>
00052 #include "nsIRollupListener.h"
00053 #include "nsIMenuRollup.h"
00054 #include "nsIServiceManager.h"
00055 #include "nsIDragSessionGTK.h"
00056 #include "nsIDragService.h"
00057 
00058 #include "nsGtkUtils.h" // for nsGtkUtils::gdk_keyboard_get_modifiers()
00059 
00060 #include "nsIPref.h"
00061 
00062 static void
00063 ConvertKeyEventToContextMenuEvent(const nsKeyEvent* inKeyEvent,
00064                                   nsMouseEvent* outCMEvent);
00065 
00066 static inline PRBool
00067 IsContextMenuKey(const nsKeyEvent& inKeyEvent);
00068 
00069 static NS_DEFINE_CID(kRegionCID, NS_REGION_CID);
00070 static NS_DEFINE_IID(kCDragServiceCID,  NS_DRAGSERVICE_CID);
00071 
00072 // this is the nsWindow with the focus
00073 nsWidget *nsWidget::sFocusWindow = 0;
00074 
00075 // this is the last time that an event happened.  we keep this
00076 // around so that we can synth drag events properly
00077 guint32 nsWidget::sLastEventTime = 0;
00078 
00079 // we should convert the context key to context menu event in the OnKey member
00080 // function, and dispatch the NS_CONTEXTMENU_KEY instead of a normal key event.
00081 PRBool nsWidget::OnKey(nsKeyEvent &aEvent)
00082 {
00083 
00084   PRBool    ret = PR_FALSE;
00085   PRBool    releaseWidget = PR_FALSE;
00086   nsWidget *widget = nsnull;
00087 
00088   // rewrite the key event to the window with 'de focus
00089   if (sFocusWindow) {
00090     widget = sFocusWindow;
00091     NS_ADDREF(widget);
00092     aEvent.widget = sFocusWindow;
00093     releaseWidget = PR_TRUE;
00094   }
00095   if (mEventCallback) {
00096     // before we dispatch a key, check if it's the context menu key.
00097     // If so, send a context menu key event instead.
00098     if (IsContextMenuKey(aEvent)) {
00099       nsMouseEvent contextMenuEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal);
00100       ConvertKeyEventToContextMenuEvent(&aEvent, &contextMenuEvent);
00101       ret = DispatchWindowEvent(&contextMenuEvent);
00102     }
00103     else
00104       ret = DispatchWindowEvent(&aEvent);
00105   }
00106 
00107   if (releaseWidget)
00108     NS_RELEASE(widget);
00109 
00110   return ret;
00111 }
00112 
00113 //
00114 // ConvertKeyEventToContextMenuEvent
00115 //
00116 // Take a key event and all of its attributes at convert it into
00117 // a context menu event. We want just about  everything (focused
00118 // widget, etc) but a few fields should be tweaked. See also the
00119 // implemention for the Mac
00120 
00121 static void
00122 ConvertKeyEventToContextMenuEvent(const nsKeyEvent* inKeyEvent,
00123                                   nsMouseEvent* outCMEvent)
00124 {
00125   *(nsInputEvent *)outCMEvent = *(nsInputEvent *)inKeyEvent;
00126   outCMEvent->eventStructType = NS_MOUSE_EVENT;
00127   outCMEvent->message = NS_CONTEXTMENU_KEY;
00128   outCMEvent->isShift = outCMEvent->isControl = PR_FALSE;
00129   outCMEvent->isAlt = outCMEvent->isMeta = PR_FALSE;
00130   outCMEvent->clickCount = 0;
00131   outCMEvent->acceptActivation = PR_FALSE;
00132 }
00133  
00134 
00135 // IsContextMenuKey
00136 //
00137 // Check if the event should be a context menu event instead. Currently,
00138 // that is a Shift-F10 in linux.
00139 //
00140 static inline PRBool
00141 IsContextMenuKey(const nsKeyEvent& inKeyEvent)
00142 {
00143    enum { kContextMenuKey = NS_VK_F10, kDedicatedContextMenuKey = NS_VK_CONTEXT_MENU };
00144 
00145    return ((inKeyEvent.keyCode == kContextMenuKey && inKeyEvent.isShift &&
00146             !inKeyEvent.isControl && !inKeyEvent.isMeta && !inKeyEvent.isAlt) ||
00147            (inKeyEvent.keyCode == kDedicatedContextMenuKey && !inKeyEvent.isShift &&
00148             !inKeyEvent.isControl && !inKeyEvent.isMeta && !inKeyEvent.isAlt));
00149 }
00150 
00151 PRBool nsWidget::OnInput(nsInputEvent &aEvent)
00152 {
00153 
00154   PRBool    ret = PR_FALSE;
00155   PRBool    releaseWidget = PR_FALSE;
00156   nsWidget *widget = NULL;
00157 
00158   // rewrite the key event to the window with 'de focus
00159   if (sFocusWindow) {
00160     widget = sFocusWindow;
00161     NS_ADDREF(widget);
00162     aEvent.widget = sFocusWindow;
00163     releaseWidget = PR_TRUE;
00164   }
00165   if (mEventCallback) {
00166     ret = DispatchWindowEvent(&aEvent);
00167   }
00168 
00169   if (releaseWidget)
00170     NS_RELEASE(widget);
00171 
00172   return ret;
00173 }
00174 
00175 /* virtual - really to be implemented by nsWindow */
00176 GtkWidget *nsWidget::GetOwningWidget()
00177 {
00178   NS_WARNING("nsWidget::GetOwningWidget called!\n");
00179   return nsnull;
00180 }
00181 
00182 void nsWidget::SetLastEventTime(guint32 aTime)
00183 {
00184   sLastEventTime = aTime;
00185 }
00186 
00187 void nsWidget::GetLastEventTime(guint32 *aTime)
00188 {
00189   if (aTime)
00190     *aTime = sLastEventTime;
00191 }
00192 
00193 void nsWidget::DropMotionTarget(void)
00194 {
00195   if (sButtonMotionTarget) {
00196     GtkWidget *owningWidget = sButtonMotionTarget->GetOwningWidget();
00197     if (owningWidget)
00198       gtk_grab_remove(owningWidget);
00199 
00200     sButtonMotionTarget = nsnull;
00201   }
00202 }
00203 
00204 nsCOMPtr<nsIRollupListener> nsWidget::gRollupListener;
00205 nsWeakPtr          nsWidget::gRollupWidget;
00206 
00207 PRBool             nsWidget::mGDKHandlerInstalled = PR_FALSE;
00208 PRBool             nsWidget::sTimeCBSet = PR_FALSE;
00209 
00210 //
00211 // Keep track of the last widget being "dragged"
00212 //
00213 nsWidget *nsWidget::sButtonMotionTarget = NULL;
00214 gint nsWidget::sButtonMotionRootX = -1;
00215 gint nsWidget::sButtonMotionRootY = -1;
00216 gint nsWidget::sButtonMotionWidgetX = -1;
00217 gint nsWidget::sButtonMotionWidgetY = -1;
00218 
00219 //#undef DEBUG_pavlov
00220 
00221 nsWidget::nsWidget()
00222 {
00223   mWidget = nsnull;
00224   mMozBox = 0;
00225   mParent = nsnull;
00226   mPreferredWidth  = 0;
00227   mPreferredHeight = 0;
00228   mShown = PR_FALSE;
00229   mInternalShown = PR_FALSE;
00230   mBounds.x = 0;
00231   mBounds.y = 0;
00232   mBounds.width = 0;
00233   mBounds.height = 0;
00234   mIsToplevel = PR_FALSE;
00235 
00236   mUpdateArea = do_CreateInstance(kRegionCID);
00237   if (mUpdateArea) {
00238     mUpdateArea->Init();
00239     mUpdateArea->SetTo(0, 0, 0, 0);
00240   }
00241   
00242   mListenForResizes = PR_FALSE;
00243   mHasFocus = PR_FALSE;
00244   if (mGDKHandlerInstalled == PR_FALSE) {
00245     mGDKHandlerInstalled = PR_TRUE;
00246     // It is most convenient for us to intercept our events after
00247     // they have been converted to GDK, but before GTK+ gets them
00248     gdk_event_handler_set (handle_gdk_event, NULL, NULL);
00249   }
00250   if (sTimeCBSet == PR_FALSE) {
00251     sTimeCBSet = PR_TRUE;
00252     nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
00253     if (!dragService) {
00254 #ifdef DEBUG
00255       g_print("*** warning: failed to get the drag service. this is a _bad_ thing.\n");
00256 #endif
00257       sTimeCBSet = PR_FALSE;
00258     }
00259     nsCOMPtr<nsIDragSessionGTK> dragServiceGTK;
00260     dragServiceGTK = do_QueryInterface(dragService);
00261     if (!dragServiceGTK) {
00262       sTimeCBSet = PR_FALSE;
00263       return;
00264     }
00265     dragServiceGTK->TargetSetTimeCallback(nsWidget::GetLastEventTime);
00266   }
00267 }
00268 
00269 nsWidget::~nsWidget()
00270 {
00271 #ifdef NOISY_DESTROY
00272   IndentByDepth(stdout);
00273   printf("nsWidget::~nsWidget:%p\n", this);
00274 #endif
00275 
00276   // it's safe to always call Destroy() because it will only allow itself
00277   // to be called once
00278   Destroy();
00279 
00280 }
00281 
00282 
00283 //-------------------------------------------------------------------------
00284 //
00285 // nsISupport stuff
00286 //
00287 //-------------------------------------------------------------------------
00288 NS_IMPL_ISUPPORTS_INHERITED2(nsWidget, nsBaseWidget, nsIKBStateControl, nsISupportsWeakReference)
00289 
00290 NS_IMETHODIMP nsWidget::WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect)
00291 {
00292   gint x;
00293   gint y;
00294 
00295   if (mWidget)
00296   {
00297     if (mWidget->window)
00298     {
00299       gdk_window_get_origin(mWidget->window, &x, &y);
00300       aNewRect.x = x + aOldRect.x;
00301       aNewRect.y = y + aOldRect.y;
00302     }
00303     else
00304       return NS_ERROR_FAILURE;
00305   }
00306 
00307   return NS_OK;
00308 }
00309 
00310 NS_IMETHODIMP nsWidget::ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect)
00311 {
00312 #ifdef DEBUG_pavlov
00313     g_print("nsWidget::ScreenToWidget\n");
00314 #endif
00315     NS_NOTYETIMPLEMENTED("nsWidget::ScreenToWidget");
00316     return NS_OK;
00317 }
00318 
00319 #ifdef DEBUG
00320 void
00321 nsWidget::IndentByDepth(FILE* out)
00322 {
00323   PRInt32 depth = 0;
00324   nsWidget* parent = (nsWidget*)mParent.get();
00325   while (parent) {
00326     parent = (nsWidget*) parent->mParent.get();
00327     depth++;
00328   }
00329   while (--depth >= 0) fprintf(out, "  ");
00330 }
00331 #endif
00332 
00333 //-------------------------------------------------------------------------
00334 //
00335 // Close this nsWidget
00336 //
00337 //-------------------------------------------------------------------------
00338 
00339 NS_IMETHODIMP nsWidget::Destroy(void)
00340 {
00341   //  printf("%p nsWidget::Destroy()\n", this);
00342   // make sure we don't call this more than once.
00343   if (mIsDestroying)
00344     return NS_OK;
00345 
00346   // we don't want people sending us events if we are the button motion target
00347   if (sButtonMotionTarget == this)
00348     DropMotionTarget();
00349 
00350   // ok, set our state
00351   mIsDestroying = PR_TRUE;
00352 
00353   // call in and clean up any of our base widget resources
00354   // are released
00355   nsBaseWidget::Destroy();
00356   mParent = 0;
00357 
00358   // just to be safe. If we're going away and for some reason we're still
00359   // the rollup widget, rollup and turn off capture.
00360   nsCOMPtr<nsIWidget> rollupWidget = do_QueryReferent(gRollupWidget);
00361   if ( NS_STATIC_CAST(nsIWidget*,this) == rollupWidget.get() ) {
00362     if ( gRollupListener )
00363       gRollupListener->Rollup();
00364     gRollupWidget = nsnull;
00365     gRollupListener = nsnull;
00366   }
00367 
00368   // destroy our native windows
00369   DestroyNative();
00370 
00371   // make sure to call the OnDestroy if it hasn't been called yet
00372   if (mOnDestroyCalled == PR_FALSE)
00373     OnDestroy();
00374 
00375   // make sure no callbacks happen
00376   mEventCallback = nsnull;
00377 
00378   return NS_OK;
00379 }
00380 
00381 // this is the function that will destroy the native windows for this widget.
00382 
00383 /* virtual */
00384 void nsWidget::DestroyNative(void)
00385 {
00386   if (mMozBox) {
00387     // destroying the mMozBox will also destroy the mWidget in question.
00388     ::gtk_widget_destroy(mMozBox);
00389     mWidget = NULL;
00390     mMozBox = NULL;
00391   }
00392 }
00393 
00394 // make sure that we clean up here
00395 
00396 void nsWidget::OnDestroy()
00397 {
00398   mOnDestroyCalled = PR_TRUE;
00399   // release references to children, device context, toolkit + app shell
00400   nsBaseWidget::OnDestroy();
00401 
00402   nsCOMPtr<nsIWidget> kungFuDeathGrip = this;
00403   DispatchStandardEvent(NS_DESTROY);
00404 }
00405 
00406 gint
00407 nsWidget::DestroySignal(GtkWidget* aGtkWidget, nsWidget* aWidget)
00408 {
00409   aWidget->OnDestroySignal(aGtkWidget);
00410   return PR_TRUE;
00411 }
00412 
00413 void
00414 nsWidget::OnDestroySignal(GtkWidget* aGtkWidget)
00415 {
00416   OnDestroy();
00417 }
00418 
00419 //-------------------------------------------------------------------------
00420 //
00421 // Get this nsWidget parent
00422 //
00423 //-------------------------------------------------------------------------
00424 
00425 nsIWidget* nsWidget::GetParent(void)
00426 {
00427   nsIWidget *ret;
00428   ret = mParent;
00429   NS_IF_ADDREF(ret);
00430   return ret;
00431 }
00432 
00433 //-------------------------------------------------------------------------
00434 //
00435 // Hide or show this component
00436 //
00437 //-------------------------------------------------------------------------
00438 
00439 NS_IMETHODIMP nsWidget::Show(PRBool bState)
00440 {
00441   if (!mWidget)
00442     return NS_OK; // Will be null durring printing
00443 
00444   mShown = bState;
00445 
00446   ResetInternalVisibility();
00447 
00448   return NS_OK;
00449 }
00450 
00451 void nsWidget::ResetInternalVisibility()
00452 {
00453   PRBool show = mShown;
00454   if (show) {
00455     if (mParent != nsnull) {
00456       nsRect parentBounds;
00457       mParent->GetClientBounds(parentBounds);
00458       parentBounds.x = parentBounds.y = 0;
00459       nsRect myBounds;
00460       GetBounds(myBounds);
00461       if (!myBounds.Intersects(parentBounds)) {
00462         show = PR_FALSE;
00463       }
00464     }
00465   }
00466 
00467   if (show == mInternalShown) {
00468     return;
00469   }
00470 
00471   SetInternalVisibility(show);
00472 }
00473 
00474 void nsWidget::SetInternalVisibility(PRBool aVisible)
00475 {
00476   mInternalShown = aVisible;
00477 
00478   if (aVisible) {
00479     if (mWidget)
00480       gtk_widget_show(mWidget);
00481     if (mMozBox)
00482       gtk_widget_show(mMozBox);
00483   } else {
00484     if (mWidget)
00485       gtk_widget_hide(mWidget);
00486     if (mMozBox)
00487       gtk_widget_hide(mMozBox);
00488   }
00489 }
00490 
00491 NS_IMETHODIMP nsWidget::CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent)
00492 {
00493   return NS_OK;
00494 }
00495 
00496 GdkWindow* nsWidget::GetLayeringWindow()
00497 {
00498   return mWidget->window;
00499 }
00500 
00501 void nsWidget::ResetZOrder()
00502 {
00503     if (!GetNextSibling()) {
00504         GdkWindow* window = GetLayeringWindow();
00505         if (window) {
00506             gdk_window_raise(window);
00507         }
00508     } else {
00509         // Move this widget and all the widgets above it to the top, in
00510         // the right order
00511         for (nsWidget* w = this; w;
00512              w = NS_STATIC_CAST(nsWidget*, w->GetNextSibling())) {
00513             GdkWindow* window = w->GetLayeringWindow();
00514             if (window) {
00515                 gdk_window_raise(window);
00516             }
00517         }
00518     }
00519 }
00520 
00521 NS_IMETHODIMP nsWidget::SetZIndex(PRInt32 aZIndex)
00522 {
00523     nsIWidget* oldPrev = GetPrevSibling();
00524 
00525     nsBaseWidget::SetZIndex(aZIndex);
00526 
00527     if (GetPrevSibling() != oldPrev) {
00528         ResetZOrder();
00529     }
00530 
00531     return NS_OK;
00532 }
00533 
00534 NS_IMETHODIMP nsWidget::IsVisible(PRBool &aState)
00535 {
00536   if (mWidget)
00537     aState = GTK_WIDGET_VISIBLE(mWidget);
00538   else
00539     aState = PR_FALSE;
00540 
00541   return NS_OK;
00542 }
00543 
00544 NS_IMETHODIMP nsWidget::GetWindowClass(char *aClass)
00545 {
00546 //nsWidget's base impl will throw a failure
00547 //to find out that this toolkit supports this function pass null.
00548   if (!aClass)
00549     return NS_OK;
00550 
00551   *aClass = nsnull;
00552 
00553   if (mWindowType != eWindowType_toplevel)
00554     return NS_OK;
00555 
00556   GtkWindow *topWindow;
00557   topWindow = GetTopLevelWindow();
00558 
00559   if (!topWindow)
00560     return NS_ERROR_FAILURE;
00561 
00562   XClassHint *class_hint = XAllocClassHint();
00563 
00564   if (XGetClassHint(GDK_DISPLAY(),
00565                     GDK_WINDOW_XWINDOW(GTK_WIDGET(topWindow)->window),
00566                     class_hint))
00567     aClass = strdup(class_hint->res_class);
00568 
00569   XFree(class_hint);
00570   return NS_OK;
00571 }
00572 
00573 NS_IMETHODIMP nsWidget::SetWindowClass(char *aClass)
00574 {
00575   if (mWindowType != eWindowType_toplevel)
00576     return NS_OK;
00577 
00578   GtkWindow *topWindow;
00579   topWindow = GetTopLevelWindow();
00580 
00581   if (!topWindow)
00582     return NS_ERROR_FAILURE;
00583 
00584   XClassHint *class_hint = XAllocClassHint();
00585 
00586   class_hint->res_name = "Mozilla";
00587   class_hint->res_class = aClass;
00588 
00589   XSetClassHint(GDK_DISPLAY(),
00590                 GDK_WINDOW_XWINDOW(GTK_WIDGET(topWindow)->window),
00591                 class_hint);
00592   XFree(class_hint);
00593   return NS_OK;
00594 }
00595 
00596 //-------------------------------------------------------------------------
00597 //
00598 // Move this component
00599 //
00600 //-------------------------------------------------------------------------
00601 
00602 NS_IMETHODIMP nsWidget::ConstrainPosition(PRBool aAllowSlop,
00603                                           PRInt32 *aX, PRInt32 *aY)
00604 {
00605   return NS_OK;
00606 }
00607 
00608 //-------------------------------------------------------------------------
00609 //
00610 // Move this component
00611 //
00612 //-------------------------------------------------------------------------
00613 
00614 NS_IMETHODIMP nsWidget::Move(PRInt32 aX, PRInt32 aY)
00615 {
00616   // check if we are at right place already
00617   if((aX == mBounds.x) && (aY == mBounds.y)) {
00618     return NS_OK;
00619   }
00620      
00621   mBounds.x = aX;
00622   mBounds.y = aY;
00623 
00624   if (mMozBox) 
00625   {
00626     gtk_mozbox_set_position(GTK_MOZBOX(mMozBox), aX, aY);
00627   }
00628 
00629   ResetInternalVisibility();
00630 
00631   return NS_OK;
00632 }
00633 
00634 NS_IMETHODIMP nsWidget::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
00635 {
00636 #ifdef DEBUG_MOVE
00637   printf("nsWidget::Resize %s (%p) to %d %d\n",
00638          (const char *) debug_GetName(mWidget),
00639          this,
00640          aWidth, aHeight);
00641 #endif
00642   mBounds.width  = aWidth;
00643   mBounds.height = aHeight;
00644 
00645   if (mWidget)
00646     gtk_widget_set_usize(mWidget, aWidth, aHeight);
00647 
00648   ResetInternalVisibility();
00649   for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
00650     NS_STATIC_CAST(nsWidget*, kid)->ResetInternalVisibility();
00651   }
00652 
00653   return NS_OK;
00654 }
00655 
00656 NS_IMETHODIMP nsWidget::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth,
00657                            PRInt32 aHeight, PRBool aRepaint)
00658 {
00659   Move(aX, aY);
00660   Resize(aWidth,aHeight,aRepaint);
00661   return NS_OK;
00662 }
00663 
00664 //-------------------------------------------------------------------------
00665 //
00666 // Send a resize message to the listener
00667 //
00668 //-------------------------------------------------------------------------
00669 PRBool nsWidget::OnResize(nsSizeEvent *event)
00670 {
00671 
00672   mBounds.width = event->mWinWidth;
00673   mBounds.height = event->mWinHeight;
00674 
00675   return DispatchWindowEvent(event);
00676 }
00677 
00678 
00679 PRBool nsWidget::OnResize(nsRect &aRect)
00680 {
00681   nsSizeEvent event(PR_TRUE, NS_SIZE, this);
00682 
00683   InitEvent(event);
00684 
00685   nsRect *foo = new nsRect(0, 0, aRect.width, aRect.height);
00686   event.windowSize = foo;
00687 
00688   event.point.x = 0;
00689   event.point.y = 0;
00690   event.mWinWidth = aRect.width;
00691   event.mWinHeight = aRect.height;
00692   
00693   mBounds.width = aRect.width;
00694   mBounds.height = aRect.height;
00695 
00696   ResetInternalVisibility();
00697 
00698   NS_ADDREF_THIS();
00699   PRBool result = OnResize(&event);
00700   NS_RELEASE_THIS();
00701 
00702   return result;
00703 }
00704 
00705 
00706 //------
00707 // Move
00708 //------
00709 PRBool nsWidget::OnMove(PRInt32 aX, PRInt32 aY)
00710 {
00711 #if 0
00712     printf("nsWidget::OnMove %s (%p) (%d,%d) -> (%d,%d)\n",
00713            (const char *) debug_GetName(mWidget),
00714            this, mBounds.x, mBounds.y, aX, aY);
00715 #endif
00716     mBounds.x = aX;
00717     mBounds.y = aY;
00718 
00719     ResetInternalVisibility();
00720 
00721     nsGUIEvent event(PR_TRUE, NS_MOVE, this);
00722     InitEvent(event);
00723     event.point.x = aX;
00724     event.point.y = aY;
00725     PRBool result = DispatchWindowEvent(&event);
00726     return result;
00727 }
00728 
00729 //-------------------------------------------------------------------------
00730 //
00731 // Enable/disable this component
00732 //
00733 //-------------------------------------------------------------------------
00734 NS_IMETHODIMP nsWidget::Enable(PRBool aState)
00735 {
00736   if (mWidget)
00737   {
00738     if (GTK_WIDGET_SENSITIVE(mWidget) == aState)
00739       return NS_OK;
00740     gtk_widget_set_sensitive(mWidget, aState);
00741   }
00742 
00743   return NS_OK;
00744 }
00745 
00746 NS_IMETHODIMP nsWidget::IsEnabled(PRBool *aState)
00747 {
00748   NS_ENSURE_ARG_POINTER(aState);
00749   *aState = !mWidget || GTK_WIDGET_SENSITIVE(mWidget);
00750   return NS_OK;
00751 }
00752 
00753 //-------------------------------------------------------------------------
00754 //
00755 // Give the focus to this component
00756 //
00757 //-------------------------------------------------------------------------
00758 NS_IMETHODIMP nsWidget::SetFocus(PRBool aRaise)
00759 {
00760   // call this so that any cleanup will happen that needs to...
00761   LoseFocus();
00762 
00763   if (mWidget)
00764   {
00765     if (!GTK_WIDGET_HAS_FOCUS(mWidget))
00766       gtk_widget_grab_focus(mWidget);
00767   }
00768 
00769   return NS_OK;
00770 }
00771 
00772 /* virtual */ void
00773 nsWidget::LoseFocus(void)
00774 {
00775   // doesn't do anything.  needed for nsWindow housekeeping, really.
00776   if (mHasFocus == PR_FALSE)
00777     return;
00778 
00779   sFocusWindow = 0;
00780   mHasFocus = PR_FALSE;
00781 
00782 }
00783 
00784 //-------------------------------------------------------------------------
00785 //
00786 // Get this component font
00787 //
00788 //-------------------------------------------------------------------------
00789 nsIFontMetrics *nsWidget::GetFont(void)
00790 {
00791   NS_NOTYETIMPLEMENTED("nsWidget::GetFont");
00792   return nsnull;
00793 }
00794 
00795 //-------------------------------------------------------------------------
00796 //
00797 // Set this component font
00798 //
00799 //-------------------------------------------------------------------------
00800 NS_IMETHODIMP nsWidget::SetFont(const nsFont &aFont)
00801 {
00802   return NS_ERROR_NOT_IMPLEMENTED;
00803 }
00804 
00805 //-------------------------------------------------------------------------
00806 //
00807 // Set the background color
00808 //
00809 //-------------------------------------------------------------------------
00810 
00811 NS_IMETHODIMP nsWidget::SetBackgroundColor(const nscolor &aColor)
00812 {
00813   nsBaseWidget::SetBackgroundColor(aColor);
00814 
00815   if (nsnull != mWidget) {
00816     GdkColor color_nor, color_bri, color_dark;
00817 
00818     NSCOLOR_TO_GDKCOLOR(aColor, color_nor);
00819     NSCOLOR_TO_GDKCOLOR(NS_BrightenColor(aColor), color_bri);
00820     NSCOLOR_TO_GDKCOLOR(NS_DarkenColor(aColor), color_dark);
00821 
00822     //    gdk_color.red = 256 * NS_GET_R(aColor);
00823     // gdk_color.green = 256 * NS_GET_G(aColor);
00824     // gdk_color.blue = 256 * NS_GET_B(aColor);
00825     // gdk_color.pixel ?
00826 
00827     // calls virtual native set color
00828     SetBackgroundColorNative(&color_nor, &color_bri, &color_dark);
00829 
00830 #if 0
00831     GtkStyle *style = gtk_style_copy(mWidget->style);
00832   
00833     style->bg[GTK_STATE_NORMAL]=gdk_color;
00834     // other states too? (GTK_STATE_ACTIVE, GTK_STATE_PRELIGHT,
00835     //               GTK_STATE_SELECTED, GTK_STATE_INSENSITIVE)
00836     gtk_widget_set_style(mWidget, style);
00837     gtk_style_unref(style);
00838 #endif
00839   }
00840 
00841   return NS_OK;
00842 }
00843 
00844 //-------------------------------------------------------------------------
00845 //
00846 // Set this component cursor
00847 //
00848 //-------------------------------------------------------------------------
00849 NS_IMETHODIMP nsWidget::SetCursor(nsCursor aCursor)
00850 {
00851 #ifdef DEBUG
00852   printf("nsWidget::SetCursor\n");
00853 #endif
00854   if (!mWidget || !mWidget->window)
00855     return NS_ERROR_FAILURE;
00856 
00857   // Only change cursor if it's changing
00858   if (aCursor != mCursor) {
00859     GdkCursor *newCursor = 0;
00860 
00861     /* These cases should agree with enum nsCursor in nsIWidget.h
00862      * We're limited to those cursors available with XCreateFontCursor()
00863      * If you change these, change them in gtk/nsWindow, too. */
00864     switch(aCursor) {
00865       case eCursor_standard:
00866         newCursor = gdk_cursor_new(GDK_LEFT_PTR);
00867         break;
00868 
00869       case eCursor_wait:
00870         newCursor = gdk_cursor_new(GDK_WATCH);
00871         break;
00872 
00873       case eCursor_select:
00874         newCursor = gdk_cursor_new(GDK_XTERM);
00875         break;
00876 
00877       case eCursor_hyperlink:
00878         newCursor = gdk_cursor_new(GDK_HAND2);
00879         break;
00880 
00881       case eCursor_n_resize:
00882         newCursor = gdk_cursor_new(GDK_TOP_SIDE);
00883         break;
00884       
00885       case eCursor_s_resize:
00886         newCursor = gdk_cursor_new(GDK_BOTTOM_SIDE);
00887         break;
00888       
00889       case eCursor_w_resize:
00890         newCursor = gdk_cursor_new(GDK_LEFT_SIDE);
00891         break;
00892 
00893       case eCursor_e_resize:
00894         newCursor = gdk_cursor_new(GDK_RIGHT_SIDE);
00895         break;
00896 
00897       case eCursor_nw_resize:
00898         newCursor = gdk_cursor_new(GDK_TOP_LEFT_CORNER);
00899         break;
00900 
00901       case eCursor_se_resize:
00902         newCursor = gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER);
00903         break;
00904 
00905       case eCursor_ne_resize:
00906         newCursor = gdk_cursor_new(GDK_TOP_RIGHT_CORNER);
00907         break;
00908 
00909       case eCursor_sw_resize:
00910         newCursor = gdk_cursor_new(GDK_BOTTOM_LEFT_CORNER);
00911         break;
00912 
00913       case eCursor_crosshair:
00914         newCursor = gdk_cursor_new(GDK_CROSSHAIR);
00915         break;
00916 
00917       case eCursor_move:
00918         newCursor = gdk_cursor_new(GDK_FLEUR);
00919         break;
00920 
00921       case eCursor_help:
00922         newCursor = gdk_cursor_new(GDK_QUESTION_ARROW);
00923         break;
00924 
00925       case eCursor_copy:
00926       case eCursor_alias:
00927         // XXX: these CSS3 cursors need to be implemented
00928         break;
00929 
00930       case eCursor_context_menu:
00931         newCursor = gdk_cursor_new(GDK_RIGHTBUTTON);
00932         break;
00933 
00934       case eCursor_cell:
00935         newCursor = gdk_cursor_new(GDK_PLUS);
00936         break;
00937 
00938       case eCursor_grab:
00939       case eCursor_grabbing:
00940         newCursor = gdk_cursor_new(GDK_HAND1);
00941         break;
00942 
00943       case eCursor_spinning:
00944         newCursor = gdk_cursor_new(GDK_EXCHANGE);
00945         break;
00946 
00947       case eCursor_zoom_in:
00948         newCursor = gdk_cursor_new(GDK_PLUS);
00949         break;
00950 
00951       case eCursor_zoom_out:
00952         newCursor = gdk_cursor_new(GDK_EXCHANGE);
00953         break;
00954 
00955       case eCursor_not_allowed:
00956       case eCursor_no_drop:
00957         newCursor = gdk_cursor_new(GDK_X_CURSOR);
00958         break;
00959 
00960       case eCursor_col_resize:
00961         newCursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
00962         break;
00963 
00964       case eCursor_row_resize:
00965         newCursor = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
00966         break;
00967 
00968       case eCursor_vertical_text:
00969         newCursor = gdk_cursor_new(GDK_XTERM);
00970         break;
00971 
00972       case eCursor_all_scroll:
00973         newCursor = gdk_cursor_new(GDK_FLEUR);
00974         break;
00975 
00976       case eCursor_nesw_resize:
00977         newCursor = gdk_cursor_new(GDK_TOP_RIGHT_CORNER);
00978         break;
00979 
00980       case eCursor_nwse_resize:
00981         newCursor = gdk_cursor_new(GDK_TOP_LEFT_CORNER);
00982         break;
00983 
00984       case eCursor_ns_resize:
00985         newCursor = gdk_cursor_new(GDK_SB_V_DOUBLE_ARROW);
00986         break;
00987 
00988       case eCursor_ew_resize:
00989         newCursor = gdk_cursor_new(GDK_SB_H_DOUBLE_ARROW);
00990         break;
00991 
00992       default:
00993         NS_ASSERTION(PR_FALSE, "Invalid cursor type");
00994         break;
00995     }
00996 
00997     if (nsnull != newCursor) {
00998       mCursor = aCursor;
00999       ::gdk_window_set_cursor(mWidget->window, newCursor);
01000       ::gdk_cursor_destroy(newCursor);
01001     }
01002   }
01003   return NS_OK;
01004 }
01005 
01006 #define CAPS_LOCK_IS_ON \
01007 (nsGtkUtils::gdk_keyboard_get_modifiers() & GDK_LOCK_MASK)
01008 
01009 NS_IMETHODIMP nsWidget::Validate()
01010 {
01011   mUpdateArea->SetTo(0, 0, 0, 0);
01012   return NS_OK;
01013 }
01014 
01015 NS_IMETHODIMP nsWidget::Invalidate(PRBool aIsSynchronous)
01016 {
01017   if (!mWidget)
01018     return NS_OK; // mWidget will be null during printing. 
01019 
01020   if (!GTK_IS_WIDGET(mWidget))
01021     return NS_ERROR_FAILURE;
01022 
01023   if (!GTK_WIDGET_REALIZED(mWidget) || !GTK_WIDGET_VISIBLE(mWidget))
01024     return NS_ERROR_FAILURE;
01025 
01026 #ifdef DEBUG
01027   // Check the pref _before_ checking caps lock, because checking
01028   // caps lock requires a server round-trip.
01029   if (debug_GetCachedBoolPref("nglayout.debug.invalidate_dumping") && CAPS_LOCK_IS_ON)
01030   {
01031     debug_DumpInvalidate(stdout,
01032                          this,
01033                          nsnull,
01034                          aIsSynchronous,
01035                          debug_GetName(mWidget),
01036                          debug_GetRenderXID(mWidget));
01037   }
01038 #endif // DEBUG
01039 
01040   mUpdateArea->SetTo(0, 0, mBounds.width, mBounds.height);
01041 
01042   if (aIsSynchronous) {
01043     ::gtk_widget_draw(mWidget, (GdkRectangle *) NULL);
01044   } else {
01045     ::gtk_widget_queue_draw(mWidget);
01046   }
01047 
01048   return NS_OK;
01049 }
01050 
01051 NS_IMETHODIMP nsWidget::Invalidate(const nsRect & aRect, PRBool aIsSynchronous)
01052 {
01053   if (!mWidget)
01054     return NS_OK;  // mWidget is null during printing
01055 
01056   if (!GTK_IS_WIDGET(mWidget))
01057     return NS_ERROR_FAILURE;
01058 
01059   if (!GTK_WIDGET_REALIZED(mWidget) || !GTK_WIDGET_VISIBLE(mWidget))
01060     return NS_ERROR_FAILURE;
01061 
01062   mUpdateArea->Union(aRect.x, aRect.y, aRect.width, aRect.height);
01063 
01064 #ifdef DEBUG
01065   // Check the pref _before_ checking caps lock, because checking
01066   // caps lock requires a server round-trip.
01067   if (debug_GetCachedBoolPref("nglayout.debug.invalidate_dumping") && CAPS_LOCK_IS_ON)
01068   {
01069     debug_DumpInvalidate(stdout,
01070                          this,
01071                          &aRect,
01072                          aIsSynchronous,
01073                          debug_GetName(mWidget),
01074                          debug_GetRenderXID(mWidget));
01075   }
01076 #endif // DEBUG
01077 
01078   if (aIsSynchronous)
01079   {
01080     GdkRectangle nRect;
01081     NSRECT_TO_GDKRECT(aRect, nRect);
01082 
01083     gtk_widget_draw(mWidget, &nRect);
01084   }
01085   else
01086   {
01087     gtk_widget_queue_draw_area(mWidget,
01088                                aRect.x, aRect.y,
01089                                aRect.width, aRect.height);
01090   }
01091 
01092   return NS_OK;
01093 }
01094 
01095 
01096 NS_IMETHODIMP nsWidget::InvalidateRegion(const nsIRegion *aRegion, PRBool aIsSynchronous)
01097 {
01098   nsRegionRectSet *regionRectSet = nsnull;
01099 
01100   if (!GTK_IS_WIDGET(mWidget))
01101     return NS_ERROR_FAILURE;
01102 
01103   if (!GTK_WIDGET_REALIZED(mWidget) || !GTK_WIDGET_VISIBLE(mWidget))
01104     return NS_ERROR_FAILURE;
01105 
01106   mUpdateArea->Union(*aRegion);
01107 
01108   if (NS_FAILED(mUpdateArea->GetRects(&regionRectSet)))
01109   {
01110     return NS_ERROR_FAILURE;
01111   }
01112 
01113   PRUint32 len;
01114   PRUint32 i;
01115 
01116   len = regionRectSet->mRectsLen;
01117 
01118   for (i=0;i<len;++i)
01119   {
01120     nsRegionRect *r = &(regionRectSet->mRects[i]);
01121 
01122 
01123 #ifdef DEBUG
01124     // Check the pref _before_ checking caps lock, because checking
01125     // caps lock requires a server round-trip.
01126     if (debug_GetCachedBoolPref("nglayout.debug.invalidate_dumping") && CAPS_LOCK_IS_ON)
01127     {
01128       nsRect rect(r->x, r->y, r->width, r->height);
01129       debug_DumpInvalidate(stdout,
01130                            this,
01131                            &rect,
01132                            aIsSynchronous,
01133                            debug_GetName(mWidget),
01134                            debug_GetRenderXID(mWidget));
01135     }
01136 #endif // DEBUG
01137 
01138 
01139     if (aIsSynchronous)
01140     {
01141       GdkRectangle nRect;
01142       nRect.x = r->x;
01143       nRect.y = r->y;
01144       nRect.width = r->width;
01145       nRect.height = r->height;
01146       gtk_widget_draw(mWidget, &nRect);
01147     } else {
01148       gtk_widget_queue_draw_area(mWidget,
01149                                  r->x, r->y,
01150                                  r->width, r->height);
01151     }
01152   }
01153 
01154   // drop the const.. whats the right thing to do here?
01155   ((nsIRegion*)aRegion)->FreeRects(regionRectSet);
01156 
01157   return NS_OK;
01158 }
01159 
01160 
01161 NS_IMETHODIMP nsWidget::Update(void)
01162 {
01163   if (!mWidget)
01164     return NS_OK;
01165 
01166   if (!GTK_IS_WIDGET(mWidget))
01167     return NS_ERROR_FAILURE;
01168 
01169   if (!GTK_WIDGET_REALIZED(mWidget) || !GTK_WIDGET_VISIBLE(mWidget))
01170     return NS_ERROR_FAILURE;
01171 
01172   //  printf("nsWidget::Update()\n");
01173 
01174   // this will Union() again, but so what?
01175   return InvalidateRegion(mUpdateArea, PR_TRUE);
01176 }
01177 
01178 //-------------------------------------------------------------------------
01179 //
01180 // Return some native data according to aDataType
01181 //
01182 //-------------------------------------------------------------------------
01183 void *nsWidget::GetNativeData(PRUint32 aDataType)
01184 {
01185   switch(aDataType) {
01186   case NS_NATIVE_WINDOW:
01187     if (mWidget) {
01188       return (void *)mWidget->window;
01189     }
01190     break;
01191 
01192   case NS_NATIVE_DISPLAY:
01193     return (void *)GDK_DISPLAY();
01194 
01195   case NS_NATIVE_WIDGET:
01196   case NS_NATIVE_PLUGIN_PORT:
01197     if (mWidget) {
01198       return (void *)mWidget;
01199     }
01200     break;
01201 
01202   case NS_NATIVE_GRAPHIC:
01203     /* GetSharedGC ups the ref count on the GdkGC so make sure you release
01204      * it afterwards. */
01205     NS_ASSERTION(nsnull != mToolkit, "NULL toolkit, unable to get a GC");
01206     return (void *)NS_STATIC_CAST(nsToolkit*,mToolkit)->GetSharedGC();
01207 
01208   default:
01209 #ifdef DEBUG
01210     g_print("nsWidget::GetNativeData(%i) - weird value\n", aDataType);
01211 #endif
01212     break;
01213   }
01214   return nsnull;
01215 }
01216 
01217 //-------------------------------------------------------------------------
01218 //
01219 // Set the colormap of the window
01220 //
01221 //-------------------------------------------------------------------------
01222 NS_IMETHODIMP nsWidget::SetColorMap(nsColorMap *aColorMap)
01223 {
01224   return NS_OK;
01225 }
01226 
01227 NS_IMETHODIMP nsWidget::BeginResizingChildren(void)
01228 {
01229   return NS_OK;
01230 }
01231 
01232 NS_IMETHODIMP nsWidget::EndResizingChildren(void)
01233 {
01234   return NS_OK;
01235 }
01236 
01237 NS_IMETHODIMP nsWidget::GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight)
01238 {
01239   aWidth  = mPreferredWidth;
01240   aHeight = mPreferredHeight;
01241   return (mPreferredWidth != 0 && mPreferredHeight != 0)?NS_OK:NS_ERROR_FAILURE;
01242 }
01243 
01244 NS_IMETHODIMP nsWidget::SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight)
01245 {
01246   mPreferredWidth  = aWidth;
01247   mPreferredHeight = aHeight;
01248   return NS_OK;
01249 }
01250 
01251 NS_IMETHODIMP nsWidget::SetTitle(const nsAString &aTitle)
01252 {
01253   gtk_widget_set_name(mWidget, "foo");
01254   return NS_OK;
01255 }
01256 
01257 nsresult nsWidget::CreateWidget(nsIWidget *aParent,
01258                                 const nsRect &aRect,
01259                                 EVENT_CALLBACK aHandleEventFunction,
01260                                 nsIDeviceContext *aContext,
01261                                 nsIAppShell *aAppShell,
01262                                 nsIToolkit *aToolkit,
01263                                 nsWidgetInitData *aInitData,
01264                                 nsNativeWidget aNativeParent)
01265 {
01266   GtkObject *parentWidget = nsnull;
01267 
01268 #ifdef NOISY_DESTROY
01269   if (aParent)
01270     g_print("nsWidget::CreateWidget (%p) nsIWidget parent\n",
01271             this);
01272   else if (aNativeParent)
01273     g_print("nsWidget::CreateWidget (%p) native parent\n",
01274             this);
01275   else if(aAppShell)
01276     g_print("nsWidget::CreateWidget (%p) nsAppShell parent\n",
01277             this);
01278 #endif
01279 
01280   gtk_widget_push_colormap(gdk_rgb_get_cmap());
01281   gtk_widget_push_visual(gdk_rgb_get_visual());
01282 
01283   nsIWidget *baseParent = aInitData &&
01284     (aInitData->mWindowType == eWindowType_dialog ||
01285      aInitData->mWindowType == eWindowType_toplevel ||
01286      aInitData->mWindowType == eWindowType_invisible) ?
01287     nsnull : aParent;
01288 
01289   NS_ASSERTION(aInitData->mWindowType != eWindowType_popup ||
01290                !aParent, "Popups should not be hooked into nsIWidget hierarchy");
01291 
01292   BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
01293              aAppShell, aToolkit, aInitData);
01294 
01295   mParent = aParent;
01296 
01297   if (aNativeParent) {
01298     parentWidget = GTK_OBJECT(aNativeParent);
01299     mListenForResizes = PR_TRUE;
01300   } else if (aParent) {
01301     // this ups the refcount of the gtk widget, we must unref later.
01302     parentWidget = GTK_OBJECT(aParent->GetNativeData(NS_NATIVE_WIDGET));
01303     mListenForResizes = aInitData ? aInitData->mListenForResizes : PR_FALSE;
01304   }
01305 
01306   mBounds = aRect;
01307   CreateNative (parentWidget);
01308 
01309   Resize(aRect.width, aRect.height, PR_FALSE);
01310 
01311   gtk_widget_pop_colormap();
01312   gtk_widget_pop_visual();
01313 
01314   if (mWidget) {
01315     /* we used to listen to motion notify signals, button press
01316        signals and button release signals here but since nsWindow
01317        became its own managed class we don't need to do that by
01318        default anymore.  Any subclasses that need to listen to those
01319        events should do so on their own. */
01320     
01321     // InstallButtonPressSignal(mWidget);
01322     // InstallButtonReleaseSignal(mWidget);
01323     
01324     // InstallMotionNotifySignal(mWidget);
01325     
01326     InstallEnterNotifySignal(mWidget);
01327     InstallLeaveNotifySignal(mWidget);
01328     
01329     // Focus
01330     InstallFocusInSignal(mWidget);
01331     InstallFocusOutSignal(mWidget);
01332     
01333   }
01334 
01335   DispatchStandardEvent(NS_CREATE);
01336   InitCallbacks();
01337 
01338   if (mWidget) {
01339     // Add in destroy callback
01340     gtk_signal_connect(GTK_OBJECT(mWidget),
01341                        "destroy",
01342                        GTK_SIGNAL_FUNC(DestroySignal),
01343                        this);
01344   }
01345 
01346   return NS_OK;
01347 }
01348 
01349 //-------------------------------------------------------------------------
01350 //
01351 // create with nsIWidget parent
01352 //
01353 //-------------------------------------------------------------------------
01354 
01355 NS_IMETHODIMP nsWidget::Create(nsIWidget *aParent,
01356                            const nsRect &aRect,
01357                            EVENT_CALLBACK aHandleEventFunction,
01358                            nsIDeviceContext *aContext,
01359                            nsIAppShell *aAppShell,
01360                            nsIToolkit *aToolkit,
01361                            nsWidgetInitData *aInitData)
01362 {
01363   return CreateWidget(aParent, aRect, aHandleEventFunction,
01364                       aContext, aAppShell, aToolkit, aInitData,
01365                       nsnull);
01366 }
01367 
01368 //-------------------------------------------------------------------------
01369 //
01370 // create with a native parent
01371 //
01372 //-------------------------------------------------------------------------
01373 NS_IMETHODIMP nsWidget::Create(nsNativeWidget aParent,
01374                            const nsRect &aRect,
01375                            EVENT_CALLBACK aHandleEventFunction,
01376                            nsIDeviceContext *aContext,
01377                            nsIAppShell *aAppShell,
01378                            nsIToolkit *aToolkit,
01379                            nsWidgetInitData *aInitData)
01380 {
01381   return CreateWidget(nsnull, aRect, aHandleEventFunction,
01382                       aContext, aAppShell, aToolkit, aInitData,
01383                       aParent);
01384 }
01385 
01386 //-------------------------------------------------------------------------
01387 //
01388 // Initialize all the Callbacks
01389 //
01390 //-------------------------------------------------------------------------
01391 void nsWidget::InitCallbacks(char *aName)
01392 {
01393 }
01394 
01395 void nsWidget::ConvertToDeviceCoordinates(nscoord &aX, nscoord &aY)
01396 {
01397 
01398 }
01399 
01400 void nsWidget::InitEvent(nsGUIEvent& event, nsPoint* aPoint)
01401 {
01402   // This copies, and we need to call gdk_event_free.
01403   GdkEvent *ge = gtk_get_current_event();
01404 
01405   if (aPoint == nsnull) {     // use the point from the event
01406     // get the message position in client coordinates and in twips
01407 
01408     if (ge != nsnull) {
01409       //       ::ScreenToClient(mWnd, &cpos);
01410       event.point.x = PRInt32(ge->configure.x);
01411       event.point.y = PRInt32(ge->configure.y);
01412     }  
01413   }    
01414   else {                      // use the point override if provided
01415     event.point.x = aPoint->x;
01416     event.point.y = aPoint->y;
01417   }
01418 
01419   event.time = gdk_event_get_time(ge);
01420 
01421   //    mLastPoint.x = event.point.x;
01422   //    mLastPoint.y = event.point.y;
01423 
01424   if (ge)
01425     gdk_event_free(ge);
01426 }
01427 
01428 PRBool nsWidget::ConvertStatus(nsEventStatus aStatus)
01429 {
01430   switch(aStatus) {
01431   case nsEventStatus_eIgnore:
01432     return(PR_FALSE);
01433   case nsEventStatus_eConsumeNoDefault:
01434     return(PR_TRUE);
01435   case nsEventStatus_eConsumeDoDefault:
01436     return(PR_FALSE);
01437   default:
01438     NS_ASSERTION(0, "Illegal nsEventStatus enumeration value");
01439     break;
01440   }
01441   return PR_FALSE;
01442 }
01443 
01444 PRBool nsWidget::DispatchWindowEvent(nsGUIEvent* event)
01445 {
01446   nsEventStatus status;
01447   DispatchEvent(event, status);
01448   return ConvertStatus(status);
01449 }
01450 
01451 //-------------------------------------------------------------------------
01452 //
01453 // Dispatch standard event
01454 //
01455 //-------------------------------------------------------------------------
01456 
01457 PRBool nsWidget::DispatchStandardEvent(PRUint32 aMsg)
01458 {
01459   nsGUIEvent event(PR_TRUE, aMsg, this);
01460   InitEvent(event);
01461   PRBool result = DispatchWindowEvent(&event);
01462   return result;
01463 }
01464 
01465 PRBool nsWidget::DispatchFocus(nsGUIEvent &aEvent)
01466 {
01467   if (mEventCallback)
01468     return DispatchWindowEvent(&aEvent);
01469 
01470   return PR_FALSE;
01471 }
01472 
01474 //
01475 // OnSomething handlers
01476 //
01478 
01479 #ifdef DEBUG
01480 PRInt32
01481 nsWidget::debug_GetRenderXID(GtkObject * aGtkWidget)
01482 {
01483   GdkWindow * renderWindow = GetRenderWindow(aGtkWidget);
01484   
01485   Window      xid = renderWindow ? GDK_WINDOW_XWINDOW(renderWindow) : 0x0;
01486   
01487   return (PRInt32) xid;
01488 }
01489 
01490 PRInt32
01491 nsWidget::debug_GetRenderXID(GtkWidget * aGtkWidget)
01492 {
01493   return debug_GetRenderXID(GTK_OBJECT(aGtkWidget));
01494 }
01495 
01496 nsCAutoString
01497 nsWidget::debug_GetName(GtkObject * aGtkWidget)
01498 {
01499   if (nsnull != aGtkWidget && GTK_IS_WIDGET(aGtkWidget))
01500     return debug_GetName(GTK_WIDGET(aGtkWidget));
01501   
01502   return nsCAutoString("null");
01503 }
01504 
01505 nsCAutoString
01506 nsWidget::debug_GetName(GtkWidget * aGtkWidget)
01507 {
01508 
01509   if (nsnull != aGtkWidget)
01510     return nsCAutoString(gtk_widget_get_name(aGtkWidget));
01511   
01512   return nsCAutoString("null");
01513 }
01514 
01515 #endif // DEBUG
01516 
01517 
01519 
01520 //-------------------------------------------------------------------------
01521 //
01522 // Invokes callback and  ProcessEvent method on Event Listener object
01523 //
01524 //-------------------------------------------------------------------------
01525 
01526 NS_IMETHODIMP nsWidget::DispatchEvent(nsGUIEvent *aEvent,
01527                                       nsEventStatus &aStatus)
01528 {
01529   NS_ADDREF(aEvent->widget);
01530 
01531 #ifdef DEBUG
01532   GtkObject *gw;
01533   void *nativeWidget = aEvent->widget->GetNativeData(NS_NATIVE_WIDGET);
01534   if (nativeWidget) {
01535     gw = GTK_OBJECT(nativeWidget);
01536     
01537     // Check the pref _before_ checking caps lock, because checking
01538     // caps lock requires a server round-trip.
01539 
01540     if (debug_GetCachedBoolPref("nglayout.debug.event_dumping") && CAPS_LOCK_IS_ON)
01541       {
01542         debug_DumpEvent(stdout,
01543                         aEvent->widget,
01544                         aEvent,
01545                         debug_GetName(gw),
01546                         (PRInt32) debug_GetRenderXID(gw));
01547       }
01548   }
01549 #endif // DEBUG
01550 
01551   if (nsnull != mMenuListener) {
01552     if (NS_MENU_EVENT == aEvent->eventStructType)
01553       aStatus = mMenuListener->MenuSelected(NS_STATIC_CAST(nsMenuEvent&, *aEvent));
01554   }
01555 
01556   aStatus = nsEventStatus_eIgnore;
01557   if (nsnull != mEventCallback) {
01558     aStatus = (*mEventCallback)(aEvent);
01559   }
01560 
01561   // Dispatch to event listener if event was not consumed
01562   if ((aStatus != nsEventStatus_eIgnore) && (nsnull != mEventListener)) {
01563     aStatus = mEventListener->ProcessEvent(*aEvent);
01564   }
01565   NS_IF_RELEASE(aEvent->widget);
01566 
01567   return NS_OK;
01568 }
01569 
01570 
01571 //-------------------------------------------------------------------------
01572 //
01573 // Deal with all sort of mouse event
01574 //
01575 //-------------------------------------------------------------------------
01576 PRBool nsWidget::DispatchMouseEvent(nsMouseEvent& aEvent)
01577 {
01578   PRBool result = PR_FALSE;
01579   if (nsnull == mEventCallback && nsnull == mMouseListener) {
01580     return result;
01581   }
01582 
01583   // call the event callback
01584   if (nsnull != mEventCallback) {
01585     result = DispatchWindowEvent(&aEvent);
01586 
01587     return result;
01588   }
01589 
01590   if (nsnull != mMouseListener) {
01591     switch (aEvent.message) {
01592       case NS_MOUSE_MOVE: {
01593 //         result = ConvertStatus(mMouseListener->MouseMoved(aEvent));
01594 //         nsRect rect;
01595 //         GetBounds(rect);
01596 //         if (rect.Contains(event.point.x, event.point.y)) {
01597 //           if (mCurrentWindow == NULL || mCurrentWindow != this) {
01598 //             printf("Mouse enter");
01599 //             mCurrentWindow = this;
01600 //           }
01601 //         } else {
01602 //           printf("Mouse exit");
01603 //         }
01604 
01605       } break;
01606 
01607       case NS_MOUSE_LEFT_BUTTON_DOWN:
01608       case NS_MOUSE_MIDDLE_BUTTON_DOWN:
01609       case NS_MOUSE_RIGHT_BUTTON_DOWN:
01610         result = ConvertStatus(mMouseListener->MousePressed(aEvent));
01611         break;
01612 
01613       case NS_MOUSE_LEFT_BUTTON_UP:
01614       case NS_MOUSE_MIDDLE_BUTTON_UP:
01615       case NS_MOUSE_RIGHT_BUTTON_UP:
01616         result = ConvertStatus(mMouseListener->MouseReleased(aEvent));
01617         result = ConvertStatus(mMouseListener->MouseClicked(aEvent));
01618         break;
01619 
01620     case NS_DRAGDROP_DROP:
01621 #ifdef DEBUG 
01622       printf("nsWidget::DispatchMouseEvent, NS_DRAGDROP_DROP\n");
01623 #endif
01624       break;
01625 
01626     default:
01627       break;
01628 
01629     } // switch
01630   }
01631   return result;
01632 }
01633 
01635 
01637 //
01638 // GTK signal installers
01639 //
01641 void
01642 nsWidget::AddToEventMask(GtkWidget * aWidget,
01643                          gint        aEventMask)
01644 {
01645   NS_ASSERTION( nsnull != aWidget, "widget is null");
01646   NS_ASSERTION( 0 != aEventMask, "mask is 0");
01647 
01648   gtk_widget_add_events(aWidget,aEventMask);
01649 }
01651 void 
01652 nsWidget::InstallEnterNotifySignal(GtkWidget * aWidget)
01653 {
01654   NS_ASSERTION( nsnull != aWidget, "widget is null");
01655 
01656   InstallSignal(aWidget,
01657                             (gchar *)"enter_notify_event",
01658                             GTK_SIGNAL_FUNC(nsWidget::EnterNotifySignal));
01659 }
01661 void 
01662 nsWidget::InstallLeaveNotifySignal(GtkWidget * aWidget)
01663 {
01664   NS_ASSERTION( nsnull != aWidget, "widget is null");
01665 
01666   InstallSignal(aWidget,
01667                             (gchar *)"leave_notify_event",
01668                             GTK_SIGNAL_FUNC(nsWidget::LeaveNotifySignal));
01669 }
01671 void 
01672 nsWidget::InstallButtonPressSignal(GtkWidget * aWidget)
01673 {
01674   NS_ASSERTION( nsnull != aWidget, "widget is null");
01675 
01676   InstallSignal(aWidget,
01677                             (gchar *)"button_press_event",
01678                             GTK_SIGNAL_FUNC(nsWidget::ButtonPressSignal));
01679 }
01681 void 
01682 nsWidget::InstallButtonReleaseSignal(GtkWidget * aWidget)
01683 {
01684   NS_ASSERTION( nsnull != aWidget, "widget is null");
01685 
01686   InstallSignal(aWidget,
01687                             (gchar *)"button_release_event",
01688                             GTK_SIGNAL_FUNC(nsWidget::ButtonReleaseSignal));
01689 }
01691 void 
01692 nsWidget::InstallFocusInSignal(GtkWidget * aWidget)
01693 {
01694   NS_ASSERTION( nsnull != aWidget, "widget is null");
01695 
01696   InstallSignal(aWidget,
01697                             (gchar *)"focus_in_event",
01698                             GTK_SIGNAL_FUNC(nsWidget::FocusInSignal));
01699 }
01701 void 
01702 nsWidget::InstallFocusOutSignal(GtkWidget * aWidget)
01703 {
01704   NS_ASSERTION( nsnull != aWidget, "widget is null");
01705 
01706   InstallSignal(aWidget,
01707                             (gchar *)"focus_out_event",
01708                             GTK_SIGNAL_FUNC(nsWidget::FocusOutSignal));
01709 }
01711 void 
01712 nsWidget::InstallRealizeSignal(GtkWidget * aWidget)
01713 {
01714   NS_ASSERTION( nsnull != aWidget, "widget is null");
01715   
01716   InstallSignal(aWidget,
01717                             (gchar *)"realize",
01718                             GTK_SIGNAL_FUNC(nsWidget::RealizeSignal));
01719 }
01721 
01723 /* virtual */ void 
01724 nsWidget::OnMotionNotifySignal(GdkEventMotion * aGdkMotionEvent)
01725 {
01726   
01727   if (mIsDestroying)
01728     return;
01729 
01730   nsMouseEvent event(PR_TRUE, NS_MOUSE_MOVE, nsnull, nsMouseEvent::eReal);
01731 
01732   // If there is a button motion target, use that instead of the
01733   // current widget
01734 
01735   // XXX pav
01736   // i'm confused as to wtf this sButtonMoetionTarget thing is for.
01737   // so i'm not going to use it.
01738 
01739   // XXX ramiro
01740   // 
01741   // Because of dynamic widget creation and destruction, this could
01742   // potentially be a dangerious thing to do.  
01743   //
01744   // If the sButtonMotionTarget is destroyed between the time when
01745   // it got set and now, we should end up sending an event to 
01746   // a junk nsWidget.
01747   //
01748   // The way to solve this would be to add a destroy signal to
01749   // the GtkWidget corresponding to the sButtonMotionTarget and
01750   // marking if nsnull in there.
01751   //
01752   gint x, y;
01753 
01754   if (aGdkMotionEvent)
01755   {
01756     x = (gint) aGdkMotionEvent->x;
01757     y = (gint) aGdkMotionEvent->y;
01758 
01759     event.point.x = nscoord(x);
01760     event.point.y = nscoord(y);
01761     event.widget = this;
01762   }
01763 
01764   if (sButtonMotionTarget)
01765   {
01766     gint diffX;
01767     gint diffY;
01768 
01769     if (aGdkMotionEvent) 
01770     {
01771       // Compute the difference between the original root coordinates
01772       diffX = (gint) aGdkMotionEvent->x_root - sButtonMotionRootX;
01773       diffY = (gint) aGdkMotionEvent->y_root - sButtonMotionRootY;
01774       
01775       event.widget = sButtonMotionTarget;
01776       
01777       // The event coords will be the initial *widget* coords plus the 
01778       // root difference computed above.
01779       event.point.x = nscoord(sButtonMotionWidgetX + diffX);
01780       event.point.y = nscoord(sButtonMotionWidgetY + diffY);
01781     }
01782   }
01783   else
01784   {
01785     event.widget = this;
01786   }
01787 
01788   if (aGdkMotionEvent)
01789   {
01790     event.time = aGdkMotionEvent->time;
01791     event.isShift = aGdkMotionEvent->state & ShiftMask;
01792     event.isControl = aGdkMotionEvent->state & ControlMask;
01793     event.isAlt = aGdkMotionEvent->state & Mod1Mask;
01794   }
01795 
01796   AddRef();
01797 
01798   if (sButtonMotionTarget)
01799     sButtonMotionTarget->DispatchMouseEvent(event);
01800   else
01801     DispatchMouseEvent(event);
01802 
01803   Release();
01804 }
01805 
01807 /* virtual */ void
01808 nsWidget::OnEnterNotifySignal(GdkEventCrossing * aGdkCrossingEvent)
01809 {
01810   if (aGdkCrossingEvent->subwindow != NULL)
01811     return;
01812 
01813   // If there is a button motion target, then we can ignore this
01814   // event since what the gecko event system expects is for
01815   // only motion events to be sent to that widget, even if the
01816   // pointer is crossing on other widgets.
01817   //
01818   // XXX ramiro - Same as above.
01819   //
01820   if (nsnull != sButtonMotionTarget)
01821   {
01822     return;
01823   }
01824 
01825   nsMouseEvent event(PR_TRUE, NS_MOUSE_ENTER, this, nsMouseEvent::eReal);
01826 
01827   if (aGdkCrossingEvent != NULL) 
01828   {
01829     event.point.x = nscoord(aGdkCrossingEvent->x);
01830     event.point.y = nscoord(aGdkCrossingEvent->y);
01831     event.time = aGdkCrossingEvent->time;
01832   }
01833 
01834   AddRef();
01835 
01836   DispatchMouseEvent(event);
01837 
01838   Release();
01839 }
01841 /* virtual */ void
01842 nsWidget::OnLeaveNotifySignal(GdkEventCrossing * aGdkCrossingEvent)
01843 {
01844   if (aGdkCrossingEvent->subwindow != NULL)
01845     return;
01846 
01847   // If there is a button motion target, then we can ignore this
01848   // event since what the gecko event system expects is for
01849   // only motion events to be sent to that widget, even if the
01850   // pointer is crossing on other widgets.
01851   //
01852   // XXX ramiro - Same as above.
01853   //
01854   if (nsnull != sButtonMotionTarget)
01855   {
01856     return;
01857   }
01858 
01859   nsMouseEvent event(PR_TRUE, NS_MOUSE_EXIT, this, nsMouseEvent::eReal);
01860 
01861   if (aGdkCrossingEvent != NULL) 
01862   {
01863     event.point.x = nscoord(aGdkCrossingEvent->x);
01864     event.point.y = nscoord(aGdkCrossingEvent->y);
01865     event.time = aGdkCrossingEvent->time;
01866   }
01867 
01868   AddRef();
01869 
01870   DispatchMouseEvent(event);
01871 
01872   Release();
01873 }
01874 
01875 
01877 /* virtual */ void
01878 nsWidget::OnButtonPressSignal(GdkEventButton * aGdkButtonEvent)
01879 {
01880   nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
01881   PRUint32 eventType = 0;
01882 
01883   // If you double click in GDK, it will actually generate a single
01884   // click event before sending the double click event, and this is
01885   // different than the DOM spec.  GDK puts this in the queue
01886   // programatically, so it's safe to assume that if there's a
01887   // double click in the queue, it was generated so we can just drop
01888   // this click.
01889   GdkEvent *peekedEvent = gdk_event_peek();
01890   if (peekedEvent) {
01891     GdkEventType type = peekedEvent->any.type;
01892     gdk_event_free(peekedEvent);
01893     if (type == GDK_2BUTTON_PRESS || type == GDK_3BUTTON_PRESS)
01894       return;
01895   }
01896 
01897 
01898   // Switch on single, double, triple click.
01899   switch (aGdkButtonEvent->type) 
01900   {
01901     // Single click.
01902   case GDK_BUTTON_PRESS:
01903     // Double click.
01904   case GDK_2BUTTON_PRESS:
01905     // Triple click.
01906   case GDK_3BUTTON_PRESS:
01907 
01908     switch (aGdkButtonEvent->button)  // Which button?
01909     {
01910     case 1:
01911       eventType = NS_MOUSE_LEFT_BUTTON_DOWN;
01912       break;
01913 
01914     case 2:
01915       eventType = NS_MOUSE_MIDDLE_BUTTON_DOWN;
01916       break;
01917 
01918     case 3:
01919       eventType = NS_MOUSE_RIGHT_BUTTON_DOWN;
01920       break;
01921 
01922     case 4:
01923     case 5:
01924     case 6:
01925     case 7:
01926       if (aGdkButtonEvent->button == 4 || aGdkButtonEvent->button == 5)
01927         scrollEvent.scrollFlags = nsMouseScrollEvent::kIsVertical;
01928       else
01929         scrollEvent.scrollFlags = nsMouseScrollEvent::kIsHorizontal;
01930 
01931       if (aGdkButtonEvent->button == 4 || aGdkButtonEvent->button == 6)
01932         scrollEvent.delta = -3;
01933       else
01934         scrollEvent.delta = 3;
01935 
01936       scrollEvent.point.x = nscoord(aGdkButtonEvent->x);
01937       scrollEvent.point.y = nscoord(aGdkButtonEvent->y);
01938       
01939       scrollEvent.isShift = (aGdkButtonEvent->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
01940       scrollEvent.isControl = (aGdkButtonEvent->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
01941       scrollEvent.isAlt = (aGdkButtonEvent->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
01942       scrollEvent.isMeta = PR_FALSE;  // GTK+ doesn't support the meta key
01943       scrollEvent.time = aGdkButtonEvent->time;
01944       AddRef();
01945       if (mEventCallback)
01946         DispatchWindowEvent(&scrollEvent);
01947       Release();
01948       return;
01949 
01950       // Single-click default.
01951     default:
01952       eventType = NS_MOUSE_LEFT_BUTTON_DOWN;
01953       break;
01954     }
01955     break;
01956 
01957   default:
01958     break;
01959   }
01960 
01961   nsMouseEvent event(PR_TRUE, eventType, this, nsMouseEvent::eReal);
01962   InitMouseEvent(aGdkButtonEvent, event);
01963 
01964   // Set the button motion target and remeber the widget and root coords
01965   sButtonMotionTarget = this;
01966 
01967   // Make sure to add this widget to the gtk grab list so that events
01968   // are rewritten to this window.
01969   GtkWidget *owningWidget;
01970   owningWidget = GetOwningWidget();
01971   if (owningWidget)
01972     gtk_grab_add(owningWidget);
01973 
01974   sButtonMotionRootX = (gint) aGdkButtonEvent->x_root;
01975   sButtonMotionRootY = (gint) aGdkButtonEvent->y_root;
01976 
01977   sButtonMotionWidgetX = (gint) aGdkButtonEvent->x;
01978   sButtonMotionWidgetY = (gint) aGdkButtonEvent->y;
01979   
01980   AddRef(); // kung-fu deathgrip
01981 
01982   DispatchMouseEvent(event);
01983 
01984   // if we're a right-button-down on linux, we're trying to
01985   // popup a context menu. send that event to gecko also.
01986   if (eventType == NS_MOUSE_RIGHT_BUTTON_DOWN) {
01987     nsMouseEvent contextMenuEvent(PR_TRUE, NS_CONTEXTMENU, this,
01988                                   nsMouseEvent::eReal);
01989     InitMouseEvent(aGdkButtonEvent, contextMenuEvent);
01990     DispatchMouseEvent(contextMenuEvent);
01991   }
01992 
01993   Release();
01994 
01995 }
01997 /* virtual */ void
01998 nsWidget::OnButtonReleaseSignal(GdkEventButton * aGdkButtonEvent)
01999 {
02000   PRUint32 eventType = 0;
02001 
02002   switch (aGdkButtonEvent->button)
02003   {
02004   case 1:
02005     eventType = NS_MOUSE_LEFT_BUTTON_UP;
02006     break;
02007          
02008   case 2:
02009     eventType = NS_MOUSE_MIDDLE_BUTTON_UP;
02010     break;
02011          
02012   case 3:
02013     eventType = NS_MOUSE_RIGHT_BUTTON_UP;
02014     break;
02015 
02016   case 4:
02017   case 5:
02018   case 6:
02019   case 7:
02020     // We don't really need to do anything here, but we don't want
02021     // LEFT_BUTTON_UP to happen
02022     return;
02023 
02024   default:
02025     eventType = NS_MOUSE_LEFT_BUTTON_UP;
02026     break;
02027        }
02028 
02029   nsMouseEvent event(PR_TRUE, eventType, this, nsMouseEvent::eReal);
02030   InitMouseEvent(aGdkButtonEvent, event);
02031 
02032   if (sButtonMotionTarget) {
02033     gint diffX = 0;
02034     gint diffY = 0;
02035 
02036     diffX = (gint) aGdkButtonEvent->x_root - sButtonMotionRootX;
02037     diffY = (gint) aGdkButtonEvent->y_root - sButtonMotionRootY;
02038 
02039     event.widget = sButtonMotionTarget;
02040 
02041     // see comments in nsWidget::OnMotionNotifySignal
02042     event.point.x = nscoord(sButtonMotionWidgetX + diffX);
02043     event.point.y = nscoord(sButtonMotionWidgetY + diffY);
02044   }
02045 
02046   // Drop the motion target before dispatching the event so that we
02047   // don't get events that we shouldn't.
02048   DropMotionTarget();
02049 
02050   // event.widget can get set to null when calling DispatchMouseEvent,
02051   // so to release it we must make a copy
02052   nsWidget* theWidget = NS_STATIC_CAST(nsWidget*,event.widget);
02053 
02054   NS_ADDREF(theWidget);
02055   theWidget->DispatchMouseEvent(event);
02056   NS_IF_RELEASE(theWidget);
02057 
02058 }
02060 /* virtual */ void
02061 nsWidget::OnFocusInSignal(GdkEventFocus * aGdkFocusEvent)
02062 {
02063   if (mIsDestroying)
02064     return;
02065 
02066   GTK_WIDGET_SET_FLAGS(mWidget, GTK_HAS_FOCUS);
02067 
02068   nsFocusEvent event(PR_TRUE, NS_GOTFOCUS, this);
02069 
02070 //  event.time = aGdkFocusEvent->time;;
02071 //  event.time = PR_Now();
02072 
02073   AddRef();
02074   
02075   DispatchFocus(event);
02076   
02077   Release();
02078 }
02080 /* virtual */ void
02081 nsWidget::OnFocusOutSignal(GdkEventFocus * aGdkFocusEvent)
02082 {
02083   if (mIsDestroying)
02084     return;
02085 
02086   GTK_WIDGET_UNSET_FLAGS(mWidget, GTK_HAS_FOCUS);
02087 
02088   nsFocusEvent event(PR_TRUE, NS_LOSTFOCUS, this);
02089 
02090 //  event.time = aGdkFocusEvent->time;;
02091 //  event.time = PR_Now();
02092 
02093   AddRef();
02094   
02095   DispatchFocus(event);
02096   
02097   Release();
02098 }
02100 /* virtual */ void
02101 nsWidget::OnRealize(GtkWidget *aWidget)
02102 {
02103 #ifdef DEBUG
02104   printf("nsWidget::OnRealize(%p)\n", NS_STATIC_CAST(void *, this));
02105 #endif
02106 }
02108 
02109 
02111 //
02112 // GTK event support methods
02113 //
02115 void 
02116 nsWidget::InstallSignal(GtkWidget *   aWidget,
02117                         gchar *       aSignalName,
02118                         GtkSignalFunc aSignalFunction)
02119 {
02120   NS_ASSERTION( nsnull != aWidget, "widget is null");
02121   NS_ASSERTION( aSignalName, "signal name is null");
02122   NS_ASSERTION( aSignalFunction, "signal function is null");
02123 
02124   gtk_signal_connect(GTK_OBJECT(aWidget),
02125                      aSignalName,
02126                      GTK_SIGNAL_FUNC(aSignalFunction),
02127                      (gpointer) this);
02128 }
02130 void 
02131 nsWidget::InitMouseEvent(GdkEventButton * aGdkButtonEvent,
02132                          nsMouseEvent &anEvent)
02133 {
02134   if (aGdkButtonEvent != NULL) {
02135     anEvent.point.x = nscoord(aGdkButtonEvent->x);
02136     anEvent.point.y = nscoord(aGdkButtonEvent->y);
02137 
02138     anEvent.isShift = (aGdkButtonEvent->state & GDK_SHIFT_MASK) ? PR_TRUE : PR_FALSE;
02139     anEvent.isControl = (aGdkButtonEvent->state & GDK_CONTROL_MASK) ? PR_TRUE : PR_FALSE;
02140     anEvent.isAlt = (aGdkButtonEvent->state & GDK_MOD1_MASK) ? PR_TRUE : PR_FALSE;
02141     anEvent.isMeta = PR_FALSE;  // GTK+ doesn't support the meta key
02142     anEvent.time = aGdkButtonEvent->time;
02143 
02144     switch(aGdkButtonEvent->type)
02145       {
02146       case GDK_BUTTON_PRESS:
02147         anEvent.clickCount = 1;
02148         break;
02149       case GDK_2BUTTON_PRESS:
02150         anEvent.clickCount = 2;
02151         break;
02152       case GDK_3BUTTON_PRESS:
02153         anEvent.clickCount = 3;
02154         break;
02155       default:
02156         anEvent.clickCount = 1;
02157     }
02158 
02159   }
02160 }
02161 
02163 //
02164 // GTK widget signals
02165 //
02167 /* static */ gint 
02168 nsWidget::EnterNotifySignal(GtkWidget *        aWidget, 
02169                                                  GdkEventCrossing * aGdkCrossingEvent, 
02170                                                  gpointer           aData)
02171 {
02172   NS_ASSERTION( nsnull != aWidget, "widget is null");
02173   NS_ASSERTION( nsnull != aGdkCrossingEvent, "event is null");
02174 
02175   nsWidget * widget = (nsWidget *) aData;
02176 
02177   NS_ASSERTION( nsnull != widget, "instance pointer is null");
02178 
02179   widget->OnEnterNotifySignal(aGdkCrossingEvent);
02180 
02181   return PR_TRUE;
02182 }
02184 /* static */ gint 
02185 nsWidget::LeaveNotifySignal(GtkWidget *        aWidget, 
02186                                                  GdkEventCrossing * aGdkCrossingEvent, 
02187                                                  gpointer           aData)
02188 {
02189   NS_ASSERTION( nsnull != aWidget, "widget is null");
02190   NS_ASSERTION( nsnull != aGdkCrossingEvent, "event is null");
02191 
02192   nsWidget * widget = (nsWidget *) aData;
02193 
02194   NS_ASSERTION( nsnull != widget, "instance pointer is null");
02195 
02196   widget->OnLeaveNotifySignal(aGdkCrossingEvent);
02197 
02198   return PR_TRUE;
02199 }
02201 /* static */ gint 
02202 nsWidget::ButtonPressSignal(GtkWidget *      aWidget, 
02203                                                  GdkEventButton * aGdkButtonEvent, 
02204                                                  gpointer         aData)
02205 {
02206   //  printf("nsWidget::ButtonPressSignal(%p)\n",aData);
02207 
02208   NS_ASSERTION( nsnull != aWidget, "widget is null");
02209   NS_ASSERTION( nsnull != aGdkButtonEvent, "event is null");
02210 
02211   nsWidget * widget = (nsWidget *) aData;
02212 
02213   NS_ASSERTION( nsnull != widget, "instance pointer is null");
02214 
02215   widget->OnButtonPressSignal(aGdkButtonEvent);
02216 
02217   return PR_TRUE;
02218 }
02220 /* static */ gint 
02221 nsWidget::ButtonReleaseSignal(GtkWidget *      aWidget, 
02222                                                  GdkEventButton * aGdkButtonEvent, 
02223                                                  gpointer         aData)
02224 {
02225   //  printf("nsWidget::ButtonReleaseSignal(%p)\n",aData);
02226 
02227   NS_ASSERTION( nsnull != aWidget, "widget is null");
02228   NS_ASSERTION( nsnull != aGdkButtonEvent, "event is null");
02229 
02230   nsWidget * widget = (nsWidget *) aData;
02231 
02232   NS_ASSERTION( nsnull != widget, "instance pointer is null");
02233 
02234   widget->OnButtonReleaseSignal(aGdkButtonEvent);
02235 
02236   return PR_TRUE;
02237 }
02239 /* static */ gint 
02240 nsWidget::RealizeSignal(GtkWidget *      aWidget,
02241                         gpointer         aData)
02242 {
02243   NS_ASSERTION( nsnull != aWidget, "widget is null");
02244   
02245   nsWidget * widget = (nsWidget *) aData;
02246 
02247   NS_ASSERTION( nsnull != widget, "instance pointer is null");
02248   
02249   widget->OnRealize(aWidget);
02250 
02251   return PR_TRUE;
02252 }
02254 /* static */ gint
02255 nsWidget::FocusInSignal(GtkWidget *      aWidget, 
02256                         GdkEventFocus *  aGdkFocusEvent, 
02257                         gpointer         aData)
02258 {
02259   //  printf("nsWidget::ButtonReleaseSignal(%p)\n",aData);
02260 
02261   NS_ASSERTION( nsnull != aWidget, "widget is null");
02262   NS_ASSERTION( nsnull != aGdkFocusEvent, "event is null");
02263 
02264   nsWidget * widget = (nsWidget *) aData;
02265 
02266   NS_ASSERTION( nsnull != widget, "instance pointer is null");
02267 
02268   widget->OnFocusInSignal(aGdkFocusEvent);
02269 
02270   if (GTK_IS_WINDOW(aWidget))
02271     gtk_signal_emit_stop_by_name(GTK_OBJECT(aWidget), "focus_in_event");
02272   
02273   return PR_TRUE;
02274 }
02276 /* static */ gint
02277 nsWidget::FocusOutSignal(GtkWidget *      aWidget, 
02278                         GdkEventFocus *  aGdkFocusEvent, 
02279                         gpointer         aData)
02280 {
02281   //  printf("nsWidget::ButtonReleaseSignal(%p)\n",aData);
02282 
02283   NS_ASSERTION( nsnull != aWidget, "widget is null");
02284   NS_ASSERTION( nsnull != aGdkFocusEvent, "event is null");
02285 
02286   nsWidget * widget = (nsWidget *) aData;
02287 
02288   NS_ASSERTION( nsnull != widget, "instance pointer is null");
02289 
02290   widget->OnFocusOutSignal(aGdkFocusEvent);
02291 
02292   if (GTK_IS_WINDOW(aWidget))
02293     gtk_signal_emit_stop_by_name(GTK_OBJECT(aWidget), "focus_out_event");
02294   
02295   return PR_TRUE;
02296 }
02298 
02299 /* virtual */ GdkWindow *
02300 nsWidget::GetRenderWindow(GtkObject * aGtkWidget)
02301 {
02302   GdkWindow * renderWindow = nsnull;
02303 
02304   if (GDK_IS_SUPERWIN(aGtkWidget)) {
02305     renderWindow = GDK_SUPERWIN(aGtkWidget)->bin_window;
02306   }
02307 
02308   return renderWindow;
02309 }
02310 
02311 void
02312 nsWidget::ThemeChanged()
02313 {
02314   // Dispatch a NS_THEMECHANGED event for each of our children, recursively
02315   for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
02316     NS_STATIC_CAST(nsWidget*, kid)->ThemeChanged();
02317   }
02318 
02319   DispatchStandardEvent(NS_THEMECHANGED);
02320   Invalidate(PR_FALSE);
02321 }
02322 
02324 // default setfont for most widgets
02325 /*virtual*/
02326 void nsWidget::SetFontNative(GdkFont *aFont)
02327 {
02328   GtkStyle *style = gtk_style_copy(mWidget->style);
02329   // gtk_style_copy ups the ref count of the font
02330   gdk_font_unref (style->font);
02331   
02332   style->font = aFont;
02333   gdk_font_ref(style->font);
02334   
02335   gtk_widget_set_style(mWidget, style);
02336   
02337   gtk_style_unref(style);
02338 }
02339 
02341 // default SetBackgroundColor for most widgets
02342 /*virtual*/
02343 void nsWidget::SetBackgroundColorNative(GdkColor *aColorNor,
02344                                         GdkColor *aColorBri,
02345                                         GdkColor *aColorDark)
02346 {
02347   // use same style copy as SetFont
02348   GtkStyle *style = gtk_style_copy(mWidget->style);
02349   
02350   style->bg[GTK_STATE_NORMAL]=*aColorNor;
02351   
02352   // Mouse over button
02353   style->bg[GTK_STATE_PRELIGHT]=*aColorBri;
02354 
02355   // Button is down
02356   style->bg[GTK_STATE_ACTIVE]=*aColorDark;
02357 
02358   // other states too? (GTK_STATE_ACTIVE, GTK_STATE_PRELIGHT,
02359   //               GTK_STATE_SELECTED, GTK_STATE_INSENSITIVE)
02360   gtk_widget_set_style(mWidget, style);
02361   gtk_style_unref(style);
02362 }
02363 
02364 
02365 
02366 
02367 
02368 
02369 
02370 
02371 
02372 
02373 
02374 
02375 
02376 
02377 
02378 
02379 
02380 
02381 
02383 
02384 NS_IMETHODIMP nsWidget::ResetInputState()
02385 {
02386   return NS_OK;
02387 }
02388 
02389 NS_IMETHODIMP nsWidget::SetIMEOpenState(PRBool aState) {
02390   return NS_ERROR_NOT_IMPLEMENTED;
02391 }
02392 
02393 NS_IMETHODIMP nsWidget::GetIMEOpenState(PRBool* aState) {
02394   return NS_ERROR_NOT_IMPLEMENTED;
02395 }
02396 
02397 NS_IMETHODIMP nsWidget::CancelIMEComposition() {
02398   return NS_ERROR_NOT_IMPLEMENTED;
02399 }
02400 
02401 /* virtual */
02402 GtkWindow *nsWidget::GetTopLevelWindow(void)
02403 {
02404   if (mWidget) 
02405     return GTK_WINDOW(gtk_widget_get_toplevel(mWidget));
02406   else
02407     return NULL;
02408 }
02409 
02410 void nsWidget::IMECommitEvent(GdkEventKey *aEvent) {
02411   NS_ASSERTION(0, "nsWidget::IMECommitEvent() shouldn't be called!\n");
02412 }
02413 
02414 void nsWidget::DispatchSetFocusEvent(void)
02415 {
02416   NS_ASSERTION(0, "nsWidget::DispatchSetFocusEvent shouldn't be called!\n");
02417 }
02418 void nsWidget::DispatchLostFocusEvent(void)
02419 {
02420   NS_ASSERTION(0, "nsWidget::DispatchLostFocusEvent shouldn't be called!\n");
02421 }
02422 void nsWidget::DispatchActivateEvent(void)
02423 {
02424   NS_ASSERTION(0, "nsWidget::DispatchActivateEvent shouldn't be called!\n");
02425 }
02426 void nsWidget::DispatchDeactivateEvent(void)
02427 {
02428   NS_ASSERTION(0, "nsWidget::DispatchDeactivateEvent shouldn't be called!\n");
02429 }