Fix pressing multiple KeyAction modifiers at the same time (fix #778)

This commit is contained in:
David Capello 2015-08-25 13:29:19 -03:00
parent f71a0e2cc4
commit 0645a66521
11 changed files with 109 additions and 110 deletions

View File

@ -96,36 +96,8 @@ public:
->getCurrentQuicktool(currentTool);
}
bool isCopySelectionKeyPressed() override {
return isKeyActionPressed(KeyAction::CopySelection);
}
bool isSnapToGridKeyPressed() override {
return isKeyActionPressed(KeyAction::SnapToGrid);
}
bool isAngleSnapKeyPressed() override {
return isKeyActionPressed(KeyAction::AngleSnap);
}
bool isMaintainAspectRatioKeyPressed() override {
return isKeyActionPressed(KeyAction::MaintainAspectRatio);
}
bool isLockAxisKeyPressed() override {
return isKeyActionPressed(KeyAction::LockAxis);
}
bool isAddSelectionPressed() override {
return isKeyActionPressed(KeyAction::AddSelection);
}
bool isSubtractSelectionPressed() override {
return isKeyActionPressed(KeyAction::SubtractSelection);
}
bool isAutoSelectLayerPressed() override {
return isKeyActionPressed(KeyAction::AutoSelectLayer);
KeyAction getPressedKeyAction(KeyContext context) {
return KeyboardShortcuts::instance()->getCurrentActionModifiers(context);
}
protected:
@ -173,13 +145,6 @@ private:
App::instance()->getMainWindow()->getPreviewEditor()->updateUsingEditor(editor);
}
bool isKeyActionPressed(KeyAction action) {
if (Key* key = KeyboardShortcuts::instance()->action(action))
return key->isPressed();
else
return false;
}
};
class PreviewEditor : public Editor,

View File

@ -1068,11 +1068,9 @@ void Editor::updateQuicktool()
// Don't change quicktools if we are in a selection tool and using
// the selection modifiers.
if (current_tool->getInk(0)->isSelection()) {
if (m_customizationDelegate->isAddSelectionPressed() ||
m_customizationDelegate->isSubtractSelectionPressed())
return;
}
if (current_tool->getInk(0)->isSelection() &&
int(m_customizationDelegate->getPressedKeyAction(KeyContext::Selection)) != 0)
return;
tools::Tool* old_quicktool = m_quicktool;
tools::Tool* new_quicktool = m_customizationDelegate->getQuickTool(current_tool);
@ -1123,9 +1121,13 @@ void Editor::updateContextBarFromModifiers()
tools::SelectionMode mode = Preferences::instance().selection.mode();
if (m_customizationDelegate && m_customizationDelegate->isAddSelectionPressed())
KeyAction action = KeyAction::None;
if (m_customizationDelegate)
action = m_customizationDelegate->getPressedKeyAction(KeyContext::Selection);
if (int(action & KeyAction::AddSelection))
mode = tools::SelectionMode::ADD;
else if (m_customizationDelegate && m_customizationDelegate->isSubtractSelectionPressed())
if (int(action & KeyAction::SubtractSelection))
mode = tools::SelectionMode::SUBTRACT;
else if (m_secondaryButton)
mode = tools::SelectionMode::SUBTRACT;
@ -1139,7 +1141,8 @@ void Editor::updateContextBarFromModifiers()
bool autoSelectLayer = Preferences::instance().editor.autoSelectLayer();
if (m_customizationDelegate && m_customizationDelegate->isAutoSelectLayerPressed())
if ((m_customizationDelegate) &&
int(m_customizationDelegate->getPressedKeyAction(KeyContext::MoveTool) & KeyAction::AutoSelectLayer))
autoSelectLayer = true;
if (m_autoSelectLayer != autoSelectLayer) {

View File

@ -9,6 +9,8 @@
#define APP_UI_EDITOR_CUSTOMIZATION_DELEGATE_H_INCLUDED
#pragma once
#include "app/ui/keyboard_shortcuts.h"
namespace tools {
class Tool;
}
@ -26,31 +28,8 @@ namespace app {
// "currentTool" is the current tool selected in the toolbox.
virtual tools::Tool* getQuickTool(tools::Tool* currentTool) = 0;
// Returns true if the user wants to copy the selection instead of
// to move it.
virtual bool isCopySelectionKeyPressed() = 0;
// Returns true if the user wants to snap to grid when he's moving
// the selection.
virtual bool isSnapToGridKeyPressed() = 0;
// Returns true if the user wants to activate angle snap, so he can
// easily specify common angles (45, 90, 135, 180, etc.).
virtual bool isAngleSnapKeyPressed() = 0;
// Returns true if the user wants to maintain the aspect ratio when
// he is scaling the selection.
virtual bool isMaintainAspectRatioKeyPressed() = 0;
// Returns true if the user wants to lock the X or Y axis when he is
// dragging the selection.
virtual bool isLockAxisKeyPressed() = 0;
virtual bool isAddSelectionPressed() = 0;
virtual bool isSubtractSelectionPressed() = 0;
virtual bool isAutoSelectLayerPressed() = 0;
// Returns what action is pressed at this moment.
virtual KeyAction getPressedKeyAction(KeyContext context) = 0;
};
} // namespace app

