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
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/
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
15
* The Original Code is mozilla.org code.
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.
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.
36
* ***** END LICENSE BLOCK ***** */
38
#include "nsCocoaWindow.h"
40
#include "nsIServiceManager.h" // for drag and drop
41
#include "nsWidgetsCID.h"
42
#include "nsIDragService.h"
43
#include "nsIDragSession.h"
44
#include "nsIDragSessionMac.h"
45
#include "nsIScreen.h"
46
#include "nsIScreenManager.h"
47
#include "nsGUIEvent.h"
48
#include "nsCarbonHelpers.h"
49
#include "nsGFXUtils.h"
50
#include "nsMacResources.h"
51
#include "nsIRollupListener.h"
52
#import "nsChildView.h"
54
#include "nsIEventQueueService.h"
61
#include <Quickdraw.h>
63
#if UNIVERSAL_INTERFACES_VERSION < 0x0340
65
kEventWindowConstrain = 83
67
const UInt32 kWindowLiveResizeAttribute = (1L << 28);
70
// Define Class IDs -- i hate having to do this
71
static NS_DEFINE_CID(kCDragServiceCID, NS_DRAGSERVICE_CID);
72
//static const char *sScreenManagerContractID = "@mozilla.org/gfx/screenmanager;1";
76
#define topLeft(r) (((Point *) &(r))[0])
79
#define botRight(r) (((Point *) &(r))[1])
82
// externs defined in nsWindow.cpp
83
extern nsIRollupListener * gRollupListener;
84
extern nsIWidget * gRollupWidget;
86
static PRBool OnMacOSX();
88
#define kWindowPositionSlop 20
92
void SetDragActionBasedOnModifiers ( nsIDragService* inDragService, short inModifiers ) ;
96
// SetDragActionsBasedOnModifiers [static]
98
// Examines the MacOS modifier keys and sets the appropriate drag action on the
99
// drag session to copy/move/etc
102
SetDragActionBasedOnModifiers ( nsIDragService* inDragService, short inModifiers )
104
nsCOMPtr<nsIDragSession> dragSession;
105
inDragService->GetCurrentSession ( getter_AddRefs(dragSession) );
107
PRUint32 action = nsIDragService::DRAGDROP_ACTION_MOVE;
109
// force copy = option, alias = cmd-option, default is move
110
if ( inModifiers & optionKey ) {
111
if ( inModifiers & cmdKey )
112
action = nsIDragService::DRAGDROP_ACTION_LINK;
114
action = nsIDragService::DRAGDROP_ACTION_COPY;
117
dragSession->SetDragAction ( action );
120
} // SetDragActionBasedOnModifiers
125
//ļæ½ļæ½ļæ½ this should probably go into the drag session as a static
127
nsCocoaWindow :: DragTrackingHandler ( DragTrackingMessage theMessage, WindowPtr theWindow,
128
void *handlerRefCon, DragReference theDrag)
130
// holds our drag service across multiple calls to this callback. The reference to
131
// the service is obtained when the mouse enters the window and is released when
132
// the mouse leaves the window (or there is a drop). This prevents us from having
133
// to re-establish the connection to the service manager 15 times a second when
134
// handling the |kDragTrackingInWindow| message.
135
static nsIDragService* sDragService = nsnull;
137
nsCocoaWindow* geckoWindow = reinterpret_cast<nsCocoaWindow*>(handlerRefCon);
138
if ( !theWindow || !geckoWindow )
139
return dragNotAcceptedErr;
142
switch ( theMessage ) {
144
case kDragTrackingEnterHandler:
147
case kDragTrackingEnterWindow:
149
// get our drag service for the duration of the drag.
150
nsresult rv = nsServiceManager::GetService(kCDragServiceCID,
151
NS_GET_IID(nsIDragService),
152
(nsISupports **)&sDragService);
153
NS_ASSERTION ( sDragService, "Couldn't get a drag service, we're in biiig trouble" );
155
// tell the session about this drag
156
if ( sDragService ) {
157
sDragService->StartDragSession();
158
nsCOMPtr<nsIDragSessionMac> macSession ( do_QueryInterface(sDragService) );
160
macSession->SetDragReference ( theDrag );
163
// let gecko know that the mouse has entered the window so it
164
// can start tracking and sending enter/exit events to frames.
165
Point mouseLocGlobal;
166
::GetDragMouse ( theDrag, &mouseLocGlobal, nsnull );
167
geckoWindow->DragEvent ( NS_DRAGDROP_ENTER, mouseLocGlobal, 0L );
171
case kDragTrackingInWindow:
173
Point mouseLocGlobal;
174
::GetDragMouse ( theDrag, &mouseLocGlobal, nsnull );
176
::GetDragModifiers ( theDrag, &modifiers, nsnull, nsnull );
178
NS_ASSERTION ( sDragService, "If we don't have a drag service, we're fucked" );
180
// set the drag action on the service so the frames know what is going on
181
SetDragActionBasedOnModifiers ( sDragService, modifiers );
183
// clear out the |canDrop| property of the drag session. If it's meant to
184
// be, it will be set again.
185
nsCOMPtr<nsIDragSession> session;
186
sDragService->GetCurrentSession(getter_AddRefs(session));
187
NS_ASSERTION ( session, "If we don't have a drag session, we're fucked" );
189
session->SetCanDrop(PR_FALSE);
191
// pass into gecko for handling...
192
geckoWindow->DragEvent ( NS_DRAGDROP_OVER, mouseLocGlobal, modifiers );
196
case kDragTrackingLeaveWindow:
198
// tell the drag service that we're done with it.
199
if ( sDragService ) {
200
sDragService->EndDragSession();
202
// clear out the dragRef in the drag session. We are guaranteed that
203
// this will be called _after_ the drop has been processed (if there
204
// is one), so we're not destroying valuable information if the drop
205
// was in our window.
206
nsCOMPtr<nsIDragSessionMac> macSession ( do_QueryInterface(sDragService) );
208
macSession->SetDragReference ( 0 );
211
// let gecko know that the mouse has left the window so it
212
// can stop tracking and sending enter/exit events to frames.
213
Point mouseLocGlobal;
214
::GetDragMouse ( theDrag, &mouseLocGlobal, nsnull );
215
geckoWindow->DragEvent ( NS_DRAGDROP_EXIT, mouseLocGlobal, 0L );
217
::HideDragHilite ( theDrag );
219
// we're _really_ done with it, so let go of the service.
220
if ( sDragService ) {
221
nsServiceManager::ReleaseService(kCDragServiceCID, sDragService);
222
sDragService = nsnull;
228
} // case of each drag message
232
} // DragTrackingHandler
235
//ļæ½ļæ½ļæ½ this should probably go into the drag session as a static
237
nsCocoaWindow :: DragReceiveHandler (WindowPtr theWindow, void *handlerRefCon,
238
DragReference theDragRef)
240
// get our window back from the refCon
241
nsCocoaWindow* geckoWindow = reinterpret_cast<nsCocoaWindow*>(handlerRefCon);
242
if ( !theWindow || !geckoWindow )
243
return dragNotAcceptedErr;
245
// We make the assuption that the dragOver handlers have correctly set
246
// the |canDrop| property of the Drag Session. Before we dispatch the event
247
// into Gecko, check that value and either dispatch it or set the result
248
// code to "spring-back" and show the user the drag failed.
249
OSErr result = noErr;
250
nsCOMPtr<nsIDragService> dragService ( do_GetService(kCDragServiceCID) );
252
nsCOMPtr<nsIDragSession> dragSession;
253
dragService->GetCurrentSession ( getter_AddRefs(dragSession) );
255
// if the target has set that it can accept the drag, pass along
256
// to gecko, otherwise set phasers for failure.
257
PRBool canDrop = PR_FALSE;
258
if ( NS_SUCCEEDED(dragSession->GetCanDrop(&canDrop)) )
260
// pass the drop event along to Gecko
261
Point mouseLocGlobal;
262
::GetDragMouse ( theDragRef, &mouseLocGlobal, nsnull );
264
::GetDragModifiers ( theDragRef, &modifiers, nsnull, nsnull );
265
geckoWindow->DragEvent ( NS_DRAGDROP_DROP, mouseLocGlobal, modifiers );
268
result = dragNotAcceptedErr;
269
} // if a valid drag session
271
// we don't need the drag session anymore, the user has released the
272
// mouse and the event has already gone to gecko.
273
dragService->EndDragSession();
278
} // DragReceiveHandler
283
NS_IMPL_ISUPPORTS_INHERITED0(nsCocoaWindow, Inherited)
286
//-------------------------------------------------------------------------
288
// nsCocoaWindow constructor
290
//-------------------------------------------------------------------------
291
nsCocoaWindow::nsCocoaWindow()
293
, mWindowMadeHere(PR_FALSE)
294
, mIsDialog(PR_FALSE)
295
, mMacEventHandler(nsnull)
296
, mAcceptsActivation(PR_TRUE)
297
, mIsActive(PR_FALSE)
298
, mZoomOnShow(PR_FALSE)
301
mOffsetParent(nsnull)
302
, mIsDialog(PR_FALSE)
303
, mIsResizing(PR_FALSE)
304
, mWindowMadeHere(PR_FALSE)
308
mMacEventHandler.reset(new nsMacEventHandler(this));
309
WIDGET_SET_CLASSNAME("nsCocoaWindow");
311
// create handlers for drag&drop
312
mDragTrackingHandlerUPP = NewDragTrackingHandlerUPP(DragTrackingHandler);
313
mDragReceiveHandlerUPP = NewDragReceiveHandlerUPP(DragReceiveHandler);
318
//-------------------------------------------------------------------------
320
// nsCocoaWindow destructor
322
//-------------------------------------------------------------------------
323
nsCocoaWindow::~nsCocoaWindow()
325
if ( mWindow && mWindowMadeHere ) {
326
[mWindow autorelease];
327
[mDelegate autorelease];
334
::DisposeWindow(mWindowPtr);
336
// clean up DragManager stuff
337
if ( mDragTrackingHandlerUPP ) {
338
::RemoveTrackingHandler ( mDragTrackingHandlerUPP, mWindowPtr );
339
::DisposeDragTrackingHandlerUPP ( mDragTrackingHandlerUPP );
341
if ( mDragReceiveHandlerUPP ) {
342
::RemoveReceiveHandler ( mDragReceiveHandlerUPP, mWindowPtr );
343
::DisposeDragReceiveHandlerUPP ( mDragReceiveHandlerUPP );
346
nsMacMessageSink::RemoveRaptorWindowFromList(mWindowPtr);
354
//-------------------------------------------------------------------------
356
// Utility method for implementing both Create(nsIWidget ...) and
357
// Create(nsNativeWidget...)
358
//-------------------------------------------------------------------------
360
nsresult nsCocoaWindow::StandardCreate(nsIWidget *aParent,
362
EVENT_CALLBACK aHandleEventFunction,
363
nsIDeviceContext *aContext,
364
nsIAppShell *aAppShell,
365
nsIToolkit *aToolkit,
366
nsWidgetInitData *aInitData,
367
nsNativeWidget aNativeParent)
369
Inherited::BaseCreate ( aParent, aRect, aHandleEventFunction, aContext, aAppShell,
370
aToolkit, aInitData );
372
if ( !aNativeParent ) {
373
mOffsetParent = aParent;
375
nsWindowType windowType = eWindowType_toplevel;
377
mWindowType = aInitData->mWindowType;
378
// if a toplevel window was requested without a titlebar, use a dialog windowproc
379
if (aInitData->mWindowType == eWindowType_toplevel &&
380
(aInitData->mBorderStyle == eBorderStyle_none ||
381
aInitData->mBorderStyle != eBorderStyle_all && !(aInitData->mBorderStyle & eBorderStyle_title)))
382
windowType = eWindowType_dialog;
385
mWindowType = (mIsDialog ? eWindowType_dialog : eWindowType_toplevel);
387
// create the cocoa window
389
rect.origin.x = rect.origin.y = 1.0;
390
rect.size.width = rect.size.height = 1.0;
391
unsigned int features = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask
392
| NSResizableWindowMask;
393
if ( mWindowType == eWindowType_popup || mWindowType == eWindowType_invisible )
396
// XXXdwh Just don't make popup windows yet. They mess up the world.
397
if (mWindowType == eWindowType_popup)
400
mWindow = [[NSWindow alloc] initWithContentRect:rect styleMask:features
401
backing:NSBackingStoreBuffered defer:NO];
403
// Popups will receive a "close" message when an app terminates
404
// that causes an extra release to occur. Make sure popups
405
// are set not to release when closed.
407
[mWindow setReleasedWhenClosed: NO];
409
// create a quickdraw view as the toplevel content view of the window
410
NSQuickDrawView* content = [[[NSQuickDrawView alloc] init] autorelease];
411
[content setFrame:[[mWindow contentView] frame]];
412
[mWindow setContentView:content];
414
// register for mouse-moved events. The default is to ignore them for perf reasons.
415
[mWindow setAcceptsMouseMovedEvents:YES];
417
// setup our notification delegate. Note that setDelegate: does NOT retain.
418
mDelegate = [[WindowDelegate alloc] initWithGeckoWindow:this];
419
[mWindow setDelegate:mDelegate];
421
mWindowMadeHere = PR_TRUE;
425
short bottomPinDelta = 0; // # of pixels to subtract to pin window bottom
426
nsCOMPtr<nsIToolkit> theToolkit = aToolkit;
428
// build the main native window
429
if (aNativeParent == nsnull)
431
nsWindowType windowType;
434
mWindowType = aInitData->mWindowType;
435
// if a toplevel window was requested without a titlebar, use a dialog windowproc
436
if (aInitData->mWindowType == eWindowType_toplevel &&
437
(aInitData->mBorderStyle == eBorderStyle_none ||
438
aInitData->mBorderStyle != eBorderStyle_all && !(aInitData->mBorderStyle & eBorderStyle_title)))
439
windowType = eWindowType_dialog;
441
mWindowType = (mIsDialog ? eWindowType_dialog : eWindowType_toplevel);
443
short wDefProcID = kWindowDocumentProc;
450
case eWindowType_popup:
451
// We're a popup, context menu, etc. Sets
452
// mAcceptsActivation to false so we don't activate the window
454
mOffsetParent = aParent;
456
theToolkit = getter_AddRefs(aParent->GetToolkit());
458
mAcceptsActivation = PR_FALSE;
463
wDefProcID = kWindowSimpleProc;
465
wDefProcID = plainDBox;
469
case eWindowType_child:
470
wDefProcID = plainDBox;
476
case eWindowType_dialog:
479
// Prior to Carbon, defProcs were solely about appearance. If told to create a dialog,
480
// we could use, for example, |kWindowMovableModalDialogProc| even if the dialog wasn't
481
// supposed to be modal. Carbon breaks this assumption, enforcing modality when using these
482
// particular proc ids. As a result, when compiling under Carbon we have to use the
483
// standard window proc id's and below, after we have a windowPtr, we'll hide the closebox
484
// that comes with the standard window proc.
486
// I'm making the assumption here that any dialog created w/out a titlebar is modal and am
487
// therefore keeping the old modal dialog proc. I'm only special-casing dialogs with a
488
// titlebar since those are the only ones that might end up not being modal.
490
switch (aInitData->mBorderStyle)
492
case eBorderStyle_none:
493
wDefProcID = kWindowModalDialogProc;
496
case eBorderStyle_all:
498
wDefProcID = kWindowGrowDocumentProc;
500
wDefProcID = kWindowMovableModalGrowProc; // should we add a close box (kWindowGrowDocumentProc) ?
504
case eBorderStyle_default:
505
wDefProcID = kWindowModalDialogProc;
509
// we ignore the close flag here, since mac dialogs should never have a close box.
510
switch(aInitData->mBorderStyle & (eBorderStyle_resizeh | eBorderStyle_title))
512
// combinations of individual options.
513
case eBorderStyle_title:
515
wDefProcID = kWindowDocumentProc;
517
wDefProcID = kWindowMovableModalDialogProc;
521
case eBorderStyle_resizeh:
522
case (eBorderStyle_title | eBorderStyle_resizeh):
524
wDefProcID = kWindowGrowDocumentProc;
526
wDefProcID = kWindowMovableModalGrowProc; // this is the only kind of resizable dialog.
531
NS_WARNING("Unhandled combination of window flags");
538
wDefProcID = kWindowModalDialogProc;
539
goAwayFlag = true; // revisit this below
542
hOffset = kDialogMarginWidth;
543
vOffset = kDialogTitleBarHeight;
546
case eWindowType_toplevel:
548
aInitData->mBorderStyle != eBorderStyle_all &&
549
aInitData->mBorderStyle != eBorderStyle_default &&
550
(aInitData->mBorderStyle == eBorderStyle_none ||
551
!(aInitData->mBorderStyle & eBorderStyle_resizeh)))
552
wDefProcID = kWindowDocumentProc;
554
wDefProcID = kWindowFullZoomGrowDocumentProc;
556
hOffset = kWindowMarginWidth;
557
vOffset = kWindowTitleBarHeight;
560
case eWindowType_invisible:
565
// now turn off some default features if requested by aInitData
566
if (aInitData && aInitData->mBorderStyle != eBorderStyle_all)
568
if (aInitData->mBorderStyle == eBorderStyle_none ||
569
aInitData->mBorderStyle == eBorderStyle_default &&
570
windowType == eWindowType_dialog ||
571
!(aInitData->mBorderStyle & eBorderStyle_close))
576
nsRectToMacRect(aRect, wRect);
578
if (eWindowType_popup != mWindowType)
579
::OffsetRect(&wRect, hOffset, vOffset + ::GetMBarHeight());
581
::OffsetRect(&wRect, hOffset, vOffset);
583
nsCOMPtr<nsIScreenManager> screenmgr = do_GetService(sScreenManagerContractID);
585
nsCOMPtr<nsIScreen> screen;
586
//screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
587
screenmgr->ScreenForRect(wRect.left, wRect.top,
588
wRect.right - wRect.left, wRect.bottom - wRect.top,
589
getter_AddRefs(screen));
591
PRInt32 left, top, width, height;
592
screen->GetAvailRect(&left, &top, &width, &height);
593
if (wRect.bottom > top+height) {
594
bottomPinDelta = wRect.bottom - (top+height);
595
wRect.bottom -= bottomPinDelta;
599
mWindowPtr = ::NewCWindow(nil, &wRect, "\p", false, wDefProcID, (WindowRef)-1, goAwayFlag, (long)nsnull);
600
mWindowMadeHere = PR_TRUE;
604
mWindowPtr = (WindowPtr)aNativeParent;
605
mWindowMadeHere = PR_FALSE;
608
if (mWindowPtr == nsnull)
609
return NS_ERROR_OUT_OF_MEMORY;
611
nsMacMessageSink::AddRaptorWindowToList(mWindowPtr, this);
613
// create the root control
614
ControlHandle rootControl = nil;
615
if (GetRootControl(mWindowPtr, &rootControl) != noErr)
617
OSErr err = CreateRootControl(mWindowPtr, &rootControl);
618
NS_ASSERTION(err == noErr, "Error creating window root control");
621
// reset the coordinates to (0,0) because it's the top level widget
622
// and adjust for any adjustment required to requested window bottom
623
nsRect bounds(0, 0, aRect.width, aRect.height - bottomPinDelta);
626
// (note: aParent is ignored. Mac (real) windows don't want parents)
627
Inherited::StandardCreate(nil, bounds, aHandleEventFunction, aContext, aAppShell, theToolkit, aInitData);
630
if ( mWindowType == eWindowType_popup ) {
631
// OSX enforces window layering so we have to make sure that popups can
632
// appear over modal dialogs (at the top of the layering chain). Create
633
// the popup like normal and change its window class to the modal layer.
635
// XXX This needs to use ::SetWindowGroup() when we move to headers that
637
::SetWindowClass(mWindowPtr, kModalWindowClass);
639
else if ( mWindowType == eWindowType_dialog ) {
640
// Dialogs on mac don't have a close box, but we probably used a defproc above that
641
// contains one. Thankfully, carbon lets us turn it off after the window has been
642
// created. Do so. We currently leave the collapse widget for all dialogs.
643
::ChangeWindowAttributes(mWindowPtr, 0L, kWindowCloseBoxAttribute );
646
// Setup the live window resizing
647
if ( mWindowType == eWindowType_toplevel || mWindowType == eWindowType_invisible ) {
648
WindowAttributes removeAttributes = kWindowNoAttributes;
649
if ( mWindowType == eWindowType_invisible )
650
removeAttributes |= kWindowInWindowMenuAttribute;
651
::ChangeWindowAttributes ( mWindowPtr, kWindowLiveResizeAttribute, removeAttributes );
653
EventTypeSpec windEventList[] = { {kEventClassWindow, kEventWindowBoundsChanged},
654
{kEventClassWindow, kEventWindowConstrain} };
655
EventTypeSpec scrollEventList[] = { {kEventClassMouse, kEventMouseWheelMoved} };
656
OSStatus err1 = ::InstallWindowEventHandler ( mWindowPtr, NewEventHandlerUPP(WindowEventHandler), 2, windEventList, this, NULL );
657
OSStatus err2 = ::InstallWindowEventHandler ( mWindowPtr, NewEventHandlerUPP(ScrollEventHandler), 1, scrollEventList, this, NULL );
658
// note, passing NULL as the final param to IWEH() causes the UPP to be disposed automatically
659
// when the event target (the window) goes away. See CarbonEvents.h for info.
661
NS_ASSERTION(err1 == noErr && err2 == noErr, "Couldn't install Carbon Event handlers");
666
// register tracking and receive handlers with the native Drag Manager
667
if ( mDragTrackingHandlerUPP ) {
668
OSErr result = ::InstallTrackingHandler ( mDragTrackingHandlerUPP, mWindowPtr, this );
669
NS_ASSERTION ( result == noErr, "can't install drag tracking handler");
671
if ( mDragReceiveHandlerUPP ) {
672
OSErr result = ::InstallReceiveHandler ( mDragReceiveHandlerUPP, mWindowPtr, this );
673
NS_ASSERTION ( result == noErr, "can't install drag receive handler");
676
// If we're a popup, we don't want a border (we want CSS to draw it for us). So
677
// install our own window defProc.
678
if ( mWindowType == eWindowType_popup )
679
InstallBorderlessDefProc(mWindowPtr);
690
nsCocoaWindow :: ScrollEventHandler ( EventHandlerCallRef inHandlerChain, EventRef inEvent, void* userData )
692
EventMouseWheelAxis axis = kEventMouseWheelAxisY;
695
OSErr err1 = ::GetEventParameter ( inEvent, kEventParamMouseWheelAxis, typeMouseWheelAxis,
696
NULL, sizeof(EventMouseWheelAxis), NULL, &axis );
697
OSErr err2 = ::GetEventParameter ( inEvent, kEventParamMouseWheelDelta, typeLongInteger,
698
NULL, sizeof(SInt32), NULL, &delta );
699
OSErr err3 = ::GetEventParameter ( inEvent, kEventParamMouseLocation, typeQDPoint,
700
NULL, sizeof(Point), NULL, &mouseLoc );
702
if ( err1 == noErr && err2 == noErr && err3 == noErr ) {
703
nsCocoaWindow* self = NS_REINTERPRET_CAST(nsCocoaWindow*, userData);
705
self->mMacEventHandler->Scroll ( axis, delta, mouseLoc );
709
} // ScrollEventHandler
713
nsCocoaWindow :: WindowEventHandler ( EventHandlerCallRef inHandlerChain, EventRef inEvent, void* userData )
715
OSStatus retVal = noErr;
717
WindowRef myWind = NULL;
718
::GetEventParameter ( inEvent, kEventParamDirectObject, typeWindowRef, NULL, sizeof(myWind), NULL, &myWind );
720
UInt32 what = ::GetEventKind ( inEvent );
723
case kEventWindowBoundsChanged:
725
// are we moving or resizing the window? we only care about resize.
726
UInt32 attributes = 0;
727
::GetEventParameter ( inEvent, kEventParamAttributes, typeUInt32, NULL, sizeof(attributes), NULL, &attributes );
728
if ( attributes & kWindowBoundsChangeSizeChanged ) {
730
::InvalWindowRect(myWind, ::GetWindowPortBounds(myWind, &bounds));
732
// resize the window and repaint
733
nsCocoaWindow* self = NS_REINTERPRET_CAST(nsCocoaWindow*, userData);
734
if ( self && !self->mResizeIsFromUs ) {
735
self->mMacEventHandler->ResizeEvent(myWind);
736
self->mMacEventHandler->UpdateEvent();
742
case kEventWindowConstrain:
744
// Ignore this event if we're an invisible window, otherwise pass along the
745
// chain to ensure it's onscreen.
746
nsCocoaWindow* self = NS_REINTERPRET_CAST(nsCocoaWindow*, userData);
748
if ( self->mWindowType != eWindowType_invisible )
749
retVal = ::CallNextEventHandler( inHandlerChain, inEvent );
758
} // case of which event?
763
} // WindowEventHandler
768
//-------------------------------------------------------------------------
770
// Create a nsCocoaWindow using a native window provided by the application
772
//-------------------------------------------------------------------------
773
NS_IMETHODIMP nsCocoaWindow::Create(nsNativeWidget aNativeParent,
775
EVENT_CALLBACK aHandleEventFunction,
776
nsIDeviceContext *aContext,
777
nsIAppShell *aAppShell,
778
nsIToolkit *aToolkit,
779
nsWidgetInitData *aInitData)
781
return(StandardCreate(nsnull, aRect, aHandleEventFunction,
782
aContext, aAppShell, aToolkit, aInitData,
787
NS_IMETHODIMP nsCocoaWindow::Create(nsIWidget* aParent,
789
EVENT_CALLBACK aHandleEventFunction,
790
nsIDeviceContext *aContext,
791
nsIAppShell *aAppShell,
792
nsIToolkit *aToolkit,
793
nsWidgetInitData *aInitData)
795
return(StandardCreate(aParent, aRect, aHandleEventFunction,
796
aContext, aAppShell, aToolkit, aInitData,
802
nsCocoaWindow::GetNativeData(PRUint32 aDataType)
804
void* retVal = nsnull;
806
switch ( aDataType ) {
808
// to emulate how windows works, we always have to return a NSView
809
// for NS_NATIVE_WIDGET
810
case NS_NATIVE_WIDGET:
811
case NS_NATIVE_DISPLAY:
812
retVal = [mWindow contentView];
815
case NS_NATIVE_WINDOW:
819
case NS_NATIVE_GRAPHIC: // quickdraw port of top view (for now)
820
retVal = [[mWindow contentView] qdPort];
824
case NS_NATIVE_REGION:
825
retVal = (void*)mVisRegion;
828
case NS_NATIVE_COLORMAP:
832
case NS_NATIVE_OFFSETX:
833
point.MoveTo(mBounds.x, mBounds.y);
834
LocalToWindowCoordinate(point);
835
retVal = (void*)point.x;
838
case NS_NATIVE_OFFSETY:
839
point.MoveTo(mBounds.x, mBounds.y);
840
LocalToWindowCoordinate(point);
841
retVal = (void*)point.y;
844
case NS_NATIVE_PLUGIN_PORT:
845
// this needs to be a combination of the port and the offsets.
846
if (mPluginPort == nsnull)
847
mPluginPort = new nsPluginPort;
849
point.MoveTo(mBounds.x, mBounds.y);
850
LocalToWindowCoordinate(point);
852
// for compatibility with 4.X, this origin is what you'd pass
854
mPluginPort->port = ::GetWindowPort(mWindowPtr);
855
mPluginPort->portx = -point.x;
856
mPluginPort->porty = -point.y;
858
retVal = (void*)mPluginPort;
867
nsCocoaWindow::IsVisible(PRBool & aState)
873
//-------------------------------------------------------------------------
875
// Hide or show this window
877
//-------------------------------------------------------------------------
878
NS_IMETHODIMP nsCocoaWindow::Show(PRBool bState)
881
[mWindow orderFront:NULL];
883
[mWindow orderOut:NULL];
888
// we need to make sure we call ::Show/HideWindow() to generate the
889
// necessary activate/deactivate events. Calling ::ShowHide() is
890
// not adequate, unless we don't want activation (popups). (pinkerton).
891
if ( bState && !mBounds.IsEmpty() ) {
892
if ( mAcceptsActivation )
893
::ShowWindow(mWindowPtr);
895
::ShowHide(mWindowPtr, true);
896
::BringToFront(mWindowPtr); // competes with ComeToFront, but makes popups work
899
SetSizeMode(nsSizeMode_Maximized);
900
mZoomOnShow = PR_FALSE;
905
// when a toplevel window goes away, make sure we rollup any popups that may
906
// be lurking. We want to catch this here because we're guaranteed that
907
// we hide a window before we destroy it, and doing it here more closely
908
// approximates where we do the same thing on windows.
909
if ( mWindowType == eWindowType_toplevel ) {
910
if ( gRollupListener )
911
gRollupListener->Rollup();
912
NS_IF_RELEASE(gRollupListener);
913
NS_IF_RELEASE(gRollupWidget);
915
::HideWindow(mWindowPtr);
924
NS_IMETHODIMP nsCocoaWindow::Enable(PRBool aState)
930
NS_IMETHODIMP nsCocoaWindow::IsEnabled(PRBool *aState)
939
NS_METHOD nsWindow::Minimize(void)
944
NS_METHOD nsWindow::Maximize(void)
949
NS_METHOD nsWindow::Restore(void)
955
NS_IMETHODIMP nsCocoaWindow::ConstrainPosition(PRBool aAllowSlop,
956
PRInt32 *aX, PRInt32 *aY)
959
if (eWindowType_popup == mWindowType || !mWindowMadeHere)
962
// Sanity check against screen size
963
// make sure the window stays visible
965
// get the window bounds
967
::GetWindowPortBounds(mWindowPtr, &portBounds);
969
short windowWidth = portBounds.right - portBounds.left;
970
short windowHeight = portBounds.bottom - portBounds.top;
972
// now get our playing field. use the current screen, or failing that for any reason,
973
// the GrayRgn (which of course is arguably more correct but has drawbacks as well)
975
nsCOMPtr<nsIScreenManager> screenmgr = do_GetService(sScreenManagerContractID);
977
nsCOMPtr<nsIScreen> screen;
978
PRInt32 left, top, width, height, fullHeight;
980
// zero size rects can happen during window creation, and confuse
981
// the screen manager
982
width = windowWidth > 0 ? windowWidth : 1;
983
height = windowHeight > 0 ? windowHeight : 1;
984
screenmgr->ScreenForRect(*aX, *aY, width, height,
985
getter_AddRefs(screen));
987
screen->GetAvailRect(&left, &top, &width, &height);
988
screen->GetRect(&left, &top, &width, &fullHeight);
989
screenRect.left = left;
990
screenRect.right = left+width;
991
screenRect.top = top;
992
screenRect.bottom = top+height;
995
::GetRegionBounds(::GetGrayRgn(), &screenRect);
997
pos = screenRect.left;
998
if (windowWidth > kWindowPositionSlop)
999
pos -= windowWidth - kWindowPositionSlop;
1002
else if (*aX >= screenRect.right - kWindowPositionSlop)
1003
*aX = screenRect.right - kWindowPositionSlop;
1005
pos = screenRect.top;
1006
if (windowHeight > kWindowPositionSlop)
1007
pos -= windowHeight - kWindowPositionSlop;
1010
else if (*aY >= screenRect.bottom - kWindowPositionSlop)
1011
*aY = screenRect.bottom - kWindowPositionSlop;
1017
//-------------------------------------------------------------------------
1021
//-------------------------------------------------------------------------
1022
//-------------------------------------------------------------------------
1024
//-------------------------------------------------------------------------
1025
NS_IMETHODIMP nsCocoaWindow::Move(PRInt32 aX, PRInt32 aY)
1028
// if we're a popup, we have to convert from our parent widget's coord
1029
// system to the global coord system first because the (x,y) we're given
1030
// is in its coordinate system.
1031
if ( mWindowType == eWindowType_popup ) {
1032
nsRect localRect, globalRect;
1035
if ( mOffsetParent ) {
1036
mOffsetParent->WidgetToScreen(localRect,globalRect);
1042
NSPoint coord = {aX, aY};
1043
//coord = [mWindow convertBaseToScreen:coord];
1044
//printf("moving to %d %d. screen coords %f %f\n", aX, aY, coord.x, coord.y);
1046
//FIXME -- ensure it's on the screen. Cocoa automatically corrects for windows
1047
// with title bars, but for other windows, we have to do this...
1049
// the point we have assumes that the screen origin is the top-left. Well,
1050
// it's not. Use the screen object to convert.
1051
//FIXME -- doesn't work on monitors other than primary
1052
NSRect screenRect = [[NSScreen mainScreen] frame];
1053
coord.y = (screenRect.origin.y + screenRect.size.height) - coord.y;
1054
//printf("final coords %f %f\n", coord.x, coord.y);
1055
//printf("- window coords before %f %f\n", [mWindow frame].origin.x, [mWindow frame].origin.y);
1056
[mWindow setFrameTopLeftPoint:coord];
1057
//printf("- window coords after %f %f\n", [mWindow frame].origin.x, [mWindow frame].origin.y);
1061
StPortSetter setOurPortForLocalToGlobal ( mWindowPtr );
1063
if (eWindowType_popup == mWindowType) {
1064
PRInt32 xOffset=0,yOffset=0;
1065
nsRect localRect,globalRect;
1067
// convert to screen coordinates
1070
localRect.width = 100;
1071
localRect.height = 100;
1073
if ( mOffsetParent ) {
1074
mOffsetParent->WidgetToScreen(localRect,globalRect);
1078
// there is a bug on OSX where if we call ::MoveWindow() with the same
1079
// coordinates (within a pixel or two) as a window's current location, it will
1080
// move to (0,0,-1,-1). The fix is to not move the window if we're already
1081
// there. (radar# 2669004)
1083
const PRInt32 kMoveThreshold = 2;
1085
const PRInt32 kMoveThreshold = 0;
1088
::GetWindowBounds ( mWindowPtr, kWindowGlobalPortRgn, &currBounds );
1089
if ( abs(currBounds.left-aX) > kMoveThreshold || abs(currBounds.top-aY) > kMoveThreshold ) {
1090
::MoveWindow(mWindowPtr, aX, aY, false);
1093
::GetWindowBounds ( mWindowPtr, kWindowGlobalPortRgn, &newBounds );
1098
} else if (mWindowMadeHere) {
1100
::GetWindowPortBounds(mWindowPtr, &portBounds);
1103
aX += kDialogMarginWidth;
1104
aY += kDialogTitleBarHeight;
1106
aX += kWindowMarginWidth;
1107
aY += kWindowTitleBarHeight;
1110
nsCOMPtr<nsIScreenManager> screenmgr = do_GetService(sScreenManagerContractID);
1112
nsCOMPtr<nsIScreen> screen;
1113
PRInt32 left, top, width, height, fullTop;
1114
// adjust for unset bounds, which confuses the screen manager
1115
width = portBounds.right - portBounds.left;
1116
height = portBounds.bottom - portBounds.top;
1117
if (height <= 0) height = 1;
1118
if (width <= 0) width = 1;
1120
screenmgr->ScreenForRect(aX, aY, width, height,
1121
getter_AddRefs(screen));
1123
screen->GetAvailRect(&left, &top, &width, &height);
1124
screen->GetRect(&left, &fullTop, &width, &height);
1129
// move the window if it has not been moved yet
1130
// (ie. if this function isn't called in response to a DragWindow event)
1131
Point macPoint = topLeft(portBounds);
1132
::LocalToGlobal(&macPoint);
1133
if (macPoint.h != aX || macPoint.v != aY)
1134
::MoveWindow(mWindowPtr, aX, aY, false);
1136
// propagate the event in global coordinates
1137
Inherited::Move(aX, aY);
1139
// reset the coordinates to (0,0) because it's the top level widget
1147
//-------------------------------------------------------------------------
1149
// Position the window behind the given window
1151
//-------------------------------------------------------------------------
1152
NS_METHOD nsCocoaWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
1153
nsIWidget *aWidget, PRBool aActivate)
1157
WindowPtr behind = (WindowPtr)aWidget->GetNativeData(NS_NATIVE_DISPLAY);
1158
::SendBehind(mWindowPtr, behind);
1159
::HiliteWindow(mWindowPtr, FALSE);
1161
if (::FrontWindow() != mWindowPtr)
1162
::SelectWindow(mWindowPtr);
1168
//-------------------------------------------------------------------------
1172
//-------------------------------------------------------------------------
1173
NS_METHOD nsCocoaWindow::SetSizeMode(PRInt32 aMode)
1177
PRInt32 currentMode;
1179
if (aMode == nsSizeMode_Minimized) // unlikely on the Mac
1180
return NS_ERROR_UNEXPECTED;
1182
// already done? it's bad to rezoom a window, so do nothing
1183
rv = nsBaseWidget::GetSizeMode(¤tMode);
1184
if (NS_SUCCEEDED(rv) && currentMode == aMode)
1188
/* zooming on the Mac doesn't seem to work until the window is visible.
1189
the rest of the app is structured to zoom before the window is visible
1190
to avoid flashing. here's where we defeat that. */
1191
if (aMode == nsSizeMode_Maximized)
1192
mZoomOnShow = PR_TRUE;
1195
rv = nsBaseWidget::SetSizeMode(aMode);
1196
if (NS_SUCCEEDED(rv)) {
1197
if (aMode == nsSizeMode_Maximized) {
1198
CalculateAndSetZoomedSize();
1199
::ZoomWindow(mWindowPtr, inZoomOut, ::FrontWindow() == mWindowPtr);
1201
::ZoomWindow(mWindowPtr, inZoomIn, ::FrontWindow() == mWindowPtr);
1202
::GetWindowPortBounds(mWindowPtr, &macRect);
1203
Resize(macRect.right - macRect.left, macRect.bottom - macRect.top, PR_FALSE);
1211
void nsCocoaWindow::CalculateAndSetZoomedSize()
1214
StPortSetter setOurPort(mWindowPtr);
1216
// calculate current window portbounds
1218
::GetWindowPortBounds(mWindowPtr, &windRect);
1219
::LocalToGlobal((Point *)&windRect.top);
1220
::LocalToGlobal((Point *)&windRect.bottom);
1222
// calculate window's borders on each side, these differ in Aqua / Platinum
1226
short wBottomBorder;
1228
RgnHandle structRgn = ::NewRgn();
1229
::GetWindowRegion(mWindowPtr, kWindowStructureRgn, structRgn);
1230
Rect structRgnBounds;
1231
::GetRegionBounds(structRgn, &structRgnBounds);
1232
wTitleHeight = windRect.top - structRgnBounds.top;
1233
wLeftBorder = windRect.left - structRgnBounds.left;
1234
wRightBorder = structRgnBounds.right - windRect.right;
1235
wBottomBorder = structRgnBounds.bottom - windRect.bottom;
1237
::DisposeRgn(structRgn);
1239
windRect.top -= wTitleHeight;
1240
windRect.bottom += wBottomBorder;
1241
windRect.right += wRightBorder;
1242
windRect.left -= wLeftBorder;
1244
// find which screen the window is (mostly) on and get its rect. GetAvailRect()
1245
// handles subtracting out the menubar and the dock for us. Set the zoom rect
1246
// to the screen rect, less some fudging and room for icons on the primary screen.
1247
nsCOMPtr<nsIScreenManager> screenMgr = do_GetService(sScreenManagerContractID);
1249
nsCOMPtr<nsIScreen> screen;
1250
screenMgr->ScreenForRect ( windRect.left, windRect.top, windRect.right - windRect.left, windRect.bottom - windRect.top,
1251
getter_AddRefs(screen) );
1253
nsRect newWindowRect;
1254
screen->GetAvailRect ( &newWindowRect.x, &newWindowRect.y, &newWindowRect.width, &newWindowRect.height );
1256
// leave room for icons on primary screen
1257
nsCOMPtr<nsIScreen> primaryScreen;
1258
screenMgr->GetPrimaryScreen ( getter_AddRefs(primaryScreen) );
1259
if (screen == primaryScreen) {
1263
iconSpace = 128; //icons/grid is wider on Mac OS X
1266
newWindowRect.width -= iconSpace;
1270
::SetRect(&zoomRect,
1271
newWindowRect.x + wLeftBorder,
1272
newWindowRect.y + wTitleHeight,
1273
newWindowRect.x + newWindowRect.width - wRightBorder,
1274
newWindowRect.y + newWindowRect.height - wBottomBorder);
1275
::SetWindowStandardState ( mWindowPtr, &zoomRect );
1280
} // CalculateAndSetZoomedSize
1283
//-------------------------------------------------------------------------
1285
// Resize this window to a point given in global (screen) coordinates. This
1286
// differs from simple Move(): that method makes JavaScript place windows
1287
// like other browsers: it puts the top-left corner of the outer edge of the
1288
// window border at the given coordinates, offset from the menubar.
1289
// MoveToGlobalPoint expects the top-left corner of the portrect, which
1290
// is inside the border, and is not offset by the menubar height.
1292
//-------------------------------------------------------------------------
1293
void nsCocoaWindow::MoveToGlobalPoint(PRInt32 aX, PRInt32 aY)
1296
PRInt32 left, top, width, height, fullTop;
1299
StPortSetter doThatThingYouDo(mWindowPtr);
1300
::GetWindowPortBounds(mWindowPtr, &portBounds);
1302
width = portBounds.right - portBounds.left;
1303
height = portBounds.bottom - portBounds.top;
1304
::LocalToGlobal(&topLeft(portBounds));
1306
nsCOMPtr<nsIScreenManager> screenmgr = do_GetService(sScreenManagerContractID);
1308
nsCOMPtr<nsIScreen> screen;
1309
//screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
1310
screenmgr->ScreenForRect(portBounds.left, portBounds.top, width, height,
1311
getter_AddRefs(screen));
1313
screen->GetAvailRect(&left, &top, &width, &height);
1314
screen->GetRect(&left, &fullTop, &width, &height);
1320
aX -= kDialogMarginWidth;
1321
aY -= kDialogTitleBarHeight;
1323
aX -= kWindowMarginWidth;
1324
aY -= kWindowTitleBarHeight;
1331
NS_IMETHODIMP nsCocoaWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
1334
Resize(aWidth, aHeight, aRepaint);
1339
//-------------------------------------------------------------------------
1341
// Resize this window
1343
//-------------------------------------------------------------------------
1344
NS_IMETHODIMP nsCocoaWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, PRBool aRepaint)
1347
NSRect newBounds = [mWindow frame];
1348
newBounds.size.width = aWidth;
1349
if ( mWindowType == eWindowType_popup )
1350
newBounds.size.height = aHeight;
1352
newBounds.size.height = aHeight + kTitleBarHeight; // add height of title bar
1354
[mWindow setFrame:newBounds display:NO];
1358
mBounds.width = aWidth;
1359
mBounds.height = aHeight;
1361
// tell gecko to update all the child widgets
1365
if (mWindowMadeHere) {
1366
// Sanity check against screen size
1368
::GetRegionBounds(::GetGrayRgn(), &screenRect);
1370
// Need to use non-negative coordinates
1371
PRInt32 screenWidth;
1372
if(screenRect.left < 0)
1373
screenWidth = screenRect.right - screenRect.left;
1375
screenWidth = screenRect.right;
1377
PRInt32 screenHeight;
1378
if(screenRect.top < 0)
1379
screenHeight = screenRect.bottom - screenRect.top;
1381
screenHeight = screenRect.bottom;
1383
if(aHeight > screenHeight)
1384
aHeight = screenHeight;
1386
if(aWidth > screenWidth)
1387
aWidth = screenWidth;
1390
::GetWindowPortBounds ( mWindowPtr, &macRect );
1392
short w = macRect.right - macRect.left;
1393
short h = macRect.bottom - macRect.top;
1394
Boolean needReposition = (w == 1 && h == 1);
1396
if ((w != aWidth) || (h != aHeight))
1398
// make sure that we don't infinitely recurse if live-resize is on
1399
mResizeIsFromUs = PR_TRUE;
1400
::SizeWindow(mWindowPtr, aWidth, aHeight, aRepaint);
1401
mResizeIsFromUs = PR_FALSE;
1403
#if defined(XP_MACOSX)
1404
// workaround for bug in MacOSX if windows start life as 1x1.
1406
RepositionWindow(mWindowPtr, NULL, kWindowCascadeOnMainScreen);
1411
//Inherited::Resize(aWidth, aHeight, aRepaint);
1415
NS_IMETHODIMP nsCocoaWindow::GetScreenBounds(nsRect &aRect) {
1418
PRInt32 yAdjust = 0;
1420
GetBounds(localBounds);
1421
// nsCocoaWindow local bounds are always supposed to be local (0,0) but in the middle of a move
1422
// can be global. This next adjustment assures they are in local coordinates, even then.
1423
localBounds.MoveBy(-localBounds.x, -localBounds.y);
1424
WidgetToScreen(localBounds, aRect);
1426
nsCOMPtr<nsIScreenManager> screenmgr = do_GetService(sScreenManagerContractID);
1428
nsCOMPtr<nsIScreen> screen;
1429
//screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
1430
screenmgr->ScreenForRect(aRect.x, aRect.y, aRect.width, aRect.height,
1431
getter_AddRefs(screen));
1433
PRInt32 left, top, width, height, fullTop;
1434
screen->GetAvailRect(&left, &top, &width, &height);
1435
screen->GetRect(&left, &fullTop, &width, &height);
1436
yAdjust = top-fullTop;
1441
aRect.MoveBy(-kDialogMarginWidth, -kDialogTitleBarHeight-yAdjust);
1443
aRect.MoveBy(-kWindowMarginWidth, -kWindowTitleBarHeight-yAdjust);
1449
//-------------------------------------------------------------------------
1452
//-------------------------------------------------------------------------
1453
PRBool nsCocoaWindow::OnPaint(nsPaintEvent &event)
1455
return PR_TRUE; // don't dispatch the update event
1458
//-------------------------------------------------------------------------
1460
// Set this window's title
1462
//-------------------------------------------------------------------------
1463
NS_IMETHODIMP nsCocoaWindow::SetTitle(const nsString& aTitle)
1465
NSString* title = [NSString stringWithCharacters:aTitle.get() length:aTitle.Length()];
1466
[mWindow setTitle:title];
1472
//-------------------------------------------------------------------------
1473
// Pass notification of some drag event to Gecko
1475
// The drag manager has let us know that something related to a drag has
1476
// occurred in this window. It could be any number of things, ranging from
1477
// a drop, to a drag enter/leave, or a drag over event. The actual event
1478
// is passed in |aMessage| and is passed along to our event hanlder so Gecko
1480
//-------------------------------------------------------------------------
1481
PRBool nsCocoaWindow::DragEvent ( unsigned int aMessage, Point aMouseGlobal, UInt16 aKeyModifiers )
1485
if (mMacEventHandler.get())
1486
retVal = mMacEventHandler->DragEvent(aMessage, aMouseGlobal, aKeyModifiers);
1494
//-------------------------------------------------------------------------
1496
// Like ::BringToFront, but constrains the window to its z-level
1498
//-------------------------------------------------------------------------
1499
void nsCocoaWindow::ComeToFront() {
1501
nsZLevelEvent event(NS_SETZLEVEL, this);
1503
event.point.x = mBounds.x;
1504
event.point.y = mBounds.y;
1505
event.time = PR_IntervalNow();
1507
event.mImmediate = PR_TRUE;
1509
DispatchWindowEvent(event);
1514
NS_IMETHODIMP nsCocoaWindow::ResetInputState()
1516
// return mMacEventHandler->ResetInputState();
1520
void nsCocoaWindow::SetIsActive(PRBool aActive)
1522
// mIsActive = aActive;
1525
void nsCocoaWindow::IsActive(PRBool* aActive)
1527
// *aActive = mIsActive;
1532
// Return true if we are on Mac OS X, caching the result after the first call
1538
static PRBool gInitVer = PR_FALSE;
1539
static PRBool gOnMacOSX = PR_FALSE;
1542
OSErr err = ::Gestalt(gestaltSystemVersion, &version);
1543
gOnMacOSX = (err == noErr && version >= 0x00001000);
1557
nsCocoaWindow::DispatchEvent ( void* anEvent, void* aView, PRBool *_retval )
1559
*_retval = PR_FALSE;
1562
NSEvent* event = NS_REINTERPRET_CAST(NSEvent*, anEvent);
1563
NS_ASSERTION(event, "null event");
1565
ChildView* view = NS_REINTERPRET_CAST(ChildView*, aView);
1567
nsMouseEvent geckoEvent(0, view ? [view widget] : this)
1569
geckoEvent.nativeMsg = anEvent;
1570
geckoEvent.time = PR_IntervalNow();
1571
NSPoint mouseLoc = [event locationInWindow];
1572
geckoEvent.refPoint.x = NS_STATIC_CAST(nscoord, mouseLoc.x);
1573
geckoEvent.refPoint.y = NS_STATIC_CAST(nscoord, mouseLoc.y);
1574
//printf("-- global mouse click at (%ld,%ld)\n", geckoEvent.refPoint.x, geckoEvent.refPoint.y );
1576
// convert point to view coordinate system
1577
NSPoint localPoint = [view convertPoint:mouseLoc fromView:nil];
1578
geckoEvent.point.x = NS_STATIC_CAST(nscoord, localPoint.x);
1579
geckoEvent.point.y = NS_STATIC_CAST(nscoord, localPoint.y);
1580
//printf("-- local mouse click at (%ld,%ld) widget = %ld\n", geckoEvent.point.x, geckoEvent.point.y,
1581
// geckoEvent.widget );
1584
geckoEvent.point = geckoEvent.refPoint;
1586
NSEventType type = [event type];
1588
case NSLeftMouseDown:
1589
//printf("left mouse down\n");
1590
geckoEvent.message = NS_MOUSE_LEFT_BUTTON_DOWN;
1591
geckoEvent.clickCount = [event clickCount];
1594
//printf("left mouse up\n");
1597
printf("mouse move\n");
1600
printf("key down\n");
1606
printf("scroll wheel\n");
1608
case NSLeftMouseDragged:
1617
nsEventStatus status = nsEventStatus_eIgnore;
1618
DispatchEvent ( &geckoEvent, status );
1629
//-------------------------------------------------------------------------
1631
// Invokes callback and ProcessEvent method on Event Listener object
1633
//-------------------------------------------------------------------------
1635
nsCocoaWindow::DispatchEvent(nsGUIEvent* event, nsEventStatus& aStatus)
1637
aStatus = nsEventStatus_eIgnore;
1639
nsIWidget* aWidget = event->widget;
1640
NS_IF_ADDREF(aWidget);
1642
if (nsnull != mMenuListener){
1643
if(NS_MENU_EVENT == event->eventStructType)
1644
aStatus = mMenuListener->MenuSelected( static_cast<nsMenuEvent&>(*event) );
1647
aStatus = (*mEventCallback)(event);
1649
// Dispatch to event listener if event was not consumed
1650
if ((aStatus != nsEventStatus_eConsumeNoDefault) && (mEventListener != nsnull))
1651
aStatus = mEventListener->ProcessEvent(*event);
1653
NS_IF_RELEASE(aWidget);
1660
nsCocoaWindow::ReportSizeEvent()
1663
nsSizeEvent sizeEvent(NS_SIZE, this);
1664
sizeEvent.time = PR_IntervalNow();
1667
sizeEvent.windowSize = &mBounds;
1668
sizeEvent.mWinWidth = mBounds.width;
1669
sizeEvent.mWinHeight = mBounds.height;
1672
nsEventStatus status = nsEventStatus_eIgnore;
1673
DispatchEvent(&sizeEvent, status);
1680
nsCocoaWindow::IsResizing ( ) const
1685
void StartResizing ( )
1687
mIsResizing = PR_TRUE;
1690
void StopResizing ( )
1692
mIsResizing = PR_FALSE;
1701
@implementation WindowDelegate
1704
- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind
1707
mGeckoWindow = geckoWind;
1711
- (void)windowDidResize:(NSNotification *)aNotification
1713
if ( !mGeckoWindow->IsResizing() ) {
1714
// must remember to give Gecko top-left, not straight cocoa origin
1715
// and that Gecko already compensates for the title bar, so we have to
1716
// strip it out here.
1717
NSRect frameRect = [[aNotification object] frame];
1718
mGeckoWindow->Resize ( NS_STATIC_CAST(PRInt32,frameRect.size.width),
1719
NS_STATIC_CAST(PRInt32,frameRect.size.height - nsCocoaWindow::kTitleBarHeight), PR_TRUE );
1724
- (void)windowDidBecomeMain:(NSNotification *)aNotification
1726
//printf("got activation\n");
1730
- (void)windowDidResignMain:(NSNotification *)aNotification
1732
//printf("got deactivate\n");
1736
- (void)windowDidBecomeKey:(NSNotification *)aNotification
1738
//printf("we're key window\n");
1742
- (void)windowDidResignKey:(NSNotification *)aNotification
1744
//printf("we're not the key window\n");
1748
- (void)windowDidMove:(NSNotification *)aNotification