Add support to transport key modifiers from she events to UI messages

It’s better if we use the original key modifiers from she::Events (given
by Cocoa or Win32 APIs) instead of asking for the current state of
the modifier when the ui::Message is created (which can be different
from the original value).

This commit adds support to transport the modifiers, but it is not
using the original key modifiers yet.
This commit is contained in:
David Capello 2015-10-14 16:42:49 -03:00
parent ba194a817f
commit bd1a1ffafb
17 changed files with 150 additions and 85 deletions

View File

@ -115,6 +115,7 @@ protected:
MouseMessage mouseMsg(
(msg->type() == kKeyDownMessage ? kMouseDownMessage: kMouseUpMessage),
(lmb->isPressed(msg) ? kButtonLeft: kButtonRight),
msg->modifiers(),
ui::get_mouse_position());
sendMessage(&mouseMsg);

View File

@ -94,7 +94,7 @@ void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg)
pointer = pointer_from_msg(editor, msg);
}
m_toolLoopManager->prepareLoop(pointer, msg->keyModifiers());
m_toolLoopManager->prepareLoop(pointer, msg->modifiers());
m_toolLoopManager->pressButton(pointer);
// This first movement is done when the user pressed Shift+click in

View File

@ -198,7 +198,7 @@ bool Key::isPressed(Message* msg) const
ASSERT(dynamic_cast<KeyMessage*>(msg) != NULL);
for (const Accelerator& accel : accels()) {
if (accel.isPressed(msg->keyModifiers(),
if (accel.isPressed(msg->modifiers(),
static_cast<KeyMessage*>(msg)->scancode(),
static_cast<KeyMessage*>(msg)->unicodeChar()) &&
(m_keycontext == KeyContext::Any ||

View File

@ -42,7 +42,7 @@ protected:
case kKeyDownMessage:
if (hasFocus() && !isReadOnly()) {
KeyMessage* keymsg = static_cast<KeyMessage*>(msg);
KeyModifiers modifiers = keymsg->keyModifiers();
KeyModifiers modifiers = keymsg->modifiers();
if (keymsg->scancode() == kKeySpace)
modifiers = (KeyModifiers)(modifiers & ~kKeySpaceModifier);

View File

@ -222,6 +222,7 @@ bool ToolBar::onProcessMessage(Message* msg)
MouseMessage* mouseMsg2 = new MouseMessage(
kMouseDownMessage,
mouseMsg->buttons(),
mouseMsg->modifiers(),
mouseMsg->position());
mouseMsg2->addRecipient(strip);
getManager()->enqueueMessage(mouseMsg2);
@ -640,6 +641,7 @@ bool ToolBar::ToolStrip::onProcessMessage(Message* msg)
MouseMessage* mouseMsg2 = new MouseMessage(
kMouseDownMessage,
mouseMsg->buttons(),
mouseMsg->modifiers(),
mouseMsg->position());
mouseMsg2->addRecipient(bar);
getManager()->enqueueMessage(mouseMsg2);

View File

@ -49,6 +49,7 @@ namespace she {
Event() : m_type(None),
m_display(nullptr),
m_scancode(kKeyNil),
m_modifiers(kKeyUninitializedModifier),
m_unicodeChar(0),
m_repeat(0),
m_preciseWheel(false),
@ -59,6 +60,7 @@ namespace she {
Display* display() const { return m_display; }
const Files& files() const { return m_files; }
KeyScancode scancode() const { return m_scancode; }
KeyModifiers modifiers() const { return m_modifiers; }
int unicodeChar() const { return m_unicodeChar; }
int repeat() const { return m_repeat; }
gfx::Point position() const { return m_position; }
@ -71,6 +73,7 @@ namespace she {
void setFiles(const Files& files) { m_files = files; }
void setScancode(KeyScancode scancode) { m_scancode = scancode; }
void setModifiers(KeyModifiers modifiers) { m_modifiers = modifiers; }
void setUnicodeChar(int unicodeChar) { m_unicodeChar = unicodeChar; }
void setRepeat(int repeat) { m_repeat = repeat; }
void setPosition(const gfx::Point& pos) { m_position = pos; }
@ -83,6 +86,7 @@ namespace she {
Display* m_display;
Files m_files;
KeyScancode m_scancode;
KeyModifiers m_modifiers;
int m_unicodeChar;
int m_repeat; // repeat=0 means the first time the key is pressed
gfx::Point m_position;

View File

@ -1,5 +1,5 @@
// SHE library
// Copyright (C) 2012-2013 David Capello
// Copyright (C) 2012-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -11,12 +11,13 @@
namespace she {
enum KeyModifiers {
kKeyNoneModifier = 0,
kKeyShiftModifier = 1,
kKeyCtrlModifier = 2,
kKeyAltModifier = 4,
kKeyCmdModifier = 8,
kKeySpaceModifier = 16
kKeyNoneModifier = 0,
kKeyShiftModifier = 1,
kKeyCtrlModifier = 2,
kKeyAltModifier = 4,
kKeyCmdModifier = 8,
kKeySpaceModifier = 16,
kKeyUninitializedModifier = 32,
};
enum KeyScancode {
@ -154,6 +155,8 @@ namespace she {
kKeyScancodes = 127
};
// Deprecated API, use modifiers in she::Event
// TODO mark these functions as deprecated
bool is_key_pressed(KeyScancode scancode);
void clear_keyboard_buffer();

View File

@ -486,7 +486,9 @@ bool ComboBoxEntry::onProcessMessage(Message* msg)
releaseMouse();
MouseMessage mouseMsg2(kMouseDownMessage,
mouseMsg->buttons(), mouseMsg->position());
mouseMsg->buttons(),
mouseMsg->modifiers(),
mouseMsg->position());
pick->sendMessage(&mouseMsg2);
return true;
}

View File

@ -295,7 +295,7 @@ bool Entry::onProcessMessage(Message* msg)
else if (keymsg->unicodeChar() >= 32) {
// Ctrl and Alt must be unpressed to insert a character
// in the text-field.
if ((msg->keyModifiers() & (kKeyCtrlModifier | kKeyAltModifier)) == 0) {
if ((msg->modifiers() & (kKeyCtrlModifier | kKeyAltModifier)) == 0) {
cmd = EntryCmd::InsertChar;
}
}

View File

@ -90,8 +90,9 @@ bool IntEntry::onProcessMessage(Message* msg)
releaseMouse();
MouseMessage mouseMsg2(kMouseDownMessage,
mouseMsg->buttons(),
mouseMsg->position());
mouseMsg->buttons(),
mouseMsg->modifiers(),
mouseMsg->position());
m_slider.sendMessage(&mouseMsg2);
}
}

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2014 David Capello
// Copyright (C) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -21,6 +21,7 @@ namespace ui {
using she::kKeyAltModifier;
using she::kKeyCmdModifier;
using she::kKeySpaceModifier;
using she::kKeyUninitializedModifier;
using she::kKeyNil;
using she::kKeyA;

View File

@ -248,12 +248,16 @@ bool Manager::generateMessages()
return false;
}
void Manager::generateSetCursorMessage(const gfx::Point& mousePos)
void Manager::generateSetCursorMessage(const gfx::Point& mousePos,
KeyModifiers modifiers)
{
Widget* dst = (capture_widget ? capture_widget: mouse_widget);
if (dst)
enqueueMessage(newMouseMessage(kSetCursorMessage, dst,
mousePos, _internal_get_mouse_buttons()));
enqueueMessage(
newMouseMessage(
kSetCursorMessage, dst,
mousePos, _internal_get_mouse_buttons(),
modifiers));
else
set_mouse_cursor(kArrowCursor);
}
@ -308,10 +312,11 @@ void Manager::generateMessagesFromSheEvents()
case she::Event::KeyDown:
case she::Event::KeyUp: {
Message* msg = new KeyMessage(
sheEvent.type() == she::Event::KeyDown ?
kKeyDownMessage:
kKeyUpMessage,
(sheEvent.type() == she::Event::KeyDown ?
kKeyDownMessage:
kKeyUpMessage),
sheEvent.scancode(),
sheEvent.modifiers(),
sheEvent.unicodeChar(),
sheEvent.repeat());
broadcastKeyMsg(msg);
@ -347,7 +352,8 @@ void Manager::generateMessagesFromSheEvents()
m_mouseButtons = (MouseButtons)((int)m_mouseButtons | (int)pressedButton);
_internal_set_mouse_buttons(m_mouseButtons);
handleMouseDown(sheEvent.position(), pressedButton);
handleMouseDown(sheEvent.position(), pressedButton,
sheEvent.modifiers());
break;
}
@ -356,19 +362,23 @@ void Manager::generateMessagesFromSheEvents()
m_mouseButtons = (MouseButtons)((int)m_mouseButtons & ~(int)releasedButton);
_internal_set_mouse_buttons(m_mouseButtons);
handleMouseUp(sheEvent.position(), releasedButton);
handleMouseUp(sheEvent.position(), releasedButton,
sheEvent.modifiers());
break;
}
case she::Event::MouseDoubleClick: {
MouseButtons clickedButton = mouse_buttons_from_she_to_ui(sheEvent);
handleMouseDoubleClick(sheEvent.position(), clickedButton);
handleMouseDoubleClick(sheEvent.position(), clickedButton,
sheEvent.modifiers());
break;
}
case she::Event::MouseWheel: {
handleMouseWheel(sheEvent.position(), m_mouseButtons,
sheEvent.wheelDelta(), sheEvent.preciseWheel());
sheEvent.modifiers(),
sheEvent.wheelDelta(),
sheEvent.preciseWheel());
break;
}
}
@ -377,11 +387,14 @@ void Manager::generateMessagesFromSheEvents()
if (lastMouseMoveEvent.type() != she::Event::None) {
_internal_set_mouse_position(lastMouseMoveEvent.position());
handleMouseMove(lastMouseMoveEvent.position(), m_mouseButtons);
handleMouseMove(lastMouseMoveEvent.position(), m_mouseButtons,
lastMouseMoveEvent.modifiers());
}
}
void Manager::handleMouseMove(const gfx::Point& mousePos, MouseButtons mouseButtons)
void Manager::handleMouseMove(const gfx::Point& mousePos,
MouseButtons mouseButtons,
KeyModifiers modifiers)
{
// Get the list of widgets to send mouse messages.
mouse_widgets_list.clear();
@ -405,43 +418,60 @@ void Manager::handleMouseMove(const gfx::Point& mousePos, MouseButtons mouseButt
// Send the mouse movement message
Widget* dst = (capture_widget ? capture_widget: mouse_widget);
enqueueMessage(newMouseMessage(kMouseMoveMessage, dst, mousePos, mouseButtons));
enqueueMessage(
newMouseMessage(
kMouseMoveMessage, dst,
mousePos, mouseButtons, modifiers));
generateSetCursorMessage(mousePos);
generateSetCursorMessage(mousePos, modifiers);
}
void Manager::handleMouseDown(const gfx::Point& mousePos, MouseButtons mouseButtons)
void Manager::handleMouseDown(const gfx::Point& mousePos,
MouseButtons mouseButtons,
KeyModifiers modifiers)
{
handleWindowZOrder();
enqueueMessage(newMouseMessage(kMouseDownMessage,
enqueueMessage(
newMouseMessage(
kMouseDownMessage,
(capture_widget ? capture_widget: mouse_widget),
mousePos, mouseButtons));
mousePos, mouseButtons, modifiers));
}
void Manager::handleMouseUp(const gfx::Point& mousePos, MouseButtons mouseButtons)
void Manager::handleMouseUp(const gfx::Point& mousePos,
MouseButtons mouseButtons,
KeyModifiers modifiers)
{
enqueueMessage(newMouseMessage(kMouseUpMessage,
enqueueMessage(
newMouseMessage(
kMouseUpMessage,
(capture_widget ? capture_widget: mouse_widget),
mousePos, mouseButtons));
mousePos, mouseButtons, modifiers));
}
void Manager::handleMouseDoubleClick(const gfx::Point& mousePos, MouseButtons mouseButtons)
void Manager::handleMouseDoubleClick(const gfx::Point& mousePos,
MouseButtons mouseButtons,
KeyModifiers modifiers)
{
Widget* dst = (capture_widget ? capture_widget: mouse_widget);
if (dst) {
enqueueMessage(newMouseMessage(kDoubleClickMessage,
dst, mousePos, mouseButtons));
enqueueMessage(
newMouseMessage(
kDoubleClickMessage,
dst, mousePos, mouseButtons, modifiers));
}
}
void Manager::handleMouseWheel(const gfx::Point& mousePos, MouseButtons mouseButtons,
void Manager::handleMouseWheel(const gfx::Point& mousePos,
MouseButtons mouseButtons, KeyModifiers modifiers,
const gfx::Point& wheelDelta, bool preciseWheel)
{
enqueueMessage(newMouseMessage(
kMouseWheelMessage,
(capture_widget ? capture_widget: mouse_widget),
mousePos, mouseButtons, wheelDelta, preciseWheel));
mousePos, mouseButtons, modifiers,
wheelDelta, preciseWheel));
}
// Handles Z order: Send the window to top (only when you click in a
@ -713,8 +743,10 @@ void Manager::setMouse(Widget* widget)
else
it = widget_parents.begin();
Message* msg = newMouseMessage(kMouseEnterMessage, NULL,
get_mouse_position(), _internal_get_mouse_buttons());
Message* msg = newMouseMessage(
kMouseEnterMessage, NULL,
get_mouse_position(), _internal_get_mouse_buttons(),
kKeyUninitializedModifier);
for (; it != widget_parents.end(); ++it) {
(*it)->enableFlags(HAS_MOUSE);
@ -722,7 +754,8 @@ void Manager::setMouse(Widget* widget)
}
enqueueMessage(msg);
generateSetCursorMessage(get_mouse_position());
generateSetCursorMessage(get_mouse_position(),
kKeyUninitializedModifier);
}
}
}
@ -1341,11 +1374,12 @@ Widget* Manager::findMagneticWidget(Widget* widget)
Message* Manager::newMouseMessage(
MessageType type,
Widget* widget, const gfx::Point& mousePos,
MouseButtons buttons,
MouseButtons buttons, KeyModifiers modifiers,
const gfx::Point& wheelDelta, bool preciseWheel)
{
Message* msg = new MouseMessage(type, buttons, mousePos,
wheelDelta, preciseWheel);
Message* msg = new MouseMessage(
type, buttons, modifiers, mousePos,
wheelDelta, preciseWheel);
if (widget != NULL)
msg->addRecipient(widget);
@ -1419,7 +1453,7 @@ static bool move_focus(Manager* manager, Message* msg)
case kKeyTab:
// Reverse tab
if ((msg->keyModifiers() & (kKeyShiftModifier | kKeyCtrlModifier | kKeyAltModifier)) != 0) {
if ((msg->modifiers() & (kKeyShiftModifier | kKeyCtrlModifier | kKeyAltModifier)) != 0) {
focus = list[count-1];
}
// Normal tab

View File

@ -9,6 +9,7 @@
#pragma once
#include "gfx/region.h"
#include "ui/keys.h"
#include "ui/message_type.h"
#include "ui/mouse_buttons.h"
#include "ui/widget.h"
@ -100,13 +101,13 @@ namespace ui {
virtual void onNewDisplayConfiguration();
private:
void generateSetCursorMessage(const gfx::Point& mousePos);
void generateSetCursorMessage(const gfx::Point& mousePos, KeyModifiers modifiers);
void generateMessagesFromSheEvents();
void handleMouseMove(const gfx::Point& mousePos, MouseButtons mouseButtons);
void handleMouseDown(const gfx::Point& mousePos, MouseButtons mouseButtons);
void handleMouseUp(const gfx::Point& mousePos, MouseButtons mouseButtons);
void handleMouseDoubleClick(const gfx::Point& mousePos, MouseButtons mouseButtons);
void handleMouseWheel(const gfx::Point& mousePos, MouseButtons mouseButtons,
void handleMouseMove(const gfx::Point& mousePos, MouseButtons mouseButtons, KeyModifiers modifiers);
void handleMouseDown(const gfx::Point& mousePos, MouseButtons mouseButtons, KeyModifiers modifiers);
void handleMouseUp(const gfx::Point& mousePos, MouseButtons mouseButtons, KeyModifiers modifiers);
void handleMouseDoubleClick(const gfx::Point& mousePos, MouseButtons mouseButtons, KeyModifiers modifiers);
void handleMouseWheel(const gfx::Point& mousePos, MouseButtons mouseButtons, KeyModifiers modifiers,
const gfx::Point& wheelDelta, bool preciseWheel);
void handleWindowZOrder();
@ -117,7 +118,8 @@ namespace ui {
static Message* newMouseMessage(
MessageType type,
Widget* widget, const gfx::Point& mousePos,
MouseButtons buttons, const gfx::Point& wheelDelta = gfx::Point(0, 0),
MouseButtons buttons, KeyModifiers modifiers,
const gfx::Point& wheelDelta = gfx::Point(0, 0),
bool preciseWheel = false);
void broadcastKeyMsg(Message* msg);

View File

@ -482,9 +482,10 @@ bool MenuBox::onProcessMessage(Message* msg)
get_base(this)->was_clicked = false;
// Check for ALT+some underlined letter
if (((this->type() == kMenuBoxWidget) && (msg->keyModifiers() == kKeyNoneModifier || // <-- Inside menu-boxes we can use letters without Alt modifier pressed
msg->keyModifiers() == kKeyAltModifier)) ||
((this->type() == kMenuBarWidget) && (msg->keyModifiers() == kKeyAltModifier))) {
if (((this->type() == kMenuBoxWidget) && (msg->modifiers() == kKeyNoneModifier || // <-- Inside menu-boxes we can use letters without Alt modifier pressed
msg->modifiers() == kKeyAltModifier)) ||
((this->type() == kMenuBarWidget) && (msg->modifiers() == kKeyAltModifier))) {
// TODO use scancode instead of unicodeChar
selected = check_for_letter(menu,
static_cast<KeyMessage*>(msg)->unicodeChar());

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2001-2013 David Capello
// Copyright (C) 2001-2013, 2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
@ -18,16 +18,23 @@
namespace ui {
Message::Message(MessageType type)
Message::Message(MessageType type, KeyModifiers modifiers)
: m_type(type)
, m_used(false)
, m_modifiers((KeyModifiers)
((she::is_key_pressed(kKeyLShift) || she::is_key_pressed(kKeyRShift) ? kKeyShiftModifier: 0) |
(she::is_key_pressed(kKeyLControl) || she::is_key_pressed(kKeyRControl) ? kKeyCtrlModifier: 0) |
(she::is_key_pressed(kKeyAlt) ? kKeyAltModifier: 0) |
(she::is_key_pressed(kKeyCommand) ? kKeyCmdModifier: 0) |
(she::is_key_pressed(kKeySpace) ? kKeySpaceModifier: 0)))
{
if (modifiers == kKeyUninitializedModifier) {
// Get modifiers from the deprecated API
// TODO remove this
m_modifiers = (KeyModifiers)
((she::is_key_pressed(kKeyLShift) || she::is_key_pressed(kKeyRShift) ? kKeyShiftModifier: 0) |
(she::is_key_pressed(kKeyLControl) || she::is_key_pressed(kKeyRControl) ? kKeyCtrlModifier: 0) |
(she::is_key_pressed(kKeyAlt) ? kKeyAltModifier: 0) |
(she::is_key_pressed(kKeyCommand) ? kKeyCmdModifier: 0) |
(she::is_key_pressed(kKeySpace) ? kKeySpaceModifier: 0));
}
else {
m_modifiers = modifiers;
}
}
Message::~Message()
@ -68,8 +75,11 @@ void Message::broadcastToChildren(Widget* widget)
addRecipient(widget);
}
KeyMessage::KeyMessage(MessageType type, KeyScancode scancode, int unicodeChar, int repeat)
: Message(type)
KeyMessage::KeyMessage(MessageType type,
KeyScancode scancode,
KeyModifiers modifiers,
int unicodeChar, int repeat)
: Message(type, modifiers)
, m_scancode(scancode)
, m_unicodeChar(unicodeChar)
, m_repeat(repeat)

View File

@ -28,7 +28,8 @@ namespace ui {
public:
typedef WidgetsList::iterator& recipients_iterator;
Message(MessageType type);
Message(MessageType type,
KeyModifiers modifiers = kKeyUninitializedModifier);
virtual ~Message();
MessageType type() const { return m_type; }
@ -36,7 +37,7 @@ namespace ui {
bool hasRecipients() const { return !m_recipients.empty(); }
bool isUsed() const { return m_used; }
void markAsUsed() { m_used = true; }
KeyModifiers keyModifiers() const { return m_modifiers; }
KeyModifiers modifiers() const { return m_modifiers; }
bool shiftPressed() const { return (m_modifiers & kKeyShiftModifier) == kKeyShiftModifier; }
bool ctrlPressed() const { return (m_modifiers & kKeyCtrlModifier) == kKeyCtrlModifier; }
bool altPressed() const { return (m_modifiers & kKeyAltModifier) == kKeyAltModifier; }
@ -59,10 +60,13 @@ namespace ui {
KeyModifiers m_modifiers; // Key modifiers pressed when message was created
};
class KeyMessage : public Message
{
class KeyMessage : public Message {
public:
KeyMessage(MessageType type, KeyScancode scancode, int unicodeChar, int repeat);
KeyMessage(MessageType type,
KeyScancode scancode,
KeyModifiers modifiers,
int unicodeChar,
int repeat);
KeyScancode scancode() const { return m_scancode; }
int unicodeChar() const { return m_unicodeChar; }
@ -80,8 +84,7 @@ namespace ui {
bool m_propagate_to_parent : 1;
};
class PaintMessage : public Message
{
class PaintMessage : public Message {
public:
PaintMessage(int count, const gfx::Rect& rect)
: Message(kPaintMessage), m_count(count), m_rect(rect) {
@ -95,14 +98,15 @@ namespace ui {
gfx::Rect m_rect; // Area to draw
};
class MouseMessage : public Message
{
class MouseMessage : public Message {
public:
MouseMessage(MessageType type, MouseButtons buttons,
MouseMessage(MessageType type,
MouseButtons buttons,
KeyModifiers modifiers,
const gfx::Point& pos,
const gfx::Point& wheelDelta = gfx::Point(0, 0),
bool preciseWheel = false)
: Message(type),
: Message(type, modifiers),
m_buttons(buttons),
m_pos(pos),
m_wheelDelta(wheelDelta),
@ -125,8 +129,7 @@ namespace ui {
bool m_preciseWheel;
};
class TimerMessage : public Message
{
class TimerMessage : public Message {
public:
TimerMessage(int count, Timer* timer)
: Message(kTimerMessage), m_count(count), m_timer(timer) {
@ -140,8 +143,7 @@ namespace ui {
Timer* m_timer; // Timer handle
};
class DropFilesMessage : public Message
{
class DropFilesMessage : public Message {
public:
typedef std::vector<std::string> Files;

View File

@ -1256,6 +1256,7 @@ void Widget::offerCapture(ui::MouseMessage* mouseMsg, int widget_type)
MouseMessage* mouseMsg2 = new MouseMessage(
kMouseDownMessage,
mouseMsg->buttons(),
mouseMsg->modifiers(),
mouseMsg->position());
mouseMsg2->addRecipient(pick);
getManager()->enqueueMessage(mouseMsg2);
@ -1338,9 +1339,10 @@ bool Widget::onProcessMessage(Message* msg)
if (kMouseDownMessage) {
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
MouseMessage mouseMsg2(kMouseDownMessage,
mouseMsg->buttons(),
mouseMsg->position(),
mouseMsg->wheelDelta());
mouseMsg->buttons(),
mouseMsg->modifiers(),
mouseMsg->position(),
mouseMsg->wheelDelta());
sendMessage(&mouseMsg2);
}