mirror of
https://github.com/clementine-player/Clementine
synced 2024-12-16 11:19:18 +01:00
Global keyboard shortcuts for Cocoa.
Requires "Enable access for assistive devices" set in Universal Access control panel.
This commit is contained in:
parent
4dbd1f2a2f
commit
f9e29fccf4
@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
set(CMAKE_C_FLAGS "-Wall")
|
||||
set(CMAKE_CXX_FLAGS "-Wnon-virtual-dtor -Woverloaded-virtual -Wall")
|
||||
set(CMAKE_CXX_FLAGS "-Woverloaded-virtual -Wall")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${SPARKLE})
|
||||
@ -356,6 +356,8 @@ endif(ENABLE_VISUALISATIONS)
|
||||
# OSDs
|
||||
if(APPLE)
|
||||
list(APPEND SOURCES widgets/osd_mac.mm)
|
||||
list(APPEND SOURCES core/macglobalshortcutbackend.mm)
|
||||
list(APPEND HEADERS core/macglobalshortcutbackend.h)
|
||||
include_directories(${GROWL}/Headers)
|
||||
else(APPLE)
|
||||
if(WIN32)
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "globalshortcuts.h"
|
||||
#include "gnomeglobalshortcutbackend.h"
|
||||
#include "macglobalshortcutbackend.h"
|
||||
#include "qxtglobalshortcutbackend.h"
|
||||
|
||||
#include "mac_startup.h"
|
||||
@ -39,11 +40,11 @@ GlobalShortcuts::GlobalShortcuts(QObject *parent)
|
||||
// Create actions
|
||||
AddShortcut("play", tr("Play"), SIGNAL(Play()));
|
||||
AddShortcut("pause", tr("Pause"), SIGNAL(Pause()));
|
||||
AddShortcut("play_pause", tr("Play/Pause"), SIGNAL(PlayPause()), QKeySequence(Qt::Key_MediaPlay));
|
||||
AddShortcut("stop", tr("Stop"), SIGNAL(Stop()), QKeySequence(Qt::Key_MediaStop));
|
||||
AddShortcut("play_pause", tr("Play/Pause"), SIGNAL(PlayPause())); //QKeySequence(Qt::Key_MediaPlay));
|
||||
AddShortcut("stop", tr("Stop"), SIGNAL(Stop()));// QKeySequence(Qt::Key_MediaStop));
|
||||
AddShortcut("stop_after", tr("Stop playing after current track"), SIGNAL(StopAfter()));
|
||||
AddShortcut("next_track", tr("Next track"), SIGNAL(Next()), QKeySequence(Qt::Key_MediaNext));
|
||||
AddShortcut("prev_track", tr("Previous track"), SIGNAL(Previous()), QKeySequence(Qt::Key_MediaPrevious));
|
||||
AddShortcut("next_track", tr("Next track"), SIGNAL(Next()));// QKeySequence(Qt::Key_MediaNext));
|
||||
AddShortcut("prev_track", tr("Previous track"), SIGNAL(Previous()));// QKeySequence(Qt::Key_MediaPrevious));
|
||||
AddShortcut("inc_volume", tr("Increase volume"), SIGNAL(IncVolume()));
|
||||
AddShortcut("dec_volume", tr("Decrease volume"), SIGNAL(DecVolume()));
|
||||
AddShortcut("mute", tr("Mute"), SIGNAL(Mute()));
|
||||
@ -57,8 +58,7 @@ GlobalShortcuts::GlobalShortcuts(QObject *parent)
|
||||
#ifndef Q_OS_DARWIN
|
||||
system_backend_ = new QxtGlobalShortcutBackend(this);
|
||||
#else
|
||||
// Setup global media key shortcuts for mac.
|
||||
mac::SetShortcutHandler(this);
|
||||
system_backend_ = new MacGlobalShortcutBackend(this);
|
||||
#endif
|
||||
|
||||
ReloadSettings();
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef MAC_STARTUP_H
|
||||
#define MAC_STARTUP_H
|
||||
|
||||
class GlobalShortcuts;
|
||||
class MacGlobalShortcutBackend;
|
||||
class QObject;
|
||||
|
||||
class PlatformInterface {
|
||||
@ -16,7 +16,7 @@ class PlatformInterface {
|
||||
namespace mac {
|
||||
|
||||
void MacMain();
|
||||
void SetShortcutHandler(GlobalShortcuts* handler);
|
||||
void SetShortcutHandler(MacGlobalShortcutBackend* handler);
|
||||
void SetApplicationHandler(PlatformInterface* handler);
|
||||
void CheckForUpdates();
|
||||
|
||||
|
@ -10,8 +10,11 @@
|
||||
#import <AppKit/NSNibDeclarations.h>
|
||||
#import <Sparkle/SUUpdater.h>
|
||||
|
||||
#import <Kernel/AvailabilityMacros.h>
|
||||
|
||||
#include "globalshortcuts.h"
|
||||
#include "mac_startup.h"
|
||||
#include "macglobalshortcutbackend.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QEvent>
|
||||
@ -22,12 +25,12 @@
|
||||
// See: http://www.rogueamoeba.com/utm/2007/09/29/apple-keyboard-media-key-event-handling/
|
||||
|
||||
@interface MacApplication :NSApplication {
|
||||
GlobalShortcuts* shortcut_handler_;
|
||||
MacGlobalShortcutBackend* shortcut_handler_;
|
||||
PlatformInterface* application_handler_;
|
||||
}
|
||||
|
||||
- (GlobalShortcuts*) shortcut_handler;
|
||||
- (void) SetShortcutHandler: (GlobalShortcuts*)handler;
|
||||
- (MacGlobalShortcutBackend*) shortcut_handler;
|
||||
- (void) SetShortcutHandler: (MacGlobalShortcutBackend*)handler;
|
||||
|
||||
- (PlatformInterface*) application_handler;
|
||||
- (void) SetApplicationHandler: (PlatformInterface*)handler;
|
||||
@ -35,7 +38,11 @@
|
||||
- (void) mediaKeyEvent: (int)key state: (BOOL)state repeat: (BOOL)repeat;
|
||||
@end
|
||||
|
||||
@interface AppDelegate :NSObject { //<NSApplicationDelegate> {
|
||||
#ifdef MAC_OS_X_VERSION_10_6
|
||||
@interface AppDelegate :NSObject <NSApplicationDelegate> {
|
||||
#else
|
||||
@interface AppDelegate :NSObject {
|
||||
#endif
|
||||
PlatformInterface* application_handler_;
|
||||
}
|
||||
|
||||
@ -86,11 +93,11 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (GlobalShortcuts*) shortcut_handler {
|
||||
- (MacGlobalShortcutBackend*) shortcut_handler {
|
||||
return shortcut_handler_;
|
||||
}
|
||||
|
||||
- (void) SetShortcutHandler: (GlobalShortcuts*)handler {
|
||||
- (void) SetShortcutHandler: (MacGlobalShortcutBackend*)handler {
|
||||
shortcut_handler_ = handler;
|
||||
}
|
||||
|
||||
@ -121,21 +128,7 @@
|
||||
return;
|
||||
}
|
||||
if (state == 0) {
|
||||
switch (key) {
|
||||
case NX_KEYTYPE_PLAY:
|
||||
// Play pressed.
|
||||
shortcut_handler_->MacMediaKeyPressed("Play");
|
||||
break;
|
||||
case NX_KEYTYPE_FAST:
|
||||
// Next pressed.
|
||||
shortcut_handler_->MacMediaKeyPressed("Next");
|
||||
break;
|
||||
case NX_KEYTYPE_REWIND:
|
||||
shortcut_handler_->MacMediaKeyPressed("Previous");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
shortcut_handler_->MacMediaKeyPressed(key);
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,7 +144,7 @@ void MacMain() {
|
||||
[[SUUpdater sharedUpdater] setDelegate: NSApp];
|
||||
}
|
||||
|
||||
void SetShortcutHandler(GlobalShortcuts* handler) {
|
||||
void SetShortcutHandler(MacGlobalShortcutBackend* handler) {
|
||||
[NSApp SetShortcutHandler: handler];
|
||||
}
|
||||
|
||||
|
51
src/core/macglobalshortcutbackend.h
Normal file
51
src/core/macglobalshortcutbackend.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MACGLOBALSHORTCUTBACKEND_H
|
||||
#define MACGLOBALSHORTCUTBACKEND_H
|
||||
|
||||
#include "globalshortcutbackend.h"
|
||||
|
||||
#include <QKeySequence>
|
||||
#include <QMap>
|
||||
|
||||
class MacGlobalShortcutBackendPrivate;
|
||||
class QAction;
|
||||
|
||||
class MacGlobalShortcutBackend : public GlobalShortcutBackend {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacGlobalShortcutBackend(GlobalShortcuts* parent);
|
||||
virtual ~MacGlobalShortcutBackend();
|
||||
|
||||
void MacMediaKeyPressed(int key);
|
||||
|
||||
protected:
|
||||
bool DoRegister();
|
||||
void DoUnregister();
|
||||
|
||||
private:
|
||||
void KeyPressed(const QKeySequence& sequence);
|
||||
|
||||
QMap<QKeySequence, QAction*> shortcuts_;
|
||||
|
||||
friend class MacGlobalShortcutBackendPrivate;
|
||||
|
||||
MacGlobalShortcutBackendPrivate* p_;
|
||||
};
|
||||
|
||||
#endif // MACGLOBALSHORTCUTBACKEND_H
|
128
src/core/macglobalshortcutbackend.mm
Normal file
128
src/core/macglobalshortcutbackend.mm
Normal file
@ -0,0 +1,128 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "macglobalshortcutbackend.h"
|
||||
|
||||
#include "globalshortcuts.h"
|
||||
#include "mac_startup.h"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <QAction>
|
||||
#include <QList>
|
||||
#include <QtDebug>
|
||||
|
||||
#include <AppKit/NSEvent.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <IOKit/hidsystem/ev_keymap.h>
|
||||
|
||||
class MacGlobalShortcutBackendPrivate : boost::noncopyable {
|
||||
public:
|
||||
explicit MacGlobalShortcutBackendPrivate(MacGlobalShortcutBackend* backend)
|
||||
: monitor_(nil),
|
||||
backend_(backend) {
|
||||
}
|
||||
|
||||
bool Register() {
|
||||
#ifdef NS_BLOCKS_AVAILABLE
|
||||
monitor_ = [NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
|
||||
handler:^(NSEvent* event) {
|
||||
qDebug() << __PRETTY_FUNCTION__;
|
||||
HandleKeyEvent(event);
|
||||
}];
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Unregister() {
|
||||
[NSEvent removeMonitor:monitor_];
|
||||
}
|
||||
|
||||
private:
|
||||
static QKeySequence GetSequence(NSEvent* event) {
|
||||
NSString* str = [event charactersIgnoringModifiers];
|
||||
NSString* lower = [str lowercaseString];
|
||||
const char* chars = [lower UTF8String];
|
||||
NSUInteger modifiers = [event modifierFlags];
|
||||
int key = Qt::Key_A + chars[0] - 'a'; // >.>
|
||||
if (modifiers & NSShiftKeyMask) {
|
||||
key += Qt::SHIFT;
|
||||
}
|
||||
if (modifiers & NSControlKeyMask) {
|
||||
key += Qt::META;
|
||||
}
|
||||
if (modifiers & NSAlternateKeyMask) {
|
||||
key += Qt::ALT;
|
||||
}
|
||||
if (modifiers & NSCommandKeyMask) {
|
||||
key += Qt::CTRL;
|
||||
}
|
||||
|
||||
return QKeySequence(key);
|
||||
}
|
||||
|
||||
void HandleKeyEvent(NSEvent* event) {
|
||||
QKeySequence sequence = GetSequence(event);
|
||||
backend_->KeyPressed(sequence);
|
||||
}
|
||||
|
||||
id monitor_;
|
||||
MacGlobalShortcutBackend* backend_;
|
||||
};
|
||||
|
||||
MacGlobalShortcutBackend::MacGlobalShortcutBackend(GlobalShortcuts* parent)
|
||||
: GlobalShortcutBackend(parent),
|
||||
p_(new MacGlobalShortcutBackendPrivate(this)) {
|
||||
}
|
||||
|
||||
MacGlobalShortcutBackend::~MacGlobalShortcutBackend() {
|
||||
delete p_;
|
||||
}
|
||||
|
||||
bool MacGlobalShortcutBackend::DoRegister() {
|
||||
mac::SetShortcutHandler(this);
|
||||
foreach (const GlobalShortcuts::Shortcut& shortcut, manager_->shortcuts().values()) {
|
||||
shortcuts_[shortcut.action->shortcut()] = shortcut.action;
|
||||
}
|
||||
return p_->Register();
|
||||
}
|
||||
|
||||
void MacGlobalShortcutBackend::DoUnregister() {
|
||||
p_->Unregister();
|
||||
}
|
||||
|
||||
void MacGlobalShortcutBackend::MacMediaKeyPressed(int key) {
|
||||
switch (key) {
|
||||
case NX_KEYTYPE_PLAY:
|
||||
manager_->shortcuts()["play_pause"].action->trigger();
|
||||
break;
|
||||
case NX_KEYTYPE_FAST:
|
||||
manager_->shortcuts()["next_track"].action->trigger();
|
||||
break;
|
||||
case NX_KEYTYPE_REWIND:
|
||||
manager_->shortcuts()["prev_track"].action->trigger();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MacGlobalShortcutBackend::KeyPressed(const QKeySequence& sequence) {
|
||||
QAction* action = shortcuts_[sequence];
|
||||
if (action) {
|
||||
action->trigger();
|
||||
}
|
||||
}
|
@ -28,11 +28,9 @@ QxtGlobalShortcutBackend::QxtGlobalShortcutBackend(GlobalShortcuts *parent)
|
||||
|
||||
bool QxtGlobalShortcutBackend::DoRegister() {
|
||||
qDebug() << __PRETTY_FUNCTION__;
|
||||
#ifndef Q_OS_DARWIN
|
||||
foreach (const GlobalShortcuts::Shortcut& shortcut, manager_->shortcuts().values()) {
|
||||
AddShortcut(shortcut.action);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user