MacUI.mm 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Copyright 2019 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "MacUpdater/ViewController.h"
  4. #include "UpdaterCommon/Platform.h"
  5. #include "UpdaterCommon/UI.h"
  6. #include "UpdaterCommon/UpdaterCommon.h"
  7. #include <Cocoa/Cocoa.h>
  8. #include <unistd.h>
  9. #include <functional>
  10. // When we call from the main thread, we are not allowed to use
  11. // dispatch_sync(dispatch_get_main_queue() as it will cause crashes) To prevent this check if we're
  12. // already on the main thread first
  13. void run_on_main(std::function<void()> fnc)
  14. {
  15. if (![NSThread isMainThread])
  16. {
  17. dispatch_sync(dispatch_get_main_queue(), ^{
  18. fnc();
  19. });
  20. }
  21. else
  22. {
  23. fnc();
  24. }
  25. }
  26. NSWindow* GetWindow()
  27. {
  28. return [[[NSApplication sharedApplication] windows] objectAtIndex:0];
  29. }
  30. ViewController* GetView()
  31. {
  32. return (ViewController*)GetWindow().contentViewController;
  33. }
  34. void UI::Error(const std::string& text)
  35. {
  36. run_on_main([&] {
  37. NSAlert* alert = [[[NSAlert alloc] init] autorelease];
  38. [alert setMessageText:@"Fatal error"];
  39. [alert setInformativeText:[NSString stringWithCString:text.c_str()
  40. encoding:NSUTF8StringEncoding]];
  41. [alert setAlertStyle:NSAlertStyleCritical];
  42. [alert beginSheetModalForWindow:GetWindow()
  43. completionHandler:^(NSModalResponse) {
  44. [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
  45. }];
  46. });
  47. }
  48. void UI::SetVisible(bool visible)
  49. {
  50. run_on_main([&] {
  51. if (visible)
  52. {
  53. [NSApp unhide:nil];
  54. [NSApp activateIgnoringOtherApps:YES];
  55. }
  56. else
  57. {
  58. [NSApp hide:nil];
  59. }
  60. });
  61. }
  62. void UI::SetDescription(const std::string& text)
  63. {
  64. run_on_main([&] {
  65. [GetView() SetDescription:[NSString stringWithCString:text.c_str()
  66. encoding:NSUTF8StringEncoding]];
  67. });
  68. }
  69. void UI::SetTotalMarquee(bool marquee)
  70. {
  71. run_on_main([marquee] { [GetView() SetTotalMarquee:marquee]; });
  72. }
  73. void UI::SetCurrentMarquee(bool marquee)
  74. {
  75. run_on_main([&] { [GetView() SetCurrentMarquee:marquee]; });
  76. }
  77. void UI::ResetTotalProgress()
  78. {
  79. run_on_main([] { SetTotalProgress(0, 1); });
  80. }
  81. void UI::ResetCurrentProgress()
  82. {
  83. run_on_main([] { SetCurrentProgress(0, 1); });
  84. }
  85. void UI::SetCurrentProgress(int current, int total)
  86. {
  87. run_on_main([&] { [GetView() SetCurrentProgress:(double)current total:(double)total]; });
  88. }
  89. void UI::SetTotalProgress(int current, int total)
  90. {
  91. run_on_main([&] { [GetView() SetTotalProgress:(double)current total:(double)total]; });
  92. }
  93. void UI::Sleep(int seconds)
  94. {
  95. [NSThread sleepForTimeInterval:static_cast<float>(seconds)];
  96. }
  97. void UI::WaitForPID(u32 pid)
  98. {
  99. for (int res = kill(pid, 0); res == 0 || (res < 0 && errno == EPERM); res = kill(pid, 0))
  100. {
  101. UI::Sleep(1);
  102. }
  103. }
  104. void UI::LaunchApplication(std::string path)
  105. {
  106. [[NSWorkspace sharedWorkspace]
  107. launchApplication:[NSString stringWithCString:path.c_str()
  108. encoding:[NSString defaultCStringEncoding]]];
  109. }
  110. void UI::Stop()
  111. {
  112. run_on_main([] { [NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0]; });
  113. }
  114. // Stub. Only needed on Windows
  115. void UI::Init()
  116. {
  117. }
  118. // test-updater.py only works on Windows.
  119. bool UI::IsTestMode()
  120. {
  121. return false;
  122. }
  123. bool Platform::VersionCheck(const std::vector<TodoList::UpdateOp>& to_update,
  124. const std::string& install_base_path, const std::string& temp_dir)
  125. {
  126. const auto op_it = std::find_if(to_update.cbegin(), to_update.cend(), [&](const auto& op) {
  127. return op.filename == "Dolphin.app/Contents/Info.plist";
  128. });
  129. if (op_it == to_update.cend())
  130. return true;
  131. const auto op = *op_it;
  132. std::string plist_path = temp_dir + "/" + HexEncode(op.new_hash.data(), op.new_hash.size());
  133. NSData* data = [NSData dataWithContentsOfFile:[NSString stringWithCString:plist_path.c_str()]];
  134. if (!data)
  135. {
  136. LogToFile("Failed to read %s, skipping platform version check.\n", plist_path.c_str());
  137. return true;
  138. }
  139. NSError* error = nil;
  140. NSDictionary* info_dict =
  141. [NSPropertyListSerialization propertyListWithData:data
  142. options:NSPropertyListImmutable
  143. format:nil
  144. error:&error];
  145. if (error)
  146. {
  147. LogToFile("Failed to parse %s, skipping platform version check.\n", plist_path.c_str());
  148. return true;
  149. }
  150. NSString* min_version_str = info_dict[@"LSMinimumSystemVersion"];
  151. if (!min_version_str)
  152. {
  153. LogToFile("LSMinimumSystemVersion key missing, skipping platform version check.\n");
  154. return true;
  155. }
  156. NSArray* components = [min_version_str componentsSeparatedByString:@"."];
  157. NSOperatingSystemVersion next_version{
  158. [components[0] integerValue], [components[1] integerValue], [components[2] integerValue]};
  159. LogToFile("Platform version check: next_version=%ld.%ld.%ld\n", (long)next_version.majorVersion,
  160. (long)next_version.minorVersion, (long)next_version.patchVersion);
  161. if (![[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:next_version])
  162. {
  163. UI::Error("Please update macOS in order to update Dolphin.");
  164. return false;
  165. }
  166. return true;
  167. }