/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if QT5_USING_X11 #include #include #endif #include #include #include #include #include #include #include static void SvpDamageHandler(void* handle, sal_Int32 nExtentsX, sal_Int32 nExtentsY, sal_Int32 nExtentsWidth, sal_Int32 nExtentsHeight) { Qt5Frame* pThis = static_cast(handle); pThis->Damage(nExtentsX, nExtentsY, nExtentsWidth, nExtentsHeight); } namespace { sal_Int32 screenNumber(const QScreen* pScreen) { const QList screens = QApplication::screens(); sal_Int32 nScreen = 0; bool bFound = false; for (const QScreen* pCurScreen : screens) { if (pScreen == pCurScreen) { bFound = true; break; } nScreen++; } return bFound ? nScreen : -1; } } Qt5Frame::Qt5Frame(Qt5Frame* pParent, SalFrameStyleFlags nStyle, bool bUseCairo) : m_pTopLevel(nullptr) , m_bUseCairo(bUseCairo) , m_pSvpGraphics(nullptr) , m_bNullRegion(true) , m_bGraphicsInUse(false) , m_bGraphicsInvalid(false) , m_ePointerStyle(PointerStyle::Arrow) , m_pDragSource(nullptr) , m_pDropTarget(nullptr) , m_bInDrag(false) , m_bDefaultSize(true) , m_bDefaultPos(true) , m_bFullScreen(false) , m_bFullScreenSpanAll(false) { Qt5Instance* pInst = static_cast(GetSalData()->m_pInstance); pInst->insertFrame(this); m_aDamageHandler.handle = this; m_aDamageHandler.damaged = ::SvpDamageHandler; if (nStyle & SalFrameStyleFlags::DEFAULT) // ensure default style { nStyle |= SalFrameStyleFlags::MOVEABLE | SalFrameStyleFlags::SIZEABLE | SalFrameStyleFlags::CLOSEABLE; nStyle &= ~SalFrameStyleFlags::FLOAT; } m_nStyle = nStyle; m_pParent = pParent; Qt::WindowFlags aWinFlags; if (!(nStyle & SalFrameStyleFlags::SYSTEMCHILD)) { if (nStyle & SalFrameStyleFlags::INTRO) aWinFlags |= Qt::SplashScreen; // floating toolbars are frameless tool windows // + they must be able to receive keyboard focus else if ((nStyle & SalFrameStyleFlags::FLOAT) && (nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION)) aWinFlags |= Qt::Tool | Qt::FramelessWindowHint; else if (nStyle & (SalFrameStyleFlags::FLOAT | SalFrameStyleFlags::TOOLTIP)) aWinFlags |= Qt::ToolTip; else if ((nStyle & SalFrameStyleFlags::FLOAT) && !(nStyle & SalFrameStyleFlags::OWNERDRAWDECORATION)) aWinFlags |= Qt::Popup; else if (nStyle & SalFrameStyleFlags::DIALOG && pParent) aWinFlags |= Qt::Dialog; else if (nStyle & SalFrameStyleFlags::TOOLWINDOW) aWinFlags |= Qt::Tool; else aWinFlags |= Qt::Window; } if (aWinFlags == Qt::Window) { QWidget* pParentWidget = m_pParent ? m_pParent->asChild() : nullptr; m_pTopLevel = new Qt5MainWindow(*this, pParentWidget, aWinFlags); m_pQWidget = new Qt5Widget(*this, aWinFlags); m_pTopLevel->setCentralWidget(m_pQWidget); } else m_pQWidget = new Qt5Widget(*this, aWinFlags); if (pParent && !(pParent->m_nStyle & SalFrameStyleFlags::PLUG)) { QWindow* pParentWindow = pParent->GetQWidget()->window()->windowHandle(); QWindow* pChildWindow = asChild()->window()->windowHandle(); if (pParentWindow && pChildWindow && (pParentWindow != pChildWindow)) pChildWindow->setTransientParent(pParentWindow); } m_aSystemData.nSize = sizeof(SystemEnvData); // Calling 'QWidget::winId()' implicitly enables native windows to be used // rather than "alien widgets" that are unknown to the windowing system, // s. https://doc.qt.io/qt-5/qwidget.html#native-widgets-vs-alien-widgets // Avoid this on Wayland due to problems with missing 'mouseMoveEvent's, // s. tdf#122293/QTBUG-75766 const bool bWayland = QGuiApplication::platformName() == "wayland"; if (!bWayland) m_aSystemData.aWindow = m_pQWidget->winId(); else { // TODO implement as needed for Wayland, // s.a. commit c0d4f3ad3307c which did this for gtk3 // QPlatformNativeInterface* native = QGuiApplication::platformNativeInterface(); // m_aSystemData.pDisplay = native->nativeResourceForWindow("display", nullptr); // m_aSystemData.aWindow = reinterpret_cast( // native->nativeResourceForWindow("surface", m_pQWidget->windowHandle())); } m_aSystemData.aShellWindow = reinterpret_cast(this); //m_aSystemData.pSalFrame = this; m_aSystemData.pWidget = m_pQWidget; //m_aSystemData.nScreen = m_nXScreen.getXScreen(); m_aSystemData.pToolkit = "qt5"; if (!bWayland) m_aSystemData.pPlatformName = "xcb"; else m_aSystemData.pPlatformName = "wayland"; SetIcon(SV_ICON_ID_OFFICE); } Qt5Frame::~Qt5Frame() { Qt5Instance* pInst = static_cast(GetSalData()->m_pInstance); pInst->eraseFrame(this); delete asChild(); m_aSystemData.aShellWindow = 0; } void Qt5Frame::Damage(sal_Int32 nExtentsX, sal_Int32 nExtentsY, sal_Int32 nExtentsWidth, sal_Int32 nExtentsHeight) const { m_pQWidget->update(nExtentsX, nExtentsY, nExtentsWidth, nExtentsHeight); } void Qt5Frame::TriggerPaintEvent() { QSize aSize(m_pQWidget->size()); SalPaintEvent aPaintEvt(0, 0, aSize.width(), aSize.height(), true); CallCallback(SalEvent::Paint, &aPaintEvt); } void Qt5Frame::TriggerPaintEvent(QRect aRect) { SalPaintEvent aPaintEvt(aRect.x(), aRect.y(), aRect.width(), aRect.height(), true); CallCallback(SalEvent::Paint, &aPaintEvt); } void Qt5Frame::InitQt5SvpGraphics(Qt5SvpGraphics* pQt5SvpGraphics) { int width = 640; int height = 480; m_pSvpGraphics = pQt5SvpGraphics; m_pSurface.reset(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height)); m_pSvpGraphics->setSurface(m_pSurface.get(), basegfx::B2IVector(width, height)); cairo_surface_set_user_data(m_pSurface.get(), Qt5SvpGraphics::getDamageKey(), &m_aDamageHandler, nullptr); } SalGraphics* Qt5Frame::AcquireGraphics() { if (m_bGraphicsInUse) return nullptr; m_bGraphicsInUse = true; if (m_bUseCairo) { if (!m_pOurSvpGraphics.get() || m_bGraphicsInvalid) { m_pOurSvpGraphics.reset(new Qt5SvpGraphics(this)); InitQt5SvpGraphics(m_pOurSvpGraphics.get()); m_bGraphicsInvalid = false; } return m_pOurSvpGraphics.get(); } else { if (!m_pQt5Graphics.get() || m_bGraphicsInvalid) { m_pQt5Graphics.reset(new Qt5Graphics(this)); m_pQImage.reset(new QImage(m_pQWidget->size(), Qt5_DefaultFormat32)); m_pQImage->fill(Qt::transparent); m_pQt5Graphics->ChangeQImage(m_pQImage.get()); m_bGraphicsInvalid = false; } return m_pQt5Graphics.get(); } } void Qt5Frame::ReleaseGraphics(SalGraphics* pSalGraph) { (void)pSalGraph; if (m_bUseCairo) assert(pSalGraph == m_pOurSvpGraphics.get()); else assert(pSalGraph == m_pQt5Graphics.get()); m_bGraphicsInUse = false; } bool Qt5Frame::PostEvent(std::unique_ptr pData) { Qt5Instance* pInst = static_cast(GetSalData()->m_pInstance); pInst->PostEvent(this, pData.release(), SalEvent::UserEvent); return true; } QWidget* Qt5Frame::asChild() const { return m_pTopLevel ? m_pTopLevel : m_pQWidget; } bool Qt5Frame::isWindow() const { return asChild()->isWindow(); } QWindow* Qt5Frame::windowHandle() const { // set attribute 'Qt::WA_NativeWindow' first to make sure a window handle actually exists QWidget* pChild = asChild(); pChild->setAttribute(Qt::WA_NativeWindow); return pChild->windowHandle(); } QScreen* Qt5Frame::screen() const { QWindow* const pWindow = windowHandle(); return pWindow ? pWindow->screen() : nullptr; } bool Qt5Frame::isMinimized() const { return asChild()->isMinimized(); } bool Qt5Frame::isMaximized() const { return asChild()->isMaximized(); } void Qt5Frame::SetWindowStateImpl(Qt::WindowStates eState) { return asChild()->setWindowState(eState); } void Qt5Frame::SetTitle(const OUString& rTitle) { m_pQWidget->window()->setWindowTitle(toQString(rTitle)); } void Qt5Frame::SetIcon(sal_uInt16 nIcon) { if (m_nStyle & (SalFrameStyleFlags::PLUG | SalFrameStyleFlags::SYSTEMCHILD | SalFrameStyleFlags::FLOAT | SalFrameStyleFlags::INTRO | SalFrameStyleFlags::OWNERDRAWDECORATION) || !isWindow()) return; QString appicon; if (nIcon == SV_ICON_ID_TEXT) appicon = "libreoffice-writer"; else if (nIcon == SV_ICON_ID_SPREADSHEET) appicon = "libreoffice-calc"; else if (nIcon == SV_ICON_ID_DRAWING) appicon = "libreoffice-draw"; else if (nIcon == SV_ICON_ID_PRESENTATION) appicon = "libreoffice-impress"; else if (nIcon == SV_ICON_ID_DATABASE) appicon = "libreoffice-base"; else if (nIcon == SV_ICON_ID_FORMULA) appicon = "libreoffice-math"; else appicon = "libreoffice-startcenter"; QIcon aIcon = QIcon::fromTheme(appicon); m_pQWidget->window()->setWindowIcon(aIcon); } void Qt5Frame::SetMenu(SalMenu* pMenu) { m_pSalMenu = static_cast(pMenu); } void Qt5Frame::DrawMenuBar() { /* not needed */} void Qt5Frame::SetExtendedFrameStyle(SalExtStyle /*nExtStyle*/) { /* not needed */} void Qt5Frame::Show(bool bVisible, bool /*bNoActivate*/) { assert(m_pQWidget); SetDefaultSize(); SetDefaultPos(); auto* pSalInst(static_cast(GetSalData()->m_pInstance)); assert(pSalInst); pSalInst->RunInMainThread([this, bVisible]() { asChild()->setVisible(bVisible); }); } void Qt5Frame::SetMinClientSize(long nWidth, long nHeight) { if (!isChild()) asChild()->setMinimumSize(nWidth, nHeight); } void Qt5Frame::SetMaxClientSize(long nWidth, long nHeight) { if (!isChild()) asChild()->setMaximumSize(nWidth, nHeight); } void Qt5Frame::SetDefaultPos() { if (!m_bDefaultPos) return; // center on parent if (m_pParent) { QWidget* const pWindow = m_pParent->GetQWidget()->window(); QWidget* const pWidget = asChild(); QPoint aPos = pWindow->rect().center() - pWidget->rect().center(); SetPosSize(aPos.x(), aPos.y(), 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y); assert(!m_bDefaultPos); } else m_bDefaultPos = false; } Size Qt5Frame::CalcDefaultSize() { assert(isWindow()); Size aSize; if (!m_bFullScreen) { const QScreen* pScreen = screen(); aSize = bestmaxFrameSizeForScreenSize( toSize(pScreen ? pScreen->size() : QApplication::desktop()->screenGeometry(0).size())); } else { if (!m_bFullScreenSpanAll) aSize = toSize( QApplication::desktop()->screenGeometry(maGeometry.nDisplayScreenNumber).size()); else { int nLeftScreen = QApplication::desktop()->screenNumber(QPoint(0, 0)); aSize = toSize(QApplication::screens()[nLeftScreen]->availableVirtualGeometry().size()); } } return aSize; } void Qt5Frame::SetDefaultSize() { if (!m_bDefaultSize) return; Size aDefSize = CalcDefaultSize(); SetPosSize(0, 0, aDefSize.Width(), aDefSize.Height(), SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT); assert(!m_bDefaultSize); } void Qt5Frame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags) { if (!isWindow() || isChild(true, false)) return; if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) { if (isChild(false) || !m_pQWidget->isMaximized()) { if (!(nFlags & SAL_FRAME_POSSIZE_WIDTH)) nWidth = maGeometry.nWidth; else if (!(nFlags & SAL_FRAME_POSSIZE_HEIGHT)) nHeight = maGeometry.nHeight; if (nWidth > 0 && nHeight > 0) { m_bDefaultSize = false; if (m_nStyle & SalFrameStyleFlags::SIZEABLE) asChild()->resize(nWidth, nHeight); else asChild()->setFixedSize(nWidth, nHeight); } // assume the resize happened // needed for calculations and will eventually be corrected by events if (nWidth > 0) maGeometry.nWidth = nWidth; if (nHeight > 0) maGeometry.nHeight = nHeight; } } if (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) { if (m_pParent) { const SalFrameGeometry& aParentGeometry = m_pParent->maGeometry; if (QGuiApplication::isRightToLeft()) nX = aParentGeometry.nX + aParentGeometry.nWidth - nX - maGeometry.nWidth - 1; else nX += aParentGeometry.nX; nY += aParentGeometry.nY; Qt5MainWindow* pTopLevel = m_pParent->GetTopLevelWindow(); if (pTopLevel && pTopLevel->menuBar() && pTopLevel->menuBar()->isVisible()) nY += pTopLevel->menuBar()->geometry().height(); } if (!(nFlags & SAL_FRAME_POSSIZE_X)) nX = maGeometry.nX; else if (!(nFlags & SAL_FRAME_POSSIZE_Y)) nY = maGeometry.nY; // assume the reposition happened // needed for calculations and will eventually be corrected by events later maGeometry.nX = nX; maGeometry.nY = nY; m_bDefaultPos = false; asChild()->move(nX, nY); } } void Qt5Frame::GetClientSize(long& rWidth, long& rHeight) { rWidth = m_pQWidget->width(); rHeight = m_pQWidget->height(); } void Qt5Frame::GetWorkArea(tools::Rectangle& rRect) { if (!isWindow()) return; QScreen* pScreen = screen(); if (!pScreen) return; QSize aSize = pScreen->availableVirtualSize(); rRect = tools::Rectangle(0, 0, aSize.width(), aSize.height()); } SalFrame* Qt5Frame::GetParent() const { return m_pParent; } void Qt5Frame::SetModal(bool bModal) { if (isWindow()) { auto* pSalInst(static_cast(GetSalData()->m_pInstance)); assert(pSalInst); pSalInst->RunInMainThread([this, bModal]() { QWidget* const pChild = asChild(); const bool bWasVisible = pChild->isVisible(); // modality change is only effective if the window is hidden if (bWasVisible) pChild->hide(); pChild->setWindowModality(bModal ? Qt::WindowModal : Qt::NonModal); if (bWasVisible) pChild->show(); }); } } bool Qt5Frame::GetModal() const { return isWindow() && windowHandle()->isModal(); } void Qt5Frame::SetWindowState(const SalFrameState* pState) { if (!isWindow() || !pState || isChild(true, false)) return; const WindowStateMask nMaxGeometryMask = WindowStateMask::X | WindowStateMask::Y | WindowStateMask::Width | WindowStateMask::Height | WindowStateMask::MaximizedX | WindowStateMask::MaximizedY | WindowStateMask::MaximizedWidth | WindowStateMask::MaximizedHeight; if ((pState->mnMask & WindowStateMask::State) && (pState->mnState & WindowStateState::Maximized) && !isMaximized() && (pState->mnMask & nMaxGeometryMask) == nMaxGeometryMask) { QWidget* const pChild = asChild(); pChild->resize(pState->mnWidth, pState->mnHeight); pChild->move(pState->mnX, pState->mnY); SetWindowStateImpl(Qt::WindowMaximized); } else if (pState->mnMask & (WindowStateMask::X | WindowStateMask::Y | WindowStateMask::Width | WindowStateMask::Height)) { sal_uInt16 nPosSizeFlags = 0; if (pState->mnMask & WindowStateMask::X) nPosSizeFlags |= SAL_FRAME_POSSIZE_X; if (pState->mnMask & WindowStateMask::Y) nPosSizeFlags |= SAL_FRAME_POSSIZE_Y; if (pState->mnMask & WindowStateMask::Width) nPosSizeFlags |= SAL_FRAME_POSSIZE_WIDTH; if (pState->mnMask & WindowStateMask::Height) nPosSizeFlags |= SAL_FRAME_POSSIZE_HEIGHT; SetPosSize(pState->mnX, pState->mnY, pState->mnWidth, pState->mnHeight, nPosSizeFlags); } else if (pState->mnMask & WindowStateMask::State && !isChild()) { if (pState->mnState & WindowStateState::Maximized) SetWindowStateImpl(Qt::WindowMaximized); else if (pState->mnState & WindowStateState::Minimized) SetWindowStateImpl(Qt::WindowMinimized); else SetWindowStateImpl(Qt::WindowNoState); } } bool Qt5Frame::GetWindowState(SalFrameState* pState) { pState->mnState = WindowStateState::Normal; pState->mnMask = WindowStateMask::State; if (isMinimized() /*|| !windowHandle()*/) pState->mnState |= WindowStateState::Minimized; else if (isMaximized()) { pState->mnState |= WindowStateState::Maximized; } else { // geometry() is the drawable area, which is wanted here QRect rect = asChild()->geometry(); pState->mnX = rect.x(); pState->mnY = rect.y(); pState->mnWidth = rect.width(); pState->mnHeight = rect.height(); // the menubar is drawn natively, adjust for that if (maGeometry.nTopDecoration) { pState->mnY += maGeometry.nTopDecoration; pState->mnHeight -= maGeometry.nTopDecoration; } pState->mnMask |= WindowStateMask::X | WindowStateMask::Y | WindowStateMask::Width | WindowStateMask::Height; } return true; } void Qt5Frame::ShowFullScreen(bool bFullScreen, sal_Int32 nScreen) { // only top-level windows can go fullscreen assert(m_pTopLevel); if (m_bFullScreen == bFullScreen) return; m_bFullScreen = bFullScreen; m_bFullScreenSpanAll = m_bFullScreen && (nScreen < 0); // show it if it isn't shown yet if (!isWindow()) m_pTopLevel->show(); if (m_bFullScreen) { m_aRestoreGeometry = m_pTopLevel->geometry(); m_nRestoreScreen = maGeometry.nDisplayScreenNumber; SetScreenNumber(m_bFullScreenSpanAll ? m_nRestoreScreen : nScreen); if (!m_bFullScreenSpanAll) windowHandle()->showFullScreen(); else windowHandle()->showNormal(); } else { SetScreenNumber(m_nRestoreScreen); windowHandle()->showNormal(); m_pTopLevel->setGeometry(m_aRestoreGeometry); } } void Qt5Frame::StartPresentation(bool bStart) { // meh - so there's no Qt platform independent solution // https://forum.qt.io/topic/38504/solved-qdialog-in-fullscreen-disable-os-screensaver #if QT5_USING_X11 boost::optional aRootWindow; boost::optional aDisplay; if (QX11Info::isPlatformX11()) { aRootWindow = QX11Info::appRootWindow(); aDisplay = QX11Info::display(); } m_ScreenSaverInhibitor.inhibit(bStart, "presentation", QX11Info::isPlatformX11(), aRootWindow, aDisplay); #else (void)bStart; #endif } void Qt5Frame::SetAlwaysOnTop(bool bOnTop) { QWidget* const pWidget = asChild(); const Qt::WindowFlags flags = pWidget->windowFlags(); if (bOnTop) pWidget->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint); else pWidget->setWindowFlags(flags & ~(Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint)); } void Qt5Frame::ToTop(SalFrameToTop nFlags) { QWidget* const pWidget = asChild(); if (isWindow() && !(nFlags & SalFrameToTop::GrabFocusOnly)) pWidget->raise(); if ((nFlags & SalFrameToTop::RestoreWhenMin) || (nFlags & SalFrameToTop::ForegroundTask)) pWidget->activateWindow(); else if ((nFlags & SalFrameToTop::GrabFocus) || (nFlags & SalFrameToTop::GrabFocusOnly)) m_pQWidget->setFocus(); } void Qt5Frame::SetPointer(PointerStyle ePointerStyle) { QWindow* pWindow = m_pQWidget->window()->windowHandle(); if (!pWindow) return; if (ePointerStyle == m_ePointerStyle) return; m_ePointerStyle = ePointerStyle; pWindow->setCursor(static_cast(GetSalData())->getCursor(ePointerStyle)); } void Qt5Frame::CaptureMouse(bool bMouse) { static const char* pEnv = getenv("SAL_NO_MOUSEGRABS"); if (pEnv && *pEnv) return; if (bMouse) m_pQWidget->grabMouse(); else m_pQWidget->releaseMouse(); } void Qt5Frame::SetPointerPos(long nX, long nY) { // some cursor already exists (and it has m_ePointerStyle shape) // so here we just reposition it QCursor::setPos(m_pQWidget->mapToGlobal(QPoint(nX, nY))); } void Qt5Frame::Flush() { // was: QGuiApplication::sync(); // but FIXME it causes too many issues, figure out sth better // unclear if we need to also flush cairo surface - gtk3 backend // does not do it. QPainter in Qt5Widget::paintEvent() is // destroyed, so that state should be safely flushed. } bool Qt5Frame::ShowTooltip(const OUString& rText, const tools::Rectangle& rHelpArea) { QRect aHelpArea(toQRect(rHelpArea)); if (QGuiApplication::isRightToLeft()) aHelpArea.moveLeft(maGeometry.nWidth - aHelpArea.width() - aHelpArea.left() - 1); QToolTip::showText(QCursor::pos(), toQString(rText), m_pQWidget, aHelpArea); return true; } void Qt5Frame::SetInputContext(SalInputContext* pContext) { if (!pContext) return; if (!(pContext->mnOptions & InputContextFlags::Text)) return; m_pQWidget->setAttribute(Qt::WA_InputMethodEnabled); } void Qt5Frame::EndExtTextInput(EndExtTextInputFlags /*nFlags*/) { Qt5Widget* pQt5Widget = static_cast(m_pQWidget); if (pQt5Widget) pQt5Widget->endExtTextInput(); } OUString Qt5Frame::GetKeyName(sal_uInt16 nKeyCode) { vcl::KeyCode vclKeyCode(nKeyCode); int nCode = vclKeyCode.GetCode(); int nRetCode = 0; if (nCode >= KEY_0 && nCode <= KEY_9) nRetCode = (nCode - KEY_0) + Qt::Key_0; else if (nCode >= KEY_A && nCode <= KEY_Z) nRetCode = (nCode - KEY_A) + Qt::Key_A; else if (nCode >= KEY_F1 && nCode <= KEY_F26) nRetCode = (nCode - KEY_F1) + Qt::Key_F1; else { switch (nCode) { case KEY_DOWN: nRetCode = Qt::Key_Down; break; case KEY_UP: nRetCode = Qt::Key_Up; break; case KEY_LEFT: nRetCode = Qt::Key_Left; break; case KEY_RIGHT: nRetCode = Qt::Key_Right; break; case KEY_HOME: nRetCode = Qt::Key_Home; break; case KEY_END: nRetCode = Qt::Key_End; break; case KEY_PAGEUP: nRetCode = Qt::Key_PageUp; break; case KEY_PAGEDOWN: nRetCode = Qt::Key_PageDown; break; case KEY_RETURN: nRetCode = Qt::Key_Return; break; case KEY_ESCAPE: nRetCode = Qt::Key_Escape; break; case KEY_TAB: nRetCode = Qt::Key_Tab; break; case KEY_BACKSPACE: nRetCode = Qt::Key_Backspace; break; case KEY_SPACE: nRetCode = Qt::Key_Space; break; case KEY_INSERT: nRetCode = Qt::Key_Insert; break; case KEY_DELETE: nRetCode = Qt::Key_Delete; break; case KEY_ADD: nRetCode = Qt::Key_Plus; break; case KEY_SUBTRACT: nRetCode = Qt::Key_Minus; break; case KEY_MULTIPLY: nRetCode = Qt::Key_Asterisk; break; case KEY_DIVIDE: nRetCode = Qt::Key_Slash; break; case KEY_POINT: nRetCode = Qt::Key_Period; break; case KEY_COMMA: nRetCode = Qt::Key_Comma; break; case KEY_LESS: nRetCode = Qt::Key_Less; break; case KEY_GREATER: nRetCode = Qt::Key_Greater; break; case KEY_EQUAL: nRetCode = Qt::Key_Equal; break; case KEY_FIND: nRetCode = Qt::Key_Find; break; case KEY_CONTEXTMENU: nRetCode = Qt::Key_Menu; break; case KEY_HELP: nRetCode = Qt::Key_Help; break; case KEY_UNDO: nRetCode = Qt::Key_Undo; break; case KEY_REPEAT: nRetCode = Qt::Key_Redo; break; case KEY_TILDE: nRetCode = Qt::Key_AsciiTilde; break; case KEY_QUOTELEFT: nRetCode = Qt::Key_QuoteLeft; break; case KEY_BRACKETLEFT: nRetCode = Qt::Key_BracketLeft; break; case KEY_BRACKETRIGHT: nRetCode = Qt::Key_BracketRight; break; case KEY_SEMICOLON: nRetCode = Qt::Key_Semicolon; break; // Special cases case KEY_COPY: nRetCode = Qt::Key_Copy; break; case KEY_CUT: nRetCode = Qt::Key_Cut; break; case KEY_PASTE: nRetCode = Qt::Key_Paste; break; case KEY_OPEN: nRetCode = Qt::Key_Open; break; } } if (vclKeyCode.IsShift()) nRetCode += Qt::SHIFT; if (vclKeyCode.IsMod1()) nRetCode += Qt::CTRL; if (vclKeyCode.IsMod2()) nRetCode += Qt::ALT; QKeySequence keySeq(nRetCode); OUString sKeyName = toOUString(keySeq.toString()); return sKeyName; } bool Qt5Frame::MapUnicodeToKeyCode(sal_Unicode /*aUnicode*/, LanguageType /*aLangType*/, vcl::KeyCode& /*rKeyCode*/) { // not supported yet return false; } LanguageType Qt5Frame::GetInputLanguage() { // fallback return LANGUAGE_DONTKNOW; } static Color toColor(const QColor& rColor) { return Color(rColor.red(), rColor.green(), rColor.blue()); } void Qt5Frame::UpdateSettings(AllSettings& rSettings) { if (Qt5Data::noNativeControls()) return; StyleSettings style(rSettings.GetStyleSettings()); // General settings QPalette pal = QApplication::palette(); style.SetToolbarIconSize(ToolbarIconSize::Large); Color aFore = toColor(pal.color(QPalette::Active, QPalette::WindowText)); Color aBack = toColor(pal.color(QPalette::Active, QPalette::Window)); Color aText = toColor(pal.color(QPalette::Active, QPalette::Text)); Color aBase = toColor(pal.color(QPalette::Active, QPalette::Base)); Color aButn = toColor(pal.color(QPalette::Active, QPalette::ButtonText)); Color aMid = toColor(pal.color(QPalette::Active, QPalette::Mid)); Color aHigh = toColor(pal.color(QPalette::Active, QPalette::Highlight)); Color aHighText = toColor(pal.color(QPalette::Active, QPalette::HighlightedText)); Color aLink = toColor(pal.color(QPalette::Active, QPalette::Link)); Color aVisitedLink = toColor(pal.color(QPalette::Active, QPalette::LinkVisited)); style.SetSkipDisabledInMenus(true); // Foreground style.SetRadioCheckTextColor(aFore); style.SetLabelTextColor(aFore); style.SetDialogTextColor(aFore); style.SetGroupTextColor(aFore); // Text style.SetFieldTextColor(aText); style.SetFieldRolloverTextColor(aText); style.SetWindowTextColor(aText); style.SetToolTextColor(aText); // Base style.SetFieldColor(aBase); style.SetWindowColor(aBase); style.SetActiveTabColor(aBase); // Buttons style.SetButtonTextColor(aButn); style.SetButtonRolloverTextColor(aButn); style.SetButtonPressedRolloverTextColor(aButn); // Tabs style.SetTabTextColor(aButn); style.SetTabRolloverTextColor(aButn); style.SetTabHighlightTextColor(aButn); // Disable color style.SetDisableColor(toColor(pal.color(QPalette::Disabled, QPalette::WindowText))); // Background style.BatchSetBackgrounds(aBack); style.SetInactiveTabColor(aBack); // Workspace style.SetWorkspaceColor(aMid); // Selection style.SetHighlightColor(aHigh); style.SetHighlightTextColor(aHighText); // Links style.SetLinkColor(aLink); style.SetVisitedLinkColor(aVisitedLink); // Tooltip style.SetHelpColor(toColor(QToolTip::palette().color(QPalette::Active, QPalette::ToolTipBase))); style.SetHelpTextColor( toColor(QToolTip::palette().color(QPalette::Active, QPalette::ToolTipText))); const int flash_time = QApplication::cursorFlashTime(); style.SetCursorBlinkTime(flash_time != 0 ? flash_time / 2 : STYLE_CURSOR_NOBLINKTIME); // Menu std::unique_ptr pMenuBar = std::make_unique(); QPalette qMenuCG = pMenuBar->palette(); // Menu text and background color, theme specific Color aMenuFore = toColor(qMenuCG.color(QPalette::WindowText)); Color aMenuBack = toColor(qMenuCG.color(QPalette::Window)); style.SetMenuTextColor(aMenuFore); style.SetMenuBarTextColor(style.GetPersonaMenuBarTextColor().get_value_or(aMenuFore)); style.SetMenuColor(aMenuBack); style.SetMenuBarColor(aMenuBack); style.SetMenuHighlightColor(toColor(qMenuCG.color(QPalette::Highlight))); style.SetMenuHighlightTextColor(toColor(qMenuCG.color(QPalette::HighlightedText))); // set special menubar highlight text color if (QApplication::style()->inherits("HighContrastStyle")) ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor = toColor(qMenuCG.color(QPalette::HighlightedText)); else ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor = aMenuFore; // set menubar rollover color if (pMenuBar->style()->styleHint(QStyle::SH_MenuBar_MouseTracking)) { style.SetMenuBarRolloverColor(toColor(qMenuCG.color(QPalette::Highlight))); style.SetMenuBarRolloverTextColor(ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor); } else { style.SetMenuBarRolloverColor(aMenuBack); style.SetMenuBarRolloverTextColor(aMenuFore); } style.SetMenuBarHighlightTextColor(style.GetMenuHighlightTextColor()); // Scroll bar size style.SetScrollBarSize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent)); style.SetMinThumbSize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarSliderMin)); // These colors are used for the ruler text and marks style.SetShadowColor(toColor(pal.color(QPalette::Disabled, QPalette::WindowText))); style.SetDarkShadowColor(toColor(pal.color(QPalette::Inactive, QPalette::WindowText))); m_bGraphicsInvalid = true; rSettings.SetStyleSettings(style); } void Qt5Frame::Beep() { QApplication::beep(); } SalFrame::SalPointerState Qt5Frame::GetPointerState() { SalPointerState aState; QPoint pos = QCursor::pos(); aState.maPos = Point(pos.x(), pos.y()); aState.mnState = GetMouseModCode(QGuiApplication::mouseButtons()) | GetKeyModCode(QGuiApplication::keyboardModifiers()); return aState; } KeyIndicatorState Qt5Frame::GetIndicatorState() { return KeyIndicatorState(); } void Qt5Frame::SimulateKeyPress(sal_uInt16 nKeyCode) { SAL_WARN("vcl.kde5", "missing simulate keypress " << nKeyCode); } void Qt5Frame::SetParent(SalFrame* pNewParent) { m_pParent = static_cast(pNewParent); } bool Qt5Frame::SetPluginParent(SystemParentData* /*pNewParent*/) { //FIXME: no SetPluginParent impl. for kde5 return false; } void Qt5Frame::ResetClipRegion() { m_bNullRegion = true; } void Qt5Frame::BeginSetClipRegion(sal_uInt32) { m_aRegion = QRegion(QRect(QPoint(0, 0), m_pQWidget->size())); } void Qt5Frame::UnionClipRegion(long nX, long nY, long nWidth, long nHeight) { m_aRegion = m_aRegion.united(QRegion(nX, nY, nWidth, nHeight)); } void Qt5Frame::EndSetClipRegion() { m_bNullRegion = false; } void Qt5Frame::SetScreenNumber(unsigned int nScreen) { if (isWindow()) { QWindow* const pWindow = windowHandle(); if (pWindow) { QList screens = QApplication::screens(); if (static_cast(nScreen) < screens.size() || m_bFullScreenSpanAll) { QRect screenGeo; if (!m_bFullScreenSpanAll) { screenGeo = QApplication::desktop()->screenGeometry(nScreen); pWindow->setScreen(QApplication::screens()[nScreen]); } else // special case: fullscreen over all available screens { assert(m_bFullScreen); // left-most screen int nLeftScreen = QApplication::desktop()->screenNumber(QPoint(0, 0)); // entire virtual desktop screenGeo = QApplication::screens()[nLeftScreen]->availableVirtualGeometry(); pWindow->setScreen(QApplication::screens()[nLeftScreen]); pWindow->setGeometry(screenGeo); nScreen = nLeftScreen; } // setScreen by itself has no effect, explicitly move the widget to // the new screen asChild()->move(screenGeo.topLeft()); } else { // index outta bounds, use primary screen QScreen* primaryScreen = QApplication::primaryScreen(); pWindow->setScreen(primaryScreen); nScreen = static_cast(screenNumber(primaryScreen)); } maGeometry.nDisplayScreenNumber = nScreen; } } } void Qt5Frame::SetApplicationID(const OUString& rWMClass) { #if QT5_USING_X11 if (QGuiApplication::platformName() != "xcb" || !m_pTopLevel) return; OString aResClass = OUStringToOString(rWMClass, RTL_TEXTENCODING_ASCII_US); const char* pResClass = !aResClass.isEmpty() ? aResClass.getStr() : SalGenericSystem::getFrameClassName(); OString aResName = SalGenericSystem::getFrameResName(); // the WM_CLASS data consists of two concatenated cstrings, including the terminating '\0' chars const uint32_t data_len = aResName.getLength() + 1 + strlen(pResClass) + 1; char* data = new char[data_len]; memcpy(data, aResName.getStr(), aResName.getLength() + 1); memcpy(data + aResName.getLength() + 1, pResClass, strlen(pResClass) + 1); xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, m_pTopLevel->winId(), XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8, data_len, data); delete[] data; #else (void)rWMClass; #endif } // Drag'n'drop foo void Qt5Frame::registerDragSource(Qt5DragSource* pDragSource) { assert(!m_pDragSource); m_pDragSource = pDragSource; } void Qt5Frame::deregisterDragSource(Qt5DragSource const* pDragSource) { assert(m_pDragSource == pDragSource); (void)pDragSource; m_pDragSource = nullptr; } void Qt5Frame::registerDropTarget(Qt5DropTarget* pDropTarget) { assert(!m_pDropTarget); m_pDropTarget = pDropTarget; m_pQWidget->setAcceptDrops(true); } void Qt5Frame::deregisterDropTarget(Qt5DropTarget const* pDropTarget) { assert(m_pDropTarget == pDropTarget); (void)pDropTarget; m_pDropTarget = nullptr; } void Qt5Frame::draggingStarted(const int x, const int y, Qt::DropActions eActions, Qt::KeyboardModifiers eKeyMod, const QMimeData* pQMimeData) { assert(m_pDropTarget); sal_Int8 nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_MOVE; if ((eKeyMod & Qt::ShiftModifier) && !(eKeyMod & Qt::ControlModifier)) nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_MOVE; else if ((eKeyMod & Qt::ControlModifier) && !(eKeyMod & Qt::ShiftModifier)) nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_COPY; else if ((eKeyMod & Qt::ShiftModifier) && (eKeyMod & Qt::ControlModifier)) nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_LINK; css::datatransfer::dnd::DropTargetDragEnterEvent aEvent; aEvent.Source = static_cast(m_pDropTarget); aEvent.Context = static_cast(m_pDropTarget); aEvent.LocationX = x; aEvent.LocationY = y; // system drop action if neither Shift nor Control is held if (!(eKeyMod & (Qt::ShiftModifier | Qt::ControlModifier))) aEvent.DropAction = getPreferredDropAction(eActions); // otherwise user-preferred action else aEvent.DropAction = nUserDropAction; aEvent.SourceActions = toVclDropActions(eActions); css::uno::Reference xTransferable; if (!pQMimeData->hasFormat(sInternalMimeType)) xTransferable = new Qt5DnDTransferable(pQMimeData); else xTransferable = Qt5DragSource::m_ActiveDragSource->GetTransferable(); if (!m_bInDrag && xTransferable.is()) { css::uno::Sequence aFormats = xTransferable->getTransferDataFlavors(); aEvent.SupportedDataFlavors = aFormats; m_pDropTarget->fire_dragEnter(aEvent); m_bInDrag = true; } else m_pDropTarget->fire_dragOver(aEvent); } void Qt5Frame::dropping(const int x, const int y, Qt::KeyboardModifiers eKeyMod, const QMimeData* pQMimeData) { assert(m_pDropTarget); css::datatransfer::dnd::DropTargetDropEvent aEvent; aEvent.Source = static_cast(m_pDropTarget); aEvent.Context = static_cast(m_pDropTarget); aEvent.LocationX = x; aEvent.LocationY = y; if (!(eKeyMod & (Qt::ShiftModifier | Qt::ControlModifier))) aEvent.DropAction = m_pDropTarget->proposedDragAction() | css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT; else aEvent.DropAction = m_pDropTarget->proposedDragAction(); aEvent.SourceActions = css::datatransfer::dnd::DNDConstants::ACTION_MOVE; css::uno::Reference xTransferable; if (!pQMimeData->hasFormat(sInternalMimeType)) xTransferable = new Qt5DnDTransferable(pQMimeData); else xTransferable = Qt5DragSource::m_ActiveDragSource->GetTransferable(); aEvent.Transferable = xTransferable; m_pDropTarget->fire_drop(aEvent); m_bInDrag = false; if (m_pDragSource) { m_pDragSource->fire_dragEnd(m_pDropTarget->proposedDragAction()); } } cairo_t* Qt5Frame::getCairoContext() const { cairo_t* cr = nullptr; if (m_bUseCairo) { cr = cairo_create(m_pSurface.get()); assert(cr); } return cr; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ on value='private/Sweetshark/killswclient'>private/Sweetshark/killswclient LibreOffice 核心代码仓库文档基金会
summaryrefslogtreecommitdiff
846b'>tdf#146619 Recheck include/c* with IWYU
AgeCommit message (Collapse)Author
2024-08-20tdf#143148 Use pragma once in svxDeepanshu Sharma
Change-Id: I22a1e384b6d6a90e412c9c0c36785f0cba73a90c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172054 Tested-by: Ilmari Lauhakangas <ilmari.lauhakangas@libreoffice.org> Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakangas@libreoffice.org>
2024-02-12make BufferedDecompositionPrimitive2D store a Primitive2DReference..Noel Grandin
.. instead of a Primitive2DContainer. The container very frequently contains only a single item, since the decomposition method often sticks only a single top-level node in there, so it turns out to be a net loss overall, memory consumption-wise. Also, if we return a single Primitive2DReference from a BufferedDecomposition, that maximises the sharing of data between the BufferedDecomposition objects at the bottom of the decomposed tree, and objects higher up. Change-Id: Iaf272e60e2997299cc35a1bd209c51b6b79e9a8b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162976 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2022-08-29ref-count SdrObjectNoel Grandin
Which means we can get rid of the majestic hack of ScCaptionPtr Previously, SdrObject was manually managed, and the ownership passed around in very complicated fashion. Notes: (*) SvxShape has a strong reference to SdrObject, where previously it had a weak reference. It is now strong since otherwise the SdrObject will go away very eagerly. (*) SdrObject still has a weak reference to SvxShape (*) In the existing places that an SdrObject is being deleted, we now just clear the reference (*) instead of SwVirtFlyDrawObj removing itself from the page that contains inside it's destructor, make the call site do the removing from the page. (*) Needed to take the SolarMutex in UndoManagerHelper_Impl::impl_clear because this can be called from UNO (e.g. sfx2_complex JUnit test) and the SdrObjects need the SolarMutex when destructing. (*) handle a tricky situation with SwDrawVirtObj in the SwDrawModel destructor because the existing code wants mpDrawObj in SwAnchoredObject to be sometimes owning, sometimes not, which results in a cycle with the new code. Change-Id: I4d79df1660e386388e5d51030653755bca02a163 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138837 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2022-07-21clang-tidy modernize-pass-by-value in svxNoel Grandin
Change-Id: Iedd87d321f4d161574df87629fdd6c7714ff31c5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137248 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2021-06-21drawinglayer: put BufferedDecompositionPrimitive2D in its own fileTomaž Vajngerl
And fix includes all over the place... Change-Id: I6e2696bbeeac6ab7467cac70545fa7209aa981a8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117528 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Gabor Kelemen
Change-Id: I0cf6f675483bddf82e7347b484a874c71963bfd7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156984 Tested-by: Jenkins Reviewed-by: Gabor Kelemen <kelemeng@ubuntu.com>
2023-08-31use concrete type for SvxShowCharSetAcc::m_aChildrenNoel Grandin
avoid some unnecessary casting Change-Id: I73338c00b90357fe939e38a53f87a4ef9f13e86c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156322 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2023-06-21Require icu-i18n >= 66Khaled Hosny
We were requiring ICU 4.6 which was released in 2011, and ifdef'ing our way through newer ICU versions. ICU is a core dependency and it makes no sense to build LibreOffice with such ancient versions of it. This change requires ICU 66 (released in 2020), and removes all the ifdefs for older versions. There are more cleanups to do, but these will be done separately. Change-Id: I2e4f7608a08f4d531b0a4c74bbfdf91a451f833f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153387 Tested-by: Jenkins Reviewed-by: خالد حسني <khaled@libreoffice.org>
2023-05-02tdf#154884 fix isFavChar, updateFavCharacterList deletes the correct pairVert D
Change-Id: I98be8df93c5e3985e95f285e3cb9a2b600eb85c9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151216 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-04-03tdf#153806 a11y: Allow opening context menu in special char dlg using keyboardMichael Weghorn
Open the context menu for the `CommandEventId::ContextMenu` command for the character table that is used in the special characters dialog, so opening the context menu is not only possible by right mouse click, but also using the keyboard (by pressing the context menu button or Shift+F10). Move the handling for the case where the context menu is activated using the mouse from `SvxShowCharSet::MouseButtonDown` to `SvxShowCharSet::Command`. When the context menu is activated using the keyboard, use the centre of the currently selected item for the context menu position. Adding support for opening the context menu for the recently used and favorite characters further down in the special characters dialog is independent of this and would have to be added separately. Change-Id: I55ef43708b95f5a90b06777a8aeb32a64609160d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149927 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-04-03Pass special char dlg context menu pos as param, drop memberMichael Weghorn
The `maPosition` member was only used for the position of the context menu. It was set before calling `SvxShowCharSet::createContextMenu` and then only used in there. Pass the position directly as a parameter instead and drop the extra member. Change-Id: I7ba9ec60ffb993ca1269d86efeddbe0950ed7fbe Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149926 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-04-03tdf#153806 a11y: Insert special char + close dialog on return keyMichael Weghorn
As discussed in tdf#153806, insert the currently selected character from the special characters dialog and close the dialog when the return key is pressed on the table of characters (either showing all characters or just the search result). Something similar should probably be done when the return key is pressed with one of the recent characters or favorite characters in the dialog having focus, but that needs to be handled separately, possibly along with the other remaining suggestions to improve keyboard handling in the special characters dialog as discussed in tdf#153806. Change-Id: Iccc19e4808ddf6f15c32710f9bea931e46b046bf Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149920 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-04-03tdf#153806 a11y: Improve keyboard interaction in special char dialogMichael Weghorn
Make interacting with the "Special Characters" dialog using the keyboard more intuitive and consistent: * Call the selection handler (that changes the "OK" button to be sensitive) when a new entry is selected, as happens e.g. when tabbing into the table of characters, at which point the currently focused character is already considered selected (as e.g. indicated by the fact that other UI elements in the dialog are already updated according to that selection). This previously required pressing the space key (or moving back and forth using the arrow keys) for no apparent reason. * When a character in the character table is selected, insert it into the document when pressing the space key, as happens when double-clicking the entry using the mouse. Insertion using the space key already works for the characters in the "Recent Characters" and "Favorite Characters" sections below the table, so this also makes the behavior more consistent within the dialog. Change-Id: I35072f565b26d1f6c12c7dc8b7c6592f6a985a03 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147657 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-04-02Avoid conversions between OUString and OString in VCLMike Kaganski
Standardize on OUString, which is the main internal string class. Convert from/to OUString only when communicating with respective external APIs. Removes about 200 conversions from the code. Change-Id: I96ecee7c6fd271bb76639220e96d69d2964bed26 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149930 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2023-03-24Delete temporary variableAndreas Heinisch
Change-Id: I5d0fc2a4b078e49be684b4a9b8a27f6059d9e5c3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149475 Tested-by: Jenkins Reviewed-by: Andreas Heinisch <andreas.heinisch@yahoo.de>
2023-03-08tdf#153918 svx a11y: Drop old items when switching FontCharMapMichael Weghorn
Calling `rRenderContext.GetFontCharMap(mxFontCharMap)` in `SvxShowCharSet::RecalculateFont` means that a new `FontCharMapRef` gets assigned to `mxFontCharMap`. Therefore, clear the old items based on the previous one from the map, so that new ones will be created based on the new font char map in `SvxShowCharSet::ImplGetItem` as needed instead of still returning the old ones. Adapt the a11y UI test to check again that the "!" character now has the proper accessible name. The incorrect accessible name in the special characters dialog had actually been uncovered by the initial version of the test that failed on Windows due to this, and the test was adapted to workaround that, s. tdf#153918 and the discussion in the Gerrit change adding the test [1] for more details. [1] https://gerrit.libreoffice.org/c/core/+/142260/24..26/sw/qa/extras/accessibility/dialogs.cxx#b85 Change-Id: I0ac578750b1fa0a7e63e62a6937a125c7ceab510 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148423 Reviewed-by: Colomban Wendling <cwendling@hypra.fr> Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-03-04tdf#141319 - Special Characters Dialog: mark empty/unused cellsAndreas Heinisch
Change-Id: I123aef9f9763b2ae88c4b4f6748b69f9d9c394af Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148051 Tested-by: Jenkins Reviewed-by: Andreas Heinisch <andreas.heinisch@yahoo.de>
2023-03-01tdf#109214 - Highlight the favorites in the grid of special charactersAndreas Heinisch
Remove visual artifacts around the corners by using horizontal and vertical round. Change-Id: I9821103c43dfbd93e6f295034b05da8b74e802e4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148040 Tested-by: Jenkins Reviewed-by: Andreas Heinisch <andreas.heinisch@yahoo.de>
2022-10-25Update to ICU 72.1Eike Rathke
https://icu.unicode.org/download/72 Unicode 15 https://blog.unicode.org/2022/09/announcing-unicode-standard-version-150.html CLDR 42 https://blog.unicode.org/2022/10/unicode-cldr-v42-available.html New scripts: USCRIPT_KAWI USCRIPT_NAG_MUNDARI New Unicode blocks: UBLOCK_ARABIC_EXTENDED_C UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_H UBLOCK_CYRILLIC_EXTENDED_D UBLOCK_DEVANAGARI_EXTENDED_A UBLOCK_KAKTOVIK_NUMERALS UBLOCK_KAWI UBLOCK_NAG_MUNDARI Change-Id: I8822791e914e6700358b817a1af94b7dcd16b26d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141788 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Jenkins
2022-10-05tdf#151232 Fix lines in Special Characters dialog in dark modeRafael Lima
This patch makes the lines in the Special Characters dialog visible in dark mode. The Insert Symbols widget is also fixed with this patch. Tested in gen, gtk3 and kf5. Change-Id: Id1ee21557f2a0ea4ad8b60973d3de71e4d6d5d09 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140759 Tested-by: Jenkins Reviewed-by: V, Stuart Foote <vstuart.foote@utsa.edu> Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
2022-07-21clang-tidy modernize-pass-by-value in svxNoel Grandin
Change-Id: Iedd87d321f4d161574df87629fdd6c7714ff31c5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137248 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2022-06-10Add asserts to those places where I fixed a EXCEPTION_INT_DIVIDE_BY_ZEROXisco Fauli
I found those crashes scraping https://crashreport.libreoffice.org/stats/ so those are blind fixes basically. Add these asserts, hoping one day someone will hit them so we can find the root cause. See 7c8b9fa98f4c5f7f5620e797dbbe24081e252548 fae937b6859517bd9fe8e400cad3c84561ff98ab ce39195e533336ce1482e2be6b1bec2b7f992125 23e3bff528ab38c8d5c6d401b672a0033cef2bd4 ea4cd397300120a0f825752182eb3b943eb8a1b2 Change-Id: I175f47361e07961417c87cc8f3d7d4d1fb50fb2c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135448 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
2022-05-25svx: fix one more EXCEPTION_INT_DIVIDE_BY_ZEROXisco Fauli
See https://crashreport.libreoffice.org/stats/signature/SvxShowCharSet::PixelToMapIndex(Point%20const%20&) Change-Id: Ied5698fd47220fae54d72be263c3eeed5fb77911 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/134890 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
2022-05-03Just use Any ctor instead of makeAny in svxStephan Bergmann
Change-Id: I59b1b3f817a9028f132456ea5094f38f88674d00 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133768 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2022-03-16tdf#109214 - Highlight the favorites in the grid of special charactersAndreas Heinisch
Change-Id: Ie1bb019495d2db4acd92da4bccf44ece2bd1d976 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131446 Tested-by: Jenkins Reviewed-by: Heiko Tietze <heiko.tietze@documentfoundation.org>
2022-03-07do not pass XComponentContext to officecfg::...::get() callsLuboš Luňák
It's used only for the ConfigurationWrapper singleton, so it's used only the first time and then ignored. It also causes calls to comphelper::getProcessComponentContext() for every single invocation despite the value not being needed, and the calls may not be cheap (it's ~5% CPU during ODS save because relatively frequent calls to officecfg::Office::Common::Save::ODF::DefaultVersion::get()). Change-Id: I02c17a1a9cb498aeef220ddd5a0bde5523cb0ffb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131056 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
2022-01-20WASM --enable-wasm-strip now skips lots of LO codeArmin Le Grand (Allotropia)
... resulting in a stripped-down, Writer-only build to decrease the resulting WASM bytecode size. It removes the following code from the build: * All other major modules: Base, Calc, Chart, Draw, Impress and Math and related writerperfect filters * The premultiply tables * The (auto-)recovery functionality * All accessibility (but not the accessibility document checker) * The LanguageGuess component * EPUB support * The start center / BackingWindow * The TipOfTheDay functionality * The splash screen communication Currently crashs with anything different then soffice --writer. Closing the document also still crashes. FYI: many of these features are now behind ENABLE_WASM_STRIP_* defines, but they normally don't work on their own, globally! That's because we started with stripping the main components. Change-Id: Ib9c0f9452815910c0a2aceaf142ba1ad4a9cb0d7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126182 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2021-12-17Fix typosAndrea Gelmini
Change-Id: I7f1636226c4fbe29d9d2ef850318a9d57f1b5450 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127009 Tested-by: Julien Nabet <serval2412@yahoo.fr> Reviewed-by: Julien Nabet <serval2412@yahoo.fr>
2021-11-16Update to ICU 70.1Eike Rathke
Unicode 14, 5 new scripts, 12 new Unicode blocks. In i18npool/qa/cppunit/test_breakiterator.cxx TestBreakIterator::testLao() had to be disabled/adapted. Needs to be investigated, see comments there. As is, Lao script word break has regressions. Correct UBLOCK_TANGUT_SUPPLEMENT Unicode range endpoint to 0x18D7F, see https://www.unicode.org/versions/Unicode14.0.0/erratafixed.html for which ublock_getCode(0x18D8F) now returned UBLOCK_NO_BLOCK and thus luckily the assert in svx/source/dialog/charmap.cxx hit. Change-Id: I4bad16ecfab3f44be365b8f884c57f34af68218e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125322 Reviewed-by: Eike Rathke <erack@redhat.com> Tested-by: Jenkins
2021-10-31Prepare for removal of non-const operator[] from Sequence in svxMike Kaganski
Change-Id: Ib5fda9469f9a1987cf9071c0e228c582cfb3dfa1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/124397 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2021-10-04loplugin:constmethodNoel Grandin
Change-Id: I56af10be5f1155db4c7f2190495fe036a9b4236a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123054 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2021-09-20clean up ambiguous confusing rectangle APIs like IsInside()Luboš Luňák
Reading 'rectA.IsInside( rectB )' kind of suggests that the code checks whether 'rectA is inside rectB', but it's actually the other way around. Rename IsInside() -> Contains(), IsOver() -> Overlaps(), which should make it clear which way the logic goes. Change-Id: I9347450fe7dc34c96df6d636a4e3e660de1801ac Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122271 Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk> Reviewed-by: Luboš Luňák <l.lunak@collabora.com> Tested-by: Jenkins
2021-08-20New loplugin:unusedcapturedefaultStephan Bergmann
In sc/qa/unit/ucalc_formula.cxx, dropping the capture-default from the lExpectedinF lambda revealed that MSVC in C++17 mode (i.e., when building without --with-latest-c++) requires ROW_RANGE (a local const int variable from the enclosing TestFormula::testTdf97369) to be captured, even though all uses of that variable within the lambda body are constant expressions. That is still true at least for the latest Visual Studio 2019 version 16.11.1. (This is not an issue for the lExpectedinH and lExpectedinI lambdas a few lines further down, as they, in addition to using that ROW_RANGE, also use the local const double variables SHIFT1 and SHIFT2, whose uses are not constant expressions, so they are implicitly captured and loplugin:unusedcapturedefault does not suggest dropping those lambdas' capture-defaults in the first place.) Change-Id: Iee7efb485187cbe8eba6a2d470afca4993eb1816 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120693 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2021-08-18undo changes to TextAlignCaolán McNamara
revert commit 8689bd5490b473a7ffb149bbe5f7f0683f679c72 Author: Caolán McNamara <caolanm@redhat.com> Date: Thu Jul 29 20:49:29 2021 +0100 convert TextAlign to scoped enum lets leave this as it always was Change-Id: Id4d2a5644974cdd2b0ed6d361d5c52629674d057 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120626 Tested-by: Caolán McNamara <caolanm@redhat.com> Reviewed-by: Caolán McNamara <caolanm@redhat.com>
2021-07-30convert TextAlign to scoped enumCaolán McNamara
Change-Id: Id2c466eacb44f0ea6adba75a0ac0be8be8e7ed4c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/119682 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
2021-06-14We only support ICU version 4.6 or newer, so drop these checksMike Kaganski
The minimal ICU version check is in configure.ac. Change-Id: Ib6480cd3290dabb45d87c6dcbcc9b5513d172e21 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/117119 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
2021-02-20loplugin:refcounting in svxNoel
Change-Id: I79afd219a29ad176ce72020579d2b29a0b3ec09d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111220 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2021-02-19rename get_vscroll_width to get_scroll_thicknessCaolán McNamara
and add split customize_scrollbars to form a separate set_scroll_thickness Change-Id: Ia4b1c85d6ae85b0fb7aeb852d3a91b36b63143db Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111207 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com>
2021-02-15loplugin:referencecasting in svxNoel
Change-Id: I072ba9da976cefd61f4a916e70b0601439e8a123 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110818 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2020-11-30loplugin:stringviewparam include comparisons with string literalsNoel
Change-Id: I8ba1214500dddaf413c506a4b82f43d63cda804b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/106559 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>