Back to index

lightning-sunbird  0.9+nobinonly
nsWidget.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; 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  *   Jerry.Kirk@Nexwarecorp.com
00024  *   Michael.Kedl@Nexwarecorp.com
00025  *   Dale.Stansberry@Nexwarecorop.com
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 
00042 #include "nsWidget.h"
00043 
00044 #include "nsIAppShell.h"
00045 #include "nsIComponentManager.h"
00046 #include "nsIDeviceContext.h"
00047 #include "nsIFontMetrics.h"
00048 #include "nsILookAndFeel.h"
00049 #include "nsToolkit.h"
00050 #include "nsWidgetsCID.h"
00051 #include "nsGfxCIID.h"
00052 #include <Pt.h>
00053 #include "PtRawDrawContainer.h"
00054 #include "nsIRollupListener.h"
00055 #include "nsIServiceManager.h"
00056 #include "nsWindow.h"
00057 #ifdef PHOTON_DND
00058 #include "nsDragService.h"
00059 #endif
00060 #include "nsIViewManager.h"
00061 #include "nsIScrollableView.h"
00062 #include "nsReadableUtils.h"
00063 
00064 #include "nsIPref.h"
00065 #include "nsClipboard.h"
00066 
00067 #include <errno.h>
00068 #include <photon/PtServer.h>
00069 
00070 extern char *__progname;
00071 
00072 static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
00073 static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
00074 
00075 // BGR, not RGB - REVISIT
00076 #define NSCOLOR_TO_PHCOLOR(g,n) \
00077   g.red=NS_GET_B(n); \
00078   g.green=NS_GET_G(n); \
00079   g.blue=NS_GET_R(n);
00080 
00082 //
00083 // Define and Initialize global variables
00084 //
00086 
00087 
00088 //
00089 // Keep track of the last widget being "dragged"
00090 //
00091 nsILookAndFeel     *nsWidget::sLookAndFeel = nsnull;
00092 #ifdef PHOTON_DND
00093 nsIDragService     *nsWidget::sDragService = nsnull;
00094 #endif
00095 nsClipboard        *nsWidget::sClipboard = nsnull;
00096 PRUint32            nsWidget::sWidgetCount = 0;
00097 nsWidget*                                        nsWidget::sFocusWidget = 0;
00098 
00099 nsWidget::nsWidget()
00100 {
00101   if (!sLookAndFeel) {
00102     CallGetService(kLookAndFeelCID, &sLookAndFeel);
00103   }
00104 
00105   if( sLookAndFeel )
00106     sLookAndFeel->GetColor( nsILookAndFeel::eColor_WindowBackground, mBackground );
00107 
00108 #ifdef PHOTON_DND
00109        if( !sDragService ) {
00110               nsresult rv;
00111               nsCOMPtr<nsIDragService> s;
00112               s = do_GetService( "@mozilla.org/widget/dragservice;1", &rv );
00113               sDragService = ( nsIDragService * ) s;
00114               if( NS_FAILED( rv ) ) sDragService = 0;
00115               }
00116 #endif
00117 
00118        if( !sClipboard ) {
00119               nsresult rv;
00120               nsCOMPtr<nsClipboard> s;
00121               s = do_GetService( kCClipboardCID, &rv );
00122               sClipboard = ( nsClipboard * ) s;
00123               if( NS_FAILED( rv ) ) sClipboard = 0;
00124               }
00125 
00126   mWidget = nsnull;
00127   mParent = nsnull;
00128   mPreferredWidth  = 0;
00129   mPreferredHeight = 0;
00130   mShown = PR_FALSE;
00131   mBounds.x = 0;
00132   mBounds.y = 0;
00133   mBounds.width = 0;
00134   mBounds.height = 0;
00135   mIsDestroying = PR_FALSE;
00136   mOnDestroyCalled = PR_FALSE;
00137   mIsToplevel = PR_FALSE;
00138   mListenForResizes = PR_FALSE;
00139   sWidgetCount++;
00140 }
00141 
00142 
00143 nsWidget::~nsWidget( ) {
00144 
00145        if( sFocusWidget == this ) sFocusWidget = 0;
00146 
00147   // it's safe to always call Destroy() because it will only allow itself to be called once
00148   Destroy();
00149 
00150   if( !sWidgetCount-- ) {
00151     NS_IF_RELEASE( sLookAndFeel );
00152        }
00153        }
00154 
00155 //-------------------------------------------------------------------------
00156 //
00157 // nsISupport stuff
00158 //
00159 //-------------------------------------------------------------------------
00160 NS_IMPL_ISUPPORTS_INHERITED1(nsWidget, nsBaseWidget, nsIKBStateControl)
00161 
00162 NS_METHOD nsWidget::WidgetToScreen( const nsRect& aOldRect, nsRect& aNewRect ) {
00163   if( mWidget ) {
00164     /* This is NOT correct */
00165     aNewRect.x = aOldRect.x;
00166     aNewRect.y = aOldRect.y;
00167        }
00168   return NS_OK;
00169        }
00170 
00171 // nsWidget::ScreenToWidget - Not Implemented
00172 NS_METHOD nsWidget::ScreenToWidget( const nsRect& aOldRect, nsRect& aNewRect ) {
00173   return NS_OK;
00174        }
00175 
00176 //-------------------------------------------------------------------------
00177 //
00178 // Close this nsWidget
00179 //
00180 //-------------------------------------------------------------------------
00181 
00182 NS_IMETHODIMP nsWidget::Destroy( void ) {
00183 
00184  // make sure we don't call this more than once.
00185   if( mIsDestroying ) return NS_OK;
00186 
00187   // ok, set our state
00188   mIsDestroying = PR_TRUE;
00189 
00190   // call in and clean up any of our base widget resources
00191   // are released
00192   nsBaseWidget::Destroy();
00193 
00194   // destroy our native windows
00195   DestroyNative();
00196 
00197   // make sure to call the OnDestroy if it hasn't been called yet
00198   if( mOnDestroyCalled == PR_FALSE ) OnDestroy();
00199 
00200   // make sure no callbacks happen
00201   mEventCallback = nsnull;
00202 
00203   return NS_OK;
00204        }
00205 
00206 // this is the function that will destroy the native windows for this widget.
00207 
00208 /* virtual */
00209 void nsWidget::DestroyNative( void ) {
00210   if( mWidget ) {
00211     // prevent the widget from causing additional events
00212     mEventCallback = nsnull;
00213          //EnableDamage( mWidget, PR_FALSE );
00214          PtDestroyWidget( mWidget );
00215          //EnableDamage( mWidget, PR_TRUE );
00216     mWidget = nsnull;
00217        }
00218        }
00219 
00220 // make sure that we clean up here
00221 
00222 void nsWidget::OnDestroy( ) {
00223   mOnDestroyCalled = PR_TRUE;
00224   // release references to children, device context, toolkit + app shell
00225   nsBaseWidget::OnDestroy();
00226   DispatchStandardEvent(NS_DESTROY);
00227        }
00228 
00230 //
00231 // nsIKBStateControl Mehthods
00232 //
00234 
00235 NS_IMETHODIMP nsWidget::ResetInputState( ) {
00236   return NS_OK;
00237        }
00238 
00239 NS_IMETHODIMP nsWidget::SetIMEOpenState(PRBool aState) {
00240   return NS_ERROR_NOT_IMPLEMENTED;
00241        }
00242 
00243 NS_IMETHODIMP nsWidget::GetIMEOpenState(PRBool* aState) {
00244   return NS_ERROR_NOT_IMPLEMENTED;
00245        }
00246 
00247 NS_IMETHODIMP nsWidget::CancelIMEComposition() {
00248   return NS_ERROR_NOT_IMPLEMENTED;
00249        }
00250 
00251 //-------------------------------------------------------------------------
00252 //
00253 // Hide or show this component
00254 //
00255 //-------------------------------------------------------------------------
00256 
00257 NS_METHOD nsWidget::Show( PRBool bState ) {
00258 
00259   if( !mWidget ) return NS_OK; // Will be null durring printing
00260 
00261   PtArg_t   arg;
00262 
00263   if( bState ) {
00264 
00265               if( mWindowType != eWindowType_child ) {
00266 
00267                 if (PtWidgetIsRealized(mWidget)) {
00268                        mShown = PR_TRUE; 
00269                        return NS_OK;
00270                      }
00271 
00272                 //EnableDamage( mWidget, PR_FALSE );
00273                 PtRealizeWidget(mWidget);
00274 
00275                 if( mWidget->rid == -1 ) {
00276                        //EnableDamage( mWidget, PR_TRUE );
00277                        NS_ASSERTION(0,"nsWidget::Show mWidget's rid == -1\n");
00278                        mShown = PR_FALSE; 
00279                        return NS_ERROR_FAILURE;
00280                      }
00281 
00282                 PtSetArg(&arg, Pt_ARG_FLAGS, 0, Pt_DELAY_REALIZE);
00283                 PtSetResources(mWidget, 1, &arg);
00284                 //EnableDamage( mWidget, PR_TRUE );
00285                 PtDamageWidget(mWidget);
00286 #ifdef Ph_REGION_NOTIFY                   
00287                 PhRegion_t region;
00288                 PtWidget_t *mWgt;
00289                 mWgt = (PtWidget_t*) GetNativeData( NS_NATIVE_WIDGET );
00290                 region.flags = Ph_REGION_NOTIFY | Ph_FORCE_BOUNDARY;
00291                 region.rid = PtWidgetRid(mWgt);
00292                 PhRegionChange(Ph_REGION_FLAGS, 0, &region, NULL, NULL);
00293 #endif
00294               }
00295               else {
00296                      PtWidgetToFront( mWidget );
00297                      if( !mShown || !( mWidget->flags & Pt_REALIZED ) ) PtRealizeWidget( mWidget );
00298                      }
00299        }
00300   else {
00301               if( mWindowType != eWindowType_child ) {
00302       //EnableDamage( mWidget, PR_FALSE );
00303       PtUnrealizeWidget(mWidget);
00304 
00305       //EnableDamage( mWidget, PR_TRUE );
00306 
00307       PtSetArg(&arg, Pt_ARG_FLAGS, Pt_DELAY_REALIZE, Pt_DELAY_REALIZE);
00308       PtSetResources(mWidget, 1, &arg);
00309                      }
00310               else {
00311                      //EnableDamage( mWidget, PR_FALSE );
00312                      PtWidgetToBack( mWidget );
00313                      if( mShown ) PtUnrealizeWidget( mWidget );
00314                      //EnableDamage( mWidget, PR_TRUE );
00315                      }
00316        }
00317 
00318   mShown = bState;
00319   return NS_OK;
00320        }
00321 
00322 
00323 // nsWidget::SetModal - Not Implemented
00324 NS_IMETHODIMP nsWidget::SetModal( PRBool aModal ) {
00325   return NS_ERROR_FAILURE;
00326        }
00327 
00328 //-------------------------------------------------------------------------
00329 //
00330 // Move this component
00331 //
00332 //-------------------------------------------------------------------------
00333 NS_METHOD nsWidget::Move( PRInt32 aX, PRInt32 aY ) {
00334 
00335        if( ( mBounds.x == aX ) && ( mBounds.y == aY ) ) return NS_OK; 
00336 
00337        mBounds.x = aX;
00338        mBounds.y = aY;
00339        
00340        if( mWidget ) {
00341               if(( mWidget->area.pos.x != aX ) || ( mWidget->area.pos.y != aY )) {
00342                      PhPoint_t pos = { aX, aY };
00343                      PtSetResource( mWidget, Pt_ARG_POS, &pos, 0 );
00344               }
00345        }
00346   return NS_OK;
00347 }
00348 
00349 
00350 NS_METHOD nsWidget::Resize( PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint ) {
00351 
00352        if( ( mBounds.width == aWidth ) && ( mBounds.height == aHeight ) ) 
00353           return NS_OK;
00354 
00355   mBounds.width  = aWidth;
00356   mBounds.height = aHeight;
00357 
00358   if( mWidget ) {
00359               PhDim_t dim = { aWidth, aHeight };
00360               //EnableDamage( mWidget, PR_FALSE );
00361               PtSetResource( mWidget, Pt_ARG_DIM, &dim, 0 );
00362               //EnableDamage( mWidget, PR_TRUE );
00363               }
00364 
00365        return NS_OK;
00366 }
00367 
00368 
00369 //-------------------------------------------------------------------------
00370 //
00371 // Send a resize message to the listener
00372 //
00373 //-------------------------------------------------------------------------
00374 PRBool nsWidget::OnResize( nsRect &aRect ) {
00375 
00376   PRBool result = PR_FALSE;
00377 
00378   // call the event callback
00379   if( mEventCallback ) {
00380               nsSizeEvent event(PR_TRUE, 0, nsnull);
00381 
00382          InitEvent(event, NS_SIZE);
00383 
00384               nsRect *foo = new nsRect(0, 0, aRect.width, aRect.height);
00385               event.windowSize = foo;
00386 
00387               event.point.x = 0;
00388               event.point.y = 0;
00389               event.mWinWidth = aRect.width;
00390               event.mWinHeight = aRect.height;
00391   
00392               NS_ADDREF_THIS();
00393               result = DispatchWindowEvent(&event);
00394               NS_RELEASE_THIS();
00395               delete foo;
00396               }
00397 
00398        return result;
00399        }
00400 
00401 //------
00402 // Move
00403 //------
00404 PRBool nsWidget::OnMove( PRInt32 aX, PRInt32 aY ) {
00405   nsGUIEvent event(PR_TRUE, 0, nsnull);
00406   InitEvent(event, NS_MOVE);
00407   event.point.x = aX;
00408   event.point.y = aY;
00409   return DispatchWindowEvent(&event);
00410        }
00411 
00412 
00413 //-------------------------------------------------------------------------
00414 //
00415 // Set this component font
00416 //
00417 //-------------------------------------------------------------------------
00418 NS_METHOD nsWidget::SetFont( const nsFont &aFont ) {
00419 
00420   nsIFontMetrics* mFontMetrics;
00421   mContext->GetMetricsFor(aFont, mFontMetrics);
00422 
00423        if( mFontMetrics ) {
00424               PtArg_t arg;
00425 
00426               nsFontHandle aFontHandle;
00427               mFontMetrics->GetFontHandle(aFontHandle);
00428               nsString *aString;
00429               aString = (nsString *) aFontHandle;
00430               char *str = ToNewCString(*aString);
00431 
00432               PtSetArg( &arg, Pt_ARG_TEXT_FONT, str, 0 );
00433               PtSetResources( mWidget, 1, &arg );
00434 
00435               delete [] str;
00436               NS_RELEASE(mFontMetrics);
00437               }
00438        return NS_OK;
00439        }
00440 
00441 //-------------------------------------------------------------------------
00442 //
00443 // Set this component cursor
00444 //
00445 //-------------------------------------------------------------------------
00446 NS_METHOD nsWidget::SetCursor( nsCursor aCursor ) {
00447 
00448   // Only change cursor if it's changing
00449   if( aCursor != mCursor ) {
00450 
00451        unsigned short curs = Ph_CURSOR_POINTER;
00452        PgColor_t color = Ph_CURSOR_DEFAULT_COLOR;
00453 
00454        switch( aCursor ) {
00455               case eCursor_nw_resize:
00456                      curs = Ph_CURSOR_DRAG_TL;
00457                      break;
00458               case eCursor_se_resize:
00459                      curs = Ph_CURSOR_DRAG_BR;
00460                      break;
00461               case eCursor_ne_resize:
00462                      curs = Ph_CURSOR_DRAG_TL;
00463                      break;
00464               case eCursor_sw_resize:
00465                      curs = Ph_CURSOR_DRAG_BL;
00466                      break;
00467 
00468               case eCursor_crosshair:
00469                      curs = Ph_CURSOR_CROSSHAIR;
00470                      break;
00471 
00472               case eCursor_copy:
00473               case eCursor_alias:
00474               case eCursor_context_menu:
00475                      // XXX: No suitable cursor, needs implementing
00476                      break;
00477 
00478               case eCursor_cell:
00479                      // XXX: No suitable cursor, needs implementing
00480                      break;
00481 
00482               case eCursor_spinning:
00483                      // XXX: No suitable cursor, needs implementing
00484                      break;
00485 
00486               case eCursor_move:
00487                 curs = Ph_CURSOR_MOVE;
00488                 break;
00489          
00490               case eCursor_help:
00491                 curs = Ph_CURSOR_QUESTION_POINT;
00492                 break;
00493          
00494               case eCursor_grab:
00495               case eCursor_grabbing:
00496                 curs = Ph_CURSOR_FINGER;
00497                 break;
00498          
00499               case eCursor_select:
00500                 curs = Ph_CURSOR_INSERT;
00501                 color = Pg_BLACK;
00502                 break;
00503          
00504               case eCursor_wait:
00505                 curs = Ph_CURSOR_LONG_WAIT;
00506                 break;
00507 
00508               case eCursor_hyperlink:
00509                 curs = Ph_CURSOR_FINGER;
00510                 break;
00511 
00512               case eCursor_standard:
00513                 curs = Ph_CURSOR_POINTER;
00514                 break;
00515 
00516               case eCursor_n_resize:
00517               case eCursor_s_resize:
00518                 curs = Ph_CURSOR_DRAG_VERTICAL;
00519                 break;
00520 
00521               case eCursor_w_resize:
00522               case eCursor_e_resize:
00523                 curs = Ph_CURSOR_DRAG_HORIZONTAL;
00524                 break;
00525 
00526               case eCursor_zoom_in:
00527               case eCursor_zoom_out:
00528                 // XXX: No suitable cursor, needs implementing
00529                 break;
00530 
00531               case eCursor_not_allowed:
00532               case eCursor_no_drop:
00533                 curs = Ph_CURSOR_DONT;
00534                 break;
00535 
00536               case eCursor_col_resize:
00537                 // XXX: not 100% appropriate perhaps
00538                 curs = Ph_CURSOR_DRAG_HORIZONTAL;
00539                 break;
00540 
00541               case eCursor_row_resize:
00542                 // XXX: not 100% appropriate perhaps
00543                 curs = Ph_CURSOR_DRAG_VERTICAL;
00544                 break;
00545 
00546               case eCursor_vertical_text:
00547                 curs = Ph_CURSOR_INSERT;
00548                 color = Pg_BLACK;
00549                 break;
00550 
00551               case eCursor_all_scroll:
00552                 // XXX: No suitable cursor, needs implementing
00553                 break;
00554 
00555               case eCursor_nesw_resize:
00556                 curs = Ph_CURSOR_DRAG_FOREDIAG;
00557                 break;
00558 
00559               case eCursor_nwse_resize:
00560                 curs = Ph_CURSOR_DRAG_BACKDIAG;
00561                 break;
00562 
00563               case eCursor_ns_resize:
00564                 curs = Ph_CURSOR_DRAG_VERTICAL;
00565                 break;
00566 
00567               case eCursor_ew_resize:
00568                 curs = Ph_CURSOR_DRAG_HORIZONTAL;
00569                 break;
00570 
00571               default:
00572                 NS_ASSERTION(0, "Invalid cursor type");
00573                 break;
00574               }
00575 
00576        if( mWidget ) {
00577          PtArg_t args[2];
00578 
00579                      PtSetArg( &args[0], Pt_ARG_CURSOR_TYPE, curs, 0 );
00580                      PtSetArg( &args[1], Pt_ARG_CURSOR_COLOR, color, 0 );
00581                      PtSetResources( mWidget, 2, args );
00582               }
00583               mCursor = aCursor;
00584               }
00585 
00586        return NS_OK;
00587        }
00588 
00589 
00590 NS_METHOD nsWidget::Invalidate( PRBool aIsSynchronous ) {
00591 
00592        // mWidget will be null during printing
00593        if( !mWidget || !PtWidgetIsRealized( mWidget ) ) return NS_OK;
00594 
00595        PtWidget_t *aWidget = (PtWidget_t *)GetNativeData(NS_NATIVE_WIDGET);
00596        PtDamageWidget( aWidget );
00597        if( aIsSynchronous ) PtFlush();
00598        return NS_OK;
00599        }
00600 
00601 NS_METHOD nsWidget::Invalidate( const nsRect & aRect, PRBool aIsSynchronous ) {
00602 
00603   if( !mWidget ) return NS_OK; // mWidget will be null during printing
00604   if( !PtWidgetIsRealized( mWidget ) ) return NS_OK;
00605 
00606        PhRect_t prect;
00607        prect.ul.x = aRect.x;
00608        prect.ul.y = aRect.y;
00609        prect.lr.x = prect.ul.x + aRect.width - 1;
00610        prect.lr.y = prect.ul.y + aRect.height - 1;
00611        if( ! ( mWidget->class_rec->flags & Pt_DISJOINT ) )
00612               PhTranslateRect( &prect, &mWidget->area.pos );
00613        PtDamageExtent( mWidget, &prect );
00614        if( aIsSynchronous ) PtFlush( );
00615        return NS_OK;
00616        }
00617 
00618 NS_IMETHODIMP nsWidget::InvalidateRegion( const nsIRegion *aRegion, PRBool aIsSynchronous ) {
00619        PhTile_t *tiles = NULL;
00620        aRegion->GetNativeRegion( ( void*& ) tiles );
00621        if( tiles ) {
00622               PhTranslateTiles( tiles, &mWidget->area.pos );
00623               PtDamageTiles( mWidget, tiles );
00624               if( aIsSynchronous ) PtFlush( );
00625               }
00626   return NS_OK;
00627        }
00628 
00629 nsresult nsWidget::CreateWidget(nsIWidget *aParent,
00630                                 const nsRect &aRect,
00631                                 EVENT_CALLBACK aHandleEventFunction,
00632                                 nsIDeviceContext *aContext,
00633                                 nsIAppShell *aAppShell,
00634                                 nsIToolkit *aToolkit,
00635                                 nsWidgetInitData *aInitData,
00636                                 nsNativeWidget aNativeParent)
00637 {
00638 
00639   PtWidget_t *parentWidget = nsnull;
00640 
00641 
00642 
00643   if( aNativeParent ) {
00644     parentWidget = (PtWidget_t*)aNativeParent;
00645     // we've got a native parent so listen for resizes
00646     mListenForResizes = PR_TRUE;
00647        }
00648   else if( aParent ) {
00649     parentWidget = (PtWidget_t*) (aParent->GetNativeData(NS_NATIVE_WIDGET));
00650               mListenForResizes = aInitData ? aInitData->mListenForResizes : PR_FALSE;
00651        }
00652 
00653        if( aInitData->mWindowType == eWindowType_child && !parentWidget ) return NS_ERROR_FAILURE;
00654 
00655   nsIWidget *baseParent = aInitData &&
00656                             (aInitData->mWindowType == eWindowType_dialog ||
00657                              aInitData->mWindowType == eWindowType_toplevel ||
00658                              aInitData->mWindowType == eWindowType_invisible) ?
00659                           nsnull : aParent;
00660 
00661   BaseCreate( baseParent, aRect, aHandleEventFunction, aContext, aAppShell, aToolkit, aInitData );
00662 
00663   mParent = aParent;
00664   mBounds = aRect;
00665 
00666   CreateNative (parentWidget);
00667 
00668        if( aRect.width > 1 && aRect.height > 1 ) Resize(aRect.width, aRect.height, PR_FALSE);
00669 
00670   if( mWidget ) {
00671     SetInstance(mWidget, this);
00672     PtAddCallback( mWidget, Pt_CB_GOT_FOCUS, GotFocusCallback, this );
00673     PtAddCallback( mWidget, Pt_CB_LOST_FOCUS, LostFocusCallback, this );
00674     PtAddCallback( mWidget, Pt_CB_IS_DESTROYED, DestroyedCallback, this );
00675 #ifdef PHOTON_DND
00676     PtAddCallback( mWidget, Pt_CB_DND, DndCallback, this );
00677 #endif
00678        }
00679 
00680   DispatchStandardEvent(NS_CREATE);
00681 
00682   return NS_OK;
00683        }
00684 
00685 
00686 //-------------------------------------------------------------------------
00687 //
00688 // Invokes callback and ProcessEvent method on Event Listener object
00689 //
00690 //-------------------------------------------------------------------------
00691 
00692 NS_IMETHODIMP nsWidget::DispatchEvent( nsGUIEvent *aEvent, nsEventStatus &aStatus ) {
00693 
00694   NS_ADDREF(aEvent->widget);
00695 
00696   if( nsnull != mMenuListener ) {
00697     if( NS_MENU_EVENT == aEvent->eventStructType )
00698       aStatus = mMenuListener->MenuSelected(NS_STATIC_CAST(nsMenuEvent&, *aEvent));
00699        }
00700 
00701   aStatus = nsEventStatus_eIgnore;
00702 
00704 
00705   if( nsnull != mEventCallback ) aStatus = (*mEventCallback)(aEvent);
00706 
00707   // Dispatch to event listener if event was not consumed
00708   if( (aStatus != nsEventStatus_eIgnore) && (nsnull != mEventListener) )
00709     aStatus = mEventListener->ProcessEvent(*aEvent);
00710 
00711    NS_IF_RELEASE(aEvent->widget);
00712 
00713   return NS_OK;
00714        }
00715 
00716 //==============================================================
00717 void nsWidget::InitMouseEvent(PhPointerEvent_t *aPhButtonEvent,
00718                               nsWidget * aWidget,
00719                               nsMouseEvent &anEvent,
00720                               PRUint32   aEventType)
00721 {
00722   anEvent.message = aEventType;
00723   anEvent.widget  = aWidget;
00724 
00725   if (aPhButtonEvent != nsnull) {
00726     anEvent.time =      PR_IntervalNow();
00727     anEvent.isShift =   ( aPhButtonEvent->key_mods & Pk_KM_Shift ) ? PR_TRUE : PR_FALSE;
00728     anEvent.isControl = ( aPhButtonEvent->key_mods & Pk_KM_Ctrl )  ? PR_TRUE : PR_FALSE;
00729     anEvent.isAlt =     ( aPhButtonEvent->key_mods & Pk_KM_Alt )   ? PR_TRUE : PR_FALSE;
00730               anEvent.isMeta =            PR_FALSE;
00731     anEvent.point.x =   aPhButtonEvent->pos.x; 
00732     anEvent.point.y =   aPhButtonEvent->pos.y;
00733     anEvent.clickCount = aPhButtonEvent->click_count;
00734        }
00735        }
00736 
00737 //-------------------------------------------------------------------------
00738 //
00739 // Deal with all sort of mouse event
00740 //
00741 //-------------------------------------------------------------------------
00742 PRBool nsWidget::DispatchMouseEvent( nsMouseEvent& aEvent ) {
00743 
00744   PRBool result = PR_FALSE;
00745   if (nsnull == mEventCallback && nsnull == mMouseListener) return result;
00746 
00747   //printf("* DispatchMouseEvent %d\n", aEvent.message);
00748   // call the event callback
00749   if (nsnull != mEventCallback) {
00750     result = DispatchWindowEvent(&aEvent);
00751     return result;
00752        }
00753 
00754   if (nsnull != mMouseListener) {
00755 
00756     switch (aEvent.message) {
00757       case NS_MOUSE_LEFT_BUTTON_DOWN:
00758       case NS_MOUSE_MIDDLE_BUTTON_DOWN:
00759       case NS_MOUSE_RIGHT_BUTTON_DOWN:
00760         result = ConvertStatus(mMouseListener->MousePressed(aEvent));
00761         break;
00762 
00763       case NS_MOUSE_LEFT_BUTTON_UP:
00764       case NS_MOUSE_MIDDLE_BUTTON_UP:
00765       case NS_MOUSE_RIGHT_BUTTON_UP:
00766         result = ConvertStatus(mMouseListener->MouseReleased(aEvent));
00767         result = ConvertStatus(mMouseListener->MouseClicked(aEvent));
00768         break;
00769 
00770        case NS_DRAGDROP_DROP:
00771          break;
00772 
00773                      case NS_MOUSE_MOVE:
00774               break;
00775 
00776        default:
00777          break;
00778 
00779        } // switch
00780        }
00781   return result;
00782        }
00783 
00784 struct nsKeyConverter {
00785   PRUint32       vkCode; // Platform independent key code
00786   unsigned long  keysym; // Photon key_sym key code
00787 };
00788 
00789 static struct nsKeyConverter nsKeycodes[] = {
00790   { NS_VK_PAGE_UP,    Pk_Pg_Up },
00791   { NS_VK_PAGE_DOWN,  Pk_Pg_Down },
00792   { NS_VK_UP,         Pk_Up },
00793   { NS_VK_DOWN,       Pk_Down },
00794   { NS_VK_TAB,        Pk_Tab },
00795   { NS_VK_TAB,        Pk_KP_Tab },
00796   { NS_VK_HOME,       Pk_Home },
00797   { NS_VK_END,        Pk_End },
00798   { NS_VK_LEFT,       Pk_Left },
00799   { NS_VK_RIGHT,      Pk_Right },
00800   { NS_VK_DELETE,     Pk_Delete },
00801   { NS_VK_CANCEL,     Pk_Cancel },
00802   { NS_VK_BACK,       Pk_BackSpace },
00803   { NS_VK_CLEAR,      Pk_Clear },
00804   { NS_VK_RETURN,     Pk_Return },
00805   { NS_VK_SHIFT,      Pk_Shift_L },
00806   { NS_VK_SHIFT,      Pk_Shift_R },
00807   { NS_VK_CONTROL,    Pk_Control_L },
00808   { NS_VK_CONTROL,    Pk_Control_R },
00809   { NS_VK_ALT,        Pk_Alt_L },
00810   { NS_VK_ALT,        Pk_Alt_R },
00811   { NS_VK_INSERT,     Pk_Insert },
00812   { NS_VK_PAUSE,      Pk_Pause },
00813   { NS_VK_CAPS_LOCK,  Pk_Caps_Lock },
00814   { NS_VK_ESCAPE,     Pk_Escape },
00815   { NS_VK_PRINTSCREEN,Pk_Print },
00816   { NS_VK_RETURN,     Pk_KP_Enter },
00817   { NS_VK_INSERT,     Pk_KP_0 },
00818   { NS_VK_END,        Pk_KP_1 },
00819   { NS_VK_DOWN,       Pk_KP_2 },
00820   { NS_VK_PAGE_DOWN,  Pk_KP_3 },
00821   { NS_VK_LEFT,       Pk_KP_4 },
00822   { NS_VK_NUMPAD5,    Pk_KP_5 },
00823   { NS_VK_RIGHT,      Pk_KP_6 },
00824   { NS_VK_HOME,       Pk_KP_7 },
00825   { NS_VK_UP,         Pk_KP_8 },
00826   { NS_VK_PAGE_UP,    Pk_KP_9 },
00827   { NS_VK_COMMA,      Pk_KP_Separator }
00828   };
00829 
00830 
00831 // Input keysym is in photon format; output is in NS_VK format
00832 PRUint32 nsWidget::nsConvertKey( PhKeyEvent_t *aPhKeyEvent ) {
00833 
00834        unsigned long keysym, keymods;
00835 
00836   const int length = sizeof(nsKeycodes) / sizeof(struct nsKeyConverter);
00837 
00838        keymods = aPhKeyEvent->key_mods;
00839        if( aPhKeyEvent->key_flags & Pk_KF_Sym_Valid )
00840               keysym = aPhKeyEvent->key_sym;
00841        else if( aPhKeyEvent->key_flags & Pk_KF_Cap_Valid )
00842               keysym = aPhKeyEvent->key_cap;
00843        else return 0;
00844        
00845   // First, try to handle alphanumeric input, not listed in nsKeycodes:
00846   if (keysym >= Pk_a && keysym <= Pk_z)
00847      return keysym - Pk_a + NS_VK_A;
00848 
00849   if (keysym >= Pk_A && keysym <= Pk_Z)
00850      return keysym - Pk_A + NS_VK_A;
00851 
00852   if (keysym >= Pk_0 && keysym <= Pk_9)
00853      return keysym - Pk_0 + NS_VK_0;
00854                 
00855   if (keysym >= Pk_F1 && keysym <= Pk_F24) {
00856      return keysym - Pk_F1 + NS_VK_F1;
00857        }
00858 
00859        if( keymods & Pk_KM_Num_Lock ) {
00860        if( keysym >= Pk_KP_0 && keysym <= Pk_KP_9 )
00861        return keysym - Pk_0 + NS_VK_0;
00862               }
00863 
00864   for (int i = 0; i < length; i++) {
00865     if( nsKeycodes[i].keysym == keysym ) {
00866       return (nsKeycodes[i].vkCode);
00867        }
00868        }
00869 
00870   return((int) 0);
00871        }
00872 
00873 PRBool  nsWidget::DispatchKeyEvent( PhKeyEvent_t *aPhKeyEvent, int force ) {
00874   NS_ASSERTION(aPhKeyEvent, "nsWidget::DispatchKeyEvent a NULL PhKeyEvent was passed in");
00875 
00876   if( !(aPhKeyEvent->key_flags & (Pk_KF_Cap_Valid|Pk_KF_Sym_Valid) ) ) {
00877               //printf("nsWidget::DispatchKeyEvent throwing away invalid key: Modifiers Valid=<%d,%d,%d> this=<%p>\n",
00878               //(aPhKeyEvent->key_flags & Pk_KF_Scan_Valid), (aPhKeyEvent->key_flags & Pk_KF_Sym_Valid), (aPhKeyEvent->key_flags & Pk_KF_Cap_Valid), this );
00879               return PR_FALSE;
00880               }
00881 
00882   if ( !force && PtIsFocused(mWidget) != 2) {
00883      //printf("nsWidget::DispatchKeyEvent Not on focus leaf! PtIsFocused(mWidget)=<%d>\n", PtIsFocused(mWidget));
00884      return PR_FALSE;
00885        }
00886   
00887   if ( ( aPhKeyEvent->key_cap == Pk_Shift_L )
00888        || ( aPhKeyEvent->key_cap == Pk_Shift_R )
00889        || ( aPhKeyEvent->key_cap == Pk_Control_L )
00890        || ( aPhKeyEvent->key_cap ==  Pk_Control_R )
00891        || ( aPhKeyEvent->key_cap ==  Pk_Num_Lock )
00892        || ( aPhKeyEvent->key_cap ==  Pk_Scroll_Lock )
00893      )
00894     return PR_TRUE;
00895 
00896   nsWindow *w = (nsWindow *) this;
00897 
00898   w->AddRef();
00899  
00900   if (aPhKeyEvent->key_flags & Pk_KF_Key_Down) {
00901               nsKeyEvent keyDownEvent(PR_TRUE, NS_KEY_DOWN, w);
00902               InitKeyEvent(aPhKeyEvent, keyDownEvent);
00903               PRBool noDefault = w->OnKey(keyDownEvent);
00904 
00905               nsKeyEvent keyPressEvent(PR_TRUE, NS_KEY_PRESS, w);
00906               InitKeyPressEvent(aPhKeyEvent, keyPressEvent);
00907               if (noDefault) {  // If prevent default set for keydown, do same for keypress
00908                      keyPressEvent.flags = NS_EVENT_FLAG_NO_DEFAULT;
00909               }
00910               w->OnKey(keyPressEvent);
00911        }
00912   else if (aPhKeyEvent->key_flags & Pk_KF_Key_Repeat) {
00913               nsKeyEvent keyPressEvent(PR_TRUE, NS_KEY_PRESS, w);
00914               InitKeyPressEvent(aPhKeyEvent, keyPressEvent);
00915               w->OnKey(keyPressEvent);
00916        }
00917   else if (PkIsKeyDown(aPhKeyEvent->key_flags) == 0) {
00918               nsKeyEvent kevent(PR_TRUE, NS_KEY_UP, w);
00919               InitKeyEvent(aPhKeyEvent, kevent);
00920               w->OnKey(kevent);
00921        }
00922 
00923   w->Release();
00924 
00925   return PR_TRUE;
00926        }
00927 
00928 inline void nsWidget::InitKeyEvent(PhKeyEvent_t *aPhKeyEvent, nsKeyEvent &anEvent )
00929 {
00930        anEvent.keyCode =    nsConvertKey( aPhKeyEvent );
00931        anEvent.time =                     PR_IntervalNow();
00932        anEvent.isShift =   ( aPhKeyEvent->key_mods & Pk_KM_Shift ) ? PR_TRUE : PR_FALSE;
00933        anEvent.isControl = ( aPhKeyEvent->key_mods & Pk_KM_Ctrl )  ? PR_TRUE : PR_FALSE;
00934        anEvent.isAlt =     ( aPhKeyEvent->key_mods & Pk_KM_Alt )   ? PR_TRUE : PR_FALSE;
00935        anEvent.isMeta =    PR_FALSE;
00936 }
00937 
00938 /* similar to PhKeyToMb */
00939 inline int key_sym_displayable(const PhKeyEvent_t *kevent)
00940 {
00941   if(kevent->key_flags & Pk_KF_Sym_Valid) {
00942     unsigned long const sym = kevent->key_sym;
00943     if  ( sym >= 0xF000
00944       ? sym >= 0xF100 && ( sizeof(wchar_t) > 2 || sym < 0x10000 )
00945       : ( sym & ~0x9F ) != 0 // exclude 0...0x1F and 0x80...0x9F
00946         ) return 1;
00947   }
00948   return 0;
00949 }
00950 
00951 /* similar to PhKeyToMb */
00952 inline int key_cap_displayable(const PhKeyEvent_t *kevent)
00953 {
00954   if(kevent->key_flags & Pk_KF_Cap_Valid) {
00955     unsigned long const cap = kevent->key_cap;
00956     if  ( cap >= 0xF000
00957       ? cap >= 0xF100 && ( sizeof(wchar_t) > 2 || cap < 0x10000 )
00958       : ( cap & ~0x9F ) != 0 // exclude 0...0x1F and 0x80...0x9F
00959         ) return 1;
00960   }
00961   return 0;
00962 }
00963 
00964 inline void nsWidget::InitKeyPressEvent(PhKeyEvent_t *aPhKeyEvent, nsKeyEvent &anEvent )
00965 {
00966        anEvent.isShift =   ( aPhKeyEvent->key_mods & Pk_KM_Shift ) ? PR_TRUE : PR_FALSE;
00967        anEvent.isControl = ( aPhKeyEvent->key_mods & Pk_KM_Ctrl )  ? PR_TRUE : PR_FALSE;
00968        anEvent.isAlt =     ( aPhKeyEvent->key_mods & Pk_KM_Alt )   ? PR_TRUE : PR_FALSE;
00969        anEvent.isMeta =    PR_FALSE;
00970 
00971        if( key_sym_displayable( aPhKeyEvent ) ) anEvent.charCode = aPhKeyEvent->key_sym;
00972        else {
00973               /* in photon Ctrl<something> or Alt<something> is not a displayable character, but
00974                      mozilla wants the keypress event as a charCode+isControl+isAlt, instead of a keyCode */
00975               if( ( anEvent.isControl || anEvent.isAlt ) && key_cap_displayable( aPhKeyEvent ) )
00976                      anEvent.charCode = aPhKeyEvent->key_cap;
00977               else anEvent.keyCode = nsConvertKey( aPhKeyEvent );
00978               }
00979 
00980        anEvent.time =                     PR_IntervalNow();
00981 }
00982 
00983 // used only once
00984 inline PRBool nsWidget::HandleEvent( PtWidget_t *widget, PtCallbackInfo_t* aCbInfo ) {
00985   PRBool  result = PR_TRUE; // call the default nsWindow proc
00986   PhEvent_t* event = aCbInfo->event;
00987   static int prevx=-1, prevy=-1, left_button_down, kwww_outbound_valid;
00988 
00989        if (event->processing_flags & Ph_CONSUMED) return PR_TRUE;
00990 
00991        switch ( event->type ) {
00992 
00993       case Ph_EV_PTR_MOTION_NOBUTTON:
00994               {
00995               PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event );
00996               nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal);
00997 
00998         if( ptrev ) {
00999 
01000                                    if( ptrev->flags & Ph_PTR_FLAG_Z_ONLY ) break; // sometimes z presses come out of nowhere */
01001 
01003 
01004               ScreenToWidgetPos( ptrev->pos );
01005               InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MOVE );
01006               result = DispatchMouseEvent(theMouseEvent);
01007               }
01008               }
01009               break;
01010 
01011       case Ph_EV_BUT_PRESS:
01012        {
01013 
01014               PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event );
01015                 nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal);
01016 
01017                             /* there should be no reason to do this - mozilla should figure out how to call SetFocus */
01018                             /* this though fixes the problem with the plugins capturing the focus */
01019                             PtWidget_t *disjoint = PtFindDisjoint( widget );
01020                             if( PtWidgetIsClassMember( disjoint, PtServer ) || //mozserver
01021                                    PtWidgetIsClassMember( disjoint, PtContainer ) ) //TestPhEmbed
01022                                    PtContainerGiveFocus( widget, aCbInfo->event );
01023 
01024         if( ptrev ) {
01025                 prevx = ptrev->pos.x;
01026                 prevy = ptrev->pos.y;
01027           ScreenToWidgetPos( ptrev->pos );
01028 
01029           if( ptrev->buttons & Ph_BUTTON_SELECT ) { // Normally the left mouse button
01030                      InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_DOWN );
01031                      left_button_down = 1;
01032           } else if( ptrev->buttons & Ph_BUTTON_MENU ) // the right button
01033                      InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_RIGHT_BUTTON_DOWN );
01034           else // middle button
01035                      InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MIDDLE_BUTTON_DOWN );
01036 
01037                 //printf("*** Button down\n");
01038                 result = DispatchMouseEvent(theMouseEvent);
01039 
01040                                    // if we're a right-button-down we're trying to popup a context menu. send that event to gecko also
01041                                    if( ptrev->buttons & Ph_BUTTON_MENU ) {
01042                                           nsMouseEvent contextMenuEvent(PR_TRUE, 0, nsnull,
01043                                                       nsMouseEvent::eReal);
01044                                           InitMouseEvent( ptrev, this, contextMenuEvent, NS_CONTEXTMENU );
01045                                           result = DispatchMouseEvent( contextMenuEvent );
01046                                           }
01047          }
01048 
01049         }
01050               break;        
01051               
01052               case Ph_EV_BUT_RELEASE:
01053                 {
01054                        PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event );
01055                        nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull,
01056                                          nsMouseEvent::eReal);
01057                        
01058                        // Update the current input group for clipboard mouse events
01059                        // (mozilla only). Note that for mozserver the mouse based
01060                        // (eg. Edit->Copy/Paste menu) events don't come through here.
01061                        // They are sent by the voyager client app via libPtWeb.so to
01062                        // do_command() in mozserver.cpp.
01063                        if (sClipboard)
01064                             sClipboard->SetInputGroup(event->input_group);
01065 
01066                        if (event->subtype==Ph_EV_RELEASE_REAL || event->subtype==Ph_EV_RELEASE_PHANTOM) {
01067                               if (ptrev) {
01068                                      ScreenToWidgetPos( ptrev->pos );
01069                                      if ( ptrev->buttons & Ph_BUTTON_SELECT ) { // Normally the left mouse button
01070                                            InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_UP );
01071                                            kwww_outbound_valid = 0;
01072                                            //
01073                                            // To be clean, let's not send multiple left button up
01074                                            // events.
01075                                            //
01076                                            if (!left_button_down)
01077                                              break; //case
01078                                            left_button_down = 0;
01079                                      } else if( ptrev->buttons & Ph_BUTTON_MENU ) // the right button
01080                                            InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_RIGHT_BUTTON_UP );
01081                                      else // middle button
01082                                            InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MIDDLE_BUTTON_UP );
01083                                      
01084                                   //printf("*** Button up %s\n", event->subtype==Ph_EV_RELEASE_PHANTOM ? "(phantom)" : "");
01085                                      result = DispatchMouseEvent(theMouseEvent);
01086                               }
01087                        }
01088                        else if (event->subtype==Ph_EV_RELEASE_OUTBOUND) {
01089                               PhRect_t rect = {{0,0},{0,0}};
01090                               PhRect_t boundary = {{-10000,-10000},{10000,10000}};
01091 
01092                               //printf("*** OUTBOUND\n");
01093                         if (__progname && strcmp(__progname, "kwww") == 0) {
01094                                    //
01095                                    // In kscope we only use dragging to scroll the view. So
01096                                    // we don't want Mozilla to do any special drag processing,
01097                                    // and fake this out by immediately doing a left-button-up.
01098                                    // We do it at (999999,999999) so any control or link under
01099                                    // the pointer doesn't get activated.
01100                                    //
01101                              ptrev->pos.x = ptrev->pos.y = 999999;
01102                     InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_UP );
01103                     result = DispatchMouseEvent(theMouseEvent);
01104                       InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MOVE );
01105                       result = DispatchMouseEvent(theMouseEvent);
01106                                    left_button_down = 0;
01107                                    kwww_outbound_valid = 1;
01108                                    //
01109                                    // In case we activated a combo box, do another down/up
01110                                    // Sending an Esc key also works. Which is better?
01111                                    // The mouse button method may prevent drag initiation
01112                                    // within (multiline?) input fields. 
01113                                    //
01114 #if 0
01115                     InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_DOWN );
01116                     result = DispatchMouseEvent(theMouseEvent);
01117                     InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_UP );
01118                     result = DispatchMouseEvent(theMouseEvent);
01119 #else
01120                                    PhKeyEvent_t kev;
01121                     memset( &kev, 0, sizeof(kev) );
01122                                    kev.key_cap = kev.key_sym = Pk_Escape;
01123                                    kev.key_flags = Pk_KF_Key_Down | Pk_KF_Cap_Valid | Pk_KF_Sym_Valid;
01124                                    DispatchKeyEvent( &kev, 1 );
01125                     memset( &kev, 0, sizeof(kev) );
01126                                    kev.key_cap = Pk_Escape;
01127                                    kev.key_flags = Pk_KF_Cap_Valid;
01128                                    DispatchKeyEvent( &kev, 1 );
01129 #endif
01130                               }
01131 
01132                               PhInitDrag( PtWidgetRid(mWidget), ( Ph_DRAG_KEY_MOTION | Ph_DRAG_TRACK | Ph_TRACK_DRAG),&rect, &boundary, aCbInfo->event->input_group , NULL, NULL, NULL, NULL, NULL);
01133                        }
01134                 }
01135            break;
01136 
01137               case Ph_EV_PTR_MOTION_BUTTON:
01138        {
01139         PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event );
01140               nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal);
01141 
01142         if( ptrev ) {
01143 
01144                                    if( ptrev->flags & Ph_PTR_FLAG_Z_ONLY ) break; // sometimes z presses come out of nowhere */
01145 
01146 #ifdef PHOTON_DND
01147                                    if( sDragService ) {
01148                                           nsDragService *d;
01149                                           nsIDragService *s = sDragService;
01150                                           d = ( nsDragService * )s;
01151                                           d->SetNativeDndData( widget, event );
01152                                           }
01153 #endif
01154 
01155                 if (!__progname || strcmp(__progname, "kwww") != 0) {
01156                   //
01157                      // We don't send these events in kscope. Dragging is devoted to
01158                      // scrolling.
01159                      //
01160             ScreenToWidgetPos( ptrev->pos );
01161               InitMouseEvent(ptrev, this, theMouseEvent, NS_MOUSE_MOVE );
01162             result = DispatchMouseEvent(theMouseEvent);
01163                      }
01164           }
01165        }
01166        break;
01167 
01168       case Ph_EV_KEY:
01169         // Update the current input group for clipboard key events. This
01170         // covers both mozserver and mozilla.
01171         if (sClipboard)
01172           sClipboard->SetInputGroup(event->input_group);
01173                             result = DispatchKeyEvent( (PhKeyEvent_t*) PhGetData( event ), 0 );
01174         break;
01175 
01176       case Ph_EV_DRAG:
01177               {
01178           nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull, nsMouseEvent::eReal);
01179 
01180           switch(event->subtype) {
01181               static int is_kwww=-1;
01182 
01183             case Ph_EV_DRAG_COMPLETE: {
01184                 nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull,
01185                                                nsMouseEvent::eReal);
01186                 PhPointerEvent_t* ptrev2 = (PhPointerEvent_t*) PhGetData( event );
01187                             //printf("*** Drag complete\n");
01188                 if (is_kwww) {  
01189                     // Already did the button up
01190                               kwww_outbound_valid = 0;
01191                               prevx = prevy = -1;
01192                          } else {
01193                   ScreenToWidgetPos( ptrev2->pos );
01194                   InitMouseEvent(ptrev2, this, theMouseEvent, NS_MOUSE_LEFT_BUTTON_UP );
01195                   result = DispatchMouseEvent(theMouseEvent);
01196                               left_button_down = 0;
01197                 }
01198                        }
01199               break;
01200             case Ph_EV_DRAG_MOTION_EVENT: {
01201                 PhPointerEvent_t* ptrev2 = (PhPointerEvent_t*) PhGetData( event );
01202                             //printf("*** Drag motion\n");
01203                          if (is_kwww == -1) {
01204                            is_kwww = 0;
01205                               if (__progname && strcmp(__progname, "kwww") == 0)
01206                             is_kwww = 1;
01207                          }
01208 
01209                          if (is_kwww) {
01210                               nsIWidget *nsw = this;
01211                               nsIWidget *top_widget = nsw;
01212 
01213                               if (!kwww_outbound_valid) {
01214                     struct dragevent {
01215                         PhEvent_t hdr;
01216                         PhDragEvent_t drag;
01217                         } ev;
01218 
01219                                    //
01220                                    // If the user does a drag where he releases the left mouse
01221                                    // button almost right away, then we will start getting
01222                                    // drag events even though the mouse button is not pressed!
01223                                    // Work around this Photon bug by cancelling the drag
01224                                    // ourselves. In 6.4.0 we can use PhCancelDrag() to do this.
01225                                    //
01226                                    //printf("*** CANCELLING DRAG!\n");
01227                     memset( &ev, 0, sizeof(ev) );
01228                     ev.hdr.type = Ph_EV_DRAG;
01229                     ev.hdr.emitter.rid = Ph_DEV_RID;
01230                     ev.hdr.flags = Ph_EVENT_INCLUSIVE | Ph_EMIT_TOWARD;
01231                     ev.hdr.data_len = sizeof( ev.drag );
01232                                    ev.hdr.subtype = Ph_EV_DRAG_COMPLETE;
01233                                    ev.hdr.input_group = aCbInfo->event->input_group;
01234                                    ev.drag.rid = PtWidgetRid(mWidget);
01235                                    ev.drag.flags = 0;
01236                                    PhEmit( &ev.hdr, NULL, &ev.drag );
01237                                    break; //case
01238                               }
01239 
01240                               while (nsw) {
01241                                    top_widget = nsw;
01242                                    nsw = nsw->GetParent();
01243                               }
01244                      try_again:
01245                   nsIView *view = nsToolkit::GetViewFor(top_widget);
01246                               if (view) {
01247                                    nsIViewManager* vm = view->GetViewManager();
01248                                    if (vm) {
01249                                   nsIScrollableView* scrollView = nsnull;
01250                                   vm->GetRootScrollableView(&scrollView);
01251                                      if (scrollView) {
01252                                           if (prevx != -1 || prevy != -1) {
01253                                             //
01254                                             // The -1 check is to handle prevx and prevy not set
01255                                             // to the button press location, which happens when
01256                                             // you click on flash.
01257                                             //
01258                                             nsresult rc = ((nsIScrollableView_MOZILLA_1_8_BRANCH*)scrollView)->ScrollByPixels(prevx - ptrev2->pos.x, prevy - ptrev2->pos.y);
01259                                             //printf("*** rc %d from ScrollByPixels\n");
01260                                           }
01261                                      } else if (top_widget != this) {
01262                                        //
01263                                           // There is no scrollable view for the top level widget.
01264                                           // See if there is one for the original widget.
01265                                           //
01266                                           top_widget = this;
01267                                           goto try_again;
01268                                      }
01269                                    }
01270                            }
01271                            prevx = ptrev2->pos.x;
01272                            prevy = ptrev2->pos.y;
01273                          } else {
01274                   ScreenToWidgetPos( ptrev2->pos );
01275                   InitMouseEvent(ptrev2, this, theMouseEvent, NS_MOUSE_MOVE );
01276                   result = DispatchMouseEvent(theMouseEvent);
01277                          }
01278               }
01279               break;
01280             }
01281           }
01282         break;
01283 
01284       case Ph_EV_BOUNDARY:
01285                             PRUint32 evtype;
01286 
01287         switch( event->subtype ) {
01288           case Ph_EV_PTR_ENTER:
01289                                    case Ph_EV_PTR_ENTER_FROM_CHILD:
01290                                           evtype = NS_MOUSE_ENTER;
01291             break;
01292                                    case Ph_EV_PTR_LEAVE_TO_CHILD:
01293           case Ph_EV_PTR_LEAVE:
01294                                           evtype = NS_MOUSE_EXIT;
01295             break;
01296           default:
01297                                           evtype = 0;
01298             break;
01299               }
01300 
01301                             if( evtype != 0 ) {
01302                                    PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( event );
01303                                    nsMouseEvent theMouseEvent(PR_TRUE, 0, nsnull,
01304                                                nsMouseEvent::eReal);
01305                                    ScreenToWidgetPos( ptrev->pos );
01306                                    InitMouseEvent( ptrev, this, theMouseEvent, evtype );
01307                                    result = DispatchMouseEvent( theMouseEvent );
01308                                    }
01309         break;
01310        }
01311 
01312   return result;
01313        }
01314 
01315 
01316 
01317 //-------------------------------------------------------------------------
01318 //
01319 // the nsWidget raw event callback for all nsWidgets in this toolkit
01320 //
01321 //-------------------------------------------------------------------------
01322 int nsWidget::RawEventHandler( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) {
01323 
01324   // Get the window which caused the event and ask it to process the message
01325   nsWidget *someWidget = (nsWidget*) data;
01326 
01327   if( someWidget && someWidget->mIsDestroying == PR_FALSE && someWidget->HandleEvent( widget, cbinfo ) )
01328               return Pt_END; // Event was consumed
01329 
01330   return Pt_CONTINUE;
01331        }
01332 
01333 
01334 int nsWidget::GotFocusCallback( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) 
01335 {
01336   nsWidget *pWidget = (nsWidget *) data;
01337 
01338        if( PtWidgetIsClass( widget, PtWindow ) ) {
01339               if( pWidget->mEventCallback ) {
01340                      /* the WM_ACTIVATE code */
01341                      pWidget->DispatchStandardEvent(NS_ACTIVATE);
01342                      return Pt_CONTINUE;
01343                      }
01344               }
01345 
01346        pWidget->DispatchStandardEvent(NS_GOTFOCUS);
01347 
01348   return Pt_CONTINUE;
01349 }
01350 
01351 int nsWidget::LostFocusCallback( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) 
01352 {
01353   nsWidget *pWidget = (nsWidget *) data;
01354        pWidget->DispatchStandardEvent(NS_LOSTFOCUS);
01355   return Pt_CONTINUE;
01356 }
01357 
01358 int nsWidget::DestroyedCallback( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) {
01359   nsWidget *pWidget = (nsWidget *) data;
01360   if( !pWidget->mIsDestroying ) pWidget->OnDestroy();
01361   return Pt_CONTINUE;
01362        }
01363 
01364 #ifdef PHOTON_DND
01365 void nsWidget::ProcessDrag( PhEvent_t *event, PRUint32 aEventType, PhPoint_t *pos ) {
01366        nsCOMPtr<nsIDragSession> currSession;
01367        sDragService->GetCurrentSession ( getter_AddRefs(currSession) );
01368        if( !currSession ) return;
01369 
01370        int action = nsIDragService::DRAGDROP_ACTION_NONE;
01371        nsDragService *d = ( nsDragService * ) sDragService;
01372        
01373   if( d->mActionType & nsIDragService::DRAGDROP_ACTION_MOVE )
01374     action = nsIDragService::DRAGDROP_ACTION_MOVE;
01375   else if( d->mActionType & nsIDragService::DRAGDROP_ACTION_LINK )
01376     action = nsIDragService::DRAGDROP_ACTION_LINK;
01377   else if( d->mActionType & nsIDragService::DRAGDROP_ACTION_COPY )
01378     action = nsIDragService::DRAGDROP_ACTION_COPY;
01379 
01380        currSession->SetDragAction( action );
01381 
01382        DispatchDragDropEvent( event, aEventType, pos );
01383 
01384        int old_subtype = event->subtype;
01385        event->subtype = Ph_EV_DND_ENTER;
01386 
01387        PRBool canDrop;
01388        currSession->GetCanDrop(&canDrop);
01389        if(!canDrop) {
01390               static PhCharacterCursorDescription_t nodrop_cursor = {  { Ph_CURSOR_NOINPUT, sizeof(PhCharacterCursorDescription_t) }, PgRGB( 255, 255, 224 ) };
01391               PhAckDnd( event, Ph_EV_DND_MOTION, ( PhCursorDescription_t * ) &nodrop_cursor );
01392               }
01393        else {
01394               static PhCharacterCursorDescription_t drop_cursor = { { Ph_CURSOR_PASTE, sizeof(PhCharacterCursorDescription_t) }, PgRGB( 255, 255, 224 ) };
01395               PhAckDnd( event, Ph_EV_DND_MOTION, ( PhCursorDescription_t * ) &drop_cursor );
01396               }
01397 
01398        event->subtype = old_subtype;
01399 
01400        // Clear the cached value
01401        currSession->SetCanDrop(PR_FALSE);
01402        }
01403 
01404 void nsWidget::DispatchDragDropEvent( PhEvent_t *phevent, PRUint32 aEventType, PhPoint_t *pos ) {
01405   nsEventStatus status;
01406   nsMouseEvent event(PR_TRUE, 0, nsnull, nsMouseEvent::eReal);
01407 
01408   InitEvent( event, aEventType );
01409 
01410   event.point.x = pos->x;
01411   event.point.y = pos->y;
01412 
01413        PhDndEvent_t *dnd = ( PhDndEvent_t * ) PhGetData( phevent );
01414   event.isControl = ( dnd->key_mods & Pk_KM_Ctrl ) ? PR_TRUE : PR_FALSE;
01415   event.isShift   = ( dnd->key_mods & Pk_KM_Shift ) ? PR_TRUE : PR_FALSE;
01416   event.isAlt     = ( dnd->key_mods & Pk_KM_Alt ) ? PR_TRUE : PR_FALSE;
01417   event.isMeta    = PR_FALSE;
01418 
01419        event.widget = this;
01420 
01422 
01423   DispatchEvent( &event, status );
01424        }
01425 
01426 int nsWidget::DndCallback( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo ) {
01427        nsWidget *pWidget = (nsWidget *) data;
01428        PtDndCallbackInfo_t *cbdnd = (  PtDndCallbackInfo_t * ) cbinfo->cbdata;
01429 
01430        static PtDndFetch_t dnd_data_template = { "Mozilla", "dnddata", Ph_TRANSPORT_INLINE, Pt_DND_SELECT_MOTION,
01431                         NULL, NULL, NULL, NULL, NULL };
01432 
01434 
01435        PhPointerEvent_t* ptrev = (PhPointerEvent_t*) PhGetData( cbinfo->event );
01436 //printf("Enter pos=%d %d\n", ptrev->pos.x, ptrev->pos.y );
01437        pWidget->ScreenToWidgetPos( ptrev->pos );
01438 //printf("After trans pos=%d %d pWidget=%p\n", ptrev->pos.x, ptrev->pos.y, pWidget );
01439 
01440 
01441        switch( cbinfo->reason_subtype ) {
01442               case Ph_EV_DND_ENTER: {
01443                      sDragService->StartDragSession();
01444                      pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_ENTER, &ptrev->pos );
01445 
01446                      PtDndSelect( widget, &dnd_data_template, 1, NULL, NULL, cbinfo );
01447                      }
01448                      break;
01449 
01450               case Ph_EV_DND_MOTION: {
01451                      pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_OVER, &ptrev->pos );
01452                      }
01453                      break;
01454               case Ph_EV_DND_DROP:
01455                      nsDragService *d;
01456                      d = ( nsDragService * )sDragService;
01457                      if( d->SetDropData( (char*)cbdnd->data ) != NS_OK ) break;
01458                      pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_DROP, &ptrev->pos );
01459                      sDragService->EndDragSession();
01460                      ((nsDragService*) sDragService)->SourceEndDrag();
01461                      break;
01462 
01463               case Ph_EV_DND_LEAVE:
01464                      pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_EXIT, &ptrev->pos );
01465                      sDragService->EndDragSession();
01466                      break;
01467 
01468               case Ph_EV_DND_CANCEL:
01469                      pWidget->ProcessDrag( cbinfo->event, NS_DRAGDROP_EXIT, &ptrev->pos );
01470                      sDragService->EndDragSession();
01471                      ((nsDragService*) sDragService)->SourceEndDrag();
01472                      break;
01473               }
01474 
01475        return Pt_CONTINUE;
01476        }
01477 #endif /* PHOTON_DND */