tuikit/driver/curses.py
changeset 113 6796adfdc7eb
parent 109 105b1affc3c2
parent 106 abcadb7e2ef1
equal deleted inserted replaced
112:ce2e67e7bbb8 113:6796adfdc7eb
     1 import curses.ascii
     1 import curses.ascii
     2 import math
     2 import math
     3 import logging
     3 import logging
     4 
     4 
     5 from tuikit.driver.driver import Driver
     5 from tuikit.driver.driver import Driver
       
     6 from tuikit.core.coords import Point
     6 
     7 
     7 
     8 
     8 class CursesDriver(Driver):
     9 class CursesDriver(Driver):
     9 
    10 
    10     key_codes = (
    11     key_codes = (
    86         self.colors = {}     # maps names to curses attributes
    87         self.colors = {}     # maps names to curses attributes
    87         self.colorpairs = {} # maps tuple (fg,bg) to curses color_pair
    88         self.colorpairs = {} # maps tuple (fg,bg) to curses color_pair
    88         self.colorstack = [] # pushcolor/popcolor puts or gets attributes from this
    89         self.colorstack = [] # pushcolor/popcolor puts or gets attributes from this
    89         self.inputqueue = []
    90         self.inputqueue = []
    90         self.mbtnstack = []
    91         self.mbtnstack = []
    91         self._mouse_last_pos = (None, None)
    92         self._mouse_last_pos = None  # Point
    92         self._mouse_last_bstate = None
    93         self._mouse_last_bstate = None
    93 
    94 
    94     ## initialization, finalization ##
    95     ## initialization, finalization ##
    95 
    96 
    96     def init(self):
    97     def init(self):
   278         try:
   279         try:
   279             _id, x, y, _z, bstate = curses.getmouse()
   280             _id, x, y, _z, bstate = curses.getmouse()
   280         except curses.error:
   281         except curses.error:
   281             return []
   282             return []
   282 
   283 
       
   284         pos = Point(x, y)
   283         out = []
   285         out = []
   284 
   286 
   285         if bstate & curses.REPORT_MOUSE_POSITION:
   287         if bstate & curses.REPORT_MOUSE_POSITION:
   286             if self._mouse_last_pos != (x, y):
   288             if self._mouse_last_pos != pos:
   287                 if self._mouse_last_pos[0] is not None:
   289                 if self._mouse_last_pos:
   288                     relx = x - (self._mouse_last_pos[0] or 0)
   290                     relpos = pos - self._mouse_last_pos
   289                     rely = y - (self._mouse_last_pos[1] or 0)
   291                     out += [('mousemove', 0, pos, relpos)]
   290                     out += [('mousemove', 0, x, y, relx, rely)]
   292                 self._mouse_last_pos = pos
   291                 self._mouse_last_pos = (x, y)
       
   292 
   293 
   293         # we are interested only in changes, not buttons already pressed before event
   294         # we are interested only in changes, not buttons already pressed before event
   294         if self._mouse_last_bstate is not None:
   295         if self._mouse_last_bstate is not None:
   295             old = self._mouse_last_bstate
   296             old = self._mouse_last_bstate
   296             new = bstate
   297             new = bstate
   298             self._mouse_last_bstate = new
   299             self._mouse_last_bstate = new
   299         else:
   300         else:
   300             self._mouse_last_bstate = bstate
   301             self._mouse_last_bstate = bstate
   301 
   302 
   302         if bstate & curses.BUTTON1_PRESSED:
   303         if bstate & curses.BUTTON1_PRESSED:
   303             out += [('mousedown', 1, x, y)]
   304             out += [('mousedown', 1, pos)]
   304         if bstate & curses.BUTTON2_PRESSED:
   305         if bstate & curses.BUTTON2_PRESSED:
   305             out += [('mousedown', 2, x, y)]
   306             out += [('mousedown', 2, pos)]
   306         if bstate & curses.BUTTON3_PRESSED:
   307         if bstate & curses.BUTTON3_PRESSED:
   307             out += [('mousedown', 3, x, y)]
   308             out += [('mousedown', 3, pos)]
   308         if bstate & curses.BUTTON1_RELEASED:
   309         if bstate & curses.BUTTON1_RELEASED:
   309             out += [('mouseup', 1, x, y)]
   310             out += [('mouseup', 1, pos)]
   310         if bstate & curses.BUTTON2_RELEASED:
   311         if bstate & curses.BUTTON2_RELEASED:
   311             out += [('mouseup', 2, x, y)]
   312             out += [('mouseup', 2, pos)]
   312         if bstate & curses.BUTTON3_RELEASED:
   313         if bstate & curses.BUTTON3_RELEASED:
   313             out += [('mouseup', 3, x, y)]
   314             out += [('mouseup', 3, pos)]
   314 
   315 
   315         # reset last pos when pressed/released
   316         # reset last pos when pressed/released
   316         if len(out) > 0 and out[-1][0] in ('mousedown', 'mouseup'):
   317         if len(out) > 0 and out[-1][0] in ('mousedown', 'mouseup'):
   317             self._mouse_last_pos = (None, None)
   318             self._mouse_last_pos = None
   318 
   319 
   319         return out
   320         return out
   320 
   321 
   321     def _process_utf8_chars(self):
   322     def _process_utf8_chars(self):
   322         #FIXME read exact number of chars as defined by utf-8
   323         #FIXME read exact number of chars as defined by utf-8
   393 
   394 
   394     def _process_xterm_mouse(self):
   395     def _process_xterm_mouse(self):
   395         t = self._inputqueue_get_wait()
   396         t = self._inputqueue_get_wait()
   396         x = self._inputqueue_get_wait() - 0x21
   397         x = self._inputqueue_get_wait() - 0x21
   397         y = self._inputqueue_get_wait() - 0x21
   398         y = self._inputqueue_get_wait() - 0x21
       
   399         pos = Point(x, y)
   398 
   400 
   399         out = []
   401         out = []
   400 
   402 
   401         if t in (0x20, 0x21, 0x22):
   403         if t in (0x20, 0x21, 0x22):
   402             # button press
   404             # button press
   403             btn = t - 0x1f
   405             btn = t - 0x1f
   404             if not btn in self.mbtnstack:
   406             if not btn in self.mbtnstack:
   405                 self.mbtnstack.append(btn)
   407                 self.mbtnstack.append(btn)
   406                 self._mouse_last_pos = (None, None)
   408                 self._mouse_last_pos = None
   407                 out += [('mousedown', btn, x, y)]
   409                 out += [('mousedown', btn, pos)]
   408             else:
   410             else:
   409                 # mouse move
   411                 # mouse move
   410                 if self._mouse_last_pos != (x, y):
   412                 if self._mouse_last_pos != pos:
   411                     if self._mouse_last_pos[0] is not None:
   413                     if self._mouse_last_pos:
   412                         relx = x - self._mouse_last_pos[0]
   414                         relpos = pos - self._mouse_last_pos
   413                         rely = y - self._mouse_last_pos[1]
   415                         out += [('mousemove', btn, pos, relpos)]
   414                         out += [('mousemove', btn, x, y, relx, rely)]
   416                     self._mouse_last_pos = pos
   415                     self._mouse_last_pos = (x, y)
       
   416         elif t == 0x23:
   417         elif t == 0x23:
   417             # button release
   418             # button release
   418             btn = self.mbtnstack.pop()
   419             btn = self.mbtnstack.pop()
   419             self._mouse_last_pos = (None, None)
   420             self._mouse_last_pos = (None, None)
   420             out += [('mouseup', btn, x, y)]
   421             out += [('mouseup', btn, pos)]
   421         elif t in (0x60, 0x61):
   422         elif t in (0x60, 0x61):
   422             # wheel up, down
   423             # wheel up, down
   423             btn = 4 + t - 0x60
   424             btn = 4 + t - 0x60
   424             out += [('mousewheel', btn, x, y)]
   425             out += [('mousewheel', btn, pos)]
   425         else:
   426         else:
   426             raise Exception('Unknown mouse event: %x' % t)
   427             raise Exception('Unknown mouse event: %x' % t)
   427 
   428 
   428         return out
   429         return out
   429 
   430