📄 raw_display.py
字号:
Return a (next_input_timeout, keys_pressed, raw_keycodes) tuple. Use this method if you are implementing your own event loop. When there is input waiting on one of the descriptors returned by get_input_descriptors() this method should be called to read and process the input. This method expects to be called in next_input_timeout seconds (a floating point number) if there is no input waiting. """ assert self._started return self._input_iter.next() def _run_input_iter(self): while True: processed = [] codes = self._get_gpm_codes() + \ self._get_keyboard_codes() original_codes = codes try: while codes: run, codes = escape.process_keyqueue( codes, True) processed.extend(run) except escape.MoreInputRequired: k = len(original_codes) - len(codes) yield (self.complete_wait, processed, original_codes[:k]) original_codes = codes processed = [] codes += self._get_keyboard_codes() + \ self._get_gpm_codes() while codes: run, codes = escape.process_keyqueue( codes, False) processed.extend(run) if self.resized: processed.append('window resize') self.resized = False yield (self.max_wait, processed, original_codes) def _get_keyboard_codes(self): codes = [] while True: code = self._getch_nodelay() if code < 0: break codes.append(code) return codes def _get_gpm_codes(self): codes = [] while self.gpm_event_pending: codes.extend(self._encode_gpm_event()) return codes def _wait_for_input_ready(self, timeout): ready = None fd_list = [sys.stdin.fileno()] if self.gpm_mev is not None: fd_list += [ self.gpm_mev.fromchild ] while True: try: ready,w,err = select.select( fd_list,[],fd_list, timeout) break except select.error, e: if e.args[0] != 4: raise if self.resized: ready = [] break return ready def _getch(self, timeout): ready = self._wait_for_input_ready(timeout) if self.gpm_mev is not None: if self.gpm_mev.fromchild.fileno() in ready: self.gpm_event_pending = True if sys.stdin.fileno() in ready: return ord(os.read(sys.stdin.fileno(), 1)) return -1 def _encode_gpm_event( self ): self.gpm_event_pending = False s = self.gpm_mev.fromchild.readline() l = s.split(",") if len(l) != 6: # unexpected output, stop tracking self._stop_gpm_tracking() return [] ev, x, y, ign, b, m = s.split(",") ev = int( ev.split("x")[-1], 16) x = int( x.split(" ")[-1] ) y = int( y.lstrip().split(" ")[0] ) b = int( b.split(" ")[-1] ) m = int( m.split("x")[-1].rstrip(), 16 ) # convert to xterm-like escape sequence last = next = self.last_bstate l = [] mod = 0 if m & 1: mod |= 4 # shift if m & 10: mod |= 8 # alt if m & 4: mod |= 16 # ctrl def append_button( b ): b |= mod l.extend([ 27, ord('['), ord('M'), b+32, x+32, y+32 ]) if ev == 20: # press if b & 4 and last & 1 == 0: append_button( 0 ) next |= 1 if b & 2 and last & 2 == 0: append_button( 1 ) next |= 2 if b & 1 and last & 4 == 0: append_button( 2 ) next |= 4 elif ev == 146: # drag if b & 4: append_button( 0 + escape.MOUSE_DRAG_FLAG ) elif b & 2: append_button( 1 + escape.MOUSE_DRAG_FLAG ) elif b & 1: append_button( 2 + escape.MOUSE_DRAG_FLAG ) else: # release if b & 4 and last & 1: append_button( 0 + escape.MOUSE_RELEASE_FLAG ) next &= ~ 1 if b & 2 and last & 2: append_button( 1 + escape.MOUSE_RELEASE_FLAG ) next &= ~ 2 if b & 1 and last & 4: append_button( 2 + escape.MOUSE_RELEASE_FLAG ) next &= ~ 4 self.last_bstate = next return l def _getch_nodelay(self): return self._getch(0) def get_cols_rows(self): """Return the terminal dimensions (num columns, num rows).""" buf = fcntl.ioctl(0, termios.TIOCGWINSZ, ' '*4) y, x = struct.unpack('hh', buf) self.maxrow = y return x, y def draw_screen(self, (maxcol, maxrow), r ): """Paint screen with rendered canvas.""" assert self._started assert maxrow == r.rows() if self.setup_G1: try: if util._use_dec_special: sys.stdout.write( escape.CURSOR_HOME + escape.DESIGNATE_G1_SPECIAL) sys.stdout.flush() self.setup_G1 = False except IOError, e: pass if self.resized: # handle resize before trying to draw screen return o = [ escape.HIDE_CURSOR, escape.CURSOR_HOME, escape.set_attributes('default','default') ] if self.screen_buf: osb = self.screen_buf else: osb = [] sb = [] ins = None #cy = 0 y = -1 for row in r.content(): y += 1 if osb and osb[y] == row: sb.append( osb[y] ) continue sb.append(row) #if cy != y: o.append( escape.set_cursor_position(0,y) ) #cy = y+1 # will be here after updating this line if y == maxrow-1: row, back, ins = self._last_row(row) first = True lasta = lastcs = None for (a,cs, run) in row: run = run.translate( _trans_table ) assert self.palette.has_key(a), `a` if first or lasta != a: o.append( self.palette[a][0] ) lasta = a if first or lastcs != cs: assert cs in [None, "0"], `cs` if cs is None: o.append( escape.SI ) else: o.append( escape.SO ) lastcs = cs o.append( run ) first = False if ins: (inserta, insertcs, inserttext) = ins ias = self.palette[inserta][0] assert insertcs in [None, "0"], `insertcs` if cs is None: icss = escape.SI else: icss = escape.SO o += [ "\x08"*back, ias, icss, escape.INSERT_ON, inserttext, escape.INSERT_OFF ] if r.cursor is not None: x,y = r.cursor o += [ escape.set_cursor_position( x, y ), escape.SHOW_CURSOR ] if self.resized: # handle resize before trying to draw screen return try: k = 0 for l in o: sys.stdout.write( l ) k += len(l) if k > 100: sys.stdout.flush() k = 0 sys.stdout.flush() except IOError, e: # ignore interrupted syscall if e.args[0] != 4: raise self.screen_buf = sb self.keep_cache_alive_link = r def _last_row(self, row): """On the last row we need to slide the bottom right character into place. Calculate the new line, attr and an insert sequence to do that. eg. last row: XXXXXXXXXXXXXXXXXXXXYZ Y will be drawn after Z, shifting Z into position. """ new_row = row[:-1] z_attr, z_cs, last_text = row[-1] last_cols = util.calc_width(last_text, 0, len(last_text)) last_offs, z_col = util.calc_text_pos(last_text, 0, len(last_text), last_cols-1) if last_offs == 0: z_text = last_text del new_row[-1] # we need another segment y_attr, y_cs, nlast_text = row[-2] nlast_cols = util.calc_width(nlast_text, 0, len(nlast_text)) z_col += nlast_cols nlast_offs, y_col = util.calc_text_pos(nlast_text, 0, len(nlast_text), nlast_cols-1) y_text = nlast_text[nlast_offs:] if nlast_offs: new_row.append((y_attr, y_cs, nlast_text[:nlast_offs])) else: z_text = last_text[last_offs:] y_attr, y_cs = z_attr, z_cs nlast_cols = util.calc_width(last_text, 0, last_offs) nlast_offs, y_col = util.calc_text_pos(last_text, 0, last_offs, nlast_cols-1) y_text = last_text[nlast_offs:last_offs] if nlast_offs: new_row.append((y_attr, y_cs, last_text[:nlast_offs])) new_row.append((z_attr, z_cs, z_text)) return new_row, z_col-y_col, (y_attr, y_cs, y_text) def clear(self): """ Force the screen to be completely repainted on the next call to draw_screen(). """ self.screen_buf = None self.setup_G1 = True
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -