]> git.saurik.com Git - wxWidgets.git/blob - src/mac/app.cpp
Added wxGTK-only cmn dialogs.
[wxWidgets.git] / src / mac / app.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: app.cpp
3 // Purpose: wxApp
4 // Author: AUTHOR
5 // Modified by:
6 // Created: ??/??/98
7 // RCS-ID: $Id$
8 // Copyright: (c) AUTHOR
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "app.h"
14 #endif
15
16 #include "wx/frame.h"
17 #include "wx/app.h"
18 #include "wx/utils.h"
19 #include "wx/gdicmn.h"
20 #include "wx/pen.h"
21 #include "wx/brush.h"
22 #include "wx/cursor.h"
23 #include "wx/icon.h"
24 #include "wx/palette.h"
25 #include "wx/dc.h"
26 #include "wx/dialog.h"
27 #include "wx/msgdlg.h"
28 #include "wx/log.h"
29 #include "wx/module.h"
30 #include "wx/memory.h"
31
32 #if wxUSE_WX_RESOURCES
33 #include "wx/resource.h"
34 #endif
35
36 #include <string.h>
37
38 // mac
39
40 #include "apprsrc.h"
41
42 extern char *wxBuffer;
43 extern wxList wxPendingDelete;
44
45 wxApp *wxTheApp = NULL;
46
47 #if !USE_SHARED_LIBRARY
48 IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
49 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
50 EVT_IDLE(wxApp::OnIdle)
51 END_EVENT_TABLE()
52 #endif
53
54 long wxApp::sm_lastMessageTime = 0;
55
56 const short kMacMinHeap = (29 * 1024) ;
57 // platform specific static variables
58
59 bool gMacHasAppearance = false ;
60 long gMacAppearanceVersion = 0 ;
61 RgnHandle gMacCursorRgn = NULL ;
62
63
64 bool wxApp::Initialize()
65 {
66 int error = 0 ;
67
68 // Mac-specific
69 long total,contig;
70
71 // init all managers
72
73 ::InitGraf(&qd.thePort);
74 ::InitFonts();
75 ::InitWindows();
76 ::InitMenus();
77 ::TEInit();
78 ::InitDialogs(0L);
79 ::InitCursor();
80 CursHandle aCursHandle = ::GetCursor(watchCursor); // Watch should be in system
81 if (aCursHandle)
82 ::SetCursor(*aCursHandle);
83 ::FlushEvents(everyEvent, 0);
84
85 // setup memory of application
86
87 ::MaxApplZone();
88 for (long i = 1; i <= 4; i++)
89 ::MoreMasters();
90 PurgeSpace(&total, &contig);
91 ::SetCursor( &qd.arrow ) ;
92
93 #if 0
94 InitAEHandlers();
95 InitializeAECore() ;
96 GUSISetup(GUSIwithInternetSockets);
97 #endif
98
99 // test the minimal configuration necessary
100
101 long theSystem ;
102 long theMachine;
103 long theAppearance ;
104
105 if (Gestalt(gestaltMachineType, &theMachine) != noErr)
106 {
107 error = kMacSTRWrongMachine;
108 }
109 else if (theMachine < gestaltMacPlus)
110 {
111 error = kMacSTRWrongMachine;
112 }
113 else if (Gestalt(gestaltSystemVersion, &theSystem) != noErr )
114 {
115 error = kMacSTROldSystem ;
116 }
117 else if ( theSystem < 0x0700 )
118 {
119 error = kMacSTROldSystem ;
120 }
121 else if ((long)GetApplLimit() - (long)ApplicationZone() < kMacMinHeap)
122 {
123 error = kMacSTRSmallSize;
124 }
125 else
126 {
127 if ( Gestalt( gestaltAppearanceAttr, &theAppearance ) == noErr )
128 {
129 gMacHasAppearance = true ;
130 RegisterAppearanceClient();
131 if ( Gestalt( gestaltAppearanceVersion, &theAppearance ) == noErr )
132 {
133 gMacAppearanceVersion = theAppearance ;
134 }
135 else
136 {
137 gMacAppearanceVersion = 0x0100 ;
138 }
139 }
140 else
141 error = kMacSTRNoPre8Yet ;
142 }
143
144 // if we encountered any problems so far, give the error code and exit immediately
145
146 if ( error )
147 {
148 short itemHit;
149 Str255 message;
150
151 SetCursor(&qd.arrow);
152 GetIndString(message, 128, error);
153 ParamText(message, (ConstStr255Param)"\p", (ConstStr255Param)"\p", (ConstStr255Param)"\p");
154 itemHit = Alert(129, nil);
155 return FALSE ;
156 }
157
158 // now avoid exceptions thrown for new (bad_alloc)
159
160 std::__throws_bad_alloc = FALSE ;
161
162 gMacCursorRgn = ::NewRgn() ;
163
164 #ifdef __WXMSW__
165 wxBuffer = new char[1500];
166 #else
167 wxBuffer = new char[BUFSIZ + 512];
168 #endif
169
170 /* No longer used
171 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
172
173 streambuf* sBuf = new wxDebugStreamBuf;
174 ostream* oStr = new ostream(sBuf) ;
175 wxDebugContext::SetStream(oStr, sBuf);
176 #endif
177 */
178
179 wxClassInfo::InitializeClasses();
180
181 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
182 wxTheColourDatabase->Initialize();
183
184 wxInitializeStockLists();
185 wxInitializeStockObjects();
186
187 #if wxUSE_WX_RESOURCES
188 wxInitializeResourceSystem();
189 #endif
190
191 wxBitmap::InitStandardHandlers();
192
193 wxModule::RegisterModules();
194 wxASSERT( wxModule::InitializeModules() == TRUE );
195
196 return TRUE;
197 }
198
199 void wxApp::CleanUp()
200 {
201 wxModule::CleanUpModules();
202
203 #if wxUSE_WX_RESOURCES
204 wxCleanUpResourceSystem();
205 #endif
206
207 wxDeleteStockObjects() ;
208
209 // Destroy all GDI lists, etc.
210
211 delete wxTheBrushList;
212 wxTheBrushList = NULL;
213
214 delete wxThePenList;
215 wxThePenList = NULL;
216
217 delete wxTheFontList;
218 wxTheFontList = NULL;
219
220 delete wxTheBitmapList;
221 wxTheBitmapList = NULL;
222
223 delete wxTheColourDatabase;
224 wxTheColourDatabase = NULL;
225
226 wxBitmap::CleanUpHandlers();
227
228 delete[] wxBuffer;
229 wxBuffer = NULL;
230
231 wxClassInfo::CleanUpClasses();
232
233 delete wxTheApp;
234 wxTheApp = NULL;
235
236 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
237 // At this point we want to check if there are any memory
238 // blocks that aren't part of the wxDebugContext itself,
239 // as a special case. Then when dumping we need to ignore
240 // wxDebugContext, too.
241 if (wxDebugContext::CountObjectsLeft() > 0)
242 {
243 wxTrace("There were memory leaks.\n");
244 wxDebugContext::Dump();
245 wxDebugContext::PrintStatistics();
246 }
247 // wxDebugContext::SetStream(NULL, NULL);
248 #endif
249
250 // do it as the very last thing because everything else can log messages
251 wxLog::DontCreateOnDemand();
252 // do it as the very last thing because everything else can log messages
253 delete wxLog::SetActiveTarget(NULL);
254
255 ::PrClose() ;
256 if (gMacCursorRgn)
257 ::DisposeRgn(gMacCursorRgn);
258 #if 0
259 TerminateAE() ;
260 #endif
261 }
262
263 int wxEntry( int argc, char *argv[] )
264 {
265 if (!wxApp::Initialize())
266 return FALSE;
267 if (!wxTheApp)
268 {
269 if (!wxApp::GetInitializerFunction())
270 {
271 printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
272 return 0;
273 };
274
275 wxTheApp = (wxApp*) (* wxApp::GetInitializerFunction()) ();
276 };
277
278 if (!wxTheApp)
279 {
280 printf( "wxWindows error: wxTheApp == NULL\n" );
281 return 0;
282 };
283
284 wxTheApp->argc = argc;
285 wxTheApp->argv = argv;
286
287 // GUI-specific initialization, such as creating an app context.
288 wxTheApp->OnInitGui();
289
290 // Here frames insert themselves automatically
291 // into wxTopLevelWindows by getting created
292 // in OnInit().
293
294 if (!wxTheApp->OnInit()) return 0;
295
296 int retValue = 0;
297
298 if (wxTheApp->Initialized()) retValue = wxTheApp->OnRun();
299
300 if (wxTheApp->GetTopWindow())
301 {
302 delete wxTheApp->GetTopWindow();
303 wxTheApp->SetTopWindow(NULL);
304 }
305
306 wxTheApp->DeletePendingObjects();
307
308 wxTheApp->OnExit();
309
310 wxApp::CleanUp();
311
312 return retValue;
313 };
314
315 // Static member initialization
316 wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
317
318 wxApp::wxApp()
319 {
320 m_topWindow = NULL;
321 wxTheApp = this;
322 m_className = "";
323 m_wantDebugOutput = TRUE ;
324 m_appName = "";
325 argc = 0;
326 argv = NULL;
327 #ifdef __WXMSW__
328 m_printMode = wxPRINT_WINDOWS;
329 #else
330 m_printMode = wxPRINT_POSTSCRIPT;
331 #endif
332 m_exitOnFrameDelete = TRUE;
333 m_auto3D = TRUE;
334 }
335
336 bool wxApp::Initialized()
337 {
338 return TRUE;
339 // if (GetTopWindow())
340 // return TRUE;
341 // else
342 // return FALSE;
343 }
344
345 int wxApp::MainLoop()
346 {
347 m_keepGoing = TRUE;
348
349 while (m_keepGoing)
350 {
351 MacDoOneEvent() ;
352 }
353
354 return 0;
355 }
356
357 // Returns TRUE if more time is needed.
358 bool wxApp::ProcessIdle()
359 {
360 wxIdleEvent event;
361 event.SetEventObject(this);
362 ProcessEvent(event);
363
364 return event.MoreRequested();
365 }
366
367 void wxApp::ExitMainLoop()
368 {
369 m_keepGoing = FALSE;
370 }
371
372 // Is a message/event pending?
373 bool wxApp::Pending()
374 {
375 /* TODO.
376 */
377 return FALSE;
378 }
379
380 // Dispatch a message.
381 void wxApp::Dispatch()
382 {
383 /* TODO.
384 */
385 }
386
387 void wxApp::OnIdle(wxIdleEvent& event)
388 {
389 static bool inOnIdle = FALSE;
390
391 // Avoid recursion (via ProcessEvent default case)
392 if (inOnIdle)
393 return;
394
395 inOnIdle = TRUE;
396
397 // 'Garbage' collection of windows deleted with Close().
398 DeletePendingObjects();
399
400 // flush the logged messages if any
401 wxLog *pLog = wxLog::GetActiveTarget();
402 if ( pLog != NULL && pLog->HasPendingMessages() )
403 pLog->Flush();
404
405 // Send OnIdle events to all windows
406 bool needMore = SendIdleEvents();
407
408 if (needMore)
409 event.RequestMore(TRUE);
410
411 inOnIdle = FALSE;
412 }
413
414 // Send idle event to all top-level windows
415 bool wxApp::SendIdleEvents()
416 {
417 bool needMore = FALSE;
418 wxNode* node = wxTopLevelWindows.First();
419 while (node)
420 {
421 wxWindow* win = (wxWindow*) node->Data();
422 if (SendIdleEvents(win))
423 needMore = TRUE;
424
425 node = node->Next();
426 }
427 return needMore;
428 }
429
430 // Send idle event to window and all subwindows
431 bool wxApp::SendIdleEvents(wxWindow* win)
432 {
433 bool needMore = FALSE;
434
435 wxIdleEvent event;
436 event.SetEventObject(win);
437 win->ProcessEvent(event);
438
439 if (event.MoreRequested())
440 needMore = TRUE;
441
442 wxNode* node = win->GetChildren().First();
443 while (node)
444 {
445 wxWindow* win = (wxWindow*) node->Data();
446 if (SendIdleEvents(win))
447 needMore = TRUE;
448
449 node = node->Next();
450 }
451 return needMore ;
452 }
453
454 void wxApp::DeletePendingObjects()
455 {
456 wxNode *node = wxPendingDelete.First();
457 while (node)
458 {
459 wxObject *obj = (wxObject *)node->Data();
460
461 delete obj;
462
463 if (wxPendingDelete.Member(obj))
464 delete node;
465
466 // Deleting one object may have deleted other pending
467 // objects, so start from beginning of list again.
468 node = wxPendingDelete.First();
469 }
470 }
471
472 wxLog* wxApp::CreateLogTarget()
473 {
474 return new wxLogGui;
475 }
476
477 wxWindow* wxApp::GetTopWindow() const
478 {
479 if (m_topWindow)
480 return m_topWindow;
481 else if (wxTopLevelWindows.Number() > 0)
482 return (wxWindow*) wxTopLevelWindows.First()->Data();
483 else
484 return NULL;
485 }
486
487 void wxExit()
488 {
489 wxApp::CleanUp();
490 ::ExitToShell() ;
491 }
492
493 // Yield to other processes
494 bool wxYield()
495 {
496 #if 0
497 ::YieldToOtherThreads() ;
498 ::SystemTime() ;
499 #endif
500 return TRUE;
501 }
502
503 // platform specifics
504
505 void wxApp::MacDoOneEvent()
506 {
507 EventRecord event ;
508
509 long sleepTime = 60;
510
511 if (WaitNextEvent(everyEvent, &event,sleepTime, gMacCursorRgn))
512 {
513 MacHandleOneEvent( &event );
514 }
515 else
516 {
517 // idlers
518 wxTheApp->ProcessIdle() ;
519 }
520
521 // repeaters
522 #if 0
523 wxMacProcessSocketEvents() ;
524 #endif
525 }
526
527 void wxApp::MacHandleOneEvent( EventRecord *ev )
528 {
529 switch (ev->what)
530 {
531 case nullEvent:
532 MacHandleNullEvent( ev ) ;
533 break ;
534 case kHighLevelEvent:
535 MacHandleHighLevelEvent( ev ) ;
536 break;
537 case mouseDown:
538 MacHandleMouseDownEvent( ev ) ;
539 wxTheApp->ExitMainLoop() ;
540 break;
541 case mouseUp:
542 MacHandleMouseUpEvent( ev ) ;
543 break;
544 case keyDown:
545 MacHandleKeyDownEvent( ev ) ;
546 break;
547 case autoKey:
548 MacHandleAutoKeyEvent( ev ) ;
549 break;
550 case keyUp:
551 MacHandleKeyUpEvent( ev ) ;
552 break;
553 case activateEvt:
554 MacHandleActivateEvent( ev ) ;
555 break;
556 case updateEvt:
557 MacHandleUpdateEvent( ev ) ;
558 break;
559 case diskEvt:
560 MacHandleDiskEvent( ev ) ;
561 break;
562 case osEvt:
563 MacHandleOSEvent( ev ) ;
564 break;
565 default:
566 break;
567 }
568 }
569
570 void wxApp::MacHandleNullEvent( EventRecord *ev )
571 {
572 }
573
574 void wxApp::MacHandleHighLevelEvent( EventRecord *ev )
575 {
576 }
577
578 void wxApp::MacHandleMouseDownEvent( EventRecord *ev )
579 {
580 }
581
582 void wxApp::MacHandleMouseUpEvent( EventRecord *ev )
583 {
584 }
585
586 void wxApp::MacHandleKeyDownEvent( EventRecord *ev )
587 {
588 }
589
590 void wxApp::MacHandleKeyUpEvent( EventRecord *ev )
591 {
592 }
593
594 void wxApp::MacHandleAutoKeyEvent( EventRecord *ev )
595 {
596 }
597
598 void wxApp::MacHandleActivateEvent( EventRecord *ev )
599 {
600 }
601
602 void wxApp::MacHandleUpdateEvent( EventRecord *ev )
603 {
604 }
605
606 void wxApp::MacHandleDiskEvent( EventRecord *ev )
607 {
608 }
609
610 void wxApp::MacHandleOSEvent( EventRecord *ev )
611 {
612 }
613
614
615
616 /*
617
618 void wxApp::doMacMouseDown(void)
619 {
620 WindowPtr window;
621 short windowPart = ::FindWindow(m_event.where, &window);
622 if ( windowPart != inMenuBar )
623 {
624 WindowPtr frontWindow = FrontWindow();
625 if (WindowIsModal(frontWindow) && (window != frontWindow))
626 SysBeep(1);
627 else
628 {
629 switch (windowPart)
630 {
631 case inMenuBar:
632 break;
633 case inContent:
634 doMacInContent(window); break;
635 case inDrag:
636 doMacInDrag(window); break;
637 case inGrow:
638 doMacInGrow(window); break;
639 case inGoAway:
640 doMacInGoAway(window); break;
641 case inZoomIn:
642 case inZoomOut:
643 doMacInZoom(window, windowPart); break;
644 default:
645 break;
646 }
647
648 }
649 }
650 else
651 {
652 doMacInMenuBar(::MenuSelect(m_event.where));
653 }
654 }
655
656 void wxApp::doMacMouseUp(void)
657 {
658 if (m_mouseWindow)
659 {
660 #if 0
661 int hitX = m_event.where.h; // screen window c.s.
662 int hitY = m_event.where.v; // screen window c.s.
663 m_mouseWindow->ScreenToClient(&hitX, &hitY); // mouseWindow client c.s.
664 m_mouseWindow->ClientToLogical(&hitX, &hitY); // mouseWindow logical c.s.
665 #endif
666
667 wxMouseEvent event(wxEVT_LEFT_UP);
668 event.m_shiftDown = m_event.modifiers & shiftKey;
669 event.m_controlDown = m_event.modifiers & controlKey;
670 event.m_altDown = m_event.modifiers & optionKey;
671 event.m_metaDown = m_event.modifiers & cmdKey;
672 event.m_leftDown = FALSE;
673 event.m_middleDown = FALSE;
674 event.m_rightDown = FALSE;
675 event.m_x = m_event.where.h;
676 event.m_y = m_event.where.v;
677 event.m_timeStamp = m_event.when;
678 event.SetEventObject(m_mouseWindow);
679
680 m_mouseWindow->ProcessEvent(event);
681 }
682 else
683 {
684 //??? Can't we just throw away mouse up events without matching mouse down
685 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(::FrontWindow());
686 if (theMacWxFrame)
687 {
688 #if 0
689 int hitX = cCurrentEvent.where.h; // screen window c.s.
690 int hitY = cCurrentEvent.where.v; // screen window c.s.
691 theMacWxFrame->ScreenToWindow(&hitX, &hitY);
692 #endif
693
694 wxMouseEvent event(wxEVT_LEFT_UP);
695 event.m_shiftDown = m_event.modifiers & shiftKey;
696 event.m_controlDown = m_event.modifiers & controlKey;
697 event.m_altDown = m_event.modifiers & optionKey;
698 event.m_metaDown = m_event.modifiers & cmdKey;
699 event.m_leftDown = FALSE;
700 event.m_middleDown = FALSE;
701 event.m_rightDown = FALSE;
702 event.m_x = m_event.where.h;
703 event.m_y = m_event.where.v;
704 event.m_timeStamp = m_event.when;
705 event.SetEventObject(m_mouseWindow);
706
707 theMacWxFrame->ProcessEvent(event);
708 }
709 }
710 }
711
712 void wxApp::doMacMouseMotion(void)
713 {
714 if (m_mouseWindow) {
715 wxMouseEvent event(wxEVT_MOTION);
716 event.m_shiftDown = m_event.modifiers & shiftKey;
717 event.m_controlDown = m_event.modifiers & controlKey;
718 event.m_altDown = m_event.modifiers & optionKey;
719 event.m_metaDown = m_event.modifiers & cmdKey;
720 event.m_leftDown = !(m_event.modifiers & btnState);
721 event.m_middleDown = FALSE;
722 event.m_rightDown = FALSE;
723 event.m_x = m_event.where.h;
724 event.m_y = m_event.where.v;
725 event.m_timeStamp = m_event.when;
726 event.SetEventObject(m_mouseWindow);
727
728 m_mouseWindow->ProcessEvent(event);
729 }
730 else
731 {
732 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(::FrontWindow());
733 if (theMacWxFrame)
734 {
735 wxMouseEvent event(wxEVT_MOTION);
736 event.m_shiftDown = m_event.modifiers & shiftKey;
737 event.m_controlDown = m_event.modifiers & controlKey;
738 event.m_altDown = m_event.modifiers & optionKey;
739 event.m_metaDown = m_event.modifiers & cmdKey;
740 event.m_leftDown = !(m_event.modifiers & btnState);
741 event.m_middleDown = FALSE;
742 event.m_rightDown = FALSE;
743 event.m_x = m_event.where.h;
744 event.m_y = m_event.where.v;
745 event.m_timeStamp = m_event.when;
746 event.SetEventObject(m_mouseWindow);
747
748 m_mouseWindow->ProcessEvent(event);
749 }
750 }
751
752 //??? Need to work with floating windows... isn't there a toolbox call to find the
753 // top window intersecting a point is screen coordinates??
754 #if 0
755 else // will only work for one floating window at the moment... ?
756 {
757 WindowPtr frontDocPtr = findFrontNonFloatingWindow();
758 WindowPtr frontFloatingPtr = ::FrontWindow();
759
760 int hitX = cCurrentEvent.where.h;
761 int hitY = cCurrentEvent.where.v;
762
763 wxFrame* macWxFrame = findMacWxFrame(frontDocPtr);
764
765 if ((frontFloatingPtr != frontDocPtr) & (frontFloatingPtr != NULL))
766 {
767 RgnHandle frontFloatStrRgn = getStructureRegion(frontFloatingPtr);
768 Rect frontFloatRect = (**frontFloatStrRgn).rgnBBox;
769
770 if ((hitX >= frontFloatRect.left) &
771 (hitX <= frontFloatRect.right) &
772 (hitY >= frontFloatRect.top) &
773 (hitY <= frontFloatRect.bottom))
774 {
775 macWxFrame = findMacWxFrame(frontFloatingPtr);
776 }
777 }
778 }
779 #endif
780 }
781
782 void wxApp::doMacKeyDown(void)
783 {
784 long menuResult = 0 ;
785 short keycode ;
786 short keychar ;
787 keychar = short(m_event.message & charCodeMask);
788 keycode = short(m_event.message & keyCodeMask) >> 8 ;
789
790 // Handle menu accelerators
791 if ( gSFMacHasAppearance )
792 {
793 menuResult = MenuEvent( &m_event ) ;
794 if ( HiWord( menuResult ) )
795 {
796 doMacInMenuBar( menuResult ) ;
797 }
798 else
799 {
800 ControlHandle control ;
801
802 GetKeyboardFocus( FrontNonFloatingWindow() , &control ) ;
803 if ( control && keychar != 0x07 )
804 HandleControlKey( control , keycode , keychar , m_event.modifiers ) ;
805 else
806 {
807 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(::FrontWindow());
808 if (theMacWxFrame)
809 {
810 wxKeyEvent event(wxEVT_CHAR);
811 event.m_shiftDown = m_event.modifiers & shiftKey;
812 event.m_controlDown = m_event.modifiers & controlKey;
813 event.m_altDown = m_event.modifiers & optionKey;
814 event.m_metaDown = m_event.modifiers & cmdKey;
815 event.m_keyCode = macTranslateKey(keychar, m_event.modifiers & (shiftKey|optionKey));
816 event.m_x = m_event.where.h;
817 event.m_y = m_event.where.v;
818 event.m_timeStamp = m_event.when;
819 event.SetEventObject(theMacWxFrame);
820
821 theMacWxFrame->ProcessEvent(event);
822 }
823 }
824 }
825 }
826 else
827 {
828 if (GetMenuHandle( kwxMacAppleMenuId ) )
829 {
830 // menuResult = MDEF_MenuKey(m_event.message, m_event.modifiers , GetMenuHandle( kwxMacAppleMenuId ) );
831 }
832 else
833 {
834 if (m_event.modifiers & cmdKey)
835 {
836 menuResult = MenuKey( keychar ) ;
837 }
838 }
839
840 if ( HiWord( menuResult ) )
841 {
842 doMacInMenuBar( menuResult ) ;
843 }
844 else
845 {
846 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(::FrontWindow());
847 if (theMacWxFrame)
848 {
849 wxKeyEvent event(wxEVT_CHAR);
850 event.m_shiftDown = m_event.modifiers & shiftKey;
851 event.m_controlDown = m_event.modifiers & controlKey;
852 event.m_altDown = m_event.modifiers & optionKey;
853 event.m_metaDown = m_event.modifiers & cmdKey;
854 event.m_keyCode = macTranslateKey(keychar, m_event.modifiers & (shiftKey|optionKey));
855 event.m_x = m_event.where.h;
856 event.m_y = m_event.where.v;
857 event.m_timeStamp = m_event.when;
858 event.SetEventObject(theMacWxFrame);
859
860 theMacWxFrame->ProcessEvent(event);
861 }
862 }
863 }
864 }
865
866 void wxApp::doMacAutoKey(void)
867 {
868 doMacKeyDown();
869 }
870
871 void wxApp::doMacKeyUp(void)
872 {
873 }
874
875 void wxApp::doMacActivateEvt(void)
876 {
877 HighlightAndActivateWindow( (WindowPtr) m_event.message , m_event.modifiers & activeFlag ) ;
878 }
879
880 void wxApp::doMacUpdateEvt(void)
881 {
882 WindowPtr theMacWindow = (WindowPtr)(m_event.message);
883 ::BeginUpdate(theMacWindow);
884
885 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(theMacWindow);
886 if (theMacWxFrame)
887 {
888 // if (!::EmptyRgn(theMacWindow->visRgn)) // this doesn't work with windowshade
889 // {
890 if ( theMacWxFrame->MacSetupPort() )
891 {
892 // Erase update region
893 // we must do this, because controls add their former rect to the inval
894 // rgn and the background might not have been correct at that moment
895 ::EraseRect(&theMacWindow->portRect);
896
897 // Can't use UpdateControls since each control has it's own coordinate system
898 // ::UpdateControls(theMacWindow, theMacWindow->visRgn);
899
900 ::UpdateControls( theMacWindow , theMacWindow->visRgn ) ;
901 #if 0
902 // Draw the grow box
903 if (cStyle & wxRESIZE_BORDER)
904 MacDrawGrowIcon();
905 #endif
906
907 wxPaintEvent event;
908 event.m_timeStamp = m_event.when;
909 event.SetEventObject(theMacWxFrame);
910
911 theMacWxFrame->ProcessEvent(event);
912 // ::SetThemeWindowBackground( theMacWindow , kThemeActiveDialogBackgroundBrush , false ) ;
913 ::ClipRect( &theMacWindow->portRect ) ;
914 ::SetOrigin( 0 , 0 );
915 }
916 else
917 {
918 wxASSERT_MSG( false , "unabled to setup window mac port") ;
919 }
920
921 // }
922 }
923
924 ::EndUpdate(theMacWindow);
925 }
926
927 void wxApp::doMacDiskEvt(void)
928 { // based on "Programming for System 7" by Gary Little and Tim Swihart
929 if ((m_event.message >> 16) != noErr)
930 {
931 const int kDILeft = 0x0050; // top coord for disk init dialog
932 const int kDITop = 0x0070; // left coord for disk init dialog
933 Point mountPoint;
934 mountPoint.h = kDILeft;
935 mountPoint.v = kDITop;
936 int myError = DIBadMount(mountPoint, m_event.message);
937 }
938 }
939
940 void wxApp::doMacOsEvt(void)
941 { // based on "Programming for System 7" by Gary Little and Tim Swihart
942 switch ((m_event.message >> 24) & 0x0ff)
943 {
944 case suspendResumeMessage:
945 if (m_event.message & resumeFlag)
946 doMacResumeEvent();
947 else
948 doMacSuspendEvent();
949 break;
950 case mouseMovedMessage:
951 doMacMouseMovedMessage();
952 break;
953 }
954 }
955
956 void wxApp::doMacHighLevelEvent(void)
957 {
958 ::AEProcessAppleEvent(&m_event); // System 7 or higher
959 }
960
961 void wxApp::doMacResumeEvent(void)
962 {
963 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(::FrontWindow());
964 if (theMacWxFrame)
965 {
966 if (m_event.message & convertClipboardFlag)
967 ::TEFromScrap();
968
969 wxActivateEvent event(wxEVT_ACTIVATE, TRUE);
970 event.m_timeStamp = m_event.when;
971 event.SetEventObject(theMacWxFrame);
972
973 theMacWxFrame->ProcessEvent(event);
974 }
975 }
976
977 void wxApp::doMacSuspendEvent(void)
978 {
979 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(::FrontWindow());
980 if (theMacWxFrame)
981 {
982 ::ZeroScrap();
983 ::TEToScrap();
984
985 wxActivateEvent event(wxEVT_ACTIVATE, FALSE);
986 event.m_timeStamp = m_event.when;
987 event.SetEventObject(theMacWxFrame);
988
989 theMacWxFrame->ProcessEvent(event);
990 }
991 }
992
993 void wxApp::doMacMouseMovedMessage(void)
994 { // based on "Programming for System 7" by Gary Little and Tim Swihart
995 if (m_cursorRgn)
996 ::DisposeRgn(m_cursorRgn);
997 m_cursorRgn = ::NewRgn();
998 ::SetRectRgn(m_cursorRgn, -32768, -32768, 32766, 32766);
999 }
1000
1001 void wxApp::doMacInMenuBar(long menuResult)
1002 {
1003 int macMenuId = HiWord(menuResult);
1004 int macMenuItemNum = LoWord(menuResult); // counting from 1
1005
1006 if (macMenuId == 0) // no menu item selected;
1007 return;
1008 if (macMenuId == 128)
1009 {
1010 if (macMenuItemNum != 1)
1011 { // if not the "About" entry (or the separator)
1012 Str255 daName;
1013 ::GetMenuItemText(GetMenuHandle(128), macMenuItemNum, daName);
1014 (void)::OpenDeskAcc(daName);
1015 ::HiliteMenu(0);
1016 return;
1017 }
1018 }
1019
1020 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(::FrontWindow());
1021 if (theMacWxFrame)
1022 {
1023 if ( theMacWxFrame->IsKindOf( CLASSINFO( wxDialog ) ) )
1024 (( wxDialog *) theMacWxFrame)->MacMenuSelect(m_event, macMenuId, macMenuItemNum);
1025 else if ( theMacWxFrame->IsKindOf( CLASSINFO( wxFrame ) ) )
1026 (( wxFrame *) theMacWxFrame)->MacMenuSelect(m_event, macMenuId, macMenuItemNum);
1027 }
1028 ::HiliteMenu(0);
1029 }
1030
1031 void wxApp::doMacInContent(WindowPtr window)
1032 {
1033 WindowPtr frontWindow = FrontWindow();
1034 if (window != frontWindow )
1035 {
1036 // SFSelectWindow( window ) ;
1037 }
1038 else
1039 {
1040 ControlHandle control ;
1041 Point localwhere = m_event.where ;
1042 GrafPtr port ;
1043 SInt16 controlpart ;
1044
1045 ::GetPort( &port ) ;
1046 ::SetPort( window ) ;
1047 ::GlobalToLocal( &localwhere ) ;
1048
1049 ::SetPort( port ) ;
1050
1051 if ( !gSFMacHasAppearance )
1052 {
1053 controlpart = FindControl( localwhere , window , &control ) ;
1054 }
1055 else
1056 {
1057 control = FindControlUnderMouse( localwhere , window , &controlpart ) ;
1058 }
1059
1060 if ( control && IsControlActive( control ) )
1061 {
1062 wxControl* wxc = (wxControl*) GetControlReference( control ) ;
1063
1064 if ( wxWindow::FindFocus() != wxc && wxc->AcceptsFocus() )
1065 {
1066 wxc->SetFocus() ;
1067 if ( wxWindow::FindFocus() != wxc )
1068 control = NULL ; // we were not able to change focus
1069 }
1070
1071 if ( control )
1072 {
1073 if ( !gSFMacHasAppearance)
1074 {
1075 controlpart = TrackControl( control , localwhere , NULL ) ;
1076 }
1077 else
1078 {
1079 controlpart = HandleControlClick( control , localwhere , m_event.modifiers , (ControlActionUPP) -1 ) ;
1080 }
1081
1082 if ( controlpart )
1083 {
1084 wxControl* wx = (wxControl*) GetControlReference( control ) ;
1085 if ( wx )
1086 wx->MacHandleControlClick( control , controlpart ) ;
1087 }
1088 }
1089 }
1090 else
1091 {
1092 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(window);
1093 if (theMacWxFrame)
1094 {
1095 doMacContentClick((wxFrame*)theMacWxFrame); // todo : this cast is wrong
1096 }
1097 }
1098 }
1099
1100 #if 0
1101 wxFrame* theMacWxFrame = findMacWxFrame(window);
1102 if (theMacWxFrame)
1103 {
1104 WindowPtr MacWindow = findFrontNonFloatingWindow();
1105 if (window != MacWindow)
1106 {
1107 wxFrame* frontFrame = findMacWxFrame(MacWindow);
1108 if (!frontFrame) wxFatalError("No wxFrame for frontnonfloatingWindow.");
1109 if (!frontFrame->IsModal())
1110 {
1111 frontFrame->SetFocus();
1112 doMacContentClick(theMacWxFrame); // jonto - to deal with doc windows behind floaters ?
1113 ::newSelectWindow(window); // WCH : should I be calling some wxMethod?
1114 if (!IsFloating(MacWindow))
1115 {
1116 KeyMap keyMap;
1117 GetKeys(keyMap);
1118 if (!(keyMap[1] & 0x8000)) theMacWxFrame->ShowAsActive(true); // temporary measure...
1119 }
1120 } // jonto : not sure yet, but let's try this ...
1121 else ::SysBeep(3);
1122 }
1123 else
1124 {
1125 doMacContentClick(theMacWxFrame);
1126 }
1127 }
1128 #endif
1129 }
1130
1131 void wxApp::doMacContentClick(wxWindow* frame)
1132 {
1133 m_mouseWindow = frame;
1134
1135 wxMouseEvent event(wxEVT_LEFT_DOWN);
1136 event.m_shiftDown = m_event.modifiers & shiftKey;
1137 event.m_controlDown = m_event.modifiers & controlKey;
1138 event.m_altDown = m_event.modifiers & optionKey;
1139 event.m_metaDown = m_event.modifiers & cmdKey;
1140 event.m_leftDown = FALSE;
1141 event.m_middleDown = FALSE;
1142 event.m_rightDown = FALSE;
1143 if ( m_event.modifiers & controlKey )
1144 {
1145 event.m_rightDown = TRUE;
1146 }
1147 else
1148 {
1149 event.m_leftDown = TRUE;
1150 }
1151 #if 0
1152 event.m_leftDown = !(m_event.modifiers & btnState);
1153 event.m_middleDown = FALSE;
1154 event.m_rightDown = FALSE;
1155 #endif
1156 event.m_x = m_event.where.h;
1157 event.m_y = m_event.where.v;
1158 event.m_timeStamp = m_event.when;
1159 event.SetEventObject(m_mouseWindow);
1160
1161 // m_mouseWindow->ProcessEvent(event);
1162 m_mouseWindow->MacDispatchMouseEvent(event);
1163
1164 #if 0
1165 // RightButton is cmdKey click on the mac platform for one-button mouse
1166 Bool rightButton = cCurrentEvent.modifiers & cmdKey;
1167 // altKey is optionKey on the mac platform:
1168 Bool isAltKey = cCurrentEvent.modifiers & optionKey;
1169
1170 WXTYPE mouseEventType = rightButton ? wxEVENT_TYPE_RIGHT_DOWN
1171 : wxEVENT_TYPE_LEFT_DOWN;
1172 wxMouseEvent theMouseEvent(mouseEventType);
1173 theMouseEvent.leftDown = !rightButton;
1174 theMouseEvent.middleDown = FALSE;
1175 theMouseEvent.rightDown = rightButton;
1176 theMouseEvent.shiftDown = cCurrentEvent.modifiers & shiftKey;
1177 theMouseEvent.controlDown = cCurrentEvent.modifiers & controlKey;
1178 theMouseEvent.altDown = isAltKey;
1179 theMouseEvent.metaDown = FALSE; // mflatt
1180 theMouseEvent.timeStamp = cCurrentEvent.when; // mflatt
1181
1182 int hitX = cCurrentEvent.where.h; // screen window c.s.
1183 int hitY = cCurrentEvent.where.v; // screen window c.s.
1184
1185 frame->ScreenToWindow(&hitX, &hitY);
1186 // frameParentArea->ScreenToArea(&hitX, &hitY); // tx coords ?
1187 theMouseEvent.x = hitX; // frame parent area c.s.
1188 theMouseEvent.y = hitY; // frame parent area c.s.
1189
1190 frame->SeekMouseEventArea(theMouseEvent);
1191 #endif
1192 }
1193
1194 void wxApp::doMacInDrag(WindowPtr window)
1195 {
1196 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(window);
1197 if (theMacWxFrame)
1198 {
1199 // should be desktop, not screen
1200 Rect dragBoundsRect = qd.screenBits.bounds; // can't move to a different screen
1201 //xxx ::InsetRect(&dragBoundsRect, 4, ::GetMBarHeight() + 4); // This is not really necessary
1202 Rect oldPos = (**(((WindowPeek)window)->strucRgn)).rgnBBox;
1203 ::DragReferencedWindow(window, m_event.where, &dragBoundsRect); // jonto
1204 #if 0
1205 theMacWxFrame->m_x += (**(((WindowPeek)window)->strucRgn)).rgnBBox.left - oldPos.left;
1206 theMacWxFrame->m_y += (**(((WindowPeek)window)->strucRgn)).rgnBBox.top - oldPos.top;
1207 #endif
1208 Move( (**(((WindowPeek)window)->strucRgn)).rgnBBox.left , (**(((WindowPeek)window)->strucRgn)).rgnBBox.top ) ;
1209 #if 0
1210 theMacWxFrame->wxMacRecalcNewSize(); // Actually, recalc new position only
1211 #endif
1212 }
1213
1214 #if 0
1215 // if (window != ::FrontWindow())
1216 if (window != findFrontNonFloatingWindow())
1217 {
1218 // wxFrame* frontFrame = findMacWxFrame(::FrontWindow());
1219 wxFrame* frontFrame = findMacWxFrame(findFrontNonFloatingWindow());
1220 if (!frontFrame) wxFatalError("No wxFrame for frontWindow.");
1221 if (frontFrame->IsModal())
1222 {
1223 ::SysBeep(3);
1224 return;
1225 }
1226 }
1227
1228 wxFrame* theMacWxFrame = findMacWxFrame(window);
1229 if (theMacWxFrame)
1230 {
1231 Rect dragBoundsRect = qd.screenBits.bounds; // can't move to a different screen
1232 ::InsetRect(&dragBoundsRect, 4, ::GetMBarHeight() + 4); // This is not really necessary
1233 newDragWindow(window, cCurrentEvent.where, &dragBoundsRect); // jonto
1234 theMacWxFrame->wxMacRecalcNewSize(); // Actually, recalc new position only
1235 if (!IsFloating(window))
1236 {
1237 theMacWxFrame->ShowAsActive(true); // temporary measure...
1238 }
1239 }
1240 #endif
1241 }
1242
1243 void wxApp::doMacInGrow(WindowPtr window)
1244 {
1245 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(window);
1246 if (theMacWxFrame)
1247 {
1248 Rect growSizeRect; // WCH: growSizeRect should be a member of wxFrame class
1249 growSizeRect.top = 1; // minimum window height
1250 growSizeRect.left = 1; // minimum window width
1251 growSizeRect.bottom = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top;
1252 growSizeRect.right = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
1253 long windSize = ::GrowWindow(window, m_event.where, &growSizeRect);
1254 if (windSize != 0)
1255 {
1256 int nWidth = LoWord(windSize);
1257 int nHeight = HiWord(windSize);
1258 int oWidth, oHeight;
1259 theMacWxFrame->GetSize(&oWidth, &oHeight);
1260 if (nWidth == 0) nWidth = oWidth;
1261 if (nHeight == 0) nHeight = oHeight;
1262 theMacWxFrame->SetSize( -1, -1, nWidth, nHeight, wxSIZE_USE_EXISTING);
1263 }
1264 }
1265 }
1266
1267 void wxApp::doMacInGoAway(WindowPtr window)
1268 {
1269 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(window);
1270 if (theMacWxFrame)
1271 {
1272 if (TrackGoAway(window, m_event.where))
1273 {
1274 // TODO: Stefan, I think you need to send a wxCloseEvent to the window
1275 // here. The OnCloseWindow handler will take care of delete the frame
1276 // if it wishes to (there should be a default wxFrame::OnCloseWindow
1277 // that destroys the frame).
1278 if (theMacWxFrame->OnClose()) {
1279 #if WXGARBAGE_COLLECTION_ON
1280 theMacWxFrame->Show(FALSE);
1281 #else
1282 delete theMacWxFrame;
1283 #endif
1284 }
1285 }
1286 }
1287 }
1288
1289 void wxApp::doMacInZoom(WindowPtr window, short windowPart)
1290 {
1291 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(window);
1292 if (theMacWxFrame)
1293 {
1294 if (TrackBox(window, m_event.where, windowPart))
1295 {
1296 #if 0
1297 theMacWxFrame->Maximize(windowPart == inZoomOut);
1298 #endif
1299 }
1300 }
1301 }
1302
1303 long wxApp::macTranslateKey(char key, int mods)
1304 {
1305 static Handle transH = NULL;
1306 static unsigned long transState = 0;
1307 static Handle ScriptH = NULL;
1308 static short region_code = 1;
1309
1310 if (!ScriptH) { // tom: don't guess the regioncode!!!!
1311 struct ItlbRecord * r;
1312 ScriptH = GetResource('itlb',0);
1313 if (ScriptH) {
1314 HLock(ScriptH);
1315 r = (ItlbRecord*)*ScriptH;
1316 region_code = r->itlbKeys;
1317 HUnlock(ScriptH);
1318 }
1319 }
1320
1321 switch (key) {
1322 case 0x7e:
1323 case 0x3e:
1324 key = WXK_UP;
1325 break;
1326 case 0x7d:
1327 case 0x3d:
1328 key = WXK_DOWN;
1329 break;
1330 case 0x7b:
1331 case 0x3b:
1332 key = WXK_LEFT;
1333 break;
1334 case 0x7c:
1335 case 0x3c:
1336 key = WXK_RIGHT;
1337 break;
1338 case 0x24:
1339 case 0x4c:
1340 key = WXK_RETURN;
1341 break;
1342 case 0x30:
1343 key = WXK_TAB;
1344 break;
1345 case 0x33:
1346 key = WXK_BACK;
1347 break;
1348 case 0x75:
1349 key = WXK_DELETE;
1350 break;
1351 case 0x73:
1352 key = WXK_HOME;
1353 break;
1354 case 0x77:
1355 key = WXK_END;
1356 break;
1357 case 0x74:
1358 key = WXK_PAGEUP;
1359 break;
1360 case 0x79:
1361 key = WXK_PAGEDOWN;
1362 break;
1363 default:
1364 if (!transH) {
1365 transH = GetIndResource('KCHR', 1);
1366 HNoPurge(transH);
1367 }
1368 #if 0 //Tom replaces
1369 if (transH) {
1370 // Only let shift & option modify the key:
1371 HLock(transH);
1372 key = KeyTranslate(*transH, (key & 0x7F) | mods, &transState) & charCodeMask;
1373 HUnlock(transH);
1374 #else
1375 if (0) { // tom fettig@dfki.uni-sb.de
1376 // why if(0):
1377 // code is not correct, see inside Macintosh: Text 1-87
1378 // and 'itlk'-resource!!
1379 // and it is not necessary, as the translated char is in
1380 // cCurrrentEvent.message!!
1381 // Only let shift & option modify the key:
1382 HLock(transH);
1383 key = KeyTranslate(*transH, (key & 0x7F) | mods, &transState) & charCodeMask;
1384 HUnlock(transH);
1385 #endif
1386 }
1387 } // end switch
1388
1389 return key;
1390 }
1391
1392 void
1393 wxApp::macAdjustCursor()
1394 {
1395 if (m_event.what != kHighLevelEvent)
1396 {
1397 wxWindow* theMacWxFrame = wxFrame::MacFindFrameOrDialog(::FrontWindow());
1398 if (theMacWxFrame)
1399 {
1400 if (!theMacWxFrame->MacAdjustCursor(m_event.where))
1401 ::SetCursor(&(qd.arrow));
1402 }
1403 }
1404 }
1405 */