llwindowmacosx-objc.mm 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /**
  2. * @file llwindowmacosx-objc.mm
  3. * @brief Definition of functions shared between llwindowmacosx.cpp
  4. * and llwindowmacosx-objc.mm.
  5. *
  6. * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. #include <AppKit/AppKit.h>
  28. #include <Cocoa/Cocoa.h>
  29. #include "llopenglview-objc.h"
  30. #include "llwindowmacosx-objc.h"
  31. #include "llappdelegate-objc.h"
  32. // Fix for deprecated convertScreenToBase, should make new function instead.
  33. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  34. /*
  35. * These functions are broken out into a separate file because the
  36. * objective-C typedef for 'BOOL' conflicts with the one in
  37. * llcommon/stdtypes.h. This makes it impossible to use the standard
  38. * linden headers with any objective-C++ source.
  39. */
  40. int createNSApp(int argc, const char* argv[])
  41. {
  42. return NSApplicationMain(argc, argv);
  43. }
  44. void setupCocoa()
  45. {
  46. static bool inited = false;
  47. if(!inited)
  48. {
  49. NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  50. // The following prevents the Cocoa command line parser from trying
  51. // to open 'unknown' arguements as documents. I.e. running:
  52. // './secondlife -set Language fr' would cause a pop-up saying cannot
  53. // open document 'fr' when init'ing the Cocoa App window.
  54. [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
  55. [pool release];
  56. inited = true;
  57. }
  58. }
  59. bool copyToPBoard(const unsigned short* str, unsigned int len)
  60. {
  61. NSAutoreleasePool* pool = [[NSAutoreleasePool alloc]init];
  62. NSPasteboard* pboard = [NSPasteboard generalPasteboard];
  63. [pboard clearContents];
  64. NSArray* contentsToPaste =
  65. [[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil];
  66. [pool release];
  67. return [pboard writeObjects:contentsToPaste];
  68. }
  69. bool pasteBoardAvailable()
  70. {
  71. NSArray* classArray = [NSArray arrayWithObject:[NSString class]];
  72. return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
  73. }
  74. const unsigned short* copyFromPBoard()
  75. {
  76. NSAutoreleasePool* pool = [[NSAutoreleasePool alloc]init];
  77. NSPasteboard* pboard = [NSPasteboard generalPasteboard];
  78. NSArray* classArray = [NSArray arrayWithObject:[NSString class]];
  79. NSString* str = NULL;
  80. BOOL ok =
  81. [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
  82. if (ok)
  83. {
  84. NSArray* objToPaste =
  85. [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]];
  86. str = [objToPaste objectAtIndex:0];
  87. }
  88. unichar* temp = (unichar*)calloc([str length] + 1, sizeof(unichar));
  89. [str getCharacters:temp];
  90. [pool release];
  91. return temp;
  92. }
  93. CursorRef createImageCursor(const char* fullpath, int hotspotX, int hotspotY)
  94. {
  95. NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  96. // extra retain on the NSCursor since we want it to live for the lifetime of the app.
  97. NSCursor* cursor =
  98. [[[NSCursor alloc]
  99. initWithImage:
  100. [[[NSImage alloc] initWithContentsOfFile:
  101. [NSString stringWithUTF8String:fullpath]
  102. ]autorelease]
  103. hotSpot:NSMakePoint(hotspotX, hotspotY)
  104. ]retain];
  105. [pool release];
  106. return (CursorRef)cursor;
  107. }
  108. void setArrowCursor()
  109. {
  110. NSCursor* cursor = [NSCursor arrowCursor];
  111. [NSCursor unhide];
  112. [cursor set];
  113. }
  114. void setIBeamCursor()
  115. {
  116. NSCursor* cursor = [NSCursor IBeamCursor];
  117. [cursor set];
  118. }
  119. void setPointingHandCursor()
  120. {
  121. NSCursor* cursor = [NSCursor pointingHandCursor];
  122. [cursor set];
  123. }
  124. void setCopyCursor()
  125. {
  126. NSCursor* cursor = [NSCursor dragCopyCursor];
  127. [cursor set];
  128. }
  129. void setCrossCursor()
  130. {
  131. NSCursor* cursor = [NSCursor crosshairCursor];
  132. [cursor set];
  133. }
  134. void setNotAllowedCursor()
  135. {
  136. NSCursor* cursor = [NSCursor operationNotAllowedCursor];
  137. [cursor set];
  138. }
  139. void hideNSCursor()
  140. {
  141. [NSCursor hide];
  142. }
  143. void showNSCursor()
  144. {
  145. [NSCursor unhide];
  146. }
  147. bool isCGCursorVisible()
  148. {
  149. return CGCursorIsVisible();
  150. }
  151. void hideNSCursorTillMove(bool hide)
  152. {
  153. [NSCursor setHiddenUntilMouseMoves:hide];
  154. }
  155. // This is currently unused, since we want all our cursors to persist for the
  156. // life of the app, but I've included it for completeness.
  157. OSErr releaseImageCursor(CursorRef ref)
  158. {
  159. if (!ref)
  160. {
  161. return paramErr;
  162. }
  163. NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  164. NSCursor* cursor = (NSCursor*)ref;
  165. [cursor release];
  166. [pool release];
  167. return noErr;
  168. }
  169. OSErr setImageCursor(CursorRef ref)
  170. {
  171. if (!ref)
  172. {
  173. return paramErr;
  174. }
  175. NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  176. NSCursor* cursor = (NSCursor*)ref;
  177. [cursor set];
  178. [pool release];
  179. return noErr;
  180. }
  181. // Now for some unholy juggling between generic pointers and casting them to Obj-C objects!
  182. // Note: things can get a bit hairy from here. This is not for the faint of heart.
  183. NSWindowRef createNSWindow(int x, int y, int width, int height)
  184. {
  185. LLNSWindow* window = [[LLNSWindow alloc]initWithContentRect:NSMakeRect(x, y, width, height)
  186. styleMask:NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTexturedBackgroundWindowMask backing:NSBackingStoreBuffered defer:NO];
  187. [window makeKeyAndOrderFront:nil];
  188. [window setAcceptsMouseMovedEvents:TRUE];
  189. [window setRestorable:FALSE]; // Viewer manages state from own settings
  190. return window;
  191. }
  192. GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync, bool core_gl)
  193. {
  194. LLOpenGLView* glview =
  195. [[LLOpenGLView alloc]initWithFrame:[(LLNSWindow*)window frame] withSamples:samples andVsync:vsync andCoreGL:core_gl];
  196. [(LLNSWindow*)window setContentView:glview];
  197. return glview;
  198. }
  199. void glSwapBuffers(void* context)
  200. {
  201. [(NSOpenGLContext*)context flushBuffer];
  202. }
  203. CGLContextObj getCGLContextObj(GLViewRef view)
  204. {
  205. return [(LLOpenGLView*)view getCGLContextObj];
  206. }
  207. CGLPixelFormatObj* getCGLPixelFormatObj(NSWindowRef window)
  208. {
  209. LLOpenGLView* glview = [(LLNSWindow*)window contentView];
  210. return [glview getCGLPixelFormatObj];
  211. }
  212. unsigned long getVramSize(GLViewRef view)
  213. {
  214. return [(LLOpenGLView*)view getVramSize];
  215. }
  216. float getDeviceUnitSize(GLViewRef view)
  217. {
  218. return [(LLOpenGLView*)view convertSizeToBacking:NSMakeSize(1, 1)].width;
  219. }
  220. CGPoint getContentViewBoundsPosition(NSWindowRef window)
  221. {
  222. return [[(LLNSWindow*)window contentView] bounds].origin;
  223. }
  224. CGSize getContentViewBoundsSize(NSWindowRef window)
  225. {
  226. return [[(LLNSWindow*)window contentView] bounds].size;
  227. }
  228. CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view)
  229. {
  230. return [(NSOpenGLView*)view convertRectToBacking:[[(LLNSWindow*)window contentView] bounds]].size;
  231. }
  232. void getWindowSize(NSWindowRef window, float* size)
  233. {
  234. NSRect frame = [(LLNSWindow*)window frame];
  235. size[0] = frame.origin.x;
  236. size[1] = frame.origin.y;
  237. size[2] = frame.size.width;
  238. size[3] = frame.size.height;
  239. }
  240. void setWindowSize(NSWindowRef window, int width, int height)
  241. {
  242. NSRect frame = [(LLNSWindow*)window frame];
  243. frame.size.width = width;
  244. frame.size.height = height;
  245. [(LLNSWindow*)window setFrame:frame display:TRUE];
  246. }
  247. void setWindowPos(NSWindowRef window, float* pos)
  248. {
  249. NSPoint point;
  250. point.x = pos[0];
  251. point.y = pos[1];
  252. [(LLNSWindow*)window setFrameOrigin:point];
  253. }
  254. void setWinTitle(NSWindowRef window, const std::string& title)
  255. {
  256. NSString* str = [NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]];
  257. [(LLNSWindow*)window setTitle:str];
  258. }
  259. void getCursorPos(NSWindowRef window, float* pos)
  260. {
  261. NSPoint mLoc;
  262. mLoc = [(LLNSWindow*)window mouseLocationOutsideOfEventStream];
  263. pos[0] = mLoc.x;
  264. pos[1] = mLoc.y;
  265. }
  266. void makeWindowOrderFront(NSWindowRef window)
  267. {
  268. [(LLNSWindow*)window makeKeyAndOrderFront:nil];
  269. }
  270. void convertScreenToWindow(NSWindowRef window, float* coord)
  271. {
  272. NSRect point;
  273. point.origin.x = coord[0];
  274. point.origin.y = coord[1];
  275. point = [(LLNSWindow*)window convertRectFromScreen:point];
  276. coord[0] = point.origin.x;
  277. coord[1] = point.origin.y;
  278. }
  279. void convertRectToScreen(NSWindowRef window, float* coord)
  280. {
  281. NSRect point;
  282. point.origin.x = coord[0];
  283. point.origin.y = coord[1];
  284. point.size.width = coord[2];
  285. point.size.height = coord[3];
  286. point = [(LLNSWindow*)window convertRectToScreen:point];
  287. coord[0] = point.origin.x;
  288. coord[1] = point.origin.y;
  289. coord[2] = point.size.width;
  290. coord[3] = point.size.height;
  291. }
  292. void convertRectFromScreen(NSWindowRef window, float* coord)
  293. {
  294. NSRect point;
  295. point.origin.x = coord[0];
  296. point.origin.y = coord[1];
  297. point.size.width = coord[2];
  298. point.size.height = coord[3];
  299. point = [(LLNSWindow*)window convertRectFromScreen:point];
  300. coord[0] = point.origin.x;
  301. coord[1] = point.origin.y;
  302. coord[2] = point.size.width;
  303. coord[3] = point.size.height;
  304. }
  305. void convertScreenToView(NSWindowRef window, float* coord)
  306. {
  307. NSRect point;
  308. point.origin.x = coord[0];
  309. point.origin.y = coord[1];
  310. point.origin = [(LLNSWindow*)window convertScreenToBase:point.origin];
  311. point.origin = [[(LLNSWindow*)window contentView] convertPoint:point.origin fromView:nil];
  312. }
  313. void convertWindowToScreen(NSWindowRef window, float* coord)
  314. {
  315. NSPoint point;
  316. point.x = coord[0];
  317. point.y = coord[1];
  318. point = [(LLNSWindow*)window convertToScreenFromLocalPoint:point relativeToView:[(LLNSWindow*)window contentView]];
  319. coord[0] = point.x;
  320. coord[1] = point.y;
  321. }
  322. void closeWindow(NSWindowRef window)
  323. {
  324. [(LLNSWindow*)window close];
  325. [(LLNSWindow*)window release];
  326. }
  327. void removeGLView(GLViewRef view)
  328. {
  329. [(LLOpenGLView*)view clearGLContext];
  330. [(LLOpenGLView*)view removeFromSuperview];
  331. }
  332. void setupInputWindow(NSWindowRef window, GLViewRef glview)
  333. {
  334. [[(LLAppDelegate*)[NSApp delegate] inputView] setGLView:(LLOpenGLView*)glview];
  335. }
  336. void commitCurrentPreedit(GLViewRef glView)
  337. {
  338. [(LLOpenGLView*)glView commitCurrentPreedit];
  339. }
  340. void allowDirectMarkedTextInput(bool allow, GLViewRef glView)
  341. {
  342. [(LLOpenGLView*)glView allowMarkedTextInput:allow];
  343. }
  344. NSWindowRef getMainAppWindow()
  345. {
  346. LLNSWindow* winRef =
  347. [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] window];
  348. [winRef setAcceptsMouseMovedEvents:TRUE];
  349. return winRef;
  350. }
  351. void makeFirstResponder(NSWindowRef window, GLViewRef view)
  352. {
  353. [(LLNSWindow*)window makeFirstResponder:(LLOpenGLView*)view];
  354. }
  355. void requestUserAttention()
  356. {
  357. [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest];
  358. }
  359. long showAlert(std::string text, std::string title, int type)
  360. {
  361. NSAlert* alert = [[NSAlert alloc] init];
  362. [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]];
  363. [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]];
  364. if (type == 0)
  365. {
  366. [alert addButtonWithTitle:@"Okay"];
  367. }
  368. else if (type == 1)
  369. {
  370. [alert addButtonWithTitle:@"Okay"];
  371. [alert addButtonWithTitle:@"Cancel"];
  372. }
  373. else if (type == 2)
  374. {
  375. [alert addButtonWithTitle:@"Yes"];
  376. [alert addButtonWithTitle:@"No"];
  377. }
  378. long ret = [alert runModal];
  379. [alert dealloc];
  380. if (ret == NSAlertFirstButtonReturn)
  381. {
  382. if (type == 1)
  383. {
  384. ret = 3;
  385. }
  386. else if (type == 2)
  387. {
  388. ret = 0;
  389. }
  390. }
  391. else if (ret == NSAlertSecondButtonReturn)
  392. {
  393. if (type == 0 || type == 1)
  394. {
  395. ret = 2;
  396. }
  397. else if (type == 2)
  398. {
  399. ret = 1;
  400. }
  401. }
  402. return ret;
  403. }
  404. unsigned int getModifiers()
  405. {
  406. return [NSEvent modifierFlags];
  407. }