125 Commits

Author SHA1 Message Date
Jacob Greenfield 6f2603c6b6 Rename MASPickAllCocoaModifiers to MASPickModifiersIncludingFn 2022-10-17 21:07:33 -07:00
Jacob Greenfield 8d52bb87c9 Add MASPickAllCocoaModifiers (including fn key) for comparisons 2022-10-17 21:07:33 -07:00
Jacob Greenfield 7fb5f964f1 Add fn key to MASPickCocoaModifiers 2022-10-17 21:07:33 -07:00
Chiahong Hong a90bab0292 Update zh-Hant localization 2022-08-29 22:58:28 -07:00
Dave Nicolson bcdb93900f Revert "Fix 'Double-quoted include "MASxxxxx.h" in framework header, expected angle-bracketed instead' warning"
This reverts commit 031e561ce8.
2022-07-28 09:14:17 -07:00
miximka 031e561ce8 Fix 'Double-quoted include "MASxxxxx.h" in framework header, expected angle-bracketed instead' warning 2022-07-03 12:47:13 -07:00
Ethan Wong 6ddfd5f866 Allow 'Services' menu items to pass the shortcut validation. 2022-04-15 15:13:57 -07:00
Ethan Wong 57ccb01886 Support for generating correct keyEquivalents for function keys. 2021-10-21 23:39:39 +03:00
Maxim Ananov d151094502 Removed an orphaned symlink 2021-09-25 04:40:07 +03:00
Maxim Ananov f186b87231 Removed obsolete MASKeyMasks.h 2021-09-25 01:53:47 +03:00
Maxim Ananov b38e38f892 Fixed .framework compilation 2021-09-24 23:59:33 +03:00
Sanjay Madan ce0c8d85df Fix typo from replacement of deprecated constants 2021-06-27 10:11:28 +01:00
SweetPPro 28f1f6a56d really fix symlinks in include folder 2021-06-27 10:04:29 +01:00
SweetPPro 105614eed0 fixed symlinks in include folder 2021-06-27 10:04:29 +01:00
SweetPPro 3664c4179b Fix Display on macOS Big Sur 2021-06-27 10:04:29 +01:00
SweetPPro 474b730b78 Update README.md with SPM installation and usage 2021-06-27 10:04:29 +01:00
SweetPPro 352c7003f9 fix spm for Swift projects 2021-06-27 10:04:29 +01:00
SweetPPro 1b7ac3dcfa spm support 2021-06-27 10:04:29 +01:00
Vadim Shpakovski 03187327f0 Update Pod spec 2021-03-05 07:36:16 +00:00
Dzmitry Neviadomski 4b3095535d Use replacements instead of deprecated constants. 2021-03-05 07:35:41 +00:00
Dzmitry Neviadomski f082e8a161 Apply Xcode recommended settings. 2021-02-28 22:30:21 +03:00
Michael Tsai 1d8629c8d8 Make MASShortcutView an accessibility element. #152
This makes it possible to select it using VoiceOver and prevents the system from ignoring the accessibility notification that's posted when the shortcut is changed.
2021-01-21 12:37:43 +03:00
Maxim Ananov 592d0deb8d Added regularSquare style to MASShortcutView 2020-10-23 09:53:32 +03:00
Davide Pedron 38df51c808 Update Italian translation
Use the word 'abbreviazione' instead of 'scorciatoia' as Apple's translations.
Fix accent (perchè -> perché).
Use a less formal formal style as in Apple's menu.
2020-05-28 22:56:53 +03:00
Darío Hereñú 2ca3d08911 Update translation (following the Apple Guidelines)
* plus some minor fixes
2019-11-05 00:50:24 +03:00
Darío Hereñú 937ef61302 Some translation are misspelled, so fixed 2019-11-05 00:50:24 +03:00
Vinh Nguyen b3e3b79626 Unbind if newKey is nil 2019-07-29 11:11:44 +03:00
Tomáš Znamenáček 17b6a748f6 Merge pull request #134 from shpakovski/feature/nullability-annotations
Add nullability annotations
2019-06-12 15:39:29 +02:00
Tomáš Znamenáček a6d27c2621 Add nullability annotations to MASShortcutView 2019-06-11 14:47:26 +02:00
Tomáš Znamenáček e02400371f Add nullability annotations to MASShortcut
Mostly it’s safely `nonnull`, I just wasn’t sure for `keyCodeString`
and `keyCodeStringForKeyEquivalent`, so I went for the safe option and
declared those `nullable`.
2019-06-11 14:36:39 +02:00
Tomáš Znamenáček 10001acbf6 Release 2.4.0 2019-06-11 12:47:47 +02:00
Tomáš Znamenáček 3383d87ecb Merge pull request #132 from shpakovski/feature/cocoapods-release
Fix CocoaPods build
2019-06-11 12:46:33 +02:00
Tomáš Znamenáček ab2f247992 Update Deployment Target mentioned in docs 2019-06-11 12:21:47 +02:00
Tomáš Znamenáček afca3a410b Add pod linting to Travis builds
This should make it less probable that we break the CocoaPods build without knowing it.
2019-06-11 12:19:49 +02:00
Tomáš Znamenáček 46b6e62a6a Simplify Deployment Target setting in Xcode
The MASShortcut and MASShortcutTests targets should inherit the project’s
Deployment Target setting, not set their own. Effectively nothing changes,
the Deployment Target is still 10.10 for both targets.
2019-06-11 12:07:11 +02:00
Tomáš Znamenáček 4dcea4bb08 Fix Deployment Target specified in podspec
Somewhere in the past we have bumped Deployment Target for the framework
to 10.10, but forgot to also bump the Deployment Target setting in the podspec,
leading to CocoaPods building the framework with different options. This lead
to mysterious warnings (#131) that were only visible in some CocoaPods builds.

This change fixes the CocoaPods Deployment Target to be the same as in the
Xcode project, ie. 10.10.
2019-06-11 12:04:37 +02:00
Tomáš Znamenáček d3dc31a7fb Merge pull request #130 from shpakovski/feature/project-improvements
Project & release process improvements
2019-06-03 17:41:06 +02:00
Tomáš Znamenáček f987cb0680 Try fixing Bundler version mismatch on Travis 2019-06-03 11:56:58 +02:00
Tomáš Znamenáček b846358d73 Document the new release process 2019-06-03 11:40:38 +02:00
Tomáš Znamenáček a117bf5dee Update .gitignore for Fastlane 2019-06-03 11:40:38 +02:00
Tomáš Znamenáček 2239ac2ec7 Set version number using agvtool
This is needed so that Fastlane may update the version number automatically.
2019-06-03 11:40:38 +02:00
Tomáš Znamenáček d86757c434 Add Fastlane action to mint a new release
Run `bundle exec fastlane release` to update the changelog, bump version
number, add a new tag and commit the release.
2019-06-03 11:40:38 +02:00
Tomáš Znamenáček d02bfb1732 Update changelog 2019-06-03 11:40:38 +02:00
Tomáš Znamenáček 8c0ff79452 Convert changelog to the keepachangelog.com format
This will make it possible to update the changelog automatically in future.
2019-06-03 10:56:22 +02:00
Tomáš Znamenáček 8bc3635a92 Update podspec to automatically point to the last version
Otherwise it’s quite easy to forget to update the commit pointer.
2019-06-03 10:49:11 +02:00
Tomáš Znamenáček ce3b7d9179 Add Fastlane changelog plugin
We will use the plugin to automate changelog updates in the future.
2019-06-03 10:44:15 +02:00
Tomáš Znamenáček f144290909 Bundle Fastlane and CocoaPods
We already use CocoaPods and would like to start using Fastlane.
To improve build reproducibility, it’s good to have the same versions
of the toolchain, so we specify tool versions in the repo. The tools
can then be installed and run using Bundler:

    bundle install # only first time, gems will end up in .bundle/
    bundle exec pod lib lint # for example
2019-06-03 09:04:37 +02:00
Tomáš Znamenáček e0b9bc7004 Switch to folder-backed Xcode file groups
This makes sure the on-disk project structure matches the tree view shown in Xcode.
2019-06-03 08:56:47 +02:00
Tomáš Znamenáček 844970408a Move localization files to a common folder
They were making the root project folder too crowded.
2019-06-03 08:50:14 +02:00
Tomáš Znamenáček cf7b2d8a4f Merge pull request #127 from shpakovski/feature/no-validation
Make it possible to turn off shortcut validation
2019-06-02 10:47:38 +02:00
Tomáš Znamenáček 4843c0708f Merge pull request #128 from shpakovski/feature/numeric-types
Use more specific types for -keyCode and -modifierFlags
2019-06-02 10:47:07 +02:00
Tomáš Znamenáček 0ba254c9db Merge pull request #129 from shpakovski/feature/nsevent-constants
Use NSEvent constants instead of hard-coded numbers, fixes #121
2019-06-02 10:46:28 +02:00
Tomáš Znamenáček 76ff9e14d8 Use NSEvent constants instead of hard-coded numbers, fixes #121 2019-05-31 17:02:06 +02:00
Tomáš Znamenáček 85d096792f Use more specific types for -keyCode and -modifierFlags
It was initially suggested in #103 that we change -keyCode to NSInteger
and -modifierFlags to NSEventModifierFlags, but the changes were mixed
with other unrelated stuff and the discussion died out. But the main
point of the proposed patch was good, the suggested types make the code
work better in Swift, apart from other things.
2019-05-31 16:16:52 +02:00
Tomáš Znamenáček 94763f73be Merge pull request #126 from shpakovski/feature/extension-support
Allow app extension API only for the framework target
2019-05-24 15:20:34 +02:00
Tomáš Znamenáček df65d89351 Make it possible to turn off shortcut validation
Previously, setting a nil `shortcutValidator` on `MASShortcutView` would
lead to all shortcuts considered invalid. I think it’s better the other
way around, where setting “no validator” means the caller wants no validation
done at all.

(I actually have a use case for this. Under normal circumstances, recording
keys with no validation doesn’t have much sense, but I use `MASShortcutView`
to record shortcuts that will be used in a different context, in the browser.)
2019-05-24 11:25:39 +02:00
Tomáš Znamenáček c6376de97a Allow app extension API only for the framework target
When MASShortcut is used in an app extension, Xcode generates a warning:

> linking against a dylib which is not safe for use in application extensions

I have checked the “Allow app extension API only” for the MASShortcut
target that should clear this warning.
2019-05-24 09:22:26 +02:00
Fletcher T. Penney 42f02fddc1 Provide intrinsicContenSize to improve compatibility with autolayout 2019-05-04 19:07:02 +03:00
Vadim Shpakovski 639bee0e71 Remove warnings in Xcode 10.1 2019-02-27 17:16:32 +03:00
Craig Hockenberry 53186d9c74 Updates for NSAppearance 2019-02-27 17:16:32 +03:00
Tomáš Znamenáček 887f3ddb8c Merge pull request #116 from saagarjha/master
Replace commas with semicolons to separate statements
2018-06-12 10:36:35 +02:00
Saagar Jha f19f2ba028 Replace commas with semicolons to separate statements 2018-06-12 01:07:55 -07:00
Tomáš Znamenáček 32a1aa3e5e Merge pull request #120 from pavelkozarek/swedish_localization
Add Swedish localization
2018-06-11 16:37:11 +02:00
Tomáš Znamenáček 9b6219ea1f Try fixing Travis build errors 2018-06-11 16:32:48 +02:00
Pavel Kozarek 20416b0641 Swedish localization. 2018-06-11 11:48:14 +02:00
Dan Messing def4890af2 remove implicit retain of self in eventMonitor block (#119) 2018-05-18 11:45:18 +03:00
Vadim Shpakovski 881157bfd6 Merge pull request #110 from exevil/master
kVK_ANSI_KeypadMinus value adjustment.
2017-05-22 14:51:53 +03:00
Vyacheslav Dubovitsky ff3bbb3c49 kVK_ANSI_KeypadMinus value adjustment.
kVK_ANSI_KeypadMinus should return regular HYPHEN-MINUS (45) symbol instead of provided EN DASH (8211).
2017-05-21 01:08:24 +02:00
Vadim Shpakovski a4a541444c Merge pull request #108 from vitu/master
Brazilian Portuguese localization
2017-03-16 10:53:45 +03:00
Victor b0dd8deed9 pt localization taking in consideration space constraints usually imposed by shortcut recording interfaces.
Also note that in the string: "… most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences", the correct path should be Keyboard, as this pane has been split in two for a while on macOS.
2017-03-15 19:44:20 -04:00
Vadim Shpakovski 7b265ca3ae Merge pull request #104 from tonyarnold/fix/install-name-base
Set DYLIB_INSTALL_NAME_BASE to @rpath
2016-12-07 14:46:57 +03:00
Tony Arnold 5ef03d07de Set LD_RUNPATH_SEARCH_PATHS to more appropriate value 2016-12-07 22:37:24 +11:00
Tony Arnold 04a892f9ec Set DYLIB_INSTALL_NAME_BASE to @rpath 2016-12-07 22:32:35 +11:00
Vadim Shpakovski 64c657331c Add default shortcut to Demo app 2016-12-06 16:03:55 +03:00
Tomáš Znamenáček b54c1edbf4 Merge pull request #100 from tonyarnold/enums
Minor fixes and Swift improvements
2016-11-01 07:52:58 +01:00
Tony Arnold e73de450ad Fix return from a NSToolTip method that expects a non-null return value
Signed-off-by: Tony Arnold <tony@thecocoabots.com>
2016-11-01 09:49:55 +11:00
Tony Arnold 4e98f342e4 Use properly typedef’d enumerations to improve Swift syntax
Signed-off-by: Tony Arnold <tony@thecocoabots.com>
2016-11-01 09:49:08 +11:00
Tomáš Znamenáček f743bdaa5b Release 2.3.6 2016-10-30 09:51:39 +01:00
Tomáš Znamenáček 6444d3f9a2 Fix wrong header import 2016-10-28 15:10:19 +02:00
Tomáš Znamenáček e7f7ee50a6 Using numerical value instead of the __MAC_10_12 symbol 2016-10-28 15:05:17 +02:00
Tomáš Znamenáček 7dfde95369 Key mask conditional compilation fix #2 2016-10-28 14:59:31 +02:00
Tomáš Znamenáček 0d54ede869 Trying to fix conditional key mask definition on 10.12 2016-10-28 14:52:37 +02:00
Tomáš Znamenáček f12ed861b0 Use modern key mask constants instead of the ones deprecated in 10.12
See #99 for details.
2016-10-28 14:40:32 +02:00
Tomáš Znamenáček bf4329178d Update build warnings as suggested by Xcode 8 2016-10-28 13:10:58 +02:00
Tomáš Znamenáček 0e0bc77433 Release 2.3.5 2016-09-07 08:56:18 +02:00
Tomáš Znamenáček 37b480f32a Improve Italian localization 2016-09-07 08:53:17 +02:00
Tomáš Znamenáček 2d1bb41d0c Link to a commit message writing guide 2016-08-12 11:53:26 +02:00
Tomáš Znamenáček 409699c3c0 Version bump to 2.3.4 2016-08-12 11:49:17 +02:00
Vadim Shpakovski 928bbe25b4 Upgrade Projects to Xcode 7 2016-08-08 18:24:19 +03:00
Vadim Shpakovski 658a4e1e78 Merge pull request #94 from sfsam/master
Added Makefile to build from the command line
2016-07-15 09:45:59 +03:00
Sanjay Madan bd3cf9bf9c Added Makefile to build from the command line 2016-07-14 22:12:06 -07:00
Vadim Shpakovski a4dd585497 Merge pull request #93 from pointum/master
ru localization update
2016-07-13 17:35:07 +03:00
Maxim Ananov 843cb81697 ru localization update 2016-07-13 17:26:02 +03:00
Tomáš Znamenáček 9471ddbc7c Update CHANGES 2016-04-14 10:08:23 +02:00
Vadim Shpakovski 46bd84f57d Merge pull request #89 from radex/add-translations
Add Korean, Dutch, Polish, Russian & update Spanish translations
2016-04-14 11:04:37 +03:00
radex 6233bfac56 Add ko, nl, pl, ru, es translations 2016-04-14 09:55:34 +02:00
Tomáš Znamenáček 03e3ed398a Use correct quote signs for German translation.
The quotes should be like „this“, not ‘this’.
2016-02-14 09:44:45 +01:00
Tomáš Znamenáček 00b5041867 Shortened the new German translation strings to fit the UI.
Closes #85.
2016-02-14 09:41:52 +01:00
Tomáš Znamenáček 69b0a06656 Added basic German localization to the demo project.
This makes it possible to test the German MASShortcut localization
on the demo project.
2016-02-10 19:13:53 +01:00
Tomáš Znamenáček abb1ac2799 Updated CHANGES. 2016-02-05 10:07:59 +01:00
Vadim Shpakovski 9bbb5b3e6a Merge pull request #84 from floschliep/master
Improve German Localization
2016-02-05 09:30:17 +01:00
Florian Schliep 00dd8616f1 Improved German Localization
I translated the missing strings and improved the existing ones.
2016-02-04 18:56:50 +01:00
Tomáš Znamenáček d359752bef Updated CHANGES. 2016-01-22 10:29:17 +01:00
Tomáš Znamenáček 6b80ea95b5 Merge pull request #83 from MichaelRow/master
Simplified and traditional Chinese localizations.
2016-01-22 10:28:06 +01:00
MichaelRow 8e14c20ca4 Simplified and traditional Chinese localizations. 2016-01-22 12:04:51 +08:00
Tomáš Znamenáček d0063130b5 Version bump to 2.3.3. 2016-01-09 15:51:28 +01:00
Tomáš Znamenáček c384d0e94b Updated CHANGES. 2016-01-09 15:47:06 +01:00
Tomáš Znamenáček e267d30bfd Whitespace fixes. 2016-01-09 15:45:45 +01:00
Nikita Ivanchikov d32fc188ca Another approach to try a fix for the CocoaPods localization bundle problem (#74).
Checking if resources bundle was copied inside framework bundle, then falling back to old search methods
2016-01-09 15:43:05 +01:00
Tomáš Znamenáček 2b2fb80556 Updated changelog. 2015-12-06 16:08:46 +01:00
Tomáš Znamenáček 60978895b2 Merge pull request #80 from magiclantern/magiclantern/french-localization
Expanded Frech localization.
2015-12-06 16:07:10 +01:00
Nikita Ourazbaev 6a97ae68e9 Some suggestions for fr
Some suggestions for the gaps in the French localization
2015-12-06 10:04:45 -05:00
Tomáš Znamenáček 29d047c928 Documented that we don’t accept Option-Shift shortcuts by default.
The reason is that Option-Shift shortcuts are often already used
by system to insert some special characters. See `MASShortcutValidator`
for details, including how to enable support for these shortcuts.
Fixes #79.
2015-12-03 15:15:05 +01:00
Tomáš Znamenáček 5a18ccc5e1 Even more elaborate workaround for the CocoaPods localization problem (#74).
Just testing if the CocoaPods bundle is present didn’t work, so now we
even try to load a localized string from the bundle.
2015-11-06 08:59:52 +01:00
Tomáš Znamenáček e83732400b Trying a fix for the CocoaPods localization bundle problem (#74).
This change simply doesn’t try to detect which bundle we should use
and tries both bundles, the CocoaPods one first. The chosen bundle is
then cached to avoid the overhead on subsequent requests.
2015-11-04 15:02:55 +01:00
Tomáš Znamenáček 2730683848 Updated CHANGES. 2015-10-31 10:26:15 +01:00
Vadim Shpakovski 471322a113 Merge pull request #77 from oreshinya/japanese_localization
Japanese localization
2015-10-14 20:16:16 +03:00
shinya takahashi 09b7364130 Japanese localization 2015-10-14 18:44:06 +09:00
Tomáš Znamenáček 82a06382f0 Version bump to 2.3.2. 2015-10-12 09:31:34 +02:00
Tomáš Znamenáček dd2507b7f9 Silenced a potential “tautological compare” warning in MASShortcutView.
Fixes #76. I considered putting the #pragma just around the particular
compare line, but I think having it around the whole block is more readable
and there’s little chance of having some legitimate warnings silenced.
2015-10-12 09:28:19 +02:00
Tomáš Znamenáček a0af086f16 Typo fix. 2015-10-08 11:53:21 +02:00
Tomáš Znamenáček a73a254ce7 Documented the CocoaPods localization fix. 2015-10-08 11:30:24 +02:00
Tomáš Znamenáček ed694bc1a5 Merge pull request #75 from beaufour/master
Fixed localization when used from CocoaPods.
2015-10-08 11:26:27 +02:00
Allan Beaufour ded95506c6 fixes localized strings when using CocoaPods
Puts strings inside a MASShortcut resource bundle, and looks for
locallized strings inside that bundle when used as a CocoaPod
2015-10-07 12:52:59 -04:00
Tomáš Znamenáček b99a1a4dc4 Updated localization and accessibility status in README. 2015-09-10 10:01:40 +02:00
84 changed files with 1716 additions and 497 deletions
+6 -1
View File
@@ -13,5 +13,10 @@ build/*
xcuserdata
profile
*.moved-aside
.bundle
Fastlane/README.md
Fastlane/report.xml
# Finder
.DS_Store
.DS_Store
.swiftpm
.build
+3 -2
View File
@@ -1,3 +1,4 @@
language: objective-c
xcode_project: MASShortcut.xcodeproj
xcode_scheme: MASShortcut
script:
- xcodebuild -scheme MASShortcut build test
- bundle exec pod lib lint
+68
View File
@@ -0,0 +1,68 @@
Details about this files format at <http://keepachangelog.com/>. The change log is parsed automatically when minting releases through Fastlane, see `Fastlane/Fastfile`.
## [Unreleased]
## [2.4.0] - 2019-06-11
- Use properly typedefd enumerations to improve Swift syntax [Tony Arnold]
- Fix return from a NSToolTip method that expects a non-null return value [Tony Arnold]
- Brazilian Portuguese localization [vitu]
- `kVK_ANSI_KeypadMinus` fixes [Vyacheslav Dubovitsky]
- Swedish localization [Pavel Kozárek]
- Provide intrinsicContenSize to improve compatibility with autolayout [Fletcher T. Penney]
- Allow app extension API only for the framework target [zoul]
- Make it possible to turn off shortcut validation [zoul]
- Use more specific types for -keyCode and -modifierFlags [zoul]
- Use NSEvent constants instead of hard-coded numbers [zoul]
## [2.3.6] - 2016-10-30
- Improve compatibility with the 10.12 SDK [thanks to Clemens Schulz]
## [2.3.5] - 2016-9-7
- Improve Italian localization [zoul]
## [2.3.4] - 2016-8-12
- Simplified and traditional Chinese localization [MichaelRow]
- Add Korean, Dutch, Polish, Russian & update Spanish localizations [Radek Pietruszewski]
- Improved German localization [Florian Schliep]
- Add a Makefile to improve command-line building [sfsam]
## [2.3.3] - 2016-1-9
- Improved Japanese localization [oreshinya]
- Improved Frech localization [magiclantern]
- Fixed CocoaPods localization with `use_frameworks!` [nivanchikov]
## [2.3.2] - 2015-10-12
- Fixed localization when building through CocoaPods [Allan Beaufour]
## [2.3.1] - 2015-9-10
- Trying to work around a strange build error in CocoaPods.
## [2.3.0] - 2015-9-10
- Basic localization support for Czech, German, Spanish, Italian, French, and Japanese. Native speaking testers welcome!
## [2.2.0] - 2015-8-18
- Basic accessibility support [starkos]
- Added an option to hide the shortcut delete button [oreshinya]
- Advertised support for Carthage [Tom Brown]
- Bugfix for shortcuts not working after set twice [Roman Sokolov]
- Ignore a solo Tab key when recording shortcuts [Roman Sokolov]
## [2.1.2] - 2015-1-28
- Better key equivalent handling for non-ASCII layouts. [Dmitry Obukhov]
## [2.1.1] - 2015-1-16
- Another headerdoc fix for CocoaDocs, hopefully the last one.
## [2.1.0] - 2015-1-16
- Added support for older OS X versions down to 10.6 included.
- Headerdoc markup that plays better with CocoaDocs.
## [2.0.1] - 2015-1-9
- Trivial Podspec fix.
## [2.0.0] - 2015-1-9
- First version with a changes file :)
- Major, backwards incompatible refactoring to simplify long-term maintenance.
- Added a simple spec describing the recording behaviour.
- Adds compatibility mode with Shortcut Recorder.
-33
View File
@@ -1,33 +0,0 @@
2.3.1 2015/9/10
- Trying to work around a strange build error in CocoaPods.
2.3.0 2015/9/10
- Basic localization support for Czech, German, Spanish,
Italian, French, and Japanese. Native speaking testers welcome!
2.2.0 2015/8/18
- Basic accessibility support [starkos]
- Added an option to hide the shortcut delete button [oreshinya]
- Advertised support for Carthage [Tom Brown]
- Bugfix for shortcuts not working after set twice [Roman Sokolov]
- Ignore a solo Tab key when recording shortcuts [Roman Sokolov]
2.1.2 2015/1/28
- Better key equivalent handling for non-ASCII layouts.
[Dmitry Obukhov]
2.1.1 2015/1/16
- Another headerdoc fix for CocoaDocs, hopefully the last one.
2.1.0 2015/1/16
- Added support for older OS X versions down to 10.6 included.
- Headerdoc markup that plays better with CocoaDocs.
2.0.1 2015/1/9
- Trivial Podspec fix.
2.0.0 2015/1/9
- First version with a changes file :)
- Major, backwards incompatible refactoring to simplify long-term maintenance.
- Added a simple spec describing the recording behaviour.
- Adds compatibility mode with Shortcut Recorder.
-29
View File
@@ -1,29 +0,0 @@
# Backward Compatibility
Please note that this framework supports older OS X versions down to 10.6. When changing the code, be careful not to call any API functions not available in 10.6 or call them conditionally, only where supported.
# Commit Messages
Please use descriptive commit message. As an example, _Bug fix_ commit message doesnt say much, while _Fixed a memory-management bug in formatting code_ works much better.
# How to Release a New Version
First, update the version numbers. (MASShortcut uses [Semantic Versioning](http://semver.org/), so please read the docs if youre not sure what the deal is.) The version number is stored in `Framework/Info.plist` and `MASShortcut.podspec` (twice in both files).
Then update the `CHANGES` file. Add information about the new version (see the previous versions for an example) and add the release date.
Now commit the changes:
$ git commit -a -m "Version bump to x.y.z."
And tag the last commit:
$ git tag -a x.y.z
Now push both the commits and tags (`--tags`) to GitHub and push the new podspec to CocoaPods:
$ pod trunk push MASShortcut.podspec
This will run sanity checks on the podspec and fail if the spec does not validate.
Thats it. Go have a beer or a cup of tea to celebrate.
+89 -3
View File
@@ -9,6 +9,7 @@ static void *MASObservingContext = &MASObservingContext;
@interface AppDelegate ()
@property(strong) IBOutlet MASShortcutView *customShortcutView;
@property(strong) IBOutlet NSTextField *feedbackTextField;
@property(strong) IBOutlet NSVisualEffectView *visualEffectView;
@end
@implementation AppDelegate
@@ -19,10 +20,15 @@ static void *MASObservingContext = &MASObservingContext;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Most apps need default shortcut, delete these lines if this is not your case
MASShortcut *firstLaunchShortcut = [MASShortcut shortcutWithKeyCode:kVK_F1 modifierFlags:NSEventModifierFlagCommand];
NSData *firstLaunchShortcutData = [NSKeyedArchiver archivedDataWithRootObject:firstLaunchShortcut];
// Register default values to be used for the first app start
[defaults registerDefaults:@{
MASHardcodedShortcutEnabledKey : @YES,
MASCustomShortcutEnabledKey : @YES,
MASCustomShortcutKey : firstLaunchShortcutData
}];
// Bind the shortcut recorder views value to user defaults.
@@ -46,9 +52,9 @@ static void *MASObservingContext = &MASObservingContext;
- (void)playShortcutFeedback
{
[[NSSound soundNamed:@"Ping"] play];
[_feedbackTextField setStringValue:NSLocalizedString(@"Shortcut pressed!", @"Feedback thats displayed when user presses the sample shortcut.")];
[self.feedbackTextField setStringValue:NSLocalizedString(@"Shortcut pressed!", @"Feedback thats displayed when user presses the sample shortcut.")];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[_feedbackTextField setStringValue:@""];
[self.feedbackTextField setStringValue:@""];
});
}
@@ -83,7 +89,7 @@ static void *MASObservingContext = &MASObservingContext;
- (void) setHardcodedShortcutEnabled: (BOOL) enabled
{
MASShortcut *shortcut = [MASShortcut shortcutWithKeyCode:kVK_F2 modifierFlags:NSCommandKeyMask];
MASShortcut *shortcut = [MASShortcut shortcutWithKeyCode:kVK_F2 modifierFlags:NSEventModifierFlagCommand];
if (enabled) {
[[MASShortcutMonitor sharedMonitor] registerShortcut:shortcut withAction:^{
[self playShortcutFeedback];
@@ -93,6 +99,86 @@ static void *MASObservingContext = &MASObservingContext;
}
}
#pragma mark Actions
// These actions let you configure the NSVisualEffect view and test the MASShortcutView in a variety of scenarios.
- (void) displayMojaveAlertWithMessage: (NSString *) message
{
NSAlert *alert = [NSAlert new];
alert.messageText = @"Not Available";
alert.informativeText = [NSString stringWithFormat:@"The %@ is only available on Mojave (10.14) and later", message];
[alert addButtonWithTitle:@"OK"];
[alert runModal];
}
- (IBAction) setAppearance: (id) sender
{
if ([sender isKindOfClass:[NSPopUpButton class]]) {
NSPopUpButton *popUpButton = (NSPopUpButton *)sender;
NSInteger tag = popUpButton.selectedTag;
switch (tag) {
case 0: // Inherited
self.visualEffectView.appearance = nil;
break;
case 1: // Vibrant Light
self.visualEffectView.appearance = [NSAppearance appearanceNamed:NSAppearanceNameVibrantLight];
break;
case 2: // Vibrant Dark
self.visualEffectView.appearance = [NSAppearance appearanceNamed:NSAppearanceNameVibrantDark];
break;
case 3: // Aqua
self.visualEffectView.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
break;
case 4: // Dark Aqua
if (@available(macOS 10.14, *)) {
self.visualEffectView.appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
} else {
[self displayMojaveAlertWithMessage:@"Dark Aqua Appearance"];
}
break;
default:
break;
}
}
}
- (IBAction) setMaterial: (id) sender
{
if ([sender isKindOfClass:[NSPopUpButton class]]) {
NSPopUpButton *popUpButton = (NSPopUpButton *)sender;
NSInteger tag = popUpButton.selectedTag;
switch (tag) {
case 0: // Popover
self.visualEffectView.material = NSVisualEffectMaterialPopover;
break;
case 1: // Sidebar
self.visualEffectView.material = NSVisualEffectMaterialSidebar;
break;
case 2: // HUD Window
if (@available(macOS 10.14, *)) {
self.visualEffectView.material = NSVisualEffectMaterialHUDWindow;
} else {
[self displayMojaveAlertWithMessage:@"HUD Window Material"];
}
break;
case 3: // Window Background
if (@available(macOS 10.14, *)) {
self.visualEffectView.material = NSVisualEffectMaterialWindowBackground;
} else {
[self displayMojaveAlertWithMessage:@"Window Background Material"];
}
break;
default:
break;
}
}
}
#pragma mark NSApplicationDelegate
- (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication*) sender
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="8173.3" systemVersion="14E46" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="8173.3"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@@ -155,8 +156,7 @@
<action selector="paste:" target="-1" id="226"/>
</connections>
</menuItem>
<menuItem title="Paste and Match Style" keyEquivalent="V" id="485">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<menuItem title="Paste and Match Style" keyEquivalent="v" id="485">
<connections>
<action selector="pasteAsPlainText:" target="-1" id="486"/>
</connections>
@@ -649,18 +649,18 @@
</menu>
<window title="Demo" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" frameAutosaveName="DemoWindow" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<rect key="contentRect" x="335" y="390" width="393" height="129"/>
<rect key="contentRect" x="335" y="390" width="393" height="284"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="393" height="129"/>
<view key="contentView" wantsLayer="YES" id="372">
<rect key="frame" x="0.0" y="0.0" width="393" height="284"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView id="536" customClass="MASShortcutView">
<rect key="frame" x="142" y="90" width="158" height="19"/>
<rect key="frame" x="142" y="245" width="158" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</customView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="PG0-jh-Onh">
<rect key="frame" x="18" y="92" width="111" height="17"/>
<rect key="frame" x="18" y="247" width="111" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Custom shortcut:" id="85u-1A-n7H">
<font key="font" metaFont="system"/>
@@ -669,7 +669,7 @@
</textFieldCell>
</textField>
<button id="zCi-ki-Uuh">
<rect key="frame" x="140" y="63" width="169" height="18"/>
<rect key="frame" x="140" y="218" width="169" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Enable custom shortcut" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Y47-p3-sDa">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@@ -680,7 +680,7 @@
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="KnS-ut-phz">
<rect key="frame" x="18" y="65" width="111" height="17"/>
<rect key="frame" x="18" y="220" width="111" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Options:" id="cUE-gA-heG">
<font key="font" metaFont="system"/>
@@ -689,7 +689,7 @@
</textFieldCell>
</textField>
<button id="F4r-KM-wn9">
<rect key="frame" x="140" y="43" width="235" height="18"/>
<rect key="frame" x="140" y="198" width="235" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Enable hard-coded shortcut (⌘F2)" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="7gv-jN-44g">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@@ -700,7 +700,7 @@
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="9fB-XS-8pK">
<rect key="frame" x="18" y="20" width="111" height="17"/>
<rect key="frame" x="18" y="175" width="111" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Feedback:" id="Zbz-mV-NDc">
<font key="font" metaFont="system"/>
@@ -709,7 +709,7 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="Aso-dH-W8I">
<rect key="frame" x="140" y="20" width="211" height="17"/>
<rect key="frame" x="140" y="175" width="211" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" placeholderString="Press a shortcut to see feedback" id="Ckx-v7-e6x">
<font key="font" metaFont="system"/>
@@ -717,14 +717,108 @@
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<visualEffectView appearanceType="inheritedVibrantDark" blendingMode="behindWindow" material="sidebar" state="followsWindowActiveState" id="l1t-cm-ytp">
<rect key="frame" x="0.0" y="0.0" width="394" height="155"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<customView id="W0x-si-HFG" customClass="MASShortcutView">
<rect key="frame" x="142" y="50" width="158" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</customView>
<textField verticalHuggingPriority="750" id="6zm-L6-krB">
<rect key="frame" x="142" y="20" width="158" height="22"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Nothing important" drawsBackground="YES" id="D9i-kK-lKz">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="inI-Z8-RQI">
<rect key="frame" x="18" y="116" width="111" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Appearance:" id="lOM-io-1Eg">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="QHs-6N-eda">
<rect key="frame" x="18" y="91" width="111" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Material:" id="c8q-5c-egp">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" id="UzX-fU-4se">
<rect key="frame" x="140" y="111" width="163" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Inherited" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="nVm-0A-rmR" id="xPV-hQ-85B">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="K7p-po-GKT">
<items>
<menuItem title="Inherited" state="on" id="nVm-0A-rmR"/>
<menuItem title="Vibrant Light" tag="1" id="OAc-mb-u8i"/>
<menuItem title="Vibrant Dark" tag="2" id="fAm-DH-Xtk"/>
<menuItem title="Aqua" tag="3" id="GAF-sP-c3A"/>
<menuItem title="Dark Aqua" tag="4" id="mk7-OA-JKv"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="setAppearance:" target="494" id="dID-gh-aL4"/>
</connections>
</popUpButton>
<popUpButton verticalHuggingPriority="750" id="h98-uu-zJN">
<rect key="frame" x="140" y="86" width="163" height="25"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Popover" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="kWK-Vb-dcN" id="HBr-i7-UuT">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="J4V-zf-WmE">
<items>
<menuItem title="Popover" state="on" id="kWK-Vb-dcN"/>
<menuItem title="Sidebar" tag="1" id="uFc-A5-T9Q"/>
<menuItem title="HUD Window" tag="2" id="gV5-Ph-kYg"/>
<menuItem title="Window Background" tag="3" id="tHv-f7-9rU"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="setMaterial:" target="494" id="M89-kv-IrJ"/>
</connections>
</popUpButton>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="FZE-8P-xqW">
<rect key="frame" x="18" y="51" width="111" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Samples:" id="Whf-bT-vQa">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" id="l37-jD-LZU">
<rect key="frame" x="302" y="42" width="63" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Foo" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="yRv-5f-OR6">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
</subviews>
</visualEffectView>
</subviews>
</view>
<point key="canvasLocation" x="352.5" y="367.5"/>
<point key="canvasLocation" x="140" y="398"/>
</window>
<customObject id="494" customClass="AppDelegate">
<connections>
<outlet property="customShortcutView" destination="536" id="aO6-hh-1vm"/>
<outlet property="feedbackTextField" destination="Aso-dH-W8I" id="hk8-xL-ieC"/>
<outlet property="visualEffectView" destination="l1t-cm-ytp" id="NSm-DS-5Sy"/>
<outlet property="window" destination="371" id="532"/>
</connections>
</customObject>
+3 -3
View File
@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.shpakovski.mac.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>2.4.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>2.4.0</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key>
+3
View File
@@ -0,0 +1,3 @@
/* Feedback thats displayed when user presses the sample shortcut. */
"Shortcut pressed!" = "Kurzbefehl gedrückt!";
+3
View File
@@ -0,0 +1,3 @@
/* Feedback thats displayed when user presses the sample shortcut. */
"Shortcut pressed!" = "ショートカットが押されました!";
+3
View File
@@ -0,0 +1,3 @@
/* Feedback thats displayed when user presses the sample shortcut. */
"Shortcut pressed!" = "Atalho pressionado!";
+34
View File
@@ -0,0 +1,34 @@
desc "Make a new release: Bump version number, update changelog and commit & tag the changes"
lane :release do |options|
# Make sure we don't commit any work-in-progress with the release
ensure_git_status_clean
# Read the release type from command-line arguments, default to patch
release_type = options[:type] ? options[:type] : "patch"
# Bump version number
increment_version_number(bump_type: release_type)
version_number = get_version_number(target: "MASShortcut")
increment_build_number(build_number: version_number)
# Update changelog with the version number and release date
stamp_changelog(section_identifier: version_number)
git_add(path: 'CHANGELOG.md')
# Update CocoaPods version
version_bump_podspec(path: "MASShortcut.podspec", bump_type: release_type)
git_add(path: 'MASShortcut.podspec')
# Commit and tag the release
commit_version_bump(
message: "Release #{version_number}",
xcodeproj: "MASShortcut.xcodeproj",
force: true)
add_git_tag(tag: version_number)
end
desc "Push podspec to CocoaPods trunk"
lane :trunk do |options|
pod_push
end
+5
View File
@@ -0,0 +1,5 @@
# Autogenerated by fastlane
#
# Ensure this file is checked in to source control!
gem 'fastlane-plugin-changelog'
+4 -4
View File
@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.github.shpakovski.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -15,10 +15,10 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.3.1</string>
<string>2.4.0</string>
<key>CFBundleVersion</key>
<string>2.3.1</string>
<string>2.4.0</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 20142015 Vadim Shpakovski. All rights reserved.</string>
<string>Copyright © Vadim Shpakovski. All rights reserved.</string>
</dict>
</plist>
-43
View File
@@ -1,43 +0,0 @@
#import <Carbon/Carbon.h>
#import <AppKit/AppKit.h>
// These glyphs are missed in Carbon.h
enum {
kMASShortcutGlyphEject = 0x23CF,
kMASShortcutGlyphClear = 0x2715,
kMASShortcutGlyphDeleteLeft = 0x232B,
kMASShortcutGlyphDeleteRight = 0x2326,
kMASShortcutGlyphLeftArrow = 0x2190,
kMASShortcutGlyphRightArrow = 0x2192,
kMASShortcutGlyphUpArrow = 0x2191,
kMASShortcutGlyphDownArrow = 0x2193,
kMASShortcutGlyphEscape = 0x238B,
kMASShortcutGlyphHelp = 0x003F,
kMASShortcutGlyphPageDown = 0x21DF,
kMASShortcutGlyphPageUp = 0x21DE,
kMASShortcutGlyphTabRight = 0x21E5,
kMASShortcutGlyphReturn = 0x2305,
kMASShortcutGlyphReturnR2L = 0x21A9,
kMASShortcutGlyphPadClear = 0x2327,
kMASShortcutGlyphNorthwestArrow = 0x2196,
kMASShortcutGlyphSoutheastArrow = 0x2198,
};
NS_INLINE NSString* NSStringFromMASKeyCode(unsigned short ch)
{
return [NSString stringWithFormat:@"%C", ch];
}
NS_INLINE NSUInteger MASPickCocoaModifiers(NSUInteger flags)
{
return (flags & (NSControlKeyMask | NSShiftKeyMask | NSAlternateKeyMask | NSCommandKeyMask));
}
NS_INLINE UInt32 MASCarbonModifiersFromCocoaModifiers(NSUInteger cocoaFlags)
{
return
(cocoaFlags & NSCommandKeyMask ? cmdKey : 0)
| (cocoaFlags & NSAlternateKeyMask ? optionKey : 0)
| (cocoaFlags & NSControlKeyMask ? controlKey : 0)
| (cocoaFlags & NSShiftKeyMask ? shiftKey : 0);
}
-7
View File
@@ -1,7 +0,0 @@
#import "MASLocalization.h"
#import "MASShortcut.h"
NSString *MASLocalizedString(NSString *key, NSString *comment) {
NSBundle *frameworkBundle = [NSBundle bundleForClass:[MASShortcut class]];
return [frameworkBundle localizedStringForKey:key value:@"XXX" table:@"Localizable"];
}
-15
View File
@@ -1,15 +0,0 @@
#import "MASShortcut.h"
@interface MASShortcutValidator : NSObject
// The following API enable hotkeys with the Option key as the only modifier
// For example, Option-G will not generate © and Option-R will not paste ®
@property(assign) BOOL allowAnyShortcutWithOptionModifier;
+ (instancetype) sharedValidator;
- (BOOL) isShortcutValid: (MASShortcut*) shortcut;
- (BOOL) isShortcut: (MASShortcut*) shortcut alreadyTakenInMenu: (NSMenu*) menu explanation: (NSString**) explanation;
- (BOOL) isShortcutAlreadyTakenBySystem: (MASShortcut*) shortcut explanation: (NSString**) explanation;
@end
+59
View File
@@ -0,0 +1,59 @@
#import <Carbon/Carbon.h>
#import <AppKit/AppKit.h>
// These glyphs are missed in Carbon.h
typedef NS_ENUM(unsigned short, kMASShortcutGlyph) {
kMASShortcutGlyphEject = 0x23CF,
kMASShortcutGlyphClear = 0x2715,
kMASShortcutGlyphDeleteLeft = 0x232B,
kMASShortcutGlyphDeleteRight = 0x2326,
kMASShortcutGlyphLeftArrow = 0x2190,
kMASShortcutGlyphRightArrow = 0x2192,
kMASShortcutGlyphUpArrow = 0x2191,
kMASShortcutGlyphDownArrow = 0x2193,
kMASShortcutGlyphEscape = 0x238B,
kMASShortcutGlyphHelp = 0x003F,
kMASShortcutGlyphPageDown = 0x21DF,
kMASShortcutGlyphPageUp = 0x21DE,
kMASShortcutGlyphTabRight = 0x21E5,
kMASShortcutGlyphReturn = 0x2305,
kMASShortcutGlyphReturnR2L = 0x21A9,
kMASShortcutGlyphPadClear = 0x2327,
kMASShortcutGlyphNorthwestArrow = 0x2196,
kMASShortcutGlyphSoutheastArrow = 0x2198,
};
// The missing function key definitions for `NS*FunctionKey`s
typedef NS_ENUM(unsigned short, kMASShortcutFuctionKey) {
kMASShortcutEscapeFunctionKey = 0x001B,
kMASShortcutDeleteFunctionKey = 0x0008,
kMASShortcutSpaceFunctionKey = 0x0020,
kMASShortcutReturnFunctionKey = 0x000D,
kMASShortcutTabFunctionKey = 0x0009,
};
NS_INLINE NSString* NSStringFromMASKeyCode(unsigned short ch)
{
return [NSString stringWithFormat:@"%C", ch];
}
NS_INLINE NSUInteger MASPickCocoaModifiers(NSUInteger flags)
{
return (flags & (NSEventModifierFlagControl | NSEventModifierFlagShift | NSEventModifierFlagOption | NSEventModifierFlagCommand));
}
// Used in `-[MASShortcutValidator isShortcut:alreadyTakenInMenu:explanation:]`.
// This prevents incorrectly detecting an overlap with any shortcuts using the `fn` key.
NS_INLINE NSUInteger MASPickModifiersIncludingFn(NSUInteger flags)
{
return (flags & (NSEventModifierFlagControl | NSEventModifierFlagShift | NSEventModifierFlagOption | NSEventModifierFlagCommand | NSEventModifierFlagFunction));
}
NS_INLINE UInt32 MASCarbonModifiersFromCocoaModifiers(NSUInteger cocoaFlags)
{
return
(cocoaFlags & NSEventModifierFlagCommand ? cmdKey : 0)
| (cocoaFlags & NSEventModifierFlagOption ? optionKey : 0)
| (cocoaFlags & NSEventModifierFlagControl ? controlKey : 0)
| (cocoaFlags & NSEventModifierFlagShift ? shiftKey : 0);
}
@@ -16,14 +16,14 @@
Hardware independent, same as in `NSEvent`. See `Events.h` in the HIToolbox
framework for a complete list, or Command-click this symbol: `kVK_ANSI_A`.
*/
@property (nonatomic, readonly) NSUInteger keyCode;
@property (nonatomic, readonly) NSInteger keyCode;
/**
Cocoa keyboard modifier flags.
Same as in `NSEvent`: `NSCommandKeyMask`, `NSAlternateKeyMask`, etc.
*/
@property (nonatomic, readonly) NSUInteger modifierFlags;
@property (nonatomic, readonly) NSEventModifierFlags modifierFlags;
/**
Same as `keyCode`, just a different type.
@@ -45,7 +45,7 @@
to be precise) the `keyCodeString` is `2` on the US keyboard, but `ě` when
the Czech keyboard layout is active. See the spec for details.
*/
@property (nonatomic, readonly) NSString *keyCodeString;
@property (nonatomic, readonly, nullable) NSString *keyCodeString;
/**
A key-code string used in key equivalent matching.
@@ -61,21 +61,21 @@
thats always displayed as `^U`. So the `keyCodeString` returns `Г`
and `keyCodeStringForKeyEquivalent` returns `U`.
*/
@property (nonatomic, readonly) NSString *keyCodeStringForKeyEquivalent;
@property (nonatomic, readonly, nullable) NSString *keyCodeStringForKeyEquivalent;
/**
A string representing the shortcut modifiers, like the `` in `5`.
*/
@property (nonatomic, readonly) NSString *modifierFlagsString;
@property (nonatomic, readonly, nonnull) NSString *modifierFlagsString;
- (instancetype)initWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags;
+ (instancetype)shortcutWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags;
- (nonnull instancetype)initWithKeyCode:(NSInteger)code modifierFlags:(NSEventModifierFlags)flags;
+ (nonnull instancetype)shortcutWithKeyCode:(NSInteger)code modifierFlags:(NSEventModifierFlags)flags;
/**
Creates a new shortcut from an `NSEvent` object.
This is just a convenience initializer that reads the key code and modifiers from an `NSEvent`.
*/
+ (instancetype)shortcutWithEvent:(NSEvent *)anEvent;
+ (nonnull instancetype)shortcutWithEvent:(nonnull NSEvent *)anEvent;
@end
@@ -8,7 +8,7 @@ static NSString *const MASShortcutModifierFlags = @"ModifierFlags";
#pragma mark Initialization
- (instancetype)initWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags
- (instancetype)initWithKeyCode:(NSInteger)code modifierFlags:(NSEventModifierFlags)flags
{
self = [super init];
if (self) {
@@ -18,7 +18,7 @@ static NSString *const MASShortcutModifierFlags = @"ModifierFlags";
return self;
}
+ (instancetype)shortcutWithKeyCode:(NSUInteger)code modifierFlags:(NSUInteger)flags
+ (instancetype)shortcutWithKeyCode:(NSInteger)code modifierFlags:(NSEventModifierFlags)flags
{
return [[self alloc] initWithKeyCode:code modifierFlags:flags];
}
@@ -48,32 +48,44 @@ static NSString *const MASShortcutModifierFlags = @"ModifierFlags";
- (NSString *)keyCodeStringForKeyEquivalent
{
NSString *keyCodeString = self.keyCodeString;
if (keyCodeString.length > 1) {
switch (self.keyCode) {
case kVK_F1: return NSStringFromMASKeyCode(0xF704);
case kVK_F2: return NSStringFromMASKeyCode(0xF705);
case kVK_F3: return NSStringFromMASKeyCode(0xF706);
case kVK_F4: return NSStringFromMASKeyCode(0xF707);
case kVK_F5: return NSStringFromMASKeyCode(0xF708);
case kVK_F6: return NSStringFromMASKeyCode(0xF709);
case kVK_F7: return NSStringFromMASKeyCode(0xF70a);
case kVK_F8: return NSStringFromMASKeyCode(0xF70b);
case kVK_F9: return NSStringFromMASKeyCode(0xF70c);
case kVK_F10: return NSStringFromMASKeyCode(0xF70d);
case kVK_F11: return NSStringFromMASKeyCode(0xF70e);
case kVK_F12: return NSStringFromMASKeyCode(0xF70f);
// From this point down I am guessing F13 etc come sequentially, I don't have a keyboard to test.
case kVK_F13: return NSStringFromMASKeyCode(0xF710);
case kVK_F14: return NSStringFromMASKeyCode(0xF711);
case kVK_F15: return NSStringFromMASKeyCode(0xF712);
case kVK_F16: return NSStringFromMASKeyCode(0xF713);
case kVK_F17: return NSStringFromMASKeyCode(0xF714);
case kVK_F18: return NSStringFromMASKeyCode(0xF715);
case kVK_F19: return NSStringFromMASKeyCode(0xF716);
case kVK_Space: return NSStringFromMASKeyCode(0x20);
default: return @"";
}
switch (self.keyCode) {
case kVK_F1: return NSStringFromMASKeyCode(NSF1FunctionKey);
case kVK_F2: return NSStringFromMASKeyCode(NSF2FunctionKey);
case kVK_F3: return NSStringFromMASKeyCode(NSF3FunctionKey);
case kVK_F4: return NSStringFromMASKeyCode(NSF4FunctionKey);
case kVK_F5: return NSStringFromMASKeyCode(NSF5FunctionKey);
case kVK_F6: return NSStringFromMASKeyCode(NSF6FunctionKey);
case kVK_F7: return NSStringFromMASKeyCode(NSF7FunctionKey);
case kVK_F8: return NSStringFromMASKeyCode(NSF8FunctionKey);
case kVK_F9: return NSStringFromMASKeyCode(NSF9FunctionKey);
case kVK_F10: return NSStringFromMASKeyCode(NSF10FunctionKey);
case kVK_F11: return NSStringFromMASKeyCode(NSF11FunctionKey);
case kVK_F12: return NSStringFromMASKeyCode(NSF12FunctionKey);
case kVK_F13: return NSStringFromMASKeyCode(NSF13FunctionKey);
case kVK_F14: return NSStringFromMASKeyCode(NSF14FunctionKey);
case kVK_F15: return NSStringFromMASKeyCode(NSF15FunctionKey);
case kVK_F16: return NSStringFromMASKeyCode(NSF16FunctionKey);
case kVK_F17: return NSStringFromMASKeyCode(NSF17FunctionKey);
case kVK_F18: return NSStringFromMASKeyCode(NSF18FunctionKey);
case kVK_F19: return NSStringFromMASKeyCode(NSF19FunctionKey);
case kVK_Space: return NSStringFromMASKeyCode(kMASShortcutSpaceFunctionKey);
case kVK_Escape: return NSStringFromMASKeyCode(kMASShortcutEscapeFunctionKey);
case kVK_Delete: return NSStringFromMASKeyCode(NSBackspaceCharacter);
case kVK_ForwardDelete: return NSStringFromMASKeyCode(NSDeleteFunctionKey);
case kVK_LeftArrow: return NSStringFromMASKeyCode(NSLeftArrowFunctionKey);
case kVK_RightArrow: return NSStringFromMASKeyCode(NSRightArrowFunctionKey);
case kVK_UpArrow: return NSStringFromMASKeyCode(NSUpArrowFunctionKey);
case kVK_DownArrow: return NSStringFromMASKeyCode(NSDownArrowFunctionKey);
case kVK_Help: return NSStringFromMASKeyCode(NSHelpFunctionKey);
case kVK_Home: return NSStringFromMASKeyCode(NSHomeFunctionKey);
case kVK_End: return NSStringFromMASKeyCode(NSEndFunctionKey);
case kVK_PageUp: return NSStringFromMASKeyCode(NSPageUpFunctionKey);
case kVK_PageDown: return NSStringFromMASKeyCode(NSPageDownFunctionKey);
case kVK_Tab: return NSStringFromMASKeyCode(kMASShortcutTabFunctionKey);
case kVK_Return: return NSStringFromMASKeyCode(kMASShortcutReturnFunctionKey);
}
return keyCodeString.lowercaseString;
}
@@ -109,7 +121,9 @@ static NSString *const MASShortcutModifierFlags = @"ModifierFlags";
case kVK_RightArrow: return NSStringFromMASKeyCode(kMASShortcutGlyphRightArrow);
case kVK_UpArrow: return NSStringFromMASKeyCode(kMASShortcutGlyphUpArrow);
case kVK_DownArrow: return NSStringFromMASKeyCode(kMASShortcutGlyphDownArrow);
case kVK_Help: return NSStringFromMASKeyCode(kMASShortcutGlyphHelp);
case kVK_Help: return NSStringFromMASKeyCode(kMASShortcutGlyphHelp); // Insert
case kVK_Home: return NSStringFromMASKeyCode(kMASShortcutGlyphNorthwestArrow);
case kVK_End: return NSStringFromMASKeyCode(kMASShortcutGlyphSoutheastArrow);
case kVK_PageUp: return NSStringFromMASKeyCode(kMASShortcutGlyphPageUp);
case kVK_PageDown: return NSStringFromMASKeyCode(kMASShortcutGlyphPageDown);
case kVK_Tab: return NSStringFromMASKeyCode(kMASShortcutGlyphTabRight);
@@ -132,12 +146,8 @@ static NSString *const MASShortcutModifierFlags = @"ModifierFlags";
case kVK_ANSI_KeypadClear: return NSStringFromMASKeyCode(kMASShortcutGlyphPadClear);
case kVK_ANSI_KeypadDivide: return @"/";
case kVK_ANSI_KeypadEnter: return NSStringFromMASKeyCode(kMASShortcutGlyphReturn);
case kVK_ANSI_KeypadMinus: return @"";
case kVK_ANSI_KeypadMinus: return @"-";
case kVK_ANSI_KeypadEquals: return @"=";
// Hardcode
case 119: return NSStringFromMASKeyCode(kMASShortcutGlyphSoutheastArrow);
case 115: return NSStringFromMASKeyCode(kMASShortcutGlyphNorthwestArrow);
}
// Everything else should be printable so look it up in the current ASCII capable keyboard layout
@@ -185,10 +195,10 @@ static NSString *const MASShortcutModifierFlags = @"ModifierFlags";
unichar chars[4];
NSUInteger count = 0;
// These are in the same order as the menu manager shows them
if (self.modifierFlags & NSControlKeyMask) chars[count++] = kControlUnicode;
if (self.modifierFlags & NSAlternateKeyMask) chars[count++] = kOptionUnicode;
if (self.modifierFlags & NSShiftKeyMask) chars[count++] = kShiftUnicode;
if (self.modifierFlags & NSCommandKeyMask) chars[count++] = kCommandUnicode;
if (self.modifierFlags & NSEventModifierFlagControl) chars[count++] = kControlUnicode;
if (self.modifierFlags & NSEventModifierFlagOption) chars[count++] = kOptionUnicode;
if (self.modifierFlags & NSEventModifierFlagShift) chars[count++] = kShiftUnicode;
if (self.modifierFlags & NSEventModifierFlagCommand) chars[count++] = kCommandUnicode;
return (count ? [NSString stringWithCharacters:chars length:count] : @"");
}
@@ -210,7 +220,7 @@ static NSString *const MASShortcutModifierFlags = @"ModifierFlags";
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeInteger:(self.keyCode != NSNotFound ? (NSInteger)self.keyCode : - 1) forKey:MASShortcutKeyCode];
[coder encodeInteger:(self.keyCode != NSNotFound ? self.keyCode : - 1) forKey:MASShortcutKeyCode];
[coder encodeInteger:(NSInteger)self.modifierFlags forKey:MASShortcutModifierFlags];
}
@@ -219,7 +229,7 @@ static NSString *const MASShortcutModifierFlags = @"ModifierFlags";
self = [super init];
if (self) {
NSInteger code = [decoder decodeIntegerForKey:MASShortcutKeyCode];
_keyCode = (code < 0 ? NSNotFound : (NSUInteger)code);
_keyCode = (code < 0) ? NSNotFound : code;
_modifierFlags = [decoder decodeIntegerForKey:MASShortcutModifierFlags];
}
return self;
@@ -5,10 +5,10 @@
- (void) testEquality
{
MASShortcut *keyA = [MASShortcut shortcutWithKeyCode:1 modifierFlags:NSControlKeyMask];
MASShortcut *keyB = [MASShortcut shortcutWithKeyCode:2 modifierFlags:NSControlKeyMask];
MASShortcut *keyC = [MASShortcut shortcutWithKeyCode:1 modifierFlags:NSAlternateKeyMask];
MASShortcut *keyD = [MASShortcut shortcutWithKeyCode:1 modifierFlags:NSControlKeyMask];
MASShortcut *keyA = [MASShortcut shortcutWithKeyCode:1 modifierFlags:NSEventModifierFlagControl];
MASShortcut *keyB = [MASShortcut shortcutWithKeyCode:2 modifierFlags:NSEventModifierFlagControl];
MASShortcut *keyC = [MASShortcut shortcutWithKeyCode:1 modifierFlags:NSEventModifierFlagOption];
MASShortcut *keyD = [MASShortcut shortcutWithKeyCode:1 modifierFlags:NSEventModifierFlagControl];
XCTAssertTrue([keyA isEqual:keyA], @"Shortcut is equal to itself.");
XCTAssertTrue([keyA isEqual:[keyA copy]], @"Shortcut is equal to its copy.");
XCTAssertFalse([keyA isEqual:keyB], @"Shortcuts not equal when key codes differ.");
+40
View File
@@ -0,0 +1,40 @@
#import "MASShortcut.h"
/**
This class is used by the recording control to tell which shortcuts are acceptable.
There are two kinds of shortcuts that are not considered acceptable: shortcuts that
are too simple (like single letter keys) and shortcuts that are already used by the
operating system.
*/
@interface MASShortcutValidator : NSObject
/**
Set to `YES` if you want to accept Option-something shortcuts.
`NO` by default, since Option-something shortcuts are often used by system,
for example Option-G will type the © sign. This also applies to Option-Shift
shortcuts in other words, shortcut recorder will not accept shortcuts like
Option-Shift-K by default. (Again, since Option-Shift-K inserts the Apple
logo sign by default.)
*/
@property(assign) BOOL allowAnyShortcutWithOptionModifier;
/**
Set to `YES` if you want to accept shortcuts that override the Services menu
item.
`NO` by default. Set to `YES` to allow shortcuts to override key equivalents of
Services menu items. This can prevent users from being confused when they can't
find the conflicting menu item since menu items in the Services menu are not
always visible.
*/
@property(assign) BOOL allowOverridingServicesShortcut;
+ (instancetype) sharedValidator;
- (BOOL) isShortcutValid: (MASShortcut*) shortcut;
- (BOOL) isShortcut: (MASShortcut*) shortcut alreadyTakenInMenu: (NSMenu*) menu explanation: (NSString**) explanation;
- (BOOL) isShortcutAlreadyTakenBySystem: (MASShortcut*) shortcut explanation: (NSString**) explanation;
@end
@@ -15,8 +15,8 @@
- (BOOL) isShortcutValid: (MASShortcut*) shortcut
{
NSUInteger keyCode = [shortcut keyCode];
NSUInteger modifiers = [shortcut modifierFlags];
NSInteger keyCode = [shortcut keyCode];
NSEventModifierFlags modifiers = [shortcut modifierFlags];
// Allow any function key with any combination of modifiers
BOOL includesFunctionKey = ((keyCode == kVK_F1) || (keyCode == kVK_F2) || (keyCode == kVK_F3) || (keyCode == kVK_F4) ||
@@ -31,12 +31,12 @@
if (!hasModifierFlags) return NO;
// Allow any hotkey containing Control or Command modifier
BOOL includesCommand = ((modifiers & NSCommandKeyMask) > 0);
BOOL includesControl = ((modifiers & NSControlKeyMask) > 0);
BOOL includesCommand = ((modifiers & NSEventModifierFlagCommand) > 0);
BOOL includesControl = ((modifiers & NSEventModifierFlagControl) > 0);
if (includesCommand || includesControl) return YES;
// Allow Option key only in selected cases
BOOL includesOption = ((modifiers & NSAlternateKeyMask) > 0);
BOOL includesOption = ((modifiers & NSEventModifierFlagOption) > 0);
if (includesOption) {
// Always allow Option-Space and Option-Escape because they do not have any bind system commands
@@ -52,19 +52,23 @@
- (BOOL) isShortcut: (MASShortcut*) shortcut alreadyTakenInMenu: (NSMenu*) menu explanation: (NSString**) explanation
{
if (self.allowOverridingServicesShortcut && menu == [NSApp servicesMenu]) {
return NO;
}
NSString *keyEquivalent = [shortcut keyCodeStringForKeyEquivalent];
NSUInteger flags = [shortcut modifierFlags];
NSEventModifierFlags flags = [shortcut modifierFlags];
for (NSMenuItem *menuItem in menu.itemArray) {
if (menuItem.hasSubmenu && [self isShortcut:shortcut alreadyTakenInMenu:[menuItem submenu] explanation:explanation]) return YES;
BOOL equalFlags = (MASPickCocoaModifiers(menuItem.keyEquivalentModifierMask) == flags);
BOOL equalFlags = (MASPickModifiersIncludingFn(menuItem.keyEquivalentModifierMask) == flags);
BOOL equalHotkeyLowercase = [menuItem.keyEquivalent.lowercaseString isEqualToString:keyEquivalent];
// Check if the cases are different, we know ours is lower and that shift is included in our modifiers
// If theirs is capitol, we need to add shift to their modifiers
if (equalHotkeyLowercase && ![menuItem.keyEquivalent isEqualToString:keyEquivalent]) {
equalFlags = (MASPickCocoaModifiers(menuItem.keyEquivalentModifierMask | NSShiftKeyMask) == flags);
equalFlags = (MASPickModifiersIncludingFn(menuItem.keyEquivalentModifierMask | NSEventModifierFlagShift) == flags);
}
if (equalFlags && equalHotkeyLowercase) {
@@ -91,7 +95,7 @@
CFNumberRef flags = CFDictionaryGetValue(hotKeyInfo, kHISymbolicHotKeyModifiers);
CFNumberRef enabled = CFDictionaryGetValue(hotKeyInfo, kHISymbolicHotKeyEnabled);
if (([(__bridge NSNumber *)code unsignedIntegerValue] == [shortcut keyCode]) &&
if (([(__bridge NSNumber *)code integerValue] == [shortcut keyCode]) &&
([(__bridge NSNumber *)flags unsignedIntegerValue] == [shortcut carbonFlags]) &&
([(__bridge NSNumber *)enabled boolValue])) {
@@ -8,7 +8,7 @@
- (void) testBasicFunctionality
{
MASHotKey *hotKey = [MASHotKey registeredHotKeyWithShortcut:
[MASShortcut shortcutWithKeyCode:kVK_ANSI_H modifierFlags:NSCommandKeyMask|NSAlternateKeyMask]];
[MASShortcut shortcutWithKeyCode:kVK_ANSI_H modifierFlags:NSEventModifierFlagCommand|NSEventModifierFlagOption]];
XCTAssertNotNil(hotKey, @"Register a simple Cmd-Alt-H hotkey.");
}
@@ -13,7 +13,7 @@
- (void) testShortcutRegistration
{
MASShortcutMonitor *monitor = [MASShortcutMonitor sharedMonitor];
MASShortcut *shortcut = [MASShortcut shortcutWithKeyCode:kVK_ANSI_H modifierFlags:NSCommandKeyMask|NSAlternateKeyMask];
MASShortcut *shortcut = [MASShortcut shortcutWithKeyCode:kVK_ANSI_H modifierFlags:NSEventModifierFlagCommand|NSEventModifierFlagOption];
XCTAssertTrue([monitor registerShortcut:shortcut withAction:NULL], @"Register a shortcut.");
XCTAssertTrue([monitor isShortcutRegistered:shortcut], @"Remember a previously registered shortcut.");
[monitor unregisterShortcut:shortcut];
@@ -2,46 +2,46 @@
"Cancel" = "Abbrechen";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "Click to record new shortcut";
"Click to record new shortcut" = "Klicken um neuen Kurzbefehl aufzunehmen";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "Delete shortcut";
"Delete shortcut" = "Kurzbefehl Löschen";
/* VoiceOver title */
"keyboard shortcut" = "keyboard shortcut";
"keyboard shortcut" = "Kurzbefehl";
/* Alert button when shortcut is already used */
"OK" = "OK";
/* Empty shortcut button in normal state */
"Record Shortcut" = "Tastaturkürzel speichern";
"Record Shortcut" = "Kurzbefehl aufnehmen";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "Shortcut cleared";
"Shortcut cleared" = "Kurzbefehl gelöscht";
/* VoiceOver: Shortcut set */
"Shortcut set" = "Shortcut set";
"Shortcut set" = "Kurzbefehl gesetzt";
/* Shortcut glyph name for SPACE key */
"Space" = "Leertaste";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "The key combination %@ cannot be used";
"The key combination %@ cannot be used" = "Die Tastenkombination %@ kann nicht genutzt werden";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences.";
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "Diese Kombination kann nicht genutzt werden, weil sie bereits als systemweiter Kurzbefehl genutzt wird.\nFalls du diese Tastenkombination wirklich benutzen willst, können die meisten Kurzbefehle in den Tastatur Systemeinstellungen geändert werden.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "This shortcut cannot be used because it is already used by the menu item %@.";
"This shortcut cannot be used because it is already used by the menu item %@." = "Dieser Kurzbefehl kann nicht genutzt werden, weil er bereits vom Menüpunkt „%@“ genutzt wird.";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut.";
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "Drücke diesen Button, um einen neuen Kurzbefehl aufzunehmen. Tippe dann den neuen Kurzbefehl oder drücke Löschen, um den aktuellen Kurzbefehl zu löschen.";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "Tastaturkürzel eingeben";
"Type New Shortcut" = "Neuen eingeben";
/* Empty shortcut button in recording state */
"Type Shortcut" = "Tastaturkürzel eingeben";
"Type Shortcut" = "Kurzbefehl eingeben";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "Use Old Shortcut";
"Use Old Shortcut" = "Alten nutzen";
@@ -0,0 +1,47 @@
/* Cancel action button in recording state */
"Cancel" = "Cancelar";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "Haga clic para grabar nuevo atajo";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "Borrar atajo";
/* VoiceOver title */
"keyboard shortcut" = "función rápida de teclado";
/* Alert button when shortcut is already used */
"OK" = "OK";
/* Empty shortcut button in normal state */
"Record Shortcut" = "Grabar Función rápida";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "Función rápida eliminada";
/* VoiceOver: Shortcut set */
"Shortcut set" = "Función rápida creada";
/* Shortcut glyph name for SPACE key */
"Space" = "Espacio";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "La combinación de teclas %@ no puede ser utilizada";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "Esta combinación no puede ser utilizar debido a que es una función rápida del sistema.\nSi realmente desea utilizar esta combinación de teclas, la mayoría de las funciones rápidas se puede cambiar en el Panel de Teclado en las Preferencias del sistema.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "Esta función rápida no se puede utilizar debido a que ya está siendo utilizada por el elemento de menú '%@'.";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "Para grabar una nueva función rápida, haga clic en este botón, y luego teclee la nueva función rápida, o pulse borrar para quitar una función rápida existente.";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "Teclee la nueva función rápida";
/* Empty shortcut button in recording state */
"Type Shortcut" = "Teclee la función rápida";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "Usar una función rápida previa";
@@ -2,13 +2,13 @@
"Cancel" = "Annuler";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "Click to record new shortcut";
"Click to record new shortcut" = "Cliquez pour enregistrer le raccourci";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "Delete shortcut";
"Delete shortcut" = "Supprimer le raccourci";
/* VoiceOver title */
"keyboard shortcut" = "keyboard shortcut";
"keyboard shortcut" = "raccourci clavier";
/* Alert button when shortcut is already used */
"OK" = "OK";
@@ -17,25 +17,25 @@
"Record Shortcut" = "Enregistrer le raccourci";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "Shortcut cleared";
"Shortcut cleared" = "Raccourci supprimé";
/* VoiceOver: Shortcut set */
"Shortcut set" = "Shortcut set";
"Shortcut set" = "Raccourci configuré";
/* Shortcut glyph name for SPACE key */
"Space" = "Espace";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "The key combination %@ cannot be used";
"The key combination %@ cannot be used" = "La combinaison %@ ne peut être utilisée";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences.";
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "Cette combinaison de touches ne peut être utilisée parce quelle est réservée pour un raccourci du système.\nSi vous désirez lutiliser, la plupart des raccourcis peuvent être modifiés dans longlet Clavier, dans Préférences Système.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "This shortcut cannot be used because it is already used by the menu item %@.";
"This shortcut cannot be used because it is already used by the menu item %@." = "Ce raccourci ne peut être utilisé parce quil est déjà utilisé par le point de menu «%@».";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut.";
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "Pour enregistrer un nouveau raccourci, cliquez sur ce bouton et tapez le nouveau raccourci, ou bien, tapez sur «Supprimer» pour supprimer le raccourci configuré.";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "Saisir un raccourci";
@@ -44,4 +44,4 @@
"Type Shortcut" = "Saisir un raccourci";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "Use Old Shortcut";
"Use Old Shortcut" = "Revenir au raccourci précédent";
@@ -0,0 +1,47 @@
/* Cancel action button in recording state */
"Cancel" = "Annulla";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "Fai clic per registrare una nuova abbreviazione";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "Cancella abbreviazione";
/* VoiceOver title */
"keyboard shortcut" = "Abbreviazione da tastiera";
/* Alert button when shortcut is already used */
"OK" = "OK";
/* Empty shortcut button in normal state */
"Record Shortcut" = "Registra abbreviazione";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "Abbreviazione rimossa";
/* VoiceOver: Shortcut set */
"Shortcut set" = "Abbreviazione impostata";
/* Shortcut glyph name for SPACE key */
"Space" = "Spazio";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "Questa combinazione %@ di tasti non può essere usata";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "Questa combinazione di tasti non può essere usata perché già assegnata a un'abbreviazione da tastiera a livello di Sistema.\nSe vuoi davvero usare questa combinazione di tasti, puoi modificare la maggior parte delle abbreviazioni nei pannelli Tastiera e Mouse delle Preferenze di Sistema.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "Questa combinazione di tasti non può essere usata perché già usata dalla voce di menu %@.";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "Per registrare una nuova abbreviazione fai clic su questo pulsante, quindi inserisci i tasti della nuova abbreviazione o premi cancella per ripristinare un'abbreviazione esistente.";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "Digita nuova abbreviazione";
/* Empty shortcut button in recording state */
"Type Shortcut" = "Digita abbreviazione";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "Usa abbreviazione precedente";
@@ -0,0 +1,47 @@
/* Cancel action button in recording state */
"Cancel" = "キャンセルする";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "クリックしてショートカットを入力";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "ショートカットを削除";
/* VoiceOver title */
"keyboard shortcut" = "キーボードショートカット";
/* Alert button when shortcut is already used */
"OK" = "OK";
/* Empty shortcut button in normal state */
"Record Shortcut" = "ショートカットを入力";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "ショートカットが削除されました";
/* VoiceOver: Shortcut set */
"Shortcut set" = "ショートカットが設定されました";
/* Shortcut glyph name for SPACE key */
"Space" = "スペース";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "%@ はショートカットに設定できません";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "このショートカットは、システム全体で使用されているショートカットのため、設定することができません。\nもしこのショートカットを使用したい場合、「システム環境設定」の「キーボード」、「マウス」のパネルから既に設定されているショートカットを変更してください。";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "このショートカットは、メニュー操作の「%@」で使われているため、設定できません。";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "このボタンをクリックし、ショートカットを入力すると、新しいショートカットが設定されます。また、削除ボタンをおすと、ショートカットが削除されます。";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "ショートカットを入力";
/* Empty shortcut button in recording state */
"Type Shortcut" = "ショートカットを入力";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "古いショートカットを使用";
@@ -0,0 +1,47 @@
/* Cancel action button in recording state */
"Cancel" = "취소";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "클릭해 단축 키를 입력";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "단축키 삭제";
/* VoiceOver title */
"keyboard shortcut" = "키보드 단축키";
/* Alert button when shortcut is already used */
"OK" = "좋아";
/* Empty shortcut button in normal state */
"Record Shortcut" = "단축키 입력";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "단축키 삭제됨";
/* VoiceOver: Shortcut set */
"Shortcut set" = "단축키 설정됨";
/* Shortcut glyph name for SPACE key */
"Space" = "스페이스 바";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "%@ 단축키로 설정할 수 없습니다";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "이 결합은 시스템 전체에서 사용 때문에 단축키로 설정 할 수 없습니다.\n단축키를 사용하고 싶으면 시스템 환경 설정의 키보드, 마우스 패널에서 이미 설정되어있는 단축키를 변경하십시오.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "이 단축키는 ‘%@’ 메뉴 아이템에 사용되고 있기 때문에 설정할 수 없습니다.";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "이 버튼을 클릭하고 단축키를 입력하면 새로운 단축키가 설정됩니다. 또한 삭제 버튼을 누르면 단축키가 삭제됩니다.";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "새 단축키 입력";
/* Empty shortcut button in recording state */
"Type Shortcut" = "단축키 입력";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "오래된 단축키를 사용";
@@ -0,0 +1,47 @@
/* Cancel action button in recording state */
"Cancel" = "Verbreken";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "Druk om een nieuwe sneltoets in te voeren";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "Verwijder sneltoets";
/* VoiceOver title */
"keyboard shortcut" = "sneltoets";
/* Alert button when shortcut is already used */
"OK" = "OK";
/* Empty shortcut button in normal state */
"Record Shortcut" = "Sneltoets opnemen";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "Sneltoets verwijderd";
/* VoiceOver: Shortcut set */
"Shortcut set" = "Sneltoets zetten";
/* Shortcut glyph name for SPACE key */
"Space" = "Spatie";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "De sneltoetsencombinatie kan niet worden gebruikt";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "Deze combinatie kan niet worden gebruikt want hij wordt al gebruikt door een systeembreed sneltoets.\nAls je deze combinatie echt wilt gebruiken, kun je de meeste sneltoetsen binnen Toetsenbordinstellingen veranderen.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "Deze sneltoets kan niet worden gebruikt want hij wordt al gebruikt door het menu item %@.";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "Om nieuwe sneltoets op te nemen, druk op deze knop, en voer een nieuwe sneltoets in, of druk op verwijder om bestaande sneltoets te verwijderen.";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "Voer Nieuwe Sneltoets in";
/* Empty shortcut button in recording state */
"Type Shortcut" = "Voer Sneltoets in";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "Gebruik Oude Sneltoets";
@@ -1,47 +1,47 @@
/* Cancel action button in recording state */
"Cancel" = "Annulla";
/* Cancel action button in recording state */
"Cancel" = "Anuluj";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "Click to record new shortcut";
"Click to record new shortcut" = "Kliknij, by ustawić nowy skrót";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "Delete shortcut";
"Delete shortcut" = "Usuń skrót";
/* VoiceOver title */
"keyboard shortcut" = "keyboard shortcut";
"keyboard shortcut" = "skrót klawiszowy";
/* Alert button when shortcut is already used */
"OK" = "OK";
/* Empty shortcut button in normal state */
"Record Shortcut" = "Registra scorciatoia";
"Record Shortcut" = "Utwórz skrót";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "Shortcut cleared";
"Shortcut cleared" = "Skrót usunięty";
/* VoiceOver: Shortcut set */
"Shortcut set" = "Shortcut set";
"Shortcut set" = "Skrót ustawiony";
/* Shortcut glyph name for SPACE key */
"Space" = "Spazio";
"Space" = "Spacja";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "The key combination %@ cannot be used";
"The key combination %@ cannot be used" = "Nie można użyć kombinacji klawiszy %@";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences.";
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "Nie można użyć tej kombinacji, ponieważ jest już zajęta przez skrót systemowy.\nMożesz to zmienić w panelu Klawiatura w Preferencjach systemowych.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "This shortcut cannot be used because it is already used by the menu item %@.";
"This shortcut cannot be used because it is already used by the menu item %@." = "Ten skrót nie może być użyty, ponieważ w menu ma już przypisaną funkcję %@.";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut.";
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "Aby ustawić nowy skrót, użyj tego przycisku, a następnie wpisz nowy skrót albo naciśnij klawisz delete, by usunąć istniejący skrót";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "Digita scorciatoia";
"Type New Shortcut" = "Wpisz nowy skrót";
/* Empty shortcut button in recording state */
"Type Shortcut" = "Digita scorciatoia";
"Type Shortcut" = "Wpisz skrót";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "Use Old Shortcut";
"Use Old Shortcut" = "Użyj starego skrótu";
@@ -1,47 +1,47 @@
/* Cancel action button in recording state */
/* Cancel action button in recording state */
"Cancel" = "Cancelar";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "Click to record new shortcut";
"Click to record new shortcut" ="Clique para gravar o atalho";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "Delete shortcut";
"Delete shortcut" = "Apagar atalho";
/* VoiceOver title */
"keyboard shortcut" = "keyboard shortcut";
"keyboard shortcut" = "atalho de teclado";
/* Alert button when shortcut is already used */
"OK" = "OK";
/* Empty shortcut button in normal state */
"Record Shortcut" = "Grabar atajo";
"Record Shortcut" = "Gravar Atalho";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "Shortcut cleared";
"Shortcut cleared" = "Atalho limpo";
/* VoiceOver: Shortcut set */
"Shortcut set" = "Shortcut set";
"Shortcut set" = "Atalho definido";
/* Shortcut glyph name for SPACE key */
"Space" = "Espacio";
"Space" = "Espaço";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "The key combination %@ cannot be used";
"The key combination %@ cannot be used" = "A combinação de teclas “%@” não pode ser usada";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences.";
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "Esta combinação não pode ser usada porque ela já é usada por um atalho global do sistema.\nA maioria dos atalhos pode ser alterada no painel Teclado das Preferências do Sistema, caso realmente deseje usar esta combinação.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "This shortcut cannot be used because it is already used by the menu item %@.";
"This shortcut cannot be used because it is already used by the menu item %@." = "Este atalho não pode ser usado porque ele já é usado pelo item de menu %@.";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut.";
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "Para gravar um atalho novo, clique neste botão e digite o novo atalho ou pressione apagar para limpar um atalho existente.";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "Escribir atajo";
"Type New Shortcut" = "Digite o atalho";
/* Empty shortcut button in recording state */
"Type Shortcut" = "Escribir atajo";
"Type Shortcut" = "Digite o atalho";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "Use Old Shortcut";
"Use Old Shortcut" = "Usar atalho antigo";
@@ -0,0 +1,47 @@
/* Cancel action button in recording state */
"Cancel" = "Отмена";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "Нажмите для записи сочетания клавиш";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "Удалить горячую клавишу";
/* VoiceOver title */
"keyboard shortcut" = "сочетание клавиш";
/* Alert button when shortcut is already used */
"OK" = "ОК";
/* Empty shortcut button in normal state */
"Record Shortcut" = "Ввести сочетание";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "Сочетание клавиш удалено";
/* VoiceOver: Shortcut set */
"Shortcut set" = "Сочетание клавиш назначено";
/* Shortcut glyph name for SPACE key */
"Space" = "Пробел";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "Нельзя использовать сочетание клавиш %@";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "Нельзя использовать это сочетание клавиш, потому что оно уже используется в системе.\n Если вы хотите использовать это сочетание, измените существующее системное сочетание клавиш через панель Клавиатура в Cистемных настройках.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "Нельзя использовать это сочетание, потому что оно уже связано с элементом ‘%@’.";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "Чтобы назначить новое сочетание клавиш, нажмите эту кнопку и введите новое сочетание, или нажмите \"Удалить\", чтобы удалить действующее сочетание клавиш.";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "Введите сочетание";
/* Empty shortcut button in recording state */
"Type Shortcut" = "Введите сочетание";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "Вернуть старое";
@@ -0,0 +1,47 @@
/* Cancel action button in recording state */
"Cancel" = "Avbryt";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "Klicka för att registrera ny kortkommando";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "Ta bort en kortkommando";
/* VoiceOver title */
"keyboard shortcut" = "Tangentbordskortkommando";
/* Alert button when shortcut is already used */
"OK" = "OK";
/* Empty shortcut button in normal state */
"Record Shortcut" = "Registrera kortkommando";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "Kortkommando rensas";
/* VoiceOver: Shortcut set */
"Shortcut set" = "Kortkommando uppsättning";
/* Shortcut glyph name for SPACE key */
"Space" = "Utrymme";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "Tangentkombinationen %@ kan inte användas";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "Den här kombinationen kan inte användas eftersom den redan används som en tangentbordskortkommando. Om du verkligen vill använda den här tangentkombinationen kan de flesta genvägar ändras under Tangentbord & Mus i Systeminställningar.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "Denna kortkommando kan inte användas eftersom det redan används av ett menyalternativ %@.";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "För att registrera en ny kortkommando, klicka på den här knappen och skriv sedan in den nya kortkommando, eller tryck på radera för att rensa en befintlig kortkommando.";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "Skriv Ny Kortkommando";
/* Empty shortcut button in recording state */
"Type Shortcut" = "Skriv Kortkommando";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "Använd Gammal Kortkommando";
@@ -0,0 +1,47 @@
/* Cancel action button in recording state */
"Cancel" = "取消";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "点击以记录新快捷键";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "删除快捷键";
/* VoiceOver title */
"keyboard shortcut" = "键盘快捷键";
/* Alert button when shortcut is already used */
"OK" = "好";
/* Empty shortcut button in normal state */
"Record Shortcut" = "记录快捷键";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "快捷键已清除";
/* VoiceOver: Shortcut set */
"Shortcut set" = "快捷键已设置";
/* Shortcut glyph name for SPACE key */
"Space" = "空格键";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "按键组合“%@”无法使用";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "当前按键组合无法使用,因为它已经用作其他系统全局快捷键。\n如果您真的想使用这个按键组合,大部分系统全局快捷键能在“系统偏好设置”里的“键盘”和“鼠标”面板中重设。";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "当前快捷键无法使用,因为它已用作菜单项“%@”的快捷键。";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "若要记录新的快捷键,单击此按钮,然后键入新的快捷键,或者按“delete键”删除已经存在的快捷键。";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "键入新快捷键";
/* Empty shortcut button in recording state */
"Type Shortcut" = "键入快捷键";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "还原快捷键";
@@ -0,0 +1,47 @@
/* Cancel action button in recording state */
"Cancel" = "取消";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "按一下以記錄新快速鍵";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "刪除快速鍵";
/* VoiceOver title */
"keyboard shortcut" = "鍵盤快速鍵";
/* Alert button when shortcut is already used */
"OK" = "好";
/* Empty shortcut button in normal state */
"Record Shortcut" = "記錄快速鍵";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "快速鍵已清除";
/* VoiceOver: Shortcut set */
"Shortcut set" = "快速鍵已設定";
/* Shortcut glyph name for SPACE key */
"Space" = "空格鍵";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "按鍵組合「%@」無法使用";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "目前按鍵組合無法使用,因為它已經用作其他系統全域快速鍵。\n如果您真的想使用此按鍵組合,大部分的系統全域快速鍵可在「系統偏好設定」裡的「鍵盤」和「滑鼠」面板中變更。";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "目前快速鍵無法使用,因為它已經用作選單項目「%@」的快速鍵。";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "若要記錄新的快速鍵,按一下此按鈕,然後輸入新的快速鍵,或者按「delete」鍵刪除已經存在的快速鍵。";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "輸入新快速鍵";
/* Empty shortcut button in recording state */
"Type Shortcut" = "輸入快速鍵";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "還原快速鍵";
+3 -1
View File
@@ -1,7 +1,9 @@
#import <AppKit/AppKit.h>
#import "MASShortcut.h"
#import "MASShortcutValidator.h"
#import "MASShortcutMonitor.h"
#import "MASShortcutBinder.h"
#import "MASDictionaryTransformer.h"
#import "MASShortcutView.h"
#import "MASShortcutView+Bindings.h"
#import "MASShortcutView+Bindings.h"
#import "MASShortcutViewButtonCell.h"
@@ -10,4 +10,4 @@
NSLocalizedString throughout the framework, it wouldnt work
properly.
*/
NSString *MASLocalizedString(NSString *key, NSString *comment);
NSString *MASLocalizedString(NSString *key, NSString *comment);
+38
View File
@@ -0,0 +1,38 @@
#import "MASLocalization.h"
#import "MASShortcut.h"
static NSString *const MASLocalizationTableName = @"Localizable";
static NSString *const MASPlaceholderLocalizationString = @"XXX";
// The CocoaPods trickery here is needed because when the code
// is built as a part of CocoaPods, it wont make a separate framework
// and the Localized.strings file wont be bundled correctly.
// See https://github.com/shpakovski/MASShortcut/issues/74
NSString *MASLocalizedString(NSString *key, NSString *comment) {
static NSBundle *localizationBundle = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
#if SWIFT_PACKAGE
localizationBundle = SWIFTPM_MODULE_BUNDLE;
#else
NSBundle *frameworkBundle = [NSBundle bundleForClass:[MASShortcut class]];
// first we'll check if resources bundle was copied to MASShortcut framework bundle when !use_frameworks option is active
NSURL *cocoaPodsBundleURL = [frameworkBundle URLForResource:@"MASShortcut" withExtension:@"bundle"];
if (cocoaPodsBundleURL) {
localizationBundle = [NSBundle bundleWithURL: cocoaPodsBundleURL];
} else {
// trying to fetch cocoapods bundle from main bundle
cocoaPodsBundleURL = [[NSBundle mainBundle] URLForResource: @"MASShortcut" withExtension:@"bundle"];
if (cocoaPodsBundleURL) {
localizationBundle = [NSBundle bundleWithURL: cocoaPodsBundleURL];
} else {
// fallback to framework bundle
localizationBundle = frameworkBundle;
}
}
#endif
});
return [localizationBundle localizedStringForKey:key
value:MASPlaceholderLocalizationString
table:MASLocalizationTableName];
}
@@ -1,3 +1,4 @@
#import <AppKit/AppKit.h>
#import "MASShortcutView.h"
/**
@@ -17,9 +18,9 @@
*/
@interface MASShortcutView (Bindings)
@property(copy) NSString *associatedUserDefaultsKey;
@property(copy, nullable) NSString *associatedUserDefaultsKey;
- (void) setAssociatedUserDefaultsKey: (NSString*) newKey withTransformer: (NSValueTransformer*) transformer;
- (void) setAssociatedUserDefaultsKey: (NSString*) newKey withTransformerName: (NSString*) transformerName;
- (void) setAssociatedUserDefaultsKey: (nullable NSString*) newKey withTransformer: (nullable NSValueTransformer*) transformer;
- (void) setAssociatedUserDefaultsKey: (nullable NSString*) newKey withTransformerName: (nullable NSString*) transformerName;
@end
@@ -16,14 +16,9 @@
- (void) setAssociatedUserDefaultsKey: (NSString*) newKey withTransformer: (NSValueTransformer*) transformer
{
// Break previous binding if any
NSString *currentKey = [self associatedUserDefaultsKey];
if (currentKey != nil) {
[self unbind:currentKey];
}
// Stop if the new binding is nil
// Break previous binding if the new binding is nil
if (newKey == nil) {
[self unbind:MASShortcutBinding];
return;
}
@@ -1,25 +1,28 @@
#import <AppKit/AppKit.h>
@class MASShortcut, MASShortcutValidator;
extern NSString *const MASShortcutBinding;
extern NSString * _Nonnull const MASShortcutBinding;
typedef enum {
typedef NS_ENUM(NSInteger, MASShortcutViewStyle) {
MASShortcutViewStyleDefault = 0, // Height = 19 px
MASShortcutViewStyleTexturedRect, // Height = 25 px
MASShortcutViewStyleRounded, // Height = 43 px
MASShortcutViewStyleFlat
} MASShortcutViewStyle;
MASShortcutViewStyleFlat,
MASShortcutViewStyleRegularSquare
};
@interface MASShortcutView : NSView
@property (nonatomic, strong) MASShortcut *shortcutValue;
@property (nonatomic, strong) MASShortcutValidator *shortcutValidator;
@property (nonatomic, strong, nullable) MASShortcut *shortcutValue;
@property (nonatomic, strong, nullable) MASShortcutValidator *shortcutValidator;
@property (nonatomic, getter = isRecording) BOOL recording;
@property (nonatomic, getter = isEnabled) BOOL enabled;
@property (nonatomic, copy) void (^shortcutValueChange)(MASShortcutView *sender);
@property (nonatomic, copy, nullable) void (^shortcutValueChange)(MASShortcutView * _Nonnull sender);
@property (nonatomic, assign) MASShortcutViewStyle style;
/// Returns custom class for drawing control.
+ (Class)shortcutCellClass;
+ (nonnull Class)shortcutCellClass;
- (void)setAcceptsFirstResponder:(BOOL)value;
@@ -1,6 +1,7 @@
#import "MASShortcutView.h"
#import "MASShortcutValidator.h"
#import "MASLocalization.h"
#import "MASShortcutViewButtonCell.h"
NSString *const MASShortcutBinding = @"shortcutValue";
@@ -20,18 +21,18 @@ static const CGFloat MASButtonFontSize = 11;
#pragma mark -
@implementation MASShortcutView {
NSButtonCell *_shortcutCell;
MASShortcutViewButtonCell *_shortcutCell;
NSInteger _shortcutToolTipTag;
NSInteger _hintToolTipTag;
NSTrackingArea *_hintArea;
BOOL _acceptsFirstResponder;
BOOL _acceptsFirstResponder;
}
#pragma mark -
+ (Class)shortcutCellClass
{
return [NSButtonCell class];
return [MASShortcutViewButtonCell class];
}
- (id)initWithFrame:(CGRect)frameRect
@@ -55,12 +56,12 @@ static const CGFloat MASButtonFontSize = 11;
- (void)commonInit
{
_shortcutCell = [[[self.class shortcutCellClass] alloc] init];
_shortcutCell.buttonType = NSPushOnPushOffButton;
_shortcutCell.buttonType = NSButtonTypePushOnPushOff;
_shortcutCell.font = [[NSFontManager sharedFontManager] convertFont:_shortcutCell.font toSize:MASButtonFontSize];
_shortcutValidator = [MASShortcutValidator sharedValidator];
_enabled = YES;
_showsDeleteButton = YES;
_acceptsFirstResponder = NO;
_acceptsFirstResponder = NO;
[self resetShortcutCellStyle];
}
@@ -78,6 +79,7 @@ static const CGFloat MASButtonFontSize = 11;
_enabled = flag;
[self updateTrackingAreas];
self.recording = NO;
[self invalidateIntrinsicContentSize];
[self setNeedsDisplay:YES];
}
}
@@ -87,6 +89,7 @@ static const CGFloat MASButtonFontSize = 11;
if (_style != newStyle) {
_style = newStyle;
[self resetShortcutCellStyle];
[self invalidateIntrinsicContentSize];
[self setNeedsDisplay:YES];
}
}
@@ -95,15 +98,15 @@ static const CGFloat MASButtonFontSize = 11;
{
switch (_style) {
case MASShortcutViewStyleDefault: {
_shortcutCell.bezelStyle = NSRoundRectBezelStyle;
_shortcutCell.bezelStyle = NSBezelStyleRoundRect;
break;
}
case MASShortcutViewStyleTexturedRect: {
_shortcutCell.bezelStyle = NSTexturedRoundedBezelStyle;
_shortcutCell.bezelStyle = NSBezelStyleTexturedRounded;
break;
}
case MASShortcutViewStyleRounded: {
_shortcutCell.bezelStyle = NSRoundedBezelStyle;
_shortcutCell.bezelStyle = NSBezelStyleRounded;
break;
}
case MASShortcutViewStyleFlat: {
@@ -112,6 +115,10 @@ static const CGFloat MASButtonFontSize = 11;
_shortcutCell.bordered = NO;
break;
}
case MASShortcutViewStyleRegularSquare: {
_shortcutCell.bezelStyle = NSBezelStyleRegularSquare;
break;
}
}
}
@@ -135,9 +142,16 @@ static const CGFloat MASButtonFontSize = 11;
[self resetToolTips];
[self activateEventMonitoring:_recording];
[self activateResignObserver:_recording];
[self invalidateIntrinsicContentSize];
[self setNeedsDisplay:YES];
// Give VoiceOver users feedback on the result. Requires at least 10.9 to run.
// Were silencing the tautological compare warning here so that if someone
// takes the naked source files and compiles them with -Wall, the following
// NSAccessibilityPriorityKey comparison doesnt cause a warning. See:
// https://github.com/shpakovski/MASShortcut/issues/76
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
if (_recording == NO && (&NSAccessibilityPriorityKey != NULL)) {
NSString* msg = _shortcutValue ?
MASLocalizedString(@"Shortcut set", @"VoiceOver: Shortcut set") :
@@ -148,12 +162,14 @@ static const CGFloat MASButtonFontSize = 11;
};
NSAccessibilityPostNotificationWithUserInfo(self, NSAccessibilityAnnouncementRequestedNotification, announcementInfo);
}
#pragma clang diagnostic pop
}
- (void)setShortcutValue:(MASShortcut *)shortcutValue
{
_shortcutValue = shortcutValue;
[self resetToolTips];
[self invalidateIntrinsicContentSize];
[self setNeedsDisplay:YES];
[self propagateValue:shortcutValue forBinding:MASShortcutBinding];
@@ -165,9 +181,17 @@ static const CGFloat MASButtonFontSize = 11;
- (void)setShortcutPlaceholder:(NSString *)shortcutPlaceholder
{
_shortcutPlaceholder = shortcutPlaceholder.copy;
[self invalidateIntrinsicContentSize];
[self setNeedsDisplay:YES];
}
#pragma mark - Appearance
- (BOOL)allowsVibrancy
{
return YES;
}
#pragma mark - Drawing
- (BOOL)isFlipped
@@ -182,24 +206,21 @@ static const CGFloat MASButtonFontSize = 11;
_shortcutCell.state = state;
_shortcutCell.enabled = self.enabled;
CGFloat yOffset;
switch (_style) {
case MASShortcutViewStyleDefault: {
[_shortcutCell drawWithFrame:frame inView:self];
case MASShortcutViewStyleTexturedRect:
case MASShortcutViewStyleRounded:
case MASShortcutViewStyleRegularSquare: {
yOffset = 1.0;
break;
}
case MASShortcutViewStyleTexturedRect: {
[_shortcutCell drawWithFrame:CGRectOffset(frame, 0.0, 1.0) inView:self];
default:
yOffset = 0.0;
break;
}
case MASShortcutViewStyleRounded: {
[_shortcutCell drawWithFrame:CGRectOffset(frame, 0.0, 1.0) inView:self];
break;
}
case MASShortcutViewStyleFlat: {
[_shortcutCell drawWithFrame:frame inView:self];
break;
}
}
[_shortcutCell drawWithFrame:CGRectOffset(frame, 0.0, yOffset) inView:self];
}
- (void)drawRect:(CGRect)dirtyRect
@@ -212,7 +233,7 @@ static const CGFloat MASButtonFontSize = 11;
buttonTitle = NSStringFromMASKeyCode(kMASShortcutGlyphClear);
}
if (buttonTitle != nil) {
[self drawInRect:self.bounds withTitle:buttonTitle alignment:NSRightTextAlignment state:NSOffState];
[self drawInRect:self.bounds withTitle:buttonTitle alignment:NSTextAlignmentRight state:NSControlStateValueOff];
}
CGRect shortcutRect;
[self getShortcutRect:&shortcutRect hintRect:NULL];
@@ -223,12 +244,12 @@ static const CGFloat MASButtonFontSize = 11;
? self.shortcutPlaceholder
: MASLocalizedString(@"Type New Shortcut", @"Non-empty shortcut button in recording state")))
: _shortcutValue ? _shortcutValue.description : @"");
[self drawInRect:shortcutRect withTitle:title alignment:NSCenterTextAlignment state:self.isRecording ? NSOnState : NSOffState];
[self drawInRect:shortcutRect withTitle:title alignment:NSTextAlignmentCenter state:self.isRecording ? NSControlStateValueOn : NSControlStateValueOff];
}
else {
if (self.recording)
{
[self drawInRect:self.bounds withTitle:NSStringFromMASKeyCode(kMASShortcutGlyphEscape) alignment:NSRightTextAlignment state:NSOffState];
[self drawInRect:self.bounds withTitle:NSStringFromMASKeyCode(kMASShortcutGlyphEscape) alignment:NSTextAlignmentRight state:NSControlStateValueOff];
CGRect shortcutRect;
[self getShortcutRect:&shortcutRect hintRect:NULL];
@@ -237,16 +258,35 @@ static const CGFloat MASButtonFontSize = 11;
: (self.shortcutPlaceholder.length > 0
? self.shortcutPlaceholder
: MASLocalizedString(@"Type Shortcut", @"Empty shortcut button in recording state")));
[self drawInRect:shortcutRect withTitle:title alignment:NSCenterTextAlignment state:NSOnState];
[self drawInRect:shortcutRect withTitle:title alignment:NSTextAlignmentCenter state:NSControlStateValueOn];
}
else
{
[self drawInRect:self.bounds withTitle:MASLocalizedString(@"Record Shortcut", @"Empty shortcut button in normal state")
alignment:NSCenterTextAlignment state:NSOffState];
alignment:NSTextAlignmentCenter state:NSControlStateValueOff];
}
}
}
- (NSSize)intrinsicContentSize
{
NSSize cellSize = _shortcutCell.cellSize;
// Use a "fake" value for width. Since determining the actual width requires information
// that is not determined until drawRect: is called, it doesn't seem feasible to properly
// calculate the intrinsic size without refactoring the code. That would give better results,
// however.
// 120 is an arbitrary number that seems to be wide enough for English localization. This
// may need to be adjusted for other locales/languages.
// NOTE: Simply returning cellSize results in a display that is sometimes correct
// and sometimes not, and changes based on whether the mouse is hovering or not.
return NSMakeSize(120, cellSize.height);
}
#pragma mark - Mouse handling
- (void)getShortcutRect:(CGRect *)shortcutRectRef hintRect:(CGRect *)hintRectRef
@@ -337,6 +377,7 @@ static const CGFloat MASButtonFontSize = 11;
{
if (_hinting != flag) {
_hinting = flag;
[self invalidateIntrinsicContentSize];
[self setNeedsDisplay:YES];
}
}
@@ -357,10 +398,12 @@ void *kUserDataHint = &kUserDataHint;
- (void)resetToolTips
{
if (_shortcutToolTipTag) {
[self removeToolTip:_shortcutToolTipTag], _shortcutToolTipTag = 0;
[self removeToolTip:_shortcutToolTipTag];
_shortcutToolTipTag = 0;
}
if (_hintToolTipTag) {
[self removeToolTip:_hintToolTipTag], _hintToolTipTag = 0;
[self removeToolTip:_hintToolTipTag];
_hintToolTipTag = 0;
}
if ((self.shortcutValue == nil) || self.recording || !self.enabled) return;
@@ -379,7 +422,7 @@ void *kUserDataHint = &kUserDataHint;
else if (data == kUserDataHint) {
return MASLocalizedString(@"Delete shortcut", @"Tooltip for hint button near the non-empty shortcut");
}
return nil;
return @"";
}
#pragma mark - Event monitoring
@@ -393,7 +436,7 @@ void *kUserDataHint = &kUserDataHint;
static id eventMonitor = nil;
if (shouldActivate) {
__unsafe_unretained MASShortcutView *weakSelf = self;
NSEventMask eventMask = (NSKeyDownMask | NSFlagsChangedMask);
NSEventMask eventMask = (NSEventMaskKeyDown | NSEventMaskFlagsChanged);
eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:eventMask handler:^(NSEvent *event) {
// Create a shortcut from the event
@@ -418,24 +461,24 @@ void *kUserDataHint = &kUserDataHint;
}
// If the shortcut is Cmd-W or Cmd-Q, cancel recording and pass the event through
else if ((shortcut.modifierFlags == NSCommandKeyMask) && (shortcut.keyCode == kVK_ANSI_W || shortcut.keyCode == kVK_ANSI_Q)) {
else if ((shortcut.modifierFlags == NSEventModifierFlagCommand) && (shortcut.keyCode == kVK_ANSI_W || shortcut.keyCode == kVK_ANSI_Q)) {
weakSelf.recording = NO;
}
else {
// Verify possible shortcut
if (shortcut.keyCodeString.length > 0) {
if ([_shortcutValidator isShortcutValid:shortcut]) {
if (!weakSelf.shortcutValidator || [weakSelf.shortcutValidator isShortcutValid:shortcut]) {
// Verify that shortcut is not used
NSString *explanation = nil;
if ([_shortcutValidator isShortcutAlreadyTakenBySystem:shortcut explanation:&explanation]) {
if ([weakSelf.shortcutValidator isShortcutAlreadyTakenBySystem:shortcut explanation:&explanation]) {
// Prevent cancel of recording when Alert window is key
[weakSelf activateResignObserver:NO];
[weakSelf activateEventMonitoring:NO];
NSString *format = MASLocalizedString(@"The key combination %@ cannot be used",
@"Title for alert when shortcut is already used");
NSAlert* alert = [[NSAlert alloc]init];
alert.alertStyle = NSCriticalAlertStyle;
alert.alertStyle = NSAlertStyleCritical;
alert.informativeText = explanation;
alert.messageText = [NSString stringWithFormat:format, shortcut];
[alert addButtonWithTitle:MASLocalizedString(@"OK", @"Alert button when shortcut is already used")];
@@ -538,9 +581,9 @@ void *kUserDataHint = &kUserDataHint;
#pragma mark - Accessibility
- (BOOL)accessibilityIsIgnored
- (BOOL)isAccessibilityElement
{
return NO;
return YES;
}
- (NSString *)accessibilityHelp
@@ -575,22 +618,24 @@ void *kUserDataHint = &kUserDataHint;
- (BOOL)acceptsFirstResponder
{
return _acceptsFirstResponder;
return _acceptsFirstResponder;
}
- (void)setAcceptsFirstResponder:(BOOL)value
{
_acceptsFirstResponder = value;
_acceptsFirstResponder = value;
}
- (BOOL)becomeFirstResponder
{
[self invalidateIntrinsicContentSize];
[self setNeedsDisplay:YES];
return [super becomeFirstResponder];
}
- (BOOL)resignFirstResponder
{
[self invalidateIntrinsicContentSize];
[self setNeedsDisplay:YES];
return [super resignFirstResponder];
}
+9
View File
@@ -0,0 +1,9 @@
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface MASShortcutViewButtonCell : NSButtonCell
@end
NS_ASSUME_NONNULL_END
+29
View File
@@ -0,0 +1,29 @@
#import "MASShortcutViewButtonCell.h"
@implementation MASShortcutViewButtonCell
-(void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
CGRect paddedFrame = cellFrame;
//fix display on Big Sur
if (@available(macOS 11, *)) {
//fix vertical alignment
paddedFrame.origin.y -= 1.0;
//fix cancel button alignment
if (self.alignment == NSTextAlignmentRight &&
(self.bezelStyle == NSBezelStyleTexturedRounded ||
self.bezelStyle == NSBezelStyleRounded)) {
paddedFrame.size.width -= 14.0;
if (self.bezelStyle == NSBezelStyleTexturedRounded)
paddedFrame.origin.x += 7.0;
}
}
[super drawInteriorWithFrame:paddedFrame inView:controlView];
}
@end
@@ -1,3 +1,5 @@
#import <AppKit/AppKit.h>
extern NSString *const MASDictionaryTransformerName;
/**
@@ -12,7 +14,7 @@ extern NSString *const MASDictionaryTransformerName;
that converts any `NSCoding` types to `NSData`, but with shortcuts
it makes sense to use a dictionary instead the defaults look better
when inspected with the `defaults` command-line utility and the
format is compatible with an older sortcut library called Shortcut
format is compatible with an older shortcut library called Shortcut
Recorder.
*/
@interface MASDictionaryTransformer : NSValueTransformer
@@ -9,7 +9,7 @@
XCTAssertNil([transformer transformedValue:nil],
@"Decoding a shortcut from a nil dictionary returns nil.");
XCTAssertNil([transformer transformedValue:(id)@"foo"],
@"Decoding a shortcut from a invalid-type dictionary returns nil.");
@"Decoding a shortcut from an invalid-type dictionary returns nil.");
XCTAssertNil([transformer transformedValue:@{}],
@"Decoding a shortcut from an empty dictionary returns nil.");
XCTAssertNil([transformer transformedValue:@{@"keyCode":@"foo"}],
@@ -57,7 +57,7 @@
/**
Register default shortcuts in user defaults.
This is a convenience frontent to `[NSUserDefaults registerDefaults]`.
This is a convenience frontend to `[NSUserDefaults registerDefaults]`.
The dictionary should contain a map of user defaults keys to appropriate
keyboard shortcuts. The shortcuts will be transformed according to
`bindingOptions` and registered using `registerDefaults`.
+1
View File
@@ -0,0 +1 @@
../User Defaults Storage/MASDictionaryTransformer.h
+1
View File
@@ -0,0 +1 @@
../Monitoring/MASHotKey.h
+1
View File
@@ -0,0 +1 @@
../Model/MASKeyCodes.h
+1
View File
@@ -0,0 +1 @@
../UI/MASLocalization.h
+1
View File
@@ -0,0 +1 @@
../Model/MASShortcut.h
+1
View File
@@ -0,0 +1 @@
../User Defaults Storage/MASShortcutBinder.h
+1
View File
@@ -0,0 +1 @@
../Monitoring/MASShortcutMonitor.h
+1
View File
@@ -0,0 +1 @@
../Model/MASShortcutValidator.h
+1
View File
@@ -0,0 +1 @@
../UI/MASShortcutView+Bindings.h
+1
View File
@@ -0,0 +1 @@
../UI/MASShortcutView.h
+1
View File
@@ -0,0 +1 @@
../UI/MASShortcutViewButtonCell.h
+1
View File
@@ -0,0 +1 @@
../Shortcut.h
+4
View File
@@ -0,0 +1,4 @@
module MASShortcut {
header "Shortcut.h"
export *
}
+6
View File
@@ -0,0 +1,6 @@
source 'https://rubygems.org'
gem 'cocoapods'
gem 'fastlane'
plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)
+214
View File
@@ -0,0 +1,214 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.0)
activesupport (4.2.11.1)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
atomos (0.1.3)
babosa (1.0.2)
claide (1.0.2)
cocoapods (1.7.1)
activesupport (>= 4.0.2, < 5)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.7.1)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 1.2.2, < 2.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-stats (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.3.1, < 2.0)
cocoapods-try (>= 1.1.0, < 2.0)
colored2 (~> 3.1)
escape (~> 0.0.4)
fourflusher (>= 2.2.0, < 3.0)
gh_inspector (~> 1.0)
molinillo (~> 0.6.6)
nap (~> 1.0)
ruby-macho (~> 1.4)
xcodeproj (>= 1.8.2, < 2.0)
cocoapods-core (1.7.1)
activesupport (>= 4.0.2, < 6)
fuzzy_match (~> 2.0.4)
nap (~> 1.0)
cocoapods-deintegrate (1.0.4)
cocoapods-downloader (1.2.2)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.0)
cocoapods-stats (1.1.0)
cocoapods-trunk (1.3.1)
nap (>= 0.8, < 2.0)
netrc (~> 0.11)
cocoapods-try (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander-fastlane (4.4.6)
highline (~> 1.7.2)
concurrent-ruby (1.1.5)
declarative (0.0.10)
declarative-option (0.1.0)
digest-crc (0.4.1)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.2)
emoji_regex (1.0.1)
escape (0.0.4)
excon (0.64.0)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
http-cookie (~> 1.0.0)
faraday_middleware (0.13.1)
faraday (>= 0.7.4, < 1.0)
fastimage (2.1.5)
fastlane (2.125.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
babosa (>= 1.0.2, < 2.0.0)
bundler (>= 1.12.0, < 3.0.0)
colored
commander-fastlane (>= 4.4.6, < 5.0.0)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 2.0)
excon (>= 0.45.0, < 1.0.0)
faraday (~> 0.9)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 0.9)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.21.2, < 0.24.0)
google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
jwt (~> 2.1.0)
mini_magick (~> 4.5.1)
multi_xml (~> 0.5)
multipart-post (~> 2.0.0)
plist (>= 3.1.0, < 4.0.0)
public_suffix (~> 2.0.0)
rubyzip (>= 1.2.2, < 2.0.0)
security (= 0.1.3)
simctl (~> 1.6.3)
slack-notifier (>= 2.0.0, < 3.0.0)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (>= 1.4.5, < 2.0.0)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.8.1, < 2.0.0)
xcpretty (~> 0.3.0)
xcpretty-travis-formatter (>= 0.0.3)
fastlane-plugin-changelog (0.14.0)
fourflusher (2.2.0)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-api-client (0.23.9)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.5, < 0.7.0)
httpclient (>= 2.8.1, < 3.0)
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.9)
google-cloud-core (1.3.0)
google-cloud-env (~> 1.0)
google-cloud-env (1.0.5)
faraday (~> 0.11)
google-cloud-storage (1.16.0)
digest-crc (~> 0.4)
google-api-client (~> 0.23)
google-cloud-core (~> 1.2)
googleauth (>= 0.6.2, < 0.10.0)
googleauth (0.6.7)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.7)
highline (1.7.10)
http-cookie (1.0.3)
domain_name (~> 0.5)
httpclient (2.8.3)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
json (2.2.0)
jwt (2.1.0)
memoist (0.16.0)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2019.0331)
mini_magick (4.5.1)
minitest (5.11.3)
molinillo (0.6.6)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
nanaimo (0.2.6)
nap (1.1.0)
naturally (2.2.0)
netrc (0.11.0)
os (1.0.1)
plist (3.5.0)
public_suffix (2.0.5)
representable (3.0.4)
declarative (< 0.1.0)
declarative-option (< 0.2.0)
uber (< 0.2.0)
retriable (3.1.2)
rouge (2.0.7)
ruby-macho (1.4.0)
rubyzip (1.2.3)
security (0.1.3)
signet (0.11.0)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.5)
CFPropertyList
naturally
slack-notifier (2.3.2)
terminal-notifier (2.0.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
tty-cursor (0.7.0)
tty-screen (0.7.0)
tty-spinner (0.9.1)
tty-cursor (~> 0.7)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.6)
unicode-display_width (1.6.0)
word_wrap (1.0.0)
xcodeproj (1.9.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.2.6)
xcpretty (0.3.0)
rouge (~> 2.0.7)
xcpretty-travis-formatter (1.0.0)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
DEPENDENCIES
cocoapods
fastlane
fastlane-plugin-changelog
BUNDLED WITH
1.16.2
+36
View File
@@ -0,0 +1,36 @@
# Backward Compatibility
Please note that this framework supports older OS X versions down to 10.10. When changing the code, be careful not to call any API functions not available in 10.10 or call them conditionally, only where supported.
# Commit Messages
Please use descriptive commit message. As an example, _Bug fix_ commit message doesnt say much, while _Fix a memory-management bug in formatting code_ works much better. A [nice detailed article about writing commit messages](http://chris.beams.io/posts/git-commit/) is also available.
# How to Release a New Version
The release process is automated using [Fastlane](https://fastlane.tools). To install the tooling:
```bash
bundle install
```
To mint a new release:
```bash
bundle exec fastlane release
```
This will bump the version number, stamp the changelog, etc. By default, the command will produce a patch release. (MASShortcut uses [Semantic Versioning](http://semver.org/), so please read the docs if youre not sure what the deal is.) If you want a minor or major bump:
```bash
bundle exec fastlane release type:minor
bundle exec fastlane release type:major
```
After pushing the release including tags (`git push --follow-tags`), dont forget to publish the release in CocoaPods:
```bash
bundle exec fastlane trunk
```
Thats it. Go have a beer or a cup of tea to celebrate.
+7 -5
View File
@@ -1,6 +1,7 @@
# coding: utf-8
Pod::Spec.new do |s|
s.name = 'MASShortcut'
s.version = '2.3.1'
s.version = '2.4.1'
s.summary = 'Modern framework for managing global keyboard shortcuts compatible with Mac App Store'
s.homepage = 'https://github.com/shpakovski/MASShortcut'
s.license = 'BSD 2-clause'
@@ -8,10 +9,11 @@ Pod::Spec.new do |s|
'Tomáš Znamenáček' => 'tomas.znamenacek@gmail.com' }
s.platform = :osx
s.osx.deployment_target = "10.6"
s.source = { :git => 'https://github.com/shpakovski/MASShortcut.git', :tag => '2.3.1' }
s.source_files = 'Framework/*.{h,m}'
s.exclude_files = 'Framework/*Tests.m'
s.osx.deployment_target = "10.10"
s.source = { :git => 'https://github.com/shpakovski/MASShortcut.git', :tag => s.version }
s.source_files = 'Framework/**/*.{h,m}'
s.exclude_files = 'Framework/**/*Tests.m'
s.osx.frameworks = 'Carbon', 'AppKit'
s.requires_arc = true
s.osx.resource_bundles = { 'MASShortcut' => ['Resources/*.lproj'] }
end
+173 -80
View File
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 48;
objects = {
/* Begin PBXBuildFile section */
@@ -43,6 +43,8 @@
0DC2F190199372B4003A0131 /* MASDictionaryTransformerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC2F18F199372B4003A0131 /* MASDictionaryTransformerTests.m */; };
0DC2F19819938EFA003A0131 /* MASShortcutView+Bindings.h in Headers */ = {isa = PBXBuildFile; fileRef = 0DC2F19619938EFA003A0131 /* MASShortcutView+Bindings.h */; settings = {ATTRIBUTES = (Public, ); }; };
0DC2F19919938EFA003A0131 /* MASShortcutView+Bindings.m in Sources */ = {isa = PBXBuildFile; fileRef = 0DC2F19719938EFA003A0131 /* MASShortcutView+Bindings.m */; };
50C888F126F8E2FE0086EB9A /* MASShortcutViewButtonCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 50C888EF26F8E2FE0086EB9A /* MASShortcutViewButtonCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
50C888F226F8E2FE0086EB9A /* MASShortcutViewButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 50C888F026F8E2FE0086EB9A /* MASShortcutViewButtonCell.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -72,14 +74,13 @@
/* Begin PBXFileReference section */
0D2CAB141B8332E5005431FC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
0D2CAB161B8332EE005431FC /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
0D2CAB171B8339F4005431FC /* MASLocalization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASLocalization.h; path = Framework/MASLocalization.h; sourceTree = "<group>"; };
0D2CAB181B8339F4005431FC /* MASLocalization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASLocalization.m; path = Framework/MASLocalization.m; sourceTree = "<group>"; };
0D2CAB1C1B83409C005431FC /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = "<group>"; };
0D2CAB171B8339F4005431FC /* MASLocalization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASLocalization.h; sourceTree = "<group>"; };
0D2CAB181B8339F4005431FC /* MASLocalization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASLocalization.m; sourceTree = "<group>"; };
0D2CAB1E1B8340A4005431FC /* cs */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = cs; path = cs.lproj/MainMenu.xib; sourceTree = "<group>"; };
0D2CAB221B834464005431FC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
0D2CAB241B834467005431FC /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = "<group>"; };
0D39DCA11A668A4400639145 /* MASHotKeyTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASHotKeyTests.m; path = Framework/MASHotKeyTests.m; sourceTree = "<group>"; };
0D39DCA31A668E5500639145 /* MASShortcutMonitorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASShortcutMonitorTests.m; path = Framework/MASShortcutMonitorTests.m; sourceTree = "<group>"; };
0D39DCA11A668A4400639145 /* MASHotKeyTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASHotKeyTests.m; sourceTree = "<group>"; };
0D39DCA31A668E5500639145 /* MASShortcutMonitorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASShortcutMonitorTests.m; sourceTree = "<group>"; };
0D58DE521BA165FC0023BFBE /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
0D58DE531BA166170023BFBE /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
0D58DE541BA166270023BFBE /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -90,39 +91,53 @@
0D827CD91990D4420010B8EF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
0D827CDA1990D4420010B8EF /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
0D827CDB1990D4420010B8EF /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
0D827D1B1990D55E0010B8EF /* MASShortcut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASShortcut.h; path = Framework/MASShortcut.h; sourceTree = "<group>"; };
0D827D1C1990D55E0010B8EF /* MASShortcut.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASShortcut.m; path = Framework/MASShortcut.m; sourceTree = "<group>"; };
0D827D211990D55E0010B8EF /* MASShortcutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASShortcutView.h; path = Framework/MASShortcutView.h; sourceTree = "<group>"; };
0D827D221990D55E0010B8EF /* MASShortcutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASShortcutView.m; path = Framework/MASShortcutView.m; sourceTree = "<group>"; };
0D827D2F1990D5640010B8EF /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Framework/Info.plist; sourceTree = "<group>"; };
0D827D1B1990D55E0010B8EF /* MASShortcut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASShortcut.h; sourceTree = "<group>"; };
0D827D1C1990D55E0010B8EF /* MASShortcut.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASShortcut.m; sourceTree = "<group>"; };
0D827D211990D55E0010B8EF /* MASShortcutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASShortcutView.h; sourceTree = "<group>"; };
0D827D221990D55E0010B8EF /* MASShortcutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASShortcutView.m; sourceTree = "<group>"; };
0D827D2F1990D5640010B8EF /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0D827D371990D5E70010B8EF /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
0D827D691990D6110010B8EF /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
0D827D6A1990D6110010B8EF /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
0D827D6B1990D6110010B8EF /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0D827D6C1990D6110010B8EF /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = "<group>"; };
0D827D6D1990D6110010B8EF /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
0D827D761990F81E0010B8EF /* Shortcut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Shortcut.h; path = Framework/Shortcut.h; sourceTree = "<group>"; };
0D827D761990F81E0010B8EF /* Shortcut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Shortcut.h; sourceTree = "<group>"; };
0D827D8319910AFF0010B8EF /* MASShortcutTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MASShortcutTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
0D827D8719910AFF0010B8EF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0D827D8D19910AFF0010B8EF /* Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = "<group>"; };
0D827D9319910B740010B8EF /* MASShortcutTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASShortcutTests.m; path = Framework/MASShortcutTests.m; sourceTree = "<group>"; };
0D827D9619910FF70010B8EF /* MASKeyCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASKeyCodes.h; path = Framework/MASKeyCodes.h; sourceTree = "<group>"; };
0D827D98199110F60010B8EF /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Prefix.pch; path = Framework/Prefix.pch; sourceTree = "<group>"; };
0D827D9C19911A190010B8EF /* MASShortcutValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASShortcutValidator.h; path = Framework/MASShortcutValidator.h; sourceTree = "<group>"; };
0D827D9D19911A190010B8EF /* MASShortcutValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASShortcutValidator.m; path = Framework/MASShortcutValidator.m; sourceTree = "<group>"; };
0D827DA319912D240010B8EF /* MASShortcutMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASShortcutMonitor.h; path = Framework/MASShortcutMonitor.h; sourceTree = "<group>"; };
0D827DA419912D240010B8EF /* MASShortcutMonitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASShortcutMonitor.m; path = Framework/MASShortcutMonitor.m; sourceTree = "<group>"; };
0D827DAB199132840010B8EF /* MASShortcutBinder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASShortcutBinder.h; path = Framework/MASShortcutBinder.h; sourceTree = "<group>"; };
0D827DAC199132840010B8EF /* MASShortcutBinder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASShortcutBinder.m; path = Framework/MASShortcutBinder.m; sourceTree = "<group>"; };
0DC2F17419922798003A0131 /* MASHotKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASHotKey.h; path = Framework/MASHotKey.h; sourceTree = "<group>"; };
0DC2F17519922798003A0131 /* MASHotKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASHotKey.m; path = Framework/MASHotKey.m; sourceTree = "<group>"; };
0DC2F18819925F8F003A0131 /* MASShortcutBinderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASShortcutBinderTests.m; path = Framework/MASShortcutBinderTests.m; sourceTree = "<group>"; };
0DC2F18B1993708A003A0131 /* MASDictionaryTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MASDictionaryTransformer.h; path = Framework/MASDictionaryTransformer.h; sourceTree = "<group>"; };
0DC2F18C1993708A003A0131 /* MASDictionaryTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASDictionaryTransformer.m; path = Framework/MASDictionaryTransformer.m; sourceTree = "<group>"; };
0DC2F18F199372B4003A0131 /* MASDictionaryTransformerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASDictionaryTransformerTests.m; path = Framework/MASDictionaryTransformerTests.m; sourceTree = "<group>"; };
0DC2F19619938EFA003A0131 /* MASShortcutView+Bindings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "MASShortcutView+Bindings.h"; path = "Framework/MASShortcutView+Bindings.h"; sourceTree = "<group>"; };
0DC2F19719938EFA003A0131 /* MASShortcutView+Bindings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "MASShortcutView+Bindings.m"; path = "Framework/MASShortcutView+Bindings.m"; sourceTree = "<group>"; };
EAFFDC811AACFF3300F38834 /* MASShortcut.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = MASShortcut.modulemap; path = Framework/MASShortcut.modulemap; sourceTree = "<group>"; };
0D827D9319910B740010B8EF /* MASShortcutTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASShortcutTests.m; sourceTree = "<group>"; };
0D827D9619910FF70010B8EF /* MASKeyCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASKeyCodes.h; sourceTree = "<group>"; };
0D827D98199110F60010B8EF /* Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = "<group>"; };
0D827D9C19911A190010B8EF /* MASShortcutValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASShortcutValidator.h; sourceTree = "<group>"; };
0D827D9D19911A190010B8EF /* MASShortcutValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASShortcutValidator.m; sourceTree = "<group>"; };
0D827DA319912D240010B8EF /* MASShortcutMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASShortcutMonitor.h; sourceTree = "<group>"; };
0D827DA419912D240010B8EF /* MASShortcutMonitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASShortcutMonitor.m; sourceTree = "<group>"; };
0D827DAB199132840010B8EF /* MASShortcutBinder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASShortcutBinder.h; sourceTree = "<group>"; };
0D827DAC199132840010B8EF /* MASShortcutBinder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASShortcutBinder.m; sourceTree = "<group>"; };
0DC2F17419922798003A0131 /* MASHotKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASHotKey.h; sourceTree = "<group>"; };
0DC2F17519922798003A0131 /* MASHotKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASHotKey.m; sourceTree = "<group>"; };
0DC2F18819925F8F003A0131 /* MASShortcutBinderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASShortcutBinderTests.m; sourceTree = "<group>"; };
0DC2F18B1993708A003A0131 /* MASDictionaryTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASDictionaryTransformer.h; sourceTree = "<group>"; };
0DC2F18C1993708A003A0131 /* MASDictionaryTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASDictionaryTransformer.m; sourceTree = "<group>"; };
0DC2F18F199372B4003A0131 /* MASDictionaryTransformerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASDictionaryTransformerTests.m; sourceTree = "<group>"; };
0DC2F19619938EFA003A0131 /* MASShortcutView+Bindings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MASShortcutView+Bindings.h"; sourceTree = "<group>"; };
0DC2F19719938EFA003A0131 /* MASShortcutView+Bindings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MASShortcutView+Bindings.m"; sourceTree = "<group>"; };
0DEDAA021C6BB479001605F5 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
50C888EF26F8E2FE0086EB9A /* MASShortcutViewButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MASShortcutViewButtonCell.h; sourceTree = "<group>"; };
50C888F026F8E2FE0086EB9A /* MASShortcutViewButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MASShortcutViewButtonCell.m; sourceTree = "<group>"; };
57B25C2D1E78E06D0061A9EC /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = "<group>"; };
57B25C2E1E78E06D0061A9EC /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/Localizable.strings; sourceTree = "<group>"; };
6EA6034E1CBF822000A3ED9C /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
6EA6034F1CBF822800A3ED9C /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = "<group>"; };
6EA603501CBF822D00A3ED9C /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
6EA603511CBF823600A3ED9C /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
76A0597D1C51DC940014B271 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
76A0597E1C51DC9F0014B271 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
EAFFDC811AACFF3300F38834 /* MASShortcut.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = MASShortcut.modulemap; sourceTree = "<group>"; };
ED840EAE25E66B37003F76F7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
ED8737791BCE459800BB1716 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = "<group>"; };
FDFF016F20CB2FB400CC88F3 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -157,8 +172,9 @@
0D827CC91990D4420010B8EF = {
isa = PBXGroup;
children = (
0D827D151990D4D70010B8EF /* Framework */,
0DBA0B9E22A4FAC5008685CD /* Framework */,
0D827D8519910AFF0010B8EF /* Test Support */,
0DBA0B9C22A4F88C008685CD /* Resources */,
0D827D681990D6110010B8EF /* Demo */,
0D827CD51990D4420010B8EF /* Frameworks */,
0D827CD41990D4420010B8EF /* Products */,
@@ -186,22 +202,6 @@
name = Frameworks;
sourceTree = "<group>";
};
0D827D151990D4D70010B8EF /* Framework */ = {
isa = PBXGroup;
children = (
0D827DA019912A660010B8EF /* Model */,
0D827DA219912A870010B8EF /* Monitoring */,
0DC2F18A19937060003A0131 /* User Defaults Storage */,
0D827DA119912A6D0010B8EF /* UI */,
0D827D2F1990D5640010B8EF /* Info.plist */,
EAFFDC811AACFF3300F38834 /* MASShortcut.modulemap */,
0D2CAB151B8332E5005431FC /* Localizable.strings */,
0D827D98199110F60010B8EF /* Prefix.pch */,
0D827D761990F81E0010B8EF /* Shortcut.h */,
);
name = Framework;
sourceTree = "<group>";
};
0D827D681990D6110010B8EF /* Demo */ = {
isa = PBXGroup;
children = (
@@ -226,7 +226,31 @@
path = Tests;
sourceTree = "<group>";
};
0D827DA019912A660010B8EF /* Model */ = {
0DBA0B9C22A4F88C008685CD /* Resources */ = {
isa = PBXGroup;
children = (
0D2CAB151B8332E5005431FC /* Localizable.strings */,
);
name = Resources;
path = Framework/Resources;
sourceTree = "<group>";
};
0DBA0B9E22A4FAC5008685CD /* Framework */ = {
isa = PBXGroup;
children = (
0DBA0B9F22A4FACE008685CD /* Model */,
0DBA0BA022A4FAE0008685CD /* Monitoring */,
0DBA0BA122A4FAF6008685CD /* User Defaults Storage */,
0DBA0BA222A4FB15008685CD /* UI */,
0D827D2F1990D5640010B8EF /* Info.plist */,
EAFFDC811AACFF3300F38834 /* MASShortcut.modulemap */,
0D827D98199110F60010B8EF /* Prefix.pch */,
0D827D761990F81E0010B8EF /* Shortcut.h */,
);
path = Framework;
sourceTree = "<group>";
};
0DBA0B9F22A4FACE008685CD /* Model */ = {
isa = PBXGroup;
children = (
0D827D9619910FF70010B8EF /* MASKeyCodes.h */,
@@ -236,23 +260,10 @@
0D827D9C19911A190010B8EF /* MASShortcutValidator.h */,
0D827D9D19911A190010B8EF /* MASShortcutValidator.m */,
);
name = Model;
path = Model;
sourceTree = "<group>";
};
0D827DA119912A6D0010B8EF /* UI */ = {
isa = PBXGroup;
children = (
0D2CAB171B8339F4005431FC /* MASLocalization.h */,
0D2CAB181B8339F4005431FC /* MASLocalization.m */,
0D827D211990D55E0010B8EF /* MASShortcutView.h */,
0D827D221990D55E0010B8EF /* MASShortcutView.m */,
0DC2F19619938EFA003A0131 /* MASShortcutView+Bindings.h */,
0DC2F19719938EFA003A0131 /* MASShortcutView+Bindings.m */,
);
name = UI;
sourceTree = "<group>";
};
0D827DA219912A870010B8EF /* Monitoring */ = {
0DBA0BA022A4FAE0008685CD /* Monitoring */ = {
isa = PBXGroup;
children = (
0DC2F17419922798003A0131 /* MASHotKey.h */,
@@ -262,10 +273,10 @@
0D827DA419912D240010B8EF /* MASShortcutMonitor.m */,
0D39DCA31A668E5500639145 /* MASShortcutMonitorTests.m */,
);
name = Monitoring;
path = Monitoring;
sourceTree = "<group>";
};
0DC2F18A19937060003A0131 /* User Defaults Storage */ = {
0DBA0BA122A4FAF6008685CD /* User Defaults Storage */ = {
isa = PBXGroup;
children = (
0DC2F18B1993708A003A0131 /* MASDictionaryTransformer.h */,
@@ -275,7 +286,22 @@
0D827DAC199132840010B8EF /* MASShortcutBinder.m */,
0DC2F18819925F8F003A0131 /* MASShortcutBinderTests.m */,
);
name = "User Defaults Storage";
path = "User Defaults Storage";
sourceTree = "<group>";
};
0DBA0BA222A4FB15008685CD /* UI */ = {
isa = PBXGroup;
children = (
0D2CAB171B8339F4005431FC /* MASLocalization.h */,
0D2CAB181B8339F4005431FC /* MASLocalization.m */,
0D827D211990D55E0010B8EF /* MASShortcutView.h */,
0D827D221990D55E0010B8EF /* MASShortcutView.m */,
50C888EF26F8E2FE0086EB9A /* MASShortcutViewButtonCell.h */,
50C888F026F8E2FE0086EB9A /* MASShortcutViewButtonCell.m */,
0DC2F19619938EFA003A0131 /* MASShortcutView+Bindings.h */,
0DC2F19719938EFA003A0131 /* MASShortcutView+Bindings.m */,
);
path = UI;
sourceTree = "<group>";
};
/* End PBXGroup section */
@@ -295,6 +321,7 @@
0D827DA519912D240010B8EF /* MASShortcutMonitor.h in Headers */,
0D827DAD199132840010B8EF /* MASShortcutBinder.h in Headers */,
0D2CAB191B8339F4005431FC /* MASLocalization.h in Headers */,
50C888F126F8E2FE0086EB9A /* MASShortcutViewButtonCell.h in Headers */,
0DC2F17619922798003A0131 /* MASHotKey.h in Headers */,
0D827D771990F81E0010B8EF /* Shortcut.h in Headers */,
);
@@ -363,7 +390,7 @@
0D827CCA1990D4420010B8EF /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
LastUpgradeCheck = 1250;
ORGANIZATIONNAME = "Vadim Shpakovski";
TargetAttributes = {
0D827D8219910AFF0010B8EF = {
@@ -372,8 +399,8 @@
};
};
buildConfigurationList = 0D827CCD1990D4420010B8EF /* Build configuration list for PBXProject "MASShortcut" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
compatibilityVersion = "Xcode 8.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
@@ -383,6 +410,15 @@
it,
fr,
ja,
"zh-Hans",
"zh-Hant",
pl,
ko,
ru,
nl,
pt,
sv,
Base,
);
mainGroup = 0D827CC91990D4420010B8EF;
productRefGroup = 0D827CD41990D4420010B8EF /* Products */;
@@ -436,6 +472,7 @@
0DC2F18E1993708A003A0131 /* MASDictionaryTransformer.m in Sources */,
0D2CAB1A1B8339F4005431FC /* MASLocalization.m in Sources */,
0DC2F19919938EFA003A0131 /* MASShortcutView+Bindings.m in Sources */,
50C888F226F8E2FE0086EB9A /* MASShortcutViewButtonCell.m in Sources */,
0DC2F17D199232F7003A0131 /* MASShortcutBinder.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -482,6 +519,14 @@
0D58DE541BA166270023BFBE /* it */,
0D58DE551BA166390023BFBE /* fr */,
0D58DE561BA166420023BFBE /* ja */,
76A0597D1C51DC940014B271 /* zh-Hans */,
76A0597E1C51DC9F0014B271 /* zh-Hant */,
6EA6034E1CBF822000A3ED9C /* pl */,
6EA6034F1CBF822800A3ED9C /* ko */,
6EA603501CBF822D00A3ED9C /* ru */,
6EA603511CBF823600A3ED9C /* nl */,
57B25C2D1E78E06D0061A9EC /* pt */,
FDFF016F20CB2FB400CC88F3 /* sv */,
);
name = Localizable.strings;
sourceTree = "<group>";
@@ -489,8 +534,8 @@
0D2CAB1D1B83409C005431FC /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
0D2CAB1C1B83409C005431FC /* en */,
0D2CAB1E1B8340A4005431FC /* cs */,
ED840EAE25E66B37003F76F7 /* Base */,
);
name = MainMenu.xib;
sourceTree = "<group>";
@@ -500,6 +545,9 @@
children = (
0D2CAB221B834464005431FC /* en */,
0D2CAB241B834467005431FC /* cs */,
ED8737791BCE459800BB1716 /* ja */,
0DEDAA021C6BB479001605F5 /* de */,
57B25C2E1E78E06D0061A9EC /* pt */,
);
name = Localizable.strings;
sourceTree = "<group>";
@@ -511,22 +559,38 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
@@ -540,7 +604,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.10;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
@@ -550,23 +614,38 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
@@ -574,7 +653,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.10;
SDKROOT = macosx;
};
name = Release;
@@ -582,19 +661,23 @@
0D827CFC1990D4420010B8EF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_CURRENT_VERSION = 2.4.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Framework/Prefix.pch;
INFOPLIST_FILE = Framework/Info.plist;
INSTALL_PATH = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.6;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = Framework/MASShortcut.modulemap;
PRODUCT_BUNDLE_IDENTIFIER = "com.github.shpakovski.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USER_HEADER_SEARCH_PATHS = "\"$SRCROOT/Framework/include\"";
USE_HEADERMAP = NO;
WRAPPER_EXTENSION = framework;
};
name = Debug;
@@ -602,19 +685,23 @@
0D827CFD1990D4420010B8EF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_CURRENT_VERSION = 2.4.0;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Framework/Prefix.pch;
INFOPLIST_FILE = Framework/Info.plist;
INSTALL_PATH = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.6;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MODULEMAP_FILE = Framework/MASShortcut.modulemap;
PRODUCT_BUNDLE_IDENTIFIER = "com.github.shpakovski.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
USER_HEADER_SEARCH_PATHS = "\"$SRCROOT/Framework/include\"";
USE_HEADERMAP = NO;
WRAPPER_EXTENSION = framework;
};
name = Release;
@@ -623,6 +710,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Demo/Prefix.pch;
@@ -631,7 +719,8 @@
"$(inherited)",
);
INFOPLIST_FILE = Demo/Info.plist;
MACOSX_DEPLOYMENT_TARGET = 10.6;
MACOSX_DEPLOYMENT_TARGET = 10.11;
PRODUCT_BUNDLE_IDENTIFIER = "com.shpakovski.mac.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -641,11 +730,13 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "-";
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Demo/Prefix.pch;
INFOPLIST_FILE = Demo/Info.plist;
MACOSX_DEPLOYMENT_TARGET = 10.6;
MACOSX_DEPLOYMENT_TARGET = 10.11;
PRODUCT_BUNDLE_IDENTIFIER = "com.shpakovski.mac.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
};
@@ -666,6 +757,7 @@
"$(inherited)",
);
INFOPLIST_FILE = Tests/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "com.github.shpakovski.MASShortcut.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = xctest;
};
@@ -682,6 +774,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Tests/Prefix.pch;
INFOPLIST_FILE = Tests/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "com.github.shpakovski.MASShortcut.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = xctest;
};
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0610"
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
@@ -38,8 +36,8 @@
ReferencedContainer = "container:MASShortcut.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -61,8 +59,6 @@
ReferencedContainer = "container:MASShortcut.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0610"
LastUpgradeVersion = "1250"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -37,10 +37,19 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D827CD21990D4420010B8EF"
BuildableName = "MASShortcut.framework"
BlueprintName = "MASShortcut"
ReferencedContainer = "container:MASShortcut.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
@@ -53,24 +62,16 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D827CD21990D4420010B8EF"
BuildableName = "MASShortcut.framework"
BlueprintName = "MASShortcut"
ReferencedContainer = "container:MASShortcut.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
@@ -81,14 +82,12 @@
ReferencedContainer = "container:MASShortcut.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
+10
View File
@@ -0,0 +1,10 @@
.PHONY: release
ifndef BUILDDIR
BUILDDIR := $(shell mktemp -d "$(TMPDIR)/MASShortcut.XXXXXX")
endif
release:
xcodebuild -scheme MASShortcut -configuration Release -derivedDataPath "$(BUILDDIR)" build
open "$(BUILDDIR)/Build/Products/Release"
Executable
+36
View File
@@ -0,0 +1,36 @@
// swift-tools-version:5.4
import PackageDescription
let package = Package(
name: "MASShortcut",
defaultLocalization: "en",
platforms: [
.macOS(.v10_11),
],
products: [
.library(name: "MASShortcut",
targets: ["MASShortcut"])
],
targets: [
.target(
name: "MASShortcut",
path: "Framework",
exclude: [
"Model/MASShortcutTests.m",
"Monitoring/MASHotKeyTests.m",
"Monitoring/MASShortcutMonitorTests.m",
"User Defaults Storage/MASDictionaryTransformerTests.m",
"User Defaults Storage/MASShortcutBinderTests.m",
"Info.plist",
"MASShortcut.modulemap",
"Prefix.pch"
],
resources: [
.process("Resources")
],
publicHeadersPath: "include"
)
],
swiftLanguageVersions: [.v5]
)
+29 -6
View File
@@ -17,19 +17,25 @@ Features:
* Can be configured to be compatible with Shortcut Recorder
* Can be installed both through CocoaPods and as a Git submodule
* Mac App Store friendly
* Works on OS X 10.6 and up
* Works on OS X 10.10 and up
* Hacking-friendly codebase covered with tests
* Basic accessibility support
Important features currently missing:
Partially done:
* Localisation
* Accessibility support. Theres some basic accessibility code, testers and feedback welcome.
* Localisation. The English and Czech localization should be complete, theres basic support for German, French, Spanish, Italian, and Japanese. If youre a native speaker in one of the mentioned languages, please test the localization and report issues or add missing strings.
Pull requests welcome :)
# Installation
### Swift Package Manager
[Swift Package Manager](https://swift.org/package-manager/) is the simplest way to install for Xcode projects. Simply add the following Package Dependency:
https://github.com/shpakovski/MASShortcut
You can use [CocoaPods](http://cocoapods.org/), adding the following line to your Podfile:
### CocoaPods
You can also use [CocoaPods](http://cocoapods.org/), by adding the following line to your Podfile:
pod 'MASShortcut'
@@ -37,14 +43,17 @@ If you want to stick to the 1.x branch, you can use the version smart match oper
pod 'MASShortcut', '~> 1'
### Carthage
You can also install via [Carthage](https://github.com/Carthage/Carthage), or you can use Git submodules and link against the MASShortcut framework manually.
To build from the command line, type 'make release'. The framework will be created in a temporary directory and revealed in Finder when the build is complete.
# Usage
I hope, it is really easy:
```objective-c
#import <MASShortcut/Shortcut.h>
#import <Shortcut.h>
// Drop a custom view into XIB, set its class to MASShortcutView
// and its height to 19. If you select another appearance style,
@@ -65,6 +74,12 @@ self.shortcutView.associatedUserDefaultsKey = kPreferenceGlobalShortcut;
}];
```
When you have installed via a method other than Swift Package Manager, then the import is slightly different:
```objective-c
#import <MASShortcut/Shortcut.h>
```
You can see a real usage example in the Demo target. Enjoy!
# Shortcut Recorder Compatibility
@@ -120,6 +135,14 @@ _observableKeyPath = [@"values." stringByAppendingString:kPreferenceGlobalShortc
# Using in Swift projects
Swift Package Manager is the simplest way to import MASShortcut, just import the Module like so:
```
import MASShortcut
```
Alternatively, you can also:
1. Install as a Pod using the latest CocoaPods with Swift support.
2. Create a bridging header file [using the instructions here](http://swiftalicio.us/2014/11/using-cocoapods-from-swift/)
3. Your bridging header file should contain the following [two](https://github.com/shpakovski/MASShortcut/issues/36) imports:
+3 -3
View File
@@ -7,16 +7,16 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.github.shpakovski.MASShortcut.${PRODUCT_NAME:rfc1034identifier}</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>2.4.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>2.4.0</string>
</dict>
</plist>
-47
View File
@@ -1,47 +0,0 @@
/* Cancel action button in recording state */
"Cancel" = "キャンセルする";
/* Tooltip for non-empty shortcut button */
"Click to record new shortcut" = "Click to record new shortcut";
/* Tooltip for hint button near the non-empty shortcut */
"Delete shortcut" = "Delete shortcut";
/* VoiceOver title */
"keyboard shortcut" = "keyboard shortcut";
/* Alert button when shortcut is already used */
"OK" = "OK";
/* Empty shortcut button in normal state */
"Record Shortcut" = "記録のショートカット";
/* VoiceOver: Shortcut cleared */
"Shortcut cleared" = "Shortcut cleared";
/* VoiceOver: Shortcut set */
"Shortcut set" = "Shortcut set";
/* Shortcut glyph name for SPACE key */
"Space" = "スペース";
/* Title for alert when shortcut is already used */
"The key combination %@ cannot be used" = "The key combination %@ cannot be used";
/* Message for alert when shortcut is already used by the system */
"This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences." = "This combination cannot be used because it is already used by a system-wide keyboard shortcut.\nIf you really want to use this key combination, most shortcuts can be changed in the Keyboard & Mouse panel in System Preferences.";
/* Message for alert when shortcut is already used */
"This shortcut cannot be used because it is already used by the menu item %@." = "This shortcut cannot be used because it is already used by the menu item %@.";
/* VoiceOver shortcut help */
"To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut." = "To record a new shortcut, click this button, and then type the new shortcut, or press delete to clear an existing shortcut.";
/* Non-empty shortcut button in recording state */
"Type New Shortcut" = "タイプのショートカット";
/* Empty shortcut button in recording state */
"Type Shortcut" = "タイプのショートカット";
/* Cancel action button for non-empty shortcut in recording state */
"Use Old Shortcut" = "Use Old Shortcut";