tuikit/driver/curses.py
author Radek Brich <radek.brich@devl.cz>
Wed, 03 Sep 2014 19:08:21 +0200
changeset 109 105b1affc3c2
parent 97 0c2e0c09ba5c
child 113 6796adfdc7eb
permissions -rw-r--r--
Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     1
import curses.ascii
57
911927edbdde DriverSDL: Add support for timeouts.
Radek Brich <radek.brich@devl.cz>
parents: 46
diff changeset
     2
import math
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     3
import logging
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     4
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
     5
from tuikit.driver.driver import Driver
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     6
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
     7
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
     8
class CursesDriver(Driver):
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
     9
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    10
    key_codes = (
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    11
        (0x09,                      'tab'           ),
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    12
        (0x0a,                      'enter'         ),
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    13
        (0x7f,                      'backspace'     ),
4
d197ca00496f Add escape sequences for linux console.
Radek Brich <radek.brich@devl.cz>
parents: 3
diff changeset
    14
        (0x1b,                      'escape'        ),
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    15
        (0x1b, 0x4f, 0x50,          'f1'            ),  # xterm
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    16
        (0x1b, 0x4f, 0x51,          'f2'            ),  # xterm
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    17
        (0x1b, 0x4f, 0x52,          'f3'            ),  # xterm
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    18
        (0x1b, 0x4f, 0x53,          'f4'            ),  # xterm
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    19
        (0x1b, 0x5b,                'CSI'           ),  # see csi_codes
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    20
        (0x1b, 0x5b, 0x4d,          'mouse'         ),
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    21
    )
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    22
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    23
    # http://en.wikipedia.org/wiki/ANSI_escape_code
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    24
    csi_codes = (
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    25
        # code            param     key name
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    26
        (0x7e,              1,      'home'          ),  # linux
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    27
        (0x7e,              2,      'insert'        ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    28
        (0x7e,              3,      'delete'        ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    29
        (0x7e,              4,      'end'           ),  # linux
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    30
        (0x7e,              5,      'pageup'        ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    31
        (0x7e,              6,      'pagedown'      ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    32
        (0x7e,              15,     'f5'            ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    33
        (0x7e,              17,     'f6'            ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    34
        (0x7e,              18,     'f7'            ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    35
        (0x7e,              19,     'f8'            ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    36
        (0x7e,              20,     'f9'            ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    37
        (0x7e,              21,     'f10'           ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    38
        (0x7e,              23,     'f11'           ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    39
        (0x7e,              24,     'f12'           ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    40
        (0x41,              1,      'up'            ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    41
        (0x42,              1,      'down'          ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    42
        (0x43,              1,      'right'         ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    43
        (0x44,              1,      'left'          ),
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    44
        (0x46,              1,      'end'           ),  # xterm
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
    45
        (0x48,              1,      'home'          ),  # xterm
109
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    46
        (0x5a,              1,      'shift+tab'     ),  # xterm
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    47
        (0x5b, 0x41,        1,      'f1'            ),  # linux
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    48
        (0x5b, 0x42,        1,      'f2'            ),  # linux
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    49
        (0x5b, 0x43,        1,      'f3'            ),  # linux
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    50
        (0x5b, 0x44,        1,      'f4'            ),  # linux
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    51
        (0x5b, 0x45,        1,      'f5'            ),  # linux
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    52
    )
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    53
27
139d1241b4c5 DriverPygame: add colors, make window resizable.
Radek Brich <radek.brich@devl.cz>
parents: 26
diff changeset
    54
    color_map = {
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    55
        'default':      (-1,                    0),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    56
        'black':        (curses.COLOR_BLACK,    0),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    57
        'blue':         (curses.COLOR_BLUE,     0),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    58
        'green':        (curses.COLOR_GREEN,    0),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    59
        'cyan':         (curses.COLOR_CYAN,     0),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    60
        'red':          (curses.COLOR_RED,      0),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    61
        'magenta':      (curses.COLOR_MAGENTA,  0),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    62
        'brown':        (curses.COLOR_YELLOW,   0),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    63
        'lightgray':    (curses.COLOR_WHITE,    0),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    64
        'gray':         (curses.COLOR_BLACK,    curses.A_BOLD),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    65
        'lightblue':    (curses.COLOR_BLUE,     curses.A_BOLD),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    66
        'lightgreen':   (curses.COLOR_GREEN,    curses.A_BOLD),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    67
        'lightcyan':    (curses.COLOR_CYAN,     curses.A_BOLD),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    68
        'lightred':     (curses.COLOR_RED,      curses.A_BOLD),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    69
        'lightmagenta': (curses.COLOR_MAGENTA,  curses.A_BOLD),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    70
        'yellow':       (curses.COLOR_YELLOW,   curses.A_BOLD),
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    71
        'white':        (curses.COLOR_WHITE,    curses.A_BOLD),
7
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    72
    }
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    73
27
139d1241b4c5 DriverPygame: add colors, make window resizable.
Radek Brich <radek.brich@devl.cz>
parents: 26
diff changeset
    74
    attr_map = {
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    75
        'bold':         curses.A_BOLD,
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    76
        'underline':    curses.A_UNDERLINE,
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    77
        'standout':     curses.A_STANDOUT,  # inverse bg/fg
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
    78
        'blink':        curses.A_BLINK,
27
139d1241b4c5 DriverPygame: add colors, make window resizable.
Radek Brich <radek.brich@devl.cz>
parents: 26
diff changeset
    79
    }
139d1241b4c5 DriverPygame: add colors, make window resizable.
Radek Brich <radek.brich@devl.cz>
parents: 26
diff changeset
    80
23
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
    81
    def __init__(self):
24
b248ef500557 Add DriverPygame (incomplete). Move unicode graphics constants to UnicodeGraphics class. Move shared parts of drivers to Driver base class.
Radek Brich <radek.brich@devl.cz>
parents: 23
diff changeset
    82
        Driver.__init__(self)
109
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
    83
        self._log = logging.getLogger(__name__)
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
    84
        self.stdscr = None
5
ae128c885d0f New GridLayout. Change cursor behavior (hide on unfocus event). Change resize event to propagate through containers. Change container clipping - allowlayout=false children are clipped without borders. More Widget doc.
Radek Brich <radek.brich@devl.cz>
parents: 4
diff changeset
    85
        self.cursor = None
7
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    86
        self.colors = {}     # maps names to curses attributes
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    87
        self.colorpairs = {} # maps tuple (fg,bg) to curses color_pair
d4a291b31cbb New color management - named colors.
Radek Brich <radek.brich@devl.cz>
parents: 5
diff changeset
    88
        self.colorstack = [] # pushcolor/popcolor puts or gets attributes from this
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    89
        self.inputqueue = []
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    90
        self.mbtnstack = []
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
    91
        self._mouse_last_pos = (None, None)
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
    92
        self._mouse_last_bstate = None
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    93
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
    94
    ## initialization, finalization ##
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
    95
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
    96
    def init(self):
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
    97
        """Initialize curses"""
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
    98
        self.stdscr = curses.initscr()
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
    99
        curses.start_color()
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   100
        curses.use_default_colors()
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   101
        curses.noecho()
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   102
        curses.cbreak()
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   103
        self.stdscr.keypad(0)
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   104
        self.stdscr.immedok(0)
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   105
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   106
        self.size.h, self.size.w = self.stdscr.getmaxyx()
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   107
23
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   108
        curses.curs_set(False)  # hide cursor
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   109
        curses.mousemask(curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION)
4e72fd2a0e14 Rename BackendCurses to DriverCurses. Add DriverDummy - dummy driver for debugging purposes. Move clipping stack from driver to common.ClipStack class.
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   110
        curses.mouseinterval(0)  # do not wait to detect clicks, we use only press/release
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   111
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   112
    def close(self):
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   113
        self.stdscr.keypad(0)
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   114
        curses.echo()
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   115
        curses.nocbreak()
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   116
        curses.endwin()
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   117
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   118
    ## drawing ##
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   119
91
de80e140b0ec Add clipping for Buffer draw operations.
Radek Brich <radek.brich@devl.cz>
parents: 88
diff changeset
   120
    def clear(self):
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   121
        self.stdscr.erase()
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   122
95
05392e369ede Refactoring: Swap drawing operations parameters. Coords are now last and have default values.
Radek Brich <radek.brich@devl.cz>
parents: 91
diff changeset
   123
    def putch(self, ch, x, y):
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   124
        try:
95
05392e369ede Refactoring: Swap drawing operations parameters. Coords are now last and have default values.
Radek Brich <radek.brich@devl.cz>
parents: 91
diff changeset
   125
            if isinstance(ch, int):
05392e369ede Refactoring: Swap drawing operations parameters. Coords are now last and have default values.
Radek Brich <radek.brich@devl.cz>
parents: 91
diff changeset
   126
                self.stdscr.addch(y, x, ch)
05392e369ede Refactoring: Swap drawing operations parameters. Coords are now last and have default values.
Radek Brich <radek.brich@devl.cz>
parents: 91
diff changeset
   127
            elif isinstance(ch, str) and len(ch) == 1:
86
0978fb755d31 Add core Application (adjusted), Window (new version), Signal (replaces Emitter), Size (adjusted). Add application demo.
Radek Brich <radek.brich@devl.cz>
parents: 84
diff changeset
   128
                self.stdscr.addstr(y, x, ch)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   129
            else:
95
05392e369ede Refactoring: Swap drawing operations parameters. Coords are now last and have default values.
Radek Brich <radek.brich@devl.cz>
parents: 91
diff changeset
   130
                raise TypeError('Integer or one-char string is required.')
05392e369ede Refactoring: Swap drawing operations parameters. Coords are now last and have default values.
Radek Brich <radek.brich@devl.cz>
parents: 91
diff changeset
   131
        except curses.error as e:
05392e369ede Refactoring: Swap drawing operations parameters. Coords are now last and have default values.
Radek Brich <radek.brich@devl.cz>
parents: 91
diff changeset
   132
            self._log.exception('putch(%r, %s, %s) error:' % (ch, x, y))
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   133
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   134
    def draw(self, buffer, x=0, y=0):
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   135
        for bufy in range(buffer.size.h):
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   136
            for bufx in range(buffer.size.w):
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   137
                char, attr_desc = buffer.get(bufx, bufy)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   138
                self.setattr(attr_desc)
95
05392e369ede Refactoring: Swap drawing operations parameters. Coords are now last and have default values.
Radek Brich <radek.brich@devl.cz>
parents: 91
diff changeset
   139
                self.putch(char, x + bufx, y + bufy)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   140
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   141
    def flush(self):
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   142
        if self.cursor:
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   143
            self.stdscr.move(self.cursor.y, self.cursor.x)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   144
            curses.curs_set(True)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   145
        else:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   146
            curses.curs_set(False)
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   147
        self.stdscr.refresh()
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   148
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   149
    ## colors, attributes ##
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   150
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   151
    def setattr(self, attr_desc):
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   152
        """Set attribute to be used for subsequent draw operations."""
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   153
        attr = self.colors.get(attr_desc, None)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   154
        if attr is None:
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   155
            # first encountered `attr_desc`, initialize
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   156
            fg, bg, attrs = self._parse_attr_desc(attr_desc)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   157
            fgcol, fgattr = self.color_map[fg]
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   158
            bgcol, _bgattr = self.color_map[bg]
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   159
            colpair = self._getcolorpair(fgcol, bgcol)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   160
            attr = curses.color_pair(colpair) | self._parseattrs(attrs) | fgattr
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   161
            self.colors[attr_desc] = attr
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   162
        self.stdscr.attrset(attr)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   163
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   164
    def _getcolorpair(self, fgcol, bgcol):
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   165
        pair = (fgcol, bgcol)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   166
        if pair in self.colorpairs:
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   167
            return self.colorpairs[pair]
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   168
        num = len(self.colorpairs) + 1
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   169
        curses.init_pair(num, fgcol, bgcol)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   170
        self.colorpairs[pair] = num
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   171
        return num
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   172
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   173
    def _parseattrs(self, attrs):
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   174
        res = 0
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   175
        for a in attrs:
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   176
            res = res | self.attr_map[a]
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   177
        return res
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   178
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   179
    ## input, events ##
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   180
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   181
    def getevents(self, timeout=None):
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   182
        """Process input, return list of events.
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   183
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   184
        timeout -- float, in seconds (None=infinite)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   185
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   186
        Returns:
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   187
            [('event', param1, ...), ...]
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   188
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   189
        """
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   190
        # empty queue -> fill
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   191
        if len(self.inputqueue) == 0:
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   192
            if timeout is not None:
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   193
                timeout = math.ceil(timeout * 10)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   194
            self._inputqueue_fill(timeout)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   195
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   196
        res = []
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   197
        while len(self.inputqueue):
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   198
            c = self._inputqueue_get()
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   199
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   200
            if c == curses.KEY_MOUSE:
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   201
                res += self._process_mouse()
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   202
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   203
            elif c == curses.KEY_RESIZE:
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   204
                self.size.h, self.size.w = self.stdscr.getmaxyx()
88
90d00354dc70 Add WindowManager, basic event handling.
Radek Brich <radek.brich@devl.cz>
parents: 86
diff changeset
   205
                res.append(('resize', self.size.w, self.size.h))
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   206
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   207
            elif curses.ascii.isctrl(c):
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   208
                self._inputqueue_unget(c)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   209
                res += self._process_control_chars()
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   210
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   211
            elif 192 <= c <= 255:
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   212
                self._inputqueue_unget(c)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   213
                res += self._process_utf8_chars()
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   214
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   215
            elif curses.ascii.isprint(c):
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   216
                res += [('keypress', None, str(chr(c)), set())]
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   217
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   218
            else:
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   219
                self._inputqueue_unget(c)
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   220
                res += self._process_control_chars()
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   221
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   222
        return res
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   223
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   224
    def _inputqueue_fill(self, timeout=None):
57
911927edbdde DriverSDL: Add support for timeouts.
Radek Brich <radek.brich@devl.cz>
parents: 46
diff changeset
   225
        """Wait for curses input, add it to inputqueue.
911927edbdde DriverSDL: Add support for timeouts.
Radek Brich <radek.brich@devl.cz>
parents: 46
diff changeset
   226
911927edbdde DriverSDL: Add support for timeouts.
Radek Brich <radek.brich@devl.cz>
parents: 46
diff changeset
   227
        timeout -- int, tenths of second (None=infinite)
911927edbdde DriverSDL: Add support for timeouts.
Radek Brich <radek.brich@devl.cz>
parents: 46
diff changeset
   228
911927edbdde DriverSDL: Add support for timeouts.
Radek Brich <radek.brich@devl.cz>
parents: 46
diff changeset
   229
        """
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   230
        if timeout is None:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   231
            # wait indefinitely
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   232
            c = self.stdscr.getch()
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   233
            self.inputqueue.insert(0, c)
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   234
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   235
        elif timeout > 0:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   236
            # wait
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   237
            curses.halfdelay(timeout)
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   238
            c = self.stdscr.getch()
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   239
            curses.cbreak()
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   240
            if c == -1:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   241
                return
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   242
            self.inputqueue.insert(0, c)
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   243
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   244
        # timeout = 0 -> no wait
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   245
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   246
        self.stdscr.nodelay(1)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   247
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   248
        while True:
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   249
            c = self.stdscr.getch()
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   250
            if c == -1:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   251
                break
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   252
            self.inputqueue.insert(0, c)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   253
83
ebe732b9ef19 Refactor Driver, CursesDriver: init, close, draw.
Radek Brich <radek.brich@devl.cz>
parents: 82
diff changeset
   254
        self.stdscr.nodelay(0)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   255
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   256
    def _inputqueue_get(self):
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   257
        c = None
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   258
        try:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   259
            c = self.inputqueue.pop()
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   260
        except IndexError:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   261
            pass
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   262
        return c
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   263
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   264
    def _inputqueue_get_wait(self):
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   265
        c = None
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   266
        while c is None:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   267
            try:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   268
                c = self.inputqueue.pop()
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   269
            except IndexError:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   270
                curses.napms(25)
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   271
                self._inputqueue_fill(0)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   272
        return c
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   273
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   274
    def _inputqueue_unget(self, c):
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   275
        self.inputqueue.append(c)
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   276
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   277
    def _process_mouse(self):
4
d197ca00496f Add escape sequences for linux console.
Radek Brich <radek.brich@devl.cz>
parents: 3
diff changeset
   278
        try:
25
f69a1f0382ce Partial DriverPygame.putch() implementation. Add patch for PyGame implementing font.render_glyph(). Add test for PyGame font module. Add special key definitions to DriverPygame.
Radek Brich <radek.brich@devl.cz>
parents: 24
diff changeset
   279
            _id, x, y, _z, bstate = curses.getmouse()
4
d197ca00496f Add escape sequences for linux console.
Radek Brich <radek.brich@devl.cz>
parents: 3
diff changeset
   280
        except curses.error:
d197ca00496f Add escape sequences for linux console.
Radek Brich <radek.brich@devl.cz>
parents: 3
diff changeset
   281
            return []
d197ca00496f Add escape sequences for linux console.
Radek Brich <radek.brich@devl.cz>
parents: 3
diff changeset
   282
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   283
        out = []
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   284
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   285
        if bstate & curses.REPORT_MOUSE_POSITION:
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   286
            if self._mouse_last_pos != (x, y):
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   287
                if self._mouse_last_pos[0] is not None:
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   288
                    relx = x - (self._mouse_last_pos[0] or 0)
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   289
                    rely = y - (self._mouse_last_pos[1] or 0)
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   290
                    out += [('mousemove', 0, x, y, relx, rely)]
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   291
                self._mouse_last_pos = (x, y)
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   292
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   293
        # we are interested only in changes, not buttons already pressed before event
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   294
        if self._mouse_last_bstate is not None:
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   295
            old = self._mouse_last_bstate
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   296
            new = bstate
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   297
            bstate = ~old & new
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   298
            self._mouse_last_bstate = new
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   299
        else:
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   300
            self._mouse_last_bstate = bstate
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   301
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   302
        if bstate & curses.BUTTON1_PRESSED:
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   303
            out += [('mousedown', 1, x, y)]
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   304
        if bstate & curses.BUTTON2_PRESSED:
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   305
            out += [('mousedown', 2, x, y)]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   306
        if bstate & curses.BUTTON3_PRESSED:
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   307
            out += [('mousedown', 3, x, y)]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   308
        if bstate & curses.BUTTON1_RELEASED:
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   309
            out += [('mouseup', 1, x, y)]
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   310
        if bstate & curses.BUTTON2_RELEASED:
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   311
            out += [('mouseup', 2, x, y)]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   312
        if bstate & curses.BUTTON3_RELEASED:
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   313
            out += [('mouseup', 3, x, y)]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   314
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   315
        # reset last pos when pressed/released
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   316
        if len(out) > 0 and out[-1][0] in ('mousedown', 'mouseup'):
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   317
            self._mouse_last_pos = (None, None)
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   318
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   319
        return out
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   320
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   321
    def _process_utf8_chars(self):
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   322
        #FIXME read exact number of chars as defined by utf-8
20
472a753664f9 Update utf8 character input to Python3. Reorganize tests.
Radek Brich <radek.brich@devl.cz>
parents: 18
diff changeset
   323
        utf = []
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   324
        while len(utf) <= 6:
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   325
            c = self._inputqueue_get_wait()
20
472a753664f9 Update utf8 character input to Python3. Reorganize tests.
Radek Brich <radek.brich@devl.cz>
parents: 18
diff changeset
   326
            utf.append(c)
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   327
            try:
20
472a753664f9 Update utf8 character input to Python3. Reorganize tests.
Radek Brich <radek.brich@devl.cz>
parents: 18
diff changeset
   328
                uni = str(bytes(utf), 'utf-8')
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   329
                return [('keypress', None, uni, set())]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   330
            except UnicodeDecodeError:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   331
                continue
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   332
        raise Exception('Invalid UTF-8 sequence: %r' % utf)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   333
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   334
    def _process_control_chars(self):
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   335
        codes = self.key_codes
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   336
        matchingcodes = []
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   337
        match = None
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   338
        consumed = []
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   339
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   340
        # consume next char, filter out matching codes
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   341
        c = self._inputqueue_get_wait()
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   342
        consumed.append(c)
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   343
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   344
        while True:
41
37b7dfc3eae6 Update Emitter: All event handlers now have exactly one argument: object inherited from Event class, which carries any data.
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
   345
            #self.log.debug('c=%s len=%s', c, len(codes))
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   346
            for code in codes:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   347
                if c == code[len(consumed)-1]:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   348
                    if len(code) - 1 == len(consumed):
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   349
                        match = code
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   350
                    else:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   351
                        matchingcodes += [code]
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   352
41
37b7dfc3eae6 Update Emitter: All event handlers now have exactly one argument: object inherited from Event class, which carries any data.
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
   353
            #self.log.debug('matching=%s', len(matchingcodes))
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   354
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   355
            # match found, or no matching code found -> stop
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   356
            if len(matchingcodes) == 0:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   357
                break
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   358
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   359
            # match found and some sequencies still match -> continue
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   360
            if len(matchingcodes) > 0:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   361
                if len(self.inputqueue) == 0:
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   362
                    self._inputqueue_fill(1)
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   363
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   364
            c = self._inputqueue_get()
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   365
            if c:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   366
                consumed.append(c)
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   367
                codes = matchingcodes
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   368
                matchingcodes = []
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   369
            else:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   370
                break
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   371
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   372
        keyname = None
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   373
        if match:
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   374
            # compare match to consumed, return unused chars
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   375
            l = len(match) - 1
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   376
            while len(consumed) > l:
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   377
                self._inputqueue_unget(consumed[-1])
3
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   378
                del consumed[-1]
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   379
            keyname = match[-1]
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   380
33ec838dc021 Fixed escape sequence handling.
Radek Brich <radek.brich@devl.cz>
parents: 2
diff changeset
   381
        if match is None:
109
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   382
            self._log.debug('Unknown control sequence: %s',
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   383
                           ','.join(['0x%x' % x for x in consumed]))
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   384
            return [('keypress', 'Unknown', None, set())]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   385
66
Radek Brich <radek.brich@devl.cz>
parents: 65
diff changeset
   386
        if keyname == 'mouse':
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   387
            return self._process_xterm_mouse()
66
Radek Brich <radek.brich@devl.cz>
parents: 65
diff changeset
   388
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   389
        if keyname == 'CSI':
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   390
            return self._process_control_sequence()
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   391
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   392
        return [('keypress', keyname, None, set())]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   393
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   394
    def _process_xterm_mouse(self):
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   395
        t = self._inputqueue_get_wait()
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   396
        x = self._inputqueue_get_wait() - 0x21
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   397
        y = self._inputqueue_get_wait() - 0x21
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   398
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   399
        out = []
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   400
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   401
        if t in (0x20, 0x21, 0x22):
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   402
            # button press
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   403
            btn = t - 0x1f
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   404
            if not btn in self.mbtnstack:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   405
                self.mbtnstack.append(btn)
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   406
                self._mouse_last_pos = (None, None)
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   407
                out += [('mousedown', btn, x, y)]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   408
            else:
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   409
                # mouse move
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   410
                if self._mouse_last_pos != (x, y):
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   411
                    if self._mouse_last_pos[0] is not None:
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   412
                        relx = x - self._mouse_last_pos[0]
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   413
                        rely = y - self._mouse_last_pos[1]
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   414
                        out += [('mousemove', btn, x, y, relx, rely)]
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   415
                    self._mouse_last_pos = (x, y)
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   416
        elif t == 0x23:
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   417
            # button release
41
37b7dfc3eae6 Update Emitter: All event handlers now have exactly one argument: object inherited from Event class, which carries any data.
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
   418
            btn = self.mbtnstack.pop()
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   419
            self._mouse_last_pos = (None, None)
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   420
            out += [('mouseup', btn, x, y)]
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   421
        elif t in (0x60, 0x61):
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   422
            # wheel up, down
41
37b7dfc3eae6 Update Emitter: All event handlers now have exactly one argument: object inherited from Event class, which carries any data.
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
   423
            btn = 4 + t - 0x60
71
cfd3445107b4 Report mousemove relative position change. Window: when in AnchorLayout, aligned right/bottom - fix resizing by mouse to behave as expected.
Radek Brich <radek.brich@devl.cz>
parents: 70
diff changeset
   424
            out += [('mousewheel', btn, x, y)]
0
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   425
        else:
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   426
            raise Exception('Unknown mouse event: %x' % t)
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   427
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   428
        return out
29
c0cdef06fd16 Import only one driver from application.
Radek Brich <radek.brich@devl.cz>
parents: 27
diff changeset
   429
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   430
    def _process_control_sequence(self):
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   431
        codes = self.csi_codes
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   432
        debug_seq = [0x1b, 0x5b]
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   433
        c = self._inputqueue_get_wait()
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   434
        debug_seq.append(c)
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   435
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   436
        # numeric parameters?
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   437
        params = []
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   438
        if chr(c).isdigit():
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   439
            params.append(chr(c))
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   440
            while True:
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   441
                c = self._inputqueue_get_wait()
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   442
                debug_seq.append(c)
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   443
                if chr(c).isdigit():
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   444
                    params[-1] += chr(c)
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   445
                elif chr(c) == ';':
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   446
                    params.append('')
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   447
                else:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   448
                    break
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   449
        params = [int(x) for x in params]
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   450
        if len(params) == 0:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   451
            params = [1]
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   452
68
bc51b0220be2 DriverCurses: filter mousemove - generate event only when coordinates changes.
Radek Brich <radek.brich@devl.cz>
parents: 66
diff changeset
   453
        # filter codes using byte sequence
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   454
        while True:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   455
            matching_codes = []
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   456
            for code in codes:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   457
                if len(code) > 2 and code[0] == c:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   458
                    matching_codes.append(code[1:])
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   459
            codes = matching_codes
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   460
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   461
            if len(codes) == 0:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   462
                # no match -> unknown code
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   463
                seq = ','.join(['0x%x' % x for x in debug_seq])
109
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   464
                self._log.debug('Unknown control sequence: %s', seq)
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   465
                return [('keypress', 'Unknown:' + seq, None, set())]
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   466
            elif len(codes) == 1:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   467
                # one match -> we got the winner
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   468
                break
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   469
            elif len(codes[0]) == 2:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   470
                # more than one matching, but no more chars to check
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   471
                # will be sorted out using parameters
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   472
                break
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   473
            else:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   474
                # more than one matching -> continue loop
84
04dfb5ddf031 Refactor Driver, CursesDriver: draw, setattr, input.
Radek Brich <radek.brich@devl.cz>
parents: 83
diff changeset
   475
                c = self._inputqueue_get_wait()
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   476
                debug_seq.append(c)
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   477
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   478
        # filter codes using first parameter
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   479
        matching_codes = []
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   480
        for code in codes:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   481
            if params[0] == code[0] or params[0] is None:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   482
                matching_codes.append(code)
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   483
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   484
        if len(matching_codes) == 0:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   485
            # no match -> unknown code
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   486
            seq = ','.join(['0x%x' % x for x in debug_seq])
109
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   487
            self._log.debug('Unknown control sequence: %s', seq)
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   488
            return [('keypress', 'Unknown:' + seq, None, set())]
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   489
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   490
        if len(matching_codes) > 1:
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   491
            raise Exception('Internal error: invalid csi_codes, more than one matching')
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   492
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   493
        keyname = matching_codes[0][1]
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   494
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   495
        # modifiers
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   496
        mod_bits = 0
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   497
        if len(params) > 1:
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   498
            mod_bits = params[1] - 1
65
5f0697950f15 DriverCurses: Add support for key modifiers.
Radek Brich <radek.brich@devl.cz>
parents: 57
diff changeset
   499
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   500
        # convert modifiers from bit-map to set
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   501
        mod_set = set()
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   502
        for bit, name in enumerate(('shift', 'alt', 'ctrl', 'meta')):
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   503
            if mod_bits & 1<<bit:
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   504
                mod_set.add(name)
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   505
109
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   506
        # parse keynames in form "shift+tab"
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   507
        if '+' in keyname:
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   508
            parts = keyname.split('+')
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   509
            for mod in parts[:-1]:
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   510
                assert(mod in ('shift', 'alt', 'ctrl', 'meta'))
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   511
                mod_set.add(mod)
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   512
            keyname = parts[-1]
105b1affc3c2 Update keypress propagation. Allow focus change by tab key. Add log property to Widget for smart logging.
Radek Brich <radek.brich@devl.cz>
parents: 97
diff changeset
   513
97
0c2e0c09ba5c Add TextField widget, keypress event, cursor.
Radek Brich <radek.brich@devl.cz>
parents: 95
diff changeset
   514
        return [('keypress', keyname, None, mod_set)]
86
0978fb755d31 Add core Application (adjusted), Window (new version), Signal (replaces Emitter), Size (adjusted). Add application demo.
Radek Brich <radek.brich@devl.cz>
parents: 84
diff changeset
   515
0978fb755d31 Add core Application (adjusted), Window (new version), Signal (replaces Emitter), Size (adjusted). Add application demo.
Radek Brich <radek.brich@devl.cz>
parents: 84
diff changeset
   516
0978fb755d31 Add core Application (adjusted), Window (new version), Signal (replaces Emitter), Size (adjusted). Add application demo.
Radek Brich <radek.brich@devl.cz>
parents: 84
diff changeset
   517
driver_class = CursesDriver