From 123f02f0fb0aef83a705bd6e518668ffe637ebca Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Fri, 27 Apr 2012 19:07:49 +0000 Subject: [PATCH] Process hotkeys in wxEVT_CHAR_HOOK rather than wxEVT_KEY_DOWN Char hook events propagate by default, removing the need for the event filter to make key down events propagate, which was causing some funny issues. On Windows, the char hook handler runs before menu accelerators, fixing a bug where Default context hotkeys would override more specific ones when they appeared on a menu. Unfortunately, this is not the case on GTK, so the dumb accelerator-disabling hack is still required. Originally committed to SVN as r6724. --- aegisub/src/audio_display.cpp | 2 +- aegisub/src/base_grid.cpp | 97 ++++++++++++++---------- aegisub/src/base_grid.h | 1 + aegisub/src/dialog_detached_video.cpp | 2 +- aegisub/src/dialog_styling_assistant.cpp | 23 +++--- aegisub/src/dialog_styling_assistant.h | 1 + aegisub/src/dialog_translation.cpp | 2 +- aegisub/src/frame_main.cpp | 2 +- aegisub/src/hotkey.cpp | 1 - aegisub/src/main.cpp | 6 -- aegisub/src/main.h | 4 - aegisub/src/subs_edit_box.cpp | 4 +- aegisub/src/video_display.cpp | 2 +- aegisub/src/video_slider.cpp | 8 +- aegisub/src/video_slider.h | 1 + 15 files changed, 83 insertions(+), 73 deletions(-) diff --git a/aegisub/src/audio_display.cpp b/aegisub/src/audio_display.cpp index 51f0e1b5c..eca5b6830 100644 --- a/aegisub/src/audio_display.cpp +++ b/aegisub/src/audio_display.cpp @@ -781,7 +781,7 @@ BEGIN_EVENT_TABLE(AudioDisplay, wxWindow) EVT_SIZE(AudioDisplay::OnSize) EVT_SET_FOCUS(AudioDisplay::OnFocus) EVT_KILL_FOCUS(AudioDisplay::OnFocus) - EVT_KEY_DOWN(AudioDisplay::OnKeyDown) + EVT_CHAR_HOOK(AudioDisplay::OnKeyDown) END_EVENT_TABLE() diff --git a/aegisub/src/base_grid.cpp b/aegisub/src/base_grid.cpp index c664f6ba2..3808b779c 100644 --- a/aegisub/src/base_grid.cpp +++ b/aegisub/src/base_grid.cpp @@ -150,6 +150,7 @@ BEGIN_EVENT_TABLE(BaseGrid,wxWindow) EVT_COMMAND_SCROLL(GRID_SCROLLBAR,BaseGrid::OnScroll) EVT_MOUSE_EVENTS(BaseGrid::OnMouseEvent) EVT_KEY_DOWN(BaseGrid::OnKeyDown) + EVT_CHAR_HOOK(BaseGrid::OnCharHook) EVT_MENU_RANGE(MENU_SHOW_COL,MENU_SHOW_COL+15,BaseGrid::OnShowColMenu) END_EVENT_TABLE() @@ -972,10 +973,24 @@ bool BaseGrid::IsDisplayed(const AssDialogue *line) const { context->videoController->FrameAtTime(line->End,agi::vfr::END) >= frame; } -void BaseGrid::OnKeyDown(wxKeyEvent &event) { +void BaseGrid::OnCharHook(wxKeyEvent &event) { if (hotkey::check("Subtitle Grid", context, event)) return; + int key = event.GetKeyCode(); + + if (key == WXK_UP || key == WXK_DOWN || + key == WXK_PAGEUP || key == WXK_PAGEDOWN || + key == WXK_HOME || key == WXK_END) + { + event.Skip(); + return; + } + + hotkey::check("Audio", context, event); +} + +void BaseGrid::OnKeyDown(wxKeyEvent &event) { int w,h; GetClientSize(&w,&h); @@ -1005,48 +1020,46 @@ void BaseGrid::OnKeyDown(wxKeyEvent &event) { step = GetRows(); } - // Moving - if (dir) { - event.Skip(false); - - int old_extend = extendRow; - int next = mid(0, GetDialogueIndex(active_line) + dir * step, GetRows() - 1); - SetActiveLine(GetDialogue(next)); - - // Move selection - if (!ctrl && !shift && !alt) { - SelectRow(next); - return; - } - - // Move active only - if (alt && !shift && !ctrl) { - Refresh(false); - return; - } - - // Shift-selection - if (shift && !ctrl && !alt) { - extendRow = old_extend; - // Set range - int begin = next; - int end = extendRow; - if (end < begin) - std::swap(begin, end); - - // Select range - Selection newsel; - for (int i = begin; i <= end; i++) - newsel.insert(GetDialogue(i)); - - SetSelectedSet(newsel); - - MakeCellVisible(extendRow, 0, false); - return; - } + if (!dir) { + event.Skip(); + return; + } + + int old_extend = extendRow; + int next = mid(0, GetDialogueIndex(active_line) + dir * step, GetRows() - 1); + SetActiveLine(GetDialogue(next)); + + // Move selection + if (!ctrl && !shift && !alt) { + SelectRow(next); + return; + } + + // Move active only + if (alt && !shift && !ctrl) { + Refresh(false); + return; + } + + // Shift-selection + if (shift && !ctrl && !alt) { + extendRow = old_extend; + // Set range + int begin = next; + int end = extendRow; + if (end < begin) + std::swap(begin, end); + + // Select range + Selection newsel; + for (int i = begin; i <= end; i++) + newsel.insert(GetDialogue(i)); + + SetSelectedSet(newsel); + + MakeCellVisible(extendRow, 0, false); + return; } - else - hotkey::check("Audio", context, event); } void BaseGrid::SetByFrame(bool state) { diff --git a/aegisub/src/base_grid.h b/aegisub/src/base_grid.h index 64d8b34f1..3bbcbf3be 100644 --- a/aegisub/src/base_grid.h +++ b/aegisub/src/base_grid.h @@ -103,6 +103,7 @@ class BaseGrid : public wxWindow, public BaseSelectionController { void OnContextMenu(wxContextMenuEvent &evt); void OnHighlightVisibleChange(agi::OptionValue const& opt); void OnKeyDown(wxKeyEvent &event); + void OnCharHook(wxKeyEvent &event); void OnMouseEvent(wxMouseEvent &event); void OnPaint(wxPaintEvent &event); void OnScroll(wxScrollEvent &event); diff --git a/aegisub/src/dialog_detached_video.cpp b/aegisub/src/dialog_detached_video.cpp index 0fa4393d8..2f865bdd8 100644 --- a/aegisub/src/dialog_detached_video.cpp +++ b/aegisub/src/dialog_detached_video.cpp @@ -94,7 +94,7 @@ DialogDetachedVideo::DialogDetachedVideo(agi::Context *context) Bind(wxEVT_CLOSE_WINDOW, &DialogDetachedVideo::OnClose, this); Bind(wxEVT_ICONIZE, &DialogDetachedVideo::OnMinimize, this); - Bind(wxEVT_KEY_DOWN, &DialogDetachedVideo::OnKeyDown, this); + Bind(wxEVT_CHAR_HOOK, &DialogDetachedVideo::OnKeyDown, this); } DialogDetachedVideo::~DialogDetachedVideo() { } diff --git a/aegisub/src/dialog_styling_assistant.cpp b/aegisub/src/dialog_styling_assistant.cpp index 600a279f9..be2108d61 100644 --- a/aegisub/src/dialog_styling_assistant.cpp +++ b/aegisub/src/dialog_styling_assistant.cpp @@ -143,7 +143,8 @@ DialogStyling::DialogStyling(agi::Context *context) c->selectionController->AddSelectionListener(this); Bind(wxEVT_ACTIVATE, &DialogStyling::OnActivate, this); - Bind(wxEVT_KEY_DOWN, &DialogStyling::OnKeyDown, this); + Bind(wxEVT_CHAR_HOOK, &DialogStyling::OnCharHook, this); + style_name->Bind(wxEVT_CHAR_HOOK, &DialogStyling::OnCharHook, this); style_name->Bind(wxEVT_KEY_DOWN, &DialogStyling::OnKeyDown, this); play_video->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogStyling::OnPlayVideoButton, this); play_audio->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogStyling::OnPlayAudioButton, this); @@ -245,15 +246,17 @@ void DialogStyling::OnPlayAudioButton(wxCommandEvent &) { style_name->SetFocus(); } +void DialogStyling::OnCharHook(wxKeyEvent &evt) { + hotkey::check("Styling Assistant", c, evt); +} + void DialogStyling::OnKeyDown(wxKeyEvent &evt) { - if (!hotkey::check("Styling Assistant", c, evt)) { - // Move the beginning of the selection back one character so that backspace - // actually does something - if (evt.GetKeyCode() == WXK_BACK && !evt.GetModifiers()) { - long from, to; - style_name->GetSelection(&from, &to); - if (from > 0) - style_name->SetSelection(from - 1, to); - } + // Move the beginning of the selection back one character so that backspace + // actually does something + if (evt.GetKeyCode() == WXK_BACK && !evt.GetModifiers()) { + long from, to; + style_name->GetSelection(&from, &to); + if (from > 0) + style_name->SetSelection(from - 1, to); } } diff --git a/aegisub/src/dialog_styling_assistant.h b/aegisub/src/dialog_styling_assistant.h index 80aab795b..7d0187663 100644 --- a/aegisub/src/dialog_styling_assistant.h +++ b/aegisub/src/dialog_styling_assistant.h @@ -55,6 +55,7 @@ class DialogStyling : public wxDialog, public SelectionListener { void OnActivate(wxActivateEvent &evt); void OnKeyDown(wxKeyEvent &evt); + void OnCharHook(wxKeyEvent &evt); void OnListClicked(wxCommandEvent &evt); void OnListDoubleClicked(wxCommandEvent &evt); void OnPlayAudioButton(wxCommandEvent &evt); diff --git a/aegisub/src/dialog_translation.cpp b/aegisub/src/dialog_translation.cpp index fa7fba961..8ce038703 100644 --- a/aegisub/src/dialog_translation.cpp +++ b/aegisub/src/dialog_translation.cpp @@ -99,7 +99,7 @@ DialogTranslation::DialogTranslation(agi::Context *c) translated_text->SetWrapMode(wxSTC_WRAP_WORD); translated_text->SetMarginWidth(1, 0); translated_text->SetFocus(); - translated_text->Bind(wxEVT_KEY_DOWN, &DialogTranslation::OnKeyDown, this); + translated_text->Bind(wxEVT_CHAR_HOOK, &DialogTranslation::OnKeyDown, this); wxSizer *translated_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Translation")); translated_box->Add(translated_text, 1, wxEXPAND, 0); diff --git a/aegisub/src/frame_main.cpp b/aegisub/src/frame_main.cpp index c0cb09752..f163bce05 100644 --- a/aegisub/src/frame_main.cpp +++ b/aegisub/src/frame_main.cpp @@ -574,7 +574,7 @@ BEGIN_EVENT_TABLE(FrameMain, wxFrame) EVT_CLOSE(FrameMain::OnCloseWindow) - EVT_KEY_DOWN(FrameMain::OnKeyDown) + EVT_CHAR_HOOK(FrameMain::OnKeyDown) EVT_MOUSEWHEEL(FrameMain::OnMouseWheel) #ifdef __WXMAC__ diff --git a/aegisub/src/hotkey.cpp b/aegisub/src/hotkey.cpp index 24929ca32..f55115d59 100644 --- a/aegisub/src/hotkey.cpp +++ b/aegisub/src/hotkey.cpp @@ -134,7 +134,6 @@ bool check(std::string const& context, agi::Context *c, int key_code, wchar_t ke } bool check(std::string const& context, agi::Context *c, wxKeyEvent &evt) { - evt.StopPropagation(); if (!hotkey::check(context, c, evt.GetKeyCode(), evt.GetUnicodeKey(), evt.GetModifiers())) { evt.Skip(); return false; diff --git a/aegisub/src/main.cpp b/aegisub/src/main.cpp index ff4944fab..1718289ef 100644 --- a/aegisub/src/main.cpp +++ b/aegisub/src/main.cpp @@ -508,12 +508,6 @@ int AegisubApp::OnRun() { return 1; } -int AegisubApp::FilterEvent(wxEvent& event) { - if (event.GetEventType() == wxEVT_KEY_DOWN) - event.ResumePropagation(wxEVENT_PROPAGATE_MAX); - return -1 /* wxEventFilter::Event_Skip */; -} - //////////////// // Apple events #ifdef __WXMAC__ diff --git a/aegisub/src/main.h b/aegisub/src/main.h index 41bc75b92..c926eed41 100644 --- a/aegisub/src/main.h +++ b/aegisub/src/main.h @@ -112,10 +112,6 @@ class AegisubApp: public wxApp { // our ticket to catch exceptions happening in event handlers. void HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent& event) const; - /// Top-level event filter to enable propagation of key events, which we - /// need for our hotkeys to work correctly - int FilterEvent(wxEvent& event); - public: /// DOCME AegisubLocale locale; diff --git a/aegisub/src/subs_edit_box.cpp b/aegisub/src/subs_edit_box.cpp index 299a7b9d9..9f61178cb 100644 --- a/aegisub/src/subs_edit_box.cpp +++ b/aegisub/src/subs_edit_box.cpp @@ -206,8 +206,8 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context) // Text editor TextEdit = new SubsTextEditCtrl(this, wxSize(300,50), wxBORDER_SUNKEN, c); - TextEdit->Bind(wxEVT_KEY_DOWN, &SubsEditBox::OnKeyDown, this); - Bind(wxEVT_KEY_DOWN, &SubsEditBox::OnKeyDown, this); + TextEdit->Bind(wxEVT_CHAR_HOOK, &SubsEditBox::OnKeyDown, this); + Bind(wxEVT_CHAR_HOOK, &SubsEditBox::OnKeyDown, this); BottomSizer = new wxBoxSizer(wxHORIZONTAL); BottomSizer->Add(TextEdit,1,wxEXPAND,0); diff --git a/aegisub/src/video_display.cpp b/aegisub/src/video_display.cpp index 0f819974c..fcf8193bc 100644 --- a/aegisub/src/video_display.cpp +++ b/aegisub/src/video_display.cpp @@ -121,7 +121,7 @@ VideoDisplay::VideoDisplay( Bind(wxEVT_SIZE, &VideoDisplay::OnSizeEvent, this); Bind(wxEVT_CONTEXT_MENU, &VideoDisplay::OnContextMenu, this); Bind(wxEVT_ENTER_WINDOW, &VideoDisplay::OnMouseEvent, this); - Bind(wxEVT_KEY_DOWN, &VideoDisplay::OnKeyDown, this); + Bind(wxEVT_CHAR_HOOK, &VideoDisplay::OnKeyDown, this); Bind(wxEVT_LEAVE_WINDOW, &VideoDisplay::OnMouseLeave, this); Bind(wxEVT_LEFT_DCLICK, &VideoDisplay::OnMouseEvent, this); Bind(wxEVT_LEFT_DOWN, &VideoDisplay::OnMouseEvent, this); diff --git a/aegisub/src/video_slider.cpp b/aegisub/src/video_slider.cpp index 56c4b35c2..b46fe4289 100644 --- a/aegisub/src/video_slider.cpp +++ b/aegisub/src/video_slider.cpp @@ -106,6 +106,7 @@ int VideoSlider::GetXAtValue(int value) { BEGIN_EVENT_TABLE(VideoSlider, wxWindow) EVT_MOUSE_EVENTS(VideoSlider::OnMouse) EVT_KEY_DOWN(VideoSlider::OnKeyDown) + EVT_CHAR_HOOK(VideoSlider::OnCharHook) EVT_PAINT(VideoSlider::OnPaint) EVT_SET_FOCUS(VideoSlider::OnFocus) EVT_KILL_FOCUS(VideoSlider::OnFocus) @@ -148,10 +149,11 @@ void VideoSlider::OnMouse(wxMouseEvent &event) { } } -void VideoSlider::OnKeyDown(wxKeyEvent &event) { - if (hotkey::check("Video", c, event)) - return; +void VideoSlider::OnCharHook(wxKeyEvent &event) { + hotkey::check("Video", c, event); +} +void VideoSlider::OnKeyDown(wxKeyEvent &event) { // Forward up/down to grid as those aren't yet handled by commands if (event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_DOWN) { c->subsGrid->GetEventHandler()->ProcessEvent(event); diff --git a/aegisub/src/video_slider.h b/aegisub/src/video_slider.h index bf1e44d1f..581835e6d 100644 --- a/aegisub/src/video_slider.h +++ b/aegisub/src/video_slider.h @@ -70,6 +70,7 @@ class VideoSlider: public wxWindow { void OnMouse(wxMouseEvent &event); void OnKeyDown(wxKeyEvent &event); + void OnCharHook(wxKeyEvent &event); void OnPaint(wxPaintEvent &); void OnFocus(wxFocusEvent &);