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 131 of file CommandManager.cpp.

Constructor & Destructor Documentation

CommandManagerEventMonitor::CommandManagerEventMonitor ( )
inline

Definition at line 134 of file CommandManager.cpp.

References FilterEvent().

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

Definition at line 193 of file CommandManager.cpp.

194  {
195 #if defined(__WXMAC__)
196  [NSEvent removeMonitor:mHandler];
197 #else
198  wxEvtHandler::RemoveFilter(this);
199 #endif
200  }

Member Function Documentation

int CommandManagerEventMonitor::FilterEvent ( wxEvent &  event)
inlineoverride

Definition at line 202 of file CommandManager.cpp.

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

Referenced by CommandManagerEventMonitor().

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

Definition at line 324 of file CommandManager.cpp.

Referenced by HandleCapture().

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

Definition at line 254 of file CommandManager.cpp.

References GetUnicodeString().

Referenced by FilterEvent().

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

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