Back to index

lightning-sunbird  0.9+nobinonly
EmbedEventHandling.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Mozilla browser.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications, Inc.
00020  * Portions created by the Initial Developer are Copyright (C) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Conrad Carlen <ccarlen@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "EmbedEventHandling.h"
00041 #include "CTextInputEventHandler.h"
00042 
00043 #include "prthread.h"
00044 
00045 #if defined(__MWERKS__) && defined(DEBUG) && !TARGET_CARBON
00046 #include "SIOUX.h"
00047 #endif
00048 
00049 #include "nsIWidget.h"
00050 #include "nsIEventSink.h"
00051 #include "nsCOMPtr.h"
00052 
00053 // Static Variables
00054 
00055 WindowPtr        CEmbedEventAttachment::mLastAlienWindowClicked;
00056 
00057 //*****************************************************************************
00058 //  CEmbedEventAttachment
00059 //
00060 //  Handles events for windows popped up by Gecko which are not LWindows
00061 //
00062 //*****************************************************************************
00063 
00064 CEmbedEventAttachment::CEmbedEventAttachment()
00065 {
00066 }
00067 
00068 CEmbedEventAttachment::~CEmbedEventAttachment()
00069 {
00070 }
00071 
00072 
00073 //
00074 // GetTopWidget
00075 //
00076 // We've stashed the nsIWidget for the given windowPtr in the data 
00077 // properties of the window. Fetch it.
00078 //
00079 void
00080 CEmbedEventAttachment::GetTopWidget ( WindowPtr aWindow, nsIWidget** outWidget )
00081 {
00082   nsIWidget* topLevelWidget = nsnull;
00083        ::GetWindowProperty ( aWindow, 'MOSS', 'GEKO', sizeof(nsIWidget*), nsnull, (void*)&topLevelWidget);
00084   if ( topLevelWidget ) {
00085     *outWidget = topLevelWidget;
00086     NS_ADDREF(*outWidget);
00087   }
00088 }
00089 
00090 
00091 //
00092 // GetWindowEventSink
00093 //
00094 // We've stashed the nsIEventSink for the given windowPtr in the data of the
00095 // root control. Fetch it.
00096 //
00097 void
00098 CEmbedEventAttachment::GetWindowEventSink ( WindowPtr aWindow, nsIEventSink** outSink )
00099 {
00100   *outSink = nsnull;
00101   
00102   nsCOMPtr<nsIWidget> topWidget;
00103   GetTopWidget ( aWindow, getter_AddRefs(topWidget) );
00104   nsCOMPtr<nsIEventSink> sink ( do_QueryInterface(topWidget) );
00105   if ( sink ) {
00106     *outSink = sink;
00107     NS_ADDREF(*outSink);
00108   }
00109 }
00110 
00111 
00112 void CEmbedEventAttachment::ExecuteSelf(MessageT inMessage,
00113                                            void*        ioParam)
00114 {
00115        SetExecuteHost(true);
00116 
00117     EventRecord *inMacEvent;
00118     WindowPtr macWindowP;
00119        
00120        // 1. Handle the msg_AdjustCursor message. PowerPlant
00121        // sends this message to attachments which are attached
00122        // to views but not those attached to the application.
00123        // IMPORTANT: For this to be called, the application's
00124        // AdjustCursor() method must be overridden to send the
00125        // msg_AdjustCursor to its attachments.
00126               
00127     if (inMessage == msg_AdjustCursor) {
00128         inMacEvent = static_cast<EventRecord*>(ioParam);
00129         ::MacFindWindow(inMacEvent->where, &macWindowP);
00130         if (IsAlienGeckoWindow(macWindowP)) {
00131             nsCOMPtr<nsIEventSink> sink;
00132             GetWindowEventSink(macWindowP, getter_AddRefs(sink));
00133             if ( sink ) {
00134               PRBool handled = PR_FALSE;
00135               sink->DispatchEvent(inMacEvent, &handled);
00136               SetExecuteHost(false);
00137             }
00138         }
00139               
00140        } else if (inMessage == msg_Event) {
00141         inMacEvent = static_cast<EventRecord*>(ioParam);
00142 
00143 #if defined(__MWERKS__) && defined(DEBUG) && !TARGET_CARBON
00144         // 2. See if the event is for the console window.
00145         // Limit what types of events we send to it.
00146         if ((inMacEvent->what == mouseDown ||
00147             inMacEvent->what == updateEvt ||
00148             inMacEvent->what == activateEvt ||
00149             inMacEvent->what == keyDown) &&
00150             SIOUXHandleOneEvent(inMacEvent))
00151         {
00152             SetExecuteHost(false);
00153             return;
00154         }
00155 #endif
00156         
00157        // 3. Finally, see if we have an event for a Gecko window
00158        // which is not an LWindow. These get created by widget to
00159        // show pop-up list boxes - grrr. The following events are
00160        // sufficient for those.
00161                 
00162         switch (inMacEvent->what)
00163            {  
00164           case mouseDown:
00165           {
00166               mLastAlienWindowClicked = nil;
00167               // If an alien window is frontmost, as they always are when present,
00168               // Gecko needs to get the event - no matter where the click occured.
00169               // This is so the pop-up window (what these alien windows are used for)
00170               // will be rolled up on a click in the menu bar, title bar, etc.
00171               WindowPtr frontWindow = ::FrontWindow();
00172               if (IsAlienGeckoWindow(frontWindow)) {
00173                  nsCOMPtr<nsIEventSink> sink;
00174                  GetWindowEventSink(frontWindow, getter_AddRefs(sink));
00175                  if (sink) {
00176                    PRBool handled = PR_FALSE;
00177                    sink->DispatchEvent(inMacEvent, &handled);
00178                    SInt16 thePart = ::MacFindWindow(inMacEvent->where, &macWindowP);
00179                    if ((thePart == inContent) && (frontWindow == macWindowP)) {
00180                      // It the click was actually in an alien window - done processing
00181                      // Otherwise, let PowerPlant continue processing the click.
00182                      mLastAlienWindowClicked = macWindowP;
00183                      SetExecuteHost(false);
00184                   }
00185                }
00186             }
00187          }
00188          break;
00189 
00190                   case mouseUp:
00191                   {
00192                       if (mLastAlienWindowClicked) {
00193                 nsCOMPtr<nsIEventSink> sink;
00194                 GetWindowEventSink(mLastAlienWindowClicked, getter_AddRefs(sink));
00195                 if ( sink ) {
00196                   PRBool handled = PR_FALSE;
00197                           sink->DispatchEvent(inMacEvent, &handled);
00198                           mLastAlienWindowClicked = nil;
00199                           SetExecuteHost(false);
00200                         }
00201                       }
00202                   }
00203                      break;
00204                             
00205                   case updateEvt:
00206                   case activateEvt:
00207                   {
00208                     macWindowP = (WindowPtr)inMacEvent->message;
00209                          if (IsAlienGeckoWindow(macWindowP)) {
00210                 nsCOMPtr<nsIEventSink> sink;
00211                 GetWindowEventSink(macWindowP, getter_AddRefs(sink));
00212                 if ( sink ) {
00213                   PRBool handled = PR_FALSE;
00214                           sink->DispatchEvent(inMacEvent, &handled);
00215                           SetExecuteHost(false);
00216                         }
00217                          }
00218                      }
00219                      break;                      
00220            }
00221        }
00222 }
00223 
00224 
00225 Boolean CEmbedEventAttachment::IsAlienGeckoWindow(WindowPtr inMacWindow)
00226 {
00227     PRBool isAlien = PR_FALSE;
00228     
00229     // it's an 'alien' window if there's no LWindow object and there is
00230     // an nsIEventSink stashed in the window's root control.
00231     if (inMacWindow && !LWindow::FetchWindowObject(inMacWindow)) {
00232       nsCOMPtr<nsIEventSink> sink;
00233       GetWindowEventSink ( inMacWindow, getter_AddRefs(sink) );
00234       if ( sink )
00235         isAlien = PR_TRUE;   
00236     }
00237     
00238     return isAlien;
00239 }
00240 
00241 
00242 //*****************************************************************************
00243 //  CEmbedIdler
00244 //
00245 //
00246 //*****************************************************************************
00247 
00248 CEmbedIdler::CEmbedIdler()
00249 {
00250 }
00251 
00252 
00253 CEmbedIdler::~CEmbedIdler()
00254 {
00255 }
00256   
00257 void CEmbedIdler::SpendTime(const EventRecord&   inMacEvent)
00258 {
00259     ::PR_Sleep(PR_INTERVAL_NO_WAIT);
00260 }
00261 
00262 //*****************************************************************************
00263 // Initialization Function - Call at application startup. 
00264 //*****************************************************************************
00265 
00266 void InitializeEmbedEventHandling(LApplication* theApplication)
00267 {
00268     CEmbedEventAttachment *windowAttachment = new CEmbedEventAttachment;
00269     ThrowIfNil_(windowAttachment);
00270     theApplication->AddAttachment(windowAttachment);
00271 
00272     CEmbedIdler *embedIdler = new CEmbedIdler;
00273     ThrowIfNil_(embedIdler);
00274     embedIdler->StartIdling();
00275     
00276 #if TARGET_CARBON
00277     InitializeTextInputEventHandling();
00278 #endif
00279 
00280 }
00281