Fix bug triggering global keyboard shortcuts when a combobox popup is open

When a combobox popup is open, it creates a new non-foreground top window
(which is sibling of the window where the combobox widget is). When the
popup receives a key press, and it doesn't use it, the key is passed to
its parent (a ui::Manager), and then the latter has to process it.

Before this commit, CustomizedGuiManager::onProcessMessage() was
filtering shortcuts for foreground window, but it was working only
when the key was pressed in the foreground window itself (not when a
combination of foreground and background windows were open). Now the
filter is done in Manager::onProcessMessage() (which returns true,
i.e. key was used, for every pressed key when a foreground window
is found in its children hierarchy).
This commit is contained in:
David Capello 2015-05-04 11:25:42 -03:00
parent ac8387a408
commit 883629b563
4 changed files with 27 additions and 24 deletions

View File

@ -402,8 +402,6 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg)
break; break;
case kKeyDownMessage: { case kKeyDownMessage: {
Window* toplevel_window = getTopWindow();
#ifdef _DEBUG #ifdef _DEBUG
// Left Shift+Ctrl+Q generates a crash (useful to test the anticrash feature) // Left Shift+Ctrl+Q generates a crash (useful to test the anticrash feature)
if (msg->ctrlPressed() && if (msg->ctrlPressed() &&
@ -414,13 +412,11 @@ bool CustomizedGuiManager::onProcessMessage(Message* msg)
} }
#endif #endif
// If there is a foreground window as top level... // Call base impl to check if there is a foreground window as
if (toplevel_window && // top level that needs keys. (In this way we just do not
toplevel_window != App::instance()->getMainWindow() && // process keyboard shortcuts for menus and tools).
toplevel_window->isForeground()) { if (Manager::onProcessMessage(msg))
// We just do not process keyboard shortcuts for menus and tools return true;
break;
}
for (const Key* key : *KeyboardShortcuts::instance()) { for (const Key* key : *KeyboardShortcuts::instance()) {
if (key->isPressed(msg)) { if (key->isPressed(msg)) {

View File

@ -705,7 +705,11 @@ bool Timeline::onProcessMessage(Message* msg)
else { else {
m_state = STATE_STANDBY; m_state = STATE_STANDBY;
} }
used = true;
// Don't use this key, so it's caught by CancelCommand.
// TODO The deselection of the current range should be
// handled in CancelCommand itself.
//used = true;
break; break;
case kKeySpace: { case kKeySpace: {

View File

@ -920,24 +920,28 @@ bool Manager::onProcessMessage(Message* msg)
// Continue sending the message to the children of all windows // Continue sending the message to the children of all windows
// (until a desktop or foreground window). // (until a desktop or foreground window).
UI_FOREACH_WIDGET(getChildren(), it) { Window* win = nullptr;
Window* w = static_cast<Window*>(*it); for (Widget* manchild : getChildren()) {
win = static_cast<Window*>(manchild);
// Send to the window. // Send to the window.
UI_FOREACH_WIDGET(w->getChildren(), it2) for (auto winchild : win->getChildren())
if ((*it2)->sendMessage(msg)) if (winchild->sendMessage(msg))
return true; return true;
if (w->isForeground() || if (win->isForeground() ||
w->isDesktop()) win->isDesktop())
break; break;
} }
// Check the focus movement. // Check the focus movement for foreground (non-desktop) windows.
if (msg->type() == kKeyDownMessage) if (win->isForeground()) {
move_focus(this, msg); if (msg->type() == kKeyDownMessage)
move_focus(this, msg);
return true; return true;
}
else
return false;
} }
} }

View File

@ -241,12 +241,11 @@ void Window::openWindow()
void Window::openWindowInForeground() void Window::openWindowInForeground()
{ {
m_isForeground = true;
openWindow(); openWindow();
MessageLoop loop(getManager()); MessageLoop loop(getManager());
m_isForeground = true;
while (!(this->flags & JI_HIDDEN)) while (!(this->flags & JI_HIDDEN))
loop.pumpMessages(); loop.pumpMessages();