Add new global shortcut system backend for X11 and Windows
- Remove qxt - Also create an option for enabled/disabling shortcuts through X11.
This commit is contained in:
@@ -43,6 +43,10 @@ include_directories(${Boost_INCLUDE_DIRS})
|
||||
include_directories(${LIBXML_INCLUDE_DIRS})
|
||||
include_directories(${CHROMAPRINT_INCLUDE_DIRS})
|
||||
|
||||
if (X11_FOUND)
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
endif(X11_FOUND)
|
||||
|
||||
if(HAVE_GSTREAMER)
|
||||
link_directories(${GSTREAMER_LIBRARY_DIRS})
|
||||
include_directories(${GSTREAMER_INCLUDE_DIRS})
|
||||
@@ -210,7 +214,6 @@ set(SOURCES
|
||||
settings/playbacksettingspage.cpp
|
||||
settings/playlistsettingspage.cpp
|
||||
settings/networkproxysettingspage.cpp
|
||||
settings/shortcutssettingspage.cpp
|
||||
settings/appearancesettingspage.cpp
|
||||
settings/notificationssettingspage.cpp
|
||||
settings/scrobblersettingspage.cpp
|
||||
@@ -250,12 +253,6 @@ set(SOURCES
|
||||
musicbrainz/acoustidclient.cpp
|
||||
musicbrainz/musicbrainzclient.cpp
|
||||
|
||||
globalshortcuts/globalshortcutbackend.cpp
|
||||
globalshortcuts/globalshortcuts.cpp
|
||||
globalshortcuts/gnomeglobalshortcutbackend.cpp
|
||||
globalshortcuts/qxtglobalshortcutbackend.cpp
|
||||
globalshortcuts/globalshortcutgrabber.cpp
|
||||
|
||||
internet/internetservices.cpp
|
||||
internet/internetservice.cpp
|
||||
internet/internetplaylistitem.cpp
|
||||
@@ -387,7 +384,6 @@ set(HEADERS
|
||||
settings/playbacksettingspage.h
|
||||
settings/playlistsettingspage.h
|
||||
settings/networkproxysettingspage.h
|
||||
settings/shortcutssettingspage.h
|
||||
settings/appearancesettingspage.h
|
||||
settings/notificationssettingspage.h
|
||||
settings/scrobblersettingspage.h
|
||||
@@ -425,11 +421,6 @@ set(HEADERS
|
||||
musicbrainz/acoustidclient.h
|
||||
musicbrainz/musicbrainzclient.h
|
||||
|
||||
globalshortcuts/globalshortcutbackend.h
|
||||
globalshortcuts/globalshortcuts.h
|
||||
globalshortcuts/gnomeglobalshortcutbackend.h
|
||||
globalshortcuts/globalshortcutgrabber.h
|
||||
|
||||
internet/internetservices.h
|
||||
internet/internetservice.h
|
||||
internet/internetsongmimedata.h
|
||||
@@ -481,7 +472,6 @@ set(UI
|
||||
settings/playbacksettingspage.ui
|
||||
settings/playlistsettingspage.ui
|
||||
settings/networkproxysettingspage.ui
|
||||
settings/shortcutssettingspage.ui
|
||||
settings/appearancesettingspage.ui
|
||||
settings/notificationssettingspage.ui
|
||||
settings/scrobblersettingspage.ui
|
||||
@@ -500,8 +490,6 @@ set(UI
|
||||
widgets/fileview.ui
|
||||
widgets/loginstatewidget.ui
|
||||
|
||||
globalshortcuts/globalshortcutgrabber.ui
|
||||
|
||||
internet/internetsearchview.ui
|
||||
|
||||
)
|
||||
@@ -511,6 +499,31 @@ set(OTHER_SOURCES)
|
||||
|
||||
option(USE_INSTALL_PREFIX "Look for data in CMAKE_INSTALL_PREFIX" ON)
|
||||
|
||||
if(HAVE_GLOBALSHORTCUTS)
|
||||
optional_source(HAVE_GLOBALSHORTCUTS
|
||||
SOURCES globalshortcuts/globalshortcuts.cpp globalshortcuts/globalshortcutbackend.cpp globalshortcuts/globalshortcutgrabber.cpp settings/shortcutssettingspage.cpp
|
||||
HEADERS globalshortcuts/globalshortcuts.h globalshortcuts/globalshortcutbackend.h globalshortcuts/globalshortcutgrabber.h settings/shortcutssettingspage.h
|
||||
UI globalshortcuts/globalshortcutgrabber.ui settings/shortcutssettingspage.ui
|
||||
)
|
||||
if (X11_FOUND OR WIN32)
|
||||
set(X11_OR_WIN ON)
|
||||
endif()
|
||||
optional_source(X11_OR_WIN
|
||||
SOURCES globalshortcuts/globalshortcutbackend-system.cpp globalshortcuts/globalshortcut.cpp
|
||||
HEADERS globalshortcuts/globalshortcutbackend-system.h globalshortcuts/globalshortcut.h
|
||||
)
|
||||
optional_source(X11_FOUND
|
||||
SOURCES globalshortcuts/globalshortcut-x11.cpp
|
||||
)
|
||||
optional_source(HAVE_DBUS
|
||||
SOURCES globalshortcuts/globalshortcutbackend-dbus.cpp
|
||||
HEADERS globalshortcuts/globalshortcutbackend-dbus.h
|
||||
)
|
||||
optional_source(WIN32
|
||||
SOURCES globalshortcuts/globalshortcut-win.cpp
|
||||
)
|
||||
endif(HAVE_GLOBALSHORTCUTS)
|
||||
|
||||
# ALSA
|
||||
optional_source(HAVE_ALSA
|
||||
SOURCES
|
||||
@@ -518,7 +531,10 @@ optional_source(HAVE_ALSA
|
||||
)
|
||||
|
||||
# X11
|
||||
optional_source(HAVE_X11 SOURCES widgets/osd_x11.cpp)
|
||||
optional_source(X11_FOUND
|
||||
SOURCES
|
||||
widgets/osd_x11.cpp
|
||||
)
|
||||
|
||||
# GStreamer
|
||||
optional_source(HAVE_GSTREAMER
|
||||
@@ -554,16 +570,18 @@ optional_source(HAVE_DEEZER
|
||||
if(UNIX AND HAVE_DBUS)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dbus)
|
||||
|
||||
# MPRIS DBUS interfaces
|
||||
#qt5_add_dbus_adaptor(SOURCES
|
||||
# dbus/org.freedesktop.MediaPlayer.player.xml
|
||||
# core/mpris1.h mpris::Mpris1Player core/mpris_player MprisPlayer)
|
||||
#qt5_add_dbus_adaptor(SOURCES
|
||||
# dbus/org.freedesktop.MediaPlayer.root.xml
|
||||
# core/mpris1.h mpris::Mpris1Root core/mpris_root MprisRoot)
|
||||
#qt5_add_dbus_adaptor(SOURCES
|
||||
# dbus/org.freedesktop.MediaPlayer.tracklist.xml
|
||||
# core/mpris1.h mpris::Mpris1TrackList core/mpris_tracklist MprisTrackList)
|
||||
optional_source(HAVE_DBUS
|
||||
SOURCES core/mpris.cpp core/mpris2.cpp core/dbusscreensaver.cpp
|
||||
HEADERS core/mpris.h core/mpris2.h
|
||||
)
|
||||
optional_source(HAVE_DEVICEKIT
|
||||
SOURCES device/devicekitlister.cpp
|
||||
HEADERS device/devicekitlister.h
|
||||
)
|
||||
optional_source(HAVE_UDISKS2
|
||||
SOURCES device/udisks2lister.cpp
|
||||
HEADERS device/udisks2lister.h
|
||||
)
|
||||
|
||||
# MPRIS 2.0 DBUS interfaces
|
||||
qt5_add_dbus_adaptor(SOURCES
|
||||
@@ -663,16 +681,6 @@ if(UNIX AND HAVE_DBUS)
|
||||
|
||||
endif(UNIX AND HAVE_DBUS)
|
||||
|
||||
optional_source(HAVE_DBUS
|
||||
SOURCES
|
||||
core/mpris.cpp
|
||||
core/mpris2.cpp
|
||||
core/dbusscreensaver.cpp
|
||||
HEADERS
|
||||
core/mpris.h
|
||||
core/mpris2.h
|
||||
)
|
||||
|
||||
optional_source(UNIX
|
||||
SOURCES
|
||||
device/connecteddevice.cpp
|
||||
@@ -700,17 +708,6 @@ optional_source(UNIX
|
||||
device/deviceviewcontainer.ui
|
||||
)
|
||||
|
||||
if(HAVE_DBUS)
|
||||
optional_source(HAVE_DEVICEKIT
|
||||
SOURCES device/devicekitlister.cpp
|
||||
HEADERS device/devicekitlister.h
|
||||
)
|
||||
optional_source(HAVE_UDISKS2
|
||||
SOURCES device/udisks2lister.cpp
|
||||
HEADERS device/udisks2lister.h
|
||||
)
|
||||
endif()
|
||||
|
||||
# Libgpod device backend
|
||||
optional_source(HAVE_LIBGPOD
|
||||
INCLUDE_DIRECTORIES ${LIBGPOD_INCLUDE_DIRS}
|
||||
@@ -842,12 +839,12 @@ optional_source(APPLE
|
||||
core/macfslistener.mm
|
||||
widgets/osd_mac.mm
|
||||
engine/osxdevicefinder.cpp
|
||||
globalshortcuts/globalshortcutgrabber.mm
|
||||
globalshortcuts/macglobalshortcutbackend.mm
|
||||
globalshortcuts/globalshortcutbackend-macos.mm
|
||||
globalshortcuts/globalshortcutgrabber-macos.mm
|
||||
HEADERS
|
||||
core/macsystemtrayicon.h
|
||||
core/macfslistener.h
|
||||
globalshortcuts/macglobalshortcutbackend.h
|
||||
globalshortcuts/globalshortcutbackend-macos.h
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
@@ -922,14 +919,22 @@ target_link_libraries(strawberry_lib
|
||||
${GOBJECT_LIBRARIES}
|
||||
${QT_LIBRARIES}
|
||||
${CHROMAPRINT_LIBRARIES}
|
||||
${SQLITE_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${QTSINGLEAPPLICATION_LIBRARIES}
|
||||
${QTSINGLECOREAPPLICATION_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${SQLITE_LIBRARIES}
|
||||
${QOCOA_LIBRARIES}
|
||||
z
|
||||
)
|
||||
|
||||
if(X11_FOUND)
|
||||
target_link_libraries(strawberry_lib ${X11_LIBRARIES})
|
||||
endif(X11_FOUND)
|
||||
|
||||
if(XCB_FOUND)
|
||||
target_link_libraries(strawberry_lib ${XCB_LIBRARIES})
|
||||
endif(XCB_FOUND)
|
||||
|
||||
if(HAVE_ALSA)
|
||||
target_link_libraries(strawberry_lib ${ALSA_LIBRARIES})
|
||||
endif(HAVE_ALSA)
|
||||
|
||||
@@ -32,19 +32,17 @@
|
||||
#cmakedefine HAVE_ALSA
|
||||
#cmakedefine HAVE_DEVICEKIT
|
||||
#cmakedefine HAVE_IMOBILEDEVICE
|
||||
#cmakedefine HAVE_LIBARCHIVE
|
||||
#cmakedefine HAVE_AUDIOCD
|
||||
#cmakedefine HAVE_LIBGPOD
|
||||
#cmakedefine HAVE_LIBMTP
|
||||
#cmakedefine HAVE_LIBPULSE
|
||||
#cmakedefine HAVE_QCA
|
||||
#cmakedefine HAVE_SPARKLE
|
||||
#cmakedefine HAVE_CHROMAPRINT
|
||||
#cmakedefine HAVE_TAGLIB_DSFFILE
|
||||
#cmakedefine HAVE_DZMEDIA
|
||||
#cmakedefine HAVE_GLOBALSHORTCUTS
|
||||
#cmakedefine IMOBILEDEVICE_USES_UDIDS
|
||||
#cmakedefine USE_INSTALL_PREFIX
|
||||
#cmakedefine USE_SYSTEM_SHA2
|
||||
|
||||
#cmakedefine HAVE_GSTREAMER
|
||||
#cmakedefine HAVE_VLC
|
||||
@@ -55,5 +53,8 @@
|
||||
#cmakedefine HAVE_STREAM_TIDAL
|
||||
#cmakedefine HAVE_STREAM_DEEZER
|
||||
|
||||
#cmakedefine HAVE_KEYSYMDEF_H
|
||||
#cmakedefine HAVE_XF86KEYSYM_H
|
||||
|
||||
#endif // CONFIG_H_IN
|
||||
|
||||
|
||||
@@ -117,7 +117,9 @@
|
||||
#include "playlistparsers/playlistparser.h"
|
||||
#include "analyzer/analyzercontainer.h"
|
||||
#include "equalizer/equalizer.h"
|
||||
#include "globalshortcuts/globalshortcuts.h"
|
||||
#ifdef HAVE_GLOBALSHORTCUTS
|
||||
# include "globalshortcuts/globalshortcuts.h"
|
||||
#endif
|
||||
#include "covermanager/albumcovermanager.h"
|
||||
#include "covermanager/albumcoverchoicecontroller.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
@@ -158,11 +160,6 @@ using std::bind;
|
||||
using std::floor;
|
||||
using std::stable_sort;
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
// Non exported mac-specific function.
|
||||
void qt_mac_set_dock_menu(QMenu*);
|
||||
#endif
|
||||
|
||||
const char *MainWindow::kSettingsGroup = "MainWindow";
|
||||
const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)");
|
||||
|
||||
@@ -180,7 +177,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
osd_(osd),
|
||||
edit_tag_dialog_(std::bind(&MainWindow::CreateEditTagDialog, this)),
|
||||
album_cover_choice_controller_(new AlbumCoverChoiceController(this)),
|
||||
#ifdef HAVE_GLOBALSHORTCUTS
|
||||
global_shortcuts_(new GlobalShortcuts(this)),
|
||||
#endif
|
||||
context_view_(new ContextView(this)),
|
||||
collection_view_(new CollectionViewContainer(this)),
|
||||
file_view_(new FileView(this)),
|
||||
@@ -632,6 +631,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
connect(check_updates, SIGNAL(triggered(bool)), SLOT(CheckForUpdates()));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GLOBALSHORTCUTS
|
||||
// Global shortcuts
|
||||
connect(global_shortcuts_, SIGNAL(Play()), app_->player(), SLOT(Play()));
|
||||
connect(global_shortcuts_, SIGNAL(Pause()), app_->player(), SLOT(Pause()));
|
||||
@@ -649,6 +649,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
connect(global_shortcuts_, SIGNAL(ShowOSD()), app_->player(), SLOT(ShowOSD()));
|
||||
connect(global_shortcuts_, SIGNAL(TogglePrettyOSD()), app_->player(), SLOT(TogglePrettyOSD()));
|
||||
connect(global_shortcuts_, SIGNAL(ToggleScrobbling()), app_->scrobbler(), SLOT(ToggleScrobbling()));
|
||||
#endif
|
||||
|
||||
// Fancy tabs
|
||||
connect(ui_->tabs, SIGNAL(ModeChanged(FancyTabWidget::Mode)), SLOT(SaveTabMode()));
|
||||
@@ -703,8 +704,10 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
connect(this, SIGNAL(StopAfterToggled(bool)), osd_, SLOT(StopAfterToggle(bool)));
|
||||
|
||||
// We need to connect these global shortcuts here after the playlist have been initialized
|
||||
#ifdef HAVE_GLOBALSHORTCUTS
|
||||
connect(global_shortcuts_, SIGNAL(CycleShuffleMode()), app_->playlist_manager()->sequence(), SLOT(CycleShuffleMode()));
|
||||
connect(global_shortcuts_, SIGNAL(CycleRepeatMode()), app_->playlist_manager()->sequence(), SLOT(CycleRepeatMode()));
|
||||
#endif
|
||||
connect(app_->playlist_manager()->sequence(), SIGNAL(RepeatModeChanged(PlaylistSequence::RepeatMode)), osd_, SLOT(RepeatModeChanged(PlaylistSequence::RepeatMode)));
|
||||
connect(app_->playlist_manager()->sequence(), SIGNAL(ShuffleModeChanged(PlaylistSequence::ShuffleMode)), osd_, SLOT(ShuffleModeChanged(PlaylistSequence::ShuffleMode)));
|
||||
|
||||
@@ -2091,7 +2094,9 @@ void MainWindow::ShowCoverManager() {
|
||||
SettingsDialog *MainWindow::CreateSettingsDialog() {
|
||||
|
||||
SettingsDialog *settings_dialog = new SettingsDialog(app_);
|
||||
#ifdef HAVE_GLOBALSHORTCUTS
|
||||
settings_dialog->SetGlobalShortcutManager(global_shortcuts_);
|
||||
#endif
|
||||
|
||||
// Settings
|
||||
connect(settings_dialog, SIGNAL(accepted()), SLOT(ReloadAllSettings()));
|
||||
|
||||
@@ -363,7 +363,7 @@ QString ColorToRgba(const QColor &c) {
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
qint32 GetMacVersion() {
|
||||
qint32 GetMacOsVersion() {
|
||||
|
||||
SInt32 minor_version;
|
||||
Gestalt(gestaltSystemVersionMinor, &minor_version);
|
||||
|
||||
@@ -127,7 +127,7 @@ void IncreaseFDLimit();
|
||||
void CheckPortable();
|
||||
|
||||
// Returns the minor version of OS X (ie. 6 for Snow Leopard, 7 for Lion).
|
||||
qint32 GetMacVersion();
|
||||
qint32 GetMacOsVersion();
|
||||
|
||||
// Borrowed from schedutils
|
||||
enum IoPriority {
|
||||
|
||||
76
src/globalshortcuts/globalshortcut-win.cpp
Normal file
76
src/globalshortcuts/globalshortcut-win.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2018, 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 <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QByteArray>
|
||||
|
||||
#include <qt_windows.h>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
#include "globalshortcuts.h"
|
||||
#include "globalshortcutbackend.h"
|
||||
#include "globalshortcut.h"
|
||||
#include "keymapper_win.h"
|
||||
|
||||
quint32 GlobalShortcut::nativeModifiers(Qt::KeyboardModifiers qt_mods) {
|
||||
|
||||
quint32 native_mods = 0;
|
||||
if (qt_mods & Qt::ShiftModifier) native_mods |= MOD_SHIFT;
|
||||
if (qt_mods & Qt::ControlModifier) native_mods |= MOD_CONTROL;
|
||||
if (qt_mods & Qt::AltModifier) native_mods |= MOD_ALT;
|
||||
if (qt_mods & Qt::MetaModifier) native_mods |= MOD_WIN;
|
||||
return native_mods;
|
||||
|
||||
}
|
||||
|
||||
quint32 GlobalShortcut::nativeKeycode(Qt::Key qt_key) {
|
||||
|
||||
quint32 key_code = 0;
|
||||
if (KeyMapperWin::keymapper_win_.contains(qt_key)) {
|
||||
key_code = KeyMapperWin::keymapper_win_.value(qt_key);
|
||||
}
|
||||
return key_code;
|
||||
|
||||
}
|
||||
|
||||
bool GlobalShortcut::registerShortcut(quint32 native_key, quint32 native_mods) {
|
||||
return RegisterHotKey(0, native_mods ^ native_key, native_mods, native_key);
|
||||
}
|
||||
|
||||
bool GlobalShortcut::unregisterShortcut(quint32 native_key, quint32 native_mods) {
|
||||
return UnregisterHotKey(0, native_mods ^ native_key);
|
||||
}
|
||||
|
||||
bool GlobalShortcut::nativeEventFilter(const QByteArray &eventtype, void *message, long *result) {
|
||||
|
||||
Q_UNUSED(eventtype);
|
||||
Q_UNUSED(result);
|
||||
|
||||
MSG *msg = static_cast<MSG*>(message);
|
||||
if (msg->message != WM_HOTKEY) return false;
|
||||
|
||||
quint32 key_code = HIWORD(msg->lParam);
|
||||
quint32 modifiers = LOWORD(msg->lParam);
|
||||
activateShortcut(key_code, modifiers);
|
||||
return true;
|
||||
|
||||
}
|
||||
112
src/globalshortcuts/globalshortcut-x11.cpp
Normal file
112
src/globalshortcuts/globalshortcut-x11.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2018, 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>
|
||||
#include <QApplication>
|
||||
#include <QObject>
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QDataStream>
|
||||
#include <QVector>
|
||||
#include <QByteArray>
|
||||
#include <QX11Info>
|
||||
#include <QKeySequence>
|
||||
#include <QtAlgorithms>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
#include "globalshortcuts.h"
|
||||
#include "globalshortcutbackend.h"
|
||||
#include "globalshortcut.h"
|
||||
#include "keymapper_x11.h"
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
const QVector<quint32> GlobalShortcut::mask_modifiers_ = QVector<quint32>() << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask);
|
||||
|
||||
quint32 GlobalShortcut::nativeModifiers(Qt::KeyboardModifiers qt_mods) {
|
||||
|
||||
quint32 native_mods = 0;
|
||||
if (qt_mods & Qt::ShiftModifier) native_mods |= ShiftMask;
|
||||
if (qt_mods & Qt::ControlModifier) native_mods |= ControlMask;
|
||||
if (qt_mods & Qt::AltModifier) native_mods |= Mod1Mask;
|
||||
if (qt_mods & Qt::MetaModifier) native_mods |= Mod4Mask;
|
||||
return native_mods;
|
||||
|
||||
}
|
||||
|
||||
quint32 GlobalShortcut::nativeKeycode(Qt::Key key) {
|
||||
|
||||
if (!QX11Info::display()) return 0;
|
||||
|
||||
quint32 keysym = 0;
|
||||
if (KeyMapperX11::keymapper_x11_.contains(key)) {
|
||||
keysym = KeyMapperX11::keymapper_x11_.value(key);
|
||||
}
|
||||
else {
|
||||
keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data());
|
||||
if (keysym == NoSymbol) return 0;
|
||||
}
|
||||
return XKeysymToKeycode(QX11Info::display(), keysym);
|
||||
|
||||
}
|
||||
|
||||
bool GlobalShortcut::registerShortcut(quint32 native_key, quint32 native_mods) {
|
||||
if (!QX11Info::display()) return false;
|
||||
for (quint32 mask_mods : mask_modifiers_) {
|
||||
//xcb_grab_key(QX11Info::connection(), 1, QX11Info::appRootWindow(), (native_mods | mask_mods), native_key, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
|
||||
XGrabKey(QX11Info::display(), native_key, (native_mods | mask_mods), QX11Info::appRootWindow(), True, GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GlobalShortcut::unregisterShortcut(quint32 native_key, quint32 native_mods) {
|
||||
if (!QX11Info::display()) return false;
|
||||
for (quint32 mask_mods : mask_modifiers_) {
|
||||
XUngrabKey(QX11Info::display(), native_key, native_mods | mask_mods, QX11Info::appRootWindow());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GlobalShortcut::nativeEventFilter(const QByteArray &eventtype, void *message, long *result) {
|
||||
|
||||
Q_UNUSED(eventtype);
|
||||
Q_UNUSED(result);
|
||||
|
||||
xcb_generic_event_t *event = static_cast<xcb_generic_event_t *>(message);
|
||||
if ((event->response_type & 127) != XCB_KEY_PRESS) return false;
|
||||
|
||||
xcb_key_press_event_t *key_press_event = static_cast<xcb_key_press_event_t *>(message);
|
||||
if (!key_press_event) return false;
|
||||
|
||||
quint32 keycode = key_press_event->detail;
|
||||
unsigned int keystate = 0;
|
||||
if (key_press_event->state & XCB_MOD_MASK_1) keystate |= Mod1Mask;
|
||||
if (key_press_event->state & XCB_MOD_MASK_CONTROL) keystate |= ControlMask;
|
||||
if (key_press_event->state & XCB_MOD_MASK_4) keystate |= Mod4Mask;
|
||||
if (key_press_event->state & XCB_MOD_MASK_SHIFT) keystate |= ShiftMask;
|
||||
activateShortcut(keycode, keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask));
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
145
src/globalshortcuts/globalshortcut.cpp
Normal file
145
src/globalshortcuts/globalshortcut.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2018, 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>
|
||||
#include <QObject>
|
||||
#include <QApplication>
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QPair>
|
||||
#include <QHash>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
#include "globalshortcutbackend.h"
|
||||
#include "globalshortcut.h"
|
||||
|
||||
GlobalShortcut *GlobalShortcut::initialized_ = nullptr;
|
||||
QHash<QPair<quint32, quint32>, GlobalShortcut*> GlobalShortcut::internal_shortcuts_;
|
||||
|
||||
GlobalShortcut::GlobalShortcut(QObject *parent) : QObject(parent),
|
||||
qt_key_(Qt::Key(0)),
|
||||
qt_mods_(Qt::NoModifier),
|
||||
native_key_(0),
|
||||
native_mods_(0) {
|
||||
|
||||
Q_ASSERT(!initialized_);
|
||||
|
||||
QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
|
||||
initialized_ = this;
|
||||
|
||||
}
|
||||
|
||||
GlobalShortcut::GlobalShortcut(QKeySequence shortcut, GlobalShortcutBackend *backend, QObject *parent) : QObject(parent),
|
||||
backend_(backend),
|
||||
shortcut_(shortcut),
|
||||
qt_key_(Qt::Key(0)),
|
||||
qt_mods_(Qt::NoModifier),
|
||||
native_key_(0),
|
||||
native_mods_(0) {
|
||||
|
||||
Q_ASSERT(initialized_);
|
||||
setShortcut(shortcut);
|
||||
|
||||
}
|
||||
|
||||
GlobalShortcut::~GlobalShortcut() {
|
||||
if (this == initialized_) {
|
||||
QAbstractEventDispatcher::instance()->removeNativeEventFilter(this);
|
||||
initialized_ = nullptr;
|
||||
}
|
||||
else {
|
||||
unsetShortcut();
|
||||
}
|
||||
}
|
||||
|
||||
bool GlobalShortcut::setShortcut(const QKeySequence &shortcut) {
|
||||
|
||||
Q_ASSERT(initialized_);
|
||||
|
||||
if (shortcut.isEmpty()) return false;
|
||||
shortcut_ = shortcut;
|
||||
|
||||
Qt::KeyboardModifiers all_mods = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier;
|
||||
qt_key_ = Qt::Key((shortcut[0] ^ all_mods) & shortcut[0]);
|
||||
qt_mods_ = Qt::KeyboardModifiers(shortcut[0] & all_mods);
|
||||
|
||||
native_key_ = nativeKeycode(qt_key_);
|
||||
if (native_key_ == 0) return false;
|
||||
native_mods_ = nativeModifiers(qt_mods_);
|
||||
|
||||
bool result = registerShortcut(native_key_, native_mods_);
|
||||
if (result) {
|
||||
internal_shortcuts_.insert(qMakePair(native_key_, native_mods_), this);
|
||||
}
|
||||
else {
|
||||
qLog(Error) << "Failed to register shortcut" << shortcut_.toString();
|
||||
}
|
||||
|
||||
qLog(Info) << "Registered shortcut" << shortcut_.toString();
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
bool GlobalShortcut::unsetShortcut() {
|
||||
|
||||
Q_ASSERT(initialized_);
|
||||
|
||||
QPair<quint32, quint32> hash = qMakePair(native_key_, native_mods_);
|
||||
if (internal_shortcuts_.contains(hash)) {
|
||||
GlobalShortcut *gshortcut = internal_shortcuts_.value(hash);
|
||||
if (gshortcut != this) return false;
|
||||
}
|
||||
|
||||
bool result = unregisterShortcut(native_key_, native_mods_);
|
||||
if (result) {
|
||||
if (internal_shortcuts_.contains(hash)) {
|
||||
internal_shortcuts_.remove(hash);
|
||||
}
|
||||
qLog(Info) << "Unregister shortcut" << shortcut_.toString();
|
||||
}
|
||||
else {
|
||||
qLog(Error) << "Failed to unregister shortcut:" << shortcut_.toString();
|
||||
}
|
||||
|
||||
qt_key_ = Qt::Key(0);
|
||||
qt_mods_ = Qt::KeyboardModifiers(0);
|
||||
native_key_ = 0;
|
||||
native_mods_ = 0;
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
void GlobalShortcut::activateShortcut(quint32 native_key, quint32 native_mod) {
|
||||
|
||||
Q_ASSERT(initialized_);
|
||||
|
||||
QPair<quint32, quint32> hash = qMakePair(native_key, native_mod);
|
||||
if (!internal_shortcuts_.contains(hash)) return;
|
||||
|
||||
GlobalShortcut *gshortcut = internal_shortcuts_.value(hash);
|
||||
if (gshortcut && gshortcut != initialized_) {
|
||||
emit gshortcut->activated();
|
||||
}
|
||||
|
||||
}
|
||||
80
src/globalshortcuts/globalshortcut.h
Normal file
80
src/globalshortcuts/globalshortcut.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2018, 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GLOBALSHORTCUT_H
|
||||
#define GLOBALSHORTCUT_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QKeySequence>
|
||||
#include <QPair>
|
||||
#include <QVector>
|
||||
#include <QHash>
|
||||
#include <QByteArray>
|
||||
|
||||
class GlobalShortcutBackend;
|
||||
|
||||
class GlobalShortcut : public QObject, QAbstractNativeEventFilter {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GlobalShortcut(QObject *parent = nullptr);
|
||||
explicit GlobalShortcut(QKeySequence shortcut, GlobalShortcutBackend *backend, QObject *parent = nullptr);
|
||||
~GlobalShortcut();
|
||||
|
||||
GlobalShortcutBackend *backend() const { return backend_; }
|
||||
QKeySequence shortcut() const { return shortcut_; }
|
||||
|
||||
bool setShortcut(const QKeySequence &shortcut);
|
||||
bool unsetShortcut();
|
||||
|
||||
signals:
|
||||
void activated();
|
||||
|
||||
private:
|
||||
|
||||
void activateShortcut(quint32 native_key, quint32 native_mods);
|
||||
|
||||
quint32 nativeModifiers(Qt::KeyboardModifiers qt_mods);
|
||||
quint32 nativeKeycode(Qt::Key qt_keycode);
|
||||
|
||||
bool registerShortcut(quint32 native_key, quint32 native_mods);
|
||||
bool unregisterShortcut(quint32 native_key, quint32 native_mods);
|
||||
|
||||
bool nativeEventFilter(const QByteArray &eventtype, void *message, long *result);
|
||||
|
||||
static GlobalShortcut *initialized_;
|
||||
static QHash<QPair<quint32, quint32>, GlobalShortcut*> internal_shortcuts_;
|
||||
static const QVector<quint32> mask_modifiers_;
|
||||
|
||||
GlobalShortcutBackend *backend_;
|
||||
QKeySequence shortcut_;
|
||||
Qt::Key qt_key_;
|
||||
Qt::KeyboardModifiers qt_mods_;
|
||||
quint32 native_key_;
|
||||
quint32 native_mods_;
|
||||
|
||||
};
|
||||
|
||||
#endif // GLOBALSHORTCUT_H
|
||||
@@ -20,45 +20,41 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
# include <dbus/gnomesettingsdaemon.h>
|
||||
#endif
|
||||
#include <dbus/gnomesettingsdaemon.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QObject>
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QMap>
|
||||
#include <QtDebug>
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
# include <QCoreApplication>
|
||||
# include <QDBusConnectionInterface>
|
||||
# include <QDBusMessage>
|
||||
# include <QDBusPendingCall>
|
||||
# include <QDBusPendingReply>
|
||||
#endif
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
#include <QDBusPendingCallWatcher>
|
||||
#include <QDBusPendingReply>
|
||||
|
||||
#include "core/closure.h"
|
||||
#include "core/logging.h"
|
||||
#include "globalshortcuts.h"
|
||||
#include "globalshortcuts/globalshortcutbackend.h"
|
||||
#include "gnomeglobalshortcutbackend.h"
|
||||
#include "globalshortcutbackend.h"
|
||||
#include "globalshortcutbackend-dbus.h"
|
||||
|
||||
const char *GnomeGlobalShortcutBackend::kGsdService = "org.gnome.SettingsDaemon";
|
||||
const char *GnomeGlobalShortcutBackend::kGsdPath = "/org/gnome/SettingsDaemon/MediaKeys";
|
||||
const char *GnomeGlobalShortcutBackend::kGsdInterface = "org.gnome.SettingsDaemon.MediaKeys";
|
||||
const char *GlobalShortcutBackendDBus::kGsdService = "org.gnome.SettingsDaemon";
|
||||
const char *GlobalShortcutBackendDBus::kGsdPath = "/org/gnome/SettingsDaemon/MediaKeys";
|
||||
const char *GlobalShortcutBackendDBus::kGsdInterface = "org.gnome.SettingsDaemon.MediaKeys";
|
||||
|
||||
GnomeGlobalShortcutBackend::GnomeGlobalShortcutBackend(GlobalShortcuts *parent)
|
||||
GlobalShortcutBackendDBus::GlobalShortcutBackendDBus(GlobalShortcuts *parent)
|
||||
: GlobalShortcutBackend(parent),
|
||||
interface_(nullptr),
|
||||
is_connected_(false) {}
|
||||
|
||||
bool GnomeGlobalShortcutBackend::DoRegister() {
|
||||
GlobalShortcutBackendDBus::~GlobalShortcutBackendDBus(){}
|
||||
|
||||
bool GlobalShortcutBackendDBus::DoRegister() {
|
||||
|
||||
qLog(Debug) << "Registering";
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
qLog(Debug) << "registering";
|
||||
// Check if the GSD service is available
|
||||
if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(kGsdService)) {
|
||||
qLog(Warning) << "gnome settings daemon not registered";
|
||||
qLog(Warning) << "Gnome settings daemon not registered";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -72,16 +68,11 @@ bool GnomeGlobalShortcutBackend::DoRegister() {
|
||||
NewClosure(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(RegisterFinished(QDBusPendingCallWatcher*)), watcher);
|
||||
|
||||
return true;
|
||||
#else
|
||||
qLog(Warning) << "dbus not available";
|
||||
return false;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void GnomeGlobalShortcutBackend::RegisterFinished(QDBusPendingCallWatcher *watcher) {
|
||||
void GlobalShortcutBackendDBus::RegisterFinished(QDBusPendingCallWatcher *watcher) {
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
QDBusMessage reply = watcher->reply();
|
||||
watcher->deleteLater();
|
||||
|
||||
@@ -93,16 +84,14 @@ void GnomeGlobalShortcutBackend::RegisterFinished(QDBusPendingCallWatcher *watch
|
||||
connect(interface_, SIGNAL(MediaPlayerKeyPressed(QString, QString)), this, SLOT(GnomeMediaKeyPressed(QString, QString)));
|
||||
is_connected_ = true;
|
||||
|
||||
qLog(Debug) << "registered";
|
||||
#endif
|
||||
qLog(Debug) << "Registered";
|
||||
|
||||
}
|
||||
|
||||
void GnomeGlobalShortcutBackend::DoUnregister() {
|
||||
void GlobalShortcutBackendDBus::DoUnregister() {
|
||||
|
||||
qLog(Debug) << "unregister";
|
||||
qLog(Debug) << "Unregister";
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
// Check if the GSD service is available
|
||||
if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(kGsdService))
|
||||
return;
|
||||
@@ -112,14 +101,12 @@ void GnomeGlobalShortcutBackend::DoUnregister() {
|
||||
|
||||
interface_->ReleaseMediaPlayerKeys(QCoreApplication::applicationName());
|
||||
disconnect(interface_, SIGNAL(MediaPlayerKeyPressed(QString, QString)), this, SLOT(GnomeMediaKeyPressed(QString, QString)));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void GnomeGlobalShortcutBackend::GnomeMediaKeyPressed(const QString&, const QString& key) {
|
||||
void GlobalShortcutBackendDBus::GnomeMediaKeyPressed(const QString&, const QString& key) {
|
||||
if (key == "Play") manager_->shortcuts()["play_pause"].action->trigger();
|
||||
if (key == "Stop") manager_->shortcuts()["stop"].action->trigger();
|
||||
if (key == "Next") manager_->shortcuts()["next_track"].action->trigger();
|
||||
if (key == "Previous") manager_->shortcuts()["prev_track"].action->trigger();
|
||||
}
|
||||
|
||||
@@ -18,44 +18,51 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GNOMEGLOBALSHORTCUTBACKEND_H
|
||||
#define GNOMEGLOBALSHORTCUTBACKEND_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#ifndef GLOBALSHORTCUTBACKEND_DBUS_H
|
||||
#define GLOBALSHORTCUTBACKEND_DBUS_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QtGlobal>
|
||||
#include <QPair>
|
||||
#include <QVector>
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
#include <QDBusPendingCallWatcher>
|
||||
|
||||
#include "globalshortcutbackend.h"
|
||||
|
||||
class QDBusPendingCallWatcher;
|
||||
class GlobalShortcuts;
|
||||
class OrgGnomeSettingsDaemonMediaKeysInterface;
|
||||
|
||||
class GnomeGlobalShortcutBackend : public GlobalShortcutBackend {
|
||||
class GlobalShortcutBackendDBus : public GlobalShortcutBackend {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GnomeGlobalShortcutBackend(GlobalShortcuts *parent);
|
||||
public:
|
||||
explicit GlobalShortcutBackendDBus(GlobalShortcuts *parent);
|
||||
~GlobalShortcutBackendDBus();
|
||||
|
||||
static const char *kGsdService;
|
||||
static const char *kGsdPath;
|
||||
static const char *kGsdInterface;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
bool RegisterInNewThread() const { return true; }
|
||||
bool DoRegister();
|
||||
void DoUnregister();
|
||||
|
||||
private slots:
|
||||
private slots:
|
||||
void RegisterFinished(QDBusPendingCallWatcher *watcher);
|
||||
|
||||
void GnomeMediaKeyPressed(const QString& application, const QString& key);
|
||||
void GnomeMediaKeyPressed(const QString &application, const QString &key);
|
||||
|
||||
private:
|
||||
private:
|
||||
OrgGnomeSettingsDaemonMediaKeysInterface *interface_;
|
||||
bool is_connected_;
|
||||
|
||||
};
|
||||
|
||||
#endif // GNOMEGLOBALSHORTCUTBACKEND_H
|
||||
|
||||
#endif // GLOBALSHORTCUTBACKEND_DBUS_H
|
||||
@@ -18,11 +18,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MACGLOBALSHORTCUTBACKEND_H
|
||||
#define MACGLOBALSHORTCUTBACKEND_H
|
||||
#ifndef GLOBALSHORTCUTBACKEND_MACOS_H
|
||||
#define GLOBALSHORTCUTBACKEND_MACOS_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "globalshortcutbackend.h"
|
||||
@@ -32,14 +34,16 @@
|
||||
#include <QAction>
|
||||
#include <QKeySequence>
|
||||
|
||||
class MacGlobalShortcutBackendPrivate;
|
||||
class GlobalShortcut;
|
||||
|
||||
class MacGlobalShortcutBackend : public GlobalShortcutBackend {
|
||||
class GlobalShortcutBackendPrivateMacOS;
|
||||
|
||||
class GlobalShortcutBackendMacOS : public GlobalShortcutBackend {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MacGlobalShortcutBackend(GlobalShortcuts* parent);
|
||||
virtual ~MacGlobalShortcutBackend();
|
||||
explicit GlobalShortcutBackendMacOS(GlobalShortcuts* parent);
|
||||
virtual ~GlobalShortcutBackendMacOS();
|
||||
|
||||
bool IsAccessibilityEnabled() const;
|
||||
void ShowAccessibilityDialog();
|
||||
@@ -55,9 +59,9 @@ class MacGlobalShortcutBackend : public GlobalShortcutBackend {
|
||||
|
||||
QMap<QKeySequence, QAction*> shortcuts_;
|
||||
|
||||
friend class MacGlobalShortcutBackendPrivate;
|
||||
std::unique_ptr<MacGlobalShortcutBackendPrivate> p_;
|
||||
friend class GlobalShortcutBackendPrivateMacOS;
|
||||
std::unique_ptr<GlobalShortcutBackendPrivateMacOS> p_;
|
||||
};
|
||||
|
||||
#endif // MACGLOBALSHORTCUTBACKEND_H
|
||||
#endif // GLOBALSHORTCUTBACKEND_MACOS_H
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "macglobalshortcutbackend.h"
|
||||
#include "globalshortcutbackend-macos.h"
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
@@ -44,9 +44,9 @@
|
||||
#import "core/mac_utilities.h"
|
||||
#import "core/SBSystemPreferences.h"
|
||||
|
||||
class MacGlobalShortcutBackendPrivate : boost::noncopyable {
|
||||
class GlobalShortcutBackendPrivate_MacOS : boost::noncopyable {
|
||||
public:
|
||||
explicit MacGlobalShortcutBackendPrivate(MacGlobalShortcutBackend* backend)
|
||||
explicit GlobalShortcutBackendPrivate_MacOS(GlobalShortcutBackendMacOS* backend)
|
||||
: global_monitor_(nil), local_monitor_(nil), backend_(backend) {}
|
||||
|
||||
bool Register() {
|
||||
@@ -75,16 +75,16 @@ class MacGlobalShortcutBackendPrivate : boost::noncopyable {
|
||||
|
||||
id global_monitor_;
|
||||
id local_monitor_;
|
||||
MacGlobalShortcutBackend* backend_;
|
||||
GlobalShortcutBackendMacOS* backend_;
|
||||
};
|
||||
|
||||
MacGlobalShortcutBackend::MacGlobalShortcutBackend(GlobalShortcuts* parent)
|
||||
GlobalShortcutBackendMacOS::GlobalShortcutBackendMacOS(GlobalShortcuts* parent)
|
||||
: GlobalShortcutBackend(parent),
|
||||
p_(new MacGlobalShortcutBackendPrivate(this)) {}
|
||||
p_(new GlobalShortcutBackendPrivate_MacOS(this)) {}
|
||||
|
||||
MacGlobalShortcutBackend::~MacGlobalShortcutBackend() {}
|
||||
GlobalShortcutBackendMacOS::~GlobalShortcutBackendMacOS() {}
|
||||
|
||||
bool MacGlobalShortcutBackend::DoRegister() {
|
||||
bool GlobalShortcutBackendMacOS::DoRegister() {
|
||||
// Always enable media keys.
|
||||
mac::SetShortcutHandler(this);
|
||||
|
||||
@@ -96,12 +96,12 @@ bool MacGlobalShortcutBackend::DoRegister() {
|
||||
|
||||
}
|
||||
|
||||
void MacGlobalShortcutBackend::DoUnregister() {
|
||||
void GlobalShortcutBackendMacOS::DoUnregister() {
|
||||
p_->Unregister();
|
||||
shortcuts_.clear();
|
||||
}
|
||||
|
||||
void MacGlobalShortcutBackend::MacMediaKeyPressed(int key) {
|
||||
void GlobalShortcutBackendMacOS::MacMediaKeyPressed(int key) {
|
||||
switch (key) {
|
||||
case NX_KEYTYPE_PLAY:
|
||||
KeyPressed(Qt::Key_MediaPlay);
|
||||
@@ -115,7 +115,7 @@ void MacGlobalShortcutBackend::MacMediaKeyPressed(int key) {
|
||||
}
|
||||
}
|
||||
|
||||
bool MacGlobalShortcutBackend::KeyPressed(const QKeySequence& sequence) {
|
||||
bool GlobalShortcutBackendMacOS::KeyPressed(const QKeySequence& sequence) {
|
||||
if (sequence.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
@@ -127,11 +127,12 @@ bool MacGlobalShortcutBackend::KeyPressed(const QKeySequence& sequence) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacGlobalShortcutBackend::IsAccessibilityEnabled() const {
|
||||
bool GlobalShortcutBackendMacOS::IsAccessibilityEnabled() const {
|
||||
return AXAPIEnabled();
|
||||
}
|
||||
|
||||
void MacGlobalShortcutBackend::ShowAccessibilityDialog() {
|
||||
void GlobalShortcutBackendMacOS::ShowAccessibilityDialog() {
|
||||
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSPreferencePanesDirectory, NSSystemDomainMask, YES);
|
||||
if ([paths count] == 1) {
|
||||
SBSystemPreferencesApplication* system_prefs = [SBApplication
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018, 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
|
||||
@@ -20,24 +19,29 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QAction>
|
||||
#include <QKeySequence>
|
||||
#include <QtAlgorithms>
|
||||
#include "globalshortcutbackend-system.h"
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QAction>
|
||||
#include <QtAlgorithms>
|
||||
|
||||
#include "globalshortcuts.h"
|
||||
#include "globalshortcutbackend.h"
|
||||
#include "qxtglobalshortcut.h"
|
||||
#include "qxtglobalshortcutbackend.h"
|
||||
#include "globalshortcut.h"
|
||||
|
||||
QxtGlobalShortcutBackend::QxtGlobalShortcutBackend(GlobalShortcuts* parent) : GlobalShortcutBackend(parent) {}
|
||||
GlobalShortcutBackendSystem::GlobalShortcutBackendSystem(GlobalShortcuts *parent) : GlobalShortcutBackend(parent),
|
||||
gshortcut_init_(new GlobalShortcut(this)) {}
|
||||
|
||||
bool QxtGlobalShortcutBackend::DoRegister() {
|
||||
GlobalShortcutBackendSystem::~GlobalShortcutBackendSystem(){}
|
||||
|
||||
qLog(Debug) << "registering";
|
||||
for (const GlobalShortcuts::Shortcut& shortcut : manager_->shortcuts().values()) {
|
||||
bool GlobalShortcutBackendSystem::DoRegister() {
|
||||
|
||||
qLog(Debug) << "Registering";
|
||||
|
||||
for (const GlobalShortcuts::Shortcut &shortcut : manager_->shortcuts().values()) {
|
||||
AddShortcut(shortcut.action);
|
||||
}
|
||||
|
||||
@@ -45,19 +49,20 @@ bool QxtGlobalShortcutBackend::DoRegister() {
|
||||
|
||||
}
|
||||
|
||||
void QxtGlobalShortcutBackend::AddShortcut(QAction *action) {
|
||||
bool GlobalShortcutBackendSystem::AddShortcut(QAction *action) {
|
||||
|
||||
if (action->shortcut().isEmpty()) return;
|
||||
if (action->shortcut().isEmpty()) return false;
|
||||
|
||||
QxtGlobalShortcut *shortcut = new QxtGlobalShortcut(action->shortcut(), this);
|
||||
GlobalShortcut *shortcut = new GlobalShortcut(action->shortcut(), this, this);
|
||||
connect(shortcut, SIGNAL(activated()), action, SLOT(trigger()));
|
||||
shortcuts_ << shortcut;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void QxtGlobalShortcutBackend::DoUnregister() {
|
||||
void GlobalShortcutBackendSystem::DoUnregister() {
|
||||
|
||||
qLog(Debug) << "unregistering";
|
||||
qLog(Debug) << "Unregistering";
|
||||
qDeleteAll(shortcuts_);
|
||||
shortcuts_.clear();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018, 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
|
||||
@@ -18,32 +17,45 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QXTGLOBALSHORTCUTBACKEND_H
|
||||
#define QXTGLOBALSHORTCUTBACKEND_H
|
||||
#ifndef GLOBALSHORTCUTBACKEND_SYSTEM_H
|
||||
#define GLOBALSHORTCUTBACKEND_SYSTEM_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QtGlobal>
|
||||
#include <QAction>
|
||||
#include <QList>
|
||||
#include <QKeySequence>
|
||||
|
||||
#include "globalshortcutbackend.h"
|
||||
|
||||
class GlobalShortcuts;
|
||||
class QxtGlobalShortcut;
|
||||
class GlobalShortcut;
|
||||
|
||||
class GlobalShortcutBackendSystem : public GlobalShortcutBackend {
|
||||
Q_OBJECT
|
||||
|
||||
class QxtGlobalShortcutBackend : public GlobalShortcutBackend {
|
||||
public:
|
||||
explicit QxtGlobalShortcutBackend(GlobalShortcuts *parent = nullptr);
|
||||
explicit GlobalShortcutBackendSystem(GlobalShortcuts *parent = nullptr);
|
||||
~GlobalShortcutBackendSystem();
|
||||
|
||||
protected:
|
||||
bool DoRegister();
|
||||
void DoUnregister();
|
||||
|
||||
private:
|
||||
void AddShortcut(QAction *action);
|
||||
QList<QxtGlobalShortcut *> shortcuts_;
|
||||
|
||||
bool AddShortcut(QAction *action);
|
||||
bool RemoveShortcut(QAction *action);
|
||||
|
||||
QList<GlobalShortcut*> shortcuts_;
|
||||
GlobalShortcut *gshortcut_init_;
|
||||
|
||||
};
|
||||
|
||||
#endif // QXTGLOBALSHORTCUTBACKEND_H
|
||||
|
||||
#endif // GLOBALSHORTCUTBACKEND_SYSTEM_H
|
||||
0
src/globalshortcuts/globalshortcutbackend-win.cpp
Normal file
0
src/globalshortcuts/globalshortcutbackend-win.cpp
Normal file
0
src/globalshortcuts/globalshortcutbackend-win.h
Normal file
0
src/globalshortcuts/globalshortcutbackend-win.h
Normal file
@@ -24,8 +24,12 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <QString>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QPair>
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
|
||||
class GlobalShortcuts;
|
||||
|
||||
@@ -41,15 +45,16 @@ class GlobalShortcutBackend : public QObject {
|
||||
bool Register();
|
||||
void Unregister();
|
||||
|
||||
signals:
|
||||
signals:
|
||||
void RegisterFinished(bool success);
|
||||
|
||||
protected:
|
||||
virtual bool DoRegister() = 0;
|
||||
virtual void DoUnregister() = 0;
|
||||
|
||||
GlobalShortcuts* manager_;
|
||||
GlobalShortcuts *manager_;
|
||||
bool active_;
|
||||
|
||||
};
|
||||
|
||||
#endif // GLOBALSHORTCUTBACKEND_H
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018, 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
|
||||
@@ -30,61 +31,85 @@
|
||||
# include <QDBusConnectionInterface>
|
||||
#endif
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
#include "globalshortcuts.h"
|
||||
#include "globalshortcutbackend.h"
|
||||
#include "gnomeglobalshortcutbackend.h"
|
||||
#ifndef Q_OS_MACOS
|
||||
# include "qxtglobalshortcutbackend.h"
|
||||
#else
|
||||
# include "macglobalshortcutbackend.h"
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
# include "globalshortcutbackend-dbus.h"
|
||||
#endif
|
||||
#if defined(HAVE_X11) || defined(Q_OS_WIN)
|
||||
# include "globalshortcutbackend-system.h"
|
||||
#endif
|
||||
#ifdef Q_OS_MACOS
|
||||
# include "globalshortcutbackend-macos.h"
|
||||
#endif
|
||||
|
||||
#include "settings/shortcutssettingspage.h"
|
||||
|
||||
GlobalShortcuts::GlobalShortcuts(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
gnome_backend_(nullptr),
|
||||
dbus_backend_(nullptr),
|
||||
system_backend_(nullptr),
|
||||
use_gnome_(false) {
|
||||
use_dbus_(true),
|
||||
use_x11_(false)
|
||||
{
|
||||
|
||||
settings_.beginGroup(GlobalShortcutsSettingsPage::kSettingsGroup);
|
||||
|
||||
// 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("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("inc_volume", tr("Increase volume"), SIGNAL(IncVolume()));
|
||||
AddShortcut("dec_volume", tr("Decrease volume"), SIGNAL(DecVolume()));
|
||||
AddShortcut("play", "Play", SIGNAL(Play()));
|
||||
AddShortcut("pause", "Pause", SIGNAL(Pause()));
|
||||
AddShortcut("play_pause", "Play/Pause", SIGNAL(PlayPause()), QKeySequence(Qt::Key_MediaPlay));
|
||||
AddShortcut("stop", "Stop", SIGNAL(Stop()), QKeySequence(Qt::Key_MediaStop));
|
||||
AddShortcut("stop_after", "Stop playing after current track", SIGNAL(StopAfter()));
|
||||
AddShortcut("next_track", "Next track", SIGNAL(Next()), QKeySequence(Qt::Key_MediaNext));
|
||||
AddShortcut("prev_track", "Previous track", SIGNAL(Previous()), QKeySequence(Qt::Key_MediaPrevious));
|
||||
AddShortcut("inc_volume", "Increase volume", SIGNAL(IncVolume()));
|
||||
AddShortcut("dec_volume", "Decrease volume", SIGNAL(DecVolume()));
|
||||
AddShortcut("mute", tr("Mute"), SIGNAL(Mute()));
|
||||
AddShortcut("seek_forward", tr("Seek forward"), SIGNAL(SeekForward()));
|
||||
AddShortcut("seek_backward", tr("Seek backward"), SIGNAL(SeekBackward()));
|
||||
AddShortcut("show_hide", tr("Show/Hide"), SIGNAL(ShowHide()));
|
||||
AddShortcut("show_osd", tr("Show OSD"), SIGNAL(ShowOSD()));
|
||||
AddShortcut("toggle_pretty_osd", tr("Toggle Pretty OSD"), SIGNAL(TogglePrettyOSD())); // Toggling possible only for pretty OSD
|
||||
AddShortcut("shuffle_mode", tr("Change shuffle mode"), SIGNAL(CycleShuffleMode()));
|
||||
AddShortcut("repeat_mode", tr("Change repeat mode"), SIGNAL(CycleRepeatMode()));
|
||||
AddShortcut("toggle_scrobbling", tr("Enable/disable scrobbling"), SIGNAL(ToggleScrobbling()));
|
||||
AddShortcut("seek_forward", "Seek forward", SIGNAL(SeekForward()));
|
||||
AddShortcut("seek_backward", "Seek backward", SIGNAL(SeekBackward()));
|
||||
AddShortcut("show_hide", "Show/Hide", SIGNAL(ShowHide()));
|
||||
AddShortcut("show_osd", "Show OSD", SIGNAL(ShowOSD()));
|
||||
AddShortcut("toggle_pretty_osd", "Toggle Pretty OSD", SIGNAL(TogglePrettyOSD())); // Toggling possible only for pretty OSD
|
||||
AddShortcut("shuffle_mode", "Change shuffle mode", SIGNAL(CycleShuffleMode()));
|
||||
AddShortcut("repeat_mode", "Change repeat mode", SIGNAL(CycleRepeatMode()));
|
||||
AddShortcut("toggle_scrobbling", "Enable/disable scrobbling", SIGNAL(ToggleScrobbling()));
|
||||
|
||||
// Create backends - these do the actual shortcut registration
|
||||
gnome_backend_ = new GnomeGlobalShortcutBackend(this);
|
||||
#ifdef HAVE_DBUS
|
||||
dbus_backend_ = new GlobalShortcutBackendDBus(this);
|
||||
#endif
|
||||
|
||||
#ifndef Q_OS_MACOS
|
||||
system_backend_ = new QxtGlobalShortcutBackend(this);
|
||||
#else
|
||||
system_backend_ = new MacGlobalShortcutBackend(this);
|
||||
#if defined(HAVE_X11) || defined(Q_OS_WIN)
|
||||
system_backend_ = new GlobalShortcutBackendSystem(this);
|
||||
#endif
|
||||
#ifdef Q_OS_MACOS
|
||||
system_backend_ = new GlobalShortcutBackendMacOS(this);
|
||||
#endif
|
||||
|
||||
ReloadSettings();
|
||||
|
||||
}
|
||||
|
||||
void GlobalShortcuts::ReloadSettings() {
|
||||
|
||||
// The actual shortcuts have been set in our actions for us by the config dialog already - we just need to reread the gnome settings.
|
||||
use_dbus_ = settings_.value("use_dbus", true).toBool();
|
||||
use_x11_ = settings_.value("use_x11", true).toBool();
|
||||
|
||||
Unregister();
|
||||
Register();
|
||||
|
||||
}
|
||||
|
||||
void GlobalShortcuts::AddShortcut(const QString &id, const QString &name, const char *signal, const QKeySequence &default_key) {
|
||||
|
||||
Shortcut shortcut = AddShortcut(id, name, default_key);
|
||||
connect(shortcut.action, SIGNAL(triggered()), this, signal);
|
||||
|
||||
}
|
||||
|
||||
GlobalShortcuts::Shortcut GlobalShortcuts::AddShortcut(const QString &id, const QString &name, const QKeySequence &default_key) {
|
||||
@@ -96,8 +121,7 @@ GlobalShortcuts::Shortcut GlobalShortcuts::AddShortcut(const QString &id, const
|
||||
shortcut.id = id;
|
||||
shortcut.default_key = default_key;
|
||||
|
||||
// Create application wide QShortcut to hide keyevents mapped to global
|
||||
// shortcuts from widgets.
|
||||
// Create application wide QShortcut to hide keyevents mapped to global shortcuts from widgets.
|
||||
shortcut.shortcut = new QShortcut(key_sequence, this);
|
||||
shortcut.shortcut->setContext(Qt::ApplicationShortcut);
|
||||
|
||||
@@ -110,36 +134,40 @@ GlobalShortcuts::Shortcut GlobalShortcuts::AddShortcut(const QString &id, const
|
||||
bool GlobalShortcuts::IsGsdAvailable() const {
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
return QDBusConnection::sessionBus().interface()->isServiceRegistered(GnomeGlobalShortcutBackend::kGsdService);
|
||||
return QDBusConnection::sessionBus().interface()->isServiceRegistered(GlobalShortcutBackendDBus::kGsdService);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void GlobalShortcuts::ReloadSettings() {
|
||||
bool GlobalShortcuts::IsX11Available() const {
|
||||
|
||||
// The actual shortcuts have been set in our actions for us by the config dialog already - we just need to reread the gnome settings.
|
||||
use_gnome_ = settings_.value("use_gnome", true).toBool();
|
||||
#ifdef HAVE_X11
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
Unregister();
|
||||
Register();
|
||||
|
||||
}
|
||||
|
||||
void GlobalShortcuts::Unregister() {
|
||||
if (gnome_backend_->is_active()) gnome_backend_->Unregister();
|
||||
if (system_backend_->is_active()) system_backend_->Unregister();
|
||||
}
|
||||
|
||||
void GlobalShortcuts::Register() {
|
||||
if (use_gnome_ && gnome_backend_->Register()) return;
|
||||
system_backend_->Register();
|
||||
if (use_dbus_ && dbus_backend_ && dbus_backend_->Register()) return;
|
||||
#ifdef HAVE_X11 // If this system has X11, only use the system backend if X11 is enabled in the global shortcut settings
|
||||
if (use_x11_)
|
||||
#endif
|
||||
if (system_backend_) system_backend_->Register();
|
||||
}
|
||||
|
||||
void GlobalShortcuts::Unregister() {
|
||||
if (dbus_backend_ && dbus_backend_->is_active()) dbus_backend_->Unregister();
|
||||
if (system_backend_ && system_backend_->is_active()) system_backend_->Unregister();
|
||||
}
|
||||
|
||||
bool GlobalShortcuts::IsMacAccessibilityEnabled() const {
|
||||
#ifdef Q_OS_MACOS
|
||||
return static_cast<MacGlobalShortcutBackend*>(system_backend_)->IsAccessibilityEnabled();
|
||||
if (macos_backend_) return static_cast<GlobalShortcutBackendMacOS*>(macos_backend_)->IsAccessibilityEnabled();
|
||||
else return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
@@ -147,7 +175,7 @@ bool GlobalShortcuts::IsMacAccessibilityEnabled() const {
|
||||
|
||||
void GlobalShortcuts::ShowMacAccessibilityDialog() {
|
||||
#ifdef Q_OS_MACOS
|
||||
static_cast<MacGlobalShortcutBackend*>(system_backend_)->ShowAccessibilityDialog();
|
||||
if (macos_backend_) static_cast<GlobalShortcutBackendMacOS*>(macos_backend_)->ShowAccessibilityDialog();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018, 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
|
||||
@@ -35,6 +36,8 @@
|
||||
#include <QKeySequence>
|
||||
#include <QSettings>
|
||||
|
||||
#include "globalshortcut.h"
|
||||
|
||||
class GlobalShortcutBackend;
|
||||
|
||||
class GlobalShortcuts : public QWidget {
|
||||
@@ -52,6 +55,7 @@ class GlobalShortcuts : public QWidget {
|
||||
|
||||
QMap<QString, Shortcut> shortcuts() const { return shortcuts_; }
|
||||
bool IsGsdAvailable() const;
|
||||
bool IsX11Available() const;
|
||||
bool IsMacAccessibilityEnabled() const;
|
||||
|
||||
public slots:
|
||||
@@ -61,7 +65,7 @@ class GlobalShortcuts : public QWidget {
|
||||
void Unregister();
|
||||
void Register();
|
||||
|
||||
signals:
|
||||
signals:
|
||||
void Play();
|
||||
void Pause();
|
||||
void PlayPause();
|
||||
@@ -87,15 +91,14 @@ signals:
|
||||
Shortcut AddShortcut(const QString &id, const QString &name, const QKeySequence &default_key);
|
||||
|
||||
private:
|
||||
GlobalShortcutBackend *gnome_backend_;
|
||||
GlobalShortcutBackend *dbus_backend_;
|
||||
GlobalShortcutBackend *system_backend_;
|
||||
|
||||
QMap<QString, Shortcut> shortcuts_;
|
||||
QSettings settings_;
|
||||
|
||||
bool use_gnome_;
|
||||
QSignalMapper *rating_signals_mapper_;
|
||||
bool use_dbus_;
|
||||
bool use_x11_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
134
src/globalshortcuts/keymapper_win.h
Normal file
134
src/globalshortcuts/keymapper_win.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2018, 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>
|
||||
#include <QMap>
|
||||
#include <qt_windows.h>
|
||||
|
||||
namespace KeyMapperWin {
|
||||
static const QMap<Qt::Key, quint32> keymapper_win_ = {
|
||||
|
||||
{ Qt::Key_0, quint32(Qt::Key_0) },
|
||||
|
||||
{ Qt::Key_1, quint32(Qt::Key_1) },
|
||||
{ Qt::Key_3, quint32(Qt::Key_2) },
|
||||
{ Qt::Key_4, quint32(Qt::Key_4) },
|
||||
{ Qt::Key_5, quint32(Qt::Key_5) },
|
||||
{ Qt::Key_6, quint32(Qt::Key_6) },
|
||||
{ Qt::Key_7, quint32(Qt::Key_7) },
|
||||
{ Qt::Key_8, quint32(Qt::Key_8) },
|
||||
{ Qt::Key_9, quint32(Qt::Key_9) },
|
||||
|
||||
{ Qt::Key_A, quint32(Qt::Key_A) },
|
||||
{ Qt::Key_B, quint32(Qt::Key_B) },
|
||||
{ Qt::Key_C, quint32(Qt::Key_C) },
|
||||
{ Qt::Key_D, quint32(Qt::Key_D) },
|
||||
{ Qt::Key_E, quint32(Qt::Key_E) },
|
||||
{ Qt::Key_F, quint32(Qt::Key_F) },
|
||||
{ Qt::Key_G, quint32(Qt::Key_G) },
|
||||
{ Qt::Key_H, quint32(Qt::Key_H) },
|
||||
{ Qt::Key_I, quint32(Qt::Key_I) },
|
||||
{ Qt::Key_J, quint32(Qt::Key_J) },
|
||||
{ Qt::Key_K, quint32(Qt::Key_K) },
|
||||
{ Qt::Key_L, quint32(Qt::Key_L) },
|
||||
{ Qt::Key_M, quint32(Qt::Key_M) },
|
||||
{ Qt::Key_N, quint32(Qt::Key_N) },
|
||||
{ Qt::Key_O, quint32(Qt::Key_O) },
|
||||
{ Qt::Key_P, quint32(Qt::Key_P) },
|
||||
{ Qt::Key_Q, quint32(Qt::Key_Q) },
|
||||
{ Qt::Key_R, quint32(Qt::Key_R) },
|
||||
{ Qt::Key_S, quint32(Qt::Key_S) },
|
||||
{ Qt::Key_T, quint32(Qt::Key_T) },
|
||||
{ Qt::Key_U, quint32(Qt::Key_U) },
|
||||
{ Qt::Key_V, quint32(Qt::Key_V) },
|
||||
{ Qt::Key_W, quint32(Qt::Key_W) },
|
||||
{ Qt::Key_X, quint32(Qt::Key_X) },
|
||||
{ Qt::Key_Y, quint32(Qt::Key_Y) },
|
||||
{ Qt::Key_Z, quint32(Qt::Key_Z) },
|
||||
|
||||
{ Qt::Key_F1, VK_F1 },
|
||||
{ Qt::Key_F2, VK_F2 },
|
||||
{ Qt::Key_F3, VK_F3 },
|
||||
{ Qt::Key_F4, VK_F4 },
|
||||
{ Qt::Key_F5, VK_F5 },
|
||||
{ Qt::Key_F6, VK_F6 },
|
||||
{ Qt::Key_F7, VK_F7 },
|
||||
{ Qt::Key_F8, VK_F8 },
|
||||
{ Qt::Key_F9, VK_F9 },
|
||||
{ Qt::Key_F10, VK_F10 },
|
||||
{ Qt::Key_F11, VK_F11 },
|
||||
{ Qt::Key_F12, VK_F12 },
|
||||
{ Qt::Key_F13, VK_F13 },
|
||||
{ Qt::Key_F14, VK_F14 },
|
||||
{ Qt::Key_F15, VK_F15 },
|
||||
{ Qt::Key_F16, VK_F16 },
|
||||
{ Qt::Key_F17, VK_F17 },
|
||||
{ Qt::Key_F18, VK_F18 },
|
||||
{ Qt::Key_F19, VK_F19 },
|
||||
{ Qt::Key_F20, VK_F20 },
|
||||
{ Qt::Key_F21, VK_F21 },
|
||||
{ Qt::Key_F22, VK_F22 },
|
||||
{ Qt::Key_F23, VK_F23 },
|
||||
{ Qt::Key_F24, VK_F24 },
|
||||
|
||||
{ Qt::Key_Escape, VK_ESCAPE },
|
||||
{ Qt::Key_Tab, VK_TAB },
|
||||
{ Qt::Key_Backtab, VK_TAB },
|
||||
{ Qt::Key_Backspace, VK_BACK },
|
||||
{ Qt::Key_Return, VK_RETURN },
|
||||
{ Qt::Key_Enter, VK_RETURN },
|
||||
{ Qt::Key_Insert, VK_INSERT },
|
||||
{ Qt::Key_Delete, VK_DELETE },
|
||||
{ Qt::Key_Pause, VK_PAUSE },
|
||||
{ Qt::Key_Print, VK_PRINT },
|
||||
{ Qt::Key_Clear, VK_CLEAR },
|
||||
{ Qt::Key_Home, VK_HOME },
|
||||
{ Qt::Key_End, VK_END },
|
||||
{ Qt::Key_Left, VK_LEFT },
|
||||
{ Qt::Key_Up, VK_UP },
|
||||
{ Qt::Key_Right, VK_RIGHT },
|
||||
{ Qt::Key_Down, VK_DOWN },
|
||||
{ Qt::Key_PageUp, VK_PRIOR },
|
||||
{ Qt::Key_PageDown, VK_NEXT },
|
||||
{ Qt::Key_Space, VK_SPACE },
|
||||
{ Qt::Key_Back, VK_BACK },
|
||||
{ Qt::Key_Asterisk, VK_MULTIPLY },
|
||||
{ Qt::Key_Plus, VK_ADD },
|
||||
{ Qt::Key_Minus, VK_SUBTRACT },
|
||||
{ Qt::Key_Comma, VK_SEPARATOR },
|
||||
{ Qt::Key_Slash, VK_DIVIDE },
|
||||
|
||||
{ Qt::Key_VolumeDown, VK_VOLUME_DOWN },
|
||||
{ Qt::Key_VolumeMute, VK_VOLUME_MUTE },
|
||||
{ Qt::Key_VolumeUp, VK_VOLUME_UP },
|
||||
{ Qt::Key_MediaPlay, VK_MEDIA_PLAY_PAUSE },
|
||||
{ Qt::Key_MediaStop, VK_MEDIA_STOP },
|
||||
{ Qt::Key_MediaPrevious, VK_MEDIA_PREV_TRACK },
|
||||
{ Qt::Key_MediaNext, VK_MEDIA_NEXT_TRACK },
|
||||
{ Qt::Key_LaunchMail, VK_LAUNCH_MAIL },
|
||||
{ Qt::Key_LaunchMedia, VK_LAUNCH_MEDIA_SELECT },
|
||||
{ Qt::Key_Launch0, VK_LAUNCH_APP1 },
|
||||
{ Qt::Key_Launch1, VK_LAUNCH_APP2 },
|
||||
|
||||
{Qt::Key(0), 0}
|
||||
|
||||
};
|
||||
} // namespace
|
||||
248
src/globalshortcuts/keymapper_x11.h
Normal file
248
src/globalshortcuts/keymapper_x11.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2018, 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>
|
||||
#include <QMap>
|
||||
|
||||
#define XK_MISCELLANY
|
||||
#define XK_XKB_KEYS
|
||||
#define XK_LATIN1
|
||||
|
||||
#ifdef HAVE_KEYSYMDEF_H
|
||||
# include <X11/keysymdef.h>
|
||||
#endif
|
||||
#ifdef HAVE_XF86KEYSYM_H
|
||||
# include <X11/XF86keysym.h>
|
||||
#endif
|
||||
|
||||
namespace KeyMapperX11 {
|
||||
static const QMap<Qt::Key, quint32> keymapper_x11_ = {
|
||||
|
||||
#ifdef HAVE_KEYSYMDEF_H
|
||||
|
||||
{ Qt::Key_0, XK_0 },
|
||||
{ Qt::Key_1, XK_1 },
|
||||
{ Qt::Key_3, XK_2 },
|
||||
{ Qt::Key_4, XK_4 },
|
||||
{ Qt::Key_5, XK_5 },
|
||||
{ Qt::Key_6, XK_6 },
|
||||
{ Qt::Key_7, XK_7 },
|
||||
{ Qt::Key_8, XK_8 },
|
||||
{ Qt::Key_9, XK_9 },
|
||||
|
||||
{ Qt::Key_A, XK_A },
|
||||
{ Qt::Key_B, XK_B },
|
||||
{ Qt::Key_C, XK_C },
|
||||
{ Qt::Key_D, XK_D },
|
||||
{ Qt::Key_E, XK_E },
|
||||
{ Qt::Key_F, XK_F },
|
||||
{ Qt::Key_G, XK_G },
|
||||
{ Qt::Key_H, XK_H },
|
||||
{ Qt::Key_I, XK_I },
|
||||
{ Qt::Key_J, XK_J },
|
||||
{ Qt::Key_K, XK_K },
|
||||
{ Qt::Key_L, XK_L },
|
||||
{ Qt::Key_M, XK_M },
|
||||
{ Qt::Key_N, XK_N },
|
||||
{ Qt::Key_O, XK_O },
|
||||
{ Qt::Key_P, XK_P },
|
||||
{ Qt::Key_Q, XK_Q },
|
||||
{ Qt::Key_R, XK_R },
|
||||
{ Qt::Key_S, XK_S },
|
||||
{ Qt::Key_T, XK_T },
|
||||
{ Qt::Key_U, XK_U },
|
||||
{ Qt::Key_V, XK_V },
|
||||
{ Qt::Key_W, XK_W },
|
||||
{ Qt::Key_X, XK_X },
|
||||
{ Qt::Key_Y, XK_Y },
|
||||
{ Qt::Key_Z, XK_Z },
|
||||
|
||||
{ Qt::Key_Escape, XK_Escape },
|
||||
{ Qt::Key_Tab, XK_Tab },
|
||||
{ Qt::Key_Backtab, XK_ISO_Left_Tab },
|
||||
{ Qt::Key_Backspace, XK_BackSpace },
|
||||
{ Qt::Key_Return, XK_Return },
|
||||
{ Qt::Key_Enter, XK_KP_Enter },
|
||||
{ Qt::Key_Insert, XK_Insert },
|
||||
{ Qt::Key_Delete, XK_Delete },
|
||||
{ Qt::Key_Pause, XK_Pause },
|
||||
{ Qt::Key_Print, XK_Print },
|
||||
{ Qt::Key_Clear, XK_Clear },
|
||||
{ Qt::Key_Home, XK_Home },
|
||||
{ Qt::Key_End, XK_End },
|
||||
{ Qt::Key_Left, XK_Left },
|
||||
{ Qt::Key_Up, XK_Up },
|
||||
{ Qt::Key_Right, XK_Right },
|
||||
{ Qt::Key_Down, XK_Down },
|
||||
{ Qt::Key_PageUp, XK_Prior },
|
||||
{ Qt::Key_PageDown, XK_Next },
|
||||
{ Qt::Key_Space, XK_space },
|
||||
{ Qt::Key_Exclam, XK_exclam },
|
||||
{ Qt::Key_QuoteDbl, XK_quotedbl },
|
||||
{ Qt::Key_NumberSign, XK_numbersign },
|
||||
{ Qt::Key_Dollar, XK_dollar },
|
||||
{ Qt::Key_Percent, XK_percent },
|
||||
{ Qt::Key_Ampersand, XK_ampersand },
|
||||
{ Qt::Key_Apostrophe, XK_apostrophe },
|
||||
{ Qt::Key_ParenLeft, XK_parenleft },
|
||||
{ Qt::Key_ParenRight, XK_parenright },
|
||||
{ Qt::Key_Asterisk, XK_asterisk },
|
||||
{ Qt::Key_Plus, XK_plus },
|
||||
{ Qt::Key_Comma, XK_comma },
|
||||
{ Qt::Key_Minus, XK_minus },
|
||||
{ Qt::Key_Period, XK_period },
|
||||
{ Qt::Key_Slash, XK_slash },
|
||||
{ Qt::Key_Colon, XK_colon },
|
||||
{ Qt::Key_Semicolon, XK_semicolon },
|
||||
{ Qt::Key_Less, XK_less },
|
||||
{ Qt::Key_Equal, XK_equal },
|
||||
{ Qt::Key_Greater, XK_greater },
|
||||
{ Qt::Key_Question, XK_question },
|
||||
{ Qt::Key_BracketLeft, XK_bracketleft },
|
||||
{ Qt::Key_Backslash, XK_backslash },
|
||||
{ Qt::Key_BracketRight, XK_bracketright },
|
||||
{ Qt::Key_AsciiCircum, XK_asciicircum },
|
||||
{ Qt::Key_Underscore, XK_underscore },
|
||||
{ Qt::Key_QuoteLeft, XK_quoteleft },
|
||||
{ Qt::Key_BraceLeft, XK_braceleft },
|
||||
{ Qt::Key_Bar, XK_bar },
|
||||
{ Qt::Key_BraceRight, XK_braceright },
|
||||
{ Qt::Key_AsciiTilde, XK_asciitilde },
|
||||
{ Qt::Key_nobreakspace, XK_nobreakspace },
|
||||
{ Qt::Key_exclamdown, XK_exclamdown },
|
||||
{ Qt::Key_cent, XK_cent },
|
||||
{ Qt::Key_sterling, XK_sterling },
|
||||
{ Qt::Key_currency, XK_currency },
|
||||
{ Qt::Key_yen, XK_yen },
|
||||
{ Qt::Key_brokenbar, XK_brokenbar },
|
||||
{ Qt::Key_section, XK_section },
|
||||
{ Qt::Key_diaeresis, XK_diaeresis },
|
||||
{ Qt::Key_copyright, XK_copyright },
|
||||
{ Qt::Key_ordfeminine, XK_ordfeminine },
|
||||
{ Qt::Key_guillemotleft, XK_guillemotleft },
|
||||
{ Qt::Key_notsign, XK_notsign },
|
||||
{ Qt::Key_hyphen, XK_hyphen },
|
||||
{ Qt::Key_registered, XK_registered },
|
||||
{ Qt::Key_macron, XK_macron },
|
||||
{ Qt::Key_degree, XK_degree },
|
||||
{ Qt::Key_plusminus, XK_plusminus },
|
||||
{ Qt::Key_twosuperior, XK_twosuperior },
|
||||
{ Qt::Key_threesuperior, XK_threesuperior },
|
||||
{ Qt::Key_acute, XK_acute },
|
||||
{ Qt::Key_mu, XK_mu },
|
||||
{ Qt::Key_paragraph, XK_paragraph },
|
||||
{ Qt::Key_periodcentered, XK_periodcentered },
|
||||
{ Qt::Key_cedilla, XK_cedilla },
|
||||
{ Qt::Key_onesuperior, XK_onesuperior },
|
||||
{ Qt::Key_masculine, XK_masculine },
|
||||
{ Qt::Key_guillemotright, XK_guillemotright },
|
||||
{ Qt::Key_onequarter, XK_onequarter },
|
||||
{ Qt::Key_onehalf, XK_onehalf },
|
||||
{ Qt::Key_threequarters, XK_threequarters },
|
||||
{ Qt::Key_questiondown, XK_questiondown },
|
||||
{ Qt::Key_Agrave, XK_Agrave },
|
||||
{ Qt::Key_Aacute, XK_Aacute },
|
||||
{ Qt::Key_Acircumflex, XK_Acircumflex },
|
||||
{ Qt::Key_Atilde, XK_Atilde },
|
||||
{ Qt::Key_Adiaeresis, XK_Adiaeresis },
|
||||
{ Qt::Key_Aring, XK_Aring },
|
||||
{ Qt::Key_AE, XK_AE },
|
||||
{ Qt::Key_Ccedilla, XK_Ccedilla },
|
||||
{ Qt::Key_Egrave, XK_Egrave },
|
||||
{ Qt::Key_Eacute, XK_Eacute },
|
||||
{ Qt::Key_Ecircumflex, XK_Ecircumflex },
|
||||
{ Qt::Key_Ediaeresis, XK_Ediaeresis },
|
||||
{ Qt::Key_Igrave, XK_Igrave },
|
||||
{ Qt::Key_Iacute, XK_Iacute },
|
||||
{ Qt::Key_Icircumflex, XK_Icircumflex },
|
||||
{ Qt::Key_Idiaeresis, XK_Idiaeresis },
|
||||
{ Qt::Key_ETH, XK_ETH },
|
||||
{ Qt::Key_Ntilde, XK_Ntilde },
|
||||
{ Qt::Key_Ograve, XK_Ograve },
|
||||
{ Qt::Key_Oacute, XK_Oacute },
|
||||
{ Qt::Key_Ocircumflex, XK_Ocircumflex },
|
||||
{ Qt::Key_Otilde, XK_Otilde },
|
||||
{ Qt::Key_Odiaeresis, XK_Odiaeresis },
|
||||
{ Qt::Key_multiply, XK_multiply },
|
||||
{ Qt::Key_Ooblique, XK_Ooblique },
|
||||
{ Qt::Key_Ugrave, XK_Ugrave },
|
||||
{ Qt::Key_Uacute, XK_Uacute },
|
||||
{ Qt::Key_Ucircumflex, XK_Ucircumflex },
|
||||
{ Qt::Key_Udiaeresis, XK_Udiaeresis },
|
||||
{ Qt::Key_Yacute, XK_Yacute },
|
||||
{ Qt::Key_THORN, XK_THORN },
|
||||
{ Qt::Key_ssharp, XK_ssharp },
|
||||
{ Qt::Key_division, XK_division },
|
||||
{ Qt::Key_ydiaeresis, XK_ydiaeresis },
|
||||
{ Qt::Key_Multi_key, XK_Multi_key },
|
||||
{ Qt::Key_Codeinput, XK_Codeinput },
|
||||
{ Qt::Key_SingleCandidate, XK_SingleCandidate },
|
||||
{ Qt::Key_MultipleCandidate, XK_MultipleCandidate },
|
||||
{ Qt::Key_PreviousCandidate, XK_PreviousCandidate },
|
||||
{ Qt::Key_Mode_switch, XK_Mode_switch },
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XF86KEYSYM_H
|
||||
{ Qt::Key_Back, XF86XK_Back },
|
||||
{ Qt::Key_Forward, XF86XK_Forward },
|
||||
{ Qt::Key_Stop, XF86XK_Stop },
|
||||
{ Qt::Key_Refresh, XF86XK_Refresh },
|
||||
{ Qt::Key_VolumeDown, XF86XK_AudioLowerVolume },
|
||||
{ Qt::Key_VolumeMute, XF86XK_AudioMute },
|
||||
{ Qt::Key_VolumeUp, XF86XK_AudioRaiseVolume },
|
||||
{ Qt::Key_MediaPlay, XF86XK_AudioPlay },
|
||||
{ Qt::Key_MediaStop, XF86XK_AudioStop },
|
||||
{ Qt::Key_MediaPrevious, XF86XK_AudioPrev },
|
||||
{ Qt::Key_MediaNext, XF86XK_AudioNext },
|
||||
{ Qt::Key_MediaRecord, XF86XK_AudioRecord },
|
||||
{ Qt::Key_MediaPause, XF86XK_AudioPause },
|
||||
{ Qt::Key_HomePage, XF86XK_HomePage },
|
||||
{ Qt::Key_Favorites, XF86XK_Favorites },
|
||||
{ Qt::Key_Search, XF86XK_Search },
|
||||
{ Qt::Key_Standby, XF86XK_Standby },
|
||||
{ Qt::Key_OpenUrl, XF86XK_OpenURL },
|
||||
{ Qt::Key_LaunchMail, XF86XK_Mail },
|
||||
{ Qt::Key_LaunchMedia, XF86XK_AudioMedia },
|
||||
{ Qt::Key_Launch0, XF86XK_MyComputer },
|
||||
{ Qt::Key_Launch1, XF86XK_Calculator },
|
||||
{ Qt::Key_Launch2, XF86XK_Launch0 },
|
||||
{ Qt::Key_Launch3, XF86XK_Launch1 },
|
||||
{ Qt::Key_Launch4, XF86XK_Launch2 },
|
||||
{ Qt::Key_Launch5, XF86XK_Launch3 },
|
||||
{ Qt::Key_Launch6, XF86XK_Launch4 },
|
||||
{ Qt::Key_Launch7, XF86XK_Launch5 },
|
||||
{ Qt::Key_Launch8, XF86XK_Launch6 },
|
||||
{ Qt::Key_Launch9, XF86XK_Launch7 },
|
||||
{ Qt::Key_LaunchA, XF86XK_Launch8 },
|
||||
{ Qt::Key_LaunchB, XF86XK_Launch9 },
|
||||
{ Qt::Key_LaunchC, XF86XK_LaunchA },
|
||||
{ Qt::Key_LaunchD, XF86XK_LaunchB },
|
||||
{ Qt::Key_LaunchE, XF86XK_LaunchC },
|
||||
{ Qt::Key_LaunchF, XF86XK_LaunchD },
|
||||
{ Qt::Key_LaunchG, XF86XK_LaunchE },
|
||||
{ Qt::Key_LaunchH, XF86XK_LaunchF },
|
||||
#endif
|
||||
|
||||
{Qt::Key(0), 0}
|
||||
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -133,7 +133,10 @@ SettingsDialog::SettingsDialog(Application *app, QWidget *parent)
|
||||
QTreeWidgetItem *iface = AddCategory(tr("User interface"));
|
||||
AddPage(Page_Appearance, new AppearanceSettingsPage(this), iface);
|
||||
AddPage(Page_Notifications, new NotificationsSettingsPage(this), iface);
|
||||
|
||||
#ifdef HAVE_GLOBALSHORTCUTS
|
||||
AddPage(Page_GlobalShortcuts, new GlobalShortcutsSettingsPage(this), iface);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_STREAM_TIDAL) || defined(HAVE_STREAM_DEEZER)
|
||||
QTreeWidgetItem *streaming = AddCategory(tr("Streaming"));
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018, 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
|
||||
@@ -53,6 +54,7 @@ GlobalShortcutsSettingsPage::GlobalShortcutsSettingsPage(SettingsDialog *dialog)
|
||||
ui_(new Ui_GlobalShortcutsSettingsPage),
|
||||
initialised_(false),
|
||||
grabber_(new GlobalShortcutGrabber) {
|
||||
|
||||
ui_->setupUi(this);
|
||||
ui_->shortcut_options->setEnabled(false);
|
||||
ui_->list->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
@@ -64,8 +66,17 @@ GlobalShortcutsSettingsPage::GlobalShortcutsSettingsPage(SettingsDialog *dialog)
|
||||
connect(ui_->radio_none, SIGNAL(clicked()), SLOT(NoneClicked()));
|
||||
connect(ui_->radio_default, SIGNAL(clicked()), SLOT(DefaultClicked()));
|
||||
connect(ui_->radio_custom, SIGNAL(clicked()), SLOT(ChangeClicked()));
|
||||
connect(ui_->change, SIGNAL(clicked()), SLOT(ChangeClicked()));
|
||||
connect(ui_->gnome_open, SIGNAL(clicked()), SLOT(OpenGnomeKeybindingProperties()));
|
||||
connect(ui_->button_change, SIGNAL(clicked()), SLOT(ChangeClicked()));
|
||||
|
||||
#if !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
|
||||
#ifdef HAVE_DBUS
|
||||
connect(ui_->checkbox_dbus, SIGNAL(clicked(bool)), SLOT(DBusChanged(bool)));
|
||||
connect(ui_->button_dbus_open, SIGNAL(clicked()), SLOT(OpenGnomeKeybindingProperties()));
|
||||
#endif
|
||||
#ifdef HAVE_X11
|
||||
connect(ui_->checkbox_x11, SIGNAL(clicked(bool)), SLOT(X11Changed(bool)));
|
||||
#endif
|
||||
#endif // !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
|
||||
|
||||
}
|
||||
|
||||
@@ -91,10 +102,16 @@ void GlobalShortcutsSettingsPage::Load() {
|
||||
if (!initialised_) {
|
||||
initialised_ = true;
|
||||
|
||||
connect(ui_->mac_open, SIGNAL(clicked()), manager, SLOT(ShowMacAccessibilityDialog()));
|
||||
connect(ui_->button_macos_open, SIGNAL(clicked()), manager, SLOT(ShowMacAccessibilityDialog()));
|
||||
|
||||
if (!manager->IsGsdAvailable()) {
|
||||
ui_->gnome_container->hide();
|
||||
ui_->widget_dbus->hide();
|
||||
settings_.setValue("use_dbus", false);
|
||||
}
|
||||
|
||||
if (!manager->IsX11Available()) {
|
||||
ui_->widget_x11->hide();
|
||||
settings_.setValue("use_x11", false);
|
||||
}
|
||||
|
||||
for (const GlobalShortcuts::Shortcut &s : manager->shortcuts().values()) {
|
||||
@@ -114,29 +131,25 @@ void GlobalShortcutsSettingsPage::Load() {
|
||||
SetShortcut(s.s.id, s.s.action->shortcut());
|
||||
}
|
||||
|
||||
bool use_gnome = settings_.value("use_gnome", true).toBool();
|
||||
if (ui_->gnome_container->isVisibleTo(this)) {
|
||||
ui_->gnome_checkbox->setChecked(use_gnome);
|
||||
bool use_dbus = settings_.value("use_dbus", true).toBool();
|
||||
if (ui_->widget_dbus->isVisibleTo(this)) {
|
||||
ui_->checkbox_dbus->setChecked(use_dbus);
|
||||
}
|
||||
|
||||
ui_->mac_container->setVisible(!manager->IsMacAccessibilityEnabled());
|
||||
bool use_x11 = settings_.value("use_x11", false).toBool();
|
||||
if (ui_->widget_x11->isVisibleTo(this)) {
|
||||
ui_->checkbox_x11->setChecked(use_x11);
|
||||
}
|
||||
|
||||
ui_->widget_macos->setVisible(!manager->IsMacAccessibilityEnabled());
|
||||
#ifdef Q_OS_MACOS
|
||||
qint32 mac_version = Utilities::GetMacVersion();
|
||||
ui_->mac_label->setVisible(mac_version < 9);
|
||||
ui_->mac_label_mavericks->setVisible(mac_version >= 9);
|
||||
qint32 macos_version = Utilities::GetMacOsVersion();
|
||||
ui_->label_macos->setVisible(macos_version < 9);
|
||||
ui_->label_macos_mavericks->setVisible(macos_version >= 9);
|
||||
#endif // Q_OS_MACOS
|
||||
|
||||
}
|
||||
|
||||
void GlobalShortcutsSettingsPage::SetShortcut(const QString &id, const QKeySequence &key) {
|
||||
|
||||
Shortcut &shortcut = shortcuts_[id];
|
||||
|
||||
shortcut.key = key;
|
||||
shortcut.item->setText(1, key.toString(QKeySequence::NativeText));
|
||||
|
||||
}
|
||||
|
||||
void GlobalShortcutsSettingsPage::Save() {
|
||||
|
||||
for (const Shortcut &s : shortcuts_.values()) {
|
||||
@@ -145,12 +158,74 @@ void GlobalShortcutsSettingsPage::Save() {
|
||||
settings_.setValue(s.s.id, s.key.toString());
|
||||
}
|
||||
|
||||
settings_.setValue("use_gnome", ui_->gnome_checkbox->isChecked());
|
||||
settings_.setValue("use_dbus", ui_->checkbox_dbus->isChecked());
|
||||
settings_.setValue("use_x11", ui_->checkbox_x11->isChecked());
|
||||
|
||||
dialog()->global_shortcuts_manager()->ReloadSettings();
|
||||
|
||||
}
|
||||
|
||||
#if !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
|
||||
#ifdef HAVE_X11
|
||||
void GlobalShortcutsSettingsPage::X11Changed(bool) {
|
||||
|
||||
if (!ui_->widget_x11->isVisible()) return;
|
||||
|
||||
if (ui_->checkbox_x11->isChecked()) {
|
||||
ui_->list->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
ui_->list->setEnabled(false);
|
||||
}
|
||||
|
||||
}
|
||||
#endif // HAVE_X11
|
||||
#ifdef HAVE_DBUS
|
||||
void GlobalShortcutsSettingsPage::DBusChanged(bool) {
|
||||
|
||||
if (!ui_->widget_dbus->isVisible()) return;
|
||||
|
||||
if (ui_->checkbox_dbus->isChecked()) {
|
||||
if (ui_->checkbox_x11->isEnabled()) {
|
||||
ui_->checkbox_x11->setEnabled(false);
|
||||
ui_->list->setEnabled(false);
|
||||
}
|
||||
|
||||
if (ui_->checkbox_x11->isChecked()) {
|
||||
ui_->checkbox_x11->setChecked(false);
|
||||
ui_->list->setEnabled(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!ui_->checkbox_x11->isEnabled()) {
|
||||
ui_->checkbox_x11->setEnabled(true);
|
||||
if (ui_->checkbox_x11->isChecked()) ui_->list->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void GlobalShortcutsSettingsPage::OpenGnomeKeybindingProperties() {
|
||||
|
||||
if (!QProcess::startDetached("gnome-keybinding-properties")) {
|
||||
if (!QProcess::startDetached("gnome-control-center", QStringList() << "keyboard")) {
|
||||
QMessageBox::warning(this, "Error", QString("The \"%1\" command could not be started.").arg("gnome-keybinding-properties"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif // HAVE_DBUS
|
||||
|
||||
#endif // !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
|
||||
|
||||
void GlobalShortcutsSettingsPage::SetShortcut(const QString &id, const QKeySequence &key) {
|
||||
|
||||
Shortcut &shortcut = shortcuts_[id];
|
||||
|
||||
shortcut.key = key;
|
||||
shortcut.item->setText(1, key.toString(QKeySequence::NativeText));
|
||||
|
||||
}
|
||||
|
||||
void GlobalShortcutsSettingsPage::ItemClicked(QTreeWidgetItem *item) {
|
||||
|
||||
current_id_ = item->data(0, Qt::UserRole).toString();
|
||||
@@ -196,14 +271,3 @@ void GlobalShortcutsSettingsPage::ChangeClicked() {
|
||||
|
||||
}
|
||||
|
||||
void GlobalShortcutsSettingsPage::OpenGnomeKeybindingProperties() {
|
||||
|
||||
if (!QProcess::startDetached("gnome-keybinding-properties")) {
|
||||
if (!QProcess::startDetached("gnome-control-center", QStringList() << "keyboard")) {
|
||||
QMessageBox::warning(this, "Error",
|
||||
tr("The \"%1\" command could not be started.")
|
||||
.arg("gnome-keybinding-properties"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018, 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
|
||||
@@ -26,6 +27,7 @@
|
||||
#include <memory>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QSettings>
|
||||
#include <QMap>
|
||||
@@ -43,7 +45,7 @@ class Ui_GlobalShortcutsSettingsPage;
|
||||
class GlobalShortcutsSettingsPage : public SettingsPage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
public:
|
||||
GlobalShortcutsSettingsPage(SettingsDialog *dialog);
|
||||
~GlobalShortcutsSettingsPage();
|
||||
static const char *kSettingsGroup;
|
||||
@@ -53,15 +55,24 @@ public:
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private slots:
|
||||
private slots:
|
||||
|
||||
#if !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
|
||||
#ifdef HAVE_X11
|
||||
void X11Changed(bool);
|
||||
#endif
|
||||
#ifdef HAVE_DBUS
|
||||
void DBusChanged(bool);
|
||||
void OpenGnomeKeybindingProperties();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void ItemClicked(QTreeWidgetItem *);
|
||||
void NoneClicked();
|
||||
void DefaultClicked();
|
||||
void ChangeClicked();
|
||||
|
||||
void OpenGnomeKeybindingProperties();
|
||||
|
||||
private:
|
||||
private:
|
||||
struct Shortcut {
|
||||
GlobalShortcuts::Shortcut s;
|
||||
QKeySequence key;
|
||||
@@ -70,7 +81,7 @@ private:
|
||||
|
||||
void SetShortcut(const QString &id, const QKeySequence &key);
|
||||
|
||||
private:
|
||||
private:
|
||||
Ui_GlobalShortcutsSettingsPage *ui_;
|
||||
|
||||
bool initialised_;
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="gnome_container" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<widget class="QWidget" name="widget_dbus" native="true">
|
||||
<layout class="QHBoxLayout" name="layout_gnome">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@@ -34,7 +34,7 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="gnome_checkbox">
|
||||
<widget class="QCheckBox" name="checkbox_dbus">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -42,12 +42,12 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Gnome's shortcut keys</string>
|
||||
<string>Use Gnome D-Bus shortcut keys</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="gnome_open">
|
||||
<widget class="QPushButton" name="button_dbus_open">
|
||||
<property name="text">
|
||||
<string>Open...</string>
|
||||
</property>
|
||||
@@ -57,7 +57,41 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="mac_container" native="true">
|
||||
<widget class="QWidget" name="widget_x11" native="true">
|
||||
<layout class="QHBoxLayout" name="layout_x11">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkbox_x11">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use X11's shortcut keys</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_macos" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
@@ -75,7 +109,7 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="mac_label">
|
||||
<widget class="QLabel" name="label_macos">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -91,7 +125,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mac_label_mavericks">
|
||||
<widget class="QLabel" name="label_macos_mavericks">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -107,7 +141,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="mac_open">
|
||||
<widget class="QPushButton" name="button_macos_open">
|
||||
<property name="text">
|
||||
<string>Open...</string>
|
||||
</property>
|
||||
@@ -167,7 +201,7 @@
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radio_default">
|
||||
<property name="text">
|
||||
<string>De&fault</string>
|
||||
<string>&Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -179,7 +213,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<spacer name="spacer_bottom">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
@@ -192,7 +226,7 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="change">
|
||||
<widget class="QPushButton" name="button_change">
|
||||
<property name="text">
|
||||
<string>Change shortcut...</string>
|
||||
</property>
|
||||
@@ -208,44 +242,11 @@
|
||||
<tabstop>radio_none</tabstop>
|
||||
<tabstop>radio_default</tabstop>
|
||||
<tabstop>radio_custom</tabstop>
|
||||
<tabstop>change</tabstop>
|
||||
<tabstop>button_change</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../data/data.qrc"/>
|
||||
<include location="../../data/icons.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>gnome_checkbox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>list</receiver>
|
||||
<slot>setDisabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>63</x>
|
||||
<y>25</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>82</x>
|
||||
<y>63</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>gnome_checkbox</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>shortcut_options</receiver>
|
||||
<slot>setDisabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>244</x>
|
||||
<y>26</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>122</x>
|
||||
<y>298</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -246,11 +246,8 @@ void StretchHeaderView::SetColumnWidth(int logical, ColumnWidthType width) {
|
||||
bool StretchHeaderView::RestoreState(const QByteArray& data) {
|
||||
|
||||
QDataStream s(data);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
|
||||
s.setVersion(QDataStream::Qt_5_5);
|
||||
#else
|
||||
|
||||
s.setVersion(QDataStream::Qt_5_6);
|
||||
#endif
|
||||
|
||||
int magic_number = 0;
|
||||
s >> magic_number;
|
||||
@@ -314,11 +311,8 @@ QByteArray StretchHeaderView::SaveState() const {
|
||||
visual_indices << logicalIndex(i);
|
||||
}
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
|
||||
s.setVersion(QDataStream::Qt_5_5);
|
||||
#else
|
||||
s.setVersion(QDataStream::Qt_5_6);
|
||||
#endif
|
||||
|
||||
s << kMagicNumber;
|
||||
|
||||
s << stretch_enabled_;
|
||||
|
||||
Reference in New Issue
Block a user