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