DriverSDL: Implement cursor, handle window resize.
authorRadek Brich <radek.brich@devl.cz>
Sun, 06 Jan 2013 13:55:02 +0100
changeset 53 c4263588b716
parent 52 50a1857557da
child 54 86b84535726e
DriverSDL: Implement cursor, handle window resize.
sdlterm/cython/sdlterm.pyx
sdlterm/src/sdlterm.cc
sdlterm/src/sdlterm.h
tuikit/driver_sdl.py
--- a/sdlterm/cython/sdlterm.pyx	Sat Jan 05 23:00:41 2013 +0100
+++ b/sdlterm/cython/sdlterm.pyx	Sun Jan 06 13:55:02 2013 +0100
@@ -45,8 +45,8 @@
         int prepare_attr(int fg, int bg, int style)
         void set_attr(int value)
 
-        void set_cursor(int x, int y)
-        void show_cursor(bool visible)
+        void show_cursor(int x, int y)
+        void hide_cursor()
 
         void get_next_event(Event event)
 
@@ -82,6 +82,11 @@
     def set_attr(self, value):
         self.thisptr.set_attr(value)
 
+    def show_cursor(self, x, y):
+        self.thisptr.show_cursor(x, y)
+    def hide_cursor(self):
+        self.thisptr.hide_cursor()
+
     def get_next_event(self):
         self.thisptr.get_next_event(self.event)
         event = self.event
@@ -101,6 +106,8 @@
             if char == '\x00':
                 char = None
             return ('keypress', keyname, char)
+        if event.type == event.RESIZE:
+            return ('resize',)
         if event.type == event.QUIT:
             return ('quit',)
         return ('unknown',)
--- a/sdlterm/src/sdlterm.cc	Sat Jan 05 23:00:41 2013 +0100
+++ b/sdlterm/src/sdlterm.cc	Sun Jan 06 13:55:02 2013 +0100
@@ -176,7 +176,7 @@
             SDL_LockSurface(cell_surface);
             int y = 1 + TTF_FontAscent(font);
             Uint32 fgcolor_mapped = SDL_MapRGB(cell_surface->format, fgcolor.r, fgcolor.g, fgcolor.b);
-            Uint32 *p = (Uint32 *)(cell_surface->pixels + y * cell_surface->pitch);
+            Uint32 *p = (Uint32 *)((Uint8 *)cell_surface->pixels + y * cell_surface->pitch);
             for (int x = 0; x < _cell_width; x++)
                 *p++ = fgcolor_mapped;
             SDL_UnlockSurface(cell_surface);
@@ -225,8 +225,6 @@
         throw std::exception();
     }
 
-    SDL_WM_SetCaption("terminal", NULL);
-
     _pixel_width = pxwidth;
     _pixel_height = pxheight;
 
@@ -248,6 +246,13 @@
 }
 
 
+void TerminalScreen::toggle_cursor(int x, int y)
+{
+    TerminalCell &cell = _cells_front[y * _width + x];
+    cell.attr ^= (Style::STANDOUT << 24);
+}
+
+
 void TerminalScreen::commit()
 {
     auto front_iter = _cells_front.begin();
@@ -275,6 +280,13 @@
 }
 
 
+void TerminalScreen::redraw()
+{
+    // clear back buffer, current screen is considered blank
+    std::fill(_cells_back.begin(), _cells_back.end(), TerminalCell());
+}
+
+
 void TerminalScreen::_reset_cells()
 {
     _cell_width = _render.get_cell_width();
@@ -289,12 +301,13 @@
 
     int num_cells = _width * _height;
     _cells_front.resize(num_cells, TerminalCell());
-    _cells_back.resize(num_cells, TerminalCell());
+    _cells_back.resize(num_cells);
+    redraw();
 }
 
 
 Terminal::Terminal()
- : _screen(), _attr(7), _mousemove_last_x(-1)
+ : _screen(), _attr(7), _cursor_visible(false), _mousemove_last_x(-1)
 {
     if (SDL_Init(SDL_INIT_VIDEO) == -1)
     {
@@ -302,6 +315,7 @@
         throw std::exception();
     }
     SDL_EnableUNICODE(1);
+    SDL_WM_SetCaption("terminal", NULL);
 }
 
 
@@ -311,6 +325,20 @@
 }
 
 
