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:
Jonas Kvinge
2019-01-01 20:07:29 +01:00
parent 2a54cb17e7
commit cef334c210
40 changed files with 1283 additions and 2345 deletions

View File

@@ -1,41 +0,0 @@
cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_CXX_STANDARD 11)
if (UNIX AND NOT APPLE)
find_package(X11)
if (X11_FOUND)
include_directories(${X11_INCLUDE_DIR})
endif(X11_FOUND)
endif(UNIX AND NOT APPLE)
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
if (NOT WIN32 AND NOT APPLE)
find_path(HAVE_QPA_QPLATFORMNATIVEINTERFACE_H qpa/qplatformnativeinterface.h PATHS ${Qt5Gui_PRIVATE_INCLUDE_DIRS})
if(NOT HAVE_QPA_QPLATFORMNATIVEINTERFACE_H)
message(FATAL_ERROR "Missing qpa/qplatformnativeinterface.h, check that you got the QT private headers installed (package libQt5Gui-private-headers-devel, qtbase5-private-dev or similar)")
endif(NOT HAVE_QPA_QPLATFORMNATIVEINTERFACE_H)
endif(NOT WIN32 AND NOT APPLE)
set(QXT-SOURCES qxtglobal.cpp qxtglobalshortcut.cpp)
set(QXT-MOC-HEADERS qxtglobalshortcut.h )
if(X11_FOUND)
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_x11.cpp)
elseif(APPLE)
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_mac.cpp)
elseif(WIN32)
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_win.cpp)
endif()
QT5_WRAP_CPP(QXT-SOURCES-MOC ${QXT-MOC-HEADERS})
ADD_LIBRARY(qxt STATIC
${QXT-SOURCES}
${QXT-SOURCES-MOC}
)
target_link_libraries(qxt Qt5::Core Qt5::Widgets)
if(X11_FOUND)
target_link_libraries(qxt Qt5::X11Extras)
endif(X11_FOUND)

89
3rdparty/qxt/LICENSE vendored
View File

@@ -1,89 +0,0 @@
Qt Extension Library
Copyright (C) 2007 Qxt Foundation
------------------- Disclaimer ------------------------------------------------
Until the Qxt Foundation is legally established, copyright for the
source code falls back to the original contributor. For information about the
status of the Qxt Foundation, or about the copyright status of any part of Qxt,
contact the Qxt project maintainers at <foundation@libqxt.org>
Once the Qxt Foundation has been legally established, all contributors must
transfer all copyright interest to the Qxt Foundation before their submissions
will be added to the project.
------------------- License ---------------------------------------------------
This library is free software; you can redistribute it and/or modify it
under the terms of the Common Public License, version 1.0, as published by IBM
or under the terms of the GNU Lesser General Public License, version 2.1,
as published by the Free Software Foundation
This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
FITNESS FOR A PARTICULAR PURPOSE.
You should have received a copy of the CPL along with this file.
See the LICENSE file and the cpl1.0.txt file included with the source
distribution for more information. If you did not receive a copy of the
license, contact the Qxt Foundation.
You should have received a copy of the LGPL along with this file.
See the LICENSE file and the lgpl-2.1.txt file included with the source
distribution for more information. If you did not receive a copy of the
license, contact the Qxt Foundation.
Parts of Qxt depend on Qt 4 and/or other libraries that have their own
licenses. Qxt is independent of these licenses; however, use of these other
libraries is subject to their respective license agreements.
------------------- Intent ----------------------------------------------------
The following section describes the opinions and intent of the Qxt Foundation
with regards to the licensing and use of the Qxt source code and library. In
the event that the CPL is found to be illegal or invalid, or if any application
or clause of the license is subjected to question or abuse, this section is a
general statement of the desired interpretation.
This section has no legal standing and the statements made here are strictly
subject to the text of the CPL; that is, if this section and the CPL are in
disagreement, the text of the CPL takes precedence. In no way does this
intent grant you any additional rights or impose any additional restrictions.
If you have questions about licensing, contact the maintainers.
Qxt is built and supported by open-source enthusiasts.
- Please respect the open-source background of the contributors. The code is
provided for everyone's use; you may not restrict the rights of anyone to
use it.
- No individual may claim ownership of any part of the code. It belongs
to the community.
- You may modify the source code to suit your needs, but these changes
must be made free. If you distribute a modified form of Qxt, you must
also distribute the entire source code of the modified form.
- Digital Rights Management (DRM) puts unfair, unfree restrictions on
users and developers. It is the opposite of Free Software. We can't
stop you from using it, but please don't use the Qxt name for software
restricted by DRM.
- Please respect the time and effort put into the project by the developers.
- If you find Qxt useful, it would be appreciated if you would include
text in your application (for instance, in the About dialog) giving
acknowledgement to Qxt.
- If you make modifications to the source code, you must not call the
modified version "Qxt." It's okay to include "Qxt" in the name, but
anyone who receives the modified version needs to know that it's not
the same as the version distributed by the Qxt Foundation.
- We want everyone to be able to use Qxt without restrictions.
- If you distribute Qxt in compiled binary form, please ensure that
everyone who receives it can get the source code used to create it.
- You are free to use Qxt in closed-source applications as long as you
distribute Qxt in an open-source fashion. This does not require you
to make your entire application open-source.
- The Qxt Foundation is a non-profit, non-political organization.
- Please don't use the Qxt name in any political or semi-political
propaganda or publication. We don't like it.
- Qxt is distributed "as-is," with no warranty.
- If it makes your program crash, your computer blow up, or tiny demons
fly out of your nose, please don't sue us.

View File

@@ -1,372 +0,0 @@
#ifndef KEYMAPPER_X11_H
#define KEYMAPPER_X11_H
// (davidsansome) Nicked from qkeymapper_x11.cpp
#include <Qt>
#define XK_MISCELLANY
#define XK_LATIN1
#define XK_KOREAN
#define XK_XKB_KEYS
#include <X11/keysymdef.h>
//
// Keyboard event translation
//
#ifndef XK_ISO_Left_Tab
#define XK_ISO_Left_Tab 0xFE20
#endif
#ifndef XK_dead_hook
#define XK_dead_hook 0xFE61
#endif
#ifndef XK_dead_horn
#define XK_dead_horn 0xFE62
#endif
#ifndef XK_Codeinput
#define XK_Codeinput 0xFF37
#endif
#ifndef XK_Kanji_Bangou
#define XK_Kanji_Bangou 0xFF37 /* same as codeinput */
#endif
// Fix old X libraries
#ifndef XK_KP_Home
#define XK_KP_Home 0xFF95
#endif
#ifndef XK_KP_Left
#define XK_KP_Left 0xFF96
#endif
#ifndef XK_KP_Up
#define XK_KP_Up 0xFF97
#endif
#ifndef XK_KP_Right
#define XK_KP_Right 0xFF98
#endif
#ifndef XK_KP_Down
#define XK_KP_Down 0xFF99
#endif
#ifndef XK_KP_Prior
#define XK_KP_Prior 0xFF9A
#endif
#ifndef XK_KP_Next
#define XK_KP_Next 0xFF9B
#endif
#ifndef XK_KP_End
#define XK_KP_End 0xFF9C
#endif
#ifndef XK_KP_Insert
#define XK_KP_Insert 0xFF9E
#endif
#ifndef XK_KP_Delete
#define XK_KP_Delete 0xFF9F
#endif
// the next lines are taken from XFree > 4.0 (X11/XF86keysyms.h), defining some special
// multimedia keys. They are included here as not every system has them.
#define XF86XK_Standby 0x1008FF10
#define XF86XK_AudioLowerVolume 0x1008FF11
#define XF86XK_AudioMute 0x1008FF12
#define XF86XK_AudioRaiseVolume 0x1008FF13
#define XF86XK_AudioPlay 0x1008FF14
#define XF86XK_AudioStop 0x1008FF15
#define XF86XK_AudioPrev 0x1008FF16
#define XF86XK_AudioNext 0x1008FF17
#define XF86XK_HomePage 0x1008FF18
#define XF86XK_Calculator 0x1008FF1D
#define XF86XK_Mail 0x1008FF19
#define XF86XK_Start 0x1008FF1A
#define XF86XK_Search 0x1008FF1B
#define XF86XK_AudioRecord 0x1008FF1C
#define XF86XK_Back 0x1008FF26
#define XF86XK_Forward 0x1008FF27
#define XF86XK_Stop 0x1008FF28
#define XF86XK_Refresh 0x1008FF29
#define XF86XK_Favorites 0x1008FF30
#define XF86XK_AudioPause 0x1008FF31
#define XF86XK_AudioMedia 0x1008FF32
#define XF86XK_MyComputer 0x1008FF33
#define XF86XK_OpenURL 0x1008FF38
#define XF86XK_Launch0 0x1008FF40
#define XF86XK_Launch1 0x1008FF41
#define XF86XK_Launch2 0x1008FF42
#define XF86XK_Launch3 0x1008FF43
#define XF86XK_Launch4 0x1008FF44
#define XF86XK_Launch5 0x1008FF45
#define XF86XK_Launch6 0x1008FF46
#define XF86XK_Launch7 0x1008FF47
#define XF86XK_Launch8 0x1008FF48
#define XF86XK_Launch9 0x1008FF49
#define XF86XK_LaunchA 0x1008FF4A
#define XF86XK_LaunchB 0x1008FF4B
#define XF86XK_LaunchC 0x1008FF4C
#define XF86XK_LaunchD 0x1008FF4D
#define XF86XK_LaunchE 0x1008FF4E
#define XF86XK_LaunchF 0x1008FF4F
// end of XF86keysyms.h
// Special keys used by Qtopia, mapped into the X11 private keypad range.
#define QTOPIAXK_Select 0x11000601
#define QTOPIAXK_Yes 0x11000602
#define QTOPIAXK_No 0x11000603
#define QTOPIAXK_Cancel 0x11000604
#define QTOPIAXK_Printer 0x11000605
#define QTOPIAXK_Execute 0x11000606
#define QTOPIAXK_Sleep 0x11000607
#define QTOPIAXK_Play 0x11000608
#define QTOPIAXK_Zoom 0x11000609
#define QTOPIAXK_Context1 0x1100060A
#define QTOPIAXK_Context2 0x1100060B
#define QTOPIAXK_Context3 0x1100060C
#define QTOPIAXK_Context4 0x1100060D
#define QTOPIAXK_Call 0x1100060E
#define QTOPIAXK_Hangup 0x1100060F
#define QTOPIAXK_Flip 0x11000610
// keyboard mapping table
static const unsigned int KeyTbl[] = {
// misc keys
XK_Escape, Qt::Key_Escape,
XK_Tab, Qt::Key_Tab,
XK_ISO_Left_Tab, Qt::Key_Backtab,
XK_BackSpace, Qt::Key_Backspace,
XK_Return, Qt::Key_Return,
XK_Insert, Qt::Key_Insert,
XK_Delete, Qt::Key_Delete,
XK_Clear, Qt::Key_Delete,
XK_Pause, Qt::Key_Pause,
XK_Print, Qt::Key_Print,
0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq
0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq
// cursor movement
XK_Home, Qt::Key_Home,
XK_End, Qt::Key_End,
XK_Left, Qt::Key_Left,
XK_Up, Qt::Key_Up,
XK_Right, Qt::Key_Right,
XK_Down, Qt::Key_Down,
XK_Prior, Qt::Key_PageUp,
XK_Next, Qt::Key_PageDown,
// modifiers
XK_Shift_L, Qt::Key_Shift,
XK_Shift_R, Qt::Key_Shift,
XK_Shift_Lock, Qt::Key_Shift,
XK_Control_L, Qt::Key_Control,
XK_Control_R, Qt::Key_Control,
XK_Meta_L, Qt::Key_Meta,
XK_Meta_R, Qt::Key_Meta,
XK_Alt_L, Qt::Key_Alt,
XK_Alt_R, Qt::Key_Alt,
XK_Caps_Lock, Qt::Key_CapsLock,
XK_Num_Lock, Qt::Key_NumLock,
XK_Scroll_Lock, Qt::Key_ScrollLock,
XK_Super_L, Qt::Key_Super_L,
XK_Super_R, Qt::Key_Super_R,
XK_Menu, Qt::Key_Menu,
XK_Hyper_L, Qt::Key_Hyper_L,
XK_Hyper_R, Qt::Key_Hyper_R,
XK_Help, Qt::Key_Help,
0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab
0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11)
0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12)
// numeric and function keypad keys
XK_KP_Enter, Qt::Key_Enter,
// special and additional keys
XK_Clear, Qt::Key_Clear,
XK_Delete, Qt::Key_Delete,
XK_space, Qt::Key_Space,
XK_exclam, Qt::Key_Exclam,
XK_quotedbl, Qt::Key_QuoteDbl,
XK_numbersign, Qt::Key_NumberSign,
XK_dollar, Qt::Key_Dollar,
XK_percent, Qt::Key_Percent,
XK_ampersand, Qt::Key_Ampersand,
XK_apostrophe, Qt::Key_Apostrophe,
XK_parenleft, Qt::Key_ParenLeft,
XK_parenright, Qt::Key_ParenRight,
XK_asterisk, Qt::Key_Asterisk,
XK_plus, Qt::Key_Plus,
XK_comma, Qt::Key_Comma,
XK_minus, Qt::Key_Minus,
XK_period, Qt::Key_Period,
XK_slash, Qt::Key_Slash,
XK_colon, Qt::Key_Colon,
XK_semicolon, Qt::Key_Semicolon,
XK_less, Qt::Key_Less,
XK_equal, Qt::Key_Equal,
XK_greater, Qt::Key_Greater,
XK_question, Qt::Key_Question,
XK_bracketleft, Qt::Key_BracketLeft,
XK_backslash, Qt::Key_Backslash,
XK_bracketright, Qt::Key_BracketRight,
XK_asciicircum, Qt::Key_AsciiCircum,
XK_underscore, Qt::Key_Underscore,
// International input method support keys
// International & multi-key character composition
XK_ISO_Level3_Shift, Qt::Key_AltGr,
XK_Multi_key, Qt::Key_Multi_key,
XK_Codeinput, Qt::Key_Codeinput,
XK_SingleCandidate, Qt::Key_SingleCandidate,
XK_MultipleCandidate, Qt::Key_MultipleCandidate,
XK_PreviousCandidate, Qt::Key_PreviousCandidate,
// Misc Functions
XK_Mode_switch, Qt::Key_Mode_switch,
XK_script_switch, Qt::Key_Mode_switch,
// Japanese keyboard support
XK_Kanji, Qt::Key_Kanji,
XK_Muhenkan, Qt::Key_Muhenkan,
//XK_Henkan_Mode, Qt::Key_Henkan_Mode,
XK_Henkan_Mode, Qt::Key_Henkan,
XK_Henkan, Qt::Key_Henkan,
XK_Romaji, Qt::Key_Romaji,
XK_Hiragana, Qt::Key_Hiragana,
XK_Katakana, Qt::Key_Katakana,
XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana,
XK_Zenkaku, Qt::Key_Zenkaku,
XK_Hankaku, Qt::Key_Hankaku,
XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku,
XK_Touroku, Qt::Key_Touroku,
XK_Massyo, Qt::Key_Massyo,
XK_Kana_Lock, Qt::Key_Kana_Lock,
XK_Kana_Shift, Qt::Key_Kana_Shift,
XK_Eisu_Shift, Qt::Key_Eisu_Shift,
XK_Eisu_toggle, Qt::Key_Eisu_toggle,
//XK_Kanji_Bangou, Qt::Key_Kanji_Bangou,
//XK_Zen_Koho, Qt::Key_Zen_Koho,
//XK_Mae_Koho, Qt::Key_Mae_Koho,
XK_Kanji_Bangou, Qt::Key_Codeinput,
XK_Zen_Koho, Qt::Key_MultipleCandidate,
XK_Mae_Koho, Qt::Key_PreviousCandidate,
#ifdef XK_KOREAN
// Korean keyboard support
XK_Hangul, Qt::Key_Hangul,
XK_Hangul_Start, Qt::Key_Hangul_Start,
XK_Hangul_End, Qt::Key_Hangul_End,
XK_Hangul_Hanja, Qt::Key_Hangul_Hanja,
XK_Hangul_Jamo, Qt::Key_Hangul_Jamo,
XK_Hangul_Romaja, Qt::Key_Hangul_Romaja,
//XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput,
XK_Hangul_Codeinput, Qt::Key_Codeinput,
XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja,
XK_Hangul_Banja, Qt::Key_Hangul_Banja,
XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja,
XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja,
//XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate,
//XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate,
//XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate,
XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate,
XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate,
XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate,
XK_Hangul_Special, Qt::Key_Hangul_Special,
//XK_Hangul_switch, Qt::Key_Hangul_switch,
XK_Hangul_switch, Qt::Key_Mode_switch,
#endif // XK_KOREAN
// dead keys
XK_dead_grave, Qt::Key_Dead_Grave,
XK_dead_acute, Qt::Key_Dead_Acute,
XK_dead_circumflex, Qt::Key_Dead_Circumflex,
XK_dead_tilde, Qt::Key_Dead_Tilde,
XK_dead_macron, Qt::Key_Dead_Macron,
XK_dead_breve, Qt::Key_Dead_Breve,
XK_dead_abovedot, Qt::Key_Dead_Abovedot,
XK_dead_diaeresis, Qt::Key_Dead_Diaeresis,
XK_dead_abovering, Qt::Key_Dead_Abovering,
XK_dead_doubleacute, Qt::Key_Dead_Doubleacute,
XK_dead_caron, Qt::Key_Dead_Caron,
XK_dead_cedilla, Qt::Key_Dead_Cedilla,
XK_dead_ogonek, Qt::Key_Dead_Ogonek,
XK_dead_iota, Qt::Key_Dead_Iota,
XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound,
XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound,
XK_dead_belowdot, Qt::Key_Dead_Belowdot,
XK_dead_hook, Qt::Key_Dead_Hook,
XK_dead_horn, Qt::Key_Dead_Horn,
// Special multimedia keys
// currently only tested with MS internet keyboard
// browsing keys
XF86XK_Back, Qt::Key_Back,
XF86XK_Forward, Qt::Key_Forward,
XF86XK_Stop, Qt::Key_Stop,
XF86XK_Refresh, Qt::Key_Refresh,
XF86XK_Favorites, Qt::Key_Favorites,
XF86XK_AudioMedia, Qt::Key_LaunchMedia,
XF86XK_OpenURL, Qt::Key_OpenUrl,
XF86XK_HomePage, Qt::Key_HomePage,
XF86XK_Search, Qt::Key_Search,
// media keys
XF86XK_AudioLowerVolume, Qt::Key_VolumeDown,
XF86XK_AudioMute, Qt::Key_VolumeMute,
XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp,
XF86XK_AudioPlay, Qt::Key_MediaPlay,
XF86XK_AudioStop, Qt::Key_MediaStop,
XF86XK_AudioPrev, Qt::Key_MediaPrevious,
XF86XK_AudioNext, Qt::Key_MediaNext,
XF86XK_AudioRecord, Qt::Key_MediaRecord,
// launch keys
XF86XK_Mail, Qt::Key_LaunchMail,
XF86XK_MyComputer, Qt::Key_Launch0,
XF86XK_Calculator, Qt::Key_Launch1,
XF86XK_Standby, Qt::Key_Standby,
XF86XK_Launch0, Qt::Key_Launch2,
XF86XK_Launch1, Qt::Key_Launch3,
XF86XK_Launch2, Qt::Key_Launch4,
XF86XK_Launch3, Qt::Key_Launch5,
XF86XK_Launch4, Qt::Key_Launch6,
XF86XK_Launch5, Qt::Key_Launch7,
XF86XK_Launch6, Qt::Key_Launch8,
XF86XK_Launch7, Qt::Key_Launch9,
XF86XK_Launch8, Qt::Key_LaunchA,
XF86XK_Launch9, Qt::Key_LaunchB,
XF86XK_LaunchA, Qt::Key_LaunchC,
XF86XK_LaunchB, Qt::Key_LaunchD,
XF86XK_LaunchC, Qt::Key_LaunchE,
XF86XK_LaunchD, Qt::Key_LaunchF,
// Qtopia keys
QTOPIAXK_Select, Qt::Key_Select,
QTOPIAXK_Yes, Qt::Key_Yes,
QTOPIAXK_No, Qt::Key_No,
QTOPIAXK_Cancel, Qt::Key_Cancel,
QTOPIAXK_Printer, Qt::Key_Printer,
QTOPIAXK_Execute, Qt::Key_Execute,
QTOPIAXK_Sleep, Qt::Key_Sleep,
QTOPIAXK_Play, Qt::Key_Play,
QTOPIAXK_Zoom, Qt::Key_Zoom,
QTOPIAXK_Context1, Qt::Key_Context1,
QTOPIAXK_Context2, Qt::Key_Context2,
QTOPIAXK_Context3, Qt::Key_Context3,
QTOPIAXK_Context4, Qt::Key_Context4,
QTOPIAXK_Call, Qt::Key_Call,
QTOPIAXK_Hangup, Qt::Key_Hangup,
QTOPIAXK_Flip, Qt::Key_Flip,
0, 0
};
#endif // KEYMAPPER_X11_H

