Audacity  2.2.2
Public Member Functions | Private Member Functions | List of all members
CommandManagerEventMonitor Class Referencefinal
Inheritance diagram for CommandManagerEventMonitor:

Public Member Functions

 CommandManagerEventMonitor ()
 
virtual ~CommandManagerEventMonitor ()
 
int FilterEvent (wxEvent &event) override
 

Private Member Functions

bool HandleCapture (wxWindow *target, const wxKeyEvent &event)
 
wxString GetUnicodeString (const wxKeyEvent &event)
 

Detailed Description

Definition at line 124 of file CommandManager.cpp.

Constructor & Destructor Documentation

CommandManagerEventMonitor::CommandManagerEventMonitor ( )
inline

Definition at line 127 of file CommandManager.cpp.

References FilterEvent().

128  : wxEventFilter()
129  {
130 #if defined(__WXMAC__)
131  // In wx3, the menu accelerators take precendence over key event processing
132  // so we won't get wxEVT_CHAR_HOOK events for combinations assigned to menus.
133  // Since we only support OS X 10.6 or greater, we can use an event monitor
134  // to capture the key event before it gets to the normal wx3 processing.
135 
136  // The documentation for addLocalMonitorForEventsMatchingMask implies that
137  // NSKeyUpMask can't be used in 10.6, but testing shows that it can.
138  NSEventMask mask = NSKeyDownMask | NSKeyUpMask;
139 
140  mHandler =
141  [
142  NSEvent addLocalMonitorForEventsMatchingMask:mask handler:^NSEvent *(NSEvent *event)
143  {
144  WXWidget widget = (WXWidget) [[event window] firstResponder];
145  if (widget)
146  {
147  wxWidgetCocoaImpl *impl = (wxWidgetCocoaImpl *)
148  wxWidgetImpl::FindFromWXWidget(widget);
149  if (impl)
150  {
151  mEvent = event;
152 
153  wxKeyEvent wxevent([event type] == NSKeyDown ? wxEVT_KEY_DOWN : wxEVT_KEY_UP);
154  impl->SetupKeyEvent(wxevent, event);
155 
156  NSEvent *result;
157  if ([event type] == NSKeyDown)
158  {
159  wxKeyEvent eventHook(wxEVT_CHAR_HOOK, wxevent);
160  result = FilterEvent(eventHook) == Event_Processed ? nil : event;
161  }
162  else
163  {
164  result = FilterEvent(wxevent) == Event_Processed ? nil : event;
165  }
166 
167  mEvent = nullptr;
168  return result;
169  }
170  }
171 
172  return event;
173  }
174  ];
175 
176  // Bug1252: must also install this filter with wxWidgets, else
177  // we don't intercept command keys when focus is in a combo box.
178  wxEvtHandler::AddFilter(this);
179 #else
180 
181  wxEvtHandler::AddFilter(this);
182 
183 #endif
184  }
int FilterEvent(wxEvent &event) override
virtual CommandManagerEventMonitor::~CommandManagerEventMonitor ( )
inlinevirtual

Definition at line 186 of file CommandManager.cpp.

187  {
188 #if defined(__WXMAC__)
189  [NSEvent removeMonitor:mHandler];
190 #else
191  wxEvtHandler::RemoveFilter(this);
192 #endif
193  }

Member Function Documentation

int CommandManagerEventMonitor::FilterEvent ( wxEvent &  event)
inlineoverride

Definition at line 195 of file CommandManager.cpp.

References CommandManager::FilterKeyEvent(), GetActiveProject(), AudacityProject::GetCommandManager(), AudacityProject::GetKeyboardCaptureHandler(), HandleCapture(), and MakeSimpleGuard().

Referenced by CommandManagerEventMonitor().

196  {
197  // Unguarded exception propagation may crash the program, at least
198  // on Mac while in the objective-C closure above
199  return GuardedCall< int > ( [&] {
200  // Quickly bail if this isn't something we want.
201  wxEventType type = event.GetEventType();
202  if (type != wxEVT_CHAR_HOOK && type != wxEVT_KEY_UP)
203  {
204  return Event_Skip;
205  }
206 
207  // We must have a project since we will be working with the Command Manager
208  // and capture handler, both of which are (currently) tied to individual projects.
209  //
210  // Shouldn't they be tied to the application instead???
211  AudacityProject *project = GetActiveProject();
212  if (!project || !project->IsEnabled())
213  {
214  return Event_Skip;
215  }
216 
217  // Make a copy of the event and (possibly) make it look like a key down
218  // event.
219  wxKeyEvent key = (wxKeyEvent &) event;
220  if (type == wxEVT_CHAR_HOOK)
221  {
222  key.SetEventType(wxEVT_KEY_DOWN);
223  }
224 
225  // Give the capture handler first dibs at the event.
226  wxWindow *handler = project->GetKeyboardCaptureHandler();
227  if (handler && HandleCapture(handler, key))
228  {
229  return Event_Processed;
230  }
231 
232  // Capture handler didn't want it, so ask the Command Manager.
233  CommandManager *manager = project->GetCommandManager();
234  if (manager && manager->FilterKeyEvent(project, key))
235  {
236  return Event_Processed;
237  }
238 
239  // Give it back to WX for normal processing.
240  return Event_Skip;
241  }, MakeSimpleGuard( Event_Skip ) );
242  }
bool FilterKeyEvent(AudacityProject *project, const wxKeyEvent &evt, bool permit=false)
CommandManager * GetCommandManager()
Definition: Project.h:331
SimpleGuard< R > MakeSimpleGuard(R value)
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:161
CommandManager implements a system for organizing all user-callable commands.
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:302
bool HandleCapture(wxWindow *target, const wxKeyEvent &event)
static wxWindow * GetKeyboardCaptureHandler()
Definition: Project.cpp:5752
wxString CommandManagerEventMonitor::GetUnicodeString ( const wxKeyEvent &  event)
inlineprivate