+void Terminal::commit()
+{
+    if (_cursor_visible)
+    {
+        _screen.toggle_cursor(_cursor_x, _cursor_y);
+        _screen.commit();
+        _screen.toggle_cursor(_cursor_x, _cursor_y);
+    }
+    else
+    {
+        _screen.commit();
+    }
+}
+
 void Terminal::get_next_event(Event &event)
 {
     static SDL_Event sdl_event;
@@ -323,6 +351,15 @@
                 event.type = Event::QUIT;
                 return;
 
+            case SDL_VIDEORESIZE:
+                event.type = Event::RESIZE;
+                _screen.resize(sdl_event.resize.w, sdl_event.resize.h);
+                return;
+
+            case SDL_VIDEOEXPOSE:
+                _screen.redraw();
+                break;
+
             case SDL_KEYDOWN:
             {
                 //switch(event.key.keysym.sym)
@@ -354,6 +391,8 @@
                 return;
 
             case SDL_MOUSEMOTION:
+                if (sdl_event.motion.state == 0)
+                    break; // continue loop, do not report move events when no button is pressed
                 event.type = Event::MOUSEMOVE;
                 event.mouse.x = sdl_event.motion.x / _screen.get_cell_width();
                 event.mouse.y = sdl_event.motion.y / _screen.get_cell_height();
--- a/sdlterm/src/sdlterm.h	Sat Jan 05 23:00:41 2013 +0100
+++ b/sdlterm/src/sdlterm.h	Sun Jan 06 13:55:02 2013 +0100
@@ -37,7 +37,7 @@
     };
 
 public:
-    void index_to_rgb(int index, SDL_Color &color);
+    void index_to_rgb(int index, SDL_Color &color) const;
 };
 
 
@@ -66,8 +66,8 @@
     // do not free surface returned!
     SDL_Surface *render_cell(Uint32 ch, Uint32 attr);
 
-    int get_cell_width() { return _cell_width; };
-    int get_cell_height() { return _cell_height; };
+    int get_cell_width() const { return _cell_width; };
+    int get_cell_height() const { return _cell_height; };
 
 private:
     TTF_Font *_font_regular;
@@ -100,6 +100,8 @@
 {
     Uint32 ch;
     Uint32 attr;
+
+    TerminalCell() : ch(0), attr(7) {};
     bool operator !=(const TerminalCell &rhs) const { return ch != rhs.ch || attr != rhs.attr; };
 };
 
@@ -118,12 +120,16 @@
 
     void erase();
     void putch(int x, int y, Uint32 ch, Uint32 attr);
+    void toggle_cursor(int x, int y);
     void commit();
 
-    int get_width() { return _width; };
-    int get_height() { return _height; };
-    int get_cell_width() { return _cell_width; };
-    int get_cell_height() { return _cell_height; };
+    // force full redraw on next commit()
+    void redraw();
+
+    int get_width() const { return _width; };
+    int get_height() const { return _height; };
+    int get_cell_width() const { return _cell_width; };
+    int get_cell_height() const { return _cell_height; };
 
 private:
     SDL_Surface *_screen_surface;
@@ -175,18 +181,18 @@
 
     void erase() { _screen.erase(); };
     void putch(int x, int y, Uint32 ch) { _screen.putch(x, y, ch, _attr); };
-    void commit() { _screen.commit(); };
+    void commit();
 
     Uint32 prepare_attr(Uint8 fg, Uint8 bg, Uint8 style) { return (Uint32)fg | (Uint32)bg << 8 | (Uint32)style << 24; };
     void set_attr(Uint32 value) { _attr = value; };
 
-    void set_cursor(int x, int y) { _cursor_x = x; _cursor_y = y; };
-    void show_cursor(bool visible) { _cursor_visible = visible; };
+    void show_cursor(int x, int y) { _cursor_x = x; _cursor_y = y; _cursor_visible = true; };
+    void hide_cursor() { _cursor_visible = false; };
 
     void get_next_event(Event &event);
 
-    int get_width() { return _screen.get_width(); };
-    int get_height() { return _screen.get_height(); };
+    int get_width() const { return _screen.get_width(); };
+    int get_height() const { return _screen.get_height(); };
 
 private:
     TerminalScreen _screen;
--- a/tuikit/driver_sdl.py	Sat Jan 05 23:00:41 2013 +0100
+++ b/tuikit/driver_sdl.py	Sun Jan 06 13:55:02 2013 +0100
@@ -67,6 +67,8 @@
     def getevents(self, timeout=None):
         '''Process input, return list of events.'''
         event = self.sdlterm.get_next_event()
+        if event[0] == 'resize':
+            self.size.w, self.size.h = self.sdlterm.width, self.sdlterm.height
         return [event]
 
 
@@ -139,11 +141,13 @@
 
     def showcursor(self, x, y):
         '''Set cursor to be shown at x, y coordinates.'''
-        self.log.info('DummyDriver.showcursor(x=%r, y=%r)', x, y)
+        if not self.clipstack.test(x, y):
+            return
+        self.sdlterm.show_cursor(x, y)
 
     def hidecursor(self):
         '''Hide cursor.'''
-        self.log.info('DummyDriver.hidecursor()')
+        self.sdlterm.hide_cursor()
 
 
 driverclass = DriverSDL