View File

@@ -1,250 +0,0 @@
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include "qxtglobal.h"
/*!
\headerfile <QxtGlobal>
\title Global Qxt Declarations
\inmodule QxtCore
\brief The <QxtGlobal> header provides basic declarations and
is included by all other Qxt headers.
*/
/*!
\macro QXT_VERSION
\relates <QxtGlobal>
This macro expands a numeric value of the form 0xMMNNPP (MM =
major, NN = minor, PP = patch) that specifies Qxt's version
number. For example, if you compile your application against Qxt
0.4.0, the QXT_VERSION macro will expand to 0x000400.
You can use QXT_VERSION to use the latest Qt features where
available. For example:
\code
#if QXT_VERSION >= 0x000400
qxtTabWidget->setTabMovementMode(QxtTabWidget::InPlaceMovement);
#endif
\endcode
\sa QXT_VERSION_STR, qxtVersion()
*/
/*!
\macro QXT_VERSION_STR
\relates <QxtGlobal>
This macro expands to a string that specifies Qxt's version number
(for example, "0.4.0"). This is the version against which the
application is compiled.
\sa qxtVersion(), QXT_VERSION
*/
/*!
\relates <QxtGlobal>
Returns the version number of Qxt at run-time as a string (for
example, "0.4.0"). This may be a different version than the
version the application was compiled against.
\sa QXT_VERSION_STR
*/
const char * qxtVersion()
{
return QXT_VERSION_STR;
}
/*!
\headerfile <QxtPimpl>
\title The Qxt private implementation
\inmodule QxtCore
\brief The <QxtPimpl> header provides tools for hiding
details of a class.
Application code generally doesn't have to be concerned about hiding its
implementation details, but when writing library code it is important to
maintain a constant interface, both source and binary. Maintaining a constant
source interface is easy enough, but keeping the binary interface constant
means moving implementation details into a private class. The PIMPL, or
d-pointer, idiom is a common method of implementing this separation. QxtPimpl
offers a convenient way to connect the public and private sides of your class.
\section1 Getting Started
Before you declare the public class, you need to make a forward declaration
of the private class. The private class must have the same name as the public
class, followed by the word Private. For example, a class named MyTest would
declare the private class with:
\code
class MyTestPrivate;
\endcode
\section1 The Public Class
Generally, you shouldn't keep any data members in the public class without a
good reason. Functions that are part of the public interface should be declared
in the public class, and functions that need to be available to subclasses (for
calling or overriding) should be in the protected section of the public class.
To connect the private class to the public class, include the
QXT_DECLARE_PRIVATE macro in the private section of the public class. In the
example above, the private class is connected as follows:
\code
private:
QXT_DECLARE_PRIVATE(MyTest)
\endcode
Additionally, you must include the QXT_INIT_PRIVATE macro in the public class's
constructor. Continuing with the MyTest example, your constructor might look
like this:
\code
MyTest::MyTest() {
// initialization
QXT_INIT_PRIVATE(MyTest);
}
\endcode
\section1 The Private Class
As mentioned above, data members should usually be kept in the private class.
This allows the memory layout of the private class to change without breaking
binary compatibility for the public class. Functions that exist only as
implementation details, or functions that need access to private data members,
should be implemented here.
To define the private class, inherit from the template QxtPrivate class, and
include the QXT_DECLARE_PUBLIC macro in its public section. The template
parameter should be the name of the public class. For example:
\code
class MyTestPrivate : public QxtPrivate<MyTest> {
public:
MyTestPrivate();
QXT_DECLARE_PUBLIC(MyTest)
};
\endcode
\section1 Accessing Private Members
Use the qxt_d() function (actually a function-like object) from functions in
the public class to access the private class. Similarly, functions in the
private class can invoke functions in the public class by using the qxt_p()
function (this one's actually a function).
For example, assume that MyTest has methods named getFoobar and doBaz(),
and MyTestPrivate has a member named foobar and a method named doQuux().
The code might resemble this example:
\code
int MyTest::getFoobar() {
return qxt_d().foobar;
}
void MyTestPrivate::doQuux() {
qxt_p().doBaz(foobar);
}
\endcode
*/
/*!
* \macro QXT_DECLARE_PRIVATE(PUB)
* \relates <QxtPimpl>
* Declares that a public class has a related private class.
*
* This shuold be put in the private section of the public class. The
* parameter \a PUB must be the name of the public class.
*/
/*!
* \macro QXT_DECLARE_PUBLIC(PUB)
* \relates <QxtPimpl>
* Declares that a private class has a related public class named \a PUB.
*
* This may be put anywhere in the declaration of the private class. The parameter is the name of the public class.
*/
/*!
* \macro QXT_INIT_PRIVATE(PUB)
* \relates <QxtPimpl>
* Initializes resources owned by the private class.
*
* This should be called from the public class's constructor,
* before qxt_d() is used for the first time. The parameter \a PUB must be
* the name of the public class.
*/
/*!
* \macro QXT_D(PUB)
* \relates <QxtPimpl>
* Returns a reference in the current scope named "d" to the private class
* associated with the public class \a PUB.
*
* This function is only available in a class using QXT_DECLARE_PRIVATE().
*/
/*!
* \macro QXT_P(PUB)
* \relates <QxtPimpl>
* Creates a reference in the current scope named "q" to the public class
* named \a PUB.
*
* This macro only works in a class using QXT_DECLARE_PUBLIC().
*/
/*!
* \fn QxtPrivate<PUB>& PUB::qxt_d()
* \relates <QxtPimpl>
* Returns a reference to the private class.
*
* This function is only available in a class using \a QXT_DECLARE_PRIVATE.
*/
/*!
* \fn const QxtPrivate<PUB>& PUB::qxt_d() const
* \relates <QxtPimpl>
* Returns a const reference to the private class.
*
* This function is only available in a class using \a QXT_DECLARE_PRIVATE.
* This overload will be automatically used in const functions.
*/
/*!
* \fn PUB& QxtPrivate::qxt_p()
* \relates <QxtPimpl>
* Returns a reference to the public class.
*
* This function is only available in a class using QXT_DECLARE_PUBLIC().
*/
/*!
* \fn const PUB& QxtPrivate::qxt_p() const
* \relates <QxtPimpl>
* Returns a const reference to the public class.
*
* This function is only available in a class using QXT_DECLARE_PUBLIC().
* This overload will be automatically used in const functions.
*/

