changeset 16610:739d7eb97b85

make blinking cursor and different cursor styles for Windows GUI terminal * QWinTerminalImpl.h, QWinTerminalImpl.cpp (QConsolePrivate::KeyboardCursorType): New enum. (QConsolePrivate::cursorRect): New function. (QConsolePrivate::BLINK_DELAY, QConsolePrivate::m_cursorBlinking, QConsolePrivate::m_blinkCursorTimer, QConsolePrivate::m_cursorType, QConsolePrivate::m_hasBlinkingCursor): New data members. (QConsolePrivate::QConsolePrivate): Initialize m_hasBlinkingCursor and m_cursorType. Create m_blinkCursorTimer. Connect m_blinkCursorTimer::timeout to parent::blinkCursorEvent. (QWinTerminalImpl::viewPaintEvent): Draw new cursor types. Handle blinking cursor. (QWinTerminalImpl::blinkCursorEvent, QWinTerminalImpl::setBlinkingCursor, QWinTerminalImpl::setBlinkingCursorState, QWinTerminalImpl::focusInEvent, QWinTerminalImpl::keyPressEvent, QWinTerminalImpl::setCursorType): New functions. (QWinTerminalImpl::focusInEvent): Call setBlinkingCursorState.
author John W. Eaton <jwe@octave.org>
date Sat, 04 May 2013 00:49:34 -0400
parents 1eeeb2599870
children 6f7940e36322
files libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h
diffstat 2 files changed, 157 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp
+++ b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp
@@ -91,6 +91,14 @@
   friend class QWinTerminalImpl;
 
 public:
+
+  enum KeyboardCursorType
+    {
+      BlockCursor,
+      UnderlineCursor,
+      IBeamCursor
+    };
+
   QConsolePrivate (QWinTerminalImpl* parent, const QString& cmd = QString ());
   ~QConsolePrivate (void);
 
@@ -103,6 +111,7 @@
   void monitorConsole (void);
   void startCommand (void);
   void sendConsoleText (const QString& s);
+  QRect cursorRect (void);
 
   void log (const char* fmt, ...);
 
@@ -126,6 +135,10 @@
   QSize m_bufferSize;
   QRect m_consoleRect;
   QPoint m_cursorPos;
+  bool m_cursorBlinking;
+  bool m_hasBlinkingCursor;
+  QTimer *m_blinkCursorTimer;
+  KeyboardCursorType m_cursorType;
 
   HANDLE m_stdOut;
   HWND m_consoleWindow;
@@ -137,12 +150,16 @@
   QScrollBar* m_scrollBar;
   QTimer* m_consoleWatcher;
   QConsoleThread *m_consoleThread;
+
+  // The delay in milliseconds between redrawing blinking text.
+  static const int BLINK_DELAY = 500;
 };
 
 //////////////////////////////////////////////////////////////////////////////
 
 QConsolePrivate::QConsolePrivate (QWinTerminalImpl* parent, const QString& cmd)
-    : q (parent), m_command (cmd), m_process (NULL), m_inWheelEvent (false)
+  : q (parent), m_command (cmd), m_hasBlinkingCursor (true),
+    m_cursorType (BlockCursor), m_process (NULL), m_inWheelEvent (false)
 {
   log (NULL);
 
@@ -255,7 +272,11 @@
   m_consoleWatcher = new QTimer (parent);
   m_consoleWatcher->setInterval (10);
   m_consoleWatcher->setSingleShot (false);
-  
+
+  m_blinkCursorTimer = new QTimer (parent);
+  QObject::connect (m_blinkCursorTimer, SIGNAL (timeout()),
+                    q, SLOT (blinkCursorEvent ()));  
+
   QObject::connect (m_scrollBar, SIGNAL (valueChanged (int)),
                     q, SLOT (scrollValueChanged (int)));
   QObject::connect (m_consoleWatcher, SIGNAL (timeout (void)),
@@ -700,6 +721,17 @@
     }
 }
 
+QRect
+QConsolePrivate::cursorRect (void)
+{
+  int cw = m_charSize.width ();
+  int ch = m_charSize.height ();
+
+  return QRect ((m_cursorPos.x () - m_consoleRect.x ()) * cw,
+                (m_cursorPos.y () - m_consoleRect.y ()) * ch,
+                cw, ch);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 QWinTerminalImpl::QWinTerminalImpl (QWidget* parent)
@@ -812,11 +844,77 @@
         }
     }
 
