Accepting request 233044 from LibreOffice:Factory

OBS-URL: https://build.opensuse.org/request/show/233044
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/libreoffice?expand=0&rev=68
This commit is contained in:
Stephan Kulow 2014-05-09 04:57:38 +00:00 committed by Git OBS Bridge
commit 7dba38d514
10 changed files with 125 additions and 909 deletions

View File

@ -1,851 +0,0 @@
From 9481fa2ea3f34746715c6127c190a441794c03a5 Mon Sep 17 00:00:00 2001
From: Andrzej Hunt <andrzej.hunt@collabora.com>
Date: Thu, 10 Apr 2014 21:58:29 +0100
Subject: [PATCH] fdo#74697 Add Bluez 5 support for impress remote.
This time we:
- Don't break SAL_WARN with an fprintf like syntax.
- Replace DBUS_TYPE_UNIX_FD with it's definition 'h' as we might
be building on dbus-glib versions that do not support it (however
presumably anyone running bluez 5 will have a dbus version that is
new enough to support this, i.e. purely a build-time issue).
- Remove various C++11'isms.
Change-Id: I736cad2122cd3789a5c7fb62c39e409d41fc1e32
Reviewed-on: https://gerrit.libreoffice.org/8924
Tested-by: Andrzej Hunt <andrzej.hunt@collabora.com>
Reviewed-by: Andrzej Hunt <andrzej.hunt@collabora.com>
(cherry picked from commit b15666fd7582729c75bd0dd1bd0cb5d7c5a77f0c)
---
sd/source/ui/remotecontrol/BluetoothServer.cxx | 673 ++++++++++++++++++---
.../ui/remotecontrol/BufferedStreamSocket.cxx | 2 +-
sd/source/ui/remotecontrol/Communicator.cxx | 2 +
3 files changed, 605 insertions(+), 72 deletions(-)
diff --git a/sd/source/ui/remotecontrol/BluetoothServer.cxx b/sd/source/ui/remotecontrol/BluetoothServer.cxx
index 63407a6..a447900 100644
--- a/sd/source/ui/remotecontrol/BluetoothServer.cxx
+++ b/sd/source/ui/remotecontrol/BluetoothServer.cxx
@@ -13,6 +13,8 @@
#include <iomanip>
#include <new>
+#include <boost/scoped_ptr.hpp>
+
#include <sal/log.hxx>
#ifdef LINUX_BLUETOOTH
@@ -90,25 +92,40 @@ struct DBusObject {
}
};
+static DBusObject* getBluez5Adapter(DBusConnection *pConnection);
+
struct sd::BluetoothServer::Impl {
// the glib mainloop running in the thread
GMainContext *mpContext;
DBusConnection *mpConnection;
DBusObject *mpService;
volatile bool mbExitMainloop;
+ enum BluezVersion { BLUEZ4, BLUEZ5, UNKNOWN };
+ BluezVersion maBluezVersion;
Impl()
: mpContext( g_main_context_new() )
, mpConnection( NULL )
, mpService( NULL )
, mbExitMainloop( false )
+ , maBluezVersion( UNKNOWN )
{ }
DBusObject *getAdapter()
{
- if( !mpService )
+ if (mpService)
+ {
+ DBusObject* pAdapter = mpService->cloneForInterface( "org.bluez.Adapter" );
+ return pAdapter;
+ }
+ else if (spServer->mpImpl->maBluezVersion == BLUEZ5)
+ {
+ return getBluez5Adapter(mpConnection);
+ }
+ else
+ {
return NULL;
- return mpService->cloneForInterface( "org.bluez.Adapter" );
+ }
}
};
@@ -156,37 +173,181 @@ sendUnrefAndWaitForReply( DBusConnection *pConnection, DBusMessage *pMsg )
return pMsg;
}
+static bool
+isBluez5Available(DBusConnection *pConnection)
+{
+ DBusMessage *pMsg;
+
+ // Simplest wasy to check whether we have Bluez 5+ is to check
+ // that we can obtain adapters using the new interfaces.
+ // The first two error checks however don't tell us anything as they should
+ // succeed as long as dbus is working correctly.
+ pMsg = DBusObject( "org.bluez", "/", "org.freedesktop.DBus.ObjectManager" ).getMethodCall( "GetManagedObjects" );
+ if (!pMsg)
+ {
+ SAL_INFO("sdremote.bluetooth", "No GetManagedObjects call created");
+ return false;
+ }
+
+ pMsg = sendUnrefAndWaitForReply( pConnection, pMsg );
+ if (!pMsg)
+ {
+ SAL_INFO("sdremote.bluetooth", "No reply received");
+ return false;
+ }
+
+ // If dbus is working correctly and we aren't on bluez 5 this is where we
+ // should actually get the error.
+ if (dbus_message_get_error_name( pMsg ))
+ {
+ SAL_INFO( "sdremote.bluetooth", "GetManagedObjects call failed with \""
+ << dbus_message_get_error_name( pMsg )
+ << "\" -- we don't seem to have Bluez 5 available");
+ return false;
+ }
+ SAL_INFO("sdremote.bluetooth", "GetManagedObjects call seems to have succeeded -- we must be on Bluez 5");
+ dbus_message_unref(pMsg);
+ return true;
+}
+
+
+static DBusObject*
+getBluez5Adapter(DBusConnection *pConnection)
+{
+ DBusMessage *pMsg;
+ // This returns a list of objects where we need to find the first
+ // org.bluez.Adapter1 .
+ pMsg = DBusObject( "org.bluez", "/", "org.freedesktop.DBus.ObjectManager" ).getMethodCall( "GetManagedObjects" );
+ if (!pMsg)
+ return NULL;
+
+ const gchar* pInterfaceType = "org.bluez.Adapter1";
+
+ pMsg = sendUnrefAndWaitForReply( pConnection, pMsg );
+
+ DBusMessageIter aObjectIterator;
+ if (pMsg && dbus_message_iter_init(pMsg, &aObjectIterator))
+ {
+ if (DBUS_TYPE_ARRAY == dbus_message_iter_get_arg_type(&aObjectIterator))
+ {
+ DBusMessageIter aObject;
+ dbus_message_iter_recurse(&aObjectIterator, &aObject);
+ do
+ {
+ if (DBUS_TYPE_DICT_ENTRY == dbus_message_iter_get_arg_type(&aObject))
+ {
+ DBusMessageIter aContainerIter;
+ dbus_message_iter_recurse(&aObject, &aContainerIter);
+ char *pPath = 0;
+ do
+ {
+ if (DBUS_TYPE_OBJECT_PATH == dbus_message_iter_get_arg_type(&aContainerIter))
+ {
+ dbus_message_iter_get_basic(&aContainerIter, &pPath);
+ SAL_INFO( "sdremote.bluetooth", "Something retrieved: '"
+ << pPath << "' '");
+ }
+ else if (DBUS_TYPE_ARRAY == dbus_message_iter_get_arg_type(&aContainerIter))
+ {
+ DBusMessageIter aInnerIter;
+ dbus_message_iter_recurse(&aContainerIter, &aInnerIter);
+ do
+ {
+ if (DBUS_TYPE_DICT_ENTRY == dbus_message_iter_get_arg_type(&aInnerIter))
+ {
+ DBusMessageIter aInnerInnerIter;
+ dbus_message_iter_recurse(&aInnerIter, &aInnerInnerIter);
+ do
+ {
+ if (DBUS_TYPE_STRING == dbus_message_iter_get_arg_type(&aInnerInnerIter))
+ {
+ char* pMessage;
+
+ dbus_message_iter_get_basic(&aInnerInnerIter, &pMessage);
+ if (OString(pMessage) == "org.bluez.Adapter1")
+ {
+ dbus_message_unref(pMsg);
+ if (pPath)
+ {
+ return new DBusObject( "org.bluez", pPath, pInterfaceType );
+ }
+ assert(false); // We should already have pPath provided for us.
+ }
+ }
+ }
+ while (dbus_message_iter_next(&aInnerInnerIter));
+ }
+ }
+ while (dbus_message_iter_next(&aInnerIter));
+ }
+ }
+ while (dbus_message_iter_next(&aContainerIter));
+ }
+ }
+ while (dbus_message_iter_next(&aObject));
+ }
+ dbus_message_unref(pMsg);
+ }
+
+ return NULL;
+}
+
static DBusObject *
-bluezGetDefaultService( DBusConnection *pConnection )
+bluez4GetDefaultService( DBusConnection *pConnection )
{
DBusMessage *pMsg;
DBusMessageIter it;
const gchar* pInterfaceType = "org.bluez.Service";
+ // org.bluez.manager only exists for bluez 4.
+ // getMethodCall should return NULL if there is any issue e.g. the
+ // if org.bluez.manager doesn't exist.
pMsg = DBusObject( "org.bluez", "/", "org.bluez.Manager" ).getMethodCall( "DefaultAdapter" );
+
+ if (!pMsg)
+ {
+ SAL_WARN("sdremote.bluetooth", "Couldn't retrieve DBusObject for DefaultAdapter");
+ return NULL;
+ }
+
+ SAL_INFO("sdremote.bluetooth", "successfully retrieved org.bluez.Manager.DefaultAdapter, attempting to use.");
pMsg = sendUnrefAndWaitForReply( pConnection, pMsg );
if(!pMsg || !dbus_message_iter_init( pMsg, &it ) )
+ {
return NULL;
+ }
- if( DBUS_TYPE_OBJECT_PATH != dbus_message_iter_get_arg_type( &it ) )
- SAL_INFO( "sdremote.bluetooth", "invalid type of reply to DefaultAdapter: '"
- << dbus_message_iter_get_arg_type( &it ) << "'" );
- else
+ // This works for Bluez 4
+ if( DBUS_TYPE_OBJECT_PATH == dbus_message_iter_get_arg_type( &it ) )
{
const char *pObjectPath = NULL;
dbus_message_iter_get_basic( &it, &pObjectPath );
SAL_INFO( "sdremote.bluetooth", "DefaultAdapter retrieved: '"
- << pObjectPath << "' '" << pInterfaceType << "'" );
+ << pObjectPath << "' '" << pInterfaceType << "'" );
+ dbus_message_unref( pMsg );
return new DBusObject( "org.bluez", pObjectPath, pInterfaceType );
}
- dbus_message_unref( pMsg );
-
+ // Some form of error, e.g. if we have bluez 5 we get a message that
+ // this method doesn't exist.
+ else if ( DBUS_TYPE_STRING == dbus_message_iter_get_arg_type( &it ) )
+ {
+ const char *pMessage = NULL;
+ dbus_message_iter_get_basic( &it, &pMessage );
+ SAL_INFO( "sdremote.bluetooth", "Error message: '"
+ << pMessage << "' '" << pInterfaceType << "'" );
+ }
+ else
+ {
+ SAL_INFO( "sdremote.bluetooth", "invalid type of reply to DefaultAdapter: '"
+ << (const char) dbus_message_iter_get_arg_type( &it ) << "'" );
+ }
+ dbus_message_unref(pMsg);
return NULL;
}
static bool
-bluezRegisterServiceRecord( DBusConnection *pConnection, DBusObject *pAdapter,
+bluez4RegisterServiceRecord( DBusConnection *pConnection, DBusObject *pAdapter,
const char *pServiceRecord )
{
DBusMessage *pMsg;
@@ -443,8 +604,14 @@ extern "C" {
}
}
+/*
+ * Bluez 4 uses custom methods for setting properties, whereas Bluez 5+
+ * implements properties using the generic "org.freedesktop.DBus.Properties"
+ * interface -- hence we have a specific Bluez 4 function to deal with the
+ * old style of reading properties.
+ */
static bool
-getBooleanProperty( DBusConnection *pConnection, DBusObject *pAdapter,
+getBluez4BooleanProperty( DBusConnection *pConnection, DBusObject *pAdapter,
const char *pPropertyName, bool *pBoolean )
{
*pBoolean = false;
@@ -523,63 +690,391 @@ getBooleanProperty( DBusConnection *pConnection, DBusObject *pAdapter,
return false;
}
-static void
-setDiscoverable( DBusConnection *pConnection, DBusObject *pAdapter, bool bDiscoverable )
+/*
+ * This gets an org.freedesktop.DBus.Properties boolean
+ * (as opposed to the old Bluez 4 custom properties methods as visible above).
+ */
+static bool
+getDBusBooleanProperty( DBusConnection *pConnection, DBusObject *pAdapter,
+ const char *pPropertyName, bool *pBoolean )
{
- SAL_INFO( "sdremote.bluetooth", "setDiscoverable to " << bDiscoverable );
+ assert( pAdapter );
- bool bPowered = false;
- if( !getBooleanProperty( pConnection, pAdapter, "Powered", &bPowered ) || !bPowered )
- return; // nothing to do
+ *pBoolean = false;
+ bool bRet = false;
- DBusMessage *pMsg;
- DBusMessageIter it, varIt;
+ ::boost::scoped_ptr< DBusObject > pProperties (
+ pAdapter->cloneForInterface( "org.freedesktop.DBus.Properties" ) );
- // set timeout to zero
- pMsg = pAdapter->getMethodCall( "SetProperty" );
- dbus_message_iter_init_append( pMsg, &it );
- const char *pTimeoutStr = "DiscoverableTimeout";
- dbus_message_iter_append_basic( &it, DBUS_TYPE_STRING, &pTimeoutStr );
- dbus_message_iter_open_container( &it, DBUS_TYPE_VARIANT,
- DBUS_TYPE_UINT32_AS_STRING, &varIt );
- dbus_uint32_t nTimeout = 0;
- dbus_message_iter_append_basic( &varIt, DBUS_TYPE_UINT32, &nTimeout );
- dbus_message_iter_close_container( &it, &varIt );
- dbus_connection_send( pConnection, pMsg, NULL ); // async send - why not ?
- dbus_message_unref( pMsg );
+ DBusMessage *pMsg = pProperties->getMethodCall( "Get" );
- // set discoverable value
- pMsg = pAdapter->getMethodCall( "SetProperty" );
- dbus_message_iter_init_append( pMsg, &it );
- const char *pDiscoverableStr = "Discoverable";
- dbus_message_iter_append_basic( &it, DBUS_TYPE_STRING, &pDiscoverableStr );
- dbus_message_iter_open_container( &it, DBUS_TYPE_VARIANT,
- DBUS_TYPE_BOOLEAN_AS_STRING, &varIt );
- dbus_bool_t bValue = bDiscoverable;
- dbus_message_iter_append_basic( &varIt, DBUS_TYPE_BOOLEAN, &bValue );
- dbus_message_iter_close_container( &it, &varIt ); // async send - why not ?
- dbus_connection_send( pConnection, pMsg, NULL );
+ DBusMessageIter itIn;
+ dbus_message_iter_init_append( pMsg, &itIn );
+ const char* pInterface = "org.bluez.Adapter1";
+ dbus_message_iter_append_basic( &itIn, DBUS_TYPE_STRING, &pInterface );
+ dbus_message_iter_append_basic( &itIn, DBUS_TYPE_STRING, &pPropertyName );
+ pMsg = sendUnrefAndWaitForReply( pConnection, pMsg );
+
+ DBusMessageIter it;
+ if( !pMsg || !dbus_message_iter_init( pMsg, &it ) )
+ {
+ SAL_WARN( "sdremote.bluetooth", "no valid reply / timeout" );
+ return false;
+ }
+
+ if( DBUS_TYPE_VARIANT != dbus_message_iter_get_arg_type( &it ) )
+ {
+ SAL_WARN( "sdremote.bluetooth", "invalid return type" );
+ }
+ else
+ {
+ DBusMessageIter variantIt;
+ dbus_message_iter_recurse( &it, &variantIt );
+
+ if( dbus_message_iter_get_arg_type( &variantIt ) == DBUS_TYPE_BOOLEAN )
+ {
+ dbus_bool_t bBool = false;
+ dbus_message_iter_get_basic( &variantIt, &bBool );
+ SAL_INFO( "sdremote.bluetooth", "" << pPropertyName << " is " << bBool );
+ *pBoolean = bBool;
+ bRet = true;
+ }
+ else
+ {
+ SAL_WARN( "sdremote.bluetooth", "" << pPropertyName << " type " <<
+ dbus_message_iter_get_arg_type( &variantIt ) );
+ }
+
+ const char* pError = dbus_message_get_error_name( pMsg );
+ if ( pError )
+ {
+ SAL_WARN( "sdremote.bluetooth",
+ "Get failed for " << pPropertyName << " on " <<
+ pAdapter->maPath << " with error: " << pError );
+ }
+ }
dbus_message_unref( pMsg );
+
+ return bRet;
+}
+
+static void
+setDBusBooleanProperty( DBusConnection *pConnection, DBusObject *pAdapter,
+ const char *pPropertyName, bool bBoolean )
+{
+ assert( pAdapter );
+
+ ::boost::scoped_ptr< DBusObject > pProperties(
+ pAdapter->cloneForInterface( "org.freedesktop.DBus.Properties" ) );
+
+ DBusMessage *pMsg = pProperties->getMethodCall( "Set" );
+
+ DBusMessageIter itIn;
+ dbus_message_iter_init_append( pMsg, &itIn );
+ const char* pInterface = "org.bluez.Adapter1";
+ dbus_message_iter_append_basic( &itIn, DBUS_TYPE_STRING, &pInterface );
+ dbus_message_iter_append_basic( &itIn, DBUS_TYPE_STRING, &pPropertyName );
+
+ {
+ DBusMessageIter varIt;
+ dbus_message_iter_open_container( &itIn, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_BOOLEAN_AS_STRING, &varIt );
+ dbus_bool_t bDBusBoolean = bBoolean;
+ dbus_message_iter_append_basic( &varIt, DBUS_TYPE_BOOLEAN, &bDBusBoolean );
+ dbus_message_iter_close_container( &itIn, &varIt );
+ }
+
+ pMsg = sendUnrefAndWaitForReply( pConnection, pMsg );
+
+ if( !pMsg )
+ {
+ SAL_WARN( "sdremote.bluetooth", "no valid reply / timeout" );
+ }
+ else
+ {
+ const char* pError = dbus_message_get_error_name( pMsg );
+ if ( pError )
+ {
+ SAL_WARN( "sdremote.bluetooth",
+ "Set failed for " << pPropertyName << " on " <<
+ pAdapter->maPath << " with error: " << pError );
+ }
+ dbus_message_unref( pMsg );
+ }
+}
+
+static bool
+getDiscoverable( DBusConnection *pConnection, DBusObject *pAdapter )
+{
+ if (pAdapter->maInterface == "org.bluez.Adapter") // Bluez 4
+ {
+ bool bDiscoverable;
+ if( getBluez4BooleanProperty(pConnection, pAdapter, "Discoverable", &bDiscoverable ) )
+ return bDiscoverable;
+ }
+ else if (pAdapter->maInterface == "org.bluez.Adapter1") // Bluez 5
+ {
+ bool bDiscoverable;
+ if ( getDBusBooleanProperty(pConnection, pAdapter, "Discoverable", &bDiscoverable ) )
+ return bDiscoverable;
+ }
+ return false;
+}
+
+static void
+setDiscoverable( DBusConnection *pConnection, DBusObject *pAdapter, bool bDiscoverable )
+{
+ SAL_INFO( "sdremote.bluetooth", "setDiscoverable to " << bDiscoverable );
+
+ if (pAdapter->maInterface == "org.bluez.Adapter") // Bluez 4
+ {
+ bool bPowered = false;
+ if( !getBluez4BooleanProperty( pConnection, pAdapter, "Powered", &bPowered ) || !bPowered )
+ return; // nothing to do
+
+ DBusMessage *pMsg;
+ DBusMessageIter it, varIt;
+
+ // set timeout to zero
+ pMsg = pAdapter->getMethodCall( "SetProperty" );
+ dbus_message_iter_init_append( pMsg, &it );
+ const char *pTimeoutStr = "DiscoverableTimeout";
+ dbus_message_iter_append_basic( &it, DBUS_TYPE_STRING, &pTimeoutStr );
+ dbus_message_iter_open_container( &it, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_UINT32_AS_STRING, &varIt );
+ dbus_uint32_t nTimeout = 0;
+ dbus_message_iter_append_basic( &varIt, DBUS_TYPE_UINT32, &nTimeout );
+ dbus_message_iter_close_container( &it, &varIt );
+ dbus_connection_send( pConnection, pMsg, NULL ); // async send - why not ?
+ dbus_message_unref( pMsg );
+
+ // set discoverable value
+ pMsg = pAdapter->getMethodCall( "SetProperty" );
+ dbus_message_iter_init_append( pMsg, &it );
+ const char *pDiscoverableStr = "Discoverable";
+ dbus_message_iter_append_basic( &it, DBUS_TYPE_STRING, &pDiscoverableStr );
+ dbus_message_iter_open_container( &it, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_BOOLEAN_AS_STRING, &varIt );
+ dbus_bool_t bValue = bDiscoverable;
+ dbus_message_iter_append_basic( &varIt, DBUS_TYPE_BOOLEAN, &bValue );
+ dbus_message_iter_close_container( &it, &varIt ); // async send - why not ?
+ dbus_connection_send( pConnection, pMsg, NULL );
+ dbus_message_unref( pMsg );
+ }
+ else if (pAdapter->maInterface == "org.bluez.Adapter1") // Bluez 5
+ {
+ setDBusBooleanProperty(pConnection, pAdapter, "Discoverable", bDiscoverable );
+ }
}
static DBusObject *
registerWithDefaultAdapter( DBusConnection *pConnection )
{
DBusObject *pService;
- pService = bluezGetDefaultService( pConnection );
- if( !pService )
- return NULL;
-
- if( !bluezRegisterServiceRecord( pConnection, pService,
- bluetooth_service_record ) )
+ pService = bluez4GetDefaultService( pConnection );
+ if( pService )
{
- delete pService;
- return NULL;
+ if( !bluez4RegisterServiceRecord( pConnection, pService,
+ bluetooth_service_record ) )
+ {
+ delete pService;
+ return NULL;
+ }
}
return pService;
}
+void ProfileUnregisterFunction
+(DBusConnection *connection, void *user_data)
+{
+ // We specifically don't need to do anything here.
+ (void) connection;
+ (void) user_data;
+}
+
+DBusHandlerResult ProfileMessageFunction
+(DBusConnection *pConnection, DBusMessage *pMessage, void *user_data)
+{
+ SAL_INFO("sdremote.bluetooth", "ProfileMessageFunction||" << dbus_message_get_interface(pMessage) << "||" << dbus_message_get_member(pMessage));
+ DBusHandlerResult aRet = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (OString(dbus_message_get_interface(pMessage)).equals("org.bluez.Profile1"))
+ {
+ if (OString(dbus_message_get_member(pMessage)).equals("Release"))
+ {
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ else if (OString(dbus_message_get_member(pMessage)).equals("NewConnection"))
+ {
+ if (!dbus_message_has_signature(pMessage, "oha{sv}"))
+ {
+ SAL_WARN("sdremote.bluetooth", "wrong signature for NewConnection");
+ }
+
+ DBusMessageIter it;
+ dbus_message_iter_init(pMessage, &it);
+
+ char* pPath;
+ dbus_message_iter_get_basic(&it, &pPath);
+ SAL_INFO("sdremote.bluetooth", "Adapter path:" << pPath);
+
+ if (!dbus_message_iter_next(&it))
+ SAL_WARN("sdremote.bluetooth", "not enough parameters passed");
+
+ // DBUS_TYPE_UNIX_FD == 'h' -- doesn't exist in older versions
+ // of dbus (< 1.3?) hence defined manually for now
+ if ('h' == dbus_message_iter_get_arg_type(&it))
+ {
+
+ int nDescriptor;
+ dbus_message_iter_get_basic(&it, &nDescriptor);
+ std::vector<Communicator*>* pCommunicators = (std::vector<Communicator*>*) user_data;
+
+ // Bluez gives us non-blocking sockets, but our code relies
+ // on blocking behaviour.
+ fcntl(nDescriptor, F_SETFL, fcntl(nDescriptor, F_GETFL) & ~O_NONBLOCK);
+
+ SAL_INFO( "sdremote.bluetooth", "connection accepted " << nDescriptor);
+ Communicator* pCommunicator = new Communicator( new BufferedStreamSocket( nDescriptor ) );
+ pCommunicators->push_back( pCommunicator );
+ pCommunicator->launch();
+ }
+
+ // For some reason an (empty?) reply is expected.
+ DBusMessage* pRet = dbus_message_new_method_return(pMessage);
+ dbus_connection_send(pConnection, pRet, NULL);
+ dbus_message_unref(pRet);
+
+ // We could read the remote profile version and features here
+ // (i.e. they are provided as part of the DBusMessage),
+ // however for us they are irrelevant (as our protocol handles
+ // equivalent functionality independently of whether we're on
+ // bluetooth or normal network connection).
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ else if (OString(dbus_message_get_member(pMessage)).equals("RequestDisconnection"))
+ {
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ }
+ SAL_WARN("sdremote.bluetooth", "Couldn't handle message correctly.");
+ return aRet;
+
+}
+
+static void
+setupBluez5Profile1(DBusConnection* pConnection, std::vector<Communicator*>* pCommunicators)
+{
+ bool bErr;
+
+ SAL_INFO("sdremote.bluetooth", "Attempting to register our org.bluez.Profile1");
+ static DBusObjectPathVTable aVTable;
+ aVTable.unregister_function = ProfileUnregisterFunction;
+ aVTable.message_function = ProfileMessageFunction;
+
+ // dbus_connection_try_register_object_path could be used but only exists for
+ // dbus-glib >= 1.2 -- we really shouldn't be trying this twice in any case.
+ // (dbus_connection_try_register_object_path also returns an error with more
+ // information which could be useful for debugging purposes.)
+ bErr = !dbus_connection_register_object_path(pConnection, "/org/libreoffice/bluez/profile1", &aVTable, pCommunicators);
+
+ if (bErr)
+ {
+ SAL_WARN("sdremote.bluetooth", "Failed to register Bluez 5 Profile1 callback, bluetooth won't work.");
+ }
+
+ dbus_connection_flush( pConnection );
+}
+
+static void
+unregisterBluez5Profile(DBusConnection* pConnection)
+{
+ DBusMessage* pMsg = dbus_message_new_method_call("org.bluez", "/org/bluez",
+ "org.bluez.ProfileManager1", "UnregisterProfile");
+ DBusMessageIter it;
+ dbus_message_iter_init_append(pMsg, &it);
+
+ const char *pPath = "/org/libreoffice/bluez/profile1";
+ dbus_message_iter_append_basic(&it, DBUS_TYPE_OBJECT_PATH, &pPath);
+
+ pMsg = sendUnrefAndWaitForReply( pConnection, pMsg );
+
+ if (pMsg)
+ dbus_message_unref(pMsg);
+
+ dbus_connection_unregister_object_path( pConnection, "/org/libreoffice/bluez/profile1");
+
+ dbus_connection_flush(pConnection);
+}
+
+static bool
+registerBluez5Profile(DBusConnection* pConnection, std::vector<Communicator*>* pCommunicators)
+{
+ setupBluez5Profile1(pConnection, pCommunicators);
+
+ DBusMessage *pMsg;
+ DBusMessageIter it;
+
+ pMsg = dbus_message_new_method_call("org.bluez", "/org/bluez",
+ "org.bluez.ProfileManager1", "RegisterProfile");
+ dbus_message_iter_init_append(pMsg, &it);
+
+ const char *pPath = "/org/libreoffice/bluez/profile1";
+ dbus_message_iter_append_basic(&it, DBUS_TYPE_OBJECT_PATH, &pPath);
+ const char *pUUID = "spp"; // Bluez translates this to 0x1101 for spp
+ dbus_message_iter_append_basic(&it, DBUS_TYPE_STRING, &pUUID);
+
+ DBusMessageIter aOptionsIter;
+ dbus_message_iter_open_container(&it, DBUS_TYPE_ARRAY, "{sv}", &aOptionsIter);
+
+ DBusMessageIter aEntry;
+
+ {
+ dbus_message_iter_open_container(&aOptionsIter, DBUS_TYPE_DICT_ENTRY, NULL, &aEntry);
+
+ const char *pString = "Name";
+ dbus_message_iter_append_basic(&aEntry, DBUS_TYPE_STRING, &pString);
+
+ const char *pValue = "LibreOffice Impress Remote";
+ DBusMessageIter aValue;
+ dbus_message_iter_open_container(&aEntry, DBUS_TYPE_VARIANT, "s", &aValue);
+ dbus_message_iter_append_basic(&aValue, DBUS_TYPE_STRING, &pValue);
+ dbus_message_iter_close_container(&aEntry, &aValue);
+ dbus_message_iter_close_container(&aOptionsIter, &aEntry);
+ }
+
+ dbus_message_iter_close_container(&it, &aOptionsIter);
+
+ // Other properties that we could set (but don't, since they appear
+ // to be useless for us):
+ // "Service": "0x1101" (not needed, but we used to have it in the manually defined profile).
+ // "Role": setting this to "server" breaks things, although we think we're a server?
+ // "Channel": seems to be dealt with automatically (but we used to use 5 in the manual profile).
+
+ bool bSuccess = true;
+
+ pMsg = sendUnrefAndWaitForReply( pConnection, pMsg );
+
+ DBusError aError;
+ dbus_error_init(&aError);
+ if (pMsg && dbus_set_error_from_message( &aError, pMsg ))
+ {
+ bSuccess = false;
+ SAL_WARN("sdremote.bluetooth",
+ "Failed to register our Profile1 with bluez ProfileManager "
+ << (const char *)(aError.message ? aError.message : "<null>"));
+ }
+
+ dbus_error_free(&aError);
+ if (pMsg)
+ dbus_message_unref(pMsg);
+
+ dbus_connection_flush(pConnection);
+
+ return bSuccess;
+}
+
#endif // LINUX_BLUETOOTH
BluetoothServer::BluetoothServer( std::vector<Communicator*>* pCommunicators )
@@ -642,14 +1137,11 @@ void BluetoothServer::doEnsureDiscoverable()
if( !pAdapter )
return;
- bool bDiscoverable;
- if( getBooleanProperty( spServer->mpImpl->mpConnection, pAdapter,
- "Discoverable", &bDiscoverable ) )
- {
- spServer->meWasDiscoverable = bDiscoverable ? DISCOVERABLE : NOT_DISCOVERABLE;
- if( !bDiscoverable )
- setDiscoverable( spServer->mpImpl->mpConnection, pAdapter, true );
- }
+ bool bDiscoverable = getDiscoverable(spServer->mpImpl->mpConnection, pAdapter );
+
+ spServer->meWasDiscoverable = bDiscoverable ? DISCOVERABLE : NOT_DISCOVERABLE;
+ if( !bDiscoverable )
+ setDiscoverable( spServer->mpImpl->mpConnection, pAdapter, true );
delete pAdapter;
#endif
@@ -690,6 +1182,56 @@ void SAL_CALL BluetoothServer::run()
if( !pConnection )
return;
+
+ // For either implementation we need to poll the dbus fd
+ int fd = -1;
+ GPollFD aDBusFD;
+ if( dbus_connection_get_unix_fd( pConnection, &fd ) && fd >= 0 )
+ {
+ aDBusFD.fd = fd;
+ aDBusFD.events = G_IO_IN | G_IO_PRI;
+ g_main_context_add_poll( mpImpl->mpContext, &aDBusFD, G_PRIORITY_DEFAULT );
+ }
+ else
+ SAL_WARN( "sdremote.bluetooth", "failed to poll for incoming dbus signals" );
+
+ if (isBluez5Available(pConnection))
+ {
+ SAL_INFO("sdremote.bluetooth", "Using Bluez 5");
+ registerBluez5Profile(pConnection, mpCommunicators);
+ mpImpl->mpConnection = pConnection;
+ mpImpl->maBluezVersion = Impl::BLUEZ5;
+
+ // We don't need to listen to adapter changes anymore -- profile
+ // registration is done globally for the entirety of bluez, so we only
+ // need adapters when setting discovereability, which can be done
+ // dyanmically without the need to listen for changes.
+
+ // TODO: exit on SD deinit
+ // Probably best to do that in SdModule::~SdModule?
+ while (!mpImpl->mbExitMainloop)
+ {
+ aDBusFD.revents = 0;
+ g_main_context_iteration( mpImpl->mpContext, TRUE );
+ if( aDBusFD.revents )
+ {
+ dbus_connection_read_write( pConnection, 0 );
+ while (DBUS_DISPATCH_DATA_REMAINS == dbus_connection_get_dispatch_status( pConnection ))
+ dbus_connection_dispatch( pConnection );
+ }
+ }
+ unregisterBluez5Profile( pConnection );
+ g_main_context_unref( mpImpl->mpContext );
+ mpImpl->mpConnection = NULL;
+ mpImpl->mpContext = NULL;
+ return;
+ }
+
+ // Otherwise we could be on Bluez 4 and continue as usual.
+ mpImpl->maBluezVersion = Impl::BLUEZ4;
+
+ // Try to setup the default adapter, otherwise wait for add/remove signal
+ mpImpl->mpService = registerWithDefaultAdapter( pConnection );
// listen for connection state and power changes - we need to close
// and re-create our socket code on suspend / resume, enable/disable
DBusError aError;
@@ -705,18 +1247,6 @@ void SAL_CALL BluetoothServer::run()
if( mpImpl->mpService )
bluezCreateAttachListeningSocket( mpImpl->mpContext, &aSocketFD );
- // also poll on our dbus connection
- int fd = -1;
- GPollFD aDBusFD;
- if( dbus_connection_get_unix_fd( pConnection, &fd ) && fd >= 0 )
- {
- aDBusFD.fd = fd;
- aDBusFD.events = G_IO_IN | G_IO_PRI;
- g_main_context_add_poll( mpImpl->mpContext, &aDBusFD, G_PRIORITY_DEFAULT );
- }
- else
- SAL_WARN( "sdremote.bluetooth", "failed to poll for incoming dbus signals" );
-
mpImpl->mpConnection = pConnection;
while( !mpImpl->mbExitMainloop )
@@ -779,6 +1309,7 @@ void SAL_CALL BluetoothServer::run()
}
}
+ unregisterBluez5Profile( pConnection );
g_main_context_unref( mpImpl->mpContext );
mpImpl->mpConnection = NULL;
mpImpl->mpContext = NULL;
diff --git a/sd/source/ui/remotecontrol/BufferedStreamSocket.cxx b/sd/source/ui/remotecontrol/BufferedStreamSocket.cxx
index 4b4c1ce..4417e09 100644
--- a/sd/source/ui/remotecontrol/BufferedStreamSocket.cxx
+++ b/sd/source/ui/remotecontrol/BufferedStreamSocket.cxx
@@ -61,7 +61,7 @@ sal_Int32 BufferedStreamSocket::write( const void* pBuffer, sal_uInt32 n )
void BufferedStreamSocket::close()
{
- if( usingCSocket )
+ if( usingCSocket && mSocket != -1 )
{
#ifdef WIN32
::closesocket( mSocket );
diff --git a/sd/source/ui/remotecontrol/Communicator.cxx b/sd/source/ui/remotecontrol/Communicator.cxx
index 4b2dc84..d3af697 100644
--- a/sd/source/ui/remotecontrol/Communicator.cxx
+++ b/sd/source/ui/remotecontrol/Communicator.cxx
@@ -122,6 +122,8 @@ void Communicator::execute()
pTransmitter->join();
pTransmitter = NULL;
+ if( mpSocket )
+ mpSocket->close();
delete mpSocket;
--
1.8.4.5

View File

@ -1,46 +1,71 @@
From 7dba6e0a71d090f06a6a1a39e87572674593b48a Mon Sep 17 00:00:00 2001
From: Jan-Marek Glogowski <glogow@fbihome.de>
Date: Mon, 10 Mar 2014 14:44:05 +0000
Subject: fdo#73115: Always run timeouts as events
From 71f2aff7a56cef4e133abad3c2e447c76c5ee1fe Mon Sep 17 00:00:00 2001
From: Luboš Luňák <l.lunak@collabora.com>
Date: Tue, 25 Mar 2014 11:20:16 +0000
Subject: prevent KDE/Qt from interfering with the session manager
Right-click popup menus run click events throught the LO main loop.
In case of KDE4 the LO main loop is run by a timer in the main thread,
with Qt::DirectConnection execution.
I occassionally get lockups in IceProcessMessages() called from QtCore,
I'm actually not exactly sure why, as theoretically two connections
from one app shouldn't be a problem, but since LO does its own
session handling, there's no need to the KDE/Qt code to be involved,
so prevent it from connecting to the session manager altogether.
If the timeout actually starts a nested event loop for a new dialog,
the timer is blocked, the nested mainloop detects it was started
from the timeout and drops the blocked timout from polling, which
blocks any further LibreOffice event loop processing.
This changes the timers to Qt::QueuedConnection, so they always
generate an event and are processed by the Qt event loop.
Change-Id: Ie626b22be3d8f9b8934bcc5e9e0e67a365549cfc
(cherry picked from commit aeda478a02523cec146f6af69710f0391061db56)
Reviewed-on: https://gerrit.libreoffice.org/8514
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Change-Id: Iebe20d4cb5403e5fea8bd5d8c1f69b62d1c2907b
---
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
index b4be6d6..4a9b70b 100644
index 820d39a..e4900a7 100644
--- a/vcl/unx/kde4/KDEXLib.cxx
+++ b/vcl/unx/kde4/KDEXLib.cxx
@@ -67,9 +67,13 @@ KDEXLib::KDEXLib() :
eventLoopType( LibreOfficeEventLoop ),
m_bYieldFrozen( false )
{
- // 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()));
+ // the timers created here means they belong to the main thread.
+ // As the timeoutTimer runs the LO event queue, which may block on a dialog,
+ // the timer has to use a Qt::QueuedConnection, otherwise the nested event
+ // loop will detect the blocking timer and drop it from the polling
+ // freezing LO X11 processing.
+ connect( &timeoutTimer, SIGNAL( timeout()), this, SLOT( timeoutActivated()), Qt::QueuedConnection );
+ connect( &userEventTimer, SIGNAL( timeout()), this, SLOT( userEventActivated()), Qt::QueuedConnection );
@@ -166,8 +166,23 @@ void KDEXLib::Init()
KCmdLineArgs::init( m_nFakeCmdLineArgs, m_pAppCmdLineArgs, kAboutData );
+ // LO does its own session management, so prevent KDE/Qt from interfering
+ // (QApplication::disableSessionManagement(false) wouldn't quite do,
+ // since that still actually connects to the session manager, it just
+ // won't save the application data on session shutdown).
+ char* session_manager = NULL;
+ if( getenv( "SESSION_MANAGER" ) != NULL )
+ {
+ session_manager = strdup( getenv( "SESSION_MANAGER" ));
+ unsetenv( "SESSION_MANAGER" );
+ }
m_pApplication = new VCLKDEApplication();
- kapp->disableSessionManagement();
+ if( session_manager != NULL )
+ {
+ setenv( "SESSION_MANAGER", session_manager, 1 );
+ free( session_manager );
+ }
+
KApplication::setQuitOnLastWindowClosed(false);
#if KDE_HAVE_GLIB
diff --git a/vcl/unx/kde4/VCLKDEApplication.hxx b/vcl/unx/kde4/VCLKDEApplication.hxx
index 412ee34..4ce0b2c 100644
--- a/vcl/unx/kde4/VCLKDEApplication.hxx
+++ b/vcl/unx/kde4/VCLKDEApplication.hxx
@@ -21,22 +21,14 @@
#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);
};
// QTimer::start() can be called only in its (here main) thread, so this will
// forward between threads if needed
--
cgit v0.9.0.2-2-gbebe

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dfbf3a9025765a73b591438e1a6cc703fc39865bd7ba0933ffebfbffb86dd672
size 123291796

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d166ffa1f2cd336a2f668ea3a912aaf98873757c67e1bcde1ac6f57c6cc605a0
size 123378868

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:559cf226dfc0df7d149445f0938803da144b4fa89be80b96a9a1262d6a5db67c
size 1855268

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a372efb0f82eeed56b7232d15a2d80a522174c3127986f6210239bbbfc342a3d
size 1855080

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:850c483cb83d7e376ee443a519285d1079752d1bb6fd313ae5c545bdd638c780
size 127774372

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c457dbf874c6f59da002288e3831cdba162f18aebf36d26f2d19f468af2c32f7
size 127819696

View File

@ -1,3 +1,24 @@
-------------------------------------------------------------------
Tue May 6 19:58:50 UTC 2014 - tchvatal@suse.com
- Version bump to 4.2.4.2:
* another bugfix release fixing more than dozen of issues.
- Add explicit dep over libxslt
- Remove patch applied upstream:
* bluez5-support-for-impress-remote.diff
-------------------------------------------------------------------
Mon May 5 13:35:28 UTC 2014 - tchvatal@suse.com
- Generate autocorr content for various language mutations properly
(shamelessly stolen from Fedora).
-------------------------------------------------------------------
Mon May 5 13:24:33 UTC 2014 - tchvatal@suse.com
- Use patch from upstream to handle the mutexes way better.
Updated patch kde4-4.2.3.3-timer-mutex.patch.
-------------------------------------------------------------------
Mon May 5 07:14:50 UTC 2014 - tchvatal@suse.com

View File

@ -29,9 +29,9 @@
%define numbertext_version 0.9.5
# Urls
%define external_url http://dev-www.libreoffice.org/src/
%define tarball_url http://download.documentfoundation.org/libreoffice/src/4.2.3/
%define tarball_url http://download.documentfoundation.org/libreoffice/src/4.2.4/
Name: libreoffice
Version: 4.2.3.3
Version: 4.2.4.2
Release: 0
Summary: A Free Office Suite (Framework)
License: Apache-2.0 and Artistic-1.0 and BSD-3-Clause and BSD-4-Clause and GPL-2.0+ and LPPL-1.3c and LGPL-2.1+ and LGPL-3.0 and MPL-1.1 and MIT and SUSE-Public-Domain and W3C
@ -87,8 +87,6 @@ Patch12: mediawiki-no-broken-help.diff
Patch13: jvmfwk-disable-gcj.diff
# Fix running wizzards in py2 as the utf is not htere
Patch16: wizards-create-temlates-with-python-2.6.diff
# Fix fdo#74697 add Bluez 5 support for impress remote.
Patch17: bluez5-support-for-impress-remote.diff
# PATCH-FIX-UPSTREAM: fix kde hanging in 4.2.3.3
Patch18: kde4-4.2.3.3-timer-mutex.patch
# try to save space by using hardlinks
@ -171,6 +169,7 @@ BuildRequires: libwpd-devel
BuildRequires: libwpg-devel
BuildRequires: libwps-devel
BuildRequires: libxml2-devel
BuildRequires: libxslt-devel
BuildRequires: lpsolve-devel
BuildRequires: make
BuildRequires: mdds-devel >= 0.8.0
@ -627,6 +626,15 @@ This package provides extensions for LibreOffice Writer:
- MediaWiki Publisher
# Symlink autocorr files for various conversion items
%define make_autocorr_aliases(l:) \
%{?-l: \
for lang in %{*}; do \
ln -sf acor_%{-l*}.dat %{buildroot}%{_libdir}/%{name}/share/autocorr/acor_$lang.dat \
done \
} \
%{!?-l:%{error:-l must be present}}
# Symlinking macro for /usr/lib64 and /usr/share packing
# As argument takes name of the package
%define _link_noarch_files() \
@ -841,8 +849,7 @@ Provides additional %{langname} translations and resources for %{project}. \
%patch12
%patch13 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1 -R
%patch18 -p1
%patch990 -p1
# 256x256 icons
tar -xjf %{SOURCE20}
@ -1090,12 +1097,26 @@ for file in sofficerc \
echo "%{_datadir}/%{name}/program/$file" >> file-lists/branding_upstream.txt
done
################
# FIXME: fast hack to solve a customer issue, n#364523
# we need a more generic solution
# FIXME: can be done better, see how fedora does it and imitate
ln -sf acor_fr-FR.dat %{buildroot}%{_libdir}/%{name}/share/autocorr/acor_fr-CA.dat
echo "%{_libdir}/%{name}/share/autocorr/acor_fr-CA.dat" >>file-lists/common_list.txt
# Fix autocorr names for various language mutations
%make_autocorr_aliases -l en-GB en-AG en-AU en-BS en-BW en-BZ en-CA en-DK en-GH en-HK en-IE en-IN en-JM en-NG en-NZ en-SG en-TT
%make_autocorr_aliases -l en-US en-PH
%make_autocorr_aliases -l en-ZA en-NA en-ZW
%make_autocorr_aliases -l af-ZA af-NA
%make_autocorr_aliases -l de-DE de-AT de-BE de-CH de-LI de-LU
%make_autocorr_aliases -l es-ES es-AR es-BO es-CL es-CO es-CR es-CU es-DO es-EC es-GT es-HN es-MX es-NI es-PA es-PE es-PR es-PY es-SV es-US es-UY es-VE
%make_autocorr_aliases -l fr-FR fr-BE fr-CA fr-CH fr-LU fr-MC
%make_autocorr_aliases -l it-IT it-CH
%make_autocorr_aliases -l nl-NL nl-AW
%make_autocorr_aliases -l sv-SE sv-FI
pushd %{buildroot}%{_libdir}/%{name}/share/autocorr
files=""
for file in acor*.dat; do
files="$files $file"
done
popd
for file in $files; do
echo "%{_libdir}/%{name}/share/autocorr/$file" >> file-lists/common_list.txt
done
# Symlink uno.py and unohelper.py so that python can find them
mkdir -p %{buildroot}%{python_sitelib}