|
62 | 62 | Needed to know when to stop the NSApp */
|
63 | 63 | static long FigureWindowCount = 0;
|
64 | 64 |
|
| 65 | +/* Keep track of modifier key states for flagsChanged |
| 66 | + to keep track of press vs release */ |
| 67 | +static bool lastCommand = false; |
| 68 | +static bool lastControl = false; |
| 69 | +static bool lastShift = false; |
| 70 | +static bool lastOption = false; |
| 71 | +static bool lastCapsLock = false; |
| 72 | +/* Keep track of whether this specific key modifier was pressed or not */ |
| 73 | +static bool keyChangeCommand = false; |
| 74 | +static bool keyChangeControl = false; |
| 75 | +static bool keyChangeShift = false; |
| 76 | +static bool keyChangeOption = false; |
| 77 | +static bool keyChangeCapsLock = false; |
| 78 | + |
65 | 79 | /* -------------------------- Helper function ---------------------------- */
|
66 | 80 |
|
67 | 81 | static void
|
@@ -247,7 +261,7 @@ - (void)keyDown:(NSEvent*)event;
|
247 | 261 | - (void)keyUp:(NSEvent*)event;
|
248 | 262 | - (void)scrollWheel:(NSEvent *)event;
|
249 | 263 | - (BOOL)acceptsFirstResponder;
|
250 |
| -//- (void)flagsChanged:(NSEvent*)event; |
| 264 | +- (void)flagsChanged:(NSEvent*)event; |
251 | 265 | @end
|
252 | 266 |
|
253 | 267 | /* ---------------------------- Python classes ---------------------------- */
|
@@ -1623,26 +1637,45 @@ - (const char*)convertKeyEvent:(NSEvent*)event
|
1623 | 1637 | ];
|
1624 | 1638 |
|
1625 | 1639 | NSMutableString* returnkey = [NSMutableString string];
|
1626 |
| - if ([event modifierFlags] & NSEventModifierFlagControl) { |
1627 |
| - [returnkey appendString:@"ctrl+" ]; |
1628 |
| - } |
1629 |
| - if ([event modifierFlags] & NSEventModifierFlagOption) { |
| 1640 | + if (keyChangeControl) { |
| 1641 | + // When control is the key that was pressed, return the full word |
| 1642 | + [returnkey appendString:@"control+"]; |
| 1643 | + } else if (([event modifierFlags] & NSEventModifierFlagControl)) { |
| 1644 | + // If control is already pressed, return the shortened version |
| 1645 | + [returnkey appendString:@"ctrl+"]; |
| 1646 | + } |
| 1647 | + if (([event modifierFlags] & NSEventModifierFlagOption) || keyChangeOption) { |
1630 | 1648 | [returnkey appendString:@"alt+" ];
|
1631 | 1649 | }
|
1632 |
| - if ([event modifierFlags] & NSEventModifierFlagCommand) { |
| 1650 | + if (([event modifierFlags] & NSEventModifierFlagCommand) || keyChangeCommand) { |
1633 | 1651 | [returnkey appendString:@"cmd+" ];
|
1634 | 1652 | }
|
| 1653 | + // Don't print caps_lock unless it was the key that got pressed |
| 1654 | + if (keyChangeCapsLock) { |
| 1655 | + [returnkey appendString:@"caps_lock+" ]; |
| 1656 | + } |
1635 | 1657 |
|
1636 |
| - unichar uc = [[event charactersIgnoringModifiers] characterAtIndex:0]; |
1637 |
| - NSString* specialchar = [specialkeymappings objectForKey:[NSNumber numberWithUnsignedLong:uc]]; |
1638 |
| - if (specialchar) { |
1639 |
| - if ([event modifierFlags] & NSEventModifierFlagShift) { |
1640 |
| - [returnkey appendString:@"shift+" ]; |
| 1658 | + // flagsChanged event can't handle charactersIgnoringModifiers |
| 1659 | + // because it was a modifier key that was pressed/released |
| 1660 | + if (event.type != NSEventTypeFlagsChanged) { |
| 1661 | + unichar uc = [[event charactersIgnoringModifiers] characterAtIndex:0]; |
| 1662 | + NSString *specialchar = [specialkeymappings objectForKey:[NSNumber numberWithUnsignedLong:uc]]; |
| 1663 | + if (specialchar) { |
| 1664 | + if (([event modifierFlags] & NSEventModifierFlagShift) || keyChangeShift) { |
| 1665 | + [returnkey appendString:@"shift+"]; |
| 1666 | + } |
| 1667 | + [returnkey appendString:specialchar]; |
| 1668 | + } else { |
| 1669 | + [returnkey appendString:[event charactersIgnoringModifiers]]; |
| 1670 | + } |
| 1671 | + } else { |
| 1672 | + if (([event modifierFlags] & NSEventModifierFlagShift) || keyChangeShift) { |
| 1673 | + [returnkey appendString:@"shift+"]; |
1641 | 1674 | }
|
1642 |
| - [returnkey appendString:specialchar]; |
| 1675 | + // Since it was a modifier event trim the final character of the string |
| 1676 | + // because we added in "+" earlier |
| 1677 | + [returnkey setString: [returnkey substringToIndex:[returnkey length] - 1]]; |
1643 | 1678 | }
|
1644 |
| - else |
1645 |
| - [returnkey appendString:[event charactersIgnoringModifiers]]; |
1646 | 1679 |
|
1647 | 1680 | return [returnkey UTF8String];
|
1648 | 1681 | }
|
@@ -1711,29 +1744,60 @@ - (BOOL)acceptsFirstResponder
|
1711 | 1744 | return YES;
|
1712 | 1745 | }
|
1713 | 1746 |
|
1714 |
| -/* This is all wrong. Address of pointer is being passed instead of pointer, keynames don't |
1715 |
| - match up with what the front-end and does the front-end even handle modifier keys by themselves? |
| 1747 | +// flagsChanged gets called whenever a modifier key is pressed OR released |
| 1748 | +// so we need to handle both cases here |
| 1749 | +- (void)flagsChanged:(NSEvent *)event |
| 1750 | +{ |
| 1751 | + bool isPress = false; // true if key is pressed, false if key was released |
| 1752 | + |
| 1753 | + // Each if clause tests the two cases for each of the keys we can handle |
| 1754 | + // 1. If the modifier flag "command key" is pressed and it was not previously |
| 1755 | + // 2. If the modifier flag "command key" is not pressed and it was previously |
| 1756 | + // !! converts the result of the bitwise & operator to a logical boolean, |
| 1757 | + // which allows us to then bitwise xor (^) the result with a boolean (lastCommand). |
| 1758 | + if (!!([event modifierFlags] & NSEventModifierFlagCommand) ^ lastCommand) { |
| 1759 | + // Command pressed/released |
| 1760 | + lastCommand = !lastCommand; |
| 1761 | + keyChangeCommand = true; |
| 1762 | + isPress = lastCommand; |
| 1763 | + } else if (!!([event modifierFlags] & NSEventModifierFlagControl) ^ lastControl) { |
| 1764 | + // Control pressed/released |
| 1765 | + lastControl = !lastControl; |
| 1766 | + keyChangeControl = true; |
| 1767 | + isPress = lastControl; |
| 1768 | + } else if (!!([event modifierFlags] & NSEventModifierFlagShift) ^ lastShift) { |
| 1769 | + // Shift pressed/released |
| 1770 | + lastShift = !lastShift; |
| 1771 | + keyChangeShift = true; |
| 1772 | + isPress = lastShift; |
| 1773 | + } else if (!!([event modifierFlags] & NSEventModifierFlagOption) ^ lastOption) { |
| 1774 | + // Option pressed/released |
| 1775 | + lastOption = !lastOption; |
| 1776 | + keyChangeOption = true; |
| 1777 | + isPress = lastOption; |
| 1778 | + } else if (!!([event modifierFlags] & NSEventModifierFlagCapsLock) ^ lastCapsLock) { |
| 1779 | + // Capslock pressed/released |
| 1780 | + lastCapsLock = !lastCapsLock; |
| 1781 | + keyChangeCapsLock = true; |
| 1782 | + isPress = lastCapsLock; |
| 1783 | + } else { |
| 1784 | + // flag we don't handle |
| 1785 | + return; |
| 1786 | + } |
1716 | 1787 |
|
1717 |
| -- (void)flagsChanged:(NSEvent*)event |
1718 |
| -{ |
1719 |
| - const char *s = NULL; |
1720 |
| - if (([event modifierFlags] & NSControlKeyMask) == NSControlKeyMask) |
1721 |
| - s = "control"; |
1722 |
| - else if (([event modifierFlags] & NSShiftKeyMask) == NSShiftKeyMask) |
1723 |
| - s = "shift"; |
1724 |
| - else if (([event modifierFlags] & NSAlternateKeyMask) == NSAlternateKeyMask) |
1725 |
| - s = "alt"; |
1726 |
| - else return; |
1727 |
| - PyGILState_STATE gstate = PyGILState_Ensure(); |
1728 |
| - PyObject* result = PyObject_CallMethod(canvas, "key_press_event", "s", &s); |
1729 |
| - if (result) |
1730 |
| - Py_DECREF(result); |
1731 |
| - else |
1732 |
| - PyErr_Print(); |
| 1788 | + if (isPress) { |
| 1789 | + [self keyDown:event]; |
| 1790 | + } else { |
| 1791 | + [self keyUp:event]; |
| 1792 | + } |
1733 | 1793 |
|
1734 |
| - PyGILState_Release(gstate); |
| 1794 | + // Reset the state for the key changes after handling the event |
| 1795 | + keyChangeCommand = false; |
| 1796 | + keyChangeControl = false; |
| 1797 | + keyChangeShift = false; |
| 1798 | + keyChangeOption = false; |
| 1799 | + keyChangeCapsLock = false; |
1735 | 1800 | }
|
1736 |
| - */ |
1737 | 1801 | @end
|
1738 | 1802 |
|
1739 | 1803 | static PyObject*
|
|
0 commit comments