Definition at line 317 of file CommandManager.cpp.

Referenced by HandleCapture().

318  {
319  wxString chars;
320 
321 #if defined(__WXMSW__)
322 
323  BYTE ks[256];
324  GetKeyboardState(ks);
325  WCHAR ucode[256];
326  int res = ToUnicode(event.GetRawKeyCode(), 0, ks, ucode, 256, 0);
327  if (res >= 1)
328  {
329  chars.Append(ucode, res);
330  }
331 
332 #elif defined(__WXGTK__)
333 
334  chars.Append((wxChar) gdk_keyval_to_unicode(event.GetRawKeyCode()));
335 
336 #elif defined(__WXMAC__)
337 
338  if (!mEvent) {
339  // TODO: we got here without getting the NSEvent pointer,
340  // as in the combo box case of bug 1252. We can't compute it!
341  // This makes a difference only when there is a capture handler.
342  // It's never the case yet that there is one.
343  wxASSERT(false);
344  return chars;
345  }
346 
347  NSString *c = [mEvent charactersIgnoringModifiers];
348  if ([c length] == 1)
349  {
350  unichar codepoint = [c characterAtIndex:0];
351  if ((codepoint >= 0xF700 && codepoint <= 0xF8FF) || codepoint == 0x7F)
352  {
353  return chars;
354  }
355  }
356 
357  c = [mEvent characters];
358  chars = [c UTF8String];
359 
360  TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
361  CFDataRef uchr = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
362  CFRelease(currentKeyboard);
363  if (uchr == NULL)
364  {
365  return chars;
366  }
367 
368  const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*)CFDataGetBytePtr(uchr);
369  if (keyboardLayout == NULL)
370  {
371  return chars;
372  }
373 
374  const UniCharCount maxStringLength = 255;
375  UniCharCount actualStringLength = 0;
376  UniChar unicodeString[maxStringLength];
377  UInt32 nsflags = [mEvent modifierFlags];
378  UInt16 modifiers = (nsflags & NSAlphaShiftKeyMask ? alphaLock : 0) |
379  (nsflags & NSShiftKeyMask ? shiftKey : 0) |
380  (nsflags & NSControlKeyMask ? controlKey : 0) |
381  (nsflags & NSAlternateKeyMask ? optionKey : 0) |
382  (nsflags & NSCommandKeyMask ? cmdKey : 0);
383 
384  OSStatus status = UCKeyTranslate(keyboardLayout,
385  [mEvent keyCode],
386  kUCKeyActionDown,
387  (modifiers >> 8) & 0xff,
388  LMGetKbdType(),
389  0,
390  &mDeadKeyState,
391  maxStringLength,
392  &actualStringLength,
393  unicodeString);
394 
395  if (status != noErr)
396  {
397  return chars;
398  }
399 
400  chars = [[NSString stringWithCharacters:unicodeString
401  length:(NSInteger)actualStringLength] UTF8String];
402 
403 #endif
404 
405  return chars;
406  }
bool CommandManagerEventMonitor::HandleCapture ( wxWindow *  target,
const wxKeyEvent &  event 
)
inlineprivate

Definition at line 247 of file CommandManager.cpp.

References GetUnicodeString().

Referenced by FilterEvent().

248  {
249  if (wxGetTopLevelParent(target) != wxGetTopLevelParent(wxWindow::FindFocus()))
250  {
251  return false;
252  }
253  wxEvtHandler *handler = target->GetEventHandler();
254 
255  // We make a copy of the event because the capture handler may modify it.
256  wxKeyEvent temp = event;
257 
258 #if defined(__WXGTK__)
259  // wxGTK uses the control and alt modifiers to represent ALTGR,
260  // so remove it as it might confuse the capture handlers.
261  if (temp.GetModifiers() == (wxMOD_CONTROL | wxMOD_ALT))
262  {
263  temp.SetControlDown(false);
264  temp.SetAltDown(false);
265  }
266 #endif
267 
268  // Ask the capture handler if the key down/up event is something they it
269  // might be interested in handling.
270  wxCommandEvent e(EVT_CAPTURE_KEY);
271  e.SetEventObject(&temp);
272  e.StopPropagation();
273  if (!handler->ProcessEvent(e))
274  {
275  return false;
276  }
277 
278  // Now, let the handler process the normal key event.
279  bool keyDown = temp.GetEventType() == wxEVT_KEY_DOWN;
280  temp.WasProcessed();
281  temp.StopPropagation();
282  wxEventProcessInHandlerOnly onlyDown(temp, handler);
283  bool processed = handler->ProcessEvent(temp);
284 
285  // Don't go any further if the capture handler didn't process
286  // the key down event.
287  if (!processed && keyDown)
288  {
289  return false;
290  }
291 
292  // At this point the capture handler has either processed a key down event
293  // or we're dealing with a key up event.
294  //
295  // So, only generate the char events for key down events.
296  if (keyDown)
297  {
298  wxString chars = GetUnicodeString(temp);
299  for (size_t i = 0, cnt = chars.Length(); i < cnt; i++)
300  {
301  temp = event;
302  temp.SetEventType(wxEVT_CHAR);
303  temp.WasProcessed();
304  temp.StopPropagation();
305  temp.m_uniChar = chars[i];
306  wxEventProcessInHandlerOnly onlyChar(temp, handler);
307  handler->ProcessEvent(temp);
308  }
309  }
310 
311  // We get here for processed key down events or for key up events, whether
312  // processed or not.
313  return true;
314  }
wxString GetUnicodeString(const wxKeyEvent &event)

The documentation for this class was generated from the following file: