1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <Qt5Widget.hxx>
21 #include <Qt5Widget.moc>
23 #include <Qt5Frame.hxx>
24 #include <Qt5Graphics.hxx>
25 #include <Qt5Instance.hxx>
26 #include <Qt5SvpGraphics.hxx>
27 #include <Qt5Transferable.hxx>
28 #include <Qt5Tools.hxx>
30 #include <QtCore/QMimeData>
31 #include <QtGui/QDrag>
32 #include <QtGui/QFocusEvent>
33 #include <QtGui/QGuiApplication>
34 #include <QtGui/QImage>
35 #include <QtGui/QKeyEvent>
36 #include <QtGui/QMouseEvent>
37 #include <QtGui/QPainter>
38 #include <QtGui/QPaintEvent>
39 #include <QtGui/QResizeEvent>
40 #include <QtGui/QShowEvent>
41 #include <QtGui/QTextCharFormat>
42 #include <QtGui/QWheelEvent>
43 #include <QtWidgets/QMainWindow>
44 #include <QtWidgets/QWidget>
47 #include <vcl/commandevent.hxx>
48 #include <vcl/event.hxx>
50 #include <tools/diagnose_ex.h>
52 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
53 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
57 #include <X11/keysymdef.h>
60 using namespace com::sun::star
;
62 void Qt5Widget::paintEvent(QPaintEvent
* pEvent
)
65 if (!m_rFrame
.m_bNullRegion
)
66 p
.setClipRegion(m_rFrame
.m_aRegion
);
69 if (m_rFrame
.m_bUseCairo
)
71 cairo_surface_t
* pSurface
= m_rFrame
.m_pSurface
.get();
72 cairo_surface_flush(pSurface
);
74 aImage
= QImage(cairo_image_surface_get_data(pSurface
),
75 cairo_image_surface_get_width(pSurface
),
76 cairo_image_surface_get_height(pSurface
), Qt5_DefaultFormat32
);
79 aImage
= *m_rFrame
.m_pQImage
;
81 const qreal fRatio
= m_rFrame
.devicePixelRatioF();
82 aImage
.setDevicePixelRatio(fRatio
);
83 QRectF
source(pEvent
->rect().topLeft() * fRatio
, pEvent
->rect().size() * fRatio
);
84 p
.drawImage(pEvent
->rect(), aImage
, source
);
87 void Qt5Widget::resizeEvent(QResizeEvent
* pEvent
)
89 const qreal fRatio
= m_rFrame
.devicePixelRatioF();
90 const int nWidth
= ceil(pEvent
->size().width() * fRatio
);
91 const int nHeight
= ceil(pEvent
->size().height() * fRatio
);
93 m_rFrame
.maGeometry
.nWidth
= nWidth
;
94 m_rFrame
.maGeometry
.nHeight
= nHeight
;
96 if (m_rFrame
.m_bUseCairo
)
98 if (m_rFrame
.m_pSvpGraphics
)
100 cairo_surface_t
* pSurface
101 = cairo_image_surface_create(CAIRO_FORMAT_ARGB32
, nWidth
, nHeight
);
102 cairo_surface_set_user_data(pSurface
, SvpSalGraphics::getDamageKey(),
103 &m_rFrame
.m_aDamageHandler
, nullptr);
104 m_rFrame
.m_pSvpGraphics
->setSurface(pSurface
, basegfx::B2IVector(nWidth
, nHeight
));
105 UniqueCairoSurface
old_surface(m_rFrame
.m_pSurface
.release());
106 m_rFrame
.m_pSurface
.reset(pSurface
);
108 int min_width
= qMin(cairo_image_surface_get_width(old_surface
.get()), nWidth
);
109 int min_height
= qMin(cairo_image_surface_get_height(old_surface
.get()), nHeight
);
111 SalTwoRect
rect(0, 0, min_width
, min_height
, 0, 0, min_width
, min_height
);
113 m_rFrame
.m_pSvpGraphics
->copySource(rect
, old_surface
.get());
118 QImage
* pImage
= nullptr;
120 if (m_rFrame
.m_pQImage
)
121 pImage
= new QImage(m_rFrame
.m_pQImage
->copy(0, 0, nWidth
, nHeight
));
124 pImage
= new QImage(nWidth
, nHeight
, Qt5_DefaultFormat32
);
125 pImage
->fill(Qt::transparent
);
128 m_rFrame
.m_pQt5Graphics
->ChangeQImage(pImage
);
129 m_rFrame
.m_pQImage
.reset(pImage
);
132 m_rFrame
.CallCallback(SalEvent::Resize
, nullptr);
135 void Qt5Widget::fillSalAbstractMouseEvent(const Qt5Frame
& rFrame
, const QInputEvent
* pQEvent
,
136 const QPoint
& rPos
, Qt::MouseButtons eButtons
, int nWidth
,
137 SalAbstractMouseEvent
& aSalEvent
)
139 const qreal fRatio
= rFrame
.devicePixelRatioF();
140 const Point aPos
= toPoint(rPos
* fRatio
);
142 aSalEvent
.mnX
= QGuiApplication::isLeftToRight() ? aPos
.X() : round(nWidth
* fRatio
) - aPos
.X();
143 aSalEvent
.mnY
= aPos
.Y();
144 aSalEvent
.mnTime
= pQEvent
->timestamp();
145 aSalEvent
.mnCode
= GetKeyModCode(pQEvent
->modifiers()) | GetMouseModCode(eButtons
);
148 #define FILL_SAME(rFrame, nWidth) \
149 fillSalAbstractMouseEvent(rFrame, pEvent, pEvent->pos(), pEvent->buttons(), nWidth, aEvent)
151 void Qt5Widget::handleMouseButtonEvent(const Qt5Frame
& rFrame
, const QMouseEvent
* pEvent
,
152 const ButtonKeyState eState
)
154 SalMouseEvent aEvent
;
155 FILL_SAME(rFrame
, rFrame
.GetQWidget()->width());
157 switch (pEvent
->button())
160 aEvent
.mnButton
= MOUSE_LEFT
;
162 case Qt::MiddleButton
:
163 aEvent
.mnButton
= MOUSE_MIDDLE
;
165 case Qt::RightButton
:
166 aEvent
.mnButton
= MOUSE_RIGHT
;
173 if (eState
== ButtonKeyState::Pressed
)
174 nEventType
= SalEvent::MouseButtonDown
;
176 nEventType
= SalEvent::MouseButtonUp
;
177 rFrame
.CallCallback(nEventType
, &aEvent
);
180 void Qt5Widget::mousePressEvent(QMouseEvent
* pEvent
) { handleMousePressEvent(m_rFrame
, pEvent
); }
182 void Qt5Widget::mouseReleaseEvent(QMouseEvent
* pEvent
)
184 handleMouseReleaseEvent(m_rFrame
, pEvent
);
187 void Qt5Widget::mouseMoveEvent(QMouseEvent
* pEvent
)
189 SalMouseEvent aEvent
;
190 FILL_SAME(m_rFrame
, width());
194 m_rFrame
.CallCallback(SalEvent::MouseMove
, &aEvent
);
198 void Qt5Widget::wheelEvent(QWheelEvent
* pEvent
)
200 SalWheelMouseEvent aEvent
;
201 #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
202 fillSalAbstractMouseEvent(m_rFrame
, pEvent
, pEvent
->position().toPoint(), pEvent
->buttons(),
205 fillSalAbstractMouseEvent(m_rFrame
, pEvent
, pEvent
->pos(), pEvent
->buttons(), width(), aEvent
);
208 // mouse wheel ticks are 120, which we map to 3 lines.
209 // we have to accumulate for touch scroll to keep track of the absolute delta.
211 int nDelta
= pEvent
->angleDelta().y(), lines
;
212 aEvent
.mbHorz
= nDelta
== 0;
215 nDelta
= (QGuiApplication::isLeftToRight() ? 1 : -1) * pEvent
->angleDelta().x();
220 lines
= m_nDeltaX
/ 40;
221 m_nDeltaX
= m_nDeltaX
% 40;
226 lines
= m_nDeltaY
/ 40;
227 m_nDeltaY
= m_nDeltaY
% 40;
230 aEvent
.mnDelta
= nDelta
;
231 aEvent
.mnNotchDelta
= nDelta
< 0 ? -1 : 1;
232 aEvent
.mnScrollLines
= std::abs(lines
);
234 m_rFrame
.CallCallback(SalEvent::WheelMouse
, &aEvent
);
238 void Qt5Widget::dragEnterEvent(QDragEnterEvent
* event
)
240 if (dynamic_cast<const Qt5MimeData
*>(event
->mimeData()))
243 event
->acceptProposedAction();
246 // also called when a drop is rejected
247 void Qt5Widget::dragLeaveEvent(QDragLeaveEvent
*) { m_rFrame
.handleDragLeave(); }
249 void Qt5Widget::dragMoveEvent(QDragMoveEvent
* pEvent
) { m_rFrame
.handleDragMove(pEvent
); }
251 void Qt5Widget::dropEvent(QDropEvent
* pEvent
) { m_rFrame
.handleDrop(pEvent
); }
253 void Qt5Widget::moveEvent(QMoveEvent
* pEvent
)
255 if (m_rFrame
.m_pTopLevel
)
258 const Point aPos
= toPoint(pEvent
->pos() * m_rFrame
.devicePixelRatioF());
259 m_rFrame
.maGeometry
.nX
= aPos
.X();
260 m_rFrame
.maGeometry
.nY
= aPos
.Y();
261 m_rFrame
.CallCallback(SalEvent::Move
, nullptr);
264 void Qt5Widget::showEvent(QShowEvent
*)
266 QSize
aSize(m_rFrame
.GetQWidget()->size() * m_rFrame
.devicePixelRatioF());
267 // forcing an immediate update somehow interferes with the hide + show
268 // sequence from Qt5Frame::SetModal, if the frame was already set visible,
269 // resulting in a hidden / unmapped window
270 SalPaintEvent
aPaintEvt(0, 0, aSize
.width(), aSize
.height());
271 m_rFrame
.CallCallback(SalEvent::Paint
, &aPaintEvt
);
274 void Qt5Widget::closeEvent(QCloseEvent
* /*pEvent*/)
276 m_rFrame
.CallCallback(SalEvent::Close
, nullptr);
279 static sal_uInt16
GetKeyCode(int keyval
, Qt::KeyboardModifiers modifiers
)
281 sal_uInt16 nCode
= 0;
282 if (keyval
>= Qt::Key_0
&& keyval
<= Qt::Key_9
)
283 nCode
= KEY_0
+ (keyval
- Qt::Key_0
);
284 else if (keyval
>= Qt::Key_A
&& keyval
<= Qt::Key_Z
)
285 nCode
= KEY_A
+ (keyval
- Qt::Key_A
);
286 else if (keyval
>= Qt::Key_F1
&& keyval
<= Qt::Key_F26
)
287 nCode
= KEY_F1
+ (keyval
- Qt::Key_F1
);
288 else if (modifiers
.testFlag(Qt::KeypadModifier
)
289 && (keyval
== Qt::Key_Period
|| keyval
== Qt::Key_Comma
))
290 // Qt doesn't use a special keyval for decimal separator ("," or ".")
291 // on numerical keypad, but sets Qt::KeypadModifier in addition
318 case Qt::Key_PageDown
:
319 nCode
= KEY_PAGEDOWN
;
329 // oddly enough, Qt doesn't send Shift-Tab event as 'Tab key pressed with Shift
330 // modifier' but as 'Backtab key pressed' (while its modifier bits are still
331 // set to Shift) -- so let's map both Key_Tab and Key_Backtab to VCL's KEY_TAB
332 case Qt::Key_Backtab
:
335 case Qt::Key_Backspace
:
336 nCode
= KEY_BACKSPACE
;
351 nCode
= KEY_SUBTRACT
;
353 case Qt::Key_Asterisk
:
354 nCode
= KEY_MULTIPLY
;
368 case Qt::Key_Greater
:
378 nCode
= KEY_CONTEXTMENU
;
392 case Qt::Key_AsciiTilde
:
395 case Qt::Key_QuoteLeft
:
396 nCode
= KEY_QUOTELEFT
;
398 case Qt::Key_BracketLeft
:
399 nCode
= KEY_BRACKETLEFT
;
401 case Qt::Key_BracketRight
:
402 nCode
= KEY_BRACKETRIGHT
;
404 case Qt::Key_Semicolon
:
405 nCode
= KEY_SEMICOLON
;
425 void Qt5Widget::commitText(Qt5Frame
& rFrame
, const QString
& aText
)
427 SalExtTextInputEvent aInputEvent
;
428 aInputEvent
.mpTextAttr
= nullptr;
429 aInputEvent
.mnCursorFlags
= 0;
430 aInputEvent
.maText
= toOUString(aText
);
431 aInputEvent
.mnCursorPos
= aInputEvent
.maText
.getLength();
433 SolarMutexGuard aGuard
;
434 vcl::DeletionListener
aDel(&rFrame
);
435 rFrame
.CallCallback(SalEvent::ExtTextInput
, &aInputEvent
);
436 if (!aDel
.isDeleted())
437 rFrame
.CallCallback(SalEvent::EndExtTextInput
, nullptr);
440 bool Qt5Widget::handleKeyEvent(Qt5Frame
& rFrame
, const QWidget
& rWidget
, QKeyEvent
* pEvent
,
441 const ButtonKeyState eState
)
443 sal_uInt16 nCode
= GetKeyCode(pEvent
->key(), pEvent
->modifiers());
444 if (eState
== ButtonKeyState::Pressed
&& nCode
== 0 && pEvent
->text().length() > 1
445 && rWidget
.testAttribute(Qt::WA_InputMethodEnabled
))
447 commitText(rFrame
, pEvent
->text());
452 if (nCode
== 0 && pEvent
->text().isEmpty())
454 sal_uInt16 nModCode
= GetKeyModCode(pEvent
->modifiers());
455 SalKeyModEvent aModEvt
;
456 aModEvt
.mbDown
= eState
== ButtonKeyState::Pressed
;
457 aModEvt
.mnModKeyCode
= ModKeyFlags::NONE
;
460 if (QGuiApplication::platformName() == "xcb")
462 // pressing just the ctrl key leads to a keysym of XK_Control but
463 // the event state does not contain ControlMask. In the release
464 // event it's the other way round: it does contain the Control mask.
465 // The modifier mode therefore has to be adapted manually.
466 ModKeyFlags nExtModMask
= ModKeyFlags::NONE
;
467 sal_uInt16 nModMask
= 0;
468 switch (pEvent
->nativeVirtualKey())
471 nExtModMask
= ModKeyFlags::LeftMod1
;
475 nExtModMask
= ModKeyFlags::RightMod1
;
479 nExtModMask
= ModKeyFlags::LeftMod2
;
483 nExtModMask
= ModKeyFlags::RightMod2
;
487 nExtModMask
= ModKeyFlags::LeftShift
;
488 nModMask
= KEY_SHIFT
;
491 nExtModMask
= ModKeyFlags::RightShift
;
492 nModMask
= KEY_SHIFT
;
494 // Map Meta/Super keys to MOD3 modifier on all Unix systems
498 nExtModMask
= ModKeyFlags::LeftMod3
;
503 nExtModMask
= ModKeyFlags::RightMod3
;
508 if (eState
== ButtonKeyState::Released
)
510 // sending the old mnModKeyCode mask on release is needed to
511 // implement the writing direction switch with Ctrl + L/R-Shift
512 aModEvt
.mnModKeyCode
= rFrame
.m_nKeyModifiers
;
513 nModCode
&= ~nModMask
;
514 rFrame
.m_nKeyModifiers
&= ~nExtModMask
;
518 nModCode
|= nModMask
;
519 rFrame
.m_nKeyModifiers
|= nExtModMask
;
520 aModEvt
.mnModKeyCode
= rFrame
.m_nKeyModifiers
;
524 aModEvt
.mnCode
= nModCode
;
526 rFrame
.CallCallback(SalEvent::KeyModChange
, &aModEvt
);
530 // prevent interference of writing direction switch (Ctrl + L/R-Shift) with "normal" shortcuts
531 rFrame
.m_nKeyModifiers
= ModKeyFlags::NONE
;
534 aEvent
.mnCharCode
= (pEvent
->text().isEmpty() ? 0 : pEvent
->text().at(0).unicode());
536 aEvent
.mnCode
= nCode
;
537 aEvent
.mnCode
|= GetKeyModCode(pEvent
->modifiers());
539 QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle
);
541 bool bStopProcessingKey
;
542 if (eState
== ButtonKeyState::Pressed
)
543 bStopProcessingKey
= rFrame
.CallCallback(SalEvent::KeyInput
, &aEvent
);
545 bStopProcessingKey
= rFrame
.CallCallback(SalEvent::KeyUp
, &aEvent
);
546 if (bStopProcessingKey
)
548 return bStopProcessingKey
;
551 bool Qt5Widget::handleEvent(Qt5Frame
& rFrame
, const QWidget
& rWidget
, QEvent
* pEvent
)
553 if (pEvent
->type() == QEvent::ShortcutOverride
)
555 // ignore non-spontaneous QEvent::ShortcutOverride events,
556 // since such an extra event is sent e.g. with Orca screen reader enabled,
557 // so that two events of that kind (the "real one" and a non-spontaneous one)
558 // would otherwise be processed, resulting in duplicate input as 'handleKeyEvent'
559 // is called below (s. tdf#122053)
560 if (!pEvent
->spontaneous())
565 // Accepted event disables shortcut activation,
566 // but enables keypress event.
567 // If event is not accepted and shortcut is successfully activated,
568 // KeyPress event is omitted.
570 // Instead of processing keyPressEvent, handle ShortcutOverride event,
571 // and if it's handled - disable the shortcut, it should have been activated.
572 // Don't process keyPressEvent generated after disabling shortcut since it was handled here.
573 // If event is not handled, don't accept it and let Qt activate related shortcut.
574 if (handleKeyEvent(rFrame
, rWidget
, static_cast<QKeyEvent
*>(pEvent
),
575 ButtonKeyState::Pressed
))
581 bool Qt5Widget::event(QEvent
* pEvent
)
583 return handleEvent(m_rFrame
, *this, pEvent
) || QWidget::event(pEvent
);
586 void Qt5Widget::keyReleaseEvent(QKeyEvent
* pEvent
)
588 if (!handleKeyReleaseEvent(m_rFrame
, *this, pEvent
))
589 QWidget::keyReleaseEvent(pEvent
);
592 void Qt5Widget::focusInEvent(QFocusEvent
*) { m_rFrame
.CallCallback(SalEvent::GetFocus
, nullptr); }
594 void Qt5Widget::focusOutEvent(QFocusEvent
*)
596 m_rFrame
.m_nKeyModifiers
= ModKeyFlags::NONE
;
598 m_rFrame
.CallCallback(SalEvent::LoseFocus
, nullptr);
601 Qt5Widget::Qt5Widget(Qt5Frame
& rFrame
, Qt::WindowFlags f
)
602 : QWidget(Q_NULLPTR
, f
)
604 , m_bNonEmptyIMPreeditSeen(false)
609 setMouseTracking(true);
610 setFocusPolicy(Qt::StrongFocus
);
613 static ExtTextInputAttr
lcl_MapUndrelineStyle(QTextCharFormat::UnderlineStyle us
)
617 case QTextCharFormat::NoUnderline
:
618 return ExtTextInputAttr::NONE
;
619 case QTextCharFormat::DotLine
:
620 return ExtTextInputAttr::DottedUnderline
;
621 case QTextCharFormat::DashDotDotLine
:
622 case QTextCharFormat::DashDotLine
:
623 return ExtTextInputAttr::DashDotUnderline
;
624 case QTextCharFormat::WaveUnderline
:
625 return ExtTextInputAttr::GrayWaveline
;
627 return ExtTextInputAttr::Underline
;
631 void Qt5Widget::inputMethodEvent(QInputMethodEvent
* pEvent
)
633 if (!pEvent
->commitString().isEmpty())
634 commitText(m_rFrame
, pEvent
->commitString());
637 SalExtTextInputEvent aInputEvent
;
638 aInputEvent
.mpTextAttr
= nullptr;
639 aInputEvent
.mnCursorFlags
= 0;
640 aInputEvent
.maText
= toOUString(pEvent
->preeditString());
641 aInputEvent
.mnCursorPos
= 0;
643 const sal_Int32 nLength
= aInputEvent
.maText
.getLength();
644 const QList
<QInputMethodEvent::Attribute
>& rAttrList
= pEvent
->attributes();
645 std::vector
<ExtTextInputAttr
> aTextAttrs(std::max(sal_Int32(1), nLength
),
646 ExtTextInputAttr::NONE
);
647 aInputEvent
.mpTextAttr
= aTextAttrs
.data();
649 for (int i
= 0; i
< rAttrList
.size(); ++i
)
651 const QInputMethodEvent::Attribute
& rAttr
= rAttrList
.at(i
);
654 case QInputMethodEvent::TextFormat
:
656 QTextCharFormat aCharFormat
657 = qvariant_cast
<QTextFormat
>(rAttr
.value
).toCharFormat();
658 if (aCharFormat
.isValid())
660 ExtTextInputAttr aETIP
661 = lcl_MapUndrelineStyle(aCharFormat
.underlineStyle());
662 if (aCharFormat
.hasProperty(QTextFormat::BackgroundBrush
))
663 aETIP
|= ExtTextInputAttr::Highlight
;
664 if (aCharFormat
.fontStrikeOut())
665 aETIP
|= ExtTextInputAttr::RedText
;
666 for (int j
= rAttr
.start
; j
< rAttr
.start
+ rAttr
.length
; j
++)
667 aTextAttrs
[j
] = aETIP
;
671 case QInputMethodEvent::Cursor
:
673 aInputEvent
.mnCursorPos
= rAttr
.start
;
674 if (rAttr
.length
== 0)
675 aInputEvent
.mnCursorFlags
|= EXTTEXTINPUT_CURSOR_INVISIBLE
;
679 SAL_WARN("vcl.qt5", "Unhandled QInputMethodEvent attribute: "
680 << static_cast<int>(rAttr
.type
));
685 const bool bIsEmpty
= aInputEvent
.maText
.isEmpty();
686 if (m_bNonEmptyIMPreeditSeen
|| !bIsEmpty
)
688 SolarMutexGuard aGuard
;
689 vcl::DeletionListener
aDel(&m_rFrame
);
690 m_rFrame
.CallCallback(SalEvent::ExtTextInput
, &aInputEvent
);
691 if (!aDel
.isDeleted() && bIsEmpty
)
692 m_rFrame
.CallCallback(SalEvent::EndExtTextInput
, nullptr);
693 m_bNonEmptyIMPreeditSeen
= !bIsEmpty
;
700 static bool lcl_retrieveSurrounding(sal_Int32
& rPosition
, sal_Int32
& rAnchor
, QString
* pText
,
703 SolarMutexGuard aGuard
;
704 vcl::Window
* pFocusWin
= Application::GetFocusWindow();
708 uno::Reference
<accessibility::XAccessibleEditableText
> xText
;
711 uno::Reference
<accessibility::XAccessible
> xAccessible(pFocusWin
->GetAccessible());
712 if (xAccessible
.is())
713 xText
= FindFocusedEditableText(xAccessible
->getAccessibleContext());
715 catch (const uno::Exception
&)
717 TOOLS_WARN_EXCEPTION("vcl.qt5", "Exception in getting input method surrounding text");
722 rPosition
= xText
->getCaretPosition();
726 *pText
= toQString(xText
->getText());
728 sal_Int32 nSelStart
= xText
->getSelectionStart();
729 sal_Int32 nSelEnd
= xText
->getSelectionEnd();
730 if (nSelStart
== nSelEnd
)
736 if (rPosition
== nSelStart
)
741 *pSelection
= toQString(xText
->getSelectedText());
750 QVariant
Qt5Widget::inputMethodQuery(Qt::InputMethodQuery property
) const
754 case Qt::ImSurroundingText
:
757 sal_Int32 nCursorPos
, nAnchor
;
758 if (lcl_retrieveSurrounding(nCursorPos
, nAnchor
, &aText
, nullptr))
759 return QVariant(aText
);
762 case Qt::ImCursorPosition
:
764 sal_Int32 nCursorPos
, nAnchor
;
765 if (lcl_retrieveSurrounding(nCursorPos
, nAnchor
, nullptr, nullptr))
766 return QVariant(static_cast<int>(nCursorPos
));
769 case Qt::ImCursorRectangle
:
771 const qreal fRatio
= m_rFrame
.devicePixelRatioF();
772 SalExtTextInputPosEvent aPosEvent
;
773 m_rFrame
.CallCallback(SalEvent::ExtTextInputPos
, &aPosEvent
);
774 return QVariant(QRect(aPosEvent
.mnX
/ fRatio
, aPosEvent
.mnY
/ fRatio
,
775 aPosEvent
.mnWidth
/ fRatio
, aPosEvent
.mnHeight
/ fRatio
));
777 case Qt::ImAnchorPosition
:
779 sal_Int32 nCursorPos
, nAnchor
;
780 if (lcl_retrieveSurrounding(nCursorPos
, nAnchor
, nullptr, nullptr))
781 return QVariant(static_cast<int>(nAnchor
));
784 case Qt::ImCurrentSelection
:
787 sal_Int32 nCursorPos
, nAnchor
;
788 if (lcl_retrieveSurrounding(nCursorPos
, nAnchor
, nullptr, &aSelection
))
789 return QVariant(aSelection
);
793 return QWidget::inputMethodQuery(property
);
797 void Qt5Widget::endExtTextInput()
799 if (m_bNonEmptyIMPreeditSeen
)
801 m_rFrame
.CallCallback(SalEvent::EndExtTextInput
, nullptr);
802 m_bNonEmptyIMPreeditSeen
= false;
806 void Qt5Widget::changeEvent(QEvent
* pEvent
)
808 switch (pEvent
->type())
810 case QEvent::FontChange
:
812 case QEvent::PaletteChange
:
814 case QEvent::StyleChange
:
816 auto* pSalInst(static_cast<Qt5Instance
*>(GetSalData()->m_pInstance
));
818 pSalInst
->UpdateStyle(QEvent::FontChange
== pEvent
->type());
824 QWidget::changeEvent(pEvent
);
827 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */