summaryrefslogtreecommitdiff
path: root/vcl/unx/kde4
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/unx/kde4')
-rw-r--r--vcl/unx/kde4/KDEData.cxx57
-rw-r--r--vcl/unx/kde4/KDEData.hxx45
-rw-r--r--vcl/unx/kde4/KDESalDisplay.cxx97
-rw-r--r--vcl/unx/kde4/KDESalDisplay.hxx55
-rw-r--r--vcl/unx/kde4/KDESalFrame.cxx407
-rw-r--r--vcl/unx/kde4/KDESalFrame.hxx61
-rw-r--r--vcl/unx/kde4/KDESalGraphics.cxx992
-rw-r--r--vcl/unx/kde4/KDESalGraphics.hxx117
-rw-r--r--vcl/unx/kde4/KDESalInstance.cxx38
-rw-r--r--vcl/unx/kde4/KDESalInstance.hxx44
-rw-r--r--vcl/unx/kde4/KDEXLib.cxx422
-rw-r--r--vcl/unx/kde4/KDEXLib.hxx94
-rw-r--r--vcl/unx/kde4/VCLKDEApplication.cxx54
-rw-r--r--vcl/unx/kde4/VCLKDEApplication.hxx52
-rw-r--r--vcl/unx/kde4/main.cxx96
-rw-r--r--vcl/unx/kde4/makefile.mk96
16 files changed, 2727 insertions, 0 deletions
diff --git a/vcl/unx/kde4/KDEData.cxx b/vcl/unx/kde4/KDEData.cxx
new file mode 100644
index 000000000000..97654cf41e76
--- /dev/null
+++ b/vcl/unx/kde4/KDEData.cxx
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "KDEData.hxx"
+
+#include "KDEXLib.hxx"
+
+KDEData::~KDEData()
+{
+}
+
+void KDEData::Init()
+{
+ pXLib_ = new KDEXLib();
+ pXLib_->Init();
+}
+
+void KDEData::initNWF()
+{
+ ImplSVData *pSVData = ImplGetSVData();
+
+ // draw toolbars on separate lines
+ pSVData->maNWFData.mbDockingAreaSeparateTB = true;
+ // no borders for menu, theming does that
+ pSVData->maNWFData.mbFlatMenu = true;
+}
+
+void KDEData::deInitNWF()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDEData.hxx b/vcl/unx/kde4/KDEData.hxx
new file mode 100644
index 000000000000..31dc7b9dcba7
--- /dev/null
+++ b/vcl/unx/kde4/KDEData.hxx
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <saldisp.hxx>
+#include <saldata.hxx>
+
+class KDEData : public X11SalData
+{
+ public:
+ KDEData() {}
+ virtual ~KDEData();
+
+ virtual void Init();
+ virtual void initNWF();
+ virtual void deInitNWF();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDESalDisplay.cxx b/vcl/unx/kde4/KDESalDisplay.cxx
new file mode 100644
index 000000000000..29292b68f142
--- /dev/null
+++ b/vcl/unx/kde4/KDESalDisplay.cxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "KDESalDisplay.hxx"
+
+#include "KDEXLib.hxx"
+#include "VCLKDEApplication.hxx"
+
+#include <assert.h>
+#include <saldata.hxx>
+
+SalKDEDisplay* SalKDEDisplay::selfptr = NULL;
+
+SalKDEDisplay::SalKDEDisplay( Display* pDisp )
+ : SalX11Display( pDisp )
+{
+ assert( selfptr == NULL );
+ selfptr = this;
+ xim_protocol = XInternAtom( pDisp_, "_XIM_PROTOCOL", False );
+}
+
+SalKDEDisplay::~SalKDEDisplay()
+{
+ // in case never a frame opened
+ static_cast<KDEXLib*>(GetXLib())->doStartup();
+ // clean up own members
+ doDestruct();
+ selfptr = NULL;
+ // prevent SalDisplay from closing KApplication's display
+ pDisp_ = NULL;
+}
+
+void SalKDEDisplay::Yield()
+{
+ if( DispatchInternalEvent() )
+ return;
+
+ DBG_ASSERT( static_cast<SalYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())->GetThreadId() ==
+ osl::Thread::getCurrentIdentifier(),
+ "will crash soon since solar mutex not locked in SalKDEDisplay::Yield" );
+
+ XEvent event;
+ XNextEvent( pDisp_, &event );
+ if( checkDirectInputEvent( &event ))
+ return;
+ qApp->x11ProcessEvent( &event );
+}
+
+// HACK: When using Qt event loop, input methods (japanese, etc.) will get broken because
+// of XFilterEvent() getting called twice, once by Qt, once by LO (bnc#665112).
+// This function is therefore called before any XEvent is passed to Qt event handling
+// and if it is a keyboard event and no Qt widget is the active window (i.e. we are
+// processing events for some LO window), then feed the event only to LO directly and skip Qt
+// completely. Skipped events are KeyPress, KeyRelease and also _XIM_PROTOCOL client message
+// (seems to be necessary too, hopefully there are not other internal XIM messages that
+// would need this handling).
+bool SalKDEDisplay::checkDirectInputEvent( XEvent* ev )
+{
+ if( ev->xany.type == XLIB_KeyPress || ev->xany.type == KeyRelease
+ || ( ev->xany.type == ClientMessage && ev->xclient.message_type == xim_protocol ))
+ {
+ if( qApp->activeWindow() == NULL )
+ {
+ Dispatch(ev);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDESalDisplay.hxx b/vcl/unx/kde4/KDESalDisplay.hxx
new file mode 100644
index 000000000000..3b7117684942
--- /dev/null
+++ b/vcl/unx/kde4/KDESalDisplay.hxx
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <saldisp.hxx>
+
+class SalKDEDisplay : public SalX11Display
+{
+ public:
+ SalKDEDisplay( Display* pDisp );
+ virtual ~SalKDEDisplay();
+ static SalKDEDisplay* self();
+ inline int userEventsCount() const { return m_aUserEvents.size(); }
+ inline void EventGuardAcquire() { osl_acquireMutex( hEventGuard_ ); }
+ inline void EventGuardRelease() { osl_releaseMutex( hEventGuard_ ); }
+// virtual long Dispatch( XEvent *event );
+ virtual void Yield();
+ bool checkDirectInputEvent( XEvent* ev );
+ private:
+ Atom xim_protocol;
+ static SalKDEDisplay* selfptr;
+};
+
+inline SalKDEDisplay* SalKDEDisplay::self()
+{
+ return selfptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDESalFrame.cxx b/vcl/unx/kde4/KDESalFrame.cxx
new file mode 100644
index 000000000000..69826443a6c2
--- /dev/null
+++ b/vcl/unx/kde4/KDESalFrame.cxx
@@ -0,0 +1,407 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define Region QtXRegion
+
+#include <QColor>
+#include <QStyle>
+
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kmenubar.h>
+#include <kconfiggroup.h>
+#include <kmainwindow.h>
+#include <kapplication.h>
+#include <ktoolbar.h>
+
+#undef Region
+
+#include "KDESalFrame.hxx"
+#include "KDEXLib.hxx"
+#include "KDESalGraphics.hxx"
+
+#include <vcl/settings.hxx>
+#include <vcl/font.hxx>
+#include <tools/color.hxx>
+
+#include <vcl/svdata.hxx>
+
+#include <pspgraphics.h>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+KDESalFrame::KDESalFrame( SalFrame* pParent, sal_uLong nState ) :
+ X11SalFrame( pParent, nState )
+{
+}
+
+void KDESalFrame::Show( sal_Bool bVisible, sal_Bool bNoActivate )
+{
+ if ( !GetParent() && ! (GetStyle() & SAL_FRAME_STYLE_INTRO) )
+ {
+ KDEXLib* pXLib = static_cast<KDEXLib*>(GetDisplay()->GetXLib());
+ pXLib->doStartup();
+ }
+
+ X11SalFrame::Show( bVisible, bNoActivate );
+}
+
+/** Helper function to convert colors.
+*/
+static Color toColor( const QColor &rColor )
+{
+ return Color( rColor.red(), rColor.green(), rColor.blue() );
+}
+
+/** Helper function to read untranslated text entry from KConfig configuration repository.
+*/
+static OUString readEntryUntranslated( KConfigGroup *pGroup, const char *pKey )
+{
+ return OUString::createFromAscii( (const char *) pGroup->readEntryUntranslated( pKey ).toAscii() );
+}
+
+#if 0
+#endif
+/** Helper function to add information to Font from QFont.
+
+ Mostly grabbed from the Gtk+ vclplug (salnativewidgets-gtk.cxx).
+*/
+static Font toFont( const QFont &rQFont, const ::com::sun::star::lang::Locale& rLocale )
+{
+ psp::FastPrintFontInfo aInfo;
+ QFontInfo qFontInfo( rQFont );
+
+ // set family name
+ aInfo.m_aFamilyName = String( (const char *) rQFont.family().toUtf8(), RTL_TEXTENCODING_UTF8 );
+
+ // set italic
+ aInfo.m_eItalic = ( qFontInfo.italic()? psp::italic::Italic: psp::italic::Upright );
+
+ // set weight
+ int nWeight = qFontInfo.weight();
+ if ( nWeight <= QFont::Light )
+ aInfo.m_eWeight = psp::weight::Light;
+ else if ( nWeight <= QFont::Normal )
+ aInfo.m_eWeight = psp::weight::Normal;
+ else if ( nWeight <= QFont::DemiBold )
+ aInfo.m_eWeight = psp::weight::SemiBold;
+ else if ( nWeight <= QFont::Bold )
+ aInfo.m_eWeight = psp::weight::Bold;
+ else
+ aInfo.m_eWeight = psp::weight::UltraBold;
+
+ // set width
+ int nStretch = rQFont.stretch();
+ if ( nStretch <= QFont::UltraCondensed )
+ aInfo.m_eWidth = psp::width::UltraCondensed;
+ else if ( nStretch <= QFont::ExtraCondensed )
+ aInfo.m_eWidth = psp::width::ExtraCondensed;
+ else if ( nStretch <= QFont::Condensed )
+ aInfo.m_eWidth = psp::width::Condensed;
+ else if ( nStretch <= QFont::SemiCondensed )
+ aInfo.m_eWidth = psp::width::SemiCondensed;
+ else if ( nStretch <= QFont::Unstretched )
+ aInfo.m_eWidth = psp::width::Normal;
+ else if ( nStretch <= QFont::SemiExpanded )
+ aInfo.m_eWidth = psp::width::SemiExpanded;
+ else if ( nStretch <= QFont::Expanded )
+ aInfo.m_eWidth = psp::width::Expanded;
+ else if ( nStretch <= QFont::ExtraExpanded )
+ aInfo.m_eWidth = psp::width::ExtraExpanded;
+ else
+ aInfo.m_eWidth = psp::width::UltraExpanded;
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "font name BEFORE system match: \"%s\"\n", OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+
+ // match font to e.g. resolve "Sans"
+ psp::PrintFontManager::get().matchFont( aInfo, rLocale );
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "font match %s, name AFTER: \"%s\"\n",
+ aInfo.m_nID != 0 ? "succeeded" : "failed",
+ OUStringToOString( aInfo.m_aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ).getStr() );
+#endif
+
+ // font height
+ int nPointHeight = qFontInfo.pointSize();
+ if ( nPointHeight <= 0 )
+ nPointHeight = rQFont.pointSize();
+
+ // Create the font
+ Font aFont( aInfo.m_aFamilyName, Size( 0, nPointHeight ) );
+ if( aInfo.m_eWeight != psp::weight::Unknown )
+ aFont.SetWeight( PspGraphics::ToFontWeight( aInfo.m_eWeight ) );
+ if( aInfo.m_eWidth != psp::width::Unknown )
+ aFont.SetWidthType( PspGraphics::ToFontWidth( aInfo.m_eWidth ) );
+ if( aInfo.m_eItalic != psp::italic::Unknown )
+ aFont.SetItalic( PspGraphics::ToFontItalic( aInfo.m_eItalic ) );
+ if( aInfo.m_ePitch != psp::pitch::Unknown )
+ aFont.SetPitch( PspGraphics::ToFontPitch( aInfo.m_ePitch ) );
+
+ return aFont;
+}
+
+/** Implementation of KDE integration's main method.
+*/
+void KDESalFrame::UpdateSettings( AllSettings& rSettings )
+{
+ StyleSettings style( rSettings.GetStyleSettings() );
+ bool bSetTitleFont = false;
+
+ // General settings
+ QPalette pal = kapp->palette();
+
+ style.SetToolbarIconSize( STYLE_TOOLBAR_ICONSIZE_LARGE );
+
+ style.SetActiveColor(toColor(pal.color(QPalette::Active, QPalette::Window)));
+ style.SetDeactiveColor(toColor(pal.color(QPalette::Inactive, QPalette::Window)));
+
+ style.SetActiveColor2(toColor(pal.color(QPalette::Active, QPalette::Window)));
+ style.SetDeactiveColor2(toColor(pal.color(QPalette::Inactive, QPalette::Window)));
+
+ style.SetActiveTextColor(toColor(pal.color(QPalette::Active, QPalette::WindowText)));
+ style.SetDeactiveTextColor(toColor(pal.color(QPalette::Inactive, QPalette::WindowText)));
+
+ // WM settings
+ KConfig *pConfig = KGlobal::config().data();
+ if ( pConfig )
+ {
+ KConfigGroup aGroup = pConfig->group( "WM" );
+ const char *pKey;
+
+ pKey = "titleFont";
+ if ( aGroup.hasKey( pKey ) )
+ {
+ Font aFont = toFont( aGroup.readEntry( pKey, QFont() ), rSettings.GetUILocale() );
+ style.SetTitleFont( aFont );
+ bSetTitleFont = true;
+ }
+
+ aGroup = pConfig->group( "Icons" );
+
+ pKey = "Theme";
+ if ( aGroup.hasKey( pKey ) )
+ style.SetPreferredSymbolsStyleName( readEntryUntranslated( &aGroup, pKey ) );
+
+ //toolbar
+ pKey = "toolbarFont";
+ if ( aGroup.hasKey( pKey ) )
+ {
+ Font aFont = toFont( aGroup.readEntry( pKey, QFont() ), rSettings.GetUILocale() );
+ style.SetToolFont( aFont );
+ }
+ }
+
+ 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 ) );
+
+ // Foreground
+ style.SetRadioCheckTextColor( aFore );
+ style.SetLabelTextColor( aFore );
+ style.SetInfoTextColor( aFore );
+ style.SetDialogTextColor( aFore );
+ style.SetGroupTextColor( aFore );
+
+ // Text
+ style.SetFieldTextColor( aText );
+ style.SetFieldRolloverTextColor( aText );
+ style.SetWindowTextColor( aText );
+ style.SetHelpTextColor( aText );
+
+ // Base
+ style.SetFieldColor( aBase );
+ style.SetHelpColor( aBase );
+ style.SetWindowColor( aBase );
+ style.SetActiveTabColor( aBase );
+
+ // Buttons
+ style.SetButtonTextColor( aButn );
+ style.SetButtonRolloverTextColor( aButn );
+
+ // Disable color
+ style.SetDisableColor( aMid );
+
+ // Workspace
+ style.SetWorkspaceColor( aMid );
+
+ // Background
+ style.Set3DColors( aBack );
+ style.SetFaceColor( aBack );
+ style.SetInactiveTabColor( aBack );
+ style.SetDialogColor( aBack );
+
+ if( aBack == COL_LIGHTGRAY )
+ style.SetCheckedColor( Color( 0xCC, 0xCC, 0xCC ) );
+ else
+ {
+ Color aColor2 = style.GetLightColor();
+ style.
+ SetCheckedColor( Color( (sal_uInt8)(((sal_uInt16)aBack.GetRed()+(sal_uInt16)aColor2.GetRed())/2),
+ (sal_uInt8)(((sal_uInt16)aBack.GetGreen()+(sal_uInt16)aColor2.GetGreen())/2),
+ (sal_uInt8)(((sal_uInt16)aBack.GetBlue()+(sal_uInt16)aColor2.GetBlue())/2)
+ ) );
+ }
+
+ // Selection
+ style.SetHighlightColor( aHigh );
+ style.SetHighlightTextColor( toColor(pal.color( QPalette::HighlightedText)) );
+
+ // Font
+ Font aFont = toFont( kapp->font(), rSettings.GetUILocale() );
+
+ style.SetAppFont( aFont );
+ style.SetHelpFont( aFont );
+
+ style.SetMenuFont( aFont ); // will be changed according to pMenuBar
+ //style.SetToolFont( aFont ); //already set above
+ style.SetLabelFont( aFont );
+ style.SetInfoFont( aFont );
+ style.SetRadioCheckFont( aFont );
+ style.SetPushButtonFont( aFont );
+ style.SetFieldFont( aFont );
+ style.SetIconFont( aFont );
+ style.SetGroupFont( aFont );
+
+ aFont.SetWeight( WEIGHT_BOLD );
+ if( !bSetTitleFont )
+ {
+ style.SetTitleFont( aFont );
+ }
+ style.SetFloatTitleFont( aFont );
+
+ int flash_time = QApplication::cursorFlashTime();
+ style.SetCursorBlinkTime( flash_time != 0 ? flash_time/2 : STYLE_CURSOR_NOBLINKTIME );
+
+ // Menu
+ style.SetSkipDisabledInMenus( TRUE );
+ KMenuBar* pMenuBar = new KMenuBar();
+ if ( pMenuBar )
+ {
+ // Color
+ 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 ) );
+
+ aMenuFore = toColor( qMenuCG.color( QPalette::ButtonText ) );
+ aMenuBack = toColor( qMenuCG.color( QPalette::Button ) );
+
+ style.SetMenuTextColor( aMenuFore );
+ style.SetMenuBarTextColor( aMenuFore );
+ style.SetMenuColor( aMenuBack );
+ style.SetMenuBarColor( aMenuBack );
+
+ style.SetMenuHighlightColor( toColor ( qMenuCG.color( QPalette::Highlight ) ) );
+
+ style.SetMenuHighlightTextColor( aMenuFore );
+
+ // set special menubar higlight text color
+ if ( kapp->style()->inherits( "HighContrastStyle" ) )
+ ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor = toColor( qMenuCG.color( QPalette::HighlightedText ) );
+ else
+ ImplGetSVData()->maNWFData.maMenuBarHighlightTextColor = aMenuFore;
+
+ // Font
+ aFont = toFont( pMenuBar->font(), rSettings.GetUILocale() );
+ style.SetMenuFont( aFont );
+ }
+
+ delete pMenuBar;
+
+ // Scroll bar size
+ style.SetScrollBarSize( kapp->style()->pixelMetric( QStyle::PM_ScrollBarExtent ) );
+ style.SetMinThumbSize( kapp->style()->pixelMetric( QStyle::PM_ScrollBarSliderMin ));
+
+ rSettings.SetStyleSettings( style );
+}
+
+
+void KDESalFrame::ReleaseGraphics( SalGraphics *pGraphics )
+{
+ for( int i = 0; i < nMaxGraphics; i++ )
+ {
+ if( m_aGraphics[i].pGraphics == pGraphics )
+ {
+ m_aGraphics[i].bInUse = false;
+ break;
+ }
+ }
+}
+
+void KDESalFrame::updateGraphics( bool bClear )
+{
+ Drawable aDrawable = bClear ? None : GetWindow();
+ for( int i = 0; i < nMaxGraphics; i++ )
+ {
+ if( m_aGraphics[i].bInUse )
+ m_aGraphics[i].pGraphics->SetDrawable( aDrawable, GetScreenNumber() );
+ }
+}
+
+KDESalFrame::~KDESalFrame()
+{
+}
+
+KDESalFrame::GraphicsHolder::~GraphicsHolder()
+{
+ delete pGraphics;
+}
+
+SalGraphics* KDESalFrame::GetGraphics()
+{
+ if( GetWindow() )
+ {
+ for( int i = 0; i < nMaxGraphics; i++ )
+ {
+ if( ! m_aGraphics[i].bInUse )
+ {
+ m_aGraphics[i].bInUse = true;
+ if( ! m_aGraphics[i].pGraphics )
+ {
+ m_aGraphics[i].pGraphics = new KDESalGraphics();
+ m_aGraphics[i].pGraphics->Init( this, GetWindow(), GetScreenNumber() );
+ }
+ return m_aGraphics[i].pGraphics;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDESalFrame.hxx b/vcl/unx/kde4/KDESalFrame.hxx
new file mode 100644
index 000000000000..f006a6e0d796
--- /dev/null
+++ b/vcl/unx/kde4/KDESalFrame.hxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <saldisp.hxx>
+#include <salframe.h>
+
+class KDESalFrame : public X11SalFrame
+{
+ private:
+ static const int nMaxGraphics = 2;
+
+ struct GraphicsHolder
+ {
+ X11SalGraphics* pGraphics;
+ bool bInUse;
+
+ GraphicsHolder() : pGraphics(0),bInUse( false ) {}
+ ~GraphicsHolder();
+ };
+
+ GraphicsHolder m_aGraphics[ nMaxGraphics ];
+
+ public:
+ KDESalFrame( SalFrame* pParent, sal_uLong nStyle );
+ virtual ~KDESalFrame();
+
+ virtual SalGraphics* GetGraphics();
+ virtual void ReleaseGraphics( SalGraphics *pGraphics );
+ virtual void updateGraphics( bool bClear );
+ virtual void UpdateSettings( AllSettings& rSettings );
+ virtual void Show( sal_Bool bVisible, sal_Bool bNoActivate );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDESalGraphics.cxx b/vcl/unx/kde4/KDESalGraphics.cxx
new file mode 100644
index 000000000000..04f71bfbed3d
--- /dev/null
+++ b/vcl/unx/kde4/KDESalGraphics.cxx
@@ -0,0 +1,992 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#define _SV_SALNATIVEWIDGETS_KDE_CXX
+
+#define Region QtXRegion
+
+#include <QStyle>
+#include <QStyleOption>
+#include <QPainter>
+#include <QFrame>
+#include <QLabel>
+
+#include <kapplication.h>
+#include <kdebug.h>
+
+#undef Region
+
+#include "KDESalGraphics.hxx"
+
+#include "vcl/settings.hxx"
+#include "vcl/decoview.hxx"
+#include "rtl/ustrbuf.hxx"
+
+using namespace ::rtl;
+
+/**
+ Conversion function between VCL ControlState together with
+ ImplControlValue and Qt state flags.
+ @param nControlState State of the widget (default, focused, ...) in Native Widget Framework.
+ @param aValue Value held by the widget (on, off, ...)
+*/
+QStyle::State vclStateValue2StateFlag( ControlState nControlState,
+ const ImplControlValue& aValue )
+{
+ QStyle::State nState =
+ ( (nControlState & CTRL_STATE_DEFAULT)? QStyle::State_None: QStyle::State_None ) |
+ ( (nControlState & CTRL_STATE_ENABLED)? QStyle::State_Enabled: QStyle::State_None ) |
+ ( (nControlState & CTRL_STATE_FOCUSED)? QStyle::State_HasFocus: QStyle::State_None ) |
+ ( (nControlState & CTRL_STATE_PRESSED)? QStyle::State_Sunken: QStyle::State_None ) |
+ ( (nControlState & CTRL_STATE_SELECTED)? QStyle::State_Selected : QStyle::State_None ) |
+ ( (nControlState & CTRL_STATE_ROLLOVER)? QStyle::State_MouseOver: QStyle::State_None );
+ //TODO ( (nControlState & CTRL_STATE_HIDDEN)? QStyle::State_: QStyle::State_None ) |
+
+ switch ( aValue.getTristateVal() )
+ {
+ case BUTTONVALUE_ON: nState |= QStyle::State_On; break;
+ case BUTTONVALUE_OFF: nState |= QStyle::State_Off; break;
+ case BUTTONVALUE_MIXED: nState |= QStyle::State_NoChange; break;
+ default: break;
+ }
+
+ return nState;
+}
+
+/**
+ Convert VCL Rectangle to QRect.
+ @param rControlRegion The Rectangle to convert.
+ @return The matching QRect
+*/
+QRect region2QRect( const Rectangle& rControlRegion )
+{
+ return QRect(rControlRegion.Left(), rControlRegion.Top(), rControlRegion.GetWidth(), rControlRegion.GetHeight());
+}
+
+KDESalGraphics::KDESalGraphics() :
+ m_image(0)
+{
+}
+
+KDESalGraphics::~KDESalGraphics()
+{
+ if (m_image)
+ delete m_image;
+}
+
+sal_Bool KDESalGraphics::IsNativeControlSupported( ControlType type, ControlPart part )
+{
+ if (type == CTRL_PUSHBUTTON) return true;
+
+ if (type == CTRL_MENUBAR) return true;
+
+ if (type == CTRL_MENU_POPUP) return true;
+
+ if (type == CTRL_EDITBOX) return true;
+
+ if (type == CTRL_COMBOBOX) return true;
+
+ if (type == CTRL_TOOLBAR) return true;
+
+ if (type == CTRL_CHECKBOX) return true;
+
+ if (type == CTRL_LISTBOX) return true;
+
+ if (type == CTRL_LISTNODE) return true;
+
+ if (type == CTRL_FRAME) return true;
+
+ if (type == CTRL_SCROLLBAR) return true;
+
+ if (type == CTRL_WINDOW_BACKGROUND) return true;
+
+ if (type == CTRL_SPINBOX && (part == PART_ENTIRE_CONTROL || part == HAS_BACKGROUND_TEXTURE) ) return true;
+
+ // no spinbuttons for KDE, paint spinbox complete
+ //if (type == CTRL_SPINBUTTONS) return true;
+
+ if (type == CTRL_GROUPBOX) return true;
+
+ if (type == CTRL_FIXEDLINE) return true;
+
+ if (type == CTRL_FIXEDBORDER) return true;
+
+ if (type == CTRL_TOOLTIP) return true;
+
+ if (type == CTRL_RADIOBUTTON) return true;
+
+ if (type == CTRL_SLIDER && (part == PART_TRACK_HORZ_AREA || part == PART_TRACK_VERT_AREA) )
+ return true;
+
+ if ( (type == CTRL_PROGRESS) && (part == PART_ENTIRE_CONTROL) ) return true;
+
+ return false;
+
+ if ( (type == CTRL_TAB_ITEM) && (part == PART_ENTIRE_CONTROL) ) return true;
+ if ( (type == CTRL_TAB_PANE) && (part == PART_ENTIRE_CONTROL) ) return true;
+ // no CTRL_TAB_BODY for KDE
+
+ return false;
+}
+
+/// helper drawing methods
+namespace
+{
+ void draw( QStyle::ControlElement element, QStyleOption* option, QImage* image, QStyle::State state, QRect rect = QRect())
+ {
+ option->state |= state;
+ option->rect = !rect.isNull() ? rect : image->rect();
+
+ QPainter painter(image);
+ kapp->style()->drawControl(element, option, &painter);
+ }
+
+ void draw( QStyle::PrimitiveElement element, QStyleOption* option, QImage* image, QStyle::State state, QRect rect = QRect())
+ {
+ option->state |= state;
+ option->rect = !rect.isNull() ? rect : image->rect();
+
+ QPainter painter(image);
+ kapp->style()->drawPrimitive(element, option, &painter);
+ }
+
+ void draw( QStyle::ComplexControl element, QStyleOptionComplex* option, QImage* image, QStyle::State state )
+ {
+ option->state |= state;
+ option->rect = image->rect();
+
+ QPainter painter(image);
+ kapp->style()->drawComplexControl(element, option, &painter);
+ }
+
+ int getFrameWidth()
+ {
+ static int s_nFrameWidth = -1;
+ if( s_nFrameWidth < 0 )
+ {
+ // fill in a default
+ s_nFrameWidth = 2;
+ QFrame aFrame( NULL );
+ aFrame.setFrameRect( QRect(0, 0, 100, 30) );
+ aFrame.setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
+ aFrame.ensurePolished();
+ s_nFrameWidth = aFrame.frameWidth();
+ }
+ return s_nFrameWidth;
+ }
+
+ void lcl_drawFrame(QStyle::PrimitiveElement element, QImage* image, QStyle::State state)
+ {
+ #if ( QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 ) )
+ QStyleOptionFrameV3 option;
+ option.frameShape = QFrame::StyledPanel;
+ option.state = QStyle::State_Sunken;
+ #else
+ QStyleOptionFrame option;
+
+ QFrame aFrame( NULL );
+ aFrame.setFrameRect( QRect(0, 0, image->width(), image->height()) );
+ aFrame.setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
+ aFrame.ensurePolished();
+
+ option.initFrom( &aFrame );
+ option.lineWidth = aFrame.lineWidth();
+ option.midLineWidth = aFrame.midLineWidth();
+ #endif
+
+ draw(element, &option, image, state);
+ }
+}
+
+#if QT_VERSION >= QT_VERSION_CHECK( 4, 5, 0 )
+#define IMAGE_BASED_PAINTING
+#else
+#undef IMAGE_BASED_PAINTING
+#endif
+
+#ifdef IMAGE_BASED_PAINTING
+// There is a small catch with this function, although hopefully only philosophical.
+// Officially Xlib's Region is an opaque data type, with only functions for manipulating it.
+// However, whoever designed it apparently didn't give it that much thought, as it's impossible
+// to find out what exactly a region actually is (except for really weird ways like XClipBox()
+// and repeated XPointInRegion(), which would be awfully slow). Fortunately, the header file
+// describing the structure actually happens to be installed too, and there's at least one
+// widely used software using it (Compiz). So access the data directly too and assume that
+// everybody who compiles with Qt4 support has Xlib new enough and good enough to support this.
+// In case this doesn't work for somebody, try #include <X11/region.h> instead, or build
+// without IMAGE_BASED_PAINTING (in which case QApplication::setGraphicsSystem( "native" ) may
+// be needed too).
+#include <X11/Xregion.h>
+static QRegion XRegionToQRegion( XLIB_Region xr )
+{
+ QRegion qr;
+ for( int i = 0;
+ i < xr->numRects;
+ ++i )
+ {
+ BOX& b = xr->rects[ i ];
+ qr |= QRect( b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1 ); // x2,y2 is outside, not the bottom-right corner
+ }
+ return qr;
+}
+#endif
+
+sal_Bool KDESalGraphics::drawNativeControl( ControlType type, ControlPart part,
+ const Rectangle& rControlRegion, ControlState nControlState,
+ const ImplControlValue& value,
+ const OUString& )
+{
+ if( lastPopupRect.isValid() && ( type != CTRL_MENU_POPUP || part != PART_MENU_ITEM ))
+ lastPopupRect = QRect();
+
+ // put not implemented types here
+ if (type == CTRL_SPINBUTTONS)
+ {
+ return false;
+ }
+
+ sal_Bool returnVal = true;
+
+ QRect widgetRect = region2QRect(rControlRegion);
+ if( type == CTRL_SPINBOX && part == PART_ALL_BUTTONS )
+ type = CTRL_SPINBUTTONS;
+ if( type == CTRL_SPINBUTTONS )
+ {
+ OSL_ASSERT( value.getType() != CTRL_SPINBUTTONS );
+ const SpinbuttonValue* pSpinVal = static_cast<const SpinbuttonValue *>(&value);
+ Rectangle aButtonRect( pSpinVal->maUpperRect);
+ aButtonRect.Union( pSpinVal->maLowerRect );;
+ widgetRect = QRect( aButtonRect.Left(), aButtonRect.Top(),
+ aButtonRect.Right(), aButtonRect.Bottom() );
+ }
+
+ //if no image, or resized, make a new image
+ if (!m_image || m_image->size() != widgetRect.size())
+ {
+ if (m_image)
+ delete m_image;
+
+ m_image = new QImage( widgetRect.width(),
+ widgetRect.height(),
+ QImage::Format_ARGB32 );
+ }
+ m_image->fill(KApplication::palette().color(QPalette::Window).rgb());
+
+ QRegion* clipRegion = NULL;
+
+ if (type == CTRL_PUSHBUTTON)
+ {
+ QStyleOptionButton option;
+ draw( QStyle::CE_PushButton, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if ( (type == CTRL_MENUBAR))
+ {
+ if (part == PART_MENU_ITEM)
+ {
+ QStyleOptionMenuItem option;
+ draw( QStyle::CE_MenuBarItem, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if (part == PART_ENTIRE_CONTROL)
+ {
+ }
+ else
+ {
+ returnVal = false;
+ }
+ }
+ else if (type == CTRL_MENU_POPUP)
+ {
+ OSL_ASSERT( part == PART_MENU_ITEM ? lastPopupRect.isValid() : !lastPopupRect.isValid());
+ if( part == PART_MENU_ITEM )
+ {
+ QStyleOptionMenuItem option;
+ draw( QStyle::CE_MenuItem, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ // HACK: LO core first paints the entire popup and only then it paints menu items,
+ // but QMenu::paintEvent() paints popup frame after all items. That means highlighted
+ // items here would paint the highlight over the frame border. Since calls to PART_MENU_ITEM
+ // are always preceded by calls to PART_ENTIRE_CONTROL, just remember the size for the whole
+ // popup (otherwise not possible to get here) and draw the border afterwards.
+ QRect framerect( lastPopupRect.topLeft() - widgetRect.topLeft(),
+ widgetRect.size().expandedTo( lastPopupRect.size()));
+ QStyleOptionFrame frame;
+ draw( QStyle::PE_FrameMenu, &frame, m_image, vclStateValue2StateFlag( nControlState, value ), framerect );
+ }
+ else if( part == PART_MENU_SEPARATOR )
+ {
+ QStyleOptionMenuItem option;
+ option.menuItemType = QStyleOptionMenuItem::Separator;
+ // Painting the whole menu item area results in different background
+ // with at least Plastique style, so clip only to the separator itself
+ // (QSize( 2, 2 ) is hardcoded in Qt)
+ option.rect = m_image->rect();
+ QSize size = kapp->style()->sizeFromContents( QStyle::CT_MenuItem, &option, QSize( 2, 2 ));
+ QRect rect = m_image->rect();
+ QPoint center = rect.center();
+ rect.setHeight( size.height());
+ rect.moveCenter( center );
+ // don't paint over popup frame border (like the hack above, but here it can be simpler)
+ int fw = kapp->style()->pixelMetric( QStyle::PM_MenuPanelWidth );
+ clipRegion = new QRegion( rect.translated( widgetRect.topLeft()).adjusted( fw, 0, -fw, 0 ));
+ draw( QStyle::CE_MenuItem, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value), rect );
+ }
+ else if( part == PART_MENU_ITEM_CHECK_MARK || part == PART_MENU_ITEM_RADIO_MARK )
+ {
+ QStyleOptionMenuItem option;
+ option.checkType = ( part == PART_MENU_ITEM_CHECK_MARK )
+ ? QStyleOptionMenuItem::NonExclusive : QStyleOptionMenuItem::Exclusive;
+ option.checked = ( nControlState & CTRL_STATE_PRESSED );
+ // widgetRect is now the rectangle for the checkbox/radiobutton itself, but Qt
+ // paints the whole menu item, so translate position (and it'll be clipped);
+ // it is also necessary to fill the background transparently first, as this
+ // is painted after menuitem highlight, otherwise there would be a grey area
+ const MenupopupValue* menuVal = static_cast<const MenupopupValue*>(&value);
+ QRect menuItemRect( region2QRect( menuVal->maItemRect ));
+ QRect rect( menuItemRect.topLeft() - widgetRect.topLeft(),
+ widgetRect.size().expandedTo( menuItemRect.size()));
+ m_image->fill( Qt::transparent );
+ draw( QStyle::CE_MenuItem, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value), rect );
+ }
+ else if( part == PART_ENTIRE_CONTROL )
+ {
+ QStyleOptionMenuItem option;
+ draw( QStyle::PE_PanelMenu, &option, m_image, vclStateValue2StateFlag( nControlState, value ));
+ QStyleOptionFrame frame;
+ draw( QStyle::PE_FrameMenu, &frame, m_image, vclStateValue2StateFlag( nControlState, value ));
+ lastPopupRect = widgetRect;
+ }
+ else
+ returnVal = false;
+ }
+ else if ( (type == CTRL_TOOLBAR) && (part == PART_BUTTON) )
+ {
+ QStyleOptionToolButton option;
+
+ option.arrowType = Qt::NoArrow;
+ option.subControls = QStyle::SC_ToolButton;
+
+ option.state = vclStateValue2StateFlag( nControlState, value );
+ option.state |= QStyle::State_Raised | QStyle::State_Enabled | QStyle::State_AutoRaise;
+
+ draw( QStyle::CC_ToolButton, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if ( (type == CTRL_TOOLBAR) && (part == PART_ENTIRE_CONTROL) )
+ {
+ QStyleOptionToolBar option;
+
+ option.rect = QRect(0, 0, widgetRect.width(), widgetRect.height());
+ option.state = vclStateValue2StateFlag( nControlState, value );
+
+ draw( QStyle::CE_ToolBar, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if ( (type == CTRL_TOOLBAR) && (part == PART_THUMB_VERT) )
+ { // reduce paint area only to the handle area
+ const int width = kapp->style()->pixelMetric(QStyle::PM_ToolBarHandleExtent);
+ QRect rect( 0, 0, width, widgetRect.height());
+ clipRegion = new QRegion( widgetRect.x(), widgetRect.y(), width, widgetRect.height());
+
+ QStyleOption option;
+ option.state = QStyle::State_Horizontal;
+
+ draw( QStyle::PE_IndicatorToolBarHandle, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value), rect );
+ }
+ else if (type == CTRL_EDITBOX)
+ {
+ QStyleOptionFrameV2 option;
+ draw( QStyle::PE_PanelLineEdit, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value), m_image->rect().adjusted( 2, 2, -2, -2 ));
+
+ draw( QStyle::PE_FrameLineEdit, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value));
+ }
+ else if (type == CTRL_COMBOBOX)
+ {
+ QStyleOptionComboBox option;
+ option.editable = true;
+
+ draw( QStyle::CC_ComboBox, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if (type == CTRL_LISTBOX)
+ {
+ if( part == PART_WINDOW )
+ {
+ lcl_drawFrame( QStyle::PE_Frame, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else
+ {
+ QStyleOptionComboBox option;
+ if (part == PART_SUB_EDIT)
+ {
+ draw( QStyle::CE_ComboBoxLabel, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else
+ {
+ draw( QStyle::CC_ComboBox, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ }
+ }
+ else if (type == CTRL_LISTNODE)
+ {
+ QStyleOption option;
+ option.state = QStyle::State_Item | QStyle::State_Children;
+
+ if (nControlState & CTRL_STATE_PRESSED)
+ option.state |= QStyle::State_Open;
+
+ draw( QStyle::PE_IndicatorBranch, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if (type == CTRL_CHECKBOX)
+ {
+ QStyleOptionButton option;
+ draw( QStyle::CE_CheckBox, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if (type == CTRL_SCROLLBAR)
+ {
+ if ((part == PART_DRAW_BACKGROUND_VERT) || (part == PART_DRAW_BACKGROUND_HORZ))
+ {
+ QStyleOptionSlider option;
+ OSL_ASSERT( value.getType() == CTRL_SCROLLBAR );
+ const ScrollbarValue* sbVal = static_cast<const ScrollbarValue *>(&value);
+
+ //if the scroll bar is active (aka not degenrate...allow for hover events
+ if (sbVal->mnVisibleSize < sbVal->mnMax)
+ option.state = QStyle::State_MouseOver;
+
+ //horizontal or vertical
+ if (part == PART_DRAW_BACKGROUND_VERT)
+ option.orientation = Qt::Vertical;
+ else
+ option.state |= QStyle::State_Horizontal;
+
+ //setup parameters from the OO values
+ option.minimum = sbVal->mnMin;
+ option.maximum = sbVal->mnMax - sbVal->mnVisibleSize;
+ option.maximum = qMax( option.maximum, option.minimum ); // bnc#619772
+ option.sliderValue = sbVal->mnCur;
+ option.sliderPosition = sbVal->mnCur;
+ option.pageStep = sbVal->mnVisibleSize;
+
+ //setup the active control...always the slider
+ if (sbVal->mnThumbState & CTRL_STATE_ROLLOVER)
+ option.activeSubControls = QStyle::SC_ScrollBarSlider;
+
+ draw( QStyle::CC_ScrollBar, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else
+ {
+ returnVal = false;
+ }
+ }
+ else if (type == CTRL_SPINBOX)
+ {
+ QStyleOptionSpinBox option;
+
+ // determine active control
+ if( value.getType() == CTRL_SPINBUTTONS )
+ {
+ const SpinbuttonValue* pSpinVal = static_cast<const SpinbuttonValue *>(&value);
+ if( (pSpinVal->mnUpperState & CTRL_STATE_PRESSED) )
+ option.activeSubControls |= QStyle::SC_SpinBoxUp;
+ if( (pSpinVal->mnLowerState & CTRL_STATE_PRESSED) )
+ option.activeSubControls |= QStyle::SC_SpinBoxDown;
+ }
+
+ draw( QStyle::CC_SpinBox, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if (type == CTRL_GROUPBOX)
+ {
+ QStyleOptionGroupBox option;
+ draw( QStyle::CC_GroupBox, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if (type == CTRL_RADIOBUTTON)
+ {
+ QStyleOptionButton option;
+ draw( QStyle::CE_RadioButton, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if (type == CTRL_TOOLTIP)
+ {
+ QStyleOption option;
+ draw( QStyle::PE_PanelTipLabel, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if (type == CTRL_FRAME)
+ {
+ lcl_drawFrame( QStyle::PE_Frame, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+
+ // draw just the border, see http://qa.openoffice.org/issues/show_bug.cgi?id=107945
+ int fw = getFrameWidth();
+ clipRegion = new QRegion( QRegion( widgetRect ).subtracted( widgetRect.adjusted( fw, fw, -fw, -fw )));
+ }
+ else if (type == CTRL_FIXEDBORDER)
+ {
+ lcl_drawFrame( QStyle::PE_FrameWindow, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if (type == CTRL_WINDOW_BACKGROUND)
+ {
+ m_image->fill(KApplication::palette().color(QPalette::Window).rgb());
+ }
+ else if (type == CTRL_FIXEDLINE)
+ {
+ QStyleOptionMenuItem option;
+ option.menuItemType = QStyleOptionMenuItem::Separator;
+ option.state |= QStyle::State_Item;
+
+ draw( QStyle::CE_MenuItem, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if (type == CTRL_SLIDER && (part == PART_TRACK_HORZ_AREA || part == PART_TRACK_VERT_AREA))
+ {
+ OSL_ASSERT( value.getType() == CTRL_SLIDER );
+ const SliderValue* slVal = static_cast<const SliderValue *>(&value);
+ QStyleOptionSlider option;
+
+ option.rect = QRect(0, 0, widgetRect.width(), widgetRect.height());
+ option.state = vclStateValue2StateFlag( nControlState, value );
+ option.maximum = slVal->mnMax;
+ option.minimum = slVal->mnMin;
+ option.sliderPosition = option.sliderValue = slVal->mnCur;
+ option.orientation = (part == PART_TRACK_HORZ_AREA) ? Qt::Horizontal : Qt::Vertical;
+
+ draw( QStyle::CC_Slider, &option, m_image, vclStateValue2StateFlag(nControlState, value) );
+ }
+ else if( type == CTRL_PROGRESS && part == PART_ENTIRE_CONTROL )
+ {
+ QStyleOptionProgressBarV2 option;
+ option.minimum = 0;
+ option.maximum = widgetRect.width();
+ option.progress = value.getNumericVal();
+ option.rect = QRect(0, 0, widgetRect.width(), widgetRect.height());
+ option.state = vclStateValue2StateFlag( nControlState, value );
+
+ draw( QStyle::CE_ProgressBar, &option, m_image,
+ vclStateValue2StateFlag(nControlState, value) );
+ }
+ else
+ {
+ returnVal = false;
+ }
+
+ if (returnVal)
+ {
+#ifdef IMAGE_BASED_PAINTING
+ // Create a wrapper QPixmap around the destination pixmap, allowing the use of QPainter.
+ // Using X11SalGraphics::CopyScreenArea() would require using QPixmap and if Qt uses
+ // other graphics system than native, QPixmap::handle() would be 0 (i.e. it wouldn't work),
+ // I have no idea how to create QPixmap with non-null handle() in such case, so go this way.
+ // See XRegionToQRegion() comment for a small catch (although not real hopefully).
+ QPixmap destPixmap = QPixmap::fromX11Pixmap( GetDrawable(), QPixmap::ExplicitlyShared );
+ QPainter paint( &destPixmap );
+ if( clipRegion && mpClipRegion )
+ paint.setClipRegion( clipRegion->intersected( XRegionToQRegion( mpClipRegion )));
+ else if( clipRegion )
+ paint.setClipRegion( *clipRegion );
+ else if( mpClipRegion )
+ paint.setClipRegion( XRegionToQRegion( mpClipRegion ));
+ paint.drawImage( widgetRect.left(), widgetRect.top(), *m_image,
+ 0, 0, widgetRect.width(), widgetRect.height(),
+ Qt::ColorOnly | Qt::OrderedDither | Qt::OrderedAlphaDither );
+#else
+ GC gc = SelectFont();
+ if( gc )
+ {
+ XLIB_Region pTempClipRegion = NULL;
+ if( clipRegion )
+ {
+ pTempClipRegion = XCreateRegion();
+ foreach( const QRect& r, clipRegion->rects())
+ {
+ XRectangle xr;
+ xr.x = r.x();
+ xr.y = r.y();
+ xr.width = r.width();
+ xr.height = r.height();
+ XUnionRectWithRegion( &xr, pTempClipRegion, pTempClipRegion );
+ }
+ if( mpClipRegion )
+ XIntersectRegion( pTempClipRegion, mpClipRegion, pTempClipRegion );
+ XSetRegion( GetXDisplay(), gc, pTempClipRegion );
+ }
+ QPixmap pixmap = QPixmap::fromImage(*m_image, Qt::ColorOnly | Qt::OrderedDither | Qt::OrderedAlphaDither);
+ X11SalGraphics::CopyScreenArea( GetXDisplay(),
+ pixmap.handle(), pixmap.x11Info().screen(), pixmap.x11Info().depth(),
+ GetDrawable(), GetScreenNumber(), GetVisual().GetDepth(),
+ gc, 0, 0, widgetRect.width(), widgetRect.height(), widgetRect.left(), widgetRect.top());
+
+ if( pTempClipRegion )
+ {
+ if( mpClipRegion )
+ XSetRegion( GetXDisplay(), gc, mpClipRegion );
+ else
+ XSetClipMask( GetXDisplay(), gc, None );
+ XDestroyRegion( pTempClipRegion );
+ }
+ }
+ else
+ returnVal = false;
+#endif
+ }
+ delete clipRegion;
+ return returnVal;
+}
+
+sal_Bool KDESalGraphics::getNativeControlRegion( ControlType type, ControlPart part,
+ const Rectangle& controlRegion, ControlState controlState,
+ const ImplControlValue& val,
+ const OUString&,
+ Rectangle &nativeBoundingRegion, Rectangle &nativeContentRegion )
+{
+ sal_Bool retVal = false;
+
+ QRect boundingRect = region2QRect( controlRegion );
+ QRect contentRect = boundingRect;
+ QStyleOptionComplex styleOption;
+
+ switch ( type )
+ {
+ // Metrics of the push button
+ case CTRL_PUSHBUTTON:
+ if (part == PART_ENTIRE_CONTROL)
+ {
+ styleOption.state = vclStateValue2StateFlag(controlState, val);
+
+ if ( controlState & CTRL_STATE_DEFAULT )
+ {
+ int size = kapp->style()->pixelMetric(
+ QStyle::PM_ButtonDefaultIndicator, &styleOption );
+
+ boundingRect.adjust( -size, -size, size, size );
+
+ retVal = true;
+ }
+ }
+ break;
+ case CTRL_EDITBOX:
+ {
+ int nFontHeight = kapp->fontMetrics().height();
+ //int nFrameSize = kapp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int nLayoutTop = kapp->style()->pixelMetric(QStyle::PM_LayoutTopMargin);
+ int nLayoutBottom = kapp->style()->pixelMetric(QStyle::PM_LayoutBottomMargin);
+ int nLayoutLeft = kapp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
+ int nLayoutRight = kapp->style()->pixelMetric(QStyle::PM_LayoutRightMargin);
+
+ int nMinHeight = (nFontHeight + nLayoutTop + nLayoutBottom);
+ if( boundingRect.height() < nMinHeight )
+ {
+ int delta = nMinHeight - boundingRect.height();
+ boundingRect.adjust( 0, 0, 0, delta );
+ }
+ contentRect = boundingRect;
+ contentRect.adjust( -nLayoutLeft+1, -nLayoutTop+1, nLayoutRight-1, nLayoutBottom-1 );
+ retVal = true;
+
+ break;
+ }
+ case CTRL_CHECKBOX:
+ if (part == PART_ENTIRE_CONTROL)
+ {
+ styleOption.state = vclStateValue2StateFlag(controlState, val);
+
+ contentRect.setWidth(kapp->style()->pixelMetric(
+ QStyle::PM_IndicatorWidth, &styleOption));
+ contentRect.setHeight(kapp->style()->pixelMetric(
+ QStyle::PM_IndicatorHeight, &styleOption));
+
+ contentRect.adjust(0, 0,
+ 2 * kapp->style()->pixelMetric(
+ QStyle::PM_FocusFrameHMargin, &styleOption),
+ 2 * kapp->style()->pixelMetric(
+ QStyle::PM_FocusFrameVMargin, &styleOption)
+ );
+
+ boundingRect = contentRect;
+
+ retVal = true;
+
+ break;
+ }
+ case CTRL_COMBOBOX:
+ case CTRL_LISTBOX:
+ {
+ QStyleOptionComboBox cbo;
+
+ cbo.rect = QRect(0, 0, contentRect.width(), contentRect.height());
+ cbo.state = vclStateValue2StateFlag(controlState, val);
+
+ switch ( part )
+ {
+ case PART_ENTIRE_CONTROL:
+ {
+ int size = kapp->style()->pixelMetric(QStyle::PM_ComboBoxFrameWidth) - 2;
+
+ // find out the minimum size that should be used
+ // assume contents is a text ling
+ int nHeight = kapp->fontMetrics().height();
+ QSize aContentSize( contentRect.width(), nHeight );
+ QSize aMinSize = kapp->style()->
+ sizeFromContents( QStyle::CT_ComboBox, &cbo, aContentSize );
+ if( aMinSize.height() > contentRect.height() )
+ contentRect.adjust( 0, 0, 0, aMinSize.height() - contentRect.height() );
+ boundingRect = contentRect;
+ // FIXME: why this difference between comboboxes and listboxes ?
+ // because a combobox has a sub edit and that is positioned
+ // inside the outer bordered control ?
+ if( type == CTRL_COMBOBOX )
+ contentRect.adjust(-size,-size,size,size);
+ retVal = true;
+ break;
+ }
+ case PART_BUTTON_DOWN:
+ //the entire control can be used as the "down" button
+ retVal = true;
+ break;
+ case PART_SUB_EDIT:
+ contentRect = kapp->style()->subControlRect(
+ QStyle::CC_ComboBox, &cbo, QStyle::SC_ComboBoxEditField );
+
+ contentRect.translate( boundingRect.left(), boundingRect.top() );
+
+ retVal = true;
+ break;
+ case PART_WINDOW:
+ retVal = true;
+ break;
+ }
+ break;
+ }
+ case CTRL_SPINBOX:
+ {
+ QStyleOptionSpinBox sbo;
+
+ sbo.rect = QRect(0, 0, contentRect.width(), contentRect.height());
+ sbo.state = vclStateValue2StateFlag(controlState, val);
+
+ switch ( part )
+ {
+ case PART_BUTTON_UP:
+ contentRect = kapp->style()->subControlRect(
+ QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxUp );
+ contentRect.translate( boundingRect.left(), boundingRect.top() );
+ retVal = true;
+ boundingRect = QRect();
+ break;
+
+ case PART_BUTTON_DOWN:
+ contentRect = kapp->style()->subControlRect(
+ QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxDown );
+ retVal = true;
+ contentRect.translate( boundingRect.left(), boundingRect.top() );
+ boundingRect = QRect();
+ break;
+
+ case PART_SUB_EDIT:
+ contentRect = kapp->style()->subControlRect(
+ QStyle::CC_SpinBox, &sbo, QStyle::SC_SpinBoxEditField );
+ retVal = true;
+ contentRect.translate( boundingRect.left(), boundingRect.top() );
+ break;
+ default:
+ retVal = true;
+ }
+ break;
+ }
+ case CTRL_MENU_POPUP:
+ if (part == PART_MENU_ITEM_CHECK_MARK || part == PART_MENU_ITEM_RADIO_MARK)
+ { // core uses this to detect radio/checkbox sizes, so just set a square
+ contentRect.setWidth(contentRect.height());
+ retVal = true;
+ }
+ break;
+ case CTRL_FRAME:
+ {
+ if( part == PART_BORDER )
+ {
+ int nFrameWidth = getFrameWidth();
+ sal_uInt16 nStyle = val.getNumericVal();
+ if( nStyle & FRAME_DRAW_NODRAW )
+ {
+ // in this case the question is: how thick would a frame be
+ // see brdwin.cxx, decoview.cxx
+ // most probably the behavior in decoview.cxx is wrong.
+ contentRect.adjust(nFrameWidth, nFrameWidth, -nFrameWidth, -nFrameWidth);
+ }
+ retVal = true;
+ }
+ break;
+ }
+ case CTRL_RADIOBUTTON:
+ {
+ const int h = kapp->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorHeight);
+ const int w = kapp->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorWidth);
+
+ contentRect = QRect(boundingRect.left(), boundingRect.top(), w, h);
+ contentRect.adjust(0, 0,
+ 2 * kapp->style()->pixelMetric(
+ QStyle::PM_FocusFrameHMargin, &styleOption),
+ 2 * kapp->style()->pixelMetric(
+ QStyle::PM_FocusFrameVMargin, &styleOption)
+ );
+ boundingRect = contentRect;
+
+ retVal = true;
+ break;
+ }
+ case CTRL_SLIDER:
+ {
+ const int w = kapp->style()->pixelMetric(QStyle::PM_SliderLength);
+ if( part == PART_THUMB_HORZ )
+ {
+ contentRect = QRect(boundingRect.left(), boundingRect.top(), w, boundingRect.height());
+ boundingRect = contentRect;
+ retVal = true;
+ }
+ else if( part == PART_THUMB_VERT )
+ {
+ contentRect = QRect(boundingRect.left(), boundingRect.top(), boundingRect.width(), w);
+ boundingRect = contentRect;
+ retVal = true;
+ }
+ break;
+ }
+ case CTRL_SCROLLBAR:
+ {
+ // core can't handle 3-button scrollbars well, so we fix that in hitTestNativeControl(),
+ // for the rest also provide the track area (i.e. area not taken by buttons)
+ if( part == PART_TRACK_VERT_AREA || part == PART_TRACK_HORZ_AREA )
+ {
+ QStyleOptionSlider option;
+ OSL_ASSERT( val.getType() == CTRL_SCROLLBAR );
+ const ScrollbarValue* sbVal = static_cast<const ScrollbarValue *>(&val);
+ option.orientation = ( part == PART_TRACK_HORZ_AREA ) ? Qt::Horizontal : Qt::Vertical;
+ option.minimum = sbVal->mnMin;
+ option.maximum = sbVal->mnMax;
+ option.sliderValue = sbVal->mnCur;
+ option.sliderPosition = sbVal->mnCur;
+ option.pageStep = sbVal->mnVisibleSize;
+ // Adjust coordinates to make the widget appear to be at (0,0), i.e. make
+ // widget and screen coordinates the same. QStyle functions should use screen
+ // coordinates but at least QPlastiqueStyle::subControlRect() is buggy
+ // and sometimes uses widget coordinates.
+ QRect rect = contentRect;
+ rect.moveTo( 0, 0 );
+ option.rect = rect;
+ rect = kapp->style()->subControlRect( QStyle::CC_ScrollBar, &option,
+ QStyle::SC_ScrollBarGroove );
+ rect.translate( contentRect.topLeft()); // reverse the workaround above
+ contentRect = boundingRect = rect;
+ retVal = true;
+ }
+ }
+ default:
+ break;
+ }
+ if (retVal)
+ {
+ // Bounding region
+ Point aBPoint( boundingRect.x(), boundingRect.y() );
+ Size aBSize( boundingRect.width(), boundingRect.height() );
+ nativeBoundingRegion = Rectangle( aBPoint, aBSize );
+
+ // Region of the content
+ Point aPoint( contentRect.x(), contentRect.y() );
+ Size aSize( contentRect.width(), contentRect.height() );
+ nativeContentRegion = Rectangle( aPoint, aSize );
+ }
+
+ return retVal;
+}
+
+/** Test whether the position is in the native widget.
+ If the return value is TRUE, bIsInside contains information whether
+ aPos was or was not inside the native widget specified by the
+ nType/nPart combination.
+*/
+sal_Bool KDESalGraphics::hitTestNativeControl( ControlType nType, ControlPart nPart,
+ const Rectangle& rControlRegion, const Point& rPos,
+ sal_Bool& rIsInside )
+{
+ if ( nType == CTRL_SCROLLBAR )
+ {
+ if( nPart != PART_BUTTON_UP && nPart != PART_BUTTON_DOWN
+ && nPart != PART_BUTTON_LEFT && nPart != PART_BUTTON_RIGHT )
+ { // we adjust only for buttons (because some scrollbars have 3 buttons,
+ // and LO core doesn't handle such scrollbars well)
+ return FALSE;
+ }
+ rIsInside = FALSE;
+ bool bHorizontal = ( nPart == PART_BUTTON_LEFT || nPart == PART_BUTTON_RIGHT );
+ QRect rect = region2QRect( rControlRegion );
+ QPoint pos( rPos.X(), rPos.Y());
+ // Adjust coordinates to make the widget appear to be at (0,0), i.e. make
+ // widget and screen coordinates the same. QStyle functions should use screen
+ // coordinates but at least QPlastiqueStyle::subControlRect() is buggy
+ // and sometimes uses widget coordinates.
+ pos -= rect.topLeft();
+ rect.moveTo( 0, 0 );
+ QStyleOptionSlider options;
+ options.orientation = bHorizontal ? Qt::Horizontal : Qt::Vertical;
+ options.rect = rect;
+ // some random sensible values, since we call this code only for scrollbar buttons,
+ // the slider position does not exactly matter
+ options.maximum = 10;
+ options.minimum = 0;
+ options.sliderPosition = options.sliderValue = 4;
+ options.pageStep = 2;
+ QStyle::SubControl control = kapp->style()->hitTestComplexControl( QStyle::CC_ScrollBar, &options, pos );
+ if( nPart == PART_BUTTON_UP || nPart == PART_BUTTON_LEFT )
+ rIsInside = ( control == QStyle::SC_ScrollBarSubLine );
+ else // DOWN, RIGHT
+ rIsInside = ( control == QStyle::SC_ScrollBarAddLine );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDESalGraphics.hxx b/vcl/unx/kde4/KDESalGraphics.hxx
new file mode 100644
index 000000000000..5d1f3541a9b5
--- /dev/null
+++ b/vcl/unx/kde4/KDESalGraphics.hxx
@@ -0,0 +1,117 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <rtl/string.hxx>
+#include <saldisp.hxx>
+#include <salgdi.h>
+
+#define Region QtXRegion
+#include <QImage>
+#undef Region
+
+/** handles graphics drawings requests and performs the needed drawing operations */
+class KDESalGraphics : public X11SalGraphics
+{
+ QImage* m_image;
+ QRect lastPopupRect;
+
+ public:
+ KDESalGraphics();
+ virtual ~KDESalGraphics();
+
+ /**
+ What widgets can be drawn the native way.
+ @param type Type of the widget.
+ @param part Specification of the widget's part if it consists of more than one.
+ @return true if the platform supports native drawing of the widget type defined by part.
+ */
+ virtual sal_Bool IsNativeControlSupported( ControlType type, ControlPart part );
+
+ /** Test whether the position is in the native widget.
+ If the return value is TRUE, bIsInside contains information whether
+ aPos was or was not inside the native widget specified by the
+ type/part combination.
+ */
+ virtual sal_Bool hitTestNativeControl( ControlType type, ControlPart part,
+ const Rectangle& rControlRegion, const Point& aPos,
+ sal_Bool& rIsInside );
+ /** Draw the requested control described by part/nControlState.
+
+ @param rControlRegion
+ The bounding Rectangle of the complete control in VCL frame coordinates.
+
+ @param aValue
+ An optional value (tristate/numerical/string).
+
+ @param aCaption
+ A caption or title string (like button text etc.)
+ */
+ virtual sal_Bool drawNativeControl( ControlType type, ControlPart part,
+ const Rectangle& rControlRegion, ControlState nControlState,
+ const ImplControlValue& aValue,
+ const rtl::OUString& aCaption );
+
+ /** Draw text on the widget.
+ OPTIONAL. Draws the requested text for the control described by part/nControlState.
+ Used if text is not drawn by DrawNativeControl().
+
+ @param rControlRegion The bounding region of the complete control in VCL frame coordinates.
+ @param aValue An optional value (tristate/numerical/string)
+ @param aCaption A caption or title string (like button text etc.)
+ */
+ virtual sal_Bool drawNativeControlText( ControlType, ControlPart,
+ const Rectangle&, ControlState,
+ const ImplControlValue&,
+ const rtl::OUString& ) { return false; }
+ /** Check if the bounding regions match.
+
+ If the return value is TRUE, rNativeBoundingRegion
+ contains the true bounding region covered by the control
+ including any adornment, while rNativeContentRegion contains the area
+ within the control that can be safely drawn into without drawing over
+ the borders of the control.
+
+ @param rControlRegion
+ The bounding region of the control in VCL frame coordinates.
+
+ @param aValue
+ An optional value (tristate/numerical/string)
+
+ @param aCaption
+ A caption or title string (like button text etc.)
+ */
+ virtual sal_Bool getNativeControlRegion( ControlType type, ControlPart part,
+ const Rectangle& rControlRegion, ControlState nControlState,
+ const ImplControlValue& aValue,
+ const rtl::OUString& aCaption,
+ Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDESalInstance.cxx b/vcl/unx/kde4/KDESalInstance.cxx
new file mode 100644
index 000000000000..c63d328e29c3
--- /dev/null
+++ b/vcl/unx/kde4/KDESalInstance.cxx
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "KDESalInstance.hxx"
+
+#include "KDESalFrame.hxx"
+
+SalFrame* KDESalInstance::CreateFrame( SalFrame *pParent, sal_uLong nState )
+{
+ return new KDESalFrame( pParent, nState );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDESalInstance.hxx b/vcl/unx/kde4/KDESalInstance.hxx
new file mode 100644
index 000000000000..9f35557061bb
--- /dev/null
+++ b/vcl/unx/kde4/KDESalInstance.hxx
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <salinst.h>
+
+class SalYieldMutex;
+class SalFrame;
+
+class KDESalInstance : public X11SalInstance
+{
+ public:
+ KDESalInstance( SalYieldMutex* pMutex ) : X11SalInstance( pMutex ) {}
+ virtual ~KDESalInstance() {}
+ virtual SalFrame* CreateFrame( SalFrame* pParent, sal_uLong nStyle );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
new file mode 100644
index 000000000000..ce4ea14dadb5
--- /dev/null
+++ b/vcl/unx/kde4/KDEXLib.cxx
@@ -0,0 +1,422 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "VCLKDEApplication.hxx"
+
+#define Region QtXRegion
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kaboutdata.h>
+#include <kcmdlineargs.h>
+#include <kstartupinfo.h>
+#include <qabstracteventdispatcher.h>
+#include <qclipboard.h>
+#include <qthread.h>
+
+#undef Region
+
+#include "KDEXLib.hxx"
+
+#include <i18n_im.hxx>
+#include <i18n_xkb.hxx>
+
+#include <saldata.hxx>
+#include <osl/process.h>
+
+#include "KDESalDisplay.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+#include <stdio.h>
+
+#if QT_VERSION >= QT_VERSION_CHECK( 4, 8, 0 )
+#define QT_UNIX_EVENT_LOOP_SUPPORT
+#ifdef KDE_HAVE_GLIB
+#define GLIB_EVENT_LOOP_SUPPORT
+#endif
+#endif
+
+#ifdef GLIB_EVENT_LOOP_SUPPORT
+#include <glib-2.0/glib.h>
+#endif
+
+KDEXLib::KDEXLib() :
+ SalXLib(), m_bStartupDone(false), m_pApplication(0),
+ m_pFreeCmdLineArgs(0), m_pAppCmdLineArgs(0), m_nFakeCmdLineArgs( 0 ),
+ eventLoopType( LibreOfficeEventLoop )
+{
+ // the timers created here means they belong to the main thread
+ connect( &timeoutTimer, SIGNAL( timeout()), this, SLOT( timeoutActivated()));
+ connect( &userEventTimer, SIGNAL( timeout()), this, SLOT( userEventActivated()));
+ // QTimer::start() can be called only in its (here main) thread, so this will
+ // forward between threads if needed
+ connect( this, SIGNAL( startTimeoutTimerSignal()), this, SLOT( startTimeoutTimer()), Qt::QueuedConnection );
+ connect( this, SIGNAL( startUserEventTimerSignal()), this, SLOT( startUserEventTimer()), Qt::QueuedConnection );
+ // this one needs to be blocking, so that the handling in main thread is processed before
+ // the thread emitting the signal continues
+ connect( this, SIGNAL( processYieldSignal( bool, bool )), this, SLOT( processYield( bool, bool )),
+ Qt::BlockingQueuedConnection );
+}
+
+KDEXLib::~KDEXLib()
+{
+ delete m_pApplication;
+
+ // free the faked cmdline arguments no longer needed by KApplication
+ for( int i = 0; i < m_nFakeCmdLineArgs; i++ )
+ {
+ free( m_pFreeCmdLineArgs[i] );
+ }
+
+ delete [] m_pFreeCmdLineArgs;
+ delete [] m_pAppCmdLineArgs;
+}
+
+void KDEXLib::Init()
+{
+ SalI18N_InputMethod* pInputMethod = new SalI18N_InputMethod;
+ pInputMethod->SetLocale();
+ XrmInitialize();
+
+ KAboutData *kAboutData = new KAboutData("LibreOffice",
+ "kdelibs4",
+ ki18n( "LibreOffice" ),
+ "3.3.0",
+ ki18n( "LibreOffice with KDE Native Widget Support." ),
+ KAboutData::License_LGPL,
+ ki18n( "Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Novell, Inc"),
+ ki18n( "LibreOffice is an office suite.\n" ),
+ "http://libreoffice.org",
+ "libreoffice@lists.freedesktop.org" );
+
+ kAboutData->addAuthor( ki18n( "Jan Holesovsky" ),
+ ki18n( "Original author and maintainer of the KDE NWF." ),
+ "kendy@artax.karlin.mff.cuni.cz",
+ "http://artax.karlin.mff.cuni.cz/~kendy" );
+ kAboutData->addAuthor( ki18n("Roman Shtylman"),
+ ki18n( "Porting to KDE 4." ),
+ "shtylman@gmail.com", "http://shtylman.com" );
+ kAboutData->addAuthor( ki18n("Eric Bischoff"),
+ ki18n( "Accessibility fixes, porting to KDE 4." ),
+ "bischoff@kde.org" );
+
+ //kAboutData->setProgramIconName("OpenOffice");
+
+ m_nFakeCmdLineArgs = 2;
+ sal_uInt16 nIdx;
+
+ int nParams = osl_getCommandArgCount();
+ rtl::OString aDisplay;
+ rtl::OUString aParam, aBin;
+
+ for ( nIdx = 0; nIdx < nParams; ++nIdx )
+ {
+ osl_getCommandArg( nIdx, &aParam.pData );
+ if ( !m_pFreeCmdLineArgs && aParam.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "-display" ) ) && nIdx + 1 < nParams )
+ {
+ osl_getCommandArg( nIdx + 1, &aParam.pData );
+ aDisplay = rtl::OUStringToOString( aParam, osl_getThreadTextEncoding() );
+
+ m_pFreeCmdLineArgs = new char*[ m_nFakeCmdLineArgs + 2 ];
+ m_pFreeCmdLineArgs[ m_nFakeCmdLineArgs + 0 ] = strdup( "-display" );
+ m_pFreeCmdLineArgs[ m_nFakeCmdLineArgs + 1 ] = strdup( aDisplay.getStr() );
+ m_nFakeCmdLineArgs += 2;
+ }
+ }
+ if ( !m_pFreeCmdLineArgs )
+ m_pFreeCmdLineArgs = new char*[ m_nFakeCmdLineArgs ];
+
+ osl_getExecutableFile( &aParam.pData );
+ osl_getSystemPathFromFileURL( aParam.pData, &aBin.pData );
+ rtl::OString aExec = rtl::OUStringToOString( aBin, osl_getThreadTextEncoding() );
+ m_pFreeCmdLineArgs[0] = strdup( aExec.getStr() );
+ m_pFreeCmdLineArgs[1] = strdup( "--nocrashhandler" );
+
+ // make a copy of the string list for freeing it since
+ // KApplication manipulates the pointers inside the argument vector
+ // note: KApplication bad !
+ m_pAppCmdLineArgs = new char*[ m_nFakeCmdLineArgs ];
+ for( int i = 0; i < m_nFakeCmdLineArgs; i++ )
+ m_pAppCmdLineArgs[i] = m_pFreeCmdLineArgs[i];
+
+ KCmdLineArgs::init( m_nFakeCmdLineArgs, m_pAppCmdLineArgs, kAboutData );
+
+ m_pApplication = new VCLKDEApplication();
+ kapp->disableSessionManagement();
+ KApplication::setQuitOnLastWindowClosed(false);
+ setupEventLoop();
+
+ Display* pDisp = QX11Info::display();
+ SalKDEDisplay *pSalDisplay = new SalKDEDisplay(pDisp);
+
+ pInputMethod->CreateMethod( pDisp );
+ pInputMethod->AddConnectionWatch( pDisp, (void*)this );
+ pSalDisplay->SetInputMethod( pInputMethod );
+
+ PushXErrorLevel( true );
+ SalI18N_KeyboardExtension *pKbdExtension = new SalI18N_KeyboardExtension( pDisp );
+ XSync( pDisp, False );
+
+ pKbdExtension->UseExtension( ! HasXErrorOccurred() );
+ PopXErrorLevel();
+
+ pSalDisplay->SetKbdExtension( pKbdExtension );
+}
+
+// When we use Qt event loop, it can actually use its own event loop handling, or wrap
+// the Glib event loop (the latter is the default is Qt is built with Glib support
+// and $QT_NO_GLIB is not set). We mostly do not care which one it is, as QSocketNotifier's
+// and QTimer's can handle it transparently, but it matters for the SolarMutex, which
+// needs to be unlocked shortly before entering the main sleep (e.g. select()) and locked
+// immediatelly after. So we need to know which event loop implementation is used and
+// hook accordingly.
+#ifdef GLIB_EVENT_LOOP_SUPPORT
+static GPollFunc old_gpoll = NULL;
+static gint gpoll_wrapper( GPollFD*, guint, gint );
+#endif
+#ifdef QT_UNIX_EVENT_LOOP_SUPPORT
+static int (*qt_select)(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
+ const struct timeval *orig_timeout);
+static int lo_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
+ const struct timeval *orig_timeout);
+#endif
+
+static bool ( *old_qt_event_filter )( void* );
+static bool qt_event_filter( void* m )
+{
+ if( old_qt_event_filter != NULL && old_qt_event_filter( m ))
+ return true;
+ if( SalKDEDisplay::self() && SalKDEDisplay::self()->checkDirectInputEvent( static_cast< XEvent* >( m )))
+ return true;
+ return false;
+}
+
+void KDEXLib::setupEventLoop()
+{
+ old_qt_event_filter = QAbstractEventDispatcher::instance()->setEventFilter( qt_event_filter );
+#ifdef GLIB_EVENT_LOOP_SUPPORT
+// Glib is simple, it has g_main_context_set_poll_func() for wrapping the sleep call.
+// The catch is that Qt has a bug that allows triggering timers even when they should
+// not be, leading to crashes caused by QClipboard re-entering the event loop.
+// (http://bugreports.qt.nokia.com/browse/QTBUG-14461), so enable only with Qt>=4.8.0,
+// where it is(?) fixed.
+ if( QAbstractEventDispatcher::instance()->inherits( "QEventDispatcherGlib" ))
+ {
+ eventLoopType = GlibEventLoop;
+ old_gpoll = g_main_context_get_poll_func( NULL );
+ g_main_context_set_poll_func( NULL, gpoll_wrapper );
+ // set QClipboard to use event loop, otherwise the main thread will hold
+ // SolarMutex locked, which will prevent the clipboard thread from answering
+ m_pApplication->clipboard()->setProperty( "useEventLoopWhenWaiting", true );
+ return;
+ }
+#endif
+#ifdef QT_UNIX_EVENT_LOOP_SUPPORT
+// When Qt does not use Glib support, it uses its own Unix event dispatcher.
+// That one has aboutToBlock() and awake() signals, but they are broken (either
+// functionality or semantics), as e.g. awake() is not emitted right after the dispatcher
+// is woken up from sleep again, but only later (which is too late for re-acquiring SolarMutex).
+// This should be fixed with Qt-4.8.0 (?) where support for adding custom select() function
+// has been added too (http://bugreports.qt.nokia.com/browse/QTBUG-16934).
+ if( QAbstractEventDispatcher::instance()->inherits( "QEventDispatcherUNIX" ))
+ {
+ eventLoopType = QtUnixEventLoop;
+ QInternal::callFunction( QInternal::GetUnixSelectFunction, reinterpret_cast< void** >( &qt_select ));
+ QInternal::callFunction( QInternal::SetUnixSelectFunction, reinterpret_cast< void** >( lo_select ));
+ // set QClipboard to use event loop, otherwise the main thread will hold
+ // SolarMutex locked, which will prevent the clipboard thread from answering
+ m_pApplication->clipboard()->setProperty( "useEventLoopWhenWaiting", true );
+ return;
+ }
+#endif
+}
+
+#ifdef GLIB_EVENT_LOOP_SUPPORT
+gint gpoll_wrapper( GPollFD* ufds, guint nfds, gint timeout )
+{
+ YieldMutexReleaser release; // release YieldMutex (and re-acquire at block end)
+ return old_gpoll( ufds, nfds, timeout );
+}
+#endif
+
+#ifdef QT_UNIX_EVENT_LOOP_SUPPORT
+int lo_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
+ const struct timeval *orig_timeout)
+{
+ YieldMutexReleaser release; // release YieldMutex (and re-acquire at block end)
+ return qt_select( nfds, fdread, fdwrite, fdexcept, orig_timeout );
+}
+#endif
+
+void KDEXLib::Insert( int fd, void* data, YieldFunc pending, YieldFunc queued, YieldFunc handle )
+{
+ if( eventLoopType == LibreOfficeEventLoop )
+ return SalXLib::Insert( fd, data, pending, queued, handle );
+ SocketData sdata;
+ sdata.data = data;
+ sdata.pending = pending;
+ sdata.queued = queued;
+ sdata.handle = handle;
+ // qApp as parent to make sure it uses the main thread event loop
+ sdata.notifier = new QSocketNotifier( fd, QSocketNotifier::Read, qApp );
+ connect( sdata.notifier, SIGNAL( activated( int )), this, SLOT( socketNotifierActivated( int )));
+ socketData[ fd ] = sdata;
+}
+
+void KDEXLib::Remove( int fd )
+{
+ if( eventLoopType == LibreOfficeEventLoop )
+ return SalXLib::Remove( fd );
+ SocketData sdata = socketData.take( fd );// according to SalXLib::Remove() this should be safe
+ delete sdata.notifier;
+}
+
+void KDEXLib::socketNotifierActivated( int fd )
+{
+ const SocketData& sdata = socketData[ fd ];
+ sdata.handle( fd, sdata.data );
+}
+
+void KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents )
+{
+ if( eventLoopType == LibreOfficeEventLoop )
+ {
+ if( qApp->thread() == QThread::currentThread())
+ {
+ // even if we use the LO event loop, still process Qt's events,
+ // otherwise they can remain unhandled for quite a long while
+ processYield( false, bHandleAllCurrentEvents );
+ }
+ return SalXLib::Yield( bWait, bHandleAllCurrentEvents );
+ }
+ // if we are the main thread (which is where the event processing is done),
+ // good, just do it
+ if( qApp->thread() == QThread::currentThread())
+ processYield( bWait, bHandleAllCurrentEvents );
+ else
+ { // if this deadlocks, event processing needs to go into a separate thread
+ // or some other solution needs to be found
+ emit processYieldSignal( bWait, bHandleAllCurrentEvents );
+ }
+}
+
+bool KDEXLib::processYield( bool bWait, bool bHandleAllCurrentEvents )
+{
+ QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance( qApp->thread());
+ bool wasEvent = false;
+ for( int cnt = bHandleAllCurrentEvents ? 100 : 1;
+ cnt > 0;
+ --cnt )
+ {
+ if( !dispatcher->processEvents( QEventLoop::AllEvents ))
+ break;
+ wasEvent = true;
+ }
+ if( bWait && !wasEvent )
+ wasEvent = dispatcher->processEvents( QEventLoop::WaitForMoreEvents );
+ return wasEvent;
+}
+
+void KDEXLib::StartTimer( sal_uLong nMS )
+{
+ if( eventLoopType == LibreOfficeEventLoop )
+ return SalXLib::StartTimer( nMS );
+ timeoutTimer.setInterval( nMS );
+ // QTimer's can be started only in their thread (main thread here)
+ if( qApp->thread() == QThread::currentThread())
+ startTimeoutTimer();
+ else
+ emit startTimeoutTimerSignal();
+}
+
+void KDEXLib::startTimeoutTimer()
+{
+ timeoutTimer.start();
+}
+
+void KDEXLib::StopTimer()
+{
+ if( eventLoopType == LibreOfficeEventLoop )
+ return SalXLib::StopTimer();
+ timeoutTimer.stop();
+}
+
+void KDEXLib::timeoutActivated()
+{
+ GetX11SalData()->Timeout();
+ // QTimer is not single shot, so will be restarted immediatelly
+}
+
+void KDEXLib::Wakeup()
+{
+ if( eventLoopType == LibreOfficeEventLoop )
+ return SalXLib::Wakeup();
+ QAbstractEventDispatcher::instance( qApp->thread())->wakeUp(); // main thread event loop
+}
+
+void KDEXLib::PostUserEvent()
+{
+ if( eventLoopType == LibreOfficeEventLoop )
+ return SalXLib::PostUserEvent();
+ if( qApp->thread() == QThread::currentThread())
+ startUserEventTimer();
+ else
+ emit startUserEventTimerSignal();
+}
+
+void KDEXLib::startUserEventTimer()
+{
+ userEventTimer.start( 0 );
+}
+
+void KDEXLib::userEventActivated()
+{
+ SalKDEDisplay::self()->EventGuardAcquire();
+ if( SalKDEDisplay::self()->userEventsCount() <= 1 )
+ userEventTimer.stop();
+ SalKDEDisplay::self()->EventGuardRelease();
+ SalKDEDisplay::self()->DispatchInternalEvent();
+ // QTimer is not single shot, so will be restarted immediatelly
+}
+
+void KDEXLib::doStartup()
+{
+ if( ! m_bStartupDone )
+ {
+ KStartupInfo::appStarted();
+ m_bStartupDone = true;
+ #if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "called KStartupInfo::appStarted()\n" );
+ #endif
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx
new file mode 100644
index 000000000000..72848ed4084c
--- /dev/null
+++ b/vcl/unx/kde4/KDEXLib.hxx
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#include <saldisp.hxx>
+
+#include <fixx11h.h>
+
+#include <qhash.h>
+#include <qsocketnotifier.h>
+#include <qtimer.h>
+
+class VCLKDEApplication;
+
+class KDEXLib : public QObject, public SalXLib
+{
+ Q_OBJECT
+ private:
+ bool m_bStartupDone;
+ VCLKDEApplication* m_pApplication;
+ char** m_pFreeCmdLineArgs;
+ char** m_pAppCmdLineArgs;
+ int m_nFakeCmdLineArgs;
+ struct SocketData
+ {
+ void* data;
+ YieldFunc pending;
+ YieldFunc queued;
+ YieldFunc handle;
+ QSocketNotifier* notifier;
+ };
+ QHash< int, SocketData > socketData; // key is fd
+ QTimer timeoutTimer;
+ QTimer userEventTimer;
+ enum { LibreOfficeEventLoop, GlibEventLoop, QtUnixEventLoop } eventLoopType;
+
+ private:
+ void setupEventLoop();
+
+ private slots:
+ void socketNotifierActivated( int fd );
+ void timeoutActivated();
+ void userEventActivated();
+ void startTimeoutTimer();
+ void startUserEventTimer();
+ bool processYield( bool bWait, bool bHandleAllCurrentEvents );
+ signals:
+ void startTimeoutTimerSignal();
+ void startUserEventTimerSignal();
+ void processYieldSignal( bool bWait, bool bHandleAllCurrentEvents );
+
+ public:
+ KDEXLib();
+ virtual ~KDEXLib();
+
+ virtual void Init();
+ virtual void Yield( bool bWait, bool bHandleAllCurrentEvents );
+ virtual void Insert( int fd, void* data, YieldFunc pending, YieldFunc queued, YieldFunc handle );
+ virtual void Remove( int fd );
+ virtual void StartTimer( sal_uLong nMS );
+ virtual void StopTimer();
+ virtual void Wakeup();
+ virtual void PostUserEvent();
+
+ void doStartup();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/VCLKDEApplication.cxx b/vcl/unx/kde4/VCLKDEApplication.cxx
new file mode 100644
index 000000000000..c923598736e8
--- /dev/null
+++ b/vcl/unx/kde4/VCLKDEApplication.cxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "VCLKDEApplication.hxx"
+
+#define Region QtXRegion
+#include <QEvent>
+#undef Region
+
+#include "KDESalDisplay.hxx"
+
+VCLKDEApplication::VCLKDEApplication() :
+ KApplication()
+{
+}
+
+bool VCLKDEApplication::x11EventFilter(XEvent* event)
+{
+ //if we have a display and the display consumes the event
+ //do not process the event in qt
+ if (SalKDEDisplay::self() && SalKDEDisplay::self()->Dispatch(event) > 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/VCLKDEApplication.hxx b/vcl/unx/kde4/VCLKDEApplication.hxx
new file mode 100644
index 000000000000..17a9b6eb0917
--- /dev/null
+++ b/vcl/unx/kde4/VCLKDEApplication.hxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#pragma once
+
+#define Region QtXRegion
+
+#include <QSessionManager>
+
+#include <kapplication.h>
+
+#undef Region
+
+/* #i59042# override KApplications method for session management
+ * since it will interfere badly with our own.
+ */
+class VCLKDEApplication : public KApplication
+{
+ public:
+ VCLKDEApplication();
+
+ virtual void commitData(QSessionManager&) {};
+
+ virtual bool x11EventFilter(XEvent* event);
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/main.cxx b/vcl/unx/kde4/main.cxx
new file mode 100644
index 000000000000..d38c346c21b8
--- /dev/null
+++ b/vcl/unx/kde4/main.cxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#define Region QtXRegion
+#include <QApplication>
+#undef Region
+
+#include "KDEData.hxx"
+#include "KDESalInstance.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+#include <rtl/string.hxx>
+
+/// entry point for the KDE4 VCL plugin
+extern "C" {
+ VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule )
+ {
+ /* #i92121# workaround deadlocks in the X11 implementation
+ */
+ static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
+ /* #i90094#
+ from now on we know that an X connection will be
+ established, so protect X against itself
+ */
+ if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
+ XInitThreads();
+
+#if QT_VERSION < 0x050000
+ // Qt 4.x support needs >= 4.1.0
+ rtl::OString aVersion( qVersion() );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "qt version string is \"%s\"\n", aVersion.getStr() );
+#endif
+ sal_Int32 nIndex = 0, nMajor = 0, nMinor = 0, nMicro = 0;
+ nMajor = aVersion.getToken( 0, '.', nIndex ).toInt32();
+ if( nIndex > 0 )
+ nMinor = aVersion.getToken( 0, '.', nIndex ).toInt32();
+ if( nIndex > 0 )
+ nMicro = aVersion.getToken( 0, '.', nIndex ).toInt32();
+ if( nMajor != 4 || nMinor < 1 )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "unsuitable qt version %d.%d.%d\n", nMajor, nMinor, nMicro );
+#endif
+ return NULL;
+ }
+#endif
+
+ KDESalInstance* pInstance = new KDESalInstance( new SalYieldMutex() );
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "created KDESalInstance 0x%p\n", pInstance );
+#endif
+
+ // initialize SalData
+ KDEData *salData = new KDEData();
+ SetSalData(salData);
+ salData->m_pInstance = pInstance;
+ salData->Init();
+ salData->initNWF();
+
+ return pInstance;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/kde4/makefile.mk b/vcl/unx/kde4/makefile.mk
new file mode 100644
index 000000000000..83ac1c0e6802
--- /dev/null
+++ b/vcl/unx/kde4/makefile.mk
@@ -0,0 +1,96 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=vcl
+TARGET=kde4plug
+.INCLUDE : $(PRJ)$/util$/makefile.pmk
+
+# workaround for makedepend hang
+MKDEPENDSOLVER=
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+.INCLUDE : $(PRJ)$/util$/makefile2.pmk
+
+# For some of the included external KDE headers, GCC complains about shadowed
+# symbols in instantiated template code only at the end of a compilation unit,
+# so the only solution is to disable that warning here:
+.IF "$(COM)" == "GCC"
+CFLAGSCXX+=-Wno-shadow
+.ENDIF
+
+# --- Files --------------------------------------------------------
+
+.IF "$(GUIBASE)"!="unx"
+
+dummy:
+ @echo "Nothing to build for GUIBASE $(GUIBASE)"
+
+.ELSE # "$(GUIBASE)"!="unx"
+
+.IF "$(ENABLE_KDE4)" != ""
+
+CFLAGS+=$(KDE4_CFLAGS) $(KDE_GLIB_CFLAGS)
+
+.IF "$(ENABLE_RANDR)" != ""
+CDEFS+=-DUSE_RANDR
+.ENDIF
+
+.IF "$(KDE_HAVE_GLIB)" != ""
+CDEFS+=-DKDE_HAVE_GLIB
+.ENDIF
+
+SLOFILES=\
+ $(SLO)$/main.obj \
+ $(SLO)$/VCLKDEApplication.obj \
+ $(SLO)$/KDEXLib.obj \
+ $(SLO)$/KDEXLib.moc.obj \
+ $(SLO)$/KDESalDisplay.obj \
+ $(SLO)$/KDESalFrame.obj \
+ $(SLO)$/KDESalGraphics.obj \
+ $(SLO)$/KDESalInstance.obj \
+ $(SLO)$/KDEData.obj
+
+
+.ELSE # "$(ENABLE_KDE4)" != ""
+
+dummy:
+ @echo KDE disabled - nothing to build
+.ENDIF
+.ENDIF # "$(GUIBASE)"!="unx"
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+.INCLUDE : $(PRJ)$/util$/target.pmk
+
+$(MISC)$/KDEXLib.moc.cxx : KDEXLib.hxx
+ $(MOC4) $< -o $@