main.mm 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. //This file will contain actual IID structures
  2. #define COM_GUIDS_MATERIALIZE
  3. #include "common.h"
  4. static NSString* s_appTitle = @"Avalonia";
  5. // Copyright (c) 2011 The Chromium Authors. All rights reserved.
  6. // Use of this source code is governed by a BSD-style license that can be
  7. // found in the LICENSE file.
  8. void SetProcessName(NSString* appTitle) {
  9. s_appTitle = appTitle;
  10. CFStringRef process_name = (__bridge CFStringRef)appTitle;
  11. if (!process_name || CFStringGetLength(process_name) == 0) {
  12. //NOTREACHED() << "SetProcessName given bad name.";
  13. return;
  14. }
  15. if (![NSThread isMainThread]) {
  16. //NOTREACHED() << "Should only set process name from main thread.";
  17. return;
  18. }
  19. // Warning: here be dragons! This is SPI reverse-engineered from WebKit's
  20. // plugin host, and could break at any time (although realistically it's only
  21. // likely to break in a new major release).
  22. // When 10.7 is available, check that this still works, and update this
  23. // comment for 10.8.
  24. // Private CFType used in these LaunchServices calls.
  25. typedef CFTypeRef PrivateLSASN;
  26. typedef PrivateLSASN (*LSGetCurrentApplicationASNType)();
  27. typedef OSStatus (*LSSetApplicationInformationItemType)(int, PrivateLSASN,
  28. CFStringRef,
  29. CFStringRef,
  30. CFDictionaryRef*);
  31. static LSGetCurrentApplicationASNType ls_get_current_application_asn_func =
  32. NULL;
  33. static LSSetApplicationInformationItemType
  34. ls_set_application_information_item_func = NULL;
  35. static CFStringRef ls_display_name_key = NULL;
  36. static bool did_symbol_lookup = false;
  37. if (!did_symbol_lookup) {
  38. did_symbol_lookup = true;
  39. CFBundleRef launch_services_bundle =
  40. CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
  41. if (!launch_services_bundle) {
  42. //LOG(ERROR) << "Failed to look up LaunchServices bundle";
  43. return;
  44. }
  45. ls_get_current_application_asn_func =
  46. reinterpret_cast<LSGetCurrentApplicationASNType>(
  47. CFBundleGetFunctionPointerForName(
  48. launch_services_bundle, CFSTR("_LSGetCurrentApplicationASN")));
  49. if (!ls_get_current_application_asn_func){}
  50. //LOG(ERROR) << "Could not find _LSGetCurrentApplicationASN";
  51. ls_set_application_information_item_func =
  52. reinterpret_cast<LSSetApplicationInformationItemType>(
  53. CFBundleGetFunctionPointerForName(
  54. launch_services_bundle,
  55. CFSTR("_LSSetApplicationInformationItem")));
  56. if (!ls_set_application_information_item_func){}
  57. //LOG(ERROR) << "Could not find _LSSetApplicationInformationItem";
  58. CFStringRef* key_pointer = reinterpret_cast<CFStringRef*>(
  59. CFBundleGetDataPointerForName(launch_services_bundle,
  60. CFSTR("_kLSDisplayNameKey")));
  61. ls_display_name_key = key_pointer ? *key_pointer : NULL;
  62. if (!ls_display_name_key){}
  63. //LOG(ERROR) << "Could not find _kLSDisplayNameKey";
  64. // Internally, this call relies on the Mach ports that are started up by the
  65. // Carbon Process Manager. In debug builds this usually happens due to how
  66. // the logging layers are started up; but in release, it isn't started in as
  67. // much of a defined order. So if the symbols had to be loaded, go ahead
  68. // and force a call to make sure the manager has been initialized and hence
  69. // the ports are opened.
  70. ProcessSerialNumber psn;
  71. GetCurrentProcess(&psn);
  72. }
  73. if (!ls_get_current_application_asn_func ||
  74. !ls_set_application_information_item_func ||
  75. !ls_display_name_key) {
  76. return;
  77. }
  78. PrivateLSASN asn = ls_get_current_application_asn_func();
  79. // Constant used by WebKit; what exactly it means is unknown.
  80. const int magic_session_constant = -2;
  81. OSErr err =
  82. ls_set_application_information_item_func(magic_session_constant, asn,
  83. ls_display_name_key,
  84. process_name,
  85. NULL /* optional out param */);
  86. //LOG_IF(ERROR, err) << "Call to set process name failed, err " << err;
  87. }
  88. class MacOptions : public ComSingleObject<IAvnMacOptions, &IID_IAvnMacOptions>
  89. {
  90. public:
  91. FORWARD_IUNKNOWN()
  92. virtual HRESULT SetApplicationTitle(void* utf8String) override
  93. {
  94. auto appTitle = [NSString stringWithUTF8String:(const char*)utf8String];
  95. [[NSProcessInfo processInfo] setProcessName:appTitle];
  96. SetProcessName(appTitle);
  97. return S_OK;
  98. }
  99. virtual HRESULT SetShowInDock(int show) override
  100. {
  101. AvnDesiredActivationPolicy = show
  102. ? NSApplicationActivationPolicyRegular : NSApplicationActivationPolicyAccessory;
  103. return S_OK;
  104. }
  105. };
  106. /// See "Using POSIX Threads in a Cocoa Application" section here:
  107. /// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html#//apple_ref/doc/uid/20000738-125024
  108. @interface ThreadingInitializer : NSObject
  109. - (void) do;
  110. @end
  111. @implementation ThreadingInitializer
  112. {
  113. int _fds[2];
  114. }
  115. - (void) runOnce
  116. {
  117. char buf[]={0};
  118. write(_fds[1], buf, 1);
  119. }
  120. - (void) do
  121. {
  122. pipe(_fds);
  123. [[[NSThread alloc] initWithTarget:self selector:@selector(runOnce) object:nil] start];
  124. char buf[1];
  125. read(_fds[0], buf, 1);
  126. close(_fds[0]);
  127. close(_fds[1]);
  128. }
  129. @end
  130. class AvaloniaNative : public ComSingleObject<IAvaloniaNativeFactory, &IID_IAvaloniaNativeFactory>
  131. {
  132. public:
  133. FORWARD_IUNKNOWN()
  134. virtual HRESULT Initialize() override
  135. {
  136. @autoreleasepool{
  137. [[ThreadingInitializer new] do];
  138. }
  139. InitializeAvnApp();
  140. return S_OK;
  141. };
  142. virtual IAvnMacOptions* GetMacOptions() override
  143. {
  144. return (IAvnMacOptions*)new MacOptions();
  145. }
  146. virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnWindow** ppv) override
  147. {
  148. if(cb == nullptr || ppv == nullptr)
  149. return E_POINTER;
  150. *ppv = CreateAvnWindow(cb, gl);
  151. return S_OK;
  152. };
  153. virtual HRESULT CreatePopup(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnPopup** ppv) override
  154. {
  155. if(cb == nullptr || ppv == nullptr)
  156. return E_POINTER;
  157. *ppv = CreateAvnPopup(cb, gl);
  158. return S_OK;
  159. }
  160. virtual HRESULT CreatePlatformThreadingInterface(IAvnPlatformThreadingInterface** ppv) override
  161. {
  162. *ppv = CreatePlatformThreading();
  163. return S_OK;
  164. }
  165. virtual HRESULT CreateSystemDialogs(IAvnSystemDialogs** ppv) override
  166. {
  167. *ppv = ::CreateSystemDialogs();
  168. return S_OK;
  169. }
  170. virtual HRESULT CreateScreens (IAvnScreens** ppv) override
  171. {
  172. *ppv = ::CreateScreens ();
  173. return S_OK;
  174. }
  175. virtual HRESULT CreateClipboard(IAvnClipboard** ppv) override
  176. {
  177. *ppv = ::CreateClipboard ();
  178. return S_OK;
  179. }
  180. virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) override
  181. {
  182. *ppv = ::CreateCursorFactory();
  183. return S_OK;
  184. }
  185. virtual HRESULT ObtainGlDisplay(IAvnGlDisplay** ppv) override
  186. {
  187. auto rv = ::GetGlDisplay();
  188. if(rv == NULL)
  189. return E_FAIL;
  190. rv->AddRef();
  191. *ppv = rv;
  192. return S_OK;
  193. }
  194. virtual HRESULT CreateMenu (IAvnAppMenu** ppv) override
  195. {
  196. *ppv = ::CreateAppMenu();
  197. return S_OK;
  198. }
  199. virtual HRESULT CreateMenuItem (IAvnAppMenuItem** ppv) override
  200. {
  201. *ppv = ::CreateAppMenuItem();
  202. return S_OK;
  203. }
  204. virtual HRESULT CreateMenuItemSeperator (IAvnAppMenuItem** ppv) override
  205. {
  206. *ppv = ::CreateAppMenuItemSeperator();
  207. return S_OK;
  208. }
  209. virtual HRESULT SetAppMenu (IAvnAppMenu* appMenu) override
  210. {
  211. ::SetAppMenu(s_appTitle, appMenu);
  212. return S_OK;
  213. }
  214. virtual HRESULT ObtainAppMenu(IAvnAppMenu** retOut) override
  215. {
  216. if(retOut == nullptr)
  217. {
  218. return E_POINTER;
  219. }
  220. *retOut = ::GetAppMenu();
  221. return S_OK;
  222. }
  223. };
  224. extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()
  225. {
  226. return new AvaloniaNative();
  227. };
  228. NSSize ToNSSize (AvnSize s)
  229. {
  230. NSSize result;
  231. result.width = s.Width;
  232. result.height = s.Height;
  233. return result;
  234. }
  235. NSPoint ToNSPoint (AvnPoint p)
  236. {
  237. NSPoint result;
  238. result.x = p.X;
  239. result.y = p.Y;
  240. return result;
  241. }
  242. AvnPoint ToAvnPoint (NSPoint p)
  243. {
  244. AvnPoint result;
  245. result.X = p.x;
  246. result.Y = p.y;
  247. return result;
  248. }
  249. AvnPoint ConvertPointY (AvnPoint p)
  250. {
  251. auto sw = [NSScreen.screens objectAtIndex:0].frame;
  252. auto t = MAX(sw.origin.y, sw.origin.y + sw.size.height);
  253. p.Y = t - p.Y;
  254. return p;
  255. }