# HG changeset patch # User John W. Eaton # Date 1367642974 14400 # Node ID 739d7eb97b85b36f117ba9b3933cdf42eea24d51 # Parent 1eeeb2599870d129f06d537086319b0160c00899 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. diff --git a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp --- 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) diff --git a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h --- 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);