Back to index

lightning-sunbird  0.9+nobinonly
nsWindow.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; 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  *   Paul Ashford <arougthopher@lizardland.net>
00024  *   Sergei Dolgov <sergei_d@fi.tartu.ee>
00025  *   Fredrik Holmqvist <thesuckiestemail@yahoo.se>
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 #include "nsDebug.h"
00042 #include "nsWindow.h"
00043 #include "nsIAppShell.h"
00044 #include "nsIFontMetrics.h"
00045 #include "nsFont.h"
00046 #include "nsGUIEvent.h"
00047 #include "nsWidgetsCID.h"
00048 #include "nsIDragService.h"
00049 #include "nsIDragSessionBeOS.h"
00050 #include "nsIDeviceContext.h"
00051 #include "nsRect.h"
00052 #include "nsIRegion.h"
00053 #include "nsTransform2D.h"
00054 #include "nsGfxCIID.h"
00055 #include "resource.h"
00056 #include "prtime.h"
00057 #include "nsReadableUtils.h"
00058 #include "nsVoidArray.h"
00059 
00060 #include <Application.h>
00061 #include <InterfaceDefs.h>
00062 #include <Region.h>
00063 #include <ScrollBar.h>
00064 #include <app/Message.h>
00065 #include <support/String.h>
00066 #include <Screen.h>
00067 
00068 #include <nsBeOSCursors.h>
00069 #if defined(BeIME)
00070 #include <Input.h>
00071 #include <InputServerMethod.h>
00072 #include <String.h>
00073 #endif
00074 
00075 #include "nsIRollupListener.h"
00076 #include "nsIMenuRollup.h"
00077 
00078 // See comments in nsWindow.h as to why we override these calls from nsBaseWidget
00079 NS_IMPL_THREADSAFE_ADDREF(nsWindow)
00080 NS_IMPL_THREADSAFE_RELEASE(nsWindow)
00081 
00082 static NS_DEFINE_IID(kIWidgetIID,       NS_IWIDGET_IID);
00083 static NS_DEFINE_IID(kRegionCID, NS_REGION_CID);
00084 static NS_DEFINE_IID(kCDragServiceCID,  NS_DRAGSERVICE_CID);
00085 //-------------------------------------------------------------------------
00086 // Global Definitions
00087 //-------------------------------------------------------------------------
00088 
00089 // Rollup Listener - static variable defintions
00090 static nsIRollupListener * gRollupListener           = nsnull;
00091 static nsIWidget         * gRollupWidget             = nsnull;
00092 static PRBool              gRollupConsumeRollupEvent = PR_FALSE;
00093 // Tracking last activated BWindow
00094 static BWindow           * gLastActiveWindow = NULL;
00095 
00096 // BCursor objects can't be created until they are used.  Some mozilla utilities, 
00097 // such as regxpcom, do not create a BApplication object, and therefor fail to run.,
00098 // since a BCursor requires a vaild BApplication (see Bug#129964).  But, we still want
00099 // to cache them for performance.  Currently, there are 17 cursors available;
00100 static nsVoidArray          gCursorArray(21);
00101 // Used in contrain position.  Specifies how much of a window must remain on screen
00102 #define kWindowPositionSlop 20
00103 // BeOS does not provide this information, so we must hard-code it
00104 #define kWindowBorderWidth 5
00105 #define kWindowTitleBarHeight 24
00106 
00107 
00108 #if defined(BeIME)
00109 #include "nsUTF8Utils.h"
00110 static inline uint32 utf8_str_len(const char* ustring, int32 length) 
00111 {
00112        CalculateUTF8Length cutf8;
00113        cutf8.write(ustring, length);
00114        return cutf8.Length();       
00115 }
00116 
00117 nsIMEBeOS::nsIMEBeOS()
00118        : imeTarget(NULL)
00119        , imeState(NS_COMPOSITION_END), imeWidth(14)
00120 {
00121 }
00122 /* placeholder for possible cleanup
00123 nsIMEBeOS::~nsIMEBeOS()
00124 {
00125 }
00126 */                                                      
00127 void nsIMEBeOS::RunIME(uint32 *args, nsWindow *target, BView *fView)
00128 {
00129        BMessage msg;
00130        msg.Unflatten((const char*)args);
00131 
00132        switch (msg.FindInt32("be:opcode")) 
00133        {
00134        case B_INPUT_METHOD_CHANGED:
00135               if (msg.HasString("be:string")) 
00136               {
00137                      const char* src = msg.FindString("be:string");
00138                      CopyUTF8toUTF16(src, imeText);
00139  
00140               if (msg.FindBool("be:confirmed")) 
00141               {      
00142                      if (imeState != NS_COMPOSITION_END)
00143                                    DispatchText(imeText, 0, NULL);
00144                      }
00145                      else 
00146                      {
00147                             nsTextRange txtRuns[2];
00148                             PRUint32 txtCount = 2;
00149 
00150                      int32 select[2];
00151                             select[0] = msg.FindInt32("be:selection", int32(0));
00152                             select[1] = msg.FindInt32("be:selection", 1);
00153 
00154                             txtRuns[0].mStartOffset = (select[0] == select[1]) ? 0 : utf8_str_len(src, select[1]);
00155                             txtRuns[0].mEndOffset       = imeText.Length();
00156                             txtRuns[0].mRangeType       = NS_TEXTRANGE_CONVERTEDTEXT;
00157                             if (select[0] == select[1])
00158                                    txtCount = 1;
00159                             else 
00160                             {
00161                                    txtRuns[1].mStartOffset = utf8_str_len(src, select[0]);
00162                                    txtRuns[1].mEndOffset       = utf8_str_len(src, select[1]);
00163                                    txtRuns[1].mRangeType       = NS_TEXTRANGE_SELECTEDCONVERTEDTEXT;
00164                             }
00165                             imeTarget = target;
00166                             DispatchText(imeText, txtCount, txtRuns);
00167                      }      
00168               }      
00169               break;
00170 
00171        case B_INPUT_METHOD_LOCATION_REQUEST:
00172               if (fView && fView->LockLooper()) 
00173               {
00174                      BPoint caret(imeCaret);
00175                      DispatchIME(NS_COMPOSITION_QUERY);
00176                      if (caret.x > imeCaret.x) 
00177                             caret.x = imeCaret.x - imeWidth * imeText.Length();     /* back */
00178 
00179                      BMessage reply(B_INPUT_METHOD_EVENT);
00180                      reply.AddInt32("be:opcode", B_INPUT_METHOD_LOCATION_REQUEST);
00181                      for (int32 s= 0; imeText[s]; s++) 
00182                      { 
00183                             reply.AddPoint("be:location_reply", fView->ConvertToScreen(caret));
00184                             reply.AddFloat("be:height_reply", imeHeight);
00185                             caret.x += imeWidth;
00186                      }
00187                      imeMessenger.SendMessage(&reply);
00188                      fView->UnlockLooper();
00189               }
00190               break;
00191 
00192        case B_INPUT_METHOD_STARTED:
00193               imeTarget = target;
00194               DispatchIME(NS_COMPOSITION_START);
00195               DispatchIME(NS_COMPOSITION_QUERY);
00196 
00197               msg.FindMessenger("be:reply_to", &imeMessenger);
00198               break;
00199        
00200        case B_INPUT_METHOD_STOPPED:
00201               if (imeState != NS_COMPOSITION_END)
00202                      DispatchIME(NS_COMPOSITION_END);
00203               imeText.Truncate();
00204               break;
00205        };
00206 }
00207 
00208 void nsIMEBeOS::DispatchText(nsString &text, PRUint32 txtCount, nsTextRange* txtRuns)
00209 {
00210        nsTextEvent textEvent(PR_TRUE,NS_TEXT_TEXT, imeTarget);
00211 
00212        textEvent.time              = 0;
00213        textEvent.isShift   = 
00214        textEvent.isControl =
00215        textEvent.isAlt      = 
00216        textEvent.isMeta     = PR_FALSE;
00217   
00218        textEvent.refPoint.x = 
00219        textEvent.refPoint.y = 0;
00220 
00221        textEvent.theText    = text.get();
00222        textEvent.isChar     = PR_TRUE;
00223        textEvent.rangeCount= txtCount;
00224        textEvent.rangeArray= txtRuns;
00225 
00226        DispatchWindowEvent(&textEvent);
00227 }
00228 
00229 void nsIMEBeOS::DispatchCancelIME()
00230 {
00231        if (imeText.Length() && imeState != NS_COMPOSITION_END) 
00232        {
00233               BMessage reply(B_INPUT_METHOD_EVENT);
00234               reply.AddInt32("be:opcode", B_INPUT_METHOD_STOPPED);
00235               imeMessenger.SendMessage(&reply);
00236 
00237               DispatchText(imeText, 0, NULL);
00238               DispatchIME(NS_COMPOSITION_END);
00239 
00240               imeText.Truncate();
00241        }
00242 }
00243 
00244 void nsIMEBeOS::DispatchIME(PRUint32 what)
00245 {
00246        nsCompositionEvent compEvent(PR_TRUE, what, imeTarget);
00247 
00248        compEvent.refPoint.x =
00249        compEvent.refPoint.y = 0;
00250        compEvent.time        = 0;
00251 
00252        DispatchWindowEvent(&compEvent);
00253        imeState = what;
00254 
00255        if (what == NS_COMPOSITION_QUERY) 
00256        {
00257               imeCaret.Set(compEvent.theReply.mCursorPosition.x,
00258                          compEvent.theReply.mCursorPosition.y);
00259               imeHeight = compEvent.theReply.mCursorPosition.height+4;
00260        }
00261 }
00262 
00263 PRBool nsIMEBeOS::DispatchWindowEvent(nsGUIEvent* event)
00264 {
00265        nsEventStatus status;
00266        imeTarget->DispatchEvent(event, status);
00267        return PR_FALSE;
00268 }
00269 // There is only one IME instance per app, actually it may be set as global
00270 nsIMEBeOS *nsIMEBeOS::GetIME()
00271 {
00272        if(beosIME == 0)
00273               beosIME = new nsIMEBeOS();
00274        return beosIME;
00275 }
00276 nsIMEBeOS *nsIMEBeOS::beosIME = 0;
00277 #endif
00278 
00279 //-------------------------------------------------------------------------
00280 //
00281 // nsWindow constructor
00282 //
00283 //-------------------------------------------------------------------------
00284 nsWindow::nsWindow() : nsBaseWidget()
00285 {
00286        rgb_color     back = ui_color(B_PANEL_BACKGROUND_COLOR);
00287 
00288        mView               = 0;
00289        mPreferredWidth     = 0;
00290        mPreferredHeight    = 0;
00291        mFontMetrics        = nsnull;
00292        mIsVisible          = PR_FALSE;
00293        mEnabled            = PR_TRUE;
00294        mIsScrolling        = PR_FALSE;
00295        mParent             = nsnull;
00296        mWindowParent       = nsnull;
00297        mUpdateArea = do_CreateInstance(kRegionCID);
00298        mForeground = NS_RGBA(0xFF,0xFF,0xFF,0xFF);
00299        mBackground = mForeground;
00300        mBWindowFeel        = B_NORMAL_WINDOW_FEEL;
00301        if (mUpdateArea)
00302        {
00303               mUpdateArea->Init();
00304               mUpdateArea->SetTo(0, 0, 0, 0);
00305        }
00306 }
00307 
00308 
00309 //-------------------------------------------------------------------------
00310 //
00311 // nsWindow destructor
00312 //
00313 //-------------------------------------------------------------------------
00314 nsWindow::~nsWindow()
00315 {
00316        mIsDestroying = PR_TRUE;
00317 
00318        // If the widget was released without calling Destroy() then the native
00319        // window still exists, and we need to destroy it
00320        if (NULL != mView) 
00321        {
00322               Destroy();
00323        }
00324        NS_IF_RELEASE(mFontMetrics);
00325 }
00326 
00327 NS_METHOD nsWindow::BeginResizingChildren(void)
00328 {
00329        // HideKids(PR_TRUE) may be used here
00330        NS_NOTYETIMPLEMENTED("BeginResizingChildren not yet implemented"); // to be implemented
00331        return NS_OK;
00332 }
00333 
00334 NS_METHOD nsWindow::EndResizingChildren(void)
00335 {
00336        // HideKids(PR_FALSE) may be used here
00337        NS_NOTYETIMPLEMENTED("EndResizingChildren not yet implemented"); // to be implemented
00338        return NS_OK;
00339 }
00340 
00341 NS_METHOD nsWindow::WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect)
00342 {
00343        BPoint point;
00344        point.x = aOldRect.x;
00345        point.y = aOldRect.y;
00346        if (mView && mView->LockLooper())
00347        {
00348               mView->ConvertToScreen(&point);
00349               mView->UnlockLooper();
00350        }
00351        aNewRect.x = nscoord(point.x);
00352        aNewRect.y = nscoord(point.y);
00353        aNewRect.width = aOldRect.width;
00354        aNewRect.height = aOldRect.height;
00355        return NS_OK;
00356 }
00357 
00358 NS_METHOD nsWindow::ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect)
00359 {
00360        BPoint point;
00361        point.x = aOldRect.x;
00362        point.y = aOldRect.y;
00363        if (mView && mView->LockLooper())
00364        {
00365               mView->ConvertFromScreen(&point);
00366               mView->UnlockLooper();
00367        }
00368        aNewRect.x = nscoord(point.x);
00369        aNewRect.y = nscoord(point.y);
00370        aNewRect.width = aOldRect.width;
00371        aNewRect.height = aOldRect.height;
00372        return NS_OK;
00373 }
00374 
00375 
00376 //-------------------------------------------------------------------------
00377 //
00378 // Convert nsEventStatus value to a windows boolean
00379 //
00380 //-------------------------------------------------------------------------
00381 
00382 PRBool nsWindow::ConvertStatus(nsEventStatus aStatus)
00383 {
00384        switch(aStatus) 
00385        {
00386               case nsEventStatus_eIgnore:
00387                      return PR_FALSE;
00388               case nsEventStatus_eConsumeNoDefault:
00389                      return PR_TRUE;
00390               case nsEventStatus_eConsumeDoDefault:
00391                      return PR_FALSE;
00392               default:
00393                      NS_ASSERTION(0, "Illegal nsEventStatus enumeration value");
00394                      break;
00395        }
00396        return PR_FALSE;
00397 }
00398 
00399 //-------------------------------------------------------------------------
00400 //
00401 // Initialize an event to dispatch
00402 //
00403 //-------------------------------------------------------------------------
00404 void nsWindow::InitEvent(nsGUIEvent& event, nsPoint* aPoint)
00405 {
00406        NS_ADDREF(event.widget);
00407 
00408        if (nsnull == aPoint) // use the point from the event
00409        {
00410               // get the message position in client coordinates and in twips
00411               event.point.x = 0;
00412               event.point.y = 0;
00413        }
00414        else // use the point override if provided
00415        {
00416               event.point.x = aPoint->x;
00417               event.point.y = aPoint->y;
00418        }
00419        event.time = PR_IntervalNow();
00420 }
00421 
00422 //-------------------------------------------------------------------------
00423 //
00424 // Invokes callback and  ProcessEvent method on Event Listener object
00425 //
00426 //-------------------------------------------------------------------------
00427 NS_IMETHODIMP nsWindow::DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus)
00428 {
00429        aStatus = nsEventStatus_eIgnore;
00430 
00431        nsCOMPtr <nsIWidget> mWidget = event->widget;
00432 
00433        if (mEventCallback)
00434               aStatus = (*mEventCallback)(event);
00435 
00436        if ((aStatus != nsEventStatus_eIgnore) && (mEventListener))
00437               aStatus = mEventListener->ProcessEvent(*event);
00438 
00439        return NS_OK;
00440 }
00441 
00442 //-------------------------------------------------------------------------
00443 //
00444 // Dispatch Window Event
00445 //
00446 //-------------------------------------------------------------------------
00447 PRBool nsWindow::DispatchWindowEvent(nsGUIEvent* event)
00448 {
00449        nsEventStatus status;
00450        DispatchEvent(event, status);
00451        return ConvertStatus(status);
00452 }
00453 
00454 //-------------------------------------------------------------------------
00455 //
00456 // Dispatch standard event
00457 //
00458 //-------------------------------------------------------------------------
00459 
00460 PRBool nsWindow::DispatchStandardEvent(PRUint32 aMsg)
00461 {
00462        nsGUIEvent event(PR_TRUE, aMsg, this);
00463        InitEvent(event);
00464 
00465        PRBool result = DispatchWindowEvent(&event);
00466        NS_RELEASE(event.widget);
00467        return result;
00468 }
00469 
00470 NS_IMETHODIMP nsWindow::PreCreateWidget(nsWidgetInitData *aInitData)
00471 {
00472        if ( nsnull == aInitData)
00473               return NS_ERROR_FAILURE;
00474        
00475        SetWindowType(aInitData->mWindowType);
00476        SetBorderStyle(aInitData->mBorderStyle);
00477        return NS_OK;
00478 }
00479 
00480 //-------------------------------------------------------------------------
00481 //
00482 // Utility method for implementing both Create(nsIWidget ...) and
00483 // Create(nsNativeWidget...)
00484 //-------------------------------------------------------------------------
00485 nsresult nsWindow::StandardWindowCreate(nsIWidget *aParent,
00486                                         const nsRect &aRect,
00487                                         EVENT_CALLBACK aHandleEventFunction,
00488                                         nsIDeviceContext *aContext,
00489                                         nsIAppShell *aAppShell,
00490                                         nsIToolkit *aToolkit,
00491                                         nsWidgetInitData *aInitData,
00492                                         nsNativeWidget aNativeParent)
00493 {
00494 
00495        //Do as little as possible for invisible windows, why are these needed?
00496        if (mWindowType == eWindowType_invisible)
00497               return NS_ERROR_FAILURE;
00498               
00499        nsIWidget *baseParent = 
00500                                (aInitData->mWindowType == eWindowType_dialog ||
00501                                 aInitData->mWindowType == eWindowType_toplevel ||
00502                                 aInitData->mWindowType == eWindowType_invisible) ?
00503                                nsnull : aParent;
00504 
00505        NS_ASSERTION(aInitData->mWindowType != eWindowType_popup || 
00506               !aParent, "Popups should not be hooked into nsIWidget hierarchy");
00507        
00508        mIsTopWidgetWindow = (nsnull == baseParent);
00509        
00510        BaseCreate(baseParent, aRect, aHandleEventFunction, aContext,
00511                   aAppShell, aToolkit, aInitData);
00512 
00513        mListenForResizes = aNativeParent ? PR_TRUE : aInitData->mListenForResizes;
00514               
00515        // Switch to the "main gui thread" if necessary... This method must
00516        // be executed on the "gui thread"...
00517        //
00518        nsToolkit* toolkit = (nsToolkit *)mToolkit;
00519        if (toolkit && !toolkit->IsGuiThread())
00520        {
00521               uint32 args[7];
00522               args[0] = (uint32)aParent;
00523               args[1] = (uint32)&aRect;
00524               args[2] = (uint32)aHandleEventFunction;
00525               args[3] = (uint32)aContext;
00526               args[4] = (uint32)aAppShell;
00527               args[5] = (uint32)aToolkit;
00528               args[6] = (uint32)aInitData;
00529 
00530               if (nsnull != aParent)
00531               {
00532                      // nsIWidget parent dispatch
00533                      MethodInfo info(this, this, nsSwitchToUIThread::CREATE, 7, args);
00534                      toolkit->CallMethod(&info);
00535               }
00536               else
00537               {
00538                      // Native parent dispatch
00539                      MethodInfo info(this, this, nsSwitchToUIThread::CREATE_NATIVE, 5, args);
00540                      toolkit->CallMethod(&info);
00541               }
00542               return NS_OK;
00543        }
00544 
00545        mParent = aParent;
00546        // Useful shortcut, wondering if we can use it also in GetParent() instead nsIWidget* type mParent.
00547        mWindowParent = (nsWindow *)aParent;
00548        SetBounds(aRect);
00549 
00550        BRect winrect = BRect(aRect.x, aRect.y, aRect.x + aRect.width - 1, aRect.y + aRect.height - 1);
00551 
00552        // Default mode for window, everything switched off.
00553        uint32 flags = B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE | B_NOT_CLOSABLE | B_ASYNCHRONOUS_CONTROLS;
00554        window_look look = B_NO_BORDER_WINDOW_LOOK;
00555        switch (mWindowType)
00556        {
00557               //handle them as childviews until I know better. Shame on me.
00558               case eWindowType_java:
00559               case eWindowType_plugin:
00560                      NS_NOTYETIMPLEMENTED("Java and plugin windows not yet implemented properly trying childview"); // to be implemented
00561                      //These fall thru and behave just like child for the time being. They may require special implementation.
00562               case eWindowType_child:
00563               {
00564                      //NS_NATIVE_GRAPHIC maybe?
00565                      //Parent may be a BView if we embed.
00566                      BView *parent= (BView *) (aParent ? aParent->GetNativeData(NS_NATIVE_WIDGET) :  aNativeParent);
00567                      //There seems to be three of these on startup,
00568                      //but I believe that these are because of bugs in 
00569                      //other code as they existed before rewriting this
00570                      //function.
00571                      NS_PRECONDITION(parent, "Childviews without parents don't get added to anything.");
00572                      // A childview that is never added to a parent is very strange.
00573                      if (!parent)
00574                             return NS_ERROR_FAILURE;
00575 
00576                      mView = new nsViewBeOS(this, winrect, "Child view", 0, B_WILL_DRAW);
00577 #if defined(BeIME)
00578                      mView->SetFlags(mView->Flags() | B_INPUT_METHOD_AWARE);
00579 #endif 
00580                      bool mustUnlock = parent->Parent() && parent->LockLooper();
00581                      parent->AddChild(mView);
00582                      if (mustUnlock) parent->UnlockLooper();
00583                      DispatchStandardEvent(NS_CREATE);
00584                      return NS_OK;
00585               }
00586 
00587               case eWindowType_popup:
00588               case eWindowType_dialog:
00589               case eWindowType_toplevel:
00590               {
00591                      //eBorderStyle_default is to ask the OS to handle it as it sees best.
00592                      //eBorderStyle_all is same as top_level window default.
00593                      if (eBorderStyle_default == mBorderStyle || eBorderStyle_all & mBorderStyle)
00594                      {
00595                             //(Firefox prefs doesn't go this way, so apparently it wants titlebar, zoom, resize and close.)
00596 
00597                             //Look and feel for others are set ok at init.
00598                             if (eWindowType_toplevel==mWindowType)
00599                             {
00600                                    look = B_TITLED_WINDOW_LOOK;
00601                                    flags = B_ASYNCHRONOUS_CONTROLS;
00602                             }
00603                      }
00604                      else
00605                      {
00606                             if (eBorderStyle_border & mBorderStyle)
00607                                    look = B_MODAL_WINDOW_LOOK;
00608  
00609                             if (eBorderStyle_resizeh & mBorderStyle)
00610                             {
00611                                    //Resize demands at least border
00612                                    look = B_MODAL_WINDOW_LOOK;
00613                                    flags &= !B_NOT_RESIZABLE;
00614                             }
00615 
00616                             //We don't have titlebar menus, so treat like title as it demands titlebar.
00617                             if (eBorderStyle_title & mBorderStyle || eBorderStyle_menu & mBorderStyle)
00618                                    look = B_TITLED_WINDOW_LOOK;
00619 
00620                             if (eBorderStyle_minimize & mBorderStyle)
00621                                    flags &= !B_NOT_MINIMIZABLE;
00622 
00623                             if (eBorderStyle_maximize & mBorderStyle)
00624                                    flags &= !B_NOT_ZOOMABLE;
00625 
00626                             if (eBorderStyle_close & mBorderStyle)
00627                                    flags &= !B_NOT_CLOSABLE;
00628                      }
00629 
00630                      //popups always avoid focus and don't force the user to another workspace.
00631                      if (eWindowType_popup==mWindowType)
00632                             flags |= B_AVOID_FOCUS | B_NO_WORKSPACE_ACTIVATION;
00633 
00634                      nsWindowBeOS * w = new nsWindowBeOS(this, winrect, "", look, mBWindowFeel, flags);
00635                      if (!w)
00636                             return NS_ERROR_OUT_OF_MEMORY;
00637 
00638                      mView = new nsViewBeOS(this, w->Bounds(), "Toplevel view", B_FOLLOW_ALL, (mWindowType == eWindowType_popup ? B_WILL_DRAW: 0));
00639  
00640                      if (!mView)
00641                             return NS_ERROR_OUT_OF_MEMORY;
00642        
00643                      w->AddChild(mView);
00644                      // I'm wondering if we can move part of that code to above
00645                      if (eWindowType_dialog == mWindowType && mWindowParent) 
00646                      {
00647                             nsWindow *topparent = mWindowParent;
00648                             while(topparent->mWindowParent)
00649                                    topparent = topparent->mWindowParent;
00650                             // may be got via mView and mView->Window() of topparent explicitly   
00651                             BWindow* subsetparent = (BWindow *)topparent->GetNativeData(NS_NATIVE_WINDOW);
00652                             if (subsetparent)
00653                             {
00654                                    mBWindowFeel = B_FLOATING_SUBSET_WINDOW_FEEL;
00655                                    w->SetFeel(mBWindowFeel);
00656                                    w->AddToSubset(subsetparent);
00657                             }
00658                      } 
00659                      else if (eWindowType_popup == mWindowType  && aNativeParent)
00660                      {
00661                             // Due poor BeOS capability to control windows hierarchy/z-order we use this workaround
00662                             // to show eWindowType_popup (e.g. drop-downs) over floating (subset) parent window.
00663                             if (((BView *)aNativeParent)->Window() &&  ((BView *)aNativeParent)->Window()->IsFloating())
00664                             {
00665                                    mBWindowFeel = B_FLOATING_ALL_WINDOW_FEEL;
00666                                    w->SetFeel(mBWindowFeel);
00667                             }
00668                      }
00669                      
00670                      DispatchStandardEvent(NS_CREATE);
00671                      return NS_OK;
00672               }
00673               case eWindowType_invisible:
00674               case eWindowType_sheet:
00675                      break;
00676               default:
00677               {
00678                      printf("UNKNOWN or not handled windowtype!!!\n");
00679               }
00680        }
00681 
00682        return NS_ERROR_FAILURE;
00683 }
00684 
00685 //-------------------------------------------------------------------------
00686 //
00687 // Create the proper widget
00688 //
00689 //-------------------------------------------------------------------------
00690 NS_METHOD nsWindow::Create(nsIWidget *aParent,
00691                            const nsRect &aRect,
00692                            EVENT_CALLBACK aHandleEventFunction,
00693                            nsIDeviceContext *aContext,
00694                            nsIAppShell *aAppShell,
00695                            nsIToolkit *aToolkit,
00696                            nsWidgetInitData *aInitData)
00697 {
00698        return(StandardWindowCreate(aParent, aRect, aHandleEventFunction,
00699                                    aContext, aAppShell, aToolkit, aInitData,
00700                                    nsnull));
00701 }
00702 
00703 
00704 //-------------------------------------------------------------------------
00705 //
00706 // create with a native parent
00707 //
00708 //-------------------------------------------------------------------------
00709 
00710 NS_METHOD nsWindow::Create(nsNativeWidget aParent,
00711                            const nsRect &aRect,
00712                            EVENT_CALLBACK aHandleEventFunction,
00713                            nsIDeviceContext *aContext,
00714                            nsIAppShell *aAppShell,
00715                            nsIToolkit *aToolkit,
00716                            nsWidgetInitData *aInitData)
00717 {
00718        return(StandardWindowCreate(nsnull, aRect, aHandleEventFunction,
00719                                    aContext, aAppShell, aToolkit, aInitData,
00720                                    aParent));
00721 }
00722 
00723 //-------------------------------------------------------------------------
00724 //
00725 // Close this nsWindow
00726 //
00727 //-------------------------------------------------------------------------
00728 NS_METHOD nsWindow::Destroy()
00729 {
00730        // Switch to the "main gui thread" if necessary... This method must
00731        // be executed on the "gui thread"...
00732        nsToolkit* toolkit = (nsToolkit *)mToolkit;
00733        if (toolkit != nsnull && !toolkit->IsGuiThread())
00734        {
00735               MethodInfo info(this, this, nsSwitchToUIThread::DESTROY);
00736               toolkit->CallMethod(&info);
00737               return NS_ERROR_FAILURE;
00738        }
00739 
00740        // Ok, now tell the nsBaseWidget class to clean up what it needs to
00741        if (!mIsDestroying)
00742        {
00743               nsBaseWidget::Destroy();
00744        }      
00745        //our windows can be subclassed by
00746        //others and these namless, faceless others
00747        //may not let us know about WM_DESTROY. so,
00748        //if OnDestroy() didn't get called, just call
00749        //it now.
00750        if (PR_FALSE == mOnDestroyCalled)
00751               OnDestroy();
00752        
00753        // Destroy the BView, if no mView, it is probably destroyed before
00754        // automatically with BWindow::Quit()
00755        if (mView)
00756        {
00757               // prevent the widget from causing additional events
00758               mEventCallback = nsnull;
00759        
00760               if (mView->LockLooper())
00761               {
00762                      while(mView->ChildAt(0))
00763                             mView->RemoveChild(mView->ChildAt(0));
00764                      // destroy from inside
00765                      BWindow       *w = mView->Window();
00766                      // if no window, it was destroyed as result of B_QUIT_REQUESTED and 
00767                      // took also all its children away
00768                      if (w)
00769                      {
00770                             w->Sync();
00771                             if (mView->Parent())
00772                             {
00773                                    mView->Parent()->RemoveChild(mView);
00774                                    if (eWindowType_child != mWindowType)
00775                                           w->Quit();
00776                                    else
00777                                    w->Unlock();
00778                             }
00779                             else
00780                             {
00781                                    w->RemoveChild(mView);
00782                                    w->Quit();
00783                             }
00784                      }
00785                      else
00786                             mView->RemoveSelf();
00787 
00788                      delete mView;
00789               }
00790 
00791               // window is already gone
00792               mView = NULL;
00793        }
00794        mParent = nsnull;
00795        mWindowParent = nsnull;
00796        return NS_OK;}
00797 
00798 
00799 //-------------------------------------------------------------------------
00800 //
00801 // Get this nsWindow parent
00802 //
00803 //-------------------------------------------------------------------------
00804 nsIWidget* nsWindow::GetParent(void)
00805 {
00806        //We cannot addref mParent directly
00807        nsIWidget     *widget = 0;
00808        if (mIsDestroying || mOnDestroyCalled)
00809               return nsnull;
00810        widget = (nsIWidget *)mParent;
00811        NS_IF_ADDREF(widget);
00812        return  widget;
00813 }
00814 
00815 
00816 //-------------------------------------------------------------------------
00817 //
00818 // Hide or show this component
00819 //
00820 //-------------------------------------------------------------------------
00821 NS_METHOD nsWindow::Show(PRBool bState)
00822 {
00823        if (!mEnabled)
00824               return NS_OK;
00825        if (mView && mView->LockLooper())
00826        {
00827               switch (mWindowType)
00828               {
00829                      case eWindowType_popup:
00830                      {
00831                             if (PR_FALSE == bState)
00832                             {
00833                                    // XXX BWindow::Hide() is needed ONLY for popups. No need to hide views for popups
00834                                    if (mView->Window() && !mView->Window()->IsHidden())
00835                                           mView->Window()->Hide();
00836                             }
00837                             else
00838                             {
00839                                           if (mView->Window())
00840                                           {
00841                                                  // bring menu to current workspace - Bug 310293
00842                                                  mView->Window()->SetWorkspaces(B_CURRENT_WORKSPACE);
00843                                                  if (mView->Window()->IsHidden())
00844                                                         mView->Window()->Show();
00845                                           }
00846                             }
00847                             break;
00848                      }
00849 
00850                      case eWindowType_child:
00851                      {
00852                             // XXX No BWindow deals for children
00853                             if (PR_FALSE == bState)
00854                             {
00855                                    if (!mView->IsHidden())
00856                                           mView->Hide();
00857                             }
00858                             else
00859                             {
00860                                    if (mView->IsHidden())
00861                                           mView->Show();              
00862                             }
00863                             break;
00864                      }
00865 
00866                      case eWindowType_dialog:
00867                      case eWindowType_toplevel:
00868                      {
00869                             if (bState == PR_FALSE)
00870                             {
00871                                    if (mView->Window() && !mView->Window()->IsHidden())
00872                                           mView->Window()->Hide();
00873                             }
00874                             else
00875                             {
00876                                    if (mView->Window() && mView->Window()->IsHidden())
00877                                           mView->Window()->Show();
00878                             }
00879                             break;
00880                      }
00881                      
00882                      default: // toplevel and dialog
00883                      {
00884                             NS_ASSERTION(false, "Unhandled Window Type in nsWindow::Show()!");
00885                             break;
00886                      }
00887               } //end switch       
00888 
00889               mView->UnlockLooper();
00890               mIsVisible = bState; 
00891        }
00892        return NS_OK;
00893 }
00894 //-------------------------------------------------------------------------
00895 // Set/unset mouse capture
00896 //-------------------------------------------------------------------------
00897 NS_METHOD nsWindow::CaptureMouse(PRBool aCapture)
00898 {
00899        if (mView && mView->LockLooper())
00900        {
00901               if (PR_TRUE == aCapture)
00902                      mView->SetEventMask(B_POINTER_EVENTS);
00903               else
00904                      mView->SetEventMask(0);
00905               mView->UnlockLooper();
00906        }
00907        return NS_OK;
00908 }
00909 //-------------------------------------------------------------------------
00910 // Capture Roolup Events
00911 //-------------------------------------------------------------------------
00912 NS_METHOD nsWindow::CaptureRollupEvents(nsIRollupListener * aListener, PRBool aDoCapture, PRBool aConsumeRollupEvent)
00913 {
00914        if (!mEnabled)
00915               return NS_OK;
00916               
00917        if (aDoCapture) 
00918        {
00919               // we haven't bothered carrying a weak reference to gRollupWidget because
00920               // we believe lifespan is properly scoped. this next assertion helps 
00921               // assure that remains true.
00922               NS_ASSERTION(!gRollupWidget, "rollup widget reassigned before release");
00923               gRollupConsumeRollupEvent = aConsumeRollupEvent;
00924               NS_IF_RELEASE(gRollupListener);
00925               NS_IF_RELEASE(gRollupWidget);
00926               gRollupListener = aListener;
00927               NS_ADDREF(aListener);
00928               gRollupWidget = this;
00929               NS_ADDREF(this);
00930        } 
00931        else 
00932        {
00933               NS_IF_RELEASE(gRollupListener);
00934               NS_IF_RELEASE(gRollupWidget);
00935        }
00936 
00937        return NS_OK;
00938 }
00939 
00940 //-------------------------------------------------------------------------
00941 // Check if event happened inside the given nsWindow
00942 //-------------------------------------------------------------------------
00943 PRBool nsWindow::EventIsInsideWindow(nsWindow* aWindow, nsPoint pos)
00944 {
00945        BRect r;
00946        BWindow *window = (BWindow *)aWindow->GetNativeData(NS_NATIVE_WINDOW);
00947        if (window)
00948        {
00949               r = window->Frame();
00950        }
00951        else
00952        {
00953               // Bummer!
00954               return PR_FALSE;
00955        }
00956 
00957        if (pos.x < r.left || pos.x > r.right ||
00958                pos.y < r.top || pos.y > r.bottom) {
00959               return PR_FALSE;
00960        }
00961 
00962        return PR_TRUE;
00963 }
00964 
00965 //-------------------------------------------------------------------------
00966 // DealWithPopups
00967 //
00968 // Handle events that may cause a popup (combobox, XPMenu, etc) to need to rollup.
00969 //-------------------------------------------------------------------------
00970 PRBool
00971 nsWindow::DealWithPopups(uint32 methodID, nsPoint pos)
00972 {
00973        if (gRollupListener && gRollupWidget) 
00974        {
00975               // Rollup if the event is outside the popup.
00976               PRBool rollup = !nsWindow::EventIsInsideWindow((nsWindow*)gRollupWidget, pos);
00977 
00978               // If we're dealing with menus, we probably have submenus and we don't
00979               // want to rollup if the click is in a parent menu of the current submenu.
00980               if (rollup) 
00981               {
00982                      nsCOMPtr<nsIMenuRollup> menuRollup ( do_QueryInterface(gRollupListener) );
00983                      if ( menuRollup ) 
00984                      {
00985                             nsCOMPtr<nsISupportsArray> widgetChain;
00986                             menuRollup->GetSubmenuWidgetChain ( getter_AddRefs(widgetChain) );
00987                             if ( widgetChain ) 
00988                             {
00989                                    PRUint32 count = 0;
00990                                    widgetChain->Count(&count);
00991                                    for ( PRUint32 i = 0; i < count; ++i ) 
00992                                    {
00993                                           nsCOMPtr<nsISupports> genericWidget;
00994                                           widgetChain->GetElementAt ( i, getter_AddRefs(genericWidget) );
00995                                           nsCOMPtr<nsIWidget> widget ( do_QueryInterface(genericWidget) );
00996                                           if ( widget ) 
00997                                           {
00998                                                  nsIWidget* temp = widget.get();
00999                                                  if ( nsWindow::EventIsInsideWindow((nsWindow*)temp, pos) ) 
01000                                                  {
01001                                                         rollup = PR_FALSE;
01002                                                         break;
01003                                                  }
01004                                           }
01005                                    } // foreach parent menu widget
01006                             } // if widgetChain
01007                      } // if rollup listener knows about menus
01008               } // if rollup
01009 
01010               if (rollup) 
01011               {
01012                      gRollupListener->Rollup();
01013 
01014                      if (gRollupConsumeRollupEvent) 
01015                      {
01016                             return PR_TRUE;
01017                      }
01018               }
01019        } // if rollup listeners registered
01020 
01021        return PR_FALSE;
01022 }
01023 
01024 
01025 //-------------------------------------------------------------------------
01026 //
01027 // IsVisible
01028 //
01029 // Return PR_TRUE if the whether the component is visible, PR_FALSE otherwise
01030 //-------------------------------------------------------------------------
01031 NS_METHOD nsWindow::IsVisible(PRBool & bState)
01032 {
01033        bState = mIsVisible;
01034        return NS_OK;
01035 }
01036 
01037 //-------------------------------------------------------------------------
01038 //
01039 // Sanity check potential move coordinates
01040 //
01041 //-------------------------------------------------------------------------
01042 NS_METHOD nsWindow::ConstrainPosition(PRBool aAllowSlop, PRInt32 *aX, PRInt32 *aY)
01043 {
01044        if (mIsTopWidgetWindow && mView->Window()) 
01045        {
01046               BScreen screen;
01047               // If no valid screen, just return
01048               if (! screen.IsValid()) return NS_OK;
01049               
01050               BRect screen_rect = screen.Frame();
01051               BRect win_bounds = mView->Window()->Frame();
01052 
01053 #ifdef DEBUG_CONSTRAIN_POSITION
01054               printf("ConstrainPosition: allowSlop=%s, x=%d, y=%d\n\tScreen :", (aAllowSlop?"T":"F"),*aX,*aY);
01055               screen_rect.PrintToStream();
01056               printf("\tWindow: ");
01057               win_bounds.PrintToStream();
01058 #endif
01059               
01060               if (aAllowSlop) 
01061               {
01062                      if (*aX < kWindowPositionSlop - win_bounds.IntegerWidth() + kWindowBorderWidth)
01063                             *aX = kWindowPositionSlop - win_bounds.IntegerWidth() + kWindowBorderWidth;
01064                      else if (*aX > screen_rect.IntegerWidth() - kWindowPositionSlop - kWindowBorderWidth)
01065                             *aX = screen_rect.IntegerWidth() - kWindowPositionSlop - kWindowBorderWidth;
01066                             
01067                      if (*aY < kWindowPositionSlop - win_bounds.IntegerHeight() + kWindowTitleBarHeight)
01068                             *aY = kWindowPositionSlop - win_bounds.IntegerHeight() + kWindowTitleBarHeight;
01069                      else if (*aY > screen_rect.IntegerHeight() - kWindowPositionSlop - kWindowBorderWidth)
01070                             *aY = screen_rect.IntegerHeight() - kWindowPositionSlop - kWindowBorderWidth;
01071                             
01072               } 
01073               else 
01074               {
01075                      
01076                      if (*aX < kWindowBorderWidth)
01077                             *aX = kWindowBorderWidth;
01078                      else if (*aX > screen_rect.IntegerWidth() - win_bounds.IntegerWidth() - kWindowBorderWidth)
01079                             *aX = screen_rect.IntegerWidth() - win_bounds.IntegerWidth() - kWindowBorderWidth;
01080                             
01081                      if (*aY < kWindowTitleBarHeight)
01082                             *aY = kWindowTitleBarHeight;
01083                      else if (*aY > screen_rect.IntegerHeight() - win_bounds.IntegerHeight() - kWindowBorderWidth)
01084                             *aY = screen_rect.IntegerHeight() - win_bounds.IntegerHeight() - kWindowBorderWidth;
01085               }
01086        }
01087        return NS_OK;
01088 }
01089 
01090 void nsWindow::HideKids(PRBool state)     
01091 {
01092        for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) 
01093        {
01094               nsWindow *childWidget = NS_STATIC_CAST(nsWindow*, kid);
01095               nsRect kidrect = ((nsWindow *)kid)->mBounds;
01096               //Don't bother about invisible
01097               if (mBounds.Intersects(kidrect))
01098               {      
01099                      childWidget->Show(!state);
01100               }
01101        }
01102 }
01103 
01104 //-------------------------------------------------------------------------
01105 //
01106 // Move this component
01107 //
01108 //-------------------------------------------------------------------------
01109 nsresult nsWindow::Move(PRInt32 aX, PRInt32 aY)
01110 {
01111        // Only perform this check for non-popup windows, since the positioning can
01112        // in fact change even when the x/y do not.  We always need to perform the
01113        // check. See bug #97805 for details.
01114        if (mWindowType != eWindowType_popup && (mBounds.x == aX) && (mBounds.y == aY))
01115        {
01116               // Nothing to do, since it is already positioned correctly.
01117               return NS_OK;    
01118        }
01119 
01120 
01121        // Set cached value for lightweight and printing
01122        mBounds.x = aX;
01123        mBounds.y = aY;
01124 
01125        // We may reset children visibility here, but it needs special care
01126        // - see comment 18 in Bug 311651. More sofisticated code needed.
01127 
01128        // until we lack separate window and widget, we "cannot" move BWindow without BView
01129        if(mView && mView->LockLooper())
01130        {
01131               if(mView->Parent() || !mView->Window())
01132                      mView->MoveTo(aX, aY);
01133               else
01134                      ((nsWindowBeOS *)mView->Window())->MoveTo(aX, aY);
01135                      
01136               mView->UnlockLooper();
01137        }
01138 
01139        OnMove(aX,aY);
01140 
01141        return NS_OK;
01142 }
01143 
01144 
01145 
01146 //-------------------------------------------------------------------------
01147 //
01148 // Resize this component
01149 //
01150 //-------------------------------------------------------------------------
01151 NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
01152 {
01153 
01154        if (aWidth < 0 || aHeight < 0)
01155               return NS_OK;
01156 
01157        mBounds.width  = aWidth;
01158        mBounds.height = aHeight;
01159        
01160        // until we lack separate window and widget, we "cannot" resize BWindow without BView
01161        if (mView && mView->LockLooper())
01162        {
01163               if (mView->Parent() || !mView->Window())
01164                      mView->ResizeTo(aWidth - 1, aHeight - 1);
01165               else
01166                      ((nsWindowBeOS *)mView->Window())->ResizeTo(aWidth - 1, aHeight - 1);
01167 
01168               mView->UnlockLooper();
01169        }
01170 
01171 
01172        OnResize(mBounds);
01173        if (aRepaint)
01174               Update();
01175        return NS_OK;
01176 }
01177 
01178 //-------------------------------------------------------------------------
01179 //
01180 // Resize this component
01181 //
01182 //-------------------------------------------------------------------------
01183 NS_METHOD nsWindow::Resize(PRInt32 aX,
01184                            PRInt32 aY,
01185                            PRInt32 aWidth,
01186                            PRInt32 aHeight,
01187                            PRBool   aRepaint)
01188 {
01189        Move(aX,aY);
01190        Resize(aWidth,aHeight,aRepaint);
01191        return NS_OK;
01192 }
01193 
01194 NS_METHOD nsWindow::SetModal(PRBool aModal)
01195 {
01196        if(!(mView && mView->Window()))
01197               return NS_ERROR_FAILURE;
01198        if(aModal)
01199        {
01200               window_feel newfeel;
01201               switch(mBWindowFeel)
01202               {
01203                      case B_FLOATING_SUBSET_WINDOW_FEEL:
01204                             newfeel = B_MODAL_SUBSET_WINDOW_FEEL;
01205                             break;
01206                      case B_FLOATING_APP_WINDOW_FEEL:
01207                             newfeel = B_MODAL_APP_WINDOW_FEEL;
01208                             break;
01209                      case B_FLOATING_ALL_WINDOW_FEEL:
01210                             newfeel = B_MODAL_ALL_WINDOW_FEEL;
01211                             break;                      
01212                      default:
01213                             return NS_OK;
01214               }
01215               mView->Window()->SetFeel(newfeel);
01216        }
01217        else
01218        {
01219               mView->Window()->SetFeel(mBWindowFeel);
01220        }
01221        return NS_OK;
01222 }
01223 //-------------------------------------------------------------------------
01224 //
01225 // Enable/disable this component
01226 //
01227 //-------------------------------------------------------------------------
01228 NS_METHOD nsWindow::Enable(PRBool aState)
01229 {
01230        //TODO: Needs real corect implementation in future
01231        mEnabled = aState;
01232        return NS_OK;
01233 }
01234 
01235 
01236 NS_METHOD nsWindow::IsEnabled(PRBool *aState)
01237 {
01238        NS_ENSURE_ARG_POINTER(aState);
01239        // looks easy enough, but...
01240        *aState = mEnabled;
01241        return NS_OK;
01242 }
01243 
01244 //-------------------------------------------------------------------------
01245 //
01246 // Give the focus to this component
01247 //
01248 //-------------------------------------------------------------------------
01249 NS_METHOD nsWindow::SetFocus(PRBool aRaise)
01250 {
01251        //
01252        // Switch to the "main gui thread" if necessary... This method must
01253        // be executed on the "gui thread"...
01254        //
01255        nsToolkit* toolkit = (nsToolkit *)mToolkit;
01256        if (!toolkit->IsGuiThread()) 
01257        {
01258               uint32 args[1];
01259               args[0] = (uint32)aRaise;
01260               MethodInfo info(this, this, nsSwitchToUIThread::SET_FOCUS, 1, args);
01261               toolkit->CallMethod(&info);
01262               return NS_ERROR_FAILURE;
01263        }
01264        
01265        // Don't set focus on disabled widgets or popups
01266        if (!mEnabled || eWindowType_popup == mWindowType)
01267               return NS_OK;
01268               
01269        if (mView && mView->LockLooper())
01270        {
01271               if (mView->Window() && 
01272                   aRaise == PR_TRUE &&
01273                   eWindowType_popup != mWindowType && 
01274                        !mView->Window()->IsActive() && 
01275                        gLastActiveWindow != mView->Window())
01276                      mView->Window()->Activate(true);
01277                      
01278               mView->MakeFocus(true);
01279               mView->UnlockLooper();
01280               DispatchFocus(NS_GOTFOCUS);
01281        }
01282 
01283        return NS_OK;
01284 }
01285 
01286 //-------------------------------------------------------------------------
01287 //
01288 // Get this component size and position in screen coordinates
01289 //
01290 //-------------------------------------------------------------------------    
01291 NS_IMETHODIMP nsWindow::GetScreenBounds(nsRect &aRect)
01292 {
01293        // A window's Frame() value is cached, so locking is not needed
01294        if (mView && mView->Window()) 
01295        {
01296               BRect r = mView->Window()->Frame();
01297               aRect.x = nscoord(r.left);
01298               aRect.y = nscoord(r.top);
01299               aRect.width  = r.IntegerWidth()+1;
01300               aRect.height = r.IntegerHeight()+1;
01301        } 
01302        else 
01303        {
01304               aRect = mBounds;
01305        }
01306        return NS_OK;
01307 }  
01308 
01309 //-------------------------------------------------------------------------
01310 //
01311 // Set the background/foreground color
01312 //
01313 //-------------------------------------------------------------------------
01314 NS_METHOD nsWindow::SetBackgroundColor(const nscolor &aColor)
01315 {
01316        nsBaseWidget::SetBackgroundColor(aColor);
01317 
01318        // We set the background of toplevel windows so that resizing doesn't show thru
01319        // to Desktop and resizing artifacts. Child windows has transparent background.
01320        if (!mIsTopWidgetWindow)
01321               return NS_OK;
01322 
01323        if (mView && mView->LockLooper())
01324        {
01325               mView->SetViewColor(NS_GET_R(aColor), NS_GET_G(aColor), NS_GET_B(aColor), NS_GET_A(aColor));
01326               mView->UnlockLooper();
01327        }
01328        return NS_OK;
01329 }
01330 
01331 //-------------------------------------------------------------------------
01332 //
01333 // Get this component font
01334 //
01335 //-------------------------------------------------------------------------
01336 nsIFontMetrics* nsWindow::GetFont(void)
01337 {
01338        return mFontMetrics;
01339 }
01340 
01341 
01342 //-------------------------------------------------------------------------
01343 //
01344 // Set this component font
01345 //
01346 //-------------------------------------------------------------------------
01347 NS_METHOD nsWindow::SetFont(const nsFont &aFont)
01348 {
01349   // Cache Font for owner draw
01350        NS_IF_RELEASE(mFontMetrics);
01351        if (mContext)
01352               mContext->GetMetricsFor(aFont, mFontMetrics);
01353        return NS_OK;
01354 }
01355 
01356 
01357 //-------------------------------------------------------------------------
01358 //
01359 // Set this component cursor
01360 //
01361 //-------------------------------------------------------------------------
01362 
01363 NS_METHOD nsWindow::SetCursor(nsCursor aCursor)
01364 {
01365        if (!mView)
01366               return NS_ERROR_FAILURE;
01367 
01368 // mCursor isn't always right.  Scrollbars and others change it, too.
01369 // If we want this optimization we need a better way to do it.
01370 // See bug 403406 for more information.
01371 //     if (aCursor != mCursor) 
01372 //     {
01373               BCursor const *newCursor = B_CURSOR_SYSTEM_DEFAULT;
01374               
01375               // Check to see if the array has been loaded, if not, do it.
01376               if (gCursorArray.Count() == 0) 
01377               {
01378                      gCursorArray.InsertElementAt((void*) new BCursor(cursorHyperlink),0);
01379                      gCursorArray.InsertElementAt((void*) new BCursor(cursorHorizontalDrag),1);
01380                      gCursorArray.InsertElementAt((void*) new BCursor(cursorVerticalDrag),2);
01381                      gCursorArray.InsertElementAt((void*) new BCursor(cursorUpperLeft),3);
01382                      gCursorArray.InsertElementAt((void*) new BCursor(cursorLowerRight),4);
01383                      gCursorArray.InsertElementAt((void*) new BCursor(cursorUpperRight),5);
01384                      gCursorArray.InsertElementAt((void*) new BCursor(cursorLowerLeft),6);
01385                      gCursorArray.InsertElementAt((void*) new BCursor(cursorCrosshair),7);
01386                      gCursorArray.InsertElementAt((void*) new BCursor(cursorHelp),8);
01387                      gCursorArray.InsertElementAt((void*) new BCursor(cursorGrab),9);
01388                      gCursorArray.InsertElementAt((void*) new BCursor(cursorGrabbing),10);
01389                      gCursorArray.InsertElementAt((void*) new BCursor(cursorCopy),11);
01390                      gCursorArray.InsertElementAt((void*) new BCursor(cursorAlias),12);
01391                      gCursorArray.InsertElementAt((void*) new BCursor(cursorWatch2),13);
01392                      gCursorArray.InsertElementAt((void*) new BCursor(cursorCell),14);
01393                      gCursorArray.InsertElementAt((void*) new BCursor(cursorZoomIn),15);
01394                      gCursorArray.InsertElementAt((void*) new BCursor(cursorZoomOut),16);
01395                      gCursorArray.InsertElementAt((void*) new BCursor(cursorLeft),17);
01396                      gCursorArray.InsertElementAt((void*) new BCursor(cursorRight),18);
01397                      gCursorArray.InsertElementAt((void*) new BCursor(cursorTop),19);
01398                      gCursorArray.InsertElementAt((void*) new BCursor(cursorBottom),20);
01399               }
01400 
01401               switch (aCursor) 
01402               {
01403                      case eCursor_standard:
01404                      case eCursor_move:
01405                             newCursor = B_CURSOR_SYSTEM_DEFAULT;
01406                             break;
01407        
01408                      case eCursor_select:
01409                             newCursor = B_CURSOR_I_BEAM;
01410                             break;
01411        
01412                      case eCursor_hyperlink:
01413                             newCursor = (BCursor *)gCursorArray.SafeElementAt(0);
01414                             break;
01415        
01416                      case eCursor_n_resize:
01417                             newCursor = (BCursor *)gCursorArray.SafeElementAt(19);
01418                             break;
01419 
01420                      case eCursor_s_resize:
01421                             newCursor = (BCursor *)gCursorArray.SafeElementAt(20);
01422                             break;
01423        
01424                      case eCursor_w_resize:
01425                             newCursor = (BCursor *)gCursorArray.SafeElementAt(17);
01426                             break;
01427 
01428                      case eCursor_e_resize:
01429                             newCursor = (BCursor *)gCursorArray.SafeElementAt(18);
01430                             break;
01431        
01432                      case eCursor_nw_resize:
01433                             newCursor = (BCursor *)gCursorArray.SafeElementAt(3);
01434                             break;
01435        
01436                      case eCursor_se_resize:
01437                             newCursor = (BCursor *)gCursorArray.SafeElementAt(4);
01438                             break;
01439        
01440                      case eCursor_ne_resize:
01441                             newCursor = (BCursor *)gCursorArray.SafeElementAt(5);
01442                             break;
01443        
01444                      case eCursor_sw_resize:
01445                             newCursor = (BCursor *)gCursorArray.SafeElementAt(6);
01446                             break;
01447        
01448                      case eCursor_crosshair:
01449                             newCursor = (BCursor *)gCursorArray.SafeElementAt(7);
01450                             break;
01451        
01452                      case eCursor_help:
01453                             newCursor = (BCursor *)gCursorArray.SafeElementAt(8);
01454                             break;
01455        
01456                      case eCursor_copy:
01457                             newCursor = (BCursor *)gCursorArray.SafeElementAt(11);
01458                             break;
01459        
01460                      case eCursor_alias:
01461                             newCursor = (BCursor *)gCursorArray.SafeElementAt(12);
01462                             break;
01463 
01464                      case eCursor_context_menu:
01465                             // XXX: No suitable cursor, needs implementing
01466                             break;
01467                             
01468                      case eCursor_cell:
01469                             newCursor = (BCursor *)gCursorArray.SafeElementAt(14);
01470                             break;
01471 
01472                      case eCursor_grab:
01473                             newCursor = (BCursor *)gCursorArray.SafeElementAt(9);
01474                             break;
01475        
01476                      case eCursor_grabbing:
01477                             newCursor = (BCursor *)gCursorArray.SafeElementAt(10);
01478                             break;
01479        
01480                      case eCursor_wait:
01481                      case eCursor_spinning:
01482                             newCursor = (BCursor *)gCursorArray.SafeElementAt(13);
01483                             break;
01484        
01485                      case eCursor_zoom_in:
01486                             newCursor = (BCursor *)gCursorArray.SafeElementAt(15);
01487                             break;
01488 
01489                      case eCursor_zoom_out:
01490                             newCursor = (BCursor *)gCursorArray.SafeElementAt(16);
01491                             break;
01492 
01493                      case eCursor_not_allowed:
01494                      case eCursor_no_drop:
01495                             // XXX: No suitable cursor, needs implementing
01496                             break;
01497 
01498                      case eCursor_col_resize:
01499                             // XXX not 100% appropriate perhaps
01500                             newCursor = (BCursor *)gCursorArray.SafeElementAt(1);
01501                             break;
01502 
01503                      case eCursor_row_resize:
01504                             // XXX not 100% appropriate perhaps
01505                             newCursor = (BCursor *)gCursorArray.SafeElementAt(2);
01506                             break;
01507 
01508                      case eCursor_vertical_text:
01509                             // XXX not 100% appropriate perhaps
01510                             newCursor = B_CURSOR_I_BEAM;
01511                             break;
01512 
01513                      case eCursor_all_scroll:
01514                             // XXX: No suitable cursor, needs implementing
01515                             break;
01516 
01517                      case eCursor_nesw_resize:
01518                             // XXX not 100% appropriate perhaps
01519                             newCursor = (BCursor *)gCursorArray.SafeElementAt(1);
01520                             break;
01521 
01522                      case eCursor_nwse_resize:
01523                             // XXX not 100% appropriate perhaps
01524                             newCursor = (BCursor *)gCursorArray.SafeElementAt(1);
01525                             break;
01526 
01527                      case eCursor_ns_resize:
01528                             newCursor = (BCursor *)gCursorArray.SafeElementAt(2);
01529                             break;
01530 
01531                      case eCursor_ew_resize:
01532                             newCursor = (BCursor *)gCursorArray.SafeElementAt(1);
01533                             break;
01534 
01535                      default:
01536                             NS_ASSERTION(0, "Invalid cursor type");
01537                             break;
01538               }
01539               NS_ASSERTION(newCursor != nsnull, "Cursor not stored in array properly!");
01540               mCursor = aCursor;
01541               be_app->SetCursor(newCursor, true);
01542 //     }
01543        return NS_OK;
01544 }
01545 
01546 //-------------------------------------------------------------------------
01547 //
01548 // Invalidate this component visible area
01549 //
01550 //-------------------------------------------------------------------------
01551 NS_METHOD nsWindow::Invalidate(PRBool aIsSynchronous)
01552 {
01553        nsresult rv = NS_ERROR_FAILURE;
01554        // Asynchronous painting is performed with via nsViewBeOS::Draw() call and its message queue. 
01555        // All update rects are collected in nsViewBeOS member  "paintregion".
01556        // Flushing of paintregion happens in nsViewBeOS::GetPaintRegion(),
01557        // cleanup  - in nsViewBeOS::Validate(), called in OnPaint().
01558        BRegion reg;
01559        reg.MakeEmpty();
01560        if (mView && mView->LockLooper())
01561        {
01562               if (PR_TRUE == aIsSynchronous)
01563               {
01564                      mView->paintregion.Include(mView->Bounds());
01565                      reg.Include(mView->Bounds());
01566               }
01567               else
01568               {
01569                      mView->Draw(mView->Bounds());
01570                      rv = NS_OK;
01571               }
01572               mView->UnlockLooper();
01573        }
01574        // Instant repaint.
01575        if (PR_TRUE == aIsSynchronous)
01576               rv = OnPaint(&reg);
01577        return rv;
01578 }
01579 
01580 //-------------------------------------------------------------------------
01581 //
01582 // Invalidate this component visible area
01583 //
01584 //-------------------------------------------------------------------------
01585 NS_METHOD nsWindow::Invalidate(const nsRect & aRect, PRBool aIsSynchronous)
01586 {
01587        nsresult rv = NS_ERROR_FAILURE;
01588        // Very temporary region for double accounting.
01589        BRegion reg;
01590        reg.MakeEmpty();
01591        if (mView && mView->LockLooper()) 
01592        {
01593               BRect  r(aRect.x, 
01594                             aRect.y, 
01595                             aRect.x + aRect.width - 1, 
01596                             aRect.y + aRect.height - 1);
01597               if (PR_TRUE == aIsSynchronous)
01598               {
01599                      mView->paintregion.Include(r);
01600                      reg.Include(r);
01601               }
01602               else
01603               {
01604                      // we use Draw() instead direct addition to paintregion,
01605                      // as it sets queue of notification messages for painting.
01606                      mView->Draw(r);
01607                      rv = NS_OK;
01608               }
01609               mView->UnlockLooper();
01610        }
01611        // Instant repaint - for given rect only. 
01612        // Don't repaint area which isn't marked here for synchronous repaint explicitly.
01613        // BRegion "reg" (equal to aRect) will be substracted from paintregion in OnPaint().
01614        if (PR_TRUE == aIsSynchronous)
01615               rv = OnPaint(&reg);
01616        return rv;
01617 }
01618 
01619 //-------------------------------------------------------------------------
01620 //
01621 // Invalidate this component visible area
01622 //
01623 //-------------------------------------------------------------------------
01624 NS_IMETHODIMP nsWindow::InvalidateRegion(const nsIRegion *aRegion, PRBool aIsSynchronous)
01625 {
01626        
01627        nsRegionRectSet *rectSet = nsnull;
01628        if (!aRegion)
01629               return NS_ERROR_FAILURE;
01630        nsresult rv = ((nsIRegion *)aRegion)->GetRects(&rectSet);
01631        if (NS_FAILED(rv))
01632               return rv;
01633        BRegion reg;
01634        reg.MakeEmpty();
01635        if (mView && mView->LockLooper())
01636        {
01637               for (PRUint32 i=0; i< rectSet->mRectsLen; ++i)
01638               {
01639                      BRect br(rectSet->mRects[i].x, rectSet->mRects[i].y,
01640                                    rectSet->mRects[i].x + rectSet->mRects[i].width-1,
01641                                    rectSet->mRects[i].y + rectSet->mRects[i].height -1);
01642                      if (PR_TRUE == aIsSynchronous)
01643                      {
01644                             mView->paintregion.Include(br);
01645                             reg.Include(br);
01646                      }
01647                      else
01648                      {
01649                             mView->Draw(br);
01650                             rv = NS_OK;
01651                      }
01652               }
01653               mView->UnlockLooper();
01654        }
01655        // Instant repaint - for given region only. 
01656        // BRegion "reg"(equal to aRegion) will be substracted from paintregion in OnPaint().
01657        if (PR_TRUE == aIsSynchronous)
01658               rv = OnPaint(&reg);
01659 
01660        return rv;
01661 }
01662 
01663 //-------------------------------------------------------------------------
01664 //
01665 // Force a synchronous repaint of the window
01666 //
01667 //-------------------------------------------------------------------------
01668 NS_IMETHODIMP nsWindow::Update()
01669 {
01670        nsresult rv = NS_ERROR_FAILURE;
01671        //Switching scrolling trigger off
01672        mIsScrolling = PR_FALSE;
01673        if (mWindowType == eWindowType_child)
01674               return NS_OK;
01675        // Getting whole paint cache filled in native and non-native Invalidate() calls.
01676        // Sending it all to view manager via OnPaint()
01677        BRegion reg;
01678        reg.MakeEmpty();
01679        if(mView && mView->LockLooper())
01680        {
01681               //Flushing native pending updates*/
01682               if (mView->Window())
01683                      mView->Window()->UpdateIfNeeded();
01684               bool nonempty = mView->GetPaintRegion(&reg);
01685               mView->UnlockLooper();
01686               if (nonempty)
01687                      rv = OnPaint(&reg);
01688        }
01689        return rv;
01690 }
01691 
01692 //-------------------------------------------------------------------------
01693 //
01694 // Return some native data according to aDataType
01695 //
01696 //-------------------------------------------------------------------------
01697 void* nsWindow::GetNativeData(PRUint32 aDataType)
01698 {
01699        if (!mView)
01700               return NULL;  
01701        switch(aDataType) 
01702        {
01703               case NS_NATIVE_WINDOW:
01704                      return (void *)(mView->Window());
01705               case NS_NATIVE_WIDGET:
01706               case NS_NATIVE_PLUGIN_PORT:
01707                      return (void *)((nsViewBeOS *)mView);
01708               case NS_NATIVE_GRAPHIC:
01709                      return (void *)((BView *)mView);
01710               case NS_NATIVE_COLORMAP:
01711               default:
01712                      break;
01713        }
01714        return NULL;
01715 }
01716 
01717 //-------------------------------------------------------------------------
01718 //
01719 // Set the colormap of the window
01720 //
01721 //-------------------------------------------------------------------------
01722 NS_METHOD nsWindow::SetColorMap(nsColorMap *aColorMap)
01723 {
01724        NS_WARNING("nsWindow::SetColorMap - not implemented");
01725        return NS_OK;
01726 }
01727 
01728 
01729 //-------------------------------------------------------------------------
01730 //
01731 // Scroll the bits of a window
01732 //
01733 //-------------------------------------------------------------------------
01734 NS_METHOD nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect)
01735 {
01736        // Switching trigger on
01737        mIsScrolling = PR_TRUE;
01738        //Preventing main view invalidation loop-chain  when children are moving
01739        //by by hiding children nsWidgets.
01740        //Maybe this method must be used wider, in move and resize chains
01741        // and implemented in BeginResizingChildren or in Reset*Visibility() methods
01742        //Children will be unhidden in ::Update() when called by other than gkview::Scroll() method.
01743        HideKids(PR_TRUE);
01744        if (mView && mView->LockLooper())
01745        {
01746               // Kill any attempt to invalidate until scroll is finished
01747               mView->SetVisible(false);
01748        
01749               BRect src;
01750               BRect b = mView->Bounds();
01751 
01752               if (aClipRect)
01753               {
01754                      src.left = aClipRect->x;
01755                      src.top = aClipRect->y;
01756                      src.right = aClipRect->XMost() - 1;
01757                      src.bottom = aClipRect->YMost() - 1;
01758               }
01759               else
01760               {
01761                      src = b;
01762               }
01763               // Restricting source by on-screen part of BView
01764               if (mView->Window())
01765               {
01766                      BRect screenframe = mView->ConvertFromScreen(BScreen(mView->Window()).Frame());
01767                      src = src & screenframe;
01768                      if (mView->Parent())
01769                      {
01770                             BRect parentframe = mView->ConvertFromParent(mView->Parent()->Frame());
01771                             src = src & parentframe;
01772                      }
01773               }
01774 
01775               BRegion       invalid;
01776               invalid.Include(src);
01777               // Next source clipping check, for same level siblings
01778               if ( BView *v = mView->Parent() )
01779               {
01780                      for (BView *child = v->ChildAt(0); child; child = child->NextSibling() )
01781                      {
01782                             BRect siblingframe = mView->ConvertFromParent(child->Frame());
01783                             if (child != mView && child->Parent() != mView)
01784                             {
01785                                    invalid.Exclude(siblingframe);
01786                                    mView->paintregion.Exclude(siblingframe);
01787                             }
01788                      }
01789                      src = invalid.Frame();
01790               }
01791 
01792               // make sure we only reference visible bits
01793               // so we don't trigger a BView invalidate
01794 
01795               if (src.left + aDx < 0)
01796                      src.left = -aDx;
01797               if (src.right + aDx > b.right)
01798                      src.right = b.right - aDx;
01799               if (src.top + aDy < 0)
01800                      src.top = -aDy;
01801               if (src.bottom + aDy > b.bottom)
01802                      src.bottom = b.bottom - aDy;
01803               
01804               BRect dest = src.OffsetByCopy(aDx, aDy);
01805               mView->ConstrainClippingRegion(&invalid);
01806               // Moving visible content 
01807               if (src.IsValid() && dest.IsValid())
01808                      mView->CopyBits(src, dest);
01809 
01810               invalid.Exclude(dest);      
01811               // Native paintregion needs shifting too, it is very important action
01812               // (as app_server doesn't know about Mozilla viewmanager tricks) -
01813               // it allows proper update after scroll for areas covered by other windows.
01814               mView->paintregion.OffsetBy(aDx, aDy);
01815               mView->ConstrainClippingRegion(&invalid);
01816               // Time to silently move now invisible children
01817               for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) 
01818               {
01819                      nsWindow *childWidget = NS_STATIC_CAST(nsWindow*, kid);
01820                      // No need to Lock/UnlockLooper with GetBounds() and Move() methods
01821                      // using cached values and native MoveBy() instead
01822                      nsRect bounds = childWidget->mBounds;
01823                      bounds.x += aDx;
01824                      bounds.y += aDy;
01825                      childWidget->Move(bounds.x, bounds.y);
01826                      BView *child = ((BView *)kid->GetNativeData(NS_NATIVE_WIDGET));
01827                      if (child)
01828                      {
01829                             //There is native child
01830                             mView->paintregion.Exclude(child->Frame());
01831                      }
01832               }                    
01833 
01834               // Painting calculated region now,
01835               // letting Update() to paint remaining content of paintregion
01836               OnPaint(&invalid);
01837               HideKids(PR_FALSE);
01838               // re-allow updates
01839               mView->SetVisible(true);
01840               mView->UnlockLooper();
01841               
01842        }
01843        return NS_OK;
01844 }
01845 
01846 
01847 //-------------------------------------------------------------------------
01848 //
01849 // Every function that needs a thread switch goes through this function
01850 // by calling SendMessage (..WM_CALLMETHOD..) in nsToolkit::CallMethod.
01851 //
01852 //-------------------------------------------------------------------------
01853 bool nsWindow::CallMethod(MethodInfo *info)
01854 {
01855        bool bRet = TRUE;
01856 
01857        switch (info->methodId)
01858        {
01859        case nsSwitchToUIThread::CREATE:
01860               NS_ASSERTION(info->nArgs == 7, "Wrong number of arguments to CallMethod");
01861               Create((nsIWidget*)(info->args[0]),
01862                      (nsRect&)*(nsRect*)(info->args[1]),
01863                      (EVENT_CALLBACK)(info->args[2]),
01864                      (nsIDeviceContext*)(info->args[3]),
01865                      (nsIAppShell *)(info->args[4]),
01866                      (nsIToolkit*)(info->args[5]),
01867                      (nsWidgetInitData*)(info->args[6]));
01868               break;
01869 
01870        case nsSwitchToUIThread::CREATE_NATIVE:
01871               NS_ASSERTION(info->nArgs == 7, "Wrong number of arguments to CallMethod");
01872               Create((nsNativeWidget)(info->args[0]),
01873                      (nsRect&)*(nsRect*)(info->args[1]),
01874                      (EVENT_CALLBACK)(info->args[2]),
01875                      (nsIDeviceContext*)(info->args[3]),
01876                      (nsIAppShell *)(info->args[4]),
01877                      (nsIToolkit*)(info->args[5]),
01878                      (nsWidgetInitData*)(info->args[6]));
01879               break;
01880 
01881        case nsSwitchToUIThread::DESTROY:
01882               NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
01883               Destroy();
01884               break;
01885 
01886        case nsSwitchToUIThread::CLOSEWINDOW :
01887               {
01888                      NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
01889                      if (eWindowType_popup != mWindowType && eWindowType_child != mWindowType)
01890                             DealWithPopups(nsSwitchToUIThread::CLOSEWINDOW,nsPoint(0,0));
01891                             for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) 
01892                             {
01893                                    nsWindow *childWidget = NS_STATIC_CAST(nsWindow*, kid);
01894                                    BWindow* kidwindow = (BWindow *)kid->GetNativeData(NS_NATIVE_WINDOW);
01895                                    if (kidwindow)
01896                                    {
01897                                           // PostMessage() is unsafe, so using BMessenger
01898                                           BMessenger bm(kidwindow);
01899                                           bm.SendMessage(B_QUIT_REQUESTED);
01900                                    }
01901                             }
01902                      DispatchStandardEvent(NS_DESTROY);
01903               }
01904               break;
01905 
01906        case nsSwitchToUIThread::SET_FOCUS:
01907               NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
01908               if (!mEnabled)
01909                      return false;
01910               SetFocus(((PRBool *)info->args)[0]);
01911               break;
01912 
01913 #ifdef DEBUG_FOCUS
01914        case nsSwitchToUIThread::GOT_FOCUS:
01915               NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
01916               if (!mEnabled)
01917                      return false;
01918               if ((uint32)info->args[0] != (uint32)mView)
01919                      printf("Wrong view to get focus\n");*/
01920               break;
01921 #endif
01922        case nsSwitchToUIThread::KILL_FOCUS:
01923               NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
01924               if ((uint32)info->args[0] == (uint32)mView)
01925                      DispatchFocus(NS_LOSTFOCUS);
01926 #ifdef DEBUG_FOCUS
01927               else
01928                      printf("Wrong view to de-focus\n");
01929 #endif
01930 #if defined(BeIME)
01931               nsIMEBeOS::GetIME()->DispatchCancelIME();
01932               if (mView && mView->LockLooper())
01933               {
01934                      mView->SetFlags(mView->Flags() & ~B_NAVIGABLE);
01935                      mView->UnlockLooper();
01936               }
01937 #endif
01938               break;
01939 
01940        case nsSwitchToUIThread::BTNCLICK :
01941               {
01942                      NS_ASSERTION(info->nArgs == 5, "Wrong number of arguments to CallMethod");
01943                      if (!mEnabled)
01944                             return false;
01945                      // close popup when clicked outside of the popup window
01946                      uint32 eventID = ((int32 *)info->args)[0];
01947                      PRBool rollup = PR_FALSE;
01948 
01949                      if ((eventID == NS_MOUSE_LEFT_BUTTON_DOWN ||
01950                              eventID == NS_MOUSE_RIGHT_BUTTON_DOWN ||
01951                              eventID == NS_MOUSE_MIDDLE_BUTTON_DOWN) &&
01952                              mView && mView->LockLooper())
01953                      {
01954                             BPoint p(((int32 *)info->args)[1], ((int32 *)info->args)[2]);
01955                             mView->ConvertToScreen(&p);
01956                             rollup = DealWithPopups(nsSwitchToUIThread::ONMOUSE, nsPoint(p.x, p.y));
01957                             mView->UnlockLooper();
01958                      }
01959                      // Drop click event - bug 314330
01960                      if (rollup)
01961                             return false;
01962                      DispatchMouseEvent(((int32 *)info->args)[0],
01963                                         nsPoint(((int32 *)info->args)[1], ((int32 *)info->args)[2]),
01964                                         ((int32 *)info->args)[3],
01965                                         ((int32 *)info->args)[4]);
01966 
01967                      if (((int32 *)info->args)[0] == NS_MOUSE_RIGHT_BUTTON_DOWN)
01968                      {
01969                             DispatchMouseEvent (NS_CONTEXTMENU,
01970                                                 nsPoint(((int32 *)info->args)[1], ((int32 *)info->args)[2]),
01971                                                 ((int32 *)info->args)[3],
01972                                                 ((int32 *)info->args)[4]);
01973                      }
01974               }
01975               break;
01976 
01977        case nsSwitchToUIThread::ONWHEEL :
01978               {
01979                      NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
01980                      // avoid mistargeting
01981                      if ((uint32)info->args[0] != (uint32)mView)
01982                             return false;
01983                      BPoint cursor(0,0);
01984                      uint32 buttons;
01985                      BPoint delta;
01986                      if (mView && mView->LockLooper())
01987                      {
01988                             mView->GetMouse(&cursor, &buttons, false);
01989                             delta = mView->GetWheel();
01990                             mView->UnlockLooper();
01991                      }
01992                      else
01993                             return false;
01994                      // BeOS TwoWheel input-filter is bit buggy atm, generating sometimes X-wheel with no reason,
01995                      // so we're setting priority for Y-wheel.
01996                      // Also hardcoding here _system_ scroll-step value to 3 lines.
01997                      if (nscoord(delta.y) != 0)
01998                      {
01999                             OnWheel(nsMouseScrollEvent::kIsVertical, buttons, cursor, nscoord(delta.y)*3);
02000                      }
02001                      else if(nscoord(delta.x) != 0)
02002                             OnWheel(nsMouseScrollEvent::kIsHorizontal, buttons, cursor, nscoord(delta.x)*3);
02003               }
02004               break;
02005 
02006        case nsSwitchToUIThread::ONKEY :
02007               NS_ASSERTION(info->nArgs == 6, "Wrong number of arguments to CallMethod");
02008               if (((int32 *)info->args)[0] == NS_KEY_DOWN)
02009               {
02010                      OnKeyDown(((int32 *)info->args)[0],
02011                                (const char *)(&((uint32 *)info->args)[1]), ((int32 *)info->args)[2],
02012                                ((uint32 *)info->args)[3], ((uint32 *)info->args)[4], ((int32 *)info->args)[5]);
02013               }
02014               else
02015               {
02016                      if (((int32 *)info->args)[0] == NS_KEY_UP)
02017                      {
02018                             OnKeyUp(((int32 *)info->args)[0],
02019                                     (const char *)(&((uint32 *)info->args)[1]), ((int32 *)info->args)[2],
02020                                     ((uint32 *)info->args)[3], ((uint32 *)info->args)[4], ((int32 *)info->args)[5]);
02021                      }
02022               }
02023               break;
02024 
02025        case nsSwitchToUIThread::ONPAINT :
02026               NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
02027               {
02028                      if ((uint32)mView != ((uint32 *)info->args)[0])
02029                             return false;
02030                      BRegion reg;
02031                      reg.MakeEmpty();
02032                      if(mView && mView->LockLooper())
02033                      {
02034                             bool nonempty = mView->GetPaintRegion(&reg);
02035                             mView->UnlockLooper();
02036                             if (nonempty)
02037                                    OnPaint(&reg);
02038                      }
02039               }
02040               break;
02041 
02042        case nsSwitchToUIThread::ONRESIZE :
02043               {
02044                      NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
02045                      if (eWindowType_popup != mWindowType && eWindowType_child != mWindowType)
02046                             DealWithPopups(nsSwitchToUIThread::ONRESIZE,nsPoint(0,0));
02047                      // This should be called only from BWindow::FrameResized()
02048                      if (!mIsTopWidgetWindow  || !mView  || !mView->Window())
02049                             return false;
02050                      
02051                      nsRect r(mBounds);
02052                      if (mView->LockLooper())
02053                      {
02054                             BRect br = mView->Frame();
02055                             r.x = nscoord(br.left);
02056                             r.y = nscoord(br.top);
02057                             r.width  = br.IntegerWidth() + 1;
02058                             r.height = br.IntegerHeight() + 1;
02059                             ((nsWindowBeOS *)mView->Window())->fJustGotBounds = true;
02060                             mView->UnlockLooper();
02061                      }
02062 
02063                      OnResize(r);
02064               }
02065               break;
02066 
02067        case nsSwitchToUIThread::ONMOUSE :
02068               {
02069               NS_ASSERTION(info->nArgs == 1, "Wrong number of arguments to CallMethod");
02070                      if (!mEnabled)
02071                             return false;
02072                      BPoint cursor(0,0);
02073                      uint32 buttons;
02074                      
02075                      if(mView && mView->LockLooper())
02076                      {
02077                             mView->GetMouse(&cursor, &buttons, true);
02078                             mView->UnlockLooper();
02079                      }
02080 
02081                      DispatchMouseEvent(((int32 *)info->args)[0],
02082                                         nsPoint(int32(cursor.x), int32(cursor.y)),
02083                                         0,
02084                                     modifiers());
02085               }
02086               break;
02087 
02088        case nsSwitchToUIThread::ONDROP :
02089               {
02090                      NS_ASSERTION(info->nArgs == 4, "Wrong number of arguments to CallMethod");
02091 
02092                      nsMouseEvent event(PR_TRUE, (int32)  info->args[0], this, nsMouseEvent::eReal);
02093                      nsPoint point(((int32 *)info->args)[1], ((int32 *)info->args)[2]);
02094                      InitEvent (event, &point);
02095                      uint32 mod = (uint32) info->args[3];
02096                      event.isShift   = mod & B_SHIFT_KEY;
02097                      event.isControl = mod & B_CONTROL_KEY;
02098                      event.isAlt     = mod & B_COMMAND_KEY;
02099                      event.isMeta     = mod & B_OPTION_KEY;
02100 
02101                      // Setting drag action, must be done before event dispatch
02102                      nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
02103                      if (dragService)
02104                      {
02105                             nsCOMPtr<nsIDragSession> dragSession;
02106                             dragService->GetCurrentSession(getter_AddRefs(dragSession));
02107                             if (dragSession)
02108                             {
02109                                    // Original action mask stored in dragsession.
02110                                    // For native events such mask must be set in nsDragServiceBeOS::UpdateDragMessageIfNeeded()
02111        
02112                                    PRUint32 action_mask = 0;
02113                                    dragSession->GetDragAction(&action_mask);
02114                                    PRUint32 action = nsIDragService::DRAGDROP_ACTION_MOVE;
02115                                    if (mod & B_OPTION_KEY)
02116                                    {
02117                                           if (mod & B_COMMAND_KEY)
02118                                                  action = nsIDragService::DRAGDROP_ACTION_LINK & action_mask;
02119                                           else
02120                                                  action = nsIDragService::DRAGDROP_ACTION_COPY & action_mask;
02121                                    }
02122                                    dragSession->SetDragAction(action);
02123                             }
02124                      }
02125 
02126                      DispatchWindowEvent(&event);
02127                      NS_RELEASE(event.widget);
02128 
02129                      if (dragService)
02130                             dragService->EndDragSession();
02131 
02132               }
02133               break;
02134 
02135        case nsSwitchToUIThread::ONACTIVATE:
02136               NS_ASSERTION(info->nArgs == 2, "Wrong number of arguments to CallMethod");
02137               if (!mEnabled || eWindowType_popup == mWindowType || 0 == mView->Window())
02138                      return false;
02139               if ((BWindow *)info->args[1] != mView->Window())
02140                      return false;
02141               if (mEventCallback || eWindowType_child == mWindowType )
02142               {
02143                      bool active = (bool)info->args[0];
02144                      if (!active) 
02145                      {
02146                             if (eWindowType_dialog == mWindowType || 
02147                                 eWindowType_toplevel == mWindowType)
02148                                    DealWithPopups(nsSwitchToUIThread::ONACTIVATE,nsPoint(0,0));
02149                             //Testing if BWindow is really deactivated.
02150                             if (!mView->Window()->IsActive())
02151                             {
02152                                    // BeOS is poor in windows hierarchy and variations support. In lot of aspects.
02153                                    // Here is workaround for flacky Activate() handling for B_FLOATING windows.
02154                                    // We should force parent (de)activation to allow main window to regain control after closing floating dialog.
02155                                    if (mWindowParent &&  mView->Window()->IsFloating())
02156                                           mWindowParent->DispatchFocus(NS_ACTIVATE);
02157 
02158                                    DispatchFocus(NS_DEACTIVATE);
02159 #if defined(BeIME)
02160                                    nsIMEBeOS::GetIME()->DispatchCancelIME();
02161 #endif
02162                             }
02163                      } 
02164                      else 
02165                      {
02166 
02167                             if (mView->Window()->IsActive())
02168                             {
02169                                    // See comment above.
02170                                    if (mWindowParent &&  mView->Window()->IsFloating())
02171                                           mWindowParent->DispatchFocus(NS_DEACTIVATE);
02172                                    
02173                                    DispatchFocus(NS_ACTIVATE);
02174                                    if (mView && mView->Window())
02175                                           gLastActiveWindow = mView->Window();
02176                             }
02177                      }
02178               }
02179               break;
02180 
02181        case nsSwitchToUIThread::ONMOVE:
02182               {
02183                      NS_ASSERTION(info->nArgs == 0, "Wrong number of arguments to CallMethod");
02184                      nsRect r;
02185                      // We use this only for tracking whole window moves
02186                      GetScreenBounds(r);         
02187                      if (eWindowType_popup != mWindowType && eWindowType_child != mWindowType)
02188                             DealWithPopups(nsSwitchToUIThread::ONMOVE,nsPoint(0,0));
02189                      OnMove(r.x, r.y);
02190               }
02191               break;
02192               
02193        case nsSwitchToUIThread::ONWORKSPACE:
02194               {
02195                      NS_ASSERTION(info->nArgs == 2, "Wrong number of arguments to CallMethod");
02196                      if (eWindowType_popup != mWindowType && eWindowType_child != mWindowType)
02197                             DealWithPopups(nsSwitchToUIThread::ONWORKSPACE,nsPoint(0,0));
02198               }
02199               break;
02200 
02201 #if defined(BeIME)
02202        case nsSwitchToUIThread::ONIME:
02203               //No assertion used, as number of arguments varies here
02204               if (mView && mView->LockLooper())
02205               {
02206                      mView->SetFlags(mView->Flags() | B_NAVIGABLE);
02207                      mView->UnlockLooper();
02208               }
02209               nsIMEBeOS::GetIME()->RunIME(info->args, this, mView);
02210               break;
02211 #endif
02212               default:
02213                      bRet = FALSE;
02214                      break;
02215               
02216        }
02217 
02218        return bRet;
02219 }
02220 
02221 //-------------------------------------------------------------------------
02222 //
02223 // Key code translation related data
02224 //
02225 //-------------------------------------------------------------------------
02226 
02227 struct nsKeyConverter {
02228        int vkCode; // Platform independent key code
02229        char bekeycode; // BeOS key code
02230 };
02231 
02232 //
02233 // Netscape keycodes are defined in widget/public/nsGUIEvent.h
02234 // BeOS keycodes can be viewd at
02235 // http://www.be.com/documentation/be_book/Keyboard/KeyboardKeyCodes.html
02236 //
02237 
02238 struct nsKeyConverter nsKeycodesBeOS[] = {
02239                //  { NS_VK_CANCEL,     GDK_Cancel },
02240                { NS_VK_BACK,       0x1e },
02241                { NS_VK_TAB,        0x26 },
02242                //  { NS_VK_TAB,        GDK_ISO_Left_Tab },
02243                //  { NS_VK_CLEAR,      GDK_Clear },
02244                { NS_VK_RETURN,     0x47 },
02245                { NS_VK_SHIFT,      0x4b },
02246                { NS_VK_SHIFT,      0x56 },
02247                { NS_VK_CONTROL,    0x5c },
02248                { NS_VK_CONTROL,    0x60 },
02249                { NS_VK_ALT,        0x5d },
02250                { NS_VK_ALT,        0x5f },
02251                { NS_VK_PAUSE,      0x22 },
02252                { NS_VK_CAPS_LOCK,  0x3b },
02253                { NS_VK_ESCAPE,     0x1 },
02254                { NS_VK_SPACE,      0x5e },
02255                { NS_VK_PAGE_UP,    0x21 },
02256                { NS_VK_PAGE_DOWN,  0x36 },
02257                { NS_VK_END,        0x35 },
02258                { NS_VK_HOME,       0x20 },
02259                { NS_VK_LEFT,       0x61 },
02260                { NS_VK_UP,         0x57 },
02261                { NS_VK_RIGHT,      0x63 },
02262                { NS_VK_DOWN,       0x62 },
02263                { NS_VK_PRINTSCREEN, 0xe },
02264                { NS_VK_INSERT,     0x1f },
02265                { NS_VK_DELETE,     0x34 },
02266 
02267                // The "Windows Key"
02268                { NS_VK_META,       0x66 },
02269                { NS_VK_META,       0x67 },
02270 
02271                // keypad keys (constant keys)
02272                { NS_VK_MULTIPLY,   0x24 },
02273                { NS_VK_ADD,        0x3a },
02274                //  { NS_VK_SEPARATOR,   }, ???
02275                { NS_VK_SUBTRACT,   0x25 },
02276                { NS_VK_DIVIDE,     0x23 },
02277                { NS_VK_RETURN,     0x5b },
02278 
02279                { NS_VK_COMMA,      0x53 },
02280                { NS_VK_PERIOD,     0x54 },
02281                { NS_VK_SLASH,      0x55 },
02282                { NS_VK_BACK_SLASH, 0x33 },
02283                { NS_VK_BACK_SLASH, 0x6a }, // got this code on japanese keyboard
02284                { NS_VK_BACK_SLASH, 0x6b }, // got this code on japanese keyboard
02285                { NS_VK_BACK_QUOTE, 0x11 },
02286                { NS_VK_OPEN_BRACKET, 0x31 },
02287                { NS_VK_CLOSE_BRACKET, 0x32 },
02288                { NS_VK_SEMICOLON, 0x45 },
02289                { NS_VK_QUOTE, 0x46 },
02290 
02291                // NS doesn't have dash or equals distinct from the numeric keypad ones,
02292                // so we'll use those for now.  See bug 17008:
02293                { NS_VK_SUBTRACT, 0x1c },
02294                { NS_VK_EQUALS, 0x1d },
02295 
02296                { NS_VK_F1, B_F1_KEY },
02297                { NS_VK_F2, B_F2_KEY },
02298                { NS_VK_F3, B_F3_KEY },
02299                { NS_VK_F4, B_F4_KEY },
02300                { NS_VK_F5, B_F5_KEY },
02301                { NS_VK_F6, B_F6_KEY },
02302                { NS_VK_F7, B_F7_KEY },
02303                { NS_VK_F8, B_F8_KEY },
02304                { NS_VK_F9, B_F9_KEY },
02305                { NS_VK_F10, B_F10_KEY },
02306                { NS_VK_F11, B_F11_KEY },
02307                { NS_VK_F12, B_F12_KEY },
02308 
02309                { NS_VK_1, 0x12 },
02310                { NS_VK_2, 0x13 },
02311                { NS_VK_3, 0x14 },
02312                { NS_VK_4, 0x15 },
02313                { NS_VK_5, 0x16 },
02314                { NS_VK_6, 0x17 },
02315                { NS_VK_7, 0x18 },
02316                { NS_VK_8, 0x19 },
02317                { NS_VK_9, 0x1a },
02318                { NS_VK_0, 0x1b },
02319 
02320                { NS_VK_A, 0x3c },
02321                { NS_VK_B, 0x50 },
02322                { NS_VK_C, 0x4e },
02323                { NS_VK_D, 0x3e },
02324                { NS_VK_E, 0x29 },
02325                { NS_VK_F, 0x3f },
02326                { NS_VK_G, 0x40 },
02327                { NS_VK_H, 0x41 },
02328                { NS_VK_I, 0x2e },
02329                { NS_VK_J, 0x42 },
02330                { NS_VK_K, 0x43 },
02331                { NS_VK_L, 0x44 },
02332                { NS_VK_M, 0x52 },
02333                { NS_VK_N, 0x51 },
02334                { NS_VK_O, 0x2f },
02335                { NS_VK_P, 0x30 },
02336                { NS_VK_Q, 0x27 },
02337                { NS_VK_R, 0x2a },
02338                { NS_VK_S, 0x3d },
02339                { NS_VK_T, 0x2b },
02340                { NS_VK_U, 0x2d },
02341                { NS_VK_V, 0x4f },
02342                { NS_VK_W, 0x28 },
02343                { NS_VK_X, 0x4d },
02344                { NS_VK_Y, 0x2c },
02345                { NS_VK_Z, 0x4c }
02346         };
02347 
02348 // keycode of keypad when num-locked
02349 struct nsKeyConverter nsKeycodesBeOSNumLock[] = {
02350                { NS_VK_NUMPAD0, 0x64 },
02351                { NS_VK_NUMPAD1, 0x58 },
02352                { NS_VK_NUMPAD2, 0x59 },
02353                { NS_VK_NUMPAD3, 0x5a },
02354                { NS_VK_NUMPAD4, 0x48 },
02355                { NS_VK_NUMPAD5, 0x49 },
02356                { NS_VK_NUMPAD6, 0x4a },
02357                { NS_VK_NUMPAD7, 0x37 },
02358                { NS_VK_NUMPAD8, 0x38 },
02359                { NS_VK_NUMPAD9, 0x39 },
02360                { NS_VK_DECIMAL, 0x65 }
02361         };
02362 
02363 // keycode of keypad when not num-locked
02364 struct nsKeyConverter nsKeycodesBeOSNoNumLock[] = {
02365                { NS_VK_LEFT,       0x48 },
02366                { NS_VK_RIGHT,      0x4a },
02367                { NS_VK_UP,         0x38 },
02368                { NS_VK_DOWN,       0x59 },
02369                { NS_VK_PAGE_UP,    0x39 },
02370                { NS_VK_PAGE_DOWN,  0x5a },
02371                { NS_VK_HOME,       0x37 },
02372                { NS_VK_END,        0x58 },
02373                { NS_VK_INSERT,     0x64 },
02374                { NS_VK_DELETE,     0x65 }
02375         };
02376 
02377 //-------------------------------------------------------------------------
02378 //
02379 // Translate key code
02380 // Input is BeOS keyboard key-code; output is in NS_VK format
02381 //
02382 //-------------------------------------------------------------------------
02383 
02384 static int TranslateBeOSKeyCode(int32 bekeycode, bool isnumlock)
02385 {
02386 #ifdef KB_DEBUG
02387        printf("TranslateBeOSKeyCode: bekeycode = 0x%x\n",bekeycode);
02388 #endif
02389        int i;
02390        int length = sizeof(nsKeycodesBeOS) / sizeof(struct nsKeyConverter);
02391        int length_numlock = sizeof(nsKeycodesBeOSNumLock) / sizeof(struct nsKeyConverter);
02392        int length_nonumlock = sizeof(nsKeycodesBeOSNoNumLock) / sizeof(struct nsKeyConverter);
02393 
02394        // key code conversion
02395        for (i = 0; i < length; i++) {
02396               if (nsKeycodesBeOS[i].bekeycode == bekeycode)
02397                      return(nsKeycodesBeOS[i].vkCode);
02398        }
02399        // numpad keycode vary with numlock
02400        if (isnumlock) {
02401               for (i = 0; i < length_numlock; i++) {
02402                      if (nsKeycodesBeOSNumLock[i].bekeycode == bekeycode)
02403                             return(nsKeycodesBeOSNumLock[i].vkCode);
02404               }
02405        } else {
02406               for (i = 0; i < length_nonumlock; i++) {
02407                      if (nsKeycodesBeOSNoNumLock[i].bekeycode == bekeycode)
02408                             return(nsKeycodesBeOSNoNumLock[i].vkCode);
02409               }
02410        }
02411 #ifdef KB_DEBUG
02412        printf("TranslateBeOSKeyCode: ####### Translation not Found #######\n");
02413 #endif
02414        return((int)0);
02415 }
02416 
02417 //-------------------------------------------------------------------------
02418 //
02419 // OnKeyDown
02420 //
02421 //-------------------------------------------------------------------------
02422 PRBool nsWindow::OnKeyDown(PRUint32 aEventType, const char *bytes,
02423                            int32 numBytes, PRUint32 mod, PRUint32 bekeycode, int32 rawcode)
02424 {
02425        PRUint32 aTranslatedKeyCode;
02426        PRBool noDefault = PR_FALSE;
02427 
02428        mIsShiftDown   = (mod & B_SHIFT_KEY) ? PR_TRUE : PR_FALSE;
02429        mIsControlDown = (mod & B_CONTROL_KEY) ? PR_TRUE : PR_FALSE;
02430        mIsAltDown     = ((mod & B_COMMAND_KEY) && !(mod & B_RIGHT_OPTION_KEY))? PR_TRUE : PR_FALSE;
02431        mIsMetaDown    = (mod & B_LEFT_OPTION_KEY) ? PR_TRUE : PR_FALSE;      
02432        bool IsNumLocked = ((mod & B_NUM_LOCK) != 0);
02433 
02434        aTranslatedKeyCode = TranslateBeOSKeyCode(bekeycode, IsNumLocked);
02435 
02436        if (numBytes <= 1)
02437        {
02438               noDefault  = DispatchKeyEvent(NS_KEY_DOWN, 0, aTranslatedKeyCode);
02439        } else {
02440               //   non ASCII chars
02441        }
02442 
02443        // ------------  On Char  ------------
02444        PRUint32      uniChar;
02445 
02446        if ((mIsControlDown || mIsAltDown || mIsMetaDown) && rawcode >= 'a' && rawcode <= 'z') {
02447               if (mIsShiftDown)
02448                      uniChar = rawcode + 'A' - 'a';
02449               else
02450                      uniChar = rawcode;
02451               aTranslatedKeyCode = 0;
02452        } else {
02453               if (numBytes == 0) // deal with unmapped key
02454                      return noDefault;
02455 
02456               switch((unsigned char)bytes[0])
02457               {
02458               case 0xc8://System Request
02459               case 0xca://Break
02460                      return noDefault;// do not send 'KEY_PRESS' message
02461 
02462               case B_INSERT:
02463               case B_ESCAPE:
02464               case B_FUNCTION_KEY:
02465               case B_HOME:
02466               case B_PAGE_UP:
02467               case B_END:
02468               case B_PAGE_DOWN:
02469               case B_UP_ARROW:
02470               case B_LEFT_ARROW:
02471               case B_DOWN_ARROW:
02472               case B_RIGHT_ARROW:
02473               case B_TAB:
02474               case B_DELETE:
02475               case B_BACKSPACE:
02476               case B_ENTER:
02477                      uniChar = 0;
02478                      break;
02479 
02480               default:
02481                      // UTF-8 to unicode conversion
02482                      if (numBytes >= 1 && (bytes[0] & 0x80) == 0) {
02483                             // 1 byte utf-8 char
02484                             uniChar = bytes[0];
02485                      } else
02486                             if (numBytes >= 2 && (bytes[0] & 0xe0) == 0xc0) {
02487                                    // 2 byte utf-8 char
02488                                    uniChar = ((uint16)(bytes[0] & 0x1f) << 6) | (uint16)(bytes[1] & 0x3f);
02489                             } else
02490                                    if (numBytes >= 3 && (bytes[0] & 0xf0) == 0xe0) {
02491                                           // 3 byte utf-8 char
02492                                           uniChar = ((uint16)(bytes[0] & 0x0f) << 12) | ((uint16)(bytes[1] & 0x3f) << 6)
02493                                                     | (uint16)(bytes[2] & 0x3f);
02494                                    } else {
02495                                           //error
02496                                           uniChar = 0;
02497                                           NS_WARNING("nsWindow::OnKeyDown() error: bytes[] has not enough chars.");
02498                                    }
02499 
02500                      aTranslatedKeyCode = 0;
02501                      break;
02502               }
02503        }
02504 
02505        // If prevent default set for onkeydown, do the same for onkeypress
02506        PRUint32 extraFlags = (noDefault ? NS_EVENT_FLAG_NO_DEFAULT : 0);
02507        return DispatchKeyEvent(NS_KEY_PRESS, uniChar, aTranslatedKeyCode, extraFlags) && noDefault;
02508 }
02509 
02510 //-------------------------------------------------------------------------
02511 //
02512 // OnKeyUp
02513 //
02514 //-------------------------------------------------------------------------
02515 PRBool nsWindow::OnKeyUp(PRUint32 aEventType, const char *bytes,
02516                          int32 numBytes, PRUint32 mod, PRUint32 bekeycode, int32 rawcode)
02517 {
02518        PRUint32 aTranslatedKeyCode;
02519        bool IsNumLocked = ((mod & B_NUM_LOCK) != 0);
02520 
02521        mIsShiftDown   = (mod & B_SHIFT_KEY) ? PR_TRUE : PR_FALSE;
02522        mIsControlDown = (mod & B_CONTROL_KEY) ? PR_TRUE : PR_FALSE;
02523        mIsAltDown     = ((mod & B_COMMAND_KEY) && !(mod & B_RIGHT_OPTION_KEY))? PR_TRUE : PR_FALSE;
02524        mIsMetaDown    = (mod & B_LEFT_OPTION_KEY) ? PR_TRUE : PR_FALSE;      
02525 
02526        aTranslatedKeyCode = TranslateBeOSKeyCode(bekeycode, IsNumLocked);
02527 
02528        PRBool result = DispatchKeyEvent(NS_KEY_UP, 0, aTranslatedKeyCode);
02529        return result;
02530 
02531 }
02532 
02533 //-------------------------------------------------------------------------
02534 //
02535 // DispatchKeyEvent
02536 //
02537 //-------------------------------------------------------------------------
02538 
02539 PRBool nsWindow::DispatchKeyEvent(PRUint32 aEventType, PRUint32 aCharCode,
02540                                   PRUint32 aKeyCode, PRUint32 aFlags)
02541 {
02542        nsKeyEvent event(PR_TRUE, aEventType, this);
02543        nsPoint point;
02544 
02545        point.x = 0;
02546        point.y = 0;
02547 
02548        InitEvent(event, &point); // this add ref's event.widget
02549 
02550        event.flags |= aFlags;
02551        event.charCode = aCharCode;
02552        event.keyCode  = aKeyCode;
02553 
02554 #ifdef KB_DEBUG
02555        static int cnt=0;
02556        printf("%d DispatchKE Type: %s charCode 0x%x  keyCode 0x%x ", cnt++,
02557               (NS_KEY_PRESS == aEventType)?"PRESS":(aEventType == NS_KEY_UP?"Up":"Down"),
02558               event.charCode, event.keyCode);
02559        printf("Shift: %s Control %s Alt: %s Meta: %s\n",  
02560               (mIsShiftDown?"D":"U"), 
02561               (mIsControlDown?"D":"U"), 
02562               (mIsAltDown?"D":"U"),
02563               (mIsMetaDown?"D":"U"));
02564 #endif
02565 
02566        event.isShift   = mIsShiftDown;
02567        event.isControl = mIsControlDown;
02568        event.isMeta   =  mIsMetaDown;
02569        event.isAlt     = mIsAltDown;
02570 
02571        PRBool result = DispatchWindowEvent(&event);
02572        NS_RELEASE(event.widget);
02573 
02574        return result;
02575 }
02576 
02577 //-------------------------------------------------------------------------
02578 //
02579 // WM_DESTROY has been called
02580 //
02581 //-------------------------------------------------------------------------
02582 void nsWindow::OnDestroy()
02583 {
02584        mOnDestroyCalled = PR_TRUE;
02585 
02586        // release references to children, device context, toolkit, and app shell
02587        nsBaseWidget::OnDestroy();
02588 
02589        // dispatch the event
02590        if (!mIsDestroying) 
02591        {
02592               // dispatching of the event may cause the reference count to drop to 0
02593               // and result in this object being destroyed. To avoid that, add a reference
02594               // and then release it after dispatching the event
02595               AddRef();
02596               DispatchStandardEvent(NS_DESTROY);
02597               Release();
02598        }
02599 }
02600 
02601 //-------------------------------------------------------------------------
02602 //
02603 // Move
02604 //
02605 //-------------------------------------------------------------------------
02606 PRBool nsWindow::OnMove(PRInt32 aX, PRInt32 aY)
02607 {
02608        nsGUIEvent event(PR_TRUE, NS_MOVE, this);
02609        InitEvent(event);
02610        event.point.x = aX;
02611        event.point.y = aY;
02612 
02613        PRBool result = DispatchWindowEvent(&event);
02614        NS_RELEASE(event.widget);
02615        return result;
02616 }
02617 
02618 void nsWindow::OnWheel(PRInt32 aDirection, uint32 aButtons, BPoint aPoint, nscoord aDelta)
02619 {
02620               // we don't use the mIsXDown bools because
02621               // they get reset on Gecko reload (makes it harder
02622               // to use stuff like Alt+Wheel)
02623 
02624               nsMouseScrollEvent scrollEvent(PR_TRUE, NS_MOUSE_SCROLL, this);
02625               uint32 mod (modifiers());
02626               scrollEvent.isControl = mod & B_CONTROL_KEY;
02627               scrollEvent.isShift = mod & B_SHIFT_KEY;
02628               scrollEvent.isAlt   = mod & B_COMMAND_KEY;
02629               scrollEvent.isMeta  = mod & B_OPTION_KEY;
02630                                           
02631               scrollEvent.scrollFlags = aDirection;
02632               scrollEvent.delta = aDelta;
02633               scrollEvent.time      = PR_IntervalNow();
02634               scrollEvent.point.x = nscoord(aPoint.x);
02635               scrollEvent.point.y = nscoord(aPoint.y);
02636 
02637               nsEventStatus rv;
02638               DispatchEvent (&scrollEvent, rv);
02639 }
02640 
02641 //-------------------------------------------------------------------------
02642 //
02643 // Paint
02644 //
02645 //-------------------------------------------------------------------------
02646 nsresult nsWindow::OnPaint(BRegion *breg)
02647 {
02648        nsresult rv = NS_ERROR_FAILURE;
02649        if (mView && mView->LockLooper())
02650        {
02651               // Substracting area from paintregion
02652               mView->Validate(breg);
02653               // looks like it should be done by Mozilla via nsRenderingContext methods,
02654               // but we saw in some cases how it follows Win32 ideas and don't care about clipping there
02655               mView->ConstrainClippingRegion(breg);
02656               mView->UnlockLooper();
02657        }
02658        else
02659               return rv;
02660        BRect br = breg->Frame();
02661        if (!br.IsValid() || !mEventCallback || !mView  || (eWindowType_child != mWindowType && eWindowType_popup != mWindowType))
02662               return rv;
02663        nsRect nsr(nscoord(br.left), nscoord(br.top), 
02664                      nscoord(br.IntegerWidth() + 1), nscoord(br.IntegerHeight() + 1));
02665        mUpdateArea->SetTo(0,0,0,0);
02666        int numrects = breg->CountRects();
02667        for (int i = 0; i< numrects; i++)
02668        {
02669               BRect br = breg->RectAt(i);
02670               mUpdateArea->Union(int(br.left), int(br.top), 
02671                                                  br.IntegerWidth() + 1, br.IntegerHeight() + 1);
02672        }      
02673 
02674        
02675        nsPaintEvent event(PR_TRUE, NS_PAINT, this);
02676 
02677        InitEvent(event);
02678        event.region = mUpdateArea;
02679        event.rect = &nsr;
02680        event.renderingContext = GetRenderingContext();
02681        if (event.renderingContext != nsnull)
02682        {
02683               // TODO: supply nsRenderingContextBeOS with font, colors and other state variables here.
02684               // It will help toget rid of some hacks in LockAndUpdateView and
02685               // allow non-permanent nsDrawingSurface for BeOS - currently it fails for non-bitmapped BViews/widgets.
02686               // Something like this:
02687               //if (mFontMetrics)
02688               //     event.renderingContext->SetFont(mFontMetrics);
02689               rv = DispatchWindowEvent(&event) ? NS_OK : NS_ERROR_FAILURE;
02690               NS_RELEASE(event.renderingContext);
02691        }
02692 
02693        NS_RELEASE(event.widget);
02694        return rv;
02695 }
02696 
02697 
02698 //-------------------------------------------------------------------------
02699 //
02700 // Send a resize message to the listener
02701 //
02702 //-------------------------------------------------------------------------
02703 PRBool nsWindow::OnResize(nsRect &aWindowRect)
02704 {
02705        // call the event callback
02706        if (mEventCallback)
02707        {
02708               nsSizeEvent event(PR_TRUE, NS_SIZE, this);
02709               InitEvent(event);
02710               event.windowSize = &aWindowRect;
02711               // We have same size for windows rect and "client area" rect
02712               event.mWinWidth  = aWindowRect.width;
02713               event.mWinHeight = aWindowRect.height;
02714               PRBool result = DispatchWindowEvent(&event);
02715               NS_RELEASE(event.widget);
02716               return result;
02717        }
02718        return PR_FALSE;
02719 }
02720 
02721 
02722 
02723 //-------------------------------------------------------------------------
02724 //
02725 // Deal with all sort of mouse event
02726 //
02727 //-------------------------------------------------------------------------
02728 PRBool nsWindow::DispatchMouseEvent(PRUint32 aEventType, nsPoint aPoint, PRUint32 clicks, PRUint32 mod)
02729 {
02730        PRBool result = PR_FALSE;
02731        if (nsnull != mEventCallback || nsnull != mMouseListener)
02732        {
02733               nsMouseEvent event(PR_TRUE, aEventType, this, nsMouseEvent::eReal);
02734               InitEvent (event, &aPoint);
02735               event.isShift   = mod & B_SHIFT_KEY;
02736               event.isControl = mod & B_CONTROL_KEY;
02737               event.isAlt     = mod & B_COMMAND_KEY;
02738               event.isMeta     = mod & B_OPTION_KEY;
02739               event.clickCount = clicks;
02740 
02741               // call the event callback
02742               if (nsnull != mEventCallback)
02743               {
02744                      result = DispatchWindowEvent(&event);
02745                      NS_RELEASE(event.widget);
02746                      return result;
02747               }
02748               else
02749               {
02750                      switch(aEventType)
02751                      {
02752                      case NS_MOUSE_MOVE :
02753                             result = ConvertStatus(mMouseListener->MouseMoved(event));
02754                             break;
02755 
02756                      case NS_MOUSE_LEFT_BUTTON_DOWN :
02757                      case NS_MOUSE_MIDDLE_BUTTON_DOWN :
02758                      case NS_MOUSE_RIGHT_BUTTON_DOWN :
02759                             result = ConvertStatus(mMouseListener->MousePressed(event));
02760                             break;
02761 
02762                      case NS_MOUSE_LEFT_BUTTON_UP :
02763                      case NS_MOUSE_MIDDLE_BUTTON_UP :
02764                      case NS_MOUSE_RIGHT_BUTTON_UP :
02765                             result = ConvertStatus(mMouseListener->MouseReleased(event)) && ConvertStatus(mMouseListener->MouseClicked(event));
02766                             break;
02767                      }
02768                      NS_RELEASE(event.widget);
02769                      return result;
02770               }
02771        }
02772 
02773        return PR_FALSE;
02774 }
02775 
02776 //-------------------------------------------------------------------------
02777 //
02778 // Deal with focus messages
02779 //
02780 //-------------------------------------------------------------------------
02781 PRBool nsWindow::DispatchFocus(PRUint32 aEventType)
02782 {
02783        // call the event callback
02784        if (mEventCallback) {
02785               return(DispatchStandardEvent(aEventType));
02786        }
02787 
02788        return PR_FALSE;
02789 }
02790 
02791 NS_METHOD nsWindow::SetTitle(const nsAString& aTitle)
02792 {
02793        if (mView && mView->LockLooper())
02794        {
02795               mView->Window()->SetTitle(NS_ConvertUTF16toUTF8(aTitle).get());
02796               mView->UnlockLooper();
02797        }
02798        return NS_OK;
02799 }
02800 
02801 //----------------------------------------------------
02802 //
02803 // Get/Set the preferred size
02804 //
02805 //----------------------------------------------------
02806 NS_METHOD nsWindow::GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight)
02807 {
02808        // TODO:  Check to see how often this is called.  If too much, leave as is,
02809        // otherwise, call mView->GetPreferredSize
02810        aWidth  = mPreferredWidth;
02811        aHeight = mPreferredHeight;
02812        return NS_ERROR_FAILURE;
02813 }
02814 
02815 NS_METHOD nsWindow::SetPreferredSize(PRInt32 aWidth, PRInt32 aHeight)
02816 {
02817        mPreferredWidth  = aWidth;
02818        mPreferredHeight = aHeight;
02819        return NS_OK;
02820 }
02821 
02822 //----------------------------------------------------
02823 // Special Sub-Class
02824 //----------------------------------------------------
02825 nsIWidgetStore::nsIWidgetStore( nsIWidget *aWidget )
02826               : mWidget( aWidget )
02827 {
02828        // NS_ADDREF/NS_RELEASE is not needed here.
02829        // This class is used as internal (BeOS native) object of nsWindow,
02830        // so it must not addref/release nsWindow here.
02831        // Otherwise, nsWindow object will leak. (Makoto Hamanaka)
02832 }
02833 
02834 nsIWidgetStore::~nsIWidgetStore()
02835 {
02836 }
02837 
02838 nsIWidget *nsIWidgetStore::GetMozillaWidget(void)
02839 {
02840        return mWidget;
02841 }
02842 
02843 //----------------------------------------------------
02844 // BeOS Sub-Class Window
02845 //----------------------------------------------------
02846 
02847 nsWindowBeOS::nsWindowBeOS( nsIWidget *aWidgetWindow, BRect aFrame, const char *aName, window_look aLook,
02848                             window_feel aFeel, int32 aFlags, int32 aWorkspace )
02849               : BWindow( aFrame, aName, aLook, aFeel, aFlags, aWorkspace ),
02850               nsIWidgetStore( aWidgetWindow )
02851 {
02852        fJustGotBounds = true;
02853 }
02854 
02855 nsWindowBeOS::~nsWindowBeOS()
02856 {
02857        //placeholder for clean up
02858 }
02859 
02860 bool nsWindowBeOS::QuitRequested( void )
02861 {
02862        if (CountChildren() != 0)
02863        {
02864               nsWindow      *w = (nsWindow *)GetMozillaWidget();
02865               nsToolkit     *t;
02866               if (w && (t = w->GetToolkit()) != 0)
02867               {
02868                      MethodInfo *info = nsnull;
02869                      if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::CLOSEWINDOW)))
02870                             t->CallMethodAsync(info);
02871                      NS_RELEASE(t);
02872               }
02873        }
02874        return true;
02875 }
02876 
02877 void nsWindowBeOS::MessageReceived(BMessage *msg)
02878 {
02879        // Temp replacement for real DnD. Supports file drop onto window.
02880        if (msg->what == B_SIMPLE_DATA)
02881        {
02882               be_app_messenger.SendMessage(msg);
02883        }
02884        BWindow::MessageReceived(msg);
02885 }
02886 
02887 // This function calls KeyDown() for Alt+whatever instead of app_server
02888 void nsWindowBeOS::DispatchMessage(BMessage *msg, BHandler *handler)
02889 {
02890        if (msg->what == B_KEY_DOWN && modifiers() & B_COMMAND_KEY) {
02891               BString bytes;
02892               if (B_OK == msg->FindString("bytes", &bytes)) {
02893                      BView *view = this->CurrentFocus();
02894                      if (view)
02895                             view->KeyDown(bytes.String(), bytes.Length());
02896               }
02897               if (strcmp(bytes.String(),"w") && strcmp(bytes.String(),"W"))
02898                      BWindow::DispatchMessage(msg, handler);
02899        }
02900        // In some cases the message don't reach QuitRequested() hook,
02901        // so do it here
02902        else if(msg->what == B_QUIT_REQUESTED)
02903        {
02904               // tells nsWindow to kill me
02905               nsWindow      *w = (nsWindow *)GetMozillaWidget();
02906               nsToolkit     *t;
02907               if (w && (t = w->GetToolkit()) != 0)
02908               {
02909                      MethodInfo *info = nsnull;
02910                      if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::CLOSEWINDOW)))
02911                             t->CallMethodAsync(info);
02912                      NS_RELEASE(t);
02913               }
02914        }
02915        else
02916               BWindow::DispatchMessage(msg, handler);
02917 }
02918 
02919 //This method serves single purpose here - allows Mozilla to save current window position,
02920 //and restore position on new start. 
02921 void nsWindowBeOS::FrameMoved(BPoint origin)
02922 {      
02923 
02924        //determine if the window position actually changed
02925        if (origin.x == lastWindowPoint.x && origin.x == lastWindowPoint.x) 
02926        {
02927               //it didn't - don't bother
02928               return;
02929        }
02930        lastWindowPoint = origin;
02931        nsWindow  *w = (nsWindow *)GetMozillaWidget();
02932        nsToolkit *t;
02933        if (w && (t = w->GetToolkit()) != 0) 
02934        {
02935               MethodInfo *info = nsnull;
02936               if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONMOVE)))
02937                      t->CallMethodAsync(info);
02938               NS_RELEASE(t);
02939        }
02940 }
02941 
02942 void nsWindowBeOS::WindowActivated(bool active)
02943 {
02944 // Calls method ONACTIVATE to dispatch focus ACTIVATE messages
02945        nsWindow        *w = (nsWindow *)GetMozillaWidget();
02946        nsToolkit     *t;
02947        if (w && (t = w->GetToolkit()) != 0)
02948        {
02949               uint32 args[2];
02950               args[0] = (uint32)active;
02951               args[1] = (uint32)this;
02952               MethodInfo *info = nsnull;
02953               if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONACTIVATE, 2, args)))
02954                      t->CallMethodAsync(info);
02955               NS_RELEASE(t);
02956        }
02957 }
02958 
02959 void  nsWindowBeOS::WorkspacesChanged(uint32 oldworkspace, uint32 newworkspace)
02960 {
02961        if (oldworkspace == newworkspace)
02962               return;
02963        nsWindow        *w = (nsWindow *)GetMozillaWidget();
02964        nsToolkit     *t;
02965        if (w && (t = w->GetToolkit()) != 0)
02966        {
02967               uint32 args[2];
02968               args[0] = newworkspace;
02969               args[1] = oldworkspace;
02970               MethodInfo *info = nsnull;
02971               if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONWORKSPACE, 2, args)))
02972                      t->CallMethodAsync(info);
02973               NS_RELEASE(t);
02974        }      
02975 }
02976 
02977 void  nsWindowBeOS::FrameResized(float width, float height)
02978 {
02979        // We have send message already, and Mozilla still didn't get it
02980        // so don't poke it endlessly with no reason
02981        if (!fJustGotBounds)
02982               return;
02983        nsWindow        *w = (nsWindow *)GetMozillaWidget();
02984        nsToolkit     *t;
02985        if (w && (t = w->GetToolkit()) != 0)
02986        {
02987               MethodInfo *info = nsnull;
02988               if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONRESIZE)))
02989               {
02990                      t->CallMethodAsync(info);
02991                      //Memorize fact of sending message
02992                      fJustGotBounds = false;
02993               }
02994               NS_RELEASE(t);
02995        }      
02996 }
02997 
02998 //----------------------------------------------------
02999 // BeOS Sub-Class View
03000 //----------------------------------------------------
03001 
03002 nsViewBeOS::nsViewBeOS(nsIWidget *aWidgetWindow, BRect aFrame, const char *aName, uint32 aResizingMode, uint32 aFlags)
03003        : BView(aFrame, aName, aResizingMode, aFlags), nsIWidgetStore(aWidgetWindow), wheel(.0,.0)
03004 {
03005        SetViewColor(B_TRANSPARENT_COLOR);
03006        paintregion.MakeEmpty();    
03007        buttons = 0;
03008        fRestoreMouseMask = false;
03009        fJustValidated = true;
03010        fWheelDispatched = true;
03011        fVisible = true;
03012 }
03013 
03014 void nsViewBeOS::SetVisible(bool visible)
03015 {
03016        if (visible) 
03017               SetFlags(Flags() | B_WILL_DRAW);
03018        else
03019               SetFlags(Flags() & ~B_WILL_DRAW);
03020        fVisible = visible;
03021 }
03022 
03023 inline bool nsViewBeOS::Visible()
03024 {
03025        return fVisible;
03026 }
03027 
03028 void nsViewBeOS::Draw(BRect updateRect)
03029 {
03030        // Ignore all, we are scrolling.
03031        if (!fVisible)
03032               return;
03033 
03034        paintregion.Include(updateRect);
03035 
03036        // We have send message already, and Mozilla still didn't get it
03037        // so don't poke it endlessly with no reason. Also don't send message
03038        // if update region is empty.
03039        if (paintregion.CountRects() == 0 || !paintregion.Frame().IsValid() || !fJustValidated)
03040               return;
03041        uint32 args[1];
03042        args[0] = (uint32)this;
03043        nsWindow      *w = (nsWindow *)GetMozillaWidget();
03044        nsToolkit     *t;
03045        if (w && (t = w->GetToolkit()) != 0)
03046        {
03047               MethodInfo *info = nsnull;
03048               info = new MethodInfo(w, w, nsSwitchToUIThread::ONPAINT, 1, args);
03049               if (info)
03050               {
03051                      t->CallMethodAsync(info);
03052                      //Memorize fact of sending message
03053                      fJustValidated = false;
03054               }
03055               NS_RELEASE(t);
03056        }
03057 }
03058 
03059 // Method to get update rects for asynchronous drawing.
03060 bool nsViewBeOS::GetPaintRegion(BRegion *r)
03061 {
03062 
03063        // Mozilla got previous ONPAINT message,
03064        // ready for next event.
03065        fJustValidated = true;
03066        if (paintregion.CountRects() == 0)
03067               return false;
03068        r->Include(&paintregion);
03069        return true;
03070 }
03071 
03072 // Method to remove painted rects from pending update region
03073 void nsViewBeOS::Validate(BRegion *reg)
03074 {
03075        paintregion.Exclude(reg);
03076 }
03077 
03078 BPoint nsViewBeOS::GetWheel()
03079 {
03080        BPoint retvalue = wheel;
03081        // Mozilla got wheel event, so setting flag and cleaning delta storage
03082        fWheelDispatched = true;
03083        wheel.x = 0;
03084        wheel.y = 0;
03085        return retvalue;
03086 }
03087 
03088 void nsViewBeOS::MouseDown(BPoint point)
03089 {
03090        if (!fRestoreMouseMask)
03091               mouseMask = SetMouseEventMask(B_POINTER_EVENTS);
03092        fRestoreMouseMask = true;
03093 
03094        //To avoid generating extra mouseevents when there is no change in pos.
03095        mousePos = point;
03096 
03097        uint32 clicks = 0;
03098        BMessage *msg = Window()->CurrentMessage();
03099        msg->FindInt32("buttons", (int32 *) &buttons);
03100        msg->FindInt32("clicks", (int32 *) &clicks);
03101 
03102        if (0 == buttons)
03103               return;
03104 
03105        nsWindow *w = (nsWindow *)GetMozillaWidget();
03106        if (w == NULL)
03107               return;
03108               
03109        nsToolkit     *t = w->GetToolkit();
03110        if (t == NULL)
03111               return;
03112 
03113        int32 ev = (buttons & B_PRIMARY_MOUSE_BUTTON) ? NS_MOUSE_LEFT_BUTTON_DOWN :
03114                   ((buttons & B_SECONDARY_MOUSE_BUTTON) ? NS_MOUSE_RIGHT_BUTTON_DOWN :
03115                    NS_MOUSE_MIDDLE_BUTTON_DOWN);
03116        uint32 args[5];
03117        args[0] = ev;
03118        args[1] = (uint32) point.x;
03119        args[2] = (uint32) point.y;
03120        args[3] = clicks;
03121        args[4] = modifiers();
03122        MethodInfo *info = nsnull;
03123        if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::BTNCLICK, 5, args)))
03124               t->CallMethodAsync(info);
03125        NS_RELEASE(t);
03126 }
03127 
03128 void nsViewBeOS::MouseMoved(BPoint point, uint32 transit, const BMessage *msg)
03129 {
03130        //To avoid generating extra mouseevents when there is no change in pos.
03131        //and not entering exiting view.
03132        if (mousePos == point && (transit == B_INSIDE_VIEW || transit == B_OUTSIDE_VIEW))
03133               return;
03134 
03135        mousePos = point;
03136 
03137        //We didn't start the mouse down and there is no drag in progress, so ignore.
03138        if (NULL == msg && !fRestoreMouseMask && buttons)
03139               return;
03140               
03141        nsWindow      *w = (nsWindow *)GetMozillaWidget();
03142        if (w == NULL)
03143               return;
03144        nsToolkit     *t = t = w->GetToolkit();
03145        if (t == NULL)
03146               return;
03147 
03148        uint32 args[1];
03149 /*     args[1] = (int32) point.x;
03150        args[2] = (int32) point.y;
03151        args[3] = modifiers();*/
03152 
03153        switch (transit)
03154        {
03155        case B_ENTERED_VIEW:
03156               {
03157                      args[0] = NULL != msg ? NS_DRAGDROP_ENTER : NS_MOUSE_ENTER;
03158                      if (msg == NULL)
03159                             break;
03160                      nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
03161                      dragService->StartDragSession();
03162                      //As it may have come from the outside we need to update this.
03163                      nsCOMPtr<nsIDragSessionBeOS> dragSessionBeOS = do_QueryInterface(dragService);
03164                      dragSessionBeOS->UpdateDragMessageIfNeeded(new BMessage(*msg));
03165               }
03166               break;
03167        case B_EXITED_VIEW:
03168               {
03169                      args[0] = NULL != msg ? NS_DRAGDROP_EXIT : NS_MOUSE_EXIT;
03170                      if (msg == NULL)
03171                             break;
03172                      nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
03173                      dragService->EndDragSession();
03174               }
03175               break;
03176        default:
03177               args[0]= msg == NULL ? NS_MOUSE_MOVE : NS_DRAGDROP_OVER;
03178        }
03179        
03180        MethodInfo *moveInfo = nsnull;
03181        if (nsnull != (moveInfo = new MethodInfo(w, w, nsSwitchToUIThread::ONMOUSE, 1, args)))
03182               t->CallMethodAsync(moveInfo);
03183        NS_RELEASE(t);
03184 }
03185 
03186 void nsViewBeOS::MouseUp(BPoint point)
03187 {
03188        if (fRestoreMouseMask) 
03189        {
03190               SetMouseEventMask(mouseMask);
03191               fRestoreMouseMask = false;
03192        }
03193 
03194        //To avoid generating extra mouseevents when there is no change in pos.
03195        mousePos = point;
03196 
03197        int32 ev = (buttons & B_PRIMARY_MOUSE_BUTTON) ? NS_MOUSE_LEFT_BUTTON_UP :
03198                   ((buttons & B_SECONDARY_MOUSE_BUTTON) ? NS_MOUSE_RIGHT_BUTTON_UP :
03199                    NS_MOUSE_MIDDLE_BUTTON_UP);
03200                    
03201        buttons = 0;
03202               
03203        nsWindow *w = (nsWindow *)GetMozillaWidget();
03204        if (w == NULL)
03205               return;
03206        nsToolkit     *t = t = w->GetToolkit();
03207        if (t == NULL)
03208               return;
03209 
03210        uint32 args[5];
03211        args[0] = ev;
03212        args[1] = (uint32) point.x;
03213        args[2] = (int32) point.y;
03214        args[3] = 0;
03215        args[4] = modifiers();
03216        MethodInfo *info = nsnull;
03217        if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::BTNCLICK, 5, args)))
03218               t->CallMethodAsync(info);
03219        NS_RELEASE(t);
03220 }
03221 
03222 void nsViewBeOS::MessageReceived(BMessage *msg)
03223 {
03224        if(msg->WasDropped())
03225        {
03226               nsWindow      *w = (nsWindow *)GetMozillaWidget();
03227               if (w == NULL)
03228                      return;
03229               nsToolkit     *t = t = w->GetToolkit();
03230               if (t == NULL)
03231                      return;
03232 
03233               uint32 args[4];
03234               args[0] = NS_DRAGDROP_DROP;
03235 
03236               //Drop point is in screen-cordinates
03237               BPoint aPoint = ConvertFromScreen(msg->DropPoint()); 
03238        
03239               args[1] = (uint32) aPoint.x;
03240               args[2] = (uint32) aPoint.y;
03241               args[3] = modifiers();
03242 
03243               MethodInfo *info = new MethodInfo(w, w, nsSwitchToUIThread::ONDROP, 4, args);
03244               t->CallMethodAsync(info);
03245               BView::MessageReceived(msg);
03246               return;
03247        }
03248 
03249        switch(msg->what)
03250        {
03251        //Native drag'n'drop negotiation
03252        case B_COPY_TARGET:
03253        case B_MOVE_TARGET:
03254        case B_LINK_TARGET:
03255        case B_TRASH_TARGET:
03256               {
03257                      nsCOMPtr<nsIDragService> dragService = do_GetService(kCDragServiceCID);
03258                      nsCOMPtr<nsIDragSessionBeOS> dragSessionBeOS = do_QueryInterface(dragService);
03259                      dragSessionBeOS->TransmitData(new BMessage(*msg));
03260               }
03261               break;
03262        case B_UNMAPPED_KEY_DOWN:
03263               //printf("unmapped_key_down\n");
03264               KeyDown(NULL, 0);
03265               break;
03266 
03267        case B_UNMAPPED_KEY_UP:
03268               //printf("unmapped_key_up\n");
03269               KeyUp(NULL, 0);
03270               break;
03271 
03272        case B_MOUSE_WHEEL_CHANGED:
03273               {
03274                      float wheel_y;
03275                      float wheel_x;
03276 
03277                      msg->FindFloat ("be:wheel_delta_y", &wheel_y);
03278                      msg->FindFloat ("be:wheel_delta_x", &wheel_x);
03279                      wheel.x += wheel_x;
03280                      wheel.y += wheel_y;
03281 
03282                      if(!fWheelDispatched || (nscoord(wheel_x) == 0 && nscoord(wheel_y) == 0))
03283                             return;
03284                      uint32 args[1];
03285                      args[0] = (uint32)this;
03286                      nsWindow    *w = (nsWindow *)GetMozillaWidget();
03287                      nsToolkit   *t;
03288 
03289                      if (w && (t = w->GetToolkit()) != 0)
03290                      {
03291                                    
03292                             MethodInfo *info = nsnull;
03293                             if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONWHEEL, 1, args)))
03294                             {
03295                                    t->CallMethodAsync(info);
03296                                    fWheelDispatched = false;
03297                                    
03298                             }
03299                             NS_RELEASE(t);
03300                      }
03301               }
03302               break;
03303               
03304 #if defined(BeIME)
03305        case B_INPUT_METHOD_EVENT:
03306               DoIME(msg);
03307               break;
03308 #endif
03309        default :
03310               BView::MessageReceived(msg);
03311               break;
03312        }
03313 }
03314 
03315 void nsViewBeOS::KeyDown(const char *bytes, int32 numBytes)
03316 {
03317        nsWindow      *w = (nsWindow *)GetMozillaWidget();
03318        nsToolkit     *t;
03319        int32 keycode = 0;
03320        int32 rawcode = 0;
03321 
03322        BMessage *msg = this->Window()->CurrentMessage();
03323        if (msg) {
03324               msg->FindInt32("key", &keycode);
03325               msg->FindInt32("raw_char", &rawcode);
03326        }
03327 
03328        if (w && (t = w->GetToolkit()) != 0) {
03329               uint32 bytebuf = 0;
03330               uint8 *byteptr = (uint8 *)&bytebuf;
03331               for(int32 i = 0; i < numBytes; i++)
03332                      byteptr[i] = bytes[i];
03333 
03334               uint32 args[6];
03335               args[0] = NS_KEY_DOWN;
03336               args[1] = bytebuf;
03337               args[2] = numBytes;
03338               args[3] = modifiers();
03339               args[4] = keycode;
03340               args[5] = rawcode;
03341               MethodInfo *info = nsnull;
03342               if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONKEY, 6, args)))
03343                      t->CallMethodAsync(info);
03344               NS_RELEASE(t);
03345        }
03346 }
03347 
03348 void nsViewBeOS::KeyUp(const char *bytes, int32 numBytes)
03349 {
03350        nsWindow      *w = (nsWindow *)GetMozillaWidget();
03351        nsToolkit     *t;
03352        int32 keycode = 0;
03353        int32 rawcode = 0;
03354        BMessage *msg = this->Window()->CurrentMessage();
03355        if (msg) {
03356               msg->FindInt32("key", &keycode);
03357               msg->FindInt32("raw_char", &rawcode);
03358        }
03359 
03360        if (w && (t = w->GetToolkit()) != 0) {
03361               uint32 bytebuf = 0;
03362               uint8 *byteptr = (uint8 *)&bytebuf;
03363               for(int32 i = 0; i < numBytes; i++)
03364                      byteptr[i] = bytes[i];
03365 
03366               uint32 args[6];
03367               args[0] = NS_KEY_UP;
03368               args[1] = (int32)bytebuf;
03369               args[2] = numBytes;
03370               args[3] = modifiers();
03371               args[4] = keycode;
03372               args[5] = rawcode;
03373               MethodInfo *info = nsnull;
03374               if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::ONKEY, 6, args)))
03375                      t->CallMethodAsync(info);
03376               NS_RELEASE(t);
03377        }
03378 }
03379 
03380 void nsViewBeOS::MakeFocus(bool focused)
03381 {
03382        if (!IsFocus() && focused)
03383               BView::MakeFocus(focused);
03384        uint32 args[1];
03385        args[0] = (uint32)this;
03386        nsWindow      *w = (nsWindow *)GetMozillaWidget();
03387        nsToolkit     *t;
03388        if (w && (t = w->GetToolkit()) != 0)
03389        {
03390               MethodInfo *info = nsnull;
03391               if (!focused)
03392               {
03393                      if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::KILL_FOCUS,1,args)))
03394                             t->CallMethodAsync(info);
03395               }
03396 #ifdef DEBUG_FOCUS
03397               else
03398               {
03399                      if (nsnull != (info = new MethodInfo(w, w, nsSwitchToUIThread::GOT_FOCUS,1,args)))
03400                             t->CallMethodAsync(info);
03401               }
03402 #endif        
03403               NS_RELEASE(t);
03404        }
03405 }
03406 
03407 #if defined(BeIME)
03408 // Inline Input Method implementation
03409 void nsViewBeOS::DoIME(BMessage *msg)
03410 {
03411        nsWindow      *w = (nsWindow *)GetMozillaWidget();
03412        nsToolkit     *t;
03413  
03414        if(w && (t = w->GetToolkit()) != 0) 
03415        {
03416               ssize_t size = msg->FlattenedSize();
03417               int32         argc = (size+3)/4;
03418               uint32 *args = new uint32[argc];
03419               if (args) 
03420               {
03421                      msg->Flatten((char*)args, size);
03422                      MethodInfo *info = new MethodInfo(w, w, nsSwitchToUIThread::ONIME, argc, args);
03423                      if (info) 
03424                      {
03425                             t->CallMethodAsync(info);
03426                             NS_RELEASE(t);
03427                      }
03428                      delete[] args;
03429               }      
03430        }
03431 }
03432 #endif