| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #include "platform/mac/specific_mac.h"
- #include "lang/lang_keys.h"
- #include "mainwidget.h"
- #include "history/history_widget.h"
- #include "core/crash_reports.h"
- #include "core/sandbox.h"
- #include "core/application.h"
- #include "core/core_settings.h"
- #include "storage/localstorage.h"
- #include "window/window_controller.h"
- #include "mainwindow.h"
- #include "history/history_location_manager.h"
- #include "base/platform/mac/base_confirm_quit.h"
- #include "base/platform/mac/base_utilities_mac.h"
- #include "base/platform/base_platform_info.h"
- #include <QtGui/QDesktopServices>
- #include <QtWidgets/QApplication>
- #include <cstdlib>
- #include <execinfo.h>
- #include <sys/xattr.h>
- #include <Cocoa/Cocoa.h>
- #include <CoreFoundation/CFURL.h>
- #include <IOKit/IOKitLib.h>
- #include <IOKit/hidsystem/ev_keymap.h>
- #include <mach-o/dyld.h>
- #include <AVFoundation/AVFoundation.h>
- namespace {
- [[nodiscard]] QImage ImageFromNS(NSImage *icon) {
- CGImageRef image = [icon CGImageForProposedRect:NULL context:nil hints:nil];
- const int width = CGImageGetWidth(image);
- const int height = CGImageGetHeight(image);
- auto result = QImage(width, height, QImage::Format_ARGB32_Premultiplied);
- result.fill(Qt::transparent);
- CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
- CGBitmapInfo info = CGBitmapInfo(kCGImageAlphaPremultipliedFirst) | kCGBitmapByteOrder32Host;
- CGContextRef context = CGBitmapContextCreate(
- result.bits(),
- width,
- height,
- 8,
- result.bytesPerLine(),
- space,
- info);
- CGRect rect = CGRectMake(0, 0, width, height);
- CGContextDrawImage(context, rect, image);
- CFRelease(space);
- CFRelease(context);
- return result;
- }
- [[nodiscard]] QImage ResolveBundleIconDefault() {
- NSString *path = [[NSBundle mainBundle] bundlePath];
- NSString *icon = [path stringByAppendingString:@"/Contents/Resources/Icon.icns"];
- NSImage *image = [[NSImage alloc] initWithContentsOfFile:icon];
- if (!image) {
- return Window::Logo();
- }
- auto result = ImageFromNS(image);
- [image release];
- return result;
- }
- } // namespace
- QString psAppDataPath() {
- return objc_appDataPath();
- }
- void psDoCleanup() {
- try {
- Platform::AutostartToggle(false);
- psSendToMenu(false, true);
- } catch (...) {
- }
- }
- int psCleanup() {
- psDoCleanup();
- return 0;
- }
- void psDoFixPrevious() {
- }
- int psFixPrevious() {
- psDoFixPrevious();
- return 0;
- }
- namespace Platform {
- void start() {
- objc_start();
- }
- void finish() {
- objc_finish();
- }
- QString SingleInstanceLocalServerName(const QString &hash) {
- #ifndef OS_MAC_STORE
- return u"/tmp/"_q + hash + '-' + cGUIDStr();
- #else // OS_MAC_STORE
- return objc_documentsPath() + hash.left(4);
- #endif // OS_MAC_STORE
- }
- #if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
- namespace {
- QString strStyleOfInterface() {
- const uint32 letters[] = { 0x3BBB7F05, 0xED4C5EC3, 0xC62C15A3, 0x5D10B283, 0x1BB35729, 0x63FB674D, 0xDBE5C174, 0x401EA195, 0x87B0C82A, 0x311BD596, 0x7063ECFA, 0x4AB90C27, 0xDA587DC4, 0x0B6296F8, 0xAA5603FA, 0xE1140A9F, 0x3D12D094, 0x339B5708, 0x712BA5B1 };
- return Platform::MakeFromLetters(letters);
- }
- bool IsDarkMenuBar() {
- bool result = false;
- @autoreleasepool {
- NSDictionary *dict = [[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain];
- id style = [dict objectForKey:Q2NSString(strStyleOfInterface())];
- BOOL darkModeOn = (style && [style isKindOfClass:[NSString class]] && NSOrderedSame == [style caseInsensitiveCompare:@"dark"]);
- result = darkModeOn ? true : false;
- }
- return result;
- }
- } // namespace
- std::optional<bool> IsDarkMode() {
- return IsMac10_14OrGreater()
- ? std::make_optional(IsDarkMenuBar())
- : std::nullopt;
- }
- #endif // Qt < 6.5.0
- void WriteCrashDumpDetails() {
- #ifndef TDESKTOP_DISABLE_CRASH_REPORTS
- double v = objc_appkitVersion();
- CrashReports::dump() << "OS-Version: " << v;
- #endif // TDESKTOP_DISABLE_CRASH_REPORTS
- }
- // I do check for availability, just not in the exact way clang is content with
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wunguarded-availability"
- PermissionStatus GetPermissionStatus(PermissionType type) {
- switch (type) {
- case PermissionType::Microphone:
- case PermissionType::Camera:
- const auto nativeType = (type == PermissionType::Microphone)
- ? AVMediaTypeAudio
- : AVMediaTypeVideo;
- if ([AVCaptureDevice respondsToSelector: @selector(authorizationStatusForMediaType:)]) { // Available starting with 10.14
- switch ([AVCaptureDevice authorizationStatusForMediaType:nativeType]) {
- case AVAuthorizationStatusNotDetermined:
- return PermissionStatus::CanRequest;
- case AVAuthorizationStatusAuthorized:
- return PermissionStatus::Granted;
- case AVAuthorizationStatusDenied:
- case AVAuthorizationStatusRestricted:
- return PermissionStatus::Denied;
- }
- }
- break;
- }
- return PermissionStatus::Granted;
- }
- void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback) {
- switch (type) {
- case PermissionType::Microphone:
- case PermissionType::Camera:
- const auto nativeType = (type == PermissionType::Microphone)
- ? AVMediaTypeAudio
- : AVMediaTypeVideo;
- if ([AVCaptureDevice respondsToSelector: @selector(requestAccessForMediaType:completionHandler:)]) { // Available starting with 10.14
- [AVCaptureDevice requestAccessForMediaType:nativeType completionHandler:^(BOOL granted) {
- crl::on_main([=] {
- resultCallback(granted ? PermissionStatus::Granted : PermissionStatus::Denied);
- });
- }];
- }
- break;
- }
- resultCallback(PermissionStatus::Granted);
- }
- #pragma clang diagnostic pop // -Wunguarded-availability
- void OpenSystemSettingsForPermission(PermissionType type) {
- switch (type) {
- case PermissionType::Microphone:
- [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone"]];
- break;
- case PermissionType::Camera:
- [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Camera"]];
- break;
- }
- }
- bool OpenSystemSettings(SystemSettingsType type) {
- switch (type) {
- case SystemSettingsType::Audio:
- [[NSWorkspace sharedWorkspace] openFile:@"/System/Library/PreferencePanes/Sound.prefPane"];
- break;
- }
- return true;
- }
- void IgnoreApplicationActivationRightNow() {
- objc_ignoreApplicationActivationRightNow();
- }
- void AutostartToggle(bool enabled, Fn<void(bool)> done) {
- if (done) {
- done(false);
- }
- }
- bool AutostartSkip() {
- return !cAutoStart();
- }
- void NewVersionLaunched(int oldVersion) {
- }
- QImage DefaultApplicationIcon() {
- static auto result = ResolveBundleIconDefault();
- return result;
- }
- bool PreventsQuit(Core::QuitReason reason) {
- // Thanks Chromium, see
- // chromium.org/developers/design-documents/confirm-to-quit-experiment
- return (reason == Core::QuitReason::QtQuitEvent)
- && Core::App().settings().macWarnBeforeQuit()
- && ([[NSApp currentEvent] type] == NSEventTypeKeyDown)
- && !ConfirmQuit::RunModal(
- tr::lng_mac_hold_to_quit(
- tr::now,
- lt_text,
- ConfirmQuit::QuitKeysString()));
- }
- void ActivateThisProcess() {
- const auto window = Core::App().activeWindow();
- objc_activateProgram(window ? window->widget()->winId() : 0);
- }
- } // namespace Platform
- void psSendToMenu(bool send, bool silent) {
- }
- void psDownloadPathEnableAccess() {
- objc_downloadPathEnableAccess(Core::App().settings().downloadPathBookmark());
- }
- QByteArray psDownloadPathBookmark(const QString &path) {
- return objc_downloadPathBookmark(path);
- }
- bool psLaunchMaps(const Data::LocationPoint &point) {
- return QDesktopServices::openUrl(u"https://maps.apple.com/?q=Point&z=16&ll=%1,%2"_q.arg(point.latAsString()).arg(point.lonAsString()));
- }
|