]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/window.mm
floating pane now respects IsFixed pane status; indirect fix for #4044
[wxWidgets.git] / src / osx / cocoa / window.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/cocoa/window.mm
3 // Purpose: widgets (non tlw) for cocoa
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 2008-06-20
7 // RCS-ID: $Id: window.mm 48805 2007-09-19 14:52:25Z SC $
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #include <Cocoa/Cocoa.h>
15
16 #ifdef __WXMAC__
17 #include "wx/osx/private.h"
18 #endif
19
20 #if wxOSX_USE_COCOA
21
22 @interface wxNSView : NSView
23 {
24 wxWidgetImpl* m_impl;
25 }
26
27 - (void)drawRect: (NSRect) rect;
28
29 -(void)mouseDown:(NSEvent *)event ;
30 -(void)rightMouseDown:(NSEvent *)event ;
31 -(void)otherMouseDown:(NSEvent *)event ;
32 -(void)mouseUp:(NSEvent *)event ;
33 -(void)rightMouseUp:(NSEvent *)event ;
34 -(void)otherMouseUp:(NSEvent *)event ;
35 -(void)handleMouseEvent:(NSEvent *)event;
36
37 - (void)setImplementation: (wxWidgetImpl *) theImplementation;
38 - (wxWidgetImpl*) implementation;
39 - (BOOL) isFlipped;
40 - (BOOL) becomeFirstResponder;
41 - (BOOL) resignFirstResponder;
42
43 @end // wxNSView
44
45 void SetupMouseEvent( wxMouseEvent &wxevent , NSEvent * nsEvent )
46 {
47 UInt32 modifiers = [nsEvent modifierFlags] ;
48 wxPoint screenMouseLocation = wxFromNSPoint( NULL, [nsEvent locationInWindow]);
49
50 // these parameters are not given for all events
51 UInt32 button = [nsEvent buttonNumber];
52 UInt32 clickCount = [nsEvent clickCount];
53 UInt32 mouseChord = 0; // TODO does this exist for cocoa
54
55 wxevent.m_x = screenMouseLocation.x;
56 wxevent.m_y = screenMouseLocation.y;
57 wxevent.m_shiftDown = modifiers & NSShiftKeyMask;
58 wxevent.m_controlDown = modifiers & NSControlKeyMask;
59 wxevent.m_altDown = modifiers & NSAlternateKeyMask;
60 wxevent.m_metaDown = modifiers & NSCommandKeyMask;
61 wxevent.m_clickCount = clickCount;
62 wxevent.SetTimestamp( [nsEvent timestamp] ) ;
63 /*
64 // a control click is interpreted as a right click
65 bool thisButtonIsFakeRight = false ;
66 if ( button == kEventMouseButtonPrimary && (modifiers & controlKey) )
67 {
68 button = kEventMouseButtonSecondary ;
69 thisButtonIsFakeRight = true ;
70 }
71
72 // otherwise we report double clicks by connecting a left click with a ctrl-left click
73 if ( clickCount > 1 && button != g_lastButton )
74 clickCount = 1 ;
75 // we must make sure that our synthetic 'right' button corresponds in
76 // mouse down, moved and mouse up, and does not deliver a right down and left up
77
78 if ( cEvent.GetKind() == kEventMouseDown )
79 {
80 g_lastButton = button ;
81 g_lastButtonWasFakeRight = thisButtonIsFakeRight ;
82 }
83
84 if ( button == 0 )
85 {
86 g_lastButton = 0 ;
87 g_lastButtonWasFakeRight = false ;
88 }
89 else if ( g_lastButton == kEventMouseButtonSecondary && g_lastButtonWasFakeRight )
90 button = g_lastButton ;
91
92 // Adjust the chord mask to remove the primary button and add the
93 // secondary button. It is possible that the secondary button is
94 // already pressed, e.g. on a mouse connected to a laptop, but this
95 // possibility is ignored here:
96 if( thisButtonIsFakeRight && ( mouseChord & 1U ) )
97 mouseChord = ((mouseChord & ~1U) | 2U);
98
99 if(mouseChord & 1U)
100 wxevent.m_leftDown = true ;
101 if(mouseChord & 2U)
102 wxevent.m_rightDown = true ;
103 if(mouseChord & 4U)
104 wxevent.m_middleDown = true ;
105
106 */
107 // translate into wx types
108 int eventType = [nsEvent type];
109 switch (eventType)
110 {
111 case NSLeftMouseDown :
112 case NSRightMouseDown :
113 case NSOtherMouseDown :
114 switch ( button )
115 {
116 case 0 :
117 wxevent.SetEventType( clickCount > 1 ? wxEVT_LEFT_DCLICK : wxEVT_LEFT_DOWN ) ;
118 break ;
119
120 case 1 :
121 wxevent.SetEventType( clickCount > 1 ? wxEVT_RIGHT_DCLICK : wxEVT_RIGHT_DOWN ) ;
122 break ;
123
124 case 2 :
125 wxevent.SetEventType( clickCount > 1 ? wxEVT_MIDDLE_DCLICK : wxEVT_MIDDLE_DOWN ) ;
126 break ;
127
128 default:
129 break ;
130 }
131 break ;
132
133 case NSLeftMouseUp :
134 case NSRightMouseUp :
135 case NSOtherMouseUp :
136 switch ( button )
137 {
138 case 0 :
139 wxevent.SetEventType( wxEVT_LEFT_UP ) ;
140 break ;
141
142 case 1 :
143 wxevent.SetEventType( wxEVT_RIGHT_UP ) ;
144 break ;
145
146 case 2 :
147 wxevent.SetEventType( wxEVT_MIDDLE_UP ) ;
148 break ;
149
150 default:
151 break ;
152 }
153 break ;
154
155 case NSScrollWheel :
156 {
157 wxevent.SetEventType( wxEVT_MOUSEWHEEL ) ;
158 /*
159 EventMouseWheelAxis axis = cEvent.GetParameter<EventMouseWheelAxis>(kEventParamMouseWheelAxis, typeMouseWheelAxis) ;
160 SInt32 delta = cEvent.GetParameter<SInt32>(kEventParamMouseWheelDelta, typeSInt32) ;
161 */
162 wxevent.m_wheelRotation = 10; // delta;
163 wxevent.m_wheelDelta = 1;
164 wxevent.m_linesPerAction = 1;
165 if ( 0 /* axis == kEventMouseWheelAxisX*/ )
166 wxevent.m_wheelAxis = 1;
167 }
168 break ;
169
170 case NSMouseEntered :
171 case NSMouseExited :
172 case NSLeftMouseDragged :
173 case NSRightMouseDragged :
174 case NSOtherMouseDragged :
175 case NSMouseMoved :
176 wxevent.SetEventType( wxEVT_MOTION ) ;
177 break;
178 default :
179 break ;
180 }
181 }
182
183 @implementation wxNSView
184
185 - (void)drawRect: (NSRect) rect
186 {
187 if ( m_impl )
188 {
189 CGContextRef context = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
190 CGContextSaveGState( context );
191 CGContextBeginPath( context );
192 CGContextMoveToPoint(context, 0, 0);
193 NSRect bounds = [self bounds];
194 CGContextAddLineToPoint(context, 10, 0);
195 CGContextMoveToPoint(context, 0, 0);
196 CGContextAddLineToPoint(context, 0, 10);
197 CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
198 CGContextAddLineToPoint(context, bounds.size.width, bounds.size.height-10);
199 CGContextMoveToPoint(context, bounds.size.width, bounds.size.height);
200 CGContextAddLineToPoint(context, bounds.size.width-10, bounds.size.height);
201 CGContextClosePath( context );
202 CGContextStrokePath(context);
203
204 if ( [ self isFlipped ] == NO )
205 {
206 CGContextTranslateCTM( context, 0, [self bounds].size.height );
207 CGContextScaleCTM( context, 1, -1 );
208 }
209 m_impl->GetWXPeer()->MacSetCGContextRef( context );
210
211 wxPaintEvent event;
212 event.SetTimestamp(0); // todo
213 event.SetEventObject(m_impl->GetWXPeer());
214 m_impl->GetWXPeer()->HandleWindowEvent(event);
215
216 CGContextRestoreGState( context );
217 }
218 }
219
220 -(void)mouseDown:(NSEvent *)event
221 {
222 [self handleMouseEvent:event];
223 }
224
225 -(void)rightMouseDown:(NSEvent *)event
226 {
227 [self handleMouseEvent:event];
228 }
229
230 -(void)otherMouseDown:(NSEvent *)event
231 {
232 [self handleMouseEvent:event];
233 }
234
235 -(void)mouseUp:(NSEvent *)event
236 {
237 [self handleMouseEvent:event];
238 }
239
240 -(void)rightMouseUp:(NSEvent *)event
241 {
242 [self handleMouseEvent:event];
243 }
244
245 -(void)otherMouseUp:(NSEvent *)event
246 {
247 [self handleMouseEvent:event];
248 }
249
250 -(void)handleMouseEvent:(NSEvent *)event
251 {
252 NSPoint clickLocation;
253 clickLocation = [self convertPoint:[event locationInWindow] fromView:nil];
254 wxPoint pt = wxFromNSPoint( self, clickLocation );
255 wxMouseEvent wxevent(wxEVT_LEFT_DOWN);
256 SetupMouseEvent( wxevent , event ) ;
257 wxevent.m_x = pt.x;
258 wxevent.m_y = pt.y;
259 m_impl->GetWXPeer()->HandleWindowEvent(wxevent);
260 }
261
262 - (void)setImplementation: (wxWidgetImpl *) theImplementation
263 {
264 m_impl = theImplementation;
265 }
266
267 - (wxWidgetImpl*) implementation
268 {
269 return m_impl;
270 }
271
272 - (BOOL) isFlipped
273 {
274 return YES;
275 }
276
277 - (BOOL) becomeFirstResponder
278 {
279 BOOL r = [super becomeFirstResponder];
280 if ( r )
281 {
282 }
283 return r;
284 }
285
286 - (BOOL) resignFirstResponder
287 {
288 BOOL r = [super resignFirstResponder];
289 if ( r )
290 {
291 }
292 return r;
293 }
294
295
296 @end // wxNSView
297
298 IMPLEMENT_DYNAMIC_CLASS( wxWidgetCocoaImpl , wxWidgetImpl )
299
300 wxWidgetCocoaImpl::wxWidgetCocoaImpl( wxWindowMac* peer , WXWidget w, bool isRootControl ) :
301 wxWidgetImpl( peer, isRootControl ), m_osxView(w)
302 {
303 }
304
305 wxWidgetCocoaImpl::wxWidgetCocoaImpl()
306 {
307 }
308
309 void wxWidgetCocoaImpl::Init()
310 {
311 m_osxView = NULL;
312 }
313
314 wxWidgetCocoaImpl::~wxWidgetCocoaImpl()
315 {
316 [m_osxView setImplementation:NULL];
317 [m_osxView release];
318 }
319
320 bool wxWidgetCocoaImpl::IsVisible() const
321 {
322 return [m_osxView isHiddenOrHasHiddenAncestor] == NO;
323 }
324
325 void wxWidgetCocoaImpl::Raise()
326 {
327 }
328
329 void wxWidgetCocoaImpl::Lower()
330 {
331 }
332
333 void wxWidgetCocoaImpl::ScrollRect( const wxRect *rect, int dx, int dy )
334 {
335 }
336
337 void wxWidgetCocoaImpl::Move(int x, int y, int width, int height)
338 {
339 NSRect r = wxToNSRect( [m_osxView superview], wxRect(x,y,width, height) );
340 [m_osxView setFrame:r];
341 }
342
343 void wxWidgetCocoaImpl::GetPosition( int &x, int &y ) const
344 {
345 wxRect r = wxFromNSRect( [m_osxView superview], [m_osxView frame] );
346 x = r.GetLeft();
347 y = r.GetTop();
348 }
349
350 void wxWidgetCocoaImpl::GetSize( int &width, int &height ) const
351 {
352 NSRect rect = [m_osxView frame];
353 width = rect.size.width;
354 height = rect.size.height;
355 }
356
357 void wxWidgetCocoaImpl::GetContentArea( int&left, int &top, int &width, int &height )
358 {
359 left = top = 0;
360 GetSize( width, height );
361 }
362
363 void wxWidgetCocoaImpl::SetNeedsDisplay( const wxRect* where )
364 {
365 if ( where )
366 [m_osxView setNeedsDisplayInRect:wxToNSRect(m_osxView, *where )];
367 else
368 [m_osxView setNeedsDisplay:YES];
369 }
370
371 bool wxWidgetCocoaImpl::GetNeedsDisplay() const
372 {
373 return [m_osxView needsDisplay];
374 }
375
376 void wxWidgetCocoaImpl::CanFocus() const
377 {
378 return [m_osxView acceptsFirstResponder] == YES;
379 }
380
381 bool wxWidgetCocoaImpl::HasFocus() const
382 {
383 return [m_osxView isFirstResponder] == YES;
384 }
385
386 bool wxWidgetCocoaImpl::SetFocus()
387 {
388 [m_osxView makeKeyWindow] ;
389 }
390
391
392 void wxWidgetCocoaImpl::RemoveFromParent()
393 {
394 [m_osxView removeFromSuperview];
395 }
396
397 void wxWidgetCocoaImpl::Embed( wxWidgetImpl *parent )
398 {
399 NSView* container = parent->GetWXWidget() ;
400 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ;
401 [container addSubview:m_osxView];
402 }
403
404
405 //
406 // Factory methods
407 //
408
409 wxWidgetImpl* wxWidgetImpl::CreateUserPane( wxWindowMac* wxpeer, const wxPoint& pos, const wxSize& size,
410 long style, long extraStyle, const wxString& name)
411 {
412 NSView* sv = (wxpeer->GetParent()->GetHandle() );
413
414 NSRect r = wxToNSRect( sv, wxRect( pos, size) );
415 // Rect bounds = wxMacGetBoundsForControl( wxpeer, pos , size ) ;
416 wxNSView* v = [[wxNSView alloc] initWithFrame:r];
417 [sv addSubview:v];
418 wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( wxpeer, v );
419 [v setImplementation:c];
420 return c;
421 }
422
423 wxWidgetImpl* wxWidgetImpl::CreateContentView( wxNonOwnedWindow* now )
424 {
425 NSWindow* tlw = now->GetWXWindow();
426 wxNSView* v = [[wxNSView alloc] initWithFrame:[[tlw contentView] frame]];
427 wxWidgetCocoaImpl* c = new wxWidgetCocoaImpl( now, v, true );
428 [v setImplementation:c];
429 [tlw setContentView:v];
430 return c;
431 }
432
433
434 #endif