• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • sources
  • kde-4.14
  • kdelibs
  • kdeui
  • util
kkeyserver_mac.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 Marijn Kruisselbrink <m.kruisselbrink@student.tue.nl>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18  */
19 
20 #include "kkeyserver_mac.h"
21 
22 #include <config.h>
23 
24 #include <QtCore/QCOORD>
25 
26 #ifdef Q_WS_MACX // Only compile this module if we're compiling for Mac OS X
27 
28 #include "kshortcut.h"
29 #include <kdebug.h>
30 #include <QMultiMap>
31 #include <Carbon/Carbon.h>
32 
33 namespace KKeyServer {
34  struct TransKey {
35  int qt_code;
36  int mac_code;
37  };
38 
39  static TransKey qtKeyToChar[] = {
40  {Qt::Key_Escape, kEscapeCharCode},
41  {Qt::Key_Tab, kTabCharCode},
42  {Qt::Key_Backtab, kTabCharCode}, // Backtab == tab with different modifiers
43  {Qt::Key_Backspace, kBackspaceCharCode},
44  {Qt::Key_Return, kReturnCharCode},
45  {Qt::Key_Enter, kEnterCharCode},
46  // Insert
47  {Qt::Key_Delete, kDeleteCharCode},
48  // Pause, Print, SysReq
49  {Qt::Key_Clear, kClearCharCode},
50  {Qt::Key_Home, kHomeCharCode},
51  {Qt::Key_End, kEndCharCode},
52  {Qt::Key_Left, kLeftArrowCharCode},
53  {Qt::Key_Up, kUpArrowCharCode},
54  {Qt::Key_Right, kRightArrowCharCode},
55  {Qt::Key_Down, kDownArrowCharCode},
56  {Qt::Key_PageUp, kPageUpCharCode},
57  {Qt::Key_PageDown, kPageDownCharCode},
58  // Shift, Control, Meta, Alt, CapsLock, NumLock, ScrollLock
59  // Super_L, Super_R, Menu, Hyper_L, Hyper_R
60  {Qt::Key_Help, kHelpCharCode},
61  // Direction_L, Direction_R
62  {Qt::Key_nobreakspace, kNonBreakingSpaceCharCode},
63  {0, 0}
64  };
65 
66  static QMultiMap<int, uint> scancodes;
67  static long lastLayoutID = -1;
68 #ifdef QT_MAC_USE_COCOA
69  static TISInputSourceRef lastLayout = 0;
70 #else
71  static KeyboardLayoutRef lastLayout = NULL;
72 #endif
73 
74  void updateScancodes() {
75 #ifdef QT_MAC_USE_COCOA
76  TISInputSourceRef layout = TISCopyCurrentKeyboardLayoutInputSource();
77  if (!layout) {
78  kWarning() << "Error retrieving current layout";
79  return;
80  }
81  if (layout == lastLayout) {
82  CFRelease(layout);
83  } else {
84  // keyboard layout changed
85 #ifndef NDEBUG
86  const void *name = TISGetInputSourceProperty(layout, kTISPropertyLocalizedName);
87  kDebug() << "Layout changed to: " << CFStringGetCStringPtr((CFStringRef)name, 0);
88 #endif
89  lastLayout = layout;
90  scancodes.clear();
91 
92  CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(layout,
93  kTISPropertyUnicodeKeyLayoutData));
94  const UCKeyboardLayout *ucData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0;
95 
96  if (!ucData) {
97  kWarning() << "Error retrieving current layout character data";
98  return;
99  }
100 
101  for (int i = 0; i < 128; ++i) {
102  UInt32 tmpState = 0;
103  UniChar str[4];
104  UniCharCount actualLength = 0;
105  OSStatus err = UCKeyTranslate(ucData, i, kUCKeyActionDown, 0, LMGetKbdType(),
106  kUCKeyTranslateNoDeadKeysMask, &tmpState, 4, &actualLength, str);
107  if (err != noErr) {
108  kWarning() << "Error translating unicode key" << err;
109  } else {
110  if (str[0] && str[0] != kFunctionKeyCharCode)
111  scancodes.insert(str[0], i);
112  }
113  }
114  }
115 #else
116  KeyboardLayoutRef layout;
117  if (KLGetCurrentKeyboardLayout(&layout) != noErr) {
118  kWarning() << "Error retrieving current layout";
119  }
120  if (layout != lastLayout) {
121 #ifndef NDEBUG
122  void *name;
123  KLGetKeyboardLayoutProperty(layout, kKLName, const_cast<const void**>(&name));
124  kDebug() << "Layout changed to: " << CFStringGetCStringPtr((CFStringRef) name, 0);
125 #endif
126  lastLayout = layout;
127  scancodes.clear();
128  void *kchr;
129  if (KLGetKeyboardLayoutProperty(layout, kKLKCHRData, const_cast<const void**>(&kchr)) != noErr) {
130  kWarning() << "Couldn't load active keyboard layout";
131  } else {
132  for (int i = 0; i < 128; i++) {
133  UInt32 tmpState = 0;
134  UInt32 chr = KeyTranslate(kchr, i, &tmpState);
135  if (chr && chr != kFunctionKeyCharCode) {
136  scancodes.insert(chr, i);
137  }
138  }
139  }
140  }
141 #endif
142  }
143 
144 #define SCANCODE(name, value) { Qt::Key_ ## name, value }
145  static TransKey functionKeys[] = {
146  SCANCODE(F1, 122),
147  SCANCODE(F2, 120),
148  SCANCODE(F3, 99),
149  SCANCODE(F4, 118),
150  SCANCODE(F5, 96),
151  SCANCODE(F6, 97),
152  SCANCODE(F7, 98),
153  SCANCODE(F8, 100),
154  SCANCODE(F9, 101),
155  SCANCODE(F10, 109),
156  //TODO: figure out scancodes of other F* keys
157  { 0, 0 }
158  };
159 #undef SCANCODE
160 
161  bool keyQtToSymMac( int keyQt, int& sym )
162  {
163  // Printable ascii values, before A
164  if (keyQt >= 0x20 && keyQt < Qt::Key_A) {
165  sym = keyQt;
166  return true;
167  }
168  // Letters, return lower-case equivalent
169  if (keyQt >= Qt::Key_A && keyQt <= Qt::Key_Z) {
170  sym = keyQt - Qt::Key_A + 'a';
171  return true;
172  }
173  // Printable ascii values up to lower-case a
174  if (keyQt > Qt::Key_Z && keyQt <= 0x60) {
175  sym = keyQt;
176  return true;
177  }
178  // Remainder of printable ascii values
179  if (keyQt >= 0x7B && keyQt < 0x7F) {
180  sym = keyQt;
181  return true;
182  }
183  // Function keys
184  if (keyQt >= Qt::Key_F1 && keyQt <= Qt::Key_F35) {
185  sym = kFunctionKeyCharCode;
186  return true;
187  }
188  // Try to find in lookup table
189  for (int i = 0; qtKeyToChar[i].qt_code; i++) {
190  if (qtKeyToChar[i].qt_code == keyQt) {
191  sym = qtKeyToChar[i].mac_code;
192  return true;
193  }
194  }
195 
196  // Not found
197  return false;
198  }
199 
200  bool keyQtToCodeMac( int keyQt, QList<uint>& keyCodes )
201  {
202  updateScancodes();
203  keyCodes.clear();
204  keyQt &= ~Qt::KeyboardModifierMask;
205  int chr;
206  if (!keyQtToSymMac( keyQt, chr ) ) return false;
207 
208  if (chr == kFunctionKeyCharCode) {
209  for (int i = 0; functionKeys[i].qt_code; i++) {
210  if (functionKeys[i].qt_code == keyQt) {
211  keyCodes.append(functionKeys[i].mac_code);
212  }
213  }
214  } else {
215  keyCodes += scancodes.values(chr);
216  }
217 
218  return keyCodes.count() > 0;
219  }
220 
221  bool keyQtToModMac( int keyQt, uint& mod )
222  {
223  mod = 0;
224  if (keyQt & Qt::ShiftModifier) {
225  mod |= shiftKey;
226  }
227  if (keyQt & Qt::ControlModifier) {
228  mod |= cmdKey;
229  }
230  if (keyQt & Qt::AltModifier) {
231  mod |= optionKey;
232  }
233  if (keyQt & Qt::MetaModifier) {
234  mod |= controlKey;
235  }
236  if (keyQt & Qt::KeypadModifier) {
237  mod |= kEventKeyModifierNumLockMask;
238  }
239  // Special case for Qt::Key_Backtab
240  if ((keyQt & ~Qt::KeyboardModifierMask) == Qt::Key_Backtab) {
241  mod |= shiftKey;
242  }
243 
244  return true;
245  }
246 } // end of namespace KKeyServer
247 
248 #endif // Q_WS_MACX
249 
QList::clear
void clear()
kdebug.h
KStandardAction::name
const char * name(StandardAction id)
This will return the internal name of a given standard action.
Definition: kstandardaction.cpp:223
kshortcut.h
Defines platform-independent classes for keyboard shortcut handling.
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
KKeyServer::keyQtToCodeMac
bool keyQtToCodeMac(int keyQt, QList< uint > &keyCodes)
Extracts all the scancodes from the given Qt key.
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
QList
kkeyserver_mac.h
KKeyServer::keyQtToModMac
bool keyQtToModMac(int keyQt, uint &mod)
Extracts the modifiers from the given Qt key and converts them in a mask of OSX modifiers.
kWarning
static QDebug kWarning(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
QMultiMap
KKeyServer::keyQtToSymMac
bool keyQtToSymMac(int keyQt, int &sym)
Extracts the symbol from the given Qt key, and converts it to an OSX symbol.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:23:59 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal