bump product version to 6.4.0.3
[LibreOffice.git] / vcl / qt5 / Qt5Widget.cxx
blob70f480364f5722d86484f06b1ad8475eaf520a3d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
46 #include <cairo.h>
47 #include <vcl/commandevent.hxx>
48 #include <vcl/event.hxx>
49 #include <window.h>
50 #include <tools/diagnose_ex.h>
52 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
53 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
55 using namespace com::sun::star;
57 void Qt5Widget::paintEvent(QPaintEvent* pEvent)
59 QPainter p(this);
60 if (!m_rFrame.m_bNullRegion)
61 p.setClipRegion(m_rFrame.m_aRegion);
63 if (m_rFrame.m_bUseCairo)
65 cairo_surface_t* pSurface = m_rFrame.m_pSurface.get();
66 cairo_surface_flush(pSurface);
68 QImage aImage(cairo_image_surface_get_data(pSurface), size().width(), size().height(),
69 Qt5_DefaultFormat32);
70 p.drawImage(pEvent->rect().topLeft(), aImage, pEvent->rect());
72 else
73 p.drawImage(pEvent->rect().topLeft(), *m_rFrame.m_pQImage, pEvent->rect());
76 void Qt5Widget::resizeEvent(QResizeEvent* pEvent)
78 const int nWidth = pEvent->size().width();
79 const int nHeight = pEvent->size().height();
81 m_rFrame.maGeometry.nWidth = nWidth;
82 m_rFrame.maGeometry.nHeight = nHeight;
84 if (m_rFrame.m_bUseCairo)
86 if (m_rFrame.m_pSvpGraphics)
88 cairo_surface_t* pSurface
89 = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, nWidth, nHeight);
90 cairo_surface_set_user_data(pSurface, SvpSalGraphics::getDamageKey(),
91 &m_rFrame.m_aDamageHandler, nullptr);
92 m_rFrame.m_pSvpGraphics->setSurface(pSurface, basegfx::B2IVector(nWidth, nHeight));
93 UniqueCairoSurface old_surface(m_rFrame.m_pSurface.release());
94 m_rFrame.m_pSurface.reset(pSurface);
96 int min_width = qMin(pEvent->oldSize().width(), nWidth);
97 int min_height = qMin(pEvent->oldSize().height(), nHeight);
99 SalTwoRect rect(0, 0, min_width, min_height, 0, 0, min_width, min_height);
101 m_rFrame.m_pSvpGraphics->copySource(rect, old_surface.get());
104 else
106 QImage* pImage = nullptr;
108 if (m_rFrame.m_pQImage)
109 pImage = new QImage(m_rFrame.m_pQImage->copy(0, 0, nWidth, nHeight));
110 else
112 pImage = new QImage(nWidth, nHeight, Qt5_DefaultFormat32);
113 pImage->fill(Qt::transparent);
116 m_rFrame.m_pQt5Graphics->ChangeQImage(pImage);
117 m_rFrame.m_pQImage.reset(pImage);
120 m_rFrame.CallCallback(SalEvent::Resize, nullptr);
123 void Qt5Widget::handleMouseButtonEvent(const Qt5Frame& rFrame, const QMouseEvent* pEvent,
124 const ButtonKeyState eState)
126 SalMouseEvent aEvent;
127 switch (pEvent->button())
129 case Qt::LeftButton:
130 aEvent.mnButton = MOUSE_LEFT;
131 break;
132 case Qt::MidButton:
133 aEvent.mnButton = MOUSE_MIDDLE;
134 break;
135 case Qt::RightButton:
136 aEvent.mnButton = MOUSE_RIGHT;
137 break;
138 default:
139 return;
142 aEvent.mnTime = pEvent->timestamp();
143 aEvent.mnX = static_cast<long>(QGuiApplication::isLeftToRight()
144 ? pEvent->pos().x()
145 : rFrame.GetQWidget()->width() - pEvent->pos().x());
146 aEvent.mnY = static_cast<long>(pEvent->pos().y());
147 aEvent.mnCode = GetKeyModCode(pEvent->modifiers()) | GetMouseModCode(pEvent->buttons());
149 SalEvent nEventType;
150 if (eState == ButtonKeyState::Pressed)
151 nEventType = SalEvent::MouseButtonDown;
152 else
153 nEventType = SalEvent::MouseButtonUp;
154 rFrame.CallCallback(nEventType, &aEvent);
157 void Qt5Widget::mousePressEvent(QMouseEvent* pEvent) { handleMousePressEvent(m_rFrame, pEvent); }
159 void Qt5Widget::mouseReleaseEvent(QMouseEvent* pEvent)
161 handleMouseReleaseEvent(m_rFrame, pEvent);
164 void Qt5Widget::mouseMoveEvent(QMouseEvent* pEvent)
166 QPoint point = pEvent->pos();
168 SalMouseEvent aEvent;
169 aEvent.mnTime = pEvent->timestamp();
170 aEvent.mnX = QGuiApplication::isLeftToRight() ? point.x() : width() - point.x();
171 aEvent.mnY = point.y();
172 aEvent.mnCode = GetKeyModCode(pEvent->modifiers()) | GetMouseModCode(pEvent->buttons());
173 aEvent.mnButton = 0;
175 m_rFrame.CallCallback(SalEvent::MouseMove, &aEvent);
176 pEvent->accept();
179 void Qt5Widget::wheelEvent(QWheelEvent* pEvent)
181 SalWheelMouseEvent aEvent;
183 aEvent.mnTime = pEvent->timestamp();
184 aEvent.mnX = pEvent->pos().x();
185 aEvent.mnY = pEvent->pos().y();
186 aEvent.mnCode = GetKeyModCode(pEvent->modifiers()) | GetMouseModCode(pEvent->buttons());
188 // mouse wheel ticks are 120, which we map to 3 lines.
189 // we have to accumulate for touch scroll to keep track of the absolute delta.
191 int nDelta = pEvent->angleDelta().y(), lines;
192 aEvent.mbHorz = nDelta == 0;
193 if (aEvent.mbHorz)
195 nDelta = (QGuiApplication::isLeftToRight() ? 1 : -1) * pEvent->angleDelta().x();
196 if (!nDelta)
197 return;
199 m_nDeltaX += nDelta;
200 lines = m_nDeltaX / 40;
201 m_nDeltaX = m_nDeltaX % 40;
203 else
205 m_nDeltaY += nDelta;
206 lines = m_nDeltaY / 40;
207 m_nDeltaY = m_nDeltaY % 40;
210 aEvent.mnDelta = nDelta;
211 aEvent.mnNotchDelta = nDelta < 0 ? -1 : 1;
212 aEvent.mnScrollLines = std::abs(lines);
214 m_rFrame.CallCallback(SalEvent::WheelMouse, &aEvent);
215 pEvent->accept();
218 void Qt5Widget::dragEnterEvent(QDragEnterEvent* event)
220 if (dynamic_cast<const Qt5MimeData*>(event->mimeData()))
221 event->accept();
222 else
223 event->acceptProposedAction();
226 // also called when a drop is rejected
227 void Qt5Widget::dragLeaveEvent(QDragLeaveEvent*) { m_rFrame.handleDragLeave(); }
229 void Qt5Widget::dragMoveEvent(QDragMoveEvent* pEvent) { m_rFrame.handleDragMove(pEvent); }
231 void Qt5Widget::dropEvent(QDropEvent* pEvent) { m_rFrame.handleDrop(pEvent); }
233 void Qt5Widget::moveEvent(QMoveEvent* pEvent)
235 if (m_rFrame.m_pTopLevel)
236 return;
238 m_rFrame.maGeometry.nX = pEvent->pos().x();
239 m_rFrame.maGeometry.nY = pEvent->pos().y();
240 m_rFrame.CallCallback(SalEvent::Move, nullptr);
243 void Qt5Widget::showEvent(QShowEvent*)
245 QSize aSize(m_rFrame.GetQWidget()->size());
246 // forcing an immediate update somehow interferes with the hide + show
247 // sequence from Qt5Frame::SetModal, if the frame was already set visible,
248 // resulting in a hidden / unmapped window
249 SalPaintEvent aPaintEvt(0, 0, aSize.width(), aSize.height());
250 m_rFrame.CallCallback(SalEvent::Paint, &aPaintEvt);
253 void Qt5Widget::closeEvent(QCloseEvent* /*pEvent*/)
255 m_rFrame.CallCallback(SalEvent::Close, nullptr);
258 static sal_uInt16 GetKeyCode(int keyval, Qt::KeyboardModifiers modifiers)
260 sal_uInt16 nCode = 0;
261 if (keyval >= Qt::Key_0 && keyval <= Qt::Key_9)
262 nCode = KEY_0 + (keyval - Qt::Key_0);
263 else if (keyval >= Qt::Key_A && keyval <= Qt::Key_Z)
264 nCode = KEY_A + (keyval - Qt::Key_A);
265 else if (keyval >= Qt::Key_F1 && keyval <= Qt::Key_F26)
266 nCode = KEY_F1 + (keyval - Qt::Key_F1);
267 else if (modifiers.testFlag(Qt::KeypadModifier)
268 && (keyval == Qt::Key_Period || keyval == Qt::Key_Comma))
269 // Qt doesn't use a special keyval for decimal separator ("," or ".")
270 // on numerical keypad, but sets Qt::KeypadModifier in addition
271 nCode = KEY_DECIMAL;
272 else
274 switch (keyval)
276 case Qt::Key_Down:
277 nCode = KEY_DOWN;
278 break;
279 case Qt::Key_Up:
280 nCode = KEY_UP;
281 break;
282 case Qt::Key_Left:
283 nCode = KEY_LEFT;
284 break;
285 case Qt::Key_Right:
286 nCode = KEY_RIGHT;
287 break;
288 case Qt::Key_Home:
289 nCode = KEY_HOME;
290 break;
291 case Qt::Key_End:
292 nCode = KEY_END;
293 break;
294 case Qt::Key_PageUp:
295 nCode = KEY_PAGEUP;
296 break;
297 case Qt::Key_PageDown:
298 nCode = KEY_PAGEDOWN;
299 break;
300 case Qt::Key_Return:
301 case Qt::Key_Enter:
302 nCode = KEY_RETURN;
303 break;
304 case Qt::Key_Escape:
305 nCode = KEY_ESCAPE;
306 break;
307 case Qt::Key_Tab:
308 // oddly enough, Qt doesn't send Shift-Tab event as 'Tab key pressed with Shift
309 // modifier' but as 'Backtab key pressed' (while its modifier bits are still
310 // set to Shift) -- so let's map both Key_Tab and Key_Backtab to VCL's KEY_TAB
311 case Qt::Key_Backtab:
312 nCode = KEY_TAB;
313 break;
314 case Qt::Key_Backspace:
315 nCode = KEY_BACKSPACE;
316 break;
317 case Qt::Key_Space:
318 nCode = KEY_SPACE;
319 break;
320 case Qt::Key_Insert:
321 nCode = KEY_INSERT;
322 break;
323 case Qt::Key_Delete:
324 nCode = KEY_DELETE;
325 break;
326 case Qt::Key_Plus:
327 nCode = KEY_ADD;
328 break;
329 case Qt::Key_Minus:
330 nCode = KEY_SUBTRACT;
331 break;
332 case Qt::Key_Asterisk:
333 nCode = KEY_MULTIPLY;
334 break;
335 case Qt::Key_Slash:
336 nCode = KEY_DIVIDE;
337 break;
338 case Qt::Key_Period:
339 nCode = KEY_POINT;
340 break;
341 case Qt::Key_Comma:
342 nCode = KEY_COMMA;
343 break;
344 case Qt::Key_Less:
345 nCode = KEY_LESS;
346 break;
347 case Qt::Key_Greater:
348 nCode = KEY_GREATER;
349 break;
350 case Qt::Key_Equal:
351 nCode = KEY_EQUAL;
352 break;
353 case Qt::Key_Find:
354 nCode = KEY_FIND;
355 break;
356 case Qt::Key_Menu:
357 nCode = KEY_CONTEXTMENU;
358 break;
359 case Qt::Key_Help:
360 nCode = KEY_HELP;
361 break;
362 case Qt::Key_Undo:
363 nCode = KEY_UNDO;
364 break;
365 case Qt::Key_Redo:
366 nCode = KEY_REPEAT;
367 break;
368 case Qt::Key_Cancel:
369 nCode = KEY_F11;
370 break;
371 case Qt::Key_AsciiTilde:
372 nCode = KEY_TILDE;
373 break;
374 case Qt::Key_QuoteLeft:
375 nCode = KEY_QUOTELEFT;
376 break;
377 case Qt::Key_BracketLeft:
378 nCode = KEY_BRACKETLEFT;
379 break;
380 case Qt::Key_BracketRight:
381 nCode = KEY_BRACKETRIGHT;
382 break;
383 case Qt::Key_Semicolon:
384 nCode = KEY_SEMICOLON;
385 break;
386 case Qt::Key_Copy:
387 nCode = KEY_COPY;
388 break;
389 case Qt::Key_Cut:
390 nCode = KEY_CUT;
391 break;
392 case Qt::Key_Open:
393 nCode = KEY_OPEN;
394 break;
395 case Qt::Key_Paste:
396 nCode = KEY_PASTE;
397 break;
401 return nCode;
404 void Qt5Widget::commitText(Qt5Frame& rFrame, const QString& aText)
406 SalExtTextInputEvent aInputEvent;
407 aInputEvent.mpTextAttr = nullptr;
408 aInputEvent.mnCursorFlags = 0;
409 aInputEvent.maText = toOUString(aText);
410 aInputEvent.mnCursorPos = aInputEvent.maText.getLength();
412 SolarMutexGuard aGuard;
413 vcl::DeletionListener aDel(&rFrame);
414 rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
415 if (!aDel.isDeleted())
416 rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
419 bool Qt5Widget::handleKeyEvent(Qt5Frame& rFrame, const QWidget& rWidget, QKeyEvent* pEvent,
420 const ButtonKeyState eState)
422 sal_uInt16 nCode = GetKeyCode(pEvent->key(), pEvent->modifiers());
423 if (eState == ButtonKeyState::Pressed && nCode == 0 && !pEvent->text().isEmpty()
424 && rWidget.testAttribute(Qt::WA_InputMethodEnabled))
426 commitText(rFrame, pEvent->text());
427 pEvent->accept();
428 return true;
431 SalKeyEvent aEvent;
432 aEvent.mnCharCode = (pEvent->text().isEmpty() ? 0 : pEvent->text().at(0).unicode());
433 aEvent.mnRepeat = 0;
434 aEvent.mnCode = nCode;
435 aEvent.mnCode |= GetKeyModCode(pEvent->modifiers());
437 QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle);
439 bool bStopProcessingKey;
440 if (eState == ButtonKeyState::Pressed)
441 bStopProcessingKey = rFrame.CallCallback(SalEvent::KeyInput, &aEvent);
442 else
443 bStopProcessingKey = rFrame.CallCallback(SalEvent::KeyUp, &aEvent);
444 if (bStopProcessingKey)
445 pEvent->accept();
446 return bStopProcessingKey;
449 bool Qt5Widget::handleEvent(Qt5Frame& rFrame, const QWidget& rWidget, QEvent* pEvent)
451 if (pEvent->type() == QEvent::ShortcutOverride)
453 // Accepted event disables shortcut activation,
454 // but enables keypress event.
455 // If event is not accepted and shortcut is successfully activated,
456 // KeyPress event is omitted.
458 // Instead of processing keyPressEvent, handle ShortcutOverride event,
459 // and if it's handled - disable the shortcut, it should have been activated.
460 // Don't process keyPressEvent generated after disabling shortcut since it was handled here.
461 // If event is not handled, don't accept it and let Qt activate related shortcut.
462 if (handleKeyEvent(rFrame, rWidget, static_cast<QKeyEvent*>(pEvent),
463 ButtonKeyState::Pressed))
464 return true;
466 return false;
469 bool Qt5Widget::event(QEvent* pEvent)
471 return handleEvent(m_rFrame, *this, pEvent) || QWidget::event(pEvent);
474 void Qt5Widget::keyReleaseEvent(QKeyEvent* pEvent)
476 if (!handleKeyReleaseEvent(m_rFrame, *this, pEvent))
477 QWidget::keyReleaseEvent(pEvent);
480 void Qt5Widget::focusInEvent(QFocusEvent*) { m_rFrame.CallCallback(SalEvent::GetFocus, nullptr); }
482 void Qt5Widget::focusOutEvent(QFocusEvent*)
484 endExtTextInput();
485 m_rFrame.CallCallback(SalEvent::LoseFocus, nullptr);
488 Qt5Widget::Qt5Widget(Qt5Frame& rFrame, Qt::WindowFlags f)
489 : QWidget(Q_NULLPTR, f)
490 , m_rFrame(rFrame)
491 , m_bNonEmptyIMPreeditSeen(false)
492 , m_nDeltaX(0)
493 , m_nDeltaY(0)
495 create();
496 setMouseTracking(true);
497 setFocusPolicy(Qt::StrongFocus);
500 static ExtTextInputAttr lcl_MapUndrelineStyle(QTextCharFormat::UnderlineStyle us)
502 switch (us)
504 case QTextCharFormat::NoUnderline:
505 return ExtTextInputAttr::NONE;
506 case QTextCharFormat::DotLine:
507 return ExtTextInputAttr::DottedUnderline;
508 case QTextCharFormat::DashDotDotLine:
509 case QTextCharFormat::DashDotLine:
510 return ExtTextInputAttr::DashDotUnderline;
511 case QTextCharFormat::WaveUnderline:
512 return ExtTextInputAttr::GrayWaveline;
513 default:
514 return ExtTextInputAttr::Underline;
518 void Qt5Widget::inputMethodEvent(QInputMethodEvent* pEvent)
520 if (!pEvent->commitString().isEmpty())
521 commitText(m_rFrame, pEvent->commitString());
522 else
524 SalExtTextInputEvent aInputEvent;
525 aInputEvent.mpTextAttr = nullptr;
526 aInputEvent.mnCursorFlags = 0;
527 aInputEvent.maText = toOUString(pEvent->preeditString());
528 aInputEvent.mnCursorPos = 0;
530 const sal_Int32 nLength = aInputEvent.maText.getLength();
531 const QList<QInputMethodEvent::Attribute>& rAttrList = pEvent->attributes();
532 std::vector<ExtTextInputAttr> aTextAttrs(std::max(sal_Int32(1), nLength),
533 ExtTextInputAttr::NONE);
534 aInputEvent.mpTextAttr = aTextAttrs.data();
536 for (int i = 0; i < rAttrList.size(); ++i)
538 const QInputMethodEvent::Attribute& rAttr = rAttrList.at(i);
539 switch (rAttr.type)
541 case QInputMethodEvent::TextFormat:
543 QTextCharFormat aCharFormat
544 = qvariant_cast<QTextFormat>(rAttr.value).toCharFormat();
545 if (aCharFormat.isValid())
547 ExtTextInputAttr aETIP
548 = lcl_MapUndrelineStyle(aCharFormat.underlineStyle());
549 if (aCharFormat.hasProperty(QTextFormat::BackgroundBrush))
550 aETIP |= ExtTextInputAttr::Highlight;
551 if (aCharFormat.fontStrikeOut())
552 aETIP |= ExtTextInputAttr::RedText;
553 for (int j = rAttr.start; j < rAttr.start + rAttr.length; j++)
554 aTextAttrs[j] = aETIP;
556 break;
558 case QInputMethodEvent::Cursor:
560 aInputEvent.mnCursorPos = rAttr.start;
561 if (rAttr.length == 0)
562 aInputEvent.mnCursorFlags |= EXTTEXTINPUT_CURSOR_INVISIBLE;
563 break;
565 default:
566 SAL_WARN("vcl.qt5", "Unhandled QInputMethodEvent attribute: "
567 << static_cast<int>(rAttr.type));
568 break;
572 const bool bIsEmpty = aInputEvent.maText.isEmpty();
573 if (m_bNonEmptyIMPreeditSeen || !bIsEmpty)
575 SolarMutexGuard aGuard;
576 vcl::DeletionListener aDel(&m_rFrame);
577 m_rFrame.CallCallback(SalEvent::ExtTextInput, &aInputEvent);
578 if (!aDel.isDeleted() && bIsEmpty)
579 m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
580 m_bNonEmptyIMPreeditSeen = !bIsEmpty;
584 pEvent->accept();
587 static bool lcl_retrieveSurrounding(sal_Int32& rPosition, sal_Int32& rAnchor, QString* pText,
588 QString* pSelection)
590 SolarMutexGuard aGuard;
591 vcl::Window* pFocusWin = Application::GetFocusWindow();
592 if (!pFocusWin)
593 return false;
595 uno::Reference<accessibility::XAccessibleEditableText> xText;
598 uno::Reference<accessibility::XAccessible> xAccessible(pFocusWin->GetAccessible());
599 if (xAccessible.is())
600 xText = FindFocusedEditableText(xAccessible->getAccessibleContext());
602 catch (const uno::Exception&)
604 TOOLS_WARN_EXCEPTION("vcl.qt5", "Exception in getting input method surrounding text");
607 bool result = false;
608 if (xText.is())
610 rPosition = xText->getCaretPosition();
611 if (rPosition != -1)
613 result = true;
614 if (pText)
615 *pText = toQString(xText->getText());
617 sal_Int32 nSelStart = xText->getSelectionStart();
618 sal_Int32 nSelEnd = xText->getSelectionEnd();
619 if (nSelStart == nSelEnd)
621 rAnchor = rPosition;
622 if (pSelection)
623 result = false;
625 else
627 if (rPosition == nSelStart)
628 rAnchor = nSelEnd;
629 else
630 rAnchor = nSelStart;
631 if (pSelection)
632 *pSelection = toQString(xText->getSelectedText());
634 return true;
638 return result;
641 QVariant Qt5Widget::inputMethodQuery(Qt::InputMethodQuery property) const
643 switch (property)
645 case Qt::ImSurroundingText:
647 QString aText;
648 sal_Int32 nCursorPos, nAnchor;
649 if (lcl_retrieveSurrounding(nCursorPos, nAnchor, &aText, nullptr))
650 return QVariant(aText);
651 [[fallthrough]];
653 case Qt::ImCursorPosition:
655 sal_Int32 nCursorPos, nAnchor;
656 if (lcl_retrieveSurrounding(nCursorPos, nAnchor, nullptr, nullptr))
657 return QVariant(static_cast<int>(nCursorPos));
658 [[fallthrough]];
660 case Qt::ImCursorRectangle:
662 SalExtTextInputPosEvent aPosEvent;
663 m_rFrame.CallCallback(SalEvent::ExtTextInputPos, &aPosEvent);
664 return QVariant(
665 QRect(aPosEvent.mnX, aPosEvent.mnY, aPosEvent.mnWidth, aPosEvent.mnHeight));
667 case Qt::ImAnchorPosition:
669 sal_Int32 nCursorPos, nAnchor;
670 if (lcl_retrieveSurrounding(nCursorPos, nAnchor, nullptr, nullptr))
671 return QVariant(static_cast<int>(nAnchor));
672 [[fallthrough]];
674 case Qt::ImCurrentSelection:
676 QString aSelection;
677 sal_Int32 nCursorPos, nAnchor;
678 if (lcl_retrieveSurrounding(nCursorPos, nAnchor, nullptr, &aSelection))
679 return QVariant(aSelection);
680 [[fallthrough]];
682 default:
683 return QWidget::inputMethodQuery(property);
686 return QVariant();
689 void Qt5Widget::endExtTextInput()
691 if (m_bNonEmptyIMPreeditSeen)
693 m_rFrame.CallCallback(SalEvent::EndExtTextInput, nullptr);
694 m_bNonEmptyIMPreeditSeen = false;
698 void Qt5Widget::changeEvent(QEvent* pEvent)
700 switch (pEvent->type())
702 case QEvent::FontChange:
703 [[fallthrough]];
704 case QEvent::PaletteChange:
705 [[fallthrough]];
706 case QEvent::StyleChange:
708 auto* pSalInst(static_cast<Qt5Instance*>(GetSalData()->m_pInstance));
709 assert(pSalInst);
710 pSalInst->UpdateStyle(QEvent::FontChange == pEvent->type());
711 break;
713 default:
714 break;
716 QWidget::changeEvent(pEvent);
719 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */