0025973: Visualization, TKOpenGl - support EAGLContext as alternative to NSOpenGLContext
[occt.git] / src / Cocoa / Cocoa_Window.mm
CommitLineData
6aca4d39 1// Created on: 2012-11-12
4fe56619 2// Created by: Kirill GAVRILOV
6aca4d39 3// Copyright (c) 2012-2014 OPEN CASCADE SAS
4fe56619 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
4fe56619 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
4fe56619 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
4fe56619 15
a2e4f780 16#import <TargetConditionals.h>
17
18#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
19 #import <UIKit/UIKit.h>
20#else
21 #import <Cocoa/Cocoa.h>
22#endif
4fe56619 23
24#include <Cocoa_Window.hxx>
25
26#include <Cocoa_LocalPool.hxx>
27
28#include <Image_AlienPixMap.hxx>
29#include <Aspect_Convert.hxx>
4fe56619 30#include <Aspect_WindowDefinitionError.hxx>
31
32IMPLEMENT_STANDARD_HANDLE (Cocoa_Window, Aspect_Window)
33IMPLEMENT_STANDARD_RTTIEXT(Cocoa_Window, Aspect_Window)
34
a2e4f780 35#if defined(__clang__) && (__clang_major__ >= 4) && __has_feature(objc_arc)
36 #define HAVE_OBJC_ARC
37#endif
38
39#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
40 //
41#else
4fe56619 42static Standard_Integer getScreenBottom()
43{
44 Cocoa_LocalPool aLocalPool;
45 NSArray* aScreens = [NSScreen screens];
46 if (aScreens == NULL || [aScreens count] == 0)
47 {
48 return 0;
49 }
50
51 NSScreen* aScreen = (NSScreen* )[aScreens objectAtIndex: 0];
52 NSDictionary* aDict = [aScreen deviceDescription];
53 NSNumber* aNumber = [aDict objectForKey: @"NSScreenNumber"];
54 if (aNumber == NULL
55 || [aNumber isKindOfClass: [NSNumber class]] == NO)
56 {
57 return 0;
58 }
59
60 CGDirectDisplayID aDispId = [aNumber unsignedIntValue];
61 CGRect aRect = CGDisplayBounds(aDispId);
62 return Standard_Integer(aRect.origin.y + aRect.size.height);
63}
a2e4f780 64#endif
4fe56619 65
66// =======================================================================
67// function : Cocoa_Window
68// purpose :
69// =======================================================================
70Cocoa_Window::Cocoa_Window (const Standard_CString theTitle,
71 const Standard_Integer thePxLeft,
72 const Standard_Integer thePxTop,
73 const Standard_Integer thePxWidth,
74 const Standard_Integer thePxHeight)
dc3fe572 75: Aspect_Window (),
a2e4f780 76#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
4fe56619 77 myHWindow (NULL),
a2e4f780 78#endif
4fe56619 79 myHView (NULL),
80 myXLeft (thePxLeft),
81 myYTop (thePxTop),
82 myXRight (thePxLeft + thePxWidth),
83 myYBottom (thePxTop + thePxHeight)
84{
a2e4f780 85#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
86 //
87#else
4fe56619 88 if (thePxWidth <= 0 || thePxHeight <= 0)
89 {
90 Aspect_WindowDefinitionError::Raise ("Coordinate(s) out of range");
91 }
92 else if (NSApp == NULL)
93 {
94 Aspect_WindowDefinitionError::Raise ("Cocoa application should be instantiated before window");
95 return;
96 }
97
98 // convert top-bottom coordinates to bottom-top (Cocoa)
99 myYTop = getScreenBottom() - myYBottom;
100 myYBottom = myYTop + thePxHeight;
101
102 Cocoa_LocalPool aLocalPool;
103 NSUInteger aWinStyle = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask;
104 NSRect aRectNs = NSMakeRect (float(myXLeft), float(myYTop), float(thePxWidth), float(thePxHeight));
105 myHWindow = [[NSWindow alloc] initWithContentRect: aRectNs
106 styleMask: aWinStyle
107 backing: NSBackingStoreBuffered
108 defer: NO];
109 if (myHWindow == NULL)
110 {
111 Aspect_WindowDefinitionError::Raise ("Unable to create window");
112 }
113 myHView = [[myHWindow contentView] retain];
114
115 NSString* aTitleNs = [[NSString alloc] initWithUTF8String: theTitle];
116 [myHWindow setTitle: aTitleNs];
117 [aTitleNs release];
118
119 // do not destroy NSWindow on close - we didn't handle it!
120 [myHWindow setReleasedWhenClosed: NO];
a2e4f780 121#endif
4fe56619 122}
123
124// =======================================================================
125// function : Cocoa_Window
126// purpose :
127// =======================================================================
a2e4f780 128#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
129Cocoa_Window::Cocoa_Window (UIView* theViewNS)
130: Aspect_Window(),
131#else
4fe56619 132Cocoa_Window::Cocoa_Window (NSView* theViewNS)
a2e4f780 133: Aspect_Window(),
4fe56619 134 myHWindow (NULL),
a2e4f780 135#endif
136 myHView (NULL),
4fe56619 137 myXLeft (0),
138 myYTop (0),
139 myXRight (512),
140 myYBottom (512)
141{
a2e4f780 142#if defined(HAVE_OBJC_ARC)
143 myHView = theViewNS;
144#else
145 myHView = [theViewNS retain];
146#endif
4fe56619 147 DoResize();
148}
149
150// =======================================================================
151// function : Destroy
152// purpose :
153// =======================================================================
154void Cocoa_Window::Destroy()
155{
a2e4f780 156#if !defined(HAVE_OBJC_ARC)
4fe56619 157 Cocoa_LocalPool aLocalPool;
a2e4f780 158#endif
159#if !(defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
4fe56619 160 if (myHWindow != NULL)
161 {
a2e4f780 162 #if !defined(HAVE_OBJC_ARC)
4fe56619 163 //[myHWindow close];
164 [myHWindow release];
a2e4f780 165 #endif
4fe56619 166 myHWindow = NULL;
167 }
a2e4f780 168#endif
4fe56619 169 if (myHView != NULL)
170 {
a2e4f780 171 #if !defined(HAVE_OBJC_ARC)
4fe56619 172 [myHView release];
a2e4f780 173 #endif
4fe56619 174 myHView = NULL;
175 }
176}
177
4fe56619 178// =======================================================================
179// function : SetHView
180// purpose :
181// =======================================================================
a2e4f780 182#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
183void Cocoa_Window::SetHView (UIView* theView)
184{
185#else
4fe56619 186void Cocoa_Window::SetHView (NSView* theView)
187{
188 if (myHWindow != NULL)
189 {
190 [myHWindow setContentView: theView];
191 }
a2e4f780 192#endif
193
194#if defined(HAVE_OBJC_ARC)
195 myHView = theView;
196#else
4fe56619 197 if (myHView != NULL)
198 {
199 [myHView release];
200 myHView = NULL;
201 }
202 myHView = [theView retain];
a2e4f780 203#endif
4fe56619 204}
205
4fe56619 206// =======================================================================
207// function : IsMapped
208// purpose :
209// =======================================================================
210Standard_Boolean Cocoa_Window::IsMapped() const
211{
212 if (IsVirtual())
213 {
214 return Standard_True;
215 }
216
a2e4f780 217#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
218 return myHView != NULL;
219#else
220 return myHView != NULL
221 && [[myHView window] isVisible];
222#endif
4fe56619 223}
224
225// =======================================================================
226// function : Map
227// purpose :
228// =======================================================================
229void Cocoa_Window::Map() const
230{
231 if (IsVirtual())
232 {
233 return;
234 }
235
236 if (myHView != NULL)
237 {
a2e4f780 238 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
239 //
240 #else
4fe56619 241 [[myHView window] orderFront: NULL];
a2e4f780 242 #endif
4fe56619 243 }
244}
245
246// =======================================================================
247// function : Unmap
248// purpose :
249// =======================================================================
250void Cocoa_Window::Unmap() const
251{
252 if (myHView != NULL)
253 {
a2e4f780 254 #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
255 //
256 #else
4fe56619 257 [[myHView window] orderOut: NULL];
a2e4f780 258 #endif
4fe56619 259 }
260}
261
262// =======================================================================
263// function : DoResize
264// purpose :
265// =======================================================================
266Aspect_TypeOfResize Cocoa_Window::DoResize() const
267{
268 if (myHView == NULL)
269 {
270 return Aspect_TOR_UNKNOWN;
271 }
272
a2e4f780 273#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
274 CGRect aBounds = [myHView bounds];
275#else
4fe56619 276 NSRect aBounds = [myHView bounds];
a2e4f780 277#endif
4fe56619 278 Standard_Integer aMask = 0;
279 Aspect_TypeOfResize aMode = Aspect_TOR_UNKNOWN;
280
281 if (Abs ((Standard_Integer )aBounds.origin.x - myXLeft ) > 2) aMask |= 1;
282 if (Abs ((Standard_Integer )(aBounds.origin.x + aBounds.size.width) - myXRight ) > 2) aMask |= 2;
283 if (Abs ((Standard_Integer )aBounds.origin.y - myYTop ) > 2) aMask |= 4;
284 if (Abs ((Standard_Integer )(aBounds.origin.y + aBounds.size.height) - myYBottom) > 2) aMask |= 8;
285 switch (aMask)
286 {
287 case 0: aMode = Aspect_TOR_NO_BORDER; break;
288 case 1: aMode = Aspect_TOR_LEFT_BORDER; break;
289 case 2: aMode = Aspect_TOR_RIGHT_BORDER; break;
290 case 4: aMode = Aspect_TOR_TOP_BORDER; break;
291 case 5: aMode = Aspect_TOR_LEFT_AND_TOP_BORDER; break;
292 case 6: aMode = Aspect_TOR_TOP_AND_RIGHT_BORDER; break;
293 case 8: aMode = Aspect_TOR_BOTTOM_BORDER; break;
294 case 9: aMode = Aspect_TOR_BOTTOM_AND_LEFT_BORDER; break;
295 case 10: aMode = Aspect_TOR_RIGHT_AND_BOTTOM_BORDER; break;
296 default: break;
297 }
298
299 *((Standard_Integer* )&myXLeft ) = (Standard_Integer )aBounds.origin.x;
300 *((Standard_Integer* )&myXRight ) = (Standard_Integer )(aBounds.origin.x + aBounds.size.width);
301 *((Standard_Integer* )&myYTop ) = (Standard_Integer )aBounds.origin.y;
302 *((Standard_Integer* )&myYBottom ) = (Standard_Integer )(aBounds.origin.y + aBounds.size.height);
303 return aMode;
304}
305
306// =======================================================================
307// function : DoMapping
308// purpose :
309// =======================================================================
310Standard_Boolean Cocoa_Window::DoMapping() const
311{
312 return Standard_True;
313}
314
4fe56619 315// =======================================================================
316// function : Ratio
317// purpose :
318// =======================================================================
319Quantity_Ratio Cocoa_Window::Ratio() const
320{
321 if (myHView == NULL)
322 {
323 return 1.0;
324 }
325
a2e4f780 326#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
327 CGRect aBounds = [myHView bounds];
328#else
4fe56619 329 NSRect aBounds = [myHView bounds];
a2e4f780 330#endif
4fe56619 331 return Quantity_Ratio (aBounds.size.width / aBounds.size.height);
332}
333
4fe56619 334// =======================================================================
335// function : Position
336// purpose :
337// =======================================================================
338void Cocoa_Window::Position (Standard_Integer& X1, Standard_Integer& Y1,
339 Standard_Integer& X2, Standard_Integer& Y2) const
340{
a2e4f780 341#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
342 CGRect aBounds = [myHView bounds];
343 X1 = 0;
344 Y1 = 0;
345 X2 = (Standard_Integer )aBounds.size.width;
346 Y2 = (Standard_Integer )aBounds.size.height;
347#else
18d715bd 348 NSWindow* aWindow = [myHView window];
349 NSRect aWindowRect = [aWindow frame];
350 X1 = (Standard_Integer) aWindowRect.origin.x;
351 Y1 = getScreenBottom() - (Standard_Integer) aWindowRect.origin.y - (Standard_Integer) aWindowRect.size.height;
352 X2 = X1 + (Standard_Integer) aWindowRect.size.width;
353 Y2 = Y1 + (Standard_Integer) aWindowRect.size.height;
a2e4f780 354#endif
4fe56619 355}
356
4fe56619 357// =======================================================================
358// function : Size
359// purpose :
360// =======================================================================
361void Cocoa_Window::Size (Standard_Integer& theWidth,
362 Standard_Integer& theHeight) const
363{
364 if (myHView == NULL)
365 {
366 return;
367 }
368
a2e4f780 369#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
370 CGRect aBounds = [myHView bounds];
371#else
4fe56619 372 NSRect aBounds = [myHView bounds];
a2e4f780 373#endif
4fe56619 374 theWidth = (Standard_Integer )aBounds.size.width;
375 theHeight = (Standard_Integer )aBounds.size.height;
376}