Remove use of some deprecated code and cleanup other macOS code
This commit is contained in:
@@ -33,7 +33,6 @@ before_install:
|
|||||||
export PATH="/usr/local/opt/gettext/bin:$PATH";
|
export PATH="/usr/local/opt/gettext/bin:$PATH";
|
||||||
export PKG_CONFIG_PATH=/usr/local/opt/libffi/lib/pkgconfig/:$PKG_CONFIG_PATH;
|
export PKG_CONFIG_PATH=/usr/local/opt/libffi/lib/pkgconfig/:$PKG_CONFIG_PATH;
|
||||||
ls /usr/local/lib/gstreamer-1.0;
|
ls /usr/local/lib/gstreamer-1.0;
|
||||||
ls /usr/local/lib/gio/modules;
|
|
||||||
fi
|
fi
|
||||||
before_script:
|
before_script:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild ; fi
|
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild ; fi
|
||||||
|
|||||||
@@ -837,6 +837,7 @@ endif()
|
|||||||
# Platform specific - macOS
|
# Platform specific - macOS
|
||||||
optional_source(APPLE
|
optional_source(APPLE
|
||||||
SOURCES
|
SOURCES
|
||||||
|
core/mac_utilities.mm
|
||||||
core/mac_startup.mm
|
core/mac_startup.mm
|
||||||
core/macsystemtrayicon.mm
|
core/macsystemtrayicon.mm
|
||||||
core/macscreensaver.cpp
|
core/macscreensaver.cpp
|
||||||
|
|||||||
@@ -68,19 +68,23 @@
|
|||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
QDebug operator<<(QDebug dbg, NSObject* object) {
|
QDebug operator<<(QDebug dbg, NSObject* object) {
|
||||||
QString ns_format = [[NSString stringWithFormat:@"%@", object] UTF8String];
|
|
||||||
|
QString ns_format = [ [NSString stringWithFormat:@"%@", object] UTF8String];
|
||||||
dbg.nospace() << ns_format;
|
dbg.nospace() << ns_format;
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Capture global media keys on Mac (Cocoa only!)
|
// Capture global media keys on Mac (Cocoa only!)
|
||||||
// See: http://www.rogueamoeba.com/utm/2007/09/29/apple-keyboard-media-key-event-handling/
|
// See: http://www.rogueamoeba.com/utm/2007/09/29/apple-keyboard-media-key-event-handling/
|
||||||
|
|
||||||
@interface MacApplication : NSApplication {
|
@interface MacApplication : NSApplication {
|
||||||
|
|
||||||
PlatformInterface* application_handler_;
|
PlatformInterface* application_handler_;
|
||||||
AppDelegate* delegate_;
|
AppDelegate* delegate_;
|
||||||
// shortcut_handler_ only used to temporarily save it AppDelegate does all the heavy-shortcut-lifting
|
// shortcut_handler_ only used to temporarily save it AppDelegate does all the heavy-shortcut-lifting
|
||||||
GlobalShortcutBackendMacOS* shortcut_handler_;
|
GlobalShortcutBackendMacOS* shortcut_handler_;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (GlobalShortcutBackendMacOS*)shortcut_handler;
|
- (GlobalShortcutBackendMacOS*)shortcut_handler;
|
||||||
@@ -91,52 +95,36 @@ QDebug operator<<(QDebug dbg, NSObject* object) {
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#ifdef HAVE_BREAKPAD
|
|
||||||
static bool BreakpadCallback(int, int, mach_port_t, void*) { return true; }
|
|
||||||
|
|
||||||
static BreakpadRef InitBreakpad() {
|
|
||||||
ScopedNSAutoreleasePool pool;
|
|
||||||
BreakpadRef breakpad = nil;
|
|
||||||
NSDictionary* plist = [[NSBundle mainBundle] infoDictionary];
|
|
||||||
if (plist) {
|
|
||||||
breakpad = BreakpadCreate(plist);
|
|
||||||
BreakpadSetFilterCallback(breakpad, &BreakpadCallback, nullptr);
|
|
||||||
}
|
|
||||||
[pool release];
|
|
||||||
return breakpad;
|
|
||||||
}
|
|
||||||
#endif // HAVE_BREAKPAD
|
|
||||||
|
|
||||||
@implementation AppDelegate
|
@implementation AppDelegate
|
||||||
|
|
||||||
- (id)init {
|
- (id)init {
|
||||||
|
|
||||||
if ((self = [super init])) {
|
if ((self = [super init])) {
|
||||||
application_handler_ = nil;
|
application_handler_ = nil;
|
||||||
shortcut_handler_ = nil;
|
shortcut_handler_ = nil;
|
||||||
dock_menu_ = nil;
|
dock_menu_ = nil;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithHandler:(PlatformInterface*)handler {
|
- (id)initWithHandler:(PlatformInterface*)handler {
|
||||||
|
|
||||||
application_handler_ = handler;
|
application_handler_ = handler;
|
||||||
|
|
||||||
#ifdef HAVE_BREAKPAD
|
|
||||||
breakpad_ = InitBreakpad();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Register defaults for the whitelist of apps that want to use media keys
|
// Register defaults for the whitelist of apps that want to use media keys
|
||||||
[[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
|
[ [NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:[SPMediaKeyTap defaultMediaKeyUserBundleIdentifiers], kMediaKeyUsingBundleIdentifiersDefaultsKey, nil] ];
|
||||||
[SPMediaKeyTap defaultMediaKeyUserBundleIdentifiers], kMediaKeyUsingBundleIdentifiersDefaultsKey,
|
|
||||||
nil]];
|
|
||||||
return self;
|
return self;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) applicationShouldHandleReopen: (NSApplication*)app hasVisibleWindows:(BOOL)flag {
|
- (BOOL) applicationShouldHandleReopen: (NSApplication*)app hasVisibleWindows:(BOOL)flag {
|
||||||
|
|
||||||
if (application_handler_) {
|
if (application_handler_) {
|
||||||
application_handler_->Activate();
|
application_handler_->Activate();
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDockMenu:(NSMenu*)menu {
|
- (void)setDockMenu:(NSMenu*)menu {
|
||||||
@@ -156,21 +144,19 @@ static BreakpadRef InitBreakpad() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
|
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
|
||||||
key_tap_ = [[SPMediaKeyTap alloc] initWithDelegate:self];
|
|
||||||
if ([SPMediaKeyTap usesGlobalMediaKeyTap] &&
|
key_tap_ = [ [SPMediaKeyTap alloc] initWithDelegate:self];
|
||||||
![[NSProcessInfo processInfo]
|
if ([SPMediaKeyTap usesGlobalMediaKeyTap] && ![ [NSProcessInfo processInfo]isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 10, .minorVersion = 12, .patchVersion = 0}]) {
|
||||||
isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){
|
|
||||||
.majorVersion = 10,
|
|
||||||
.minorVersion = 12,
|
|
||||||
.patchVersion = 0}]) {
|
|
||||||
[key_tap_ startWatchingMediaKeys];
|
[key_tap_ startWatchingMediaKeys];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qLog(Warning) << "Media key monitoring disabled";
|
qLog(Warning) << "Media key monitoring disabled";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)application:(NSApplication*)app openFile:(NSString*)filename {
|
- (BOOL)application:(NSApplication*)app openFile:(NSString*)filename {
|
||||||
|
|
||||||
qLog(Debug) << "Wants to open:" << [filename UTF8String];
|
qLog(Debug) << "Wants to open:" << [filename UTF8String];
|
||||||
|
|
||||||
if (application_handler_->LoadUrl(QString::fromUtf8([filename UTF8String]))) {
|
if (application_handler_->LoadUrl(QString::fromUtf8([filename UTF8String]))) {
|
||||||
@@ -178,16 +164,20 @@ static BreakpadRef InitBreakpad() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)application:(NSApplication*)app openFiles:(NSArray*)filenames {
|
- (void)application:(NSApplication*)app openFiles:(NSArray*)filenames {
|
||||||
|
|
||||||
qLog(Debug) << "Wants to open:" << filenames;
|
qLog(Debug) << "Wants to open:" << filenames;
|
||||||
[filenames enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL* stop) {
|
[filenames enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL* stop) {
|
||||||
[self application:app openFile:(NSString*)object];
|
[self application:app openFile:(NSString*)object];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) mediaKeyTap: (SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event {
|
- (void) mediaKeyTap: (SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event {
|
||||||
|
|
||||||
NSAssert([event type] == NSSystemDefined && [event subtype] == SPSystemDefinedEventMediaKeys, @"Unexpected NSEvent in mediaKeyTap:receivedMediaKeyEvent:");
|
NSAssert([event type] == NSSystemDefined && [event subtype] == SPSystemDefinedEventMediaKeys, @"Unexpected NSEvent in mediaKeyTap:receivedMediaKeyEvent:");
|
||||||
|
|
||||||
int key_code = (([event data1] & 0xFFFF0000) >> 16);
|
int key_code = (([event data1] & 0xFFFF0000) >> 16);
|
||||||
@@ -202,12 +192,10 @@ static BreakpadRef InitBreakpad() {
|
|||||||
if (key_is_released) {
|
if (key_is_released) {
|
||||||
shortcut_handler_->MacMediaKeyPressed(key_code);
|
shortcut_handler_->MacMediaKeyPressed(key_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication*) sender {
|
- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication*) sender {
|
||||||
#ifdef HAVE_BREAKPAD
|
|
||||||
BreakpadRelease(breakpad_);
|
|
||||||
#endif
|
|
||||||
return NSTerminateNow;
|
return NSTerminateNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,17 +230,19 @@ static BreakpadRef InitBreakpad() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)SetApplicationHandler:(PlatformInterface*)handler {
|
- (void)SetApplicationHandler:(PlatformInterface*)handler {
|
||||||
delegate_ = [[AppDelegate alloc] initWithHandler:handler];
|
|
||||||
|
delegate_ = [ [AppDelegate alloc] initWithHandler:handler];
|
||||||
// App-shortcut-handler set before delegate is set.
|
// App-shortcut-handler set before delegate is set.
|
||||||
// this makes sure the delegate's shortcut_handler is set
|
// this makes sure the delegate's shortcut_handler is set
|
||||||
[delegate_ setShortcutHandler:shortcut_handler_];
|
[delegate_ setShortcutHandler:shortcut_handler_];
|
||||||
[self setDelegate:delegate_];
|
[self setDelegate:delegate_];
|
||||||
|
|
||||||
[[NSUserNotificationCenter defaultUserNotificationCenter]
|
[ [NSUserNotificationCenter defaultUserNotificationCenter]setDelegate:delegate_];
|
||||||
setDelegate:delegate_];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)sendEvent:(NSEvent*)event {
|
- (void)sendEvent:(NSEvent*)event {
|
||||||
|
|
||||||
// If event tap is not installed, handle events that reach the app instead
|
// If event tap is not installed, handle events that reach the app instead
|
||||||
BOOL shouldHandleMediaKeyEventLocally = ![SPMediaKeyTap usesGlobalMediaKeyTap];
|
BOOL shouldHandleMediaKeyEventLocally = ![SPMediaKeyTap usesGlobalMediaKeyTap];
|
||||||
|
|
||||||
@@ -261,6 +251,7 @@ static BreakpadRef InitBreakpad() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[super sendEvent:event];
|
[super sendEvent:event];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -268,13 +259,15 @@ static BreakpadRef InitBreakpad() {
|
|||||||
namespace mac {
|
namespace mac {
|
||||||
|
|
||||||
void MacMain() {
|
void MacMain() {
|
||||||
|
|
||||||
ScopedNSAutoreleasePool pool;
|
ScopedNSAutoreleasePool pool;
|
||||||
// Creates and sets the magic global variable so QApplication will find it.
|
// Creates and sets the magic global variable so QApplication will find it.
|
||||||
[MacApplication sharedApplication];
|
[MacApplication sharedApplication];
|
||||||
#ifdef HAVE_SPARKLE
|
#ifdef HAVE_SPARKLE
|
||||||
// Creates and sets the magic global variable for Sparkle.
|
// Creates and sets the magic global variable for Sparkle.
|
||||||
[[SUUpdater sharedUpdater] setDelegate:NSApp];
|
[ [SUUpdater sharedUpdater] setDelegate:NSApp];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetShortcutHandler(GlobalShortcutBackendMacOS* handler) {
|
void SetShortcutHandler(GlobalShortcutBackendMacOS* handler) {
|
||||||
@@ -287,52 +280,61 @@ void SetApplicationHandler(PlatformInterface* handler) {
|
|||||||
|
|
||||||
void CheckForUpdates() {
|
void CheckForUpdates() {
|
||||||
#ifdef HAVE_SPARKLE
|
#ifdef HAVE_SPARKLE
|
||||||
[[SUUpdater sharedUpdater] checkForUpdates:NSApp];
|
[ [SUUpdater sharedUpdater] checkForUpdates:NSApp];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GetBundlePath() {
|
QString GetBundlePath() {
|
||||||
|
|
||||||
ScopedCFTypeRef<CFURLRef> app_url(CFBundleCopyBundleURL(CFBundleGetMainBundle()));
|
ScopedCFTypeRef<CFURLRef> app_url(CFBundleCopyBundleURL(CFBundleGetMainBundle()));
|
||||||
ScopedCFTypeRef<CFStringRef> mac_path(CFURLCopyFileSystemPath(app_url.get(), kCFURLPOSIXPathStyle));
|
ScopedCFTypeRef<CFStringRef> mac_path(CFURLCopyFileSystemPath(app_url.get(), kCFURLPOSIXPathStyle));
|
||||||
const char* path = CFStringGetCStringPtr(mac_path.get(), CFStringGetSystemEncoding());
|
const char* path = CFStringGetCStringPtr(mac_path.get(), CFStringGetSystemEncoding());
|
||||||
QString bundle_path = QString::fromUtf8(path);
|
QString bundle_path = QString::fromUtf8(path);
|
||||||
return bundle_path;
|
return bundle_path;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GetResourcesPath() {
|
QString GetResourcesPath() {
|
||||||
|
|
||||||
QString bundle_path = GetBundlePath();
|
QString bundle_path = GetBundlePath();
|
||||||
return bundle_path + "/Contents/Resources";
|
return bundle_path + "/Contents/Resources";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GetApplicationSupportPath() {
|
QString GetApplicationSupportPath() {
|
||||||
|
|
||||||
ScopedNSAutoreleasePool pool;
|
ScopedNSAutoreleasePool pool;
|
||||||
NSArray* paths = NSSearchPathForDirectoriesInDomains(
|
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||||
NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
|
||||||
QString ret;
|
QString ret;
|
||||||
if ([paths count] > 0) {
|
if ([paths count] > 0) {
|
||||||
NSString* user_path = [paths objectAtIndex:0];
|
NSString* user_path = [paths objectAtIndex:0];
|
||||||
ret = QString::fromUtf8([user_path UTF8String]);
|
ret = QString::fromUtf8([user_path UTF8String]);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
ret = "~/Library/Application Support";
|
ret = "~/Library/Application Support";
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GetMusicDirectory() {
|
QString GetMusicDirectory() {
|
||||||
|
|
||||||
ScopedNSAutoreleasePool pool;
|
ScopedNSAutoreleasePool pool;
|
||||||
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSMusicDirectory,
|
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSMusicDirectory, NSUserDomainMask, YES);
|
||||||
NSUserDomainMask, YES);
|
|
||||||
QString ret;
|
QString ret;
|
||||||
if ([paths count] > 0) {
|
if ([paths count] > 0) {
|
||||||
NSString* user_path = [paths objectAtIndex:0];
|
NSString* user_path = [paths objectAtIndex:0];
|
||||||
ret = QString::fromUtf8([user_path UTF8String]);
|
ret = QString::fromUtf8([user_path UTF8String]);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
ret = "~/Music";
|
ret = "~/Music";
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int MapFunctionKey(int keycode) {
|
static int MapFunctionKey(int keycode) {
|
||||||
|
|
||||||
switch (keycode) {
|
switch (keycode) {
|
||||||
// Function keys
|
// Function keys
|
||||||
case NSInsertFunctionKey: return Qt::Key_Insert;
|
case NSInsertFunctionKey: return Qt::Key_Insert;
|
||||||
@@ -392,6 +394,7 @@ static int MapFunctionKey(int keycode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QKeySequence KeySequenceFromNSEvent(NSEvent* event) {
|
QKeySequence KeySequenceFromNSEvent(NSEvent* event) {
|
||||||
|
|
||||||
NSString* str = [event charactersIgnoringModifiers];
|
NSString* str = [event charactersIgnoringModifiers];
|
||||||
NSString* upper = [str uppercaseString];
|
NSString* upper = [str uppercaseString];
|
||||||
const char* chars = [upper UTF8String];
|
const char* chars = [upper UTF8String];
|
||||||
@@ -409,7 +412,8 @@ QKeySequence KeySequenceFromNSEvent(NSEvent* event) {
|
|||||||
if (key == 0) {
|
if (key == 0) {
|
||||||
if (c >= 0x20 && c <= 0x7e) { // ASCII from space to ~
|
if (c >= 0x20 && c <= 0x7e) { // ASCII from space to ~
|
||||||
key = c;
|
key = c;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
key = MapFunctionKey([event keyCode]);
|
key = MapFunctionKey([event keyCode]);
|
||||||
if (key == 0) {
|
if (key == 0) {
|
||||||
return QKeySequence();
|
return QKeySequence();
|
||||||
@@ -431,11 +435,14 @@ QKeySequence KeySequenceFromNSEvent(NSEvent* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return QKeySequence(key);
|
return QKeySequence(key);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpDictionary(CFDictionaryRef dict) {
|
void DumpDictionary(CFDictionaryRef dict) {
|
||||||
|
|
||||||
NSDictionary* d = (NSDictionary*)dict;
|
NSDictionary* d = (NSDictionary*)dict;
|
||||||
NSLog(@"%@", d);
|
NSLog(@"%@", d);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NSWindowCollectionBehaviorFullScreenPrimary
|
// NSWindowCollectionBehaviorFullScreenPrimary
|
||||||
@@ -446,11 +453,14 @@ void EnableFullScreen(const QWidget& main_window) {
|
|||||||
NSView* view = reinterpret_cast<NSView*>(main_window.winId());
|
NSView* view = reinterpret_cast<NSView*>(main_window.winId());
|
||||||
NSWindow* window = [view window];
|
NSWindow* window = [view window];
|
||||||
[window setCollectionBehavior:kFullScreenPrimary];
|
[window setCollectionBehavior:kFullScreenPrimary];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float GetDevicePixelRatio(QWidget* widget) {
|
float GetDevicePixelRatio(QWidget* widget) {
|
||||||
|
|
||||||
NSView* view = reinterpret_cast<NSView*>(widget->winId());
|
NSView* view = reinterpret_cast<NSView*>(widget->winId());
|
||||||
return [[view window] backingScaleFactor];
|
return [ [view window] backingScaleFactor];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mac
|
} // namespace mac
|
||||||
|
|||||||
@@ -37,3 +37,7 @@ QKeySequence KeySequenceFromNSEvent(NSEvent* event);
|
|||||||
void DumpDictionary(CFDictionaryRef dict);
|
void DumpDictionary(CFDictionaryRef dict);
|
||||||
float GetDevicePixelRatio(QWidget *widget);
|
float GetDevicePixelRatio(QWidget *widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Utilities {
|
||||||
|
qint32 GetMacOsVersion();
|
||||||
|
}
|
||||||
|
|||||||
36
src/core/mac_utilities.mm
Normal file
36
src/core/mac_utilities.mm
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Strawberry Music Player
|
||||||
|
* Copyright 2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
|
*
|
||||||
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Strawberry is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <Foundation/NSProcessInfo.h>
|
||||||
|
|
||||||
|
namespace Utilities {
|
||||||
|
|
||||||
|
qint32 GetMacOsVersion() {
|
||||||
|
|
||||||
|
NSOperatingSystemVersion version = [ [NSProcessInfo processInfo] operatingSystemVersion];
|
||||||
|
return version.minorVersion;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Utilities
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
#include "core/utilities.h"
|
#include "core/utilities.h"
|
||||||
|
#include "core/mac_utilities.h"
|
||||||
|
|
||||||
// kIOPMAssertionTypePreventUserIdleDisplaySleep from Lion.
|
// kIOPMAssertionTypePreventUserIdleDisplaySleep from Lion.
|
||||||
#define kLionDisplayAssertion CFSTR("PreventUserIdleDisplaySleep")
|
#define kLionDisplayAssertion CFSTR("PreventUserIdleDisplaySleep")
|
||||||
|
|||||||
@@ -329,14 +329,6 @@ QString ColorToRgba(const QColor &c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
qint32 GetMacOsVersion() {
|
|
||||||
|
|
||||||
SInt32 minor_version;
|
|
||||||
Gestalt(gestaltSystemVersionMinor, &minor_version);
|
|
||||||
return minor_version;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Better than openUrl(dirname(path)) - also highlights file at path
|
// Better than openUrl(dirname(path)) - also highlights file at path
|
||||||
void RevealFileInFinder(QString const &path) {
|
void RevealFileInFinder(QString const &path) {
|
||||||
QProcess::execute("/usr/bin/open", QStringList() << "-R" << path);
|
QProcess::execute("/usr/bin/open", QStringList() << "-R" << path);
|
||||||
|
|||||||
@@ -125,9 +125,6 @@ void SetEnv(const char *key, const QString &value);
|
|||||||
void IncreaseFDLimit();
|
void IncreaseFDLimit();
|
||||||
void CheckPortable();
|
void CheckPortable();
|
||||||
|
|
||||||
// Returns the minor version of OS X (ie. 6 for Snow Leopard, 7 for Lion).
|
|
||||||
qint32 GetMacOsVersion();
|
|
||||||
|
|
||||||
// Borrowed from schedutils
|
// Borrowed from schedutils
|
||||||
enum IoPriority {
|
enum IoPriority {
|
||||||
IOPRIO_CLASS_NONE = 0,
|
IOPRIO_CLASS_NONE = 0,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <AppKit/NSWorkspace.h>
|
#include <AppKit/NSWorkspace.h>
|
||||||
#include <Foundation/NSString.h>
|
#include <Foundation/NSString.h>
|
||||||
#include <IOKit/hidsystem/ev_keymap.h>
|
#include <IOKit/hidsystem/ev_keymap.h>
|
||||||
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
@@ -50,15 +51,13 @@ class GlobalShortcutBackendMacOSPrivate : boost::noncopyable {
|
|||||||
: global_monitor_(nil), local_monitor_(nil), backend_(backend) {}
|
: global_monitor_(nil), local_monitor_(nil), backend_(backend) {}
|
||||||
|
|
||||||
bool Register() {
|
bool Register() {
|
||||||
global_monitor_ = [NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
|
global_monitor_ = [NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent* event) {
|
||||||
handler:^(NSEvent* event) {
|
HandleKeyEvent(event);
|
||||||
HandleKeyEvent(event);
|
} ];
|
||||||
}];
|
local_monitor_ = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:^(NSEvent* event) {
|
||||||
local_monitor_ = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask
|
|
||||||
handler:^(NSEvent* event) {
|
|
||||||
// Filter event if we handle it as a global shortcut.
|
// Filter event if we handle it as a global shortcut.
|
||||||
return HandleKeyEvent(event) ? nil : event;
|
return HandleKeyEvent(event) ? nil : event;
|
||||||
}];
|
} ];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +84,7 @@ GlobalShortcutBackendMacOS::GlobalShortcutBackendMacOS(GlobalShortcuts* parent)
|
|||||||
GlobalShortcutBackendMacOS::~GlobalShortcutBackendMacOS() {}
|
GlobalShortcutBackendMacOS::~GlobalShortcutBackendMacOS() {}
|
||||||
|
|
||||||
bool GlobalShortcutBackendMacOS::DoRegister() {
|
bool GlobalShortcutBackendMacOS::DoRegister() {
|
||||||
|
|
||||||
// Always enable media keys.
|
// Always enable media keys.
|
||||||
mac::SetShortcutHandler(this);
|
mac::SetShortcutHandler(this);
|
||||||
|
|
||||||
@@ -97,11 +97,14 @@ bool GlobalShortcutBackendMacOS::DoRegister() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GlobalShortcutBackendMacOS::DoUnregister() {
|
void GlobalShortcutBackendMacOS::DoUnregister() {
|
||||||
|
|
||||||
p_->Unregister();
|
p_->Unregister();
|
||||||
shortcuts_.clear();
|
shortcuts_.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalShortcutBackendMacOS::MacMediaKeyPressed(int key) {
|
void GlobalShortcutBackendMacOS::MacMediaKeyPressed(int key) {
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case NX_KEYTYPE_PLAY:
|
case NX_KEYTYPE_PLAY:
|
||||||
KeyPressed(Qt::Key_MediaPlay);
|
KeyPressed(Qt::Key_MediaPlay);
|
||||||
@@ -113,9 +116,11 @@ void GlobalShortcutBackendMacOS::MacMediaKeyPressed(int key) {
|
|||||||
KeyPressed(Qt::Key_MediaPrevious);
|
KeyPressed(Qt::Key_MediaPrevious);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GlobalShortcutBackendMacOS::KeyPressed(const QKeySequence& sequence) {
|
bool GlobalShortcutBackendMacOS::KeyPressed(const QKeySequence& sequence) {
|
||||||
|
|
||||||
if (sequence.isEmpty()) {
|
if (sequence.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -125,24 +130,27 @@ bool GlobalShortcutBackendMacOS::KeyPressed(const QKeySequence& sequence) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GlobalShortcutBackendMacOS::IsAccessibilityEnabled() const {
|
bool GlobalShortcutBackendMacOS::IsAccessibilityEnabled() const {
|
||||||
return AXAPIEnabled();
|
|
||||||
|
NSDictionary *options = @{(id)kAXTrustedCheckOptionPrompt: @YES};
|
||||||
|
return AXIsProcessTrustedWithOptions((CFDictionaryRef)options);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalShortcutBackendMacOS::ShowAccessibilityDialog() {
|
void GlobalShortcutBackendMacOS::ShowAccessibilityDialog() {
|
||||||
|
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSSystemDomainMask, YES);
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSSystemDomainMask, YES);
|
||||||
if ([paths count] == 1) {
|
if ([paths count] == 1) {
|
||||||
SBSystemPreferencesApplication* system_prefs = [SBApplication
|
SBSystemPreferencesApplication* system_prefs = [SBApplication applicationWithBundleIdentifier:@"com.apple.systempreferences"];
|
||||||
applicationWithBundleIdentifier:@"com.apple.systempreferences"];
|
|
||||||
[system_prefs activate];
|
[system_prefs activate];
|
||||||
|
|
||||||
SBElementArray* panes = [system_prefs panes];
|
SBElementArray* panes = [system_prefs panes];
|
||||||
SBSystemPreferencesPane* security_pane = nil;
|
SBSystemPreferencesPane* security_pane = nil;
|
||||||
for (SBSystemPreferencesPane* pane : panes) {
|
for (SBSystemPreferencesPane* pane : panes) {
|
||||||
if ([[pane id] isEqualToString:@"com.apple.preference.security"]) {
|
if ([ [pane id] isEqualToString:@"com.apple.preference.security"]) {
|
||||||
security_pane = pane;
|
security_pane = pane;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -151,7 +159,7 @@ void GlobalShortcutBackendMacOS::ShowAccessibilityDialog() {
|
|||||||
|
|
||||||
SBElementArray* anchors = [security_pane anchors];
|
SBElementArray* anchors = [security_pane anchors];
|
||||||
for (SBSystemPreferencesAnchor* anchor : anchors) {
|
for (SBSystemPreferencesAnchor* anchor : anchors) {
|
||||||
if ([[anchor name] isEqualToString:@"Privacy_Accessibility"]) {
|
if ([ [anchor name] isEqualToString:@"Privacy_Accessibility"]) {
|
||||||
[anchor reveal];
|
[anchor reveal];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
|
|
||||||
#include "core/iconloader.h"
|
#include "core/iconloader.h"
|
||||||
#include "core/utilities.h"
|
#include "core/utilities.h"
|
||||||
|
#ifdef Q_OS_MACOS
|
||||||
|
# include "core/mac_utilities.h"
|
||||||
|
#endif
|
||||||
#include "globalshortcuts/globalshortcutgrabber.h"
|
#include "globalshortcuts/globalshortcutgrabber.h"
|
||||||
#include "globalshortcuts/globalshortcuts.h"
|
#include "globalshortcuts/globalshortcuts.h"
|
||||||
#include "settingspage.h"
|
#include "settingspage.h"
|
||||||
|
|||||||
@@ -27,30 +27,33 @@ THE SOFTWARE.
|
|||||||
#include <QtMacExtras>
|
#include <QtMacExtras>
|
||||||
#include <QMacCocoaViewContainer>
|
#include <QMacCocoaViewContainer>
|
||||||
|
|
||||||
static inline NSString* fromQString(const QString &string)
|
static inline NSString* fromQString(const QString &string) {
|
||||||
{
|
|
||||||
const QByteArray utf8 = string.toUtf8();
|
const QByteArray utf8 = string.toUtf8();
|
||||||
const char* cString = utf8.constData();
|
const char* cString = utf8.constData();
|
||||||
return [[NSString alloc] initWithUTF8String:cString];
|
return [ [NSString alloc] initWithUTF8String:cString];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QString toQString(NSString *string)
|
static inline QString toQString(NSString *string) {
|
||||||
{
|
|
||||||
if (!string)
|
if (!string) return QString();
|
||||||
return QString();
|
return QString::fromUtf8([string UTF8String]);
|
||||||
return QString::fromUtf8([string UTF8String]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline NSImage* fromQPixmap(const QPixmap &pixmap)
|
static inline NSImage* fromQPixmap(const QPixmap &pixmap) {
|
||||||
{
|
|
||||||
CGImageRef cgImage = QtMac::toCGImageRef(pixmap);
|
CGImageRef cgImage = QtMac::toCGImageRef(pixmap);
|
||||||
return [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize];
|
return [ [NSImage alloc] initWithCGImage:cgImage size:NSZeroSize];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void setupLayout(NSView *cocoaView, QWidget *parent)
|
static inline void setupLayout(NSView *cocoaView, QWidget *parent) {
|
||||||
{
|
|
||||||
parent->setAttribute(Qt::WA_NativeWindow);
|
parent->setAttribute(Qt::WA_NativeWindow);
|
||||||
QVBoxLayout *layout = new QVBoxLayout(parent);
|
QVBoxLayout *layout = new QVBoxLayout(parent);
|
||||||
layout->setMargin(0);
|
layout->setMargin(0);
|
||||||
layout->addWidget(new QMacCocoaViewContainer(cocoaView, parent));
|
layout->addWidget(new QMacCocoaViewContainer(cocoaView, parent));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user