OpenClonk
C4AppMac.mm
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 
17 // based on SDL implementation
18 
20 #define GL_SILENCE_DEPRECATION
21 #include <epoxy/gl.h>
22 
23 #include "C4Include.h"
24 #include "platform/C4Window.h"
25 #include "graphics/C4Draw.h"
26 
27 #include "platform/C4App.h"
28 #import <Cocoa/Cocoa.h>
29 
30 #ifndef USE_CONSOLE
32 #import "graphics/C4DrawGLMac.h"
33 
34 bool C4AbstractApp::Copy(const std::string &text, bool fClipboard)
35 {
36  NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
37  [pasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
38  NSString* string = [NSString stringWithCString:text.c_str() encoding:NSUTF8StringEncoding];
39  if (![pasteboard setString:string forType:NSStringPboardType])
40  {
41  Log("Writing to Cocoa pasteboard failed");
42  return false;
43  }
44  return true;
45 }
46 
47 std::string C4AbstractApp::Paste(bool fClipboard)
48 {
49  if (fClipboard)
50  {
51  NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
52  const char* chars = [[pasteboard stringForType:NSStringPboardType] cStringUsingEncoding:NSUTF8StringEncoding];
53  return chars;
54  }
55  return std::string();
56 }
57 
58 bool C4AbstractApp::IsClipboardFull(bool fClipboard)
59 {
60  return [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]];
61 }
62 
63 void C4AbstractApp::MessageDialog(const char * message)
64 {
65  NSAlert* alert = [NSAlert alertWithMessageText:@"Fatal Error"
66  defaultButton:nil
67  alternateButton:nil
68  otherButton:nil
69  informativeTextWithFormat:@"%@",
70  [NSString stringWithUTF8String:message]
71  ];
72  [alert runModal];
73 }
74 
76 {
77  [NSApp requestUserAttention:NSCriticalRequest];
78 }
79 
80 #ifdef USE_COCOA
81 
82 C4AbstractApp::C4AbstractApp(): Active(false), fQuitMsgReceived(false), MainThread(pthread_self()), fDspModeSet(false)
83 {
84 }
85 
87 
88 bool C4AbstractApp::Init(int argc, char * argv[])
89 {
90  // Set locale
91  setlocale(LC_ALL,"");
92 
93  // Custom initialization
94  return DoInit (argc, argv);
95 }
96 
97 
98 void C4AbstractApp::Clear() {}
99 
100 void C4AbstractApp::Quit()
101 {
102  [NSApp terminate:[NSApp delegate]];
103 }
104 
106 {
107  // Always fail after quit message
108  if(fQuitMsgReceived)
109  return false;
110 
111  while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE) == kCFRunLoopRunHandledSource);
112  NSEvent* event;
113  while ((event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSEventTrackingRunLoopMode dequeue:YES]) != nil)
114  {
115  [NSApp sendEvent:event];
116  [NSApp updateWindows];
117  }
118  return true;
119 }
120 
121 static int32_t bitDepthFromPixelEncoding(CFStringRef encoding)
122 {
123  // copy-pasta: http://gitorious.org/ogre3d/mainlinemirror/commit/722dbd024aa91a6401850788db76af89c364d6e7
124  if (CFStringCompare(encoding, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
125  return 32;
126  else if(CFStringCompare(encoding, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
127  return 16;
128  else if(CFStringCompare(encoding, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
129  return 8;
130  else
131  return -1; // fail
132 }
133 
134 bool C4AbstractApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor)
135 {
136  // No support for multiple monitors.
137  CFArrayRef array = CGDisplayCopyAllDisplayModes(iMonitor, NULL);
138  bool good_index = iIndex >= 0 && iIndex < (int32_t)CFArrayGetCount(array);
139  if (good_index)
140  {
141  CGDisplayModeRef displayMode = (CGDisplayModeRef)CFArrayGetValueAtIndex(array, iIndex);
142  *piXRes = CGDisplayModeGetWidth(displayMode);
143  *piYRes = CGDisplayModeGetHeight(displayMode);
144  CFStringRef pixelEncoding = CGDisplayModeCopyPixelEncoding(displayMode);
145  *piBitDepth = bitDepthFromPixelEncoding(pixelEncoding);
146  CFRelease(pixelEncoding);
147  }
148  CFRelease(array);
149  return good_index;
150 }
151 
153 {
154 }
155 
156 bool C4AbstractApp::SetVideoMode(int iXRes, int iYRes, unsigned int iRefreshRate, unsigned int iMonitor, bool fFullScreen)
157 {
158  fFullScreen &= !lionAndBeyond(); // Always false for Lion since then Lion's true(tm) Fullscreen is used
159  C4WindowController* controller = pWindow->objectiveCObject<C4WindowController>();
160  NSWindow* window = controller.window;
161 
162  size_t dw = CGDisplayPixelsWide(C4OpenGLView.displayID);
163  size_t dh = CGDisplayPixelsHigh(C4OpenGLView.displayID);
164  if (iXRes == -1)
165  iXRes = dw;
166  if (iYRes == -1)
167  iYRes = dh;
168  ActualFullscreenX = iXRes;
169  ActualFullscreenY = iYRes;
170  [C4OpenGLView setSurfaceBackingSizeOf:[C4OpenGLView mainContext] width:ActualFullscreenX height:ActualFullscreenY];
171  if ((window.styleMask & NSWindowStyleMaskFullScreen) == 0)
172  {
173  [window setResizeIncrements:NSMakeSize(1.0, 1.0)];
174  pWindow->SetSize(iXRes, iYRes);
175  [controller setFullscreen:fFullScreen];
176  [window setAspectRatio:[[window contentView] frame].size];
177  [window center];
178  }
179  else
180  {
181  [window toggleFullScreen:window];
182  pWindow->SetSize(dw, dh);
183  }
184  if (!fFullScreen)
185  [window makeKeyAndOrderFront:nil];
186  OnResolutionChanged(iXRes, iYRes);
187  return true;
188 }
189 
190 #endif // USE_COCOA
191 #endif // USE_CONSOLE
192 
194 {
195  id languages = [[NSUserDefaults standardUserDefaults] valueForKey:@"AppleLanguages"];
196  return languages && [[languages objectAtIndex:0] isEqualToString:@"de"];
197 }
198 
199 bool OpenURL(const char* szURL)
200 {
201  std::string command = std::string("open ") + '"' + szURL + '"';
202  std::system(command.c_str());
203  return true;
204 }
205 
206 bool EraseItemSafe(const char* szFilename)
207 {
208  NSString* filename = [NSString stringWithUTF8String: szFilename];
209  return [[NSWorkspace sharedWorkspace]
210  performFileOperation: NSWorkspaceRecycleOperation
211  source: [filename stringByDeletingLastPathComponent]
212  destination: @""
213  files: [NSArray arrayWithObject: [filename lastPathComponent]]
214  tag: 0];
215 }
216 
217 std::string C4AbstractApp::GetGameDataPath()
218 {
219  return [[[NSBundle mainBundle] resourcePath] fileSystemRepresentation];
220 }
bool EraseItemSafe(const char *szFilename)
Definition: C4AppMac.mm:206
bool IsGermanSystem()
Definition: C4AppMac.mm:193
bool OpenURL(const char *szURL)
Definition: C4AppMac.mm:199
bool Log(const char *szMessage)
Definition: C4Log.cpp:204
bool lionAndBeyond()
void MessageDialog(const char *message)
Definition: C4AppMac.mm:63
bool SetVideoMode(int iXRes, int iYRes, unsigned int iRefreshRate, unsigned int iMonitor, bool fFullScreen)
Definition: C4AppSDL.cpp:354
bool IsClipboardFull(bool fClipboard=true)
Definition: C4AppMac.mm:58
bool fQuitMsgReceived
Definition: C4App.h:81
virtual void Quit()
Definition: C4AppSDL.cpp:110
virtual void OnResolutionChanged(unsigned int iXRes, unsigned int iYRes)=0
bool GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor)
Definition: C4AppSDL.cpp:335
~C4AbstractApp() override
Definition: C4AppT.cpp:40
bool FlushMessages()
Definition: C4AppSDL.cpp:115
void RestoreVideoMode()
Definition: C4AppSDL.cpp:443
bool Copy(const std::string &text, bool fClipboard=true)
Definition: C4AppMac.mm:34
std::string Paste(bool fClipboard=true)
Definition: C4AppMac.mm:47
virtual bool DoInit(int argc, char *argv[])=0
C4Window * pWindow
Definition: C4App.h:80
bool Init(int argc, char *argv[])
Definition: C4AppSDL.cpp:87
virtual void Clear()
Definition: C4AppSDL.cpp:105
void FlashWindow()
Definition: C4AppMac.mm:75
void SetSize(unsigned int cx, unsigned int cy)
Definition: C4AppT.cpp:113