]> git.saurik.com Git - wxWidgets.git/blob - src/cocoa/toplevel.mm
Very lame fix for windows with -1 for a component of position or size
[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 // Licence: wxWindows licence
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 #include "wx/cocoa/string.h"
33
34 #import <AppKit/NSView.h>
35 #import <AppKit/NSWindow.h>
36 #import <AppKit/NSPanel.h>
37 // ----------------------------------------------------------------------------
38 // globals
39 // ----------------------------------------------------------------------------
40
41 // list of all frames and modeless dialogs
42 wxWindowList wxModelessWindows;
43
44 // ============================================================================
45 // wxTopLevelWindowCocoa implementation
46 // ============================================================================
47
48 // ----------------------------------------------------------------------------
49 // wxTopLevelWindowCocoa creation
50 // ----------------------------------------------------------------------------
51 BEGIN_EVENT_TABLE(wxTopLevelWindowCocoa,wxTopLevelWindowBase)
52 EVT_CLOSE(wxTopLevelWindowCocoa::OnCloseWindow)
53 END_EVENT_TABLE()
54
55 void wxTopLevelWindowCocoa::Init()
56 {
57 m_iconized =
58 m_maximizeOnShow =
59 m_closed = false;
60 }
61
62 unsigned int wxTopLevelWindowCocoa::NSWindowStyleForWxStyle(long style)
63 {
64 unsigned int styleMask = 0;
65 if(style & wxCAPTION)
66 styleMask |= NSTitledWindowMask;
67 if(style & wxMINIMIZE_BOX)
68 styleMask |= NSMiniaturizableWindowMask;
69 #if 0
70 if(style & wxMAXIMIZE_BOX)
71 styleMask |= NSWindowMask;
72 #endif
73 if(style & wxCLOSE_BOX)
74 styleMask |= NSClosableWindowMask;
75 if(style & wxRESIZE_BORDER)
76 styleMask |= NSResizableWindowMask;
77 if(style & wxSIMPLE_BORDER)
78 styleMask |= NSBorderlessWindowMask;
79 return styleMask;
80 }
81
82 bool wxTopLevelWindowCocoa::Create(wxWindow *parent,
83 wxWindowID winid,
84 const wxString& title,
85 const wxPoint& pos,
86 const wxSize& size,
87 long style,
88 const wxString& name)
89 {
90 wxAutoNSAutoreleasePool pool;
91 wxTopLevelWindows.Append(this);
92
93 if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
94 return FALSE;
95
96 if ( parent )
97 parent->AddChild(this);
98
99 unsigned int cocoaStyle = NSWindowStyleForWxStyle(style);
100 if(style & wxFRAME_TOOL_WINDOW)
101 cocoaStyle |= NSUtilityWindowMask;
102
103 wxPoint realpos = pos;
104 wxSize realsize = size;
105 // FIXME: this is lame
106 if(realpos.x==-1)
107 realpos.x=100;
108 if(realpos.y==-1)
109 realpos.y=100;
110 if(realsize.x==-1)
111 realsize.x=200;
112 if(realsize.y==-1)
113 realsize.y=200;
114 // NOTE: y-origin needs to be flipped.
115 NSRect cocoaRect = [NSWindow contentRectForFrameRect:NSMakeRect(realpos.x,realpos.y,realsize.x,realsize.y) styleMask:cocoaStyle];
116
117 m_cocoaNSWindow = NULL;
118 m_cocoaNSView = NULL;
119 if(style & wxFRAME_TOOL_WINDOW)
120 SetNSWindow([[NSPanel alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
121 else
122 SetNSWindow([[NSWindow alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
123 // NOTE: SetNSWindow has retained the Cocoa object for this object.
124 // Because we do not release on close, the following release matches the
125 // above alloc and thus the retain count will be 1.
126 [m_cocoaNSWindow release];
127
128 if(style & wxFRAME_NO_TASKBAR)
129 [m_cocoaNSWindow setExcludedFromWindowsMenu: YES];
130 if(style & wxSTAY_ON_TOP)
131 [m_cocoaNSWindow setLevel:NSFloatingWindowLevel];
132 [m_cocoaNSWindow setTitle:wxNSStringWithWxString(title)];
133 return TRUE;
134 }
135
136 wxTopLevelWindowCocoa::~wxTopLevelWindowCocoa()
137 {
138 wxAutoNSAutoreleasePool pool;
139 DestroyChildren();
140 SetNSWindow(NULL);
141 }
142
143 // ----------------------------------------------------------------------------
144 // wxTopLevelWindowCocoa Cocoa Specifics
145 // ----------------------------------------------------------------------------
146
147 wxMenuBar* wxTopLevelWindowCocoa::GetAppMenuBar(wxCocoaNSWindow *win)
148 {
149 wxTopLevelWindowCocoa *parent = wxDynamicCast(GetParent(),wxTopLevelWindow);
150 if(parent)
151 return parent->GetAppMenuBar(win);
152 return NULL;
153 }
154
155 void wxTopLevelWindowCocoa::SetNSWindow(WX_NSWindow cocoaNSWindow)
156 {
157 bool need_debug = cocoaNSWindow || m_cocoaNSWindow;
158 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [m_cocoaNSWindow=%p retainCount]=%d",this,m_cocoaNSWindow,[m_cocoaNSWindow retainCount]);
159 DisassociateNSWindow(m_cocoaNSWindow);
160 [cocoaNSWindow retain];
161 [m_cocoaNSWindow release];
162 m_cocoaNSWindow = cocoaNSWindow;
163 if(m_cocoaNSWindow)
164 SetNSView([m_cocoaNSWindow contentView]);
165 else
166 SetNSView(NULL);
167 AssociateNSWindow(m_cocoaNSWindow);
168 if(need_debug) wxLogDebug("wxTopLevelWindowCocoa=%p::SetNSWindow [cocoaNSWindow=%p retainCount]=%d",this,cocoaNSWindow,[cocoaNSWindow retainCount]);
169 }
170
171 void wxTopLevelWindowCocoa::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
172 {
173 if([m_cocoaNSWindow contentView] == (id)oldView)
174 [m_cocoaNSWindow setContentView:newView];
175 }
176
177 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeKey(void)
178 {
179 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeKey",this);
180 wxActivateEvent event(wxEVT_ACTIVATE, TRUE, GetId());
181 event.SetEventObject(this);
182 GetEventHandler()->ProcessEvent(event);
183 }
184
185 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignKey(void)
186 {
187 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignKey",this);
188 wxActivateEvent event(wxEVT_ACTIVATE, FALSE, GetId());
189 event.SetEventObject(this);
190 GetEventHandler()->ProcessEvent(event);
191 }
192
193 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidBecomeMain(void)
194 {
195 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidBecomeMain",this);
196 }
197
198 void wxTopLevelWindowCocoa::CocoaDelegate_windowDidResignMain(void)
199 {
200 wxLogDebug("wxTopLevelWindowCocoa=%p::CocoaDelegate_windowDidResignMain",this);
201 }
202
203 void wxTopLevelWindowCocoa::CocoaDelegate_windowWillClose(void)
204 {
205 m_closed = true;
206 Destroy();
207 /* Be SURE that idle events get ran. If the window was not active when
208 it was closed, then there will be no more events to trigger this and
209 therefore it must be done here */
210 wxTheApp->CocoaInstallRequestedIdleHandler();
211 }
212
213 bool wxTopLevelWindowCocoa::CocoaDelegate_windowShouldClose()
214 {
215 return wxWindowBase::Close(false);
216 }
217
218 // ----------------------------------------------------------------------------
219 // wxTopLevelWindowCocoa maximize/minimize
220 // ----------------------------------------------------------------------------
221
222 void wxTopLevelWindowCocoa::Maximize(bool maximize)
223 {
224 }
225
226 bool wxTopLevelWindowCocoa::IsMaximized() const
227 {
228 return false ;
229 }
230
231 void wxTopLevelWindowCocoa::Iconize(bool iconize)
232 {
233 }
234
235 bool wxTopLevelWindowCocoa::IsIconized() const
236 {
237 return FALSE;
238 }
239
240 void wxTopLevelWindowCocoa::Restore()
241 {
242 }
243
244 bool wxTopLevelWindowCocoa::Show(bool show)
245 {
246 if(m_isShown == show)
247 return false;
248 wxAutoNSAutoreleasePool pool;
249 if(show)
250 {
251 // Send the window a size event because wxWindows apps expect it
252 // NOTE: This should really only be done the first time a window
253 // is shown. I doubt this will cause any problems though.
254 wxSizeEvent event(GetSize(), GetId());
255 event.SetEventObject(this);
256 GetEventHandler()->ProcessEvent(event);
257
258 [m_cocoaNSWindow makeKeyAndOrderFront:m_cocoaNSWindow];
259 }
260 else
261 [m_cocoaNSWindow orderOut:m_cocoaNSWindow];
262 m_isShown = show;
263 return true;
264 }
265
266 bool wxTopLevelWindowCocoa::Close(bool force)
267 {
268 if(force)
269 return wxWindowBase::Close(force);
270 // performClose will fake the user clicking the close button which
271 // will invoke windowShouldClose which will call the base class version
272 // of Close() which will NOT Destroy() the window (see below) but
273 // if closing is not stopped, then performClose will go ahead and
274 // close the window which will send the close notifications setting
275 // m_closed to true and Destroy()ing the window.
276 [m_cocoaNSWindow performClose:m_cocoaNSWindow];
277 return m_closed;
278 }
279
280 void wxTopLevelWindowCocoa::OnCloseWindow(wxCloseEvent& event)
281 {
282 // If the event was forced, close the window which will Destroy() it
283 if(!event.CanVeto())
284 [m_cocoaNSWindow close];
285 // if the event was not forced, it's probably because the user clicked
286 // the close button, or Close(false) was called which (see above) is
287 // redirected to performClose and thus Cocoa itself will close the window
288 }
289
290 // ----------------------------------------------------------------------------
291 // wxTopLevelWindowCocoa misc
292 // ----------------------------------------------------------------------------
293
294 bool wxTopLevelWindowCocoa::ShowFullScreen(bool show, long style)
295 {
296 return FALSE;
297 }
298
299 bool wxTopLevelWindowCocoa::IsFullScreen() const
300 {
301 return FALSE;
302 }
303
304 void wxTopLevelWindowCocoa::CocoaSetWxWindowSize(int width, int height)
305 {
306 // Set the NSView size by setting the frame size to enclose it
307 unsigned int styleMask = [m_cocoaNSWindow styleMask];
308 NSRect frameRect = [m_cocoaNSWindow frame];
309 NSRect contentRect = [NSWindow
310 contentRectForFrameRect: frameRect
311 styleMask: styleMask];
312 contentRect.size.width = width;
313 contentRect.size.height = height;
314 frameRect = [NSWindow
315 frameRectForContentRect: contentRect
316 styleMask: styleMask];
317 [m_cocoaNSWindow setFrame: frameRect display: NO];
318 }
319
320 void wxTopLevelWindowCocoa::DoMoveWindow(int x, int y, int width, int height)
321 {
322 // wxLogDebug("wxTopLevelWindow=%p::DoMoveWindow(%d,%d,%d,%d)",this,x,y,width,height);
323
324 NSRect cocoaRect = NSMakeRect(x,y,width,height);
325 [m_cocoaNSWindow setFrame: cocoaRect display:NO];
326 }
327
328 void wxTopLevelWindowCocoa::DoGetSize(int *w, int *h) const
329 {
330 NSRect cocoaRect = [m_cocoaNSWindow frame];
331 if(w)
332 *w=(int)cocoaRect.size.width;
333 if(h)
334 *h=(int)cocoaRect.size.height;
335 // wxLogDebug("wxTopLevelWindow=%p::DoGetSize = (%d,%d)",this,(int)cocoaRect.size.width,(int)cocoaRect.size.height);
336 }
337
338 void wxTopLevelWindowCocoa::DoGetPosition(int *x, int *y) const
339 {
340 NSRect cocoaRect = [m_cocoaNSWindow frame];
341 if(x)
342 *x=(int)cocoaRect.origin.x;
343 if(y)
344 *y=(int)cocoaRect.origin.y;
345 // wxLogDebug("wxTopLevelWindow=%p::DoGetPosition = (%d,%d)",this,(int)cocoaRect.origin.x,(int)cocoaRect.origin.y);
346 }
347