source: trunk/third/mozilla/xpfe/bootstrap/nsNativeAppSupportMac.cpp @ 19518

Revision 19518, 12.9 KB checked in by rbasch, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19517, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Netscape Public License
6 * Version 1.1 (the "License"); you may not use this file except in
7 * compliance with the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/NPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is Mozilla Communicator client code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the NPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the NPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37#include "nsNativeAppSupport.h"
38#include "nsString.h"
39
40#include <Gestalt.h>
41#include <Dialogs.h>
42#include <Resources.h>
43#include <TextUtils.h>
44#include <ControlDefinitions.h>
45
46#include "nsAppShellCIDs.h"
47#include "nsCOMPtr.h"
48#include "nsNativeAppSupportBase.h"
49
50#include "nsIAppShellService.h"
51#include "nsIBaseWindow.h"
52#include "nsICmdLineService.h"
53#include "nsIDOMWindowInternal.h"
54#include "nsIDocShellTreeItem.h"
55#include "nsIDocShellTreeOwner.h"
56#include "nsIInterfaceRequestorUtils.h"
57#include "nsIObserver.h"
58#include "nsIServiceManager.h"
59#include "nsIWebNavigation.h"
60#include "nsIWidget.h"
61#include "nsIWindowMediator.h"
62
63static NS_DEFINE_CID(kCmdLineServiceCID,    NS_COMMANDLINE_SERVICE_CID);
64static NS_DEFINE_CID(kAppShellServiceCID,   NS_APPSHELL_SERVICE_CID);
65
66#define rSplashDialog 512
67
68static Boolean VersGreaterThan4(const FSSpec *fSpec);
69
70const OSType kNSCreator = 'MOSS';
71const OSType kMozCreator = 'MOZZ';
72const SInt16 kNSCanRunStrArrayID = 1000;
73const SInt16 kAnotherVersionStrIndex = 1;
74
75nsresult
76GetNativeWindowPointerFromDOMWindow(nsIDOMWindowInternal *window, WindowRef *nativeWindow);
77
78const SInt16 kNSOSVersErrsStrArrayID = 1001;
79
80enum {
81        eOSXVersTooOldErrIndex = 1,
82        eOSXVersTooOldExplanationIndex,
83        eContinueButtonTextIndex,
84        eQuitButtonTextIndex,
85        eCarbonLibVersTooOldIndex,
86        eCarbonLibVersTooOldExplanationIndex
87     };
88
89class nsNativeAppSupportMac : public nsNativeAppSupportBase,
90                              public nsIObserver
91{
92public:
93
94    // dialog items
95    enum {
96      eSplashPictureItem = 1,
97      eSplashStatusTextItem   
98    };
99   
100            nsNativeAppSupportMac();   
101    virtual ~nsNativeAppSupportMac();
102
103    NS_DECL_ISUPPORTS
104    NS_DECL_NSINATIVEAPPSUPPORT
105    NS_DECL_NSIOBSERVER
106
107protected:
108
109    DialogPtr mDialog;
110
111}; // class nsSplashScreenMac
112
113
114nsNativeAppSupportMac::nsNativeAppSupportMac()
115: mDialog(nsnull)
116{
117}
118
119
120nsNativeAppSupportMac::~nsNativeAppSupportMac()
121{
122  HideSplashScreen();
123}
124
125NS_IMPL_ISUPPORTS2(nsNativeAppSupportMac, nsINativeAppSupport, nsIObserver);
126
127/* boolean start (); */
128NS_IMETHODIMP nsNativeAppSupportMac::Start(PRBool *_retval)
129{
130  Str255 str1;
131  Str255 str2;
132  SInt16 outItemHit;
133  long   response = 0;
134  OSErr  err = ::Gestalt (gestaltSystemVersion, &response);
135  // check for at least MacOS 8.5
136  if ( err || response < 0x850)
137  {
138    ::StopAlert (5000, NULL);
139    *_retval = PR_FALSE;
140    return NS_ERROR_FAILURE;
141  }
142 
143#if TARGET_CARBON
144  // If we're running under Mac OS X check for at least Mac OS X 10.1
145  // If that fails display a StandardAlert giving the user the option
146  // to continue running the app or quitting
147  if (response >= 0x00001000 && response < 0x00001010)
148  {
149    // put up error dialog
150    Str255 continueButtonLabel;
151    Str255 quitButtonLabel;
152    ::GetIndString(str1, kNSOSVersErrsStrArrayID, eOSXVersTooOldErrIndex);
153    ::GetIndString(str2, kNSOSVersErrsStrArrayID, eOSXVersTooOldExplanationIndex);
154    ::GetIndString(continueButtonLabel, kNSOSVersErrsStrArrayID, eContinueButtonTextIndex);
155    ::GetIndString(quitButtonLabel, kNSOSVersErrsStrArrayID, eQuitButtonTextIndex);
156    if (StrLength(str1) && StrLength(str1) && StrLength(continueButtonLabel) && StrLength(quitButtonLabel))
157    {
158      AlertStdAlertParamRec pRec;
159     
160      pRec.movable      = nil;
161      pRec.filterProc   = nil;
162      pRec.defaultText  = continueButtonLabel;
163      pRec.cancelText   = quitButtonLabel;
164      pRec.otherText    = nil;
165      pRec.helpButton   = nil;
166      pRec.defaultButton = kAlertStdAlertOKButton;
167      pRec.cancelButton  = kAlertStdAlertCancelButton;
168      pRec.position      = 0;
169     
170      ::StandardAlert(kAlertNoteAlert, str1, str2, &pRec, &outItemHit);
171      if (outItemHit == kAlertStdAlertCancelButton)
172        return PR_FALSE;
173    }
174    else
175      return PR_FALSE;
176  }
177 
178  // We also check for CarbonLib version >= 1.4 if OS vers < 10.0
179  // which is always cause for the app to quit
180  if (response < 0x00001000)
181  {
182    err = ::Gestalt (gestaltCarbonVersion, &response);
183    if (err || response < 0x00000140)
184    {
185      // put up error dialog
186      ::GetIndString(str1, kNSOSVersErrsStrArrayID, eCarbonLibVersTooOldIndex);
187      ::GetIndString(str2, kNSOSVersErrsStrArrayID, eCarbonLibVersTooOldExplanationIndex);
188      if (StrLength(str1) && StrLength(str1))
189      {
190        ::StandardAlert(kAlertStopAlert, str1, str2, nil, &outItemHit);
191      }
192      return PR_FALSE;
193    }
194  }
195#endif
196
197  *_retval = PR_TRUE;
198  return NS_OK;
199}
200
201/* boolean stop (); */
202NS_IMETHODIMP nsNativeAppSupportMac::Stop(PRBool *_retval)
203{
204  *_retval = PR_TRUE;
205  return NS_OK;
206}
207
208/* void quit (); */
209NS_IMETHODIMP nsNativeAppSupportMac::Quit()
210{
211  return NS_OK;
212}
213
214/* [noscript] void ensureProfile (in nsICmdLineService aCmdService); */
215NS_IMETHODIMP nsNativeAppSupportMac::EnsureProfile(nsICmdLineService *aCmdService)
216{
217  return NS_OK;
218}
219
220/* void showSplashScreen (); */
221NS_IMETHODIMP nsNativeAppSupportMac::ShowSplashScreen()
222{
223  mDialog = ::GetNewDialog(rSplashDialog, nil, (WindowPtr)-1L);
224  if (!mDialog) return NS_ERROR_FAILURE;
225
226#if TARGET_CARBON
227  ::ShowWindow(GetDialogWindow(mDialog));
228  ::SetPortDialogPort(mDialog);
229#else
230  ::ShowWindow(mDialog);
231  ::SetPort(mDialog);
232#endif
233
234  ::DrawDialog(mDialog);    // we don't handle events for this dialog, so we
235                            // need to draw explicitly. Yuck.
236  return NS_OK;
237}
238
239/* void hideSplashScreen (); */
240NS_IMETHODIMP nsNativeAppSupportMac::HideSplashScreen()
241{
242  if (mDialog)
243  {
244    ::DisposeDialog( mDialog );
245    mDialog = nsnull;
246  }
247  return NS_OK;
248}
249
250/* attribute boolean isServerMode; */
251NS_IMETHODIMP nsNativeAppSupportMac::GetIsServerMode(PRBool *aIsServerMode)
252{
253  *aIsServerMode = PR_FALSE;
254  return NS_OK;;
255}
256NS_IMETHODIMP nsNativeAppSupportMac::SetIsServerMode(PRBool aIsServerMode)
257{
258  return NS_ERROR_NOT_IMPLEMENTED;
259}
260
261/* attribute boolean shouldShowUI; */
262NS_IMETHODIMP nsNativeAppSupportMac::GetShouldShowUI(PRBool *aShouldShowUI)
263{
264  *aShouldShowUI = PR_TRUE;
265  return NS_OK;;
266}
267
268NS_IMETHODIMP nsNativeAppSupportMac::SetShouldShowUI(PRBool aShouldShowUI)
269{
270  return NS_ERROR_NOT_IMPLEMENTED;
271}
272
273/* void startServerMode (); */
274NS_IMETHODIMP nsNativeAppSupportMac::StartServerMode()
275{
276  return NS_ERROR_NOT_IMPLEMENTED;
277}
278
279/* void onLastWindowClosing (in nsIXULWindow aWindow); */
280NS_IMETHODIMP nsNativeAppSupportMac::OnLastWindowClosing()
281{
282  return NS_OK;
283}
284
285NS_IMETHODIMP
286nsNativeAppSupportMac::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
287{
288  // update a string in the dialog
289 
290  nsCAutoString statusString;
291  statusString.AssignWithConversion(someData);
292
293  ControlHandle   staticTextControl;
294  OSErr err = ::GetDialogItemAsControl(mDialog, eSplashStatusTextItem, &staticTextControl);
295  if (err != noErr) return NS_OK;
296 
297  PRInt32   maxLen = statusString.Length();
298  if (maxLen > 254)
299    maxLen = 254;
300 
301  ::SetControlData(staticTextControl, 0, kControlStaticTextTextTag, maxLen, statusString.get());
302  ::DrawOneControl(staticTextControl);
303     
304  //::DrawDialog(mDialog);
305  return NS_OK;
306}
307
308NS_IMETHODIMP
309nsNativeAppSupportMac::ReOpen()
310{
311
312  PRBool haveUncollapsed = PR_FALSE;
313  PRBool haveOpenWindows = PR_FALSE;
314  PRBool done = PR_FALSE;
315 
316  nsCOMPtr<nsIWindowMediator>
317    wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
318  if (!wm)
319  {
320    return NS_ERROR_FAILURE;
321  }
322  else
323  {
324    nsCOMPtr<nsISimpleEnumerator> windowList;
325    wm->GetXULWindowEnumerator(nsnull, getter_AddRefs(windowList));
326    PRBool more;
327    windowList->HasMoreElements(&more);
328    while (more)
329    {
330      nsCOMPtr<nsISupports> nextWindow = nsnull;
331      windowList->GetNext(getter_AddRefs(nextWindow));
332      nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(nextWindow));
333                  if (!baseWindow)
334                  {
335        windowList->HasMoreElements(&more);
336        continue;
337      }
338      else
339      {
340        haveOpenWindows = PR_TRUE;
341      }
342
343      nsCOMPtr<nsIWidget> widget = nsnull;
344      baseWindow->GetMainWidget(getter_AddRefs(widget));
345      if (!widget)
346      {
347        windowList->HasMoreElements(&more);
348        continue;
349      }
350      WindowRef windowRef = (WindowRef)widget->GetNativeData(NS_NATIVE_DISPLAY);
351      if (!::IsWindowCollapsed(windowRef))
352      {
353        haveUncollapsed = PR_TRUE;
354        break;  //have un-minimized windows, nothing to do
355      }
356      windowList->HasMoreElements(&more);
357    } // end while
358       
359    if (!haveUncollapsed)
360    {
361      //uncollapse the most recenty used window
362      nsCOMPtr<nsIDOMWindowInternal> mru = nsnull;
363      wm->GetMostRecentWindow(nsnull, getter_AddRefs(mru));
364           
365      if (mru)
366      {       
367        WindowRef mruRef = nil;
368        GetNativeWindowPointerFromDOMWindow(mru, &mruRef);
369        if (mruRef)
370        {
371          ::CollapseWindow(mruRef, FALSE);
372          ::SelectWindow(mruRef);
373          done = PR_TRUE;
374        }
375      }
376     
377    } // end if have uncollapsed
378   
379    if (!haveOpenWindows && !done)
380    {   
381   
382      NS_WARNING("trying to open new window");
383      //use the bootstrap helpers to make the right kind(s) of window open       
384      nsresult rv = PR_FALSE;
385      nsCOMPtr<nsIAppShellService> appShell(do_GetService(kAppShellServiceCID, &rv));
386      if (!rv)
387      {
388        PRBool openedAWindow = PR_FALSE;
389        appShell->CreateStartupState(nsIAppShellService::SIZE_TO_CONTENT,
390                                        nsIAppShellService::SIZE_TO_CONTENT,
391                                        &openedAWindow);
392      }
393    }
394   
395  } // got window mediator
396  return NS_OK;
397}
398
399nsresult
400GetNativeWindowPointerFromDOMWindow(nsIDOMWindowInternal *a_window, WindowRef *a_nativeWindow)
401{
402    *a_nativeWindow = nil;
403    if (!a_window) return NS_ERROR_INVALID_ARG;
404   
405    nsCOMPtr<nsIWebNavigation> mruWebNav(do_GetInterface(a_window));
406    if (mruWebNav)
407    {
408      nsCOMPtr<nsIDocShellTreeItem> mruTreeItem(do_QueryInterface(mruWebNav));
409      nsCOMPtr<nsIDocShellTreeOwner> mruTreeOwner = nsnull;
410      mruTreeItem->GetTreeOwner(getter_AddRefs(mruTreeOwner));
411      if(mruTreeOwner)
412      {
413        nsCOMPtr<nsIBaseWindow> mruBaseWindow(do_QueryInterface(mruTreeOwner));
414        if (mruBaseWindow)
415        {
416          nsCOMPtr<nsIWidget> mruWidget = nsnull;
417          mruBaseWindow->GetMainWidget(getter_AddRefs(mruWidget));
418          if (mruWidget)
419          {
420            *a_nativeWindow = (WindowRef)mruWidget->GetNativeData(NS_NATIVE_DISPLAY);
421          }
422        }
423      }
424    }
425    return NS_OK;
426}
427
428#pragma mark -
429
430// Create and return an instance of class nsNativeAppSupportMac.
431nsresult NS_CreateNativeAppSupport(nsINativeAppSupport**aResult)
432{
433  if ( aResult )
434  { 
435      *aResult = new nsNativeAppSupportMac;
436      if ( *aResult )
437      {
438          NS_ADDREF( *aResult );
439          return NS_OK;
440      }
441      else
442      {
443          return NS_ERROR_OUT_OF_MEMORY;
444      }
445  }
446  else
447  {
448      return NS_ERROR_NULL_POINTER;
449  }
450}
451
452// Snagged from mozilla/xpinstall/wizrd/mac/src/SetupTypeWin.c
453// VersGreaterThan4 - utility function to test if it's >4.x running
454static Boolean VersGreaterThan4(const FSSpec *fSpec)
455{
456  Boolean result = false;
457  short fRefNum = 0;
458 
459  ::SetResLoad(false);
460  fRefNum = ::FSpOpenResFile(fSpec, fsRdPerm);
461  ::SetResLoad(true);
462  if (fRefNum != -1)
463  {
464    Handle  h;
465    h = ::Get1Resource('vers', 2);
466    if (h && **(unsigned short**)h >= 0x0500)
467      result = true;
468    ::CloseResFile(fRefNum);
469  }
470   
471  return result;
472}
Note: See TracBrowser for help on using the repository browser.