Back to index

lightning-sunbird  0.9+nobinonly
EmbeddedFrame.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the MRJ Carbon OJI Plugin.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corp.
00018  * Portions created by the Initial Developer are Copyright (C) 2001
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Patrick C. Beard <beard@netscape.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039        TopLevelFrame.cpp
00040        
00041        An MRJFrame sub-class that manages the behavior of a top-level window
00042        running inside the Communicator.
00043        
00044        by Patrick C. Beard.
00045  */
00046 
00047 #include <Controls.h>
00048 #include <Events.h>
00049 
00050 #include "EmbeddedFrame.h"
00051 #include "EmbeddedFramePluginInstance.h"
00052 #include "MRJPlugin.h"
00053 #include "MRJSession.h"
00054 
00055 #include "nsIPluginInstancePeer.h"
00056 #include "nsIOutputStream.h"
00057 #include "JSEvaluator.h"
00058 #include "LocalPort.h"
00059 #include "StringUtils.h"
00060 
00061 static void UnsetPort(GrafPtr port);
00062 
00063 EmbeddedFrame::EmbeddedFrame(MRJPluginInstance* pluginInstance, JMFrameRef frameRef, JMFrameKind kind,
00064                                                  const Rect* initialBounds, Boolean resizeable)
00065        :      MRJFrame(frameRef),
00066               mPluginInstance(NULL), mEvaluator(NULL), mWindow(NULL), mBounds(*initialBounds)
00067 {
00068        Boolean hasGoAway = true;
00069        SInt16 windowProc = documentProc;
00070        SInt16 resizeHeight = resizeable ? 15 : 0;
00071        
00072        switch (kind) {
00073        case eBorderlessModelessWindowFrame:
00074               hasGoAway = false;
00075               windowProc = plainDBox;
00076               // mBounds.bottom += resizeHeight;
00077               resizeable = false;
00078               break;
00079        case eModelessWindowFrame:
00080        case eModelessDialogFrame:
00081               hasGoAway = true;
00082               windowProc = resizeable ? zoomDocProc : documentProc;
00083               // mBounds.bottom += resizeHeight;
00084               break;
00085        case eModalWindowFrame:
00086               hasGoAway = true;
00087               // We have to allow resizeable modal windows.
00088               windowProc = resizeable ? documentProc : movableDBoxProc;
00089               break;
00090        }
00091 
00092 #if 0
00093        
00094        // Note:  opening a new window on a stream using the following code crashes 4.X browsers.
00095        // The problem is that the window has no URL assigned to it, and so some variables are
00096        // unitialized and the browser crashes in a call to strlen().
00097 
00098        class NewStreamMessage : public NativeMessage {
00099               nsIPluginInstancePeer* mPeer;
00100               const char* mType;
00101        public:
00102               NewStreamMessage(nsIPluginInstancePeer* peer, const char* type) : mPeer(peer), mType(type) {}
00103               
00104               virtual void execute() {
00105                      nsIOutputStream* output = NULL;
00106                      if (mPeer->NewStream(mType, "_new", &output) == NS_OK) {
00107                             // write some data to the stream.  
00108                             output->Close();
00109                             NS_RELEASE(output);
00110                      }
00111               }
00112        };
00113 
00114        // open a stream of type "application/x-java-frame", which should cause a full-screen plugin to get created for a Java frame's
00115        // behalf. communicate with the other instance via this stream.
00116        nsIPluginInstancePeer* peer = NULL;
00117        if (pluginInstance->GetPeer(&peer) == NS_OK) {
00118               NewStreamMessage msg(peer, "application/x-java-frame");
00119               pluginInstance->getSession()->sendMessage(&msg);
00120               NS_RELEASE(peer);
00121        }
00122 
00123 #else
00124        // var w = window.open('', '_new','resizable=no,status=no,width=200,height=200'); d = w.document; d.open(); d.write('<BODY MARGINHEIGHT=0 MARGINWIDTH=0>Hi</BODY>'); d.close();
00125 
00126        static UInt32 embeddedFrameCounter = 0;
00127 
00128        // Use JavaScript to create a window with an <EMBED TYPE="application/x-java-frame"> tag.
00129        const char* kEmbeddedFrameScript = "var w = window.open('','__MRJ_JAVA_FRAME_%d__','resizable=no,status=no,width=%d,height=%d,screenX=%d,screenY=%d');"
00130                                           "var d = w.document; d.open();"
00131                                           "d.writeln('<BODY BGCOLOR=#FFFFFF MARGINWIDTH=0 MARGINHEIGHT=0>&nbsp;<EMBED TYPE=application/x-java-frame WIDTH=%d HEIGHT=%d JAVAFRAME=%08X>');"
00132                                           "d.close();";
00133 
00134        int width = mBounds.right - mBounds.left;
00135        int height = mBounds.bottom - mBounds.top;
00136        int screenX = mBounds.left;
00137        int screenY = mBounds.top;
00138 
00139        char* script = new char[::strlen(kEmbeddedFrameScript) + 100];
00140        ::sprintf(script, kEmbeddedFrameScript, ++embeddedFrameCounter, width, height, screenX, screenY, width, height, this);
00141 
00142        JSEvaluator* evaluator = new JSEvaluator(pluginInstance);
00143        evaluator->AddRef();
00144        
00145        // create the window. It will have been created after returning from eval.
00146        const char* result = evaluator->eval(script);
00147        
00148        evaluator->Release();
00149        
00150        delete[] script;
00151 
00152 #endif
00153 
00154        if (mWindow != NULL) {
00155               Point zeroPt = { 0, 0 };
00156               ::JMSetFrameVisibility(mFrameRef, mWindow, zeroPt, NULL);
00157        }
00158 }
00159 
00160 EmbeddedFrame::~EmbeddedFrame()
00161 {
00162        if (mPluginInstance != NULL)
00163               mPluginInstance->setFrame(NULL);
00164 
00165        // make sure the window is hidden (and unregistered with the browser).
00166        showHide(false);
00167 
00168        // make sure this port isn't ever current again.
00169        ::UnsetPort(mWindow);
00170 
00171        // if (mWindow != NULL)
00172        //     ::DisposeWindow(mWindow);
00173 }
00174 
00175 void EmbeddedFrame::setSize(const Rect* newSize)
00176 {
00177        mBounds = *newSize;
00178 
00179        if (mWindow != NULL) {
00180               SInt16 width = newSize->right - newSize->left;
00181               SInt16 height = newSize->bottom - newSize->top;
00182               ::SizeWindow(mWindow, width, height, true);
00183               ::MoveWindow(mWindow, newSize->left, newSize->top, false);
00184        }
00185 }
00186 
00187 void EmbeddedFrame::invalRect(const Rect* invalidRect)
00188 {
00189        if (mWindow != NULL) {
00190               ::InvalRect(invalidRect);
00191        }
00192 }
00193 
00194 void EmbeddedFrame::showHide(Boolean visible)
00195 {
00196        if (mWindow != NULL && visible != IsWindowVisible(mWindow)) {
00197               if (visible) {
00198                      // Have to notify the browser that this window exists, so that it will receive events.
00199                      ::ShowWindow(mWindow);
00200                      ::SelectWindow(mWindow);
00201               } else {
00202                      ::HideWindow(mWindow);
00203               }
00204               
00205               // ::ShowHide(mWindow, visible);
00206        }
00207 }
00208 
00209 void EmbeddedFrame::setTitle(const StringPtr title)
00210 {
00211        if (mWindow != NULL) {
00212               ::SetWTitle(mWindow, title);
00213        }
00214 }
00215 
00216 void EmbeddedFrame::checkUpdate()
00217 {
00218 }
00219 
00220 void EmbeddedFrame::reorder(ReorderRequest request)
00221 {
00222        switch (request) {
00223        case eBringToFront:         /* bring the window to front */
00224               break;
00225        case eSendToBack:           /* send the window to back */
00226               break;
00227        case eSendBehindFront:      /* send the window behind the front window */
00228               break;
00229        }
00230 }
00231 
00232 void EmbeddedFrame::setResizeable(Boolean resizeable)
00233 {
00234        // this might have to recreate the window, no?
00235 }
00236 
00237 static void computeBounds(WindowRef window, Rect* bounds)
00238 {
00239        LocalPort port(window);
00240        port.Enter();
00241        
00242               Point position = { 0, 0 };
00243               ::LocalToGlobal(&position);
00244               
00245               *bounds = window->portRect;
00246        
00247        port.Exit();
00248        
00249        ::OffsetRect(bounds, position.h, position.v);
00250 }
00251 
00252 void EmbeddedFrame::activate(Boolean active)
00253 {
00254        focusEvent(active);
00255        MRJFrame::activate(active);
00256 }
00257 
00258 void EmbeddedFrame::click(const EventRecord* event)
00259 {
00260        Point where = event->where;
00261        SInt16 modifiers = event->modifiers;
00262        WindowRef hitWindow;
00263        short partCode = ::FindWindow(where, &hitWindow);
00264        switch (partCode) {
00265        case inContent:
00266               ::SelectWindow(mWindow);
00267               MRJFrame::click(event);
00268               break;
00269        case inDrag:
00270               Rect bounds = (**GetGrayRgn()).rgnBBox;
00271               DragWindow(mWindow, where, &bounds);
00272               computeBounds(mWindow, &mBounds);
00273               break;
00274        case inGrow:
00275               Rect limits = { 30, 30, 5000, 5000 };
00276               long result = GrowWindow(mWindow, where, &limits);
00277               if (result != 0) {
00278                      short width = (result & 0xFFFF);
00279                      short height = (result >> 16) & 0xFFFF;
00280                      Rect newBounds;
00281                      topLeft(newBounds) = topLeft(mBounds);
00282                      newBounds.right = newBounds.left + width;
00283                      newBounds.bottom = newBounds.top + height;
00284                      ::JMSetFrameSize(mFrameRef, &newBounds);
00285               }
00286               break;
00287        case inGoAway:
00288               if (::TrackGoAway(mWindow, where))
00289                      ::JMFrameGoAway(mFrameRef);
00290               break;
00291        case inZoomIn:
00292        case inZoomOut:
00293               if (::TrackBox(mWindow, where, partCode)) {
00294                      ZoomWindow(mWindow, partCode, true);
00295                      computeBounds(mWindow, &mBounds);
00296                      ::JMSetFrameSize(mFrameRef, &mBounds);
00297               }
00298               break;
00299        case inCollapseBox:
00300               break;
00301        }
00302 }
00303 
00304 void EmbeddedFrame::setPluginInstance(EmbeddedFramePluginInstance* embeddedInstance)
00305 {
00306        mPluginInstance = embeddedInstance;
00307 }
00308 
00309 void EmbeddedFrame::setWindow(WindowRef window)
00310 {
00311        mWindow = window;
00312 }
00313 
00314 WindowRef EmbeddedFrame::getWindow()
00315 {
00316        return mWindow;
00317 }
00318 
00319 GrafPtr EmbeddedFrame::getPort()
00320 {
00321        return mWindow;
00322 }
00323 
00324 static void UnsetPort(GrafPtr port)
00325 {
00326        GrafPtr curPort;
00327        ::GetPort(&curPort);
00328        if (curPort == port) {
00329               ::GetWMgrPort(&port);
00330               ::SetPort(port);
00331        }
00332 }