Send activate/deactivate events for become/resign key
[wxWidgets.git] / src / cocoa / toplevel.mm
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        cocoa/toplevel.mm
3 // Purpose:     implements wxTopLevelWindow for Cocoa
4 // Author:      David Elliott 
5 // Modified by:
6 // Created:     2002/11/27
7 // RCS-ID:      $Id:
8 // Copyright:   (c) 2002 David Elliott
9 // License:     wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22 #ifndef WX_PRECOMP
23     #include "wx/window.h"
24     #include "wx/toplevel.h"
25     #include "wx/menuitem.h"
26     #include "wx/frame.h"
27     #include "wx/log.h"
28     #include "wx/app.h"
29 #endif //WX_PRECOMP
30
31 #include "wx/cocoa/autorelease.h"
32
33 #import <AppKit/NSView.h>
34 #import <AppKit/NSWindow.h>
35 // ----------------------------------------------------------------------------
36 // globals
37 // ----------------------------------------------------------------------------
38
39 // list of all frames and modeless dialogs
40 wxWindowList       wxModelessWindows;
41
42 // ============================================================================
43 // wxTopLevelWindowCocoa implementation
44 // ============================================================================
45
46 // ----------------------------------------------------------------------------
47 // wxTopLevelWindowCocoa creation
48 // ----------------------------------------------------------------------------
49 BEGIN_EVENT_TABLE(wxTopLevelWindowCocoa,wxTopLevelWindowBase)
50     EVT_CLOSE(wxTopLevelWindowCocoa::OnCloseWindow)
51 END_EVENT_TABLE()
52
53 void wxTopLevelWindowCocoa::Init()
54 {
55     m_iconized =
56     m_maximizeOnShow =
57     m_closed = false;
58 }
59
60 bool wxTopLevelWindowCocoa::Create(wxWindow *parent,
61                                  wxWindowID winid,
62                                  const wxString& title,
63                                  const wxPoint& pos,
64                                  const wxSize& size,
65                                  long style,
66                                  const wxString& name)
67 {
68     wxAutoNSAutoreleasePool pool;
69     wxTopLevelWindows.Append(this);
70
71     if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
72         return FALSE;
73
74     if ( parent )
75         parent->AddChild(this);
76
77     // TODO: get rect from given position/size
78     NSRect cocoaRect =  NSMakeRect(100,100,200,200);
79
80     // TODO: Set flags given wxWindows style
81     unsigned int cocoaStyle = 0;
82     cocoaStyle |= NSTitledWindowMask;
83     cocoaStyle |= NSClosableWindowMask;
84     cocoaStyle |= NSMiniaturizableWindowMask;
85     cocoaStyle |= NSResizableWindowMask;
86
87     m_cocoaNSWindow = NULL;
88     m_cocoaNSView = NULL;
89     SetNSWindow([[NSWindow alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
90     // NOTE: SetNSWindow has retained the Cocoa object for this object.
91     // Because we do not release on close, the following release matches the
92     // above alloc and thus the retain count will be 1.
93     [m_cocoaNSWindow release];
94
95     return TRUE;
96 }
97
98 wxTopLevelWindowCocoa::~wxTopLevelWindowCocoa()
99 {
100     wxAutoNSAutoreleasePool pool;
101     DestroyChildren();
102     SetNSWindow(NULL);
103 }
104
105 // ----------------------------------------------------------------------------
106 // wxTopLevelWindowCocoa Cocoa Specifics
107 // ----------------------------------------------------------------------------
108
109 void wxTopLevelWindowCocoa::SetNSWindow(WX_NSWindow cocoaNSWindow)
110 {
111     bool need_debug = cocoaNSWindow || m_cocoaNSWindow;
112     if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [m_cocoaNSWindow=%p retainCount]=%d",this,m_cocoaNSWindow,[m_cocoaNSWindow retainCount]);
113     DisassociateNSWindow(m_cocoaNSWindow);
114     [cocoaNSWindow retain];
115     [m_cocoaNSWindow release];
116     m_cocoaNSWindow = cocoaNSWindow;
117     if(m_cocoaNSWindow)
118         SetNSView([m_cocoaNSWindow contentView]);
119     else
120         SetNSView(NULL);
121     AssociateNSWindow(m_cocoaNSWindow);
122     if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [cocoaNSWindow=%p retainCount]=%d",this,cocoaNSWindow,[cocoaNSWindow retainCount]);
123 }
124
125 void wxTopLevelWindowCocoa::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
126 {
127     if([m_cocoaNSWindow contentView] == oldView)
128         [m_cocoaNSWindow setContentView:newView];
129 }
130
131 void wxTopLevelWindowCocoa::Cocoa_wxMenuItemAction(wxMenuItem& item)
132 {
133 }
134
135 void wxTopLevelWindowCocoa::CocoaNotification_DidBecomeKey(void)
136 {
137     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaNotification_DidBecomeKey",this);
138     wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
139     event.SetEventObject(this);
140     GetEventHandler()->ProcessEvent(event);
141 }
142
143 void wxTopLevelWindowCocoa::CocoaNotification_DidResignKey(void)
144 {
145     wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaNotification_DidResignKey",this);
146     wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
147     event.SetEventObject(this);
148     GetEventHandler()->ProcessEvent(event);
149 }
150
151 void wxTopLevelWindowCocoa::Cocoa_close(void)
152 {
153     m_closed = true;
154     Destroy();
155     /* Be SURE that idle events get ran.  If the window was not active when
156     it was closed, then there will be no more events to trigger this and
157     therefore it must be done here */
158     wxTheApp->CocoaInstallRequestedIdleHandler();
159 }
160
161 bool wxTopLevelWindowCocoa::Cocoa_windowShouldClose()
162 {
163     return wxWindowBase::Close(false);
164 }
165
166 // ----------------------------------------------------------------------------
167 // wxTopLevelWindowCocoa maximize/minimize
168 // ----------------------------------------------------------------------------
169
170 void wxTopLevelWindowCocoa::Maximize(bool maximize)
171 {
172 }
173
174 bool wxTopLevelWindowCocoa::IsMaximized() const
175 {
176     return false ; 
177 }
178
179 void wxTopLevelWindowCocoa::Iconize(bool iconize)
180 {
181 }
182
183 bool wxTopLevelWindowCocoa::IsIconized() const
184 {
185     return FALSE;
186 }
187
188 void wxTopLevelWindowCocoa::Restore()
189 {
190 }
191
192 bool wxTopLevelWindowCocoa::Show(bool show)
193 {
194     wxAutoNSAutoreleasePool pool;
195     if(show)
196     {
197         // Send the window a size event because wxWindows apps expect it
198         // NOTE: This should really only be done the first time a window
199         // is shown.  I doubt this will cause any problems though.
200         wxSizeEvent event(GetSize(), GetId());
201         event.SetEventObject(this);
202         GetEventHandler()->ProcessEvent(event);
203
204         [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
205     }
206     else
207         [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
208     return true;
209 }
210
211 bool wxTopLevelWindowCocoa::Close(bool force)
212 {
213     if(force)
214         return wxWindowBase::Close(force);
215     // performClose  will fake the user clicking the close button which
216     // will invoke windowShouldClose which will call the base class version
217     // of Close() which will NOT Destroy() the window (see below) but
218     // if closing is not stopped, then performClose will go ahead and
219     // close the window which will invoke Cocoa_close() setting m_closed
220     // to true and Destroy()ing the window.
221     [m_cocoaNSWindow performClose:m_cocoaNSWindow];
222     return m_closed;
223 }
224
225 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
226 {
227     // If the event was forced, close the window which will Destroy() it
228     if(!event.CanVeto())
229         [m_cocoaNSWindow close];
230     // if the event was not forced, it's probably because the user clicked
231     // the close button, or Close(false) was called which (see above) is
232     // redirected to performClose and thus Cocoa itself will close the window
233 }
234
235 // ----------------------------------------------------------------------------
236 // wxTopLevelWindowCocoa misc
237 // ----------------------------------------------------------------------------
238
239 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
240 {
241     return FALSE;
242 }
243
244 bool wxTopLevelWindowCocoa::IsFullScreen() const
245 {
246     return FALSE;
247 }
248
249 void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
250 {
251     // Set the NSView size by setting the frame size to enclose it
252     unsigned int styleMask = [m_cocoaNSWindow styleMask];
253     NSRect frameRect = [m_cocoaNSWindow frame];
254     NSRect contentRect = [NSWindow
255         contentRectForFrameRect: frameRect
256         styleMask: styleMask];
257     contentRect.size.width = width;
258     contentRect.size.height = height;
259     frameRect = [NSWindow
260         frameRectForContentRect: contentRect
261         styleMask: styleMask];
262     [m_cocoaNSWindow setFrame: frameRect display: NO];
263 }
264
265 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
266 {
267 //    wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
268
269     NSRect cocoaRect = NSMakeRect(x,y,width,height);
270     [m_cocoaNSWindow setFrame: cocoaRect display:NO];
271 }
272
273 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
274 {
275     NSRect cocoaRect = [m_cocoaNSWindow frame];
276     if(w)
277         *w=(int)cocoaRect.size.width;
278     if(h)
279         *h=(int)cocoaRect.size.height;
280 //    wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
281 }
282
283 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
284 {
285     NSRect cocoaRect = [m_cocoaNSWindow frame];
286     if(x)
287         *x=(int)cocoaRect.origin.x;
288     if(y)
289         *y=(int)cocoaRect.origin.y;
290 //    wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);
291 }
292