View File

@@ -1,232 +0,0 @@
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#ifndef QXTGLOBAL_H
#define QXTGLOBAL_H
#include <QtGlobal>
#define QXT_VERSION 0x000700
#define QXT_VERSION_STR "0.7.0"
//--------------------------global macros------------------------------
#ifndef QXT_NO_MACROS
#ifndef _countof
#define _countof(x) (sizeof(x)/sizeof(*x))
#endif
#endif // QXT_NO_MACROS
//--------------------------export macros------------------------------
#define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_CORE)
# define QXT_CORE_EXPORT Q_DECL_EXPORT
# else
# define QXT_CORE_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_CORE_EXPORT
#endif // BUILD_QXT_CORE
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_GUI)
# define QXT_GUI_EXPORT Q_DECL_EXPORT
# else
# define QXT_GUI_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_GUI_EXPORT
#endif // BUILD_QXT_GUI
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_NETWORK)
# define QXT_NETWORK_EXPORT Q_DECL_EXPORT
# else
# define QXT_NETWORK_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_NETWORK_EXPORT
#endif // BUILD_QXT_NETWORK
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_SQL)
# define QXT_SQL_EXPORT Q_DECL_EXPORT
# else
# define QXT_SQL_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_SQL_EXPORT
#endif // BUILD_QXT_SQL
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_WEB)
# define QXT_WEB_EXPORT Q_DECL_EXPORT
# else
# define QXT_WEB_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_WEB_EXPORT
#endif // BUILD_QXT_WEB
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_BERKELEY)
# define QXT_BERKELEY_EXPORT Q_DECL_EXPORT
# else
# define QXT_BERKELEY_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_BERKELEY_EXPORT
#endif // BUILD_QXT_BERKELEY
#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN)
# if defined(BUILD_QXT_ZEROCONF)
# define QXT_ZEROCONF_EXPORT Q_DECL_EXPORT
# else
# define QXT_ZEROCONF_EXPORT Q_DECL_IMPORT
# endif
#else
# define QXT_ZEROCONF_EXPORT
#endif // QXT_ZEROCONF_EXPORT
#if defined(BUILD_QXT_CORE) || defined(BUILD_QXT_GUI) || defined(BUILD_QXT_SQL) || defined(BUILD_QXT_NETWORK) || defined(BUILD_QXT_WEB) || defined(BUILD_QXT_BERKELEY) || defined(BUILD_QXT_ZEROCONF)
# define BUILD_QXT
#endif
QXT_CORE_EXPORT const char* qxtVersion();
#ifndef QT_BEGIN_NAMESPACE
#define QT_BEGIN_NAMESPACE
#endif
#ifndef QT_END_NAMESPACE
#define QT_END_NAMESPACE
#endif
#ifndef QT_FORWARD_DECLARE_CLASS
#define QT_FORWARD_DECLARE_CLASS(Class) class Class;
#endif
/****************************************************************************
** This file is derived from code bearing the following notice:
** The sole author of this file, Adam Higerd, has explicitly disclaimed all
** copyright interest and protection for the content within. This file has
** been placed in the public domain according to United States copyright
** statute and case law. In jurisdictions where this public domain dedication
** is not legally recognized, anyone who receives a copy of this file is
** permitted to use, modify, duplicate, and redistribute this file, in whole
** or in part, with no restrictions or conditions. In these jurisdictions,
** this file shall be copyright (C) 2006-2008 by Adam Higerd.
****************************************************************************/
#define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface<PUB, PUB##Private> qxt_d;
#define QXT_DECLARE_PUBLIC(PUB) friend class PUB;
#define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this);
#define QXT_D(PUB) PUB##Private& d = qxt_d()
#define QXT_P(PUB) PUB& p = qxt_p()
template <typename PUB>
class QxtPrivate
{
public:
virtual ~QxtPrivate()
{}
inline void QXT_setPublic(PUB* pub)
{
qxt_p_ptr = pub;
}
protected:
inline PUB& qxt_p()
{
return *qxt_p_ptr;
}
inline const PUB& qxt_p() const
{
return *qxt_p_ptr;
}
inline PUB* qxt_ptr()
{
return qxt_p_ptr;
}
inline const PUB* qxt_ptr() const
{
return qxt_p_ptr;
}
private:
PUB* qxt_p_ptr;
};
template <typename PUB, typename PVT>
class QxtPrivateInterface
{
friend class QxtPrivate<PUB>;
public:
QxtPrivateInterface()
{
pvt = new PVT;
}
~QxtPrivateInterface()
{
delete pvt;
}
inline void setPublic(PUB* pub)
{
pvt->QXT_setPublic(pub);
}
inline PVT& operator()()
{
return *static_cast<PVT*>(pvt);
}
inline const PVT& operator()() const
{
return *static_cast<PVT*>(pvt);
}
inline PVT * operator->()
{
return static_cast<PVT*>(pvt);
}
inline const PVT * operator->() const
{
return static_cast<PVT*>(pvt);
}
private:
QxtPrivateInterface(const QxtPrivateInterface&) { }
QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }
QxtPrivate<PUB>* pvt;
};
#endif // QXT_GLOBAL