-  // Draw cursor
-  p.setCompositionMode (QPainter::RasterOp_SourceXorDestination);
-  p.fillRect ((d->m_cursorPos.x () - d->m_consoleRect.x ()) * cw,
-              (d->m_cursorPos.y () - d->m_consoleRect.y ()) * ch,
-              cw, ch, d->m_colors[7]);
+  if (! d->m_cursorBlinking)
+    {
+      QColor cursorColor = d->m_colors[7];
+      QRect cursorRect = d->cursorRect ();
+
+      p.setPen (d->m_foregroundColor);
+
+      if (d->m_cursorType == QConsolePrivate::BlockCursor)
+        {
+          if (hasFocus ())
+            {
+              p.setCompositionMode (QPainter::RasterOp_SourceXorDestination);
+
+              p.fillRect (cursorRect, cursorColor);
+            }
+          else
+            {
+              // draw the cursor outline, adjusting the area so that
+              // it is draw entirely inside 'rect'
+ 
+              int penWidth = qMax (1, p.pen().width());
+ 
+              p.setBrush (Qt::NoBrush);
+
+              p.drawRect (cursorRect.adjusted (penWidth/2, penWidth/2,
+                                               - penWidth/2 - penWidth%2,
+                                               - penWidth/2 - penWidth%2));
+            }
+        }
+      else if (d->m_cursorType == QConsolePrivate::UnderlineCursor)
+        {
+          p.drawLine (cursorRect.left (), cursorRect.bottom (),
+                      cursorRect.right (), cursorRect.bottom ());
+        }
+      else if (d->m_cursorType == QConsolePrivate::IBeamCursor)
+        {
+          p.drawLine (cursorRect.left (), cursorRect.top (),
+                      cursorRect.left (), cursorRect.bottom ());
+        }
+    }
+}
+
+void QWinTerminalImpl::blinkCursorEvent (void)
+{
+  if (d->m_hasBlinkingCursor)
+    d->m_cursorBlinking = ! d->m_cursorBlinking;
+  else
+    d->m_cursorBlinking = false;
+
+  d->m_consoleView->update (d->cursorRect ());
+}
+
+void QWinTerminalImpl::setBlinkingCursor (bool blink)
+{
+  d->m_hasBlinkingCursor = blink;
+
+  setBlinkingCursorState (blink);
+}
+
+void QWinTerminalImpl::setBlinkingCursorState (bool blink)
+{
+  if (blink && ! d->m_blinkCursorTimer->isActive ())
+    d->m_blinkCursorTimer->start (d->BLINK_DELAY);
+
+  if (! blink && d->m_blinkCursorTimer->isActive ())
+    {
+      d->m_blinkCursorTimer->stop ();
+
+      if (d->m_cursorBlinking)
+        blinkCursorEvent ();
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -871,9 +969,34 @@
 
 void QWinTerminalImpl::focusInEvent (QFocusEvent* event)
 {
+  setBlinkingCursorState (true);
+
   QWidget::focusInEvent (event);
 }
 
+void QWinTerminalImpl::focusOutEvent (QFocusEvent* event)
+{
+  // Force the cursor to be redrawn.
+  d->m_cursorBlinking = true;
+
+  setBlinkingCursorState (false);
+
+  QWidget::focusOutEvent (event);
+}
+
+void QWinTerminalImpl::keyPressEvent (QKeyEvent* event)
+{
+  if (d->m_hasBlinkingCursor)
+    {
+      d->m_blinkCursorTimer->start (d->BLINK_DELAY);
+
+      if (d->m_cursorBlinking)
+        blinkCursorEvent ();
+    }
+
+  QWidget::keyPressEvent (event);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 void QWinTerminalImpl::start (void)
@@ -888,6 +1011,26 @@
   d->sendConsoleText (s);
 }
 
+void QWinTerminalImpl::setCursorType (CursorType type, bool blinking)
+{
+  switch (type)
+    {
+    case UnderlineCursor:
+      d->m_cursorType = QConsolePrivate::UnderlineCursor;
+      break;
+
+    case BlockCursor:
+      d->m_cursorType = QConsolePrivate::BlockCursor;
+      break;
+
+    case IBeamCursor:
+      d->m_cursorType = QConsolePrivate::IBeamCursor;
+      break;
+    }
+
+  setBlinkingCursor (blinking);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 void QWinTerminalImpl::setTerminalFont (const QFont& f)
--- a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h
+++ b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h
@@ -26,6 +26,7 @@
 #include "QTerminalInterface.h"
 class QFocusEvent;
 class QKeyEvent;
+class QPainter;
 class QPaintEvent;
 class QResizeEvent;
 class QWheelEvent;
@@ -51,10 +52,12 @@
   void setTerminalFont (const QFont& font);
   void setSize (int columns, int lines);
   void sendText (const QString& s);
+  void setCursorType (CursorType type, bool blinking);
 
 public slots:
   void copyClipboard (void);
   void pasteClipboard (void);
+  void blinkCursorEvent (void);
 
 signals:
   void terminated (void);
@@ -62,9 +65,13 @@
 
 protected:
   void viewPaintEvent (QConsoleView*, QPaintEvent*);
+  void setBlinkingCursor (bool blink);
+  void setBlinkingCursorState (bool blink);
   void viewResizeEvent (QConsoleView*, QResizeEvent*);
   void wheelEvent (QWheelEvent*);
   void focusInEvent (QFocusEvent*);
+  void focusOutEvent (QFocusEvent*);
+  void keyPressEvent (QKeyEvent*);
   bool winEvent (MSG*, long*);
   virtual void start (void);