diff --git a/src/TerminalDisplay.h b/src/TerminalDisplay.h --- a/src/TerminalDisplay.h +++ b/src/TerminalDisplay.h @@ -946,7 +946,6 @@ // than 'columns' if the character image provided with setImage() is smaller // than the maximum image size which can be displayed - QRect _contentRect; Character *_image; // [lines][columns] // only the area [usedLines][usedColumns] in the image contains valid data diff --git a/src/TerminalDisplay.cpp b/src/TerminalDisplay.cpp --- a/src/TerminalDisplay.cpp +++ b/src/TerminalDisplay.cpp @@ -406,7 +406,6 @@ , _columns(1) , _usedLines(1) , _usedColumns(1) - , _contentRect(QRect()) , _image(nullptr) , _imageSize(0) , _lineProperties(QVector()) @@ -476,12 +475,12 @@ , _searchBar(new IncrementalSearchBar(this)) , _searchResultRect(QRect()) { + setContentsMargins(_margin, _margin, _margin, _margin); + // terminal applications are not designed with Right-To-Left in mind, // so the layout is forced to Left-To-Right setLayoutDirection(Qt::LeftToRight); - _contentRect = QRect(_margin, _margin, 1, 1); - // create scroll bar for scrolling output up and down _scrollBar = new QScrollBar(this); _scrollBar->setAutoFillBackground(false); @@ -1282,7 +1281,7 @@ void* firstCharPos = &_image[ region.top() * _columns ]; void* lastCharPos = &_image[(region.top() + abs(lines)) * _columns ]; - const int top = _contentRect.top() + (region.top() * _fontHeight); + const int top = contentsRect().top() + (region.top() * _fontHeight); const int linesToMove = region.height() - abs(lines); const int bytesToMove = linesToMove * _columns * sizeof(Character); @@ -1416,9 +1415,7 @@ int y, x, len; - const QPoint tL = contentsRect().topLeft(); - const int tLx = tL.x(); - const int tLy = tL.y(); + const QPoint topLeft = contentsRect().topLeft(); _hasTextBlinker = false; CharacterColor cf; // undefined @@ -1520,8 +1517,8 @@ // add the area occupied by this line to the region which needs to be // repainted - QRect dirtyRect = QRect(_contentRect.left() + tLx , - _contentRect.top() + tLy + _fontHeight * y , + QRect dirtyRect = QRect(topLeft.x(), + topLeft.y() + _fontHeight * y , _fontWidth * columnsToUpdate , _fontHeight); @@ -1536,16 +1533,16 @@ // if the new _image is smaller than the previous _image, then ensure that the area // outside the new _image is cleared if (linesToUpdate < _usedLines) { - dirtyRegion |= QRect(_contentRect.left() + tLx , - _contentRect.top() + tLy + _fontHeight * linesToUpdate , + dirtyRegion |= QRect(topLeft.x(), + topLeft.y() + _fontHeight * linesToUpdate , _fontWidth * _columns , _fontHeight * (_usedLines - linesToUpdate)); } _usedLines = linesToUpdate; if (columnsToUpdate < _usedColumns) { - dirtyRegion |= QRect(_contentRect.left() + tLx + columnsToUpdate * _fontWidth , - _contentRect.top() + tLy , + dirtyRegion |= QRect(topLeft.x() + columnsToUpdate * _fontWidth , + topLeft.y(), _fontWidth * (_usedColumns - columnsToUpdate) , _fontHeight * _lines); } @@ -1557,7 +1554,7 @@ // De-highlight previous result region dirtyRegion |= _searchResultRect; // Highlight new result region - dirtyRegion |= QRect(0, _contentRect.top() + (_screenWindow->currentResultLine() - _screenWindow->currentLine()) * _fontHeight, + dirtyRegion |= QRect(0, contentsRect().top() + (_screenWindow->currentResultLine() - _screenWindow->currentLine()) * _fontHeight, _columns * _fontWidth, _fontHeight); } _screenWindow->resetScrollCount(); @@ -1614,24 +1611,25 @@ // Determine which characters should be repainted (1 region unit = 1 character) QRegion dirtyImageRegion; - foreach(const QRect & rect, (pe->region() & contentsRect()).rects()) { + for (const QRect &rect : (pe->region() & rect()).rects()) { dirtyImageRegion += widgetToImage(rect); drawBackground(paint, rect, getBackgroundColor(), true /* use opacity setting */); } paint.setRenderHint(QPainter::Antialiasing, _antialiasText); - foreach(const QRect & rect, dirtyImageRegion.rects()) { + for (const QRect &rect : dirtyImageRegion.rects()) { drawContents(paint, rect); } + drawCurrentResultRect(paint); drawInputMethodPreeditString(paint, preeditRect()); paintFilters(paint); const bool drawDimmed = _dimWhenInactive && !hasFocus(); - const QColor dimColor(0, 0, 0, 128); - foreach(const QRect & rect, (pe->region() & contentsRect()).rects()) { - if (drawDimmed) { + if (drawDimmed) { + const QColor dimColor(0, 0, 0, 128); + for (const QRect &rect : (pe->region() & rect()).rects()) { paint.fillRect(rect, dimColor); } } @@ -1714,28 +1712,28 @@ if (spot->type() == Filter::HotSpot::Link) { QRect r; if (spot->startLine() == spot->endLine()) { - r.setCoords(spot->startColumn()*_fontWidth + _contentRect.left(), - spot->startLine()*_fontHeight + _contentRect.top(), - (spot->endColumn())*_fontWidth + _contentRect.left() - 1, - (spot->endLine() + 1)*_fontHeight + _contentRect.top() - 1); + r.setCoords(spot->startColumn()*_fontWidth + contentsRect().left(), + spot->startLine()*_fontHeight + contentsRect().top(), + (spot->endColumn())*_fontWidth + contentsRect().left() - 1, + (spot->endLine() + 1)*_fontHeight + contentsRect().top() - 1); region |= r; } else { - r.setCoords(spot->startColumn()*_fontWidth + _contentRect.left(), - spot->startLine()*_fontHeight + _contentRect.top(), - (_columns)*_fontWidth + _contentRect.left() - 1, - (spot->startLine() + 1)*_fontHeight + _contentRect.top() - 1); + r.setCoords(spot->startColumn()*_fontWidth + contentsRect().left(), + spot->startLine()*_fontHeight + contentsRect().top(), + (_columns)*_fontWidth + contentsRect().left() - 1, + (spot->startLine() + 1)*_fontHeight + contentsRect().top() - 1); region |= r; for (int line = spot->startLine() + 1 ; line < spot->endLine() ; line++) { - r.setCoords(0 * _fontWidth + _contentRect.left(), - line * _fontHeight + _contentRect.top(), - (_columns)*_fontWidth + _contentRect.left() - 1, - (line + 1)*_fontHeight + _contentRect.top() - 1); + r.setCoords(0 * _fontWidth + contentsRect().left(), + line * _fontHeight + contentsRect().top(), + (_columns)*_fontWidth + contentsRect().left() - 1, + (line + 1)*_fontHeight + contentsRect().top() - 1); region |= r; } - r.setCoords(0 * _fontWidth + _contentRect.left(), - spot->endLine()*_fontHeight + _contentRect.top(), - (spot->endColumn())*_fontWidth + _contentRect.left() - 1, - (spot->endLine() + 1)*_fontHeight + _contentRect.top() - 1); + r.setCoords(0 * _fontWidth + contentsRect().left(), + spot->endLine()*_fontHeight + contentsRect().top(), + (spot->endColumn())*_fontWidth + contentsRect().left() - 1, + (spot->endLine() + 1)*_fontHeight + contentsRect().top() - 1); region |= r; } @@ -1789,10 +1787,10 @@ // because the check below for the position of the cursor // finds it on the border of the target area QRect r; - r.setCoords(startColumn * _fontWidth + _contentRect.left(), - line * _fontHeight + _contentRect.top(), - endColumn * _fontWidth + _contentRect.left() - 1, - (line + 1)*_fontHeight + _contentRect.top() - 1); + r.setCoords(startColumn * _fontWidth + contentsRect().left(), + line * _fontHeight + contentsRect().top(), + endColumn * _fontWidth + contentsRect().left() - 1, + (line + 1)*_fontHeight + contentsRect().top() - 1); // Underline link hotspots if (spot->type() == Filter::HotSpot::Link) { QFontMetrics metrics(font()); @@ -1960,8 +1958,8 @@ paint.setWorldMatrix(textScale, true); //calculate the area in which the text will be drawn - QRect textArea = QRect(_contentRect.left() + contentsRect().left() + _fontWidth * x, - _contentRect.top() + contentsRect().top() + _fontHeight * y, + QRect textArea = QRect(contentsRect().left() + _fontWidth * x, + contentsRect().top() + _fontHeight * y, _fontWidth * len, _fontHeight); @@ -2015,7 +2013,7 @@ return; } - _searchResultRect.setRect(0, _contentRect.top() + (_screenWindow->currentResultLine() - _screenWindow->currentLine()) * _fontHeight, + _searchResultRect.setRect(0, contentsRect().top() + (_screenWindow->currentResultLine() - _screenWindow->currentLine()) * _fontHeight, _columns * _fontWidth, _fontHeight); painter.fillRect(_searchResultRect, QColor(0, 0, 255, 80)); } @@ -2023,8 +2021,8 @@ QRect TerminalDisplay::imageToWidget(const QRect& imageArea) const { QRect result; - result.setLeft(_contentRect.left() + _fontWidth * imageArea.left()); - result.setTop(_contentRect.top() + _fontHeight * imageArea.top()); + result.setLeft(contentsRect().left() + _fontWidth * imageArea.left()); + result.setTop(contentsRect().top() + _fontHeight * imageArea.top()); result.setWidth(_fontWidth * imageArea.width()); result.setHeight(_fontHeight * imageArea.height()); @@ -2034,10 +2032,10 @@ QRect TerminalDisplay::widgetToImage(const QRect &widgetArea) const { QRect result; - result.setLeft( qMin(_usedColumns - 1, qMax(0, (widgetArea.left() - contentsRect().left() - _contentRect.left()) / _fontWidth ))); - result.setTop( qMin(_usedLines - 1, qMax(0, (widgetArea.top() - contentsRect().top() - _contentRect.top() ) / _fontHeight))); - result.setRight( qMin(_usedColumns - 1, qMax(0, (widgetArea.right() - contentsRect().left() - _contentRect.left()) / _fontWidth ))); - result.setBottom(qMin(_usedLines - 1, qMax(0, (widgetArea.bottom() - contentsRect().top() - _contentRect.top() ) / _fontHeight))); + result.setLeft( qMin(_usedColumns - 1, qMax(0, (widgetArea.left() - contentsRect().left()) / _fontWidth ))); + result.setTop( qMin(_usedLines - 1, qMax(0, (widgetArea.top() - contentsRect().top() ) / _fontHeight))); + result.setRight( qMin(_usedColumns - 1, qMax(0, (widgetArea.right() - contentsRect().left()) / _fontWidth ))); + result.setBottom(qMin(_usedLines - 1, qMax(0, (widgetArea.bottom() - contentsRect().top() ) / _fontHeight))); return result; } @@ -2163,6 +2161,11 @@ void TerminalDisplay::resizeEvent(QResizeEvent *event) { + // We get resize events even when we change our internal margins, so ignore these + if (event->oldSize() == event->size()) { + return; + } + const auto width = event->size().width() - _scrollBar->geometry().width(); _searchBar->correctPosition(QSize(width, event->size().height())); if (contentsRect().isValid()) { @@ -2205,7 +2208,7 @@ if (_resizing) { showResizeNotification(); - emit changedContentSizeSignal(_contentRect.height(), _contentRect.width()); // expose resizeEvent + emit changedContentSizeSignal(contentsRect().height(), contentsRect().width()); // expose resizeEvent } _resizing = false; @@ -2238,34 +2241,57 @@ void TerminalDisplay::calcGeometry() { - _scrollBar->resize(_scrollBar->sizeHint().width(), contentsRect().height()); - _contentRect = contentsRect().adjusted(_margin, _margin, -_margin, -_margin); + QMargins margins(_margin, _margin, _margin, _margin); + const int scrollbarWidth = _scrollBar->sizeHint().width(); switch (_scrollbarLocation) { - case Enum::ScrollBarHidden : - break; - case Enum::ScrollBarLeft : - _contentRect.setLeft(_contentRect.left() + _scrollBar->width()); - _scrollBar->move(contentsRect().topLeft()); + case Enum::ScrollBarLeft: + margins.setLeft(_margin + scrollbarWidth); break; case Enum::ScrollBarRight: - _contentRect.setRight(_contentRect.right() - _scrollBar->width()); - _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width() - 1, 0)); + margins.setRight(_margin + scrollbarWidth); + break; + case Enum::ScrollBarHidden: + default: break; } + setContentsMargins(margins); + // ensure that display is always at least one column wide - _columns = qMax(1, _contentRect.width() / _fontWidth); + _columns = qMax(1, contentsRect().width() / _fontWidth); _usedColumns = qMin(_usedColumns, _columns); // ensure that display is always at least one line high - _lines = qMax(1, _contentRect.height() / _fontHeight); + _lines = qMax(1, contentsRect().height() / _fontHeight); _usedLines = qMin(_usedLines, _lines); if(_centerContents) { - QSize unusedPixels = _contentRect.size() - QSize(_columns * _fontWidth, _lines * _fontHeight); - _contentRect.adjust(unusedPixels.width() / 2, unusedPixels.height() / 2, 0, 0); + QSize unusedPixels = contentsRect().size() - QSize(_columns * _fontWidth, _lines * _fontHeight); + + if (unusedPixels.width() > 0) { + margins.setLeft(margins.left() + unusedPixels.width() / 2); + } + if (unusedPixels.height() > 0) { + margins.setTop(margins.top() + unusedPixels.height() / 2); + } + + setContentsMargins(margins); } + + switch (_scrollbarLocation) { + case Enum::ScrollBarLeft: + _scrollBar->move(0, 0); + break; + case Enum::ScrollBarRight: + _scrollBar->move(contentsRect().right(), 0); + break; + case Enum::ScrollBarHidden: + default: + break; + } + + _scrollBar->resize(scrollbarWidth, height()); } // calculate the needed size, this must be synced with calcGeometry() @@ -2297,11 +2323,11 @@ void TerminalDisplay::showEvent(QShowEvent*) { propagateSize(); - emit changedContentSizeSignal(_contentRect.height(), _contentRect.width()); + emit changedContentSizeSignal(contentsRect().height(), contentsRect().width()); } void TerminalDisplay::hideEvent(QHideEvent*) { - emit changedContentSizeSignal(_contentRect.height(), _contentRect.width()); + emit changedContentSizeSignal(contentsRect().height(), contentsRect().width()); } void TerminalDisplay::setMargin(int margin) @@ -2529,28 +2555,28 @@ _mouseOverHotspotArea = QRegion(); QRect r; if (spot->startLine() == spot->endLine()) { - r.setCoords(spot->startColumn()*_fontWidth + _contentRect.left(), - spot->startLine()*_fontHeight + _contentRect.top(), - (spot->endColumn())*_fontWidth + _contentRect.left() - 1, - (spot->endLine() + 1)*_fontHeight + _contentRect.top() - 1); + r.setCoords(spot->startColumn()*_fontWidth + contentsRect().left(), + spot->startLine()*_fontHeight + contentsRect().top(), + (spot->endColumn())*_fontWidth + contentsRect().left() - 1, + (spot->endLine() + 1)*_fontHeight + contentsRect().top() - 1); _mouseOverHotspotArea |= r; } else { - r.setCoords(spot->startColumn()*_fontWidth + _contentRect.left(), - spot->startLine()*_fontHeight + _contentRect.top(), - (_columns)*_fontWidth + _contentRect.left() - 1, - (spot->startLine() + 1)*_fontHeight + _contentRect.top() - 1); + r.setCoords(spot->startColumn()*_fontWidth + contentsRect().left(), + spot->startLine()*_fontHeight + contentsRect().top(), + (_columns)*_fontWidth + contentsRect().left() - 1, + (spot->startLine() + 1)*_fontHeight + contentsRect().top() - 1); _mouseOverHotspotArea |= r; for (int line = spot->startLine() + 1 ; line < spot->endLine() ; line++) { - r.setCoords(0 * _fontWidth + _contentRect.left(), - line * _fontHeight + _contentRect.top(), - (_columns)*_fontWidth + _contentRect.left() - 1, - (line + 1)*_fontHeight + _contentRect.top() - 1); + r.setCoords(0 * _fontWidth + contentsRect().left(), + line * _fontHeight + contentsRect().top(), + (_columns)*_fontWidth + contentsRect().left() - 1, + (line + 1)*_fontHeight + contentsRect().top() - 1); _mouseOverHotspotArea |= r; } - r.setCoords(0 * _fontWidth + _contentRect.left(), - spot->endLine()*_fontHeight + _contentRect.top(), - (spot->endColumn())*_fontWidth + _contentRect.left() - 1, - (spot->endLine() + 1)*_fontHeight + _contentRect.top() - 1); + r.setCoords(0 * _fontWidth + contentsRect().left(), + spot->endLine()*_fontHeight + contentsRect().top(), + (spot->endColumn())*_fontWidth + contentsRect().left() - 1, + (spot->endLine() + 1)*_fontHeight + contentsRect().top() - 1); _mouseOverHotspotArea |= r; } @@ -2643,10 +2669,6 @@ return; } - //if ( !contentsRect().contains(ev->pos()) ) return; - const QPoint tL = contentsRect().topLeft(); - const int tLx = tL.x(); - const int tLy = tL.y(); const int scroll = _scrollBar->value(); // we're in the process of moving the mouse with the left button pressed @@ -2655,10 +2677,8 @@ int linesBeyondWidget = 0; - QRect textBounds(tLx + _contentRect.left(), - tLy + _contentRect.top(), - _usedColumns * _fontWidth - 1, - _usedLines * _fontHeight - 1); + const QPoint textBottomRight(_usedColumns * _fontWidth - _margin, _usedLines * _fontHeight - _margin); + QRect textBounds(contentsRect().topLeft(), textBottomRight); QPoint pos = position; @@ -2846,8 +2866,8 @@ // column (or left-most for right-to-left input) const int columnMax = edge ? _usedColumns : _usedColumns - 1; const int xOffset = edge ? _fontWidth / 2 : 0; - column = qBound(0, (widgetPoint.x() + xOffset - contentsRect().left() - _contentRect.left()) / _fontWidth, columnMax); - line = qBound(0, (widgetPoint.y() - contentsRect().top() - _contentRect.top()) / _fontHeight, _usedLines - 1); + column = qBound(0, (widgetPoint.x() + xOffset - contentsRect().left()) / _fontWidth, columnMax); + line = qBound(0, (widgetPoint.y() - contentsRect().top()) / _fontHeight, _usedLines - 1); } void TerminalDisplay::updateLineProperties() @@ -3642,12 +3662,12 @@ if (preeditLength == 0) { return {}; } - const QRect stringRect(_contentRect.left() + _fontWidth * cursorPosition().x(), - _contentRect.top() + _fontHeight * cursorPosition().y(), + const QRect stringRect(contentsRect().left() + _fontWidth * cursorPosition().x(), + contentsRect().top() + _fontHeight * cursorPosition().y(), _fontWidth * preeditLength, _fontHeight); - return stringRect.intersected(_contentRect); + return stringRect.intersected(contentsRect()); } void TerminalDisplay::drawInputMethodPreeditString(QPainter& painter , const QRect& rect)