View File

@@ -1,197 +0,0 @@
#include "qxtglobalshortcut.h"
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include <QtGlobal>
#include <QAbstractEventDispatcher>
#include <QHash>
#include <QPair>
#include <QtDebug>
#include "qxtglobalshortcut_p.h"
bool QxtGlobalShortcutPrivate::error = false;
#ifndef Q_OS_MACOS
int QxtGlobalShortcutPrivate::ref = 0;
#endif // Q_OS_MACOS
QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts;
QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier) {
#ifndef Q_OS_MACOS
if (!ref++)
QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
#endif // Q_OS_MACOS
}
QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate() {
#ifndef Q_OS_MACOS
if (!--ref)
QAbstractEventDispatcher::instance()->removeNativeEventFilter(this);
#endif // Q_OS_MACOS
}
bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) {
Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier;
key = shortcut.isEmpty() ? Qt::Key(0) : Qt::Key((shortcut[0] ^ allMods) & shortcut[0]);
mods = shortcut.isEmpty() ? Qt::KeyboardModifiers(0) : Qt::KeyboardModifiers(shortcut[0] & allMods);
const quint32 nativeKey = nativeKeycode(key);
const quint32 nativeMods = nativeModifiers(mods);
const bool res = registerShortcut(nativeKey, nativeMods);
if (res)
shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p());
else
qWarning() << "QxtGlobalShortcut failed to register:" << QKeySequence(key + mods).toString();
return res;
}
bool QxtGlobalShortcutPrivate::unsetShortcut() {
bool res = false;
const quint32 nativeKey = nativeKeycode(key);
const quint32 nativeMods = nativeModifiers(mods);
if (shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p())
res = unregisterShortcut(nativeKey, nativeMods);
if (res)
shortcuts.remove(qMakePair(nativeKey, nativeMods));
else
qWarning() << "QxtGlobalShortcut failed to unregister:" << QKeySequence(key + mods).toString();
key = Qt::Key(0);
mods = Qt::KeyboardModifiers(0);
return res;
}
void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods) {
QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods));
if (shortcut && shortcut->isEnabled())
emit shortcut->activated();
}
/*!
\class QxtGlobalShortcut
\inmodule QxtWidgets
\brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey".
A global shortcut triggers even if the application is not active. This
makes it easy to implement applications that react to certain shortcuts
still if some other application is active or if the application is for
example minimized to the system tray.
Example usage:
\code
QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window);
connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility()));
shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12"));
\endcode
\bold {Note:} Since Qxt 0.6 QxtGlobalShortcut no more requires QxtApplication.
*/
/*!
\fn QxtGlobalShortcut::activated()
This signal is emitted when the user types the shortcut's key sequence.
\sa shortcut
*/
/*!
Constructs a new QxtGlobalShortcut with \a parent.
*/
QxtGlobalShortcut::QxtGlobalShortcut(QObject* parent) : QObject(parent) {
QXT_INIT_PRIVATE(QxtGlobalShortcut);
}
/*!
Constructs a new QxtGlobalShortcut with \a shortcut and \a parent.
*/
QxtGlobalShortcut::QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent) : QObject(parent) {
QXT_INIT_PRIVATE(QxtGlobalShortcut);
setShortcut(shortcut);
}
/*!
Destructs the QxtGlobalShortcut.
*/
QxtGlobalShortcut::~QxtGlobalShortcut() {
if (qxt_d().key != 0) qxt_d().unsetShortcut();
}
/*!
\property QxtGlobalShortcut::shortcut
\brief the shortcut key sequence
\bold {Note:} Notice that corresponding key press and release events are not
delivered for registered global shortcuts even if they are disabled.
Also, comma separated key sequences are not supported.
Only the first part is used:
\code
qxtShortcut->setShortcut(QKeySequence("Ctrl+Alt+A,Ctrl+Alt+B"));
Q_ASSERT(qxtShortcut->shortcut() == QKeySequence("Ctrl+Alt+A"));
\endcode
*/
QKeySequence QxtGlobalShortcut::shortcut() const {
return QKeySequence(qxt_d().key | qxt_d().mods);
}
bool QxtGlobalShortcut::setShortcut(const QKeySequence& shortcut) {
if (qxt_d().key != 0)
qxt_d().unsetShortcut();
return qxt_d().setShortcut(shortcut);
}
/*!
\property QxtGlobalShortcut::enabled
\brief whether the shortcut is enabled
A disabled shortcut does not get activated.
The default value is \c true.
\sa setDisabled()
*/
bool QxtGlobalShortcut::isEnabled() const {
return qxt_d().enabled;
}
void QxtGlobalShortcut::setEnabled(bool enabled) {
qxt_d().enabled = enabled;
}
/*!
Sets the shortcut \a disabled.
\sa enabled
*/
void QxtGlobalShortcut::setDisabled(bool disabled) {
qxt_d().enabled = !disabled;
}

View File

@@ -1,67 +0,0 @@
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#ifndef QXTGLOBALSHORTCUT_H
#define QXTGLOBALSHORTCUT_H
#include <QObject>
#include <QKeySequence>
#include <QString>
#include "qxtglobal.h"
class QxtGlobalShortcutPrivate;
class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject {
Q_OBJECT
QXT_DECLARE_PRIVATE(QxtGlobalShortcut)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
public:
explicit QxtGlobalShortcut(QObject* parent = nullptr);
explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = nullptr);
~QxtGlobalShortcut();
QKeySequence shortcut() const;
bool setShortcut(const QKeySequence& shortcut);
bool isEnabled() const;
public Q_SLOTS:
void setEnabled(bool enabled = true);
void setDisabled(bool disabled = true);
Q_SIGNALS:
void activated();
};
#endif // QXTGLOBALSHORTCUT_H

View File