View File

@ -129,7 +129,7 @@ bool MovingCelState::onMouseMove(Editor* editor, MouseMessage* msg)
gfx::Point newCursorPos = editor->screenToEditor(msg->position());
gfx::Point delta = newCursorPos - m_mouseStart;
if (editor->getCustomizationDelegate()->isLockAxisKeyPressed()) {
if (int(editor->getCustomizationDelegate()->getPressedKeyAction(KeyContext::MovingPixels) & KeyAction::LockAxis)) {
if (ABS(delta.x) < ABS(delta.y)) {
delta.x = 0;
}

View File

@ -263,7 +263,8 @@ bool MovingPixelsState::onMouseDown(Editor* editor, MouseMessage* msg)
msg->right())) {
// In case that the user is pressing the copy-selection keyboard shortcut.
EditorCustomizationDelegate* customization = editor->getCustomizationDelegate();
if (customization && customization->isCopySelectionKeyPressed()) {
if ((customization) &&
int(customization->getPressedKeyAction(KeyContext::MovingPixels) & KeyAction::CopySelection)) {
// Stamp the pixels to create the copy.
m_pixelsMovement->stampImage();
}
@ -315,17 +316,18 @@ bool MovingPixelsState::onMouseMove(Editor* editor, MouseMessage* msg)
// Get the customization for the pixels movement (snap to grid, angle snap, etc.).
PixelsMovement::MoveModifier moveModifier = PixelsMovement::NormalMovement;
KeyAction action = editor->getCustomizationDelegate()->getPressedKeyAction(KeyContext::MovingPixels);
if (editor->getCustomizationDelegate()->isSnapToGridKeyPressed())
if (int(action & KeyAction::SnapToGrid))
moveModifier |= PixelsMovement::SnapToGridMovement;
if (editor->getCustomizationDelegate()->isAngleSnapKeyPressed())
if (int(action & KeyAction::AngleSnap))
moveModifier |= PixelsMovement::AngleSnapMovement;
if (editor->getCustomizationDelegate()->isMaintainAspectRatioKeyPressed())
if (int(action & KeyAction::MaintainAspectRatio))
moveModifier |= PixelsMovement::MaintainAspectRatioMovement;
if (editor->getCustomizationDelegate()->isLockAxisKeyPressed())
if (int(action & KeyAction::LockAxis))
moveModifier |= PixelsMovement::LockAxisMovement;
// Invalidate handles

View File

@ -252,6 +252,17 @@ void PixelsMovement::moveImage(const gfx::Point& pos, MoveModifier moveModifier)
y2 += dy;
updateBounds = true;
if ((moveModifier & LockAxisMovement) == LockAxisMovement) {
if (ABS(dx) < ABS(dy)) {
x1 -= dx;
x2 -= dx;
}
else {
y1 -= dy;
y2 -= dy;
}
}
if ((moveModifier & SnapToGridMovement) == SnapToGridMovement) {
// Snap the x1,y1 point to the grid.
gfx::Rect gridBounds = App::instance()
@ -268,16 +279,6 @@ void PixelsMovement::moveImage(const gfx::Point& pos, MoveModifier moveModifier)
x2 += gridOffset.x;
y2 += gridOffset.y;
}
else if ((moveModifier & LockAxisMovement) == LockAxisMovement) {
if (ABS(dx) < ABS(dy)) {
x1 -= dx;
x2 -= dx;
}
else {
y1 -= dy;
y2 -= dy;
}
}
break;
case ScaleNWHandle:

View File

@ -315,8 +315,8 @@ bool StandbyState::onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos)
// Move pixels
if (editor->isInsideSelection()) {
EditorCustomizationDelegate* customization = editor->getCustomizationDelegate();
if (customization && customization->isCopySelectionKeyPressed())
if ((customization) &&
int(customization->getPressedKeyAction(KeyContext::MovingPixels) & KeyAction::CopySelection))
editor->showMouseCursor(kArrowPlusCursor);
else
editor->showMouseCursor(kMoveCursor);
@ -452,7 +452,8 @@ void StandbyState::transformSelection(Editor* editor, MouseMessage* msg, HandleT
"Transformation"));
// If the Ctrl key is pressed start dragging a copy of the selection
if (customization && customization->isCopySelectionKeyPressed())
if ((customization) &&
int(customization->getPressedKeyAction(KeyContext::MovingPixels) & KeyAction::CopySelection))
pixelsMovement->copyMask();
else
pixelsMovement->cutMask();

View File

@ -215,6 +215,15 @@ bool Key::isPressed() const
return false;
}
bool Key::isLooselyPressed() const
{
for (const Accelerator& accel : this->accels()) {
if (accel.isLooselyPressed())
return true;
}
return false;
}
bool Key::hasAccel(const ui::Accelerator& accel) const
{
return accels().has(accel);
@ -677,4 +686,19 @@ tools::Tool* KeyboardShortcuts::getCurrentQuicktool(tools::Tool* currentTool)
return NULL;
}
KeyAction KeyboardShortcuts::getCurrentActionModifiers(KeyContext context)
{
KeyAction flags = KeyAction::None;
for (Key* key : m_keys) {
if (key->type() == KeyType::Action &&
key->keycontext() == context &&
key->isLooselyPressed()) {
flags = static_cast<KeyAction>(int(flags) | int(key->action()));
}
}
return flags;
}
} // namespace app

View File

@ -50,20 +50,25 @@ namespace app {
Action,
};
// TODO This should be called "KeyActionModifier" or something similar
enum class KeyAction {
None,
CopySelection,
SnapToGrid,
AngleSnap,
MaintainAspectRatio,
LockAxis,
AddSelection,
SubtractSelection,
AutoSelectLayer,
LeftMouseButton,
RightMouseButton
None = 0x00000000,
CopySelection = 0x00000001,
SnapToGrid = 0x00000002,
AngleSnap = 0x00000004,
MaintainAspectRatio = 0x00000008,
LockAxis = 0x00000010,
AddSelection = 0x00000020,
SubtractSelection = 0x00000040,
AutoSelectLayer = 0x00000080,
LeftMouseButton = 0x00000100,
RightMouseButton = 0x00000200,
};
inline KeyAction operator&(KeyAction a, KeyAction b) {
return KeyAction(int(a) & int(b));
}
class Key {
public:
Key(Command* command, const Params& params, KeyContext keyContext);
@ -81,6 +86,7 @@ namespace app {
void add(const ui::Accelerator& accel, KeySource source);
bool isPressed(ui::Message* msg) const;
bool isPressed() const;
bool isLooselyPressed() const;
bool hasAccel(const ui::Accelerator& accel) const;
void disableAccel(const ui::Accelerator& accel);
@ -147,6 +153,7 @@ namespace app {
KeyContext getCurrentKeyContext();
bool getCommandFromKeyMessage(ui::Message* msg, Command** command, Params* params);
tools::Tool* getCurrentQuicktool(tools::Tool* currentTool);
KeyAction getCurrentActionModifiers(KeyContext context);
private:
KeyboardShortcuts();

View File

@ -27,8 +27,17 @@
namespace ui {
//////////////////////////////////////////////////////////////////////
// Accelerator
static KeyModifiers get_pressed_modifiers_from_she()
{
KeyModifiers mods = kKeyNoneModifier;
if (she::is_key_pressed(kKeyLShift) ) mods = KeyModifiers(int(mods) | int(kKeyShiftModifier));
if (she::is_key_pressed(kKeyRShift) ) mods = KeyModifiers(int(mods) | int(kKeyShiftModifier));
if (she::is_key_pressed(kKeyLControl)) mods = KeyModifiers(int(mods) | int(kKeyCtrlModifier));
if (she::is_key_pressed(kKeyRControl)) mods = KeyModifiers(int(mods) | int(kKeyCtrlModifier));
if (she::is_key_pressed(kKeyAlt) ) mods = KeyModifiers(int(mods) | int(kKeyAltModifier));
if (she::is_key_pressed(kKeyCommand) ) mods = KeyModifiers(int(mods) | int(kKeyCmdModifier));
return mods;
}
Accelerator::Accelerator()
: m_modifiers(kKeyNoneModifier)
@ -434,19 +443,20 @@ bool Accelerator::isPressed(KeyModifiers modifiers, KeyScancode scancode, int un
bool Accelerator::isPressed() const
{
KeyModifiers modifiers = kKeyNoneModifier;
if (she::is_key_pressed(kKeyLShift) ) modifiers = (KeyModifiers)((int)modifiers | (int)kKeyShiftModifier);
if (she::is_key_pressed(kKeyRShift) ) modifiers = (KeyModifiers)((int)modifiers | (int)kKeyShiftModifier);
if (she::is_key_pressed(kKeyLControl)) modifiers = (KeyModifiers)((int)modifiers | (int)kKeyCtrlModifier);
if (she::is_key_pressed(kKeyRControl)) modifiers = (KeyModifiers)((int)modifiers | (int)kKeyCtrlModifier);
if (she::is_key_pressed(kKeyAlt) ) modifiers = (KeyModifiers)((int)modifiers | (int)kKeyAltModifier);
if (she::is_key_pressed(kKeyCommand) ) modifiers = (KeyModifiers)((int)modifiers | (int)kKeyCmdModifier);
KeyModifiers modifiers = get_pressed_modifiers_from_she();
return ((m_scancode == 0 || she::is_key_pressed(m_scancode)) &&
(m_modifiers == modifiers));
}
bool Accelerator::isLooselyPressed() const
{
KeyModifiers modifiers = get_pressed_modifiers_from_she();
return ((m_scancode == 0 || she::is_key_pressed(m_scancode)) &&
(int(m_modifiers & modifiers) == m_modifiers));
}
//////////////////////////////////////////////////////////////////////
// Accelerators

View File

@ -26,8 +26,15 @@ namespace ui {
std::string toString() const;
bool isPressed(KeyModifiers modifiers, KeyScancode scancode, int unicodeChar) const;
// Returns true if the key is pressed and only its modifiers are
// pressed.
bool isPressed() const;
// Returns true if the key is pressed and the accelerator
// modifiers are pressed (other modifiers are allowed).
bool isLooselyPressed() const;
bool operator==(const Accelerator& other) const;
bool operator!=(const Accelerator& other) const {
return !operator==(other);