@@ -1,207 +0,0 @@
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include <Carbon/Carbon.h>
#include "qxtglobalshortcut_p.h"
#include <QMap>
#include <QHash>
#include <QPair>
#include <QtDebug>
#include <QApplication>
typedef QPair<uint, uint> Identifier;
static QMap<quint32, EventHotKeyRef> keyRefs;
static QHash<Identifier, quint32> keyIDs;
static quint32 hotKeySerial = 0;
static bool qxt_mac_handler_installed = false;
OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) {
Q_UNUSED(nextHandler);
Q_UNUSED(data);
if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed) {
EventHotKeyID keyID;
GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, nullptr, sizeof(keyID), nullptr, &keyID);
Identifier id = keyIDs.key(keyID.id);
QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first);
}
return noErr;
}
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) {
quint32 native = 0;
if (modifiers & Qt::ShiftModifier) native |= shiftKey;
if (modifiers & Qt::ControlModifier) native |= cmdKey;
if (modifiers & Qt::AltModifier) native |= optionKey;
if (modifiers & Qt::MetaModifier) native |= controlKey;
if (modifiers & Qt::KeypadModifier) native |= kEventKeyModifierNumLockMask;
return native;
}
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) {
UTF16Char ch;
// Constants found in NSEvent.h from AppKit.framework
switch (key) {
case Qt::Key_Return: return kVK_Return;
case Qt::Key_Enter: return kVK_ANSI_KeypadEnter;
case Qt::Key_Tab: return kVK_Tab;
case Qt::Key_Space: return kVK_Space;
case Qt::Key_Backspace: return kVK_Delete;
case Qt::Key_Control: return kVK_Command;
case Qt::Key_Shift: return kVK_Shift;
case Qt::Key_CapsLock: return kVK_CapsLock;
case Qt::Key_Option: return kVK_Option;
case Qt::Key_Meta: return kVK_Control;
case Qt::Key_F17: return kVK_F17;
case Qt::Key_VolumeUp: return kVK_VolumeUp;
case Qt::Key_VolumeDown: return kVK_VolumeDown;
case Qt::Key_F18: return kVK_F18;
case Qt::Key_F19: return kVK_F19;
case Qt::Key_F20: return kVK_F20;
case Qt::Key_F5: return kVK_F5;
case Qt::Key_F6: return kVK_F6;
case Qt::Key_F7: return kVK_F7;
case Qt::Key_F3: return kVK_F3;
case Qt::Key_F8: return kVK_F8;
case Qt::Key_F9: return kVK_F9;
case Qt::Key_F11: return kVK_F11;
case Qt::Key_F13: return kVK_F13;
case Qt::Key_F16: return kVK_F16;
case Qt::Key_F14: return kVK_F14;
case Qt::Key_F10: return kVK_F10;
case Qt::Key_F12: return kVK_F12;
case Qt::Key_F15: return kVK_F15;
case Qt::Key_Help: return kVK_Help;
case Qt::Key_Home: return kVK_Home;
case Qt::Key_PageUp: return kVK_PageUp;
case Qt::Key_Delete: return kVK_ForwardDelete;
case Qt::Key_F4: return kVK_F4;
case Qt::Key_End: return kVK_End;
case Qt::Key_F2: return kVK_F2;
case Qt::Key_PageDown: return kVK_PageDown;
case Qt::Key_F1: return kVK_F1;
case Qt::Key_Left: return kVK_LeftArrow;
case Qt::Key_Right: return kVK_RightArrow;
case Qt::Key_Down: return kVK_DownArrow;
case Qt::Key_Up: return kVK_UpArrow;
default:
;
}
if (key == Qt::Key_Escape) ch = 27;
else if (key == Qt::Key_Return) ch = 13;
else if (key == Qt::Key_Enter) ch = 3;
else if (key == Qt::Key_Tab) ch = 9;
else ch = key;
CFDataRef currentLayoutData;
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
if (currentKeyboard == nullptr)
return 0;
currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
CFRelease(currentKeyboard);
if (currentLayoutData == nullptr)
return 0;
UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData);
UCKeyboardTypeHeader* table = header->keyboardTypeList;
uint8_t *data = (uint8_t*)header;
// God, would a little documentation for this shit kill you...
for (quint32 i=0; i < header->keyboardTypeCount; i++) {
UCKeyStateRecordsIndex* stateRec = 0;
if (table[i].keyStateRecordsIndexOffset != 0) {
stateRec = reinterpret_cast<UCKeyStateRecordsIndex*>(data + table[i].keyStateRecordsIndexOffset);
if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0;
}
UCKeyToCharTableIndex* charTable = reinterpret_cast<UCKeyToCharTableIndex*>(data + table[i].keyToCharTableIndexOffset);
if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue;
for (quint32 j=0; j < charTable->keyToCharTableCount; j++) {
UCKeyOutput* keyToChar = reinterpret_cast<UCKeyOutput*>(data + charTable->keyToCharTableOffsets[j]);
for (quint32 k=0; k < charTable->keyToCharTableSize; k++) {
if (keyToChar[k] & kUCKeyOutputTestForIndexMask) {
long idx = keyToChar[k] & kUCKeyOutputGetIndexMask;
if (stateRec && idx < stateRec->keyStateRecordCount) {
UCKeyStateRecord* rec = reinterpret_cast<UCKeyStateRecord*>(data + stateRec->keyStateRecordOffsets[idx]);
if (rec->stateZeroCharData == ch) return k;
}
}
else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) {
if (keyToChar[k] == ch) return k;
}
} // for k
} // for j
} // for i
return 0;
}
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) {
if (!qxt_mac_handler_installed) {
EventTypeSpec t;
t.eventClass = kEventClassKeyboard;
t.eventKind = kEventHotKeyPressed;
InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, nullptr, nullptr);
}
EventHotKeyID keyID;
keyID.signature = 'cute';
keyID.id = ++hotKeySerial;
EventHotKeyRef ref = 0;
bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref);
if (rv) {
keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id);
keyRefs.insert(keyID.id, ref);
}
return rv;
}
bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) {
Identifier id(nativeMods, nativeKey);
if (!keyIDs.contains(id)) return false;
EventHotKeyRef ref = keyRefs.take(keyIDs[id]);
keyIDs.remove(id);
return !UnregisterEventHotKey(ref);
}

View File

@@ -1,72 +0,0 @@
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#ifndef QXTGLOBALSHORTCUT_P_H
#define QXTGLOBALSHORTCUT_P_H
#include "qxtglobalshortcut.h"
#include <QHash>
#include <QAbstractEventDispatcher>
#include <QAbstractNativeEventFilter>
#include <QKeySequence>
class QxtGlobalShortcutPrivate : public QxtPrivate<QxtGlobalShortcut>, public QAbstractNativeEventFilter {
public:
QXT_DECLARE_PUBLIC(QxtGlobalShortcut)
QxtGlobalShortcutPrivate();
~QxtGlobalShortcutPrivate();
bool enabled;
Qt::Key key;
Qt::KeyboardModifiers mods;
bool setShortcut(const QKeySequence& shortcut);
bool unsetShortcut();
static bool error;
#ifndef Q_OS_MACOS
static int ref;
virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result);
#endif // Q_OS_MAC
static void activateShortcut(quint32 nativeKey, quint32 nativeMods);
private:
static quint32 nativeKeycode(Qt::Key keycode);
static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers);
static bool registerShortcut(quint32 nativeKey, quint32 nativeMods);
static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods);
static QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> shortcuts;
};
#endif // QXTGLOBALSHORTCUT_P_H

View File

@@ -1,239 +0,0 @@
#include "qxtglobalshortcut_p.h"
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include <qt_windows.h>
bool QxtGlobalShortcutPrivate::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) {
const quint32 keycode = HIWORD(msg->lParam);
const quint32 modifiers = LOWORD(msg->lParam);
activateShortcut(keycode, modifiers);
}
return false;
}
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) {
// MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN
quint32 native = 0;
if (modifiers & Qt::ShiftModifier)
native |= MOD_SHIFT;
if (modifiers & Qt::ControlModifier)
native |= MOD_CONTROL;
if (modifiers & Qt::AltModifier)
native |= MOD_ALT;
if (modifiers & Qt::MetaModifier)
native |= MOD_WIN;
// TODO: resolve these?
//if (modifiers & Qt::KeypadModifier)
//if (modifiers & Qt::GroupSwitchModifier)
return native;
}
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) {
switch (key) {
case Qt::Key_Escape:
return VK_ESCAPE;
case Qt::Key_Tab:
case Qt::Key_Backtab:
return VK_TAB;
case Qt::Key_Backspace:
return VK_BACK;
case Qt::Key_Return:
case Qt::Key_Enter:
return VK_RETURN;
case Qt::Key_Insert:
return VK_INSERT;
case Qt::Key_Delete:
return VK_DELETE;
case Qt::Key_Pause:
return VK_PAUSE;
case Qt::Key_Print:
return VK_PRINT;
case Qt::Key_Clear:
return VK_CLEAR;
case Qt::Key_Home:
return VK_HOME;
case Qt::Key_End:
return VK_END;
case Qt::Key_Left:
return VK_LEFT;
case Qt::Key_Up:
return VK_UP;
case Qt::Key_Right:
return VK_RIGHT;
case Qt::Key_Down:
return VK_DOWN;
case Qt::Key_PageUp:
return VK_PRIOR;
case Qt::Key_PageDown:
return VK_NEXT;
case Qt::Key_F1:
return VK_F1;
case Qt::Key_F2:
return VK_F2;
case Qt::Key_F3:
return VK_F3;
case Qt::Key_F4:
return VK_F4;
case Qt::Key_F5:
return VK_F5;
case Qt::Key_F6:
return VK_F6;
case Qt::Key_F7:
return VK_F7;
case Qt::Key_F8:
return VK_F8;
case Qt::Key_F9:
return VK_F9;
case Qt::Key_F10:
return VK_F10;
case Qt::Key_F11:
return VK_F11;
case Qt::Key_F12:
return VK_F12;
case Qt::Key_F13:
return VK_F13;
case Qt::Key_F14:
return VK_F14;
case Qt::Key_F15:
return VK_F15;
case Qt::Key_F16:
return VK_F16;
case Qt::Key_F17:
return VK_F17;
case Qt::Key_F18:
return VK_F18;
case Qt::Key_F19:
return VK_F19;
case Qt::Key_F20:
return VK_F20;
case Qt::Key_F21:
return VK_F21;
case Qt::Key_F22:
return VK_F22;
case Qt::Key_F23:
return VK_F23;
case Qt::Key_F24:
return VK_F24;
case Qt::Key_Space:
return VK_SPACE;
case Qt::Key_Asterisk:
return VK_MULTIPLY;
case Qt::Key_Plus:
return VK_ADD;
case Qt::Key_Comma:
return VK_SEPARATOR;
case Qt::Key_Minus:
return VK_SUBTRACT;
case Qt::Key_Slash:
return VK_DIVIDE;
case Qt::Key_MediaNext:
return VK_MEDIA_NEXT_TRACK;
case Qt::Key_MediaPrevious:
return VK_MEDIA_PREV_TRACK;
case Qt::Key_MediaPlay:
return VK_MEDIA_PLAY_PAUSE;
case Qt::Key_MediaStop:
return VK_MEDIA_STOP;
// couldn't find those in VK_*
//case Qt::Key_MediaLast:
//case Qt::Key_MediaRecord:
case Qt::Key_VolumeDown:
return VK_VOLUME_DOWN;
case Qt::Key_VolumeUp:
return VK_VOLUME_UP;
case Qt::Key_VolumeMute:
return VK_VOLUME_MUTE;
// numbers
case Qt::Key_0:
case Qt::Key_1:
case Qt::Key_2:
case Qt::Key_3:
case Qt::Key_4:
case Qt::Key_5:
case Qt::Key_6:
case Qt::Key_7:
case Qt::Key_8:
case Qt::Key_9:
return key;
// letters
case Qt::Key_A:
case Qt::Key_B:
case Qt::Key_C:
case Qt::Key_D:
case Qt::Key_E:
case Qt::Key_F:
case Qt::Key_G:
case Qt::Key_H:
case Qt::Key_I:
case Qt::Key_J:
case Qt::Key_K:
case Qt::Key_L:
case Qt::Key_M:
case Qt::Key_N:
case Qt::Key_O:
case Qt::Key_P:
case Qt::Key_Q:
case Qt::Key_R:
case Qt::Key_S:
case Qt::Key_T:
case Qt::Key_U:
case Qt::Key_V:
case Qt::Key_W:
case Qt::Key_X:
case Qt::Key_Y:
case Qt::Key_Z:
return key;
default:
return 0;
}
}
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) {
return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey);
}
bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) {
return UnregisterHotKey(0, nativeMods ^ nativeKey);
}

View File

@@ -1,236 +0,0 @@
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/
#include "qxtglobalshortcut_p.h"
#include <QtGlobal>
#include <QApplication>
#include <QGuiApplication>
#include <QKeySequence>
#include <QByteArray>
#include <QString>
#include <QVector>
#include <QX11Info>
#include <qpa/qplatformnativeinterface.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <xcb/xcb.h>
#include <xcb/xproto.h>
#include "keymapper_x11.h"
namespace {
const QVector<quint32> maskModifiers = QVector<quint32>() << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask);
typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event);
class QxtX11ErrorHandler {
public:
static bool error;
static int qxtX11ErrorHandler(Display *display, XErrorEvent *event) {
Q_UNUSED(display);
switch (event->error_code) {
case BadAccess:
case BadValue:
case BadWindow:
if (event->request_code == 33 /* X_GrabKey */ ||
event->request_code == 34 /* X_UngrabKey */)
{
error = true;
//TODO:
//char errstr[256];
//XGetErrorText(dpy, err->error_code, errstr, 256);
}
}
return 0;
}
QxtX11ErrorHandler() {
error = false;
m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler);
}
~QxtX11ErrorHandler() {
XSetErrorHandler(m_previousErrorHandler);
}
private:
X11ErrorHandler m_previousErrorHandler;
};
bool QxtX11ErrorHandler::error = false;
class QxtX11Data {
public:
QxtX11Data() {
QPlatformNativeInterface *native = qApp->platformNativeInterface();
//void *display = native->nativeResourceForScreen(QByteArray("display"), QGuiApplication::primaryScreen());
//m_display = reinterpret_cast<Display *>(display);
m_display = QX11Info::display();
}
bool isValid() {
return m_display != nullptr;
}
Display *display() {
Q_ASSERT(isValid());
return m_display;
}
Window rootWindow() {
return DefaultRootWindow(display());
}
bool grabKey(quint32 keycode, quint32 modifiers, Window window) {
QxtX11ErrorHandler errorHandler;
for (int i = 0; !errorHandler.error && i < maskModifiers.size(); ++i) {
XGrabKey(display(), keycode, modifiers | maskModifiers[i], window, True, GrabModeAsync, GrabModeAsync);
}
if (errorHandler.error) {
ungrabKey(keycode, modifiers, window);
return false;
}
return true;
}
bool ungrabKey(quint32 keycode, quint32 modifiers, Window window) {
QxtX11ErrorHandler errorHandler;
foreach (quint32 maskMods, maskModifiers) {
XUngrabKey(display(), keycode, modifiers | maskMods, window);
}
return !errorHandler.error;
}
private:
Display *m_display;
};
} // namespace
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, void *message, long *result) {
Q_UNUSED(result);
xcb_key_press_event_t *kev = nullptr;
if (eventType == "xcb_generic_event_t") {
xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
if ((ev->response_type & 127) == XCB_KEY_PRESS)
kev = static_cast<xcb_key_press_event_t *>(message);
}
if (kev != nullptr) {
unsigned int keycode = kev->detail;
unsigned int keystate = 0;
if(kev->state & XCB_MOD_MASK_1)
keystate |= Mod1Mask;
if(kev->state & XCB_MOD_MASK_CONTROL)
keystate |= ControlMask;
if(kev->state & XCB_MOD_MASK_4)
keystate |= Mod4Mask;
if(kev->state & XCB_MOD_MASK_SHIFT)
keystate |= ShiftMask;
activateShortcut(keycode,
// Mod1Mask == Alt, Mod4Mask == Meta
keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask));
}
return false;
}
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) {
// ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask
quint32 native = 0;
if (modifiers & Qt::ShiftModifier)
native |= ShiftMask;
if (modifiers & Qt::ControlModifier)
native |= ControlMask;
if (modifiers & Qt::AltModifier)
native |= Mod1Mask;
if (modifiers & Qt::MetaModifier)
native |= Mod4Mask;
// TODO: resolve these?
//if (modifiers & Qt::MetaModifier)
//if (modifiers & Qt::KeypadModifier)
//if (modifiers & Qt::GroupSwitchModifier)
return native;
}
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) {
// (davidsansome) Try the table from QKeyMapper first - this seems to be
// the only way to get Keysyms for the media keys.
unsigned int keysym = 0;
int i = 0;
while (KeyTbl[i]) {
if (KeyTbl[i+1] == static_cast<uint>(key)) {
keysym = KeyTbl[i];
break;
}
i += 2;
}
// If that didn't work then fall back on XStringToKeysym
if (!keysym) {
keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data());
if (keysym == NoSymbol)
keysym = static_cast<ushort>(key);
}
QxtX11Data x11;
if (!x11.isValid())
return 0;
return XKeysymToKeycode(x11.display(), keysym);
}
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) {
QxtX11Data x11;
return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow());
}
bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) {
QxtX11Data x11;
return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow());
}

View File

@@ -88,8 +88,9 @@ else(LINUX)
find_package(ALSA)
pkg_check_modules(DBUS dbus-1)
endif(LINUX)
if (NOT APPLE)
if (UNIX AND NOT APPLE)
find_package(X11)
pkg_check_modules(XCB xcb)
endif()
if(X11_FOUND)
set(HAVE_X11 ON)
@@ -118,7 +119,7 @@ if(WIN32)
endif(WIN32)
# QT
set(QT_MIN_VERSION 5.5.1)
set(QT_MIN_VERSION 5.6)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Concurrent Widgets Network Sql)
if(X11_FOUND)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras)
@@ -149,6 +150,17 @@ if(WIN32)
set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::WinExtras)
endif()
if(X11_FOUND)
find_path(KEYSYMDEF_H keysymdef.h PATHS ${X11_INCLUDE_DIR})
find_path(XF86KEYSYM_H XF86keysym.h PATHS ${X11_INCLUDE_DIR})
if(KEYSYMDEF_H)
set(HAVE_KEYSYMDEF_H ON)
endif()
if(XF86KEYSYM_H)
set(HAVE_XF86KEYSYM_H ON)
endif()
endif(X11_FOUND)
# TAGLIB
pkg_check_modules(TAGLIB taglib)
# Only use system taglib if it's greater than 1.11.1
@@ -202,25 +214,6 @@ else(USE_SYSTEM_QTSINGLEAPPLICATION)
set(QTSINGLEAPPLICATION_LIBRARIES qtsingleapplication)
endif(USE_SYSTEM_QTSINGLEAPPLICATION)
# Use system Qxt only if explicitly enabled.
option(USE_SYSTEM_QXT "Use system Qxt library" OFF)
if (USE_SYSTEM_QXT)
message(STATUS "Using system Qxt library")
find_path(QXTCORE_INCLUDE_DIRS qxtglobal.h PATH_SUFFIXES qt5/QxtCore)
find_path(QXTGUI_INCLUDE_DIRS qxtglobalshortcut.h PATH_SUFFIXES qt5/QxtWidgets)
set(QXT_INCLUDE_DIRS ${QXTCORE_INCLUDE_DIRS} ${QXTGUI_INCLUDE_DIRS})
# We only need its header. We don't need to link to QxtCore.
find_library(QXT_LIBRARIES QxtWidgets-qt5)
else (USE_SYSTEM_QXT)
message(STATUS "Using builtin Qxt library")
add_definitions(-DQXT_STATIC -DBUILD_QXT_GUI -DBUILD_QXT_CORE)
set(QXT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qxt)
set(QXT_LIBRARIES qxt)
if (NOT APPLE)
add_subdirectory(3rdparty/qxt)
endif (NOT APPLE)
endif (USE_SYSTEM_QXT)
# Qocoa
set(QOCOA_LIBRARIES Qocoa)
add_subdirectory(3rdparty/qocoa)
@@ -288,10 +281,18 @@ else ()
)
endif()
optional_component(CHROMAPRINT ON "Chromaprint support / Tag fetching from Musicbrainz"
optional_component(CHROMAPRINT ON "Chromaprint (Tag fetching from Musicbrainz)"
DEPENDS "chromaprint" CHROMAPRINT_FOUND
)
if (X11_FOUND OR HAVE_DBUS OR APPLE OR WIN32)
set(HAVE_GLOBALSHORTCUTS_SUPPORT ON)
endif()
optional_component(GLOBALSHORTCUTS ON "Global shortcuts"
DEPENDS "D-Bus, X11, Windows or macOS" HAVE_GLOBALSHORTCUTS_SUPPORT
)
optional_component(AUDIOCD ON "Devices: Audio CD support"
DEPENDS "libcdio" CDIO_FOUND
)
@@ -325,7 +326,7 @@ optional_component(IMOBILEDEVICE ON "Devices: iPod Touch, iPhone, iPad support"
)
optional_component(SPARKLE ON "Sparkle integration"
DEPENDS "Mac OS X" APPLE
DEPENDS "macOS" APPLE
DEPENDS "Sparkle" SPARKLE
)

16
dist/debian/copyright vendored
View File

@@ -47,6 +47,14 @@ Files: src/core/main.h
src/covermanager/lastfmcoverprovider.h
src/covermanager/musicbrainzcoverprovider.cpp
src/covermanager/musicbrainzcoverprovider.h
src/globalshortcuts/globalshortcutbackend-system.cpp
src/globalshortcuts/globalshortcutbackend-system.h
src/globalshortcuts/globalshortcut.cpp
src/globalshortcuts/globalshortcut.h
src/globalshortcuts/globalshortcut-X11.cpp
src/globalshortcuts/globalshortcut-win.cpp
src/globalshortcuts/keymapper_x11.h
src/globalshortcuts/keymapper_win.h
src/lyrics/*
src/scrobbler/*
src/tidal/*
@@ -102,6 +110,10 @@ Files: src/core/main.cpp
src/device/deviceview.h
src/device/connecteddevice.cpp
src/device/connecteddevice.h
src/globalshortcuts/globalshortcuts.cpp
src/globalshortcuts/globalshortcuts.h
src/settings/shortcutssettingspage.cpp
src/settings/shortcutssettingspage.h
Copyright: 2010, 2012-2014 David Sansome <me@davidsansome.com>
2012-2014, 2017-2018 Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
@@ -249,10 +261,6 @@ Files: 3rdparty/qtsingleapplication/*
Copyright: 2010, Nokia Corporation and/or its subsidiary(-ies).
License: BSD-3-clause
Files: 3rdparty/qxt/*
Copyright: 2006-2011, the LibQxt project <foundation@libqxt.org>
License: BSD-3-clause
Files: 3rdparty/taglib/*
Copyright: 2002-2008, Scott Wheeler
License: LGPL-2.1 and/or MPL-1.1

View File

@@ -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)

View File

@@ -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

View File

@@ -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()));

View File

@@ -363,7 +363,7 @@ QString ColorToRgba(const QColor &c) {
}
#ifdef Q_OS_MACOS
qint32 GetMacVersion() {
qint32 GetMacOsVersion() {
SInt32 minor_version;
Gestalt(gestaltSystemVersionMinor, &minor_version);

View File

@@ -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 {

View 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;
}

View 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;
}

View 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();
}
}

View 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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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

View 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

View File

@@ -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
}

View File

@@ -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

View 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

View 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

View File

@@ -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"));

View File

@@ -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"));
}
}
}

View File

@@ -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_;

View File

@@ -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&amp;fault</string>
<string>&amp;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>

View File

@@ -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_;