Accepting request 230220 from LibreOffice:Factory

- Fix haning in KDE by applying upstream fix. Will be included
  in next release.
- added patches:
  * kde4-4.2.3.3-timer-mutex.patch

- fix for non-working bluetooth remote control from upstream
- added patches:
  * bluez5-support-for-impress-remote.diff

OBS-URL: https://build.opensuse.org/request/show/230220
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/libreoffice?expand=0&rev=65
This commit is contained in:
Stephan Kulow 2014-04-16 05:26:43 +00:00 committed by Git OBS Bridge
commit d20dfa32bf
4 changed files with 918 additions and 0 deletions

View File

@ -0,0 +1,851 @@
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

@ -0,0 +1,46 @@
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
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.
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>
---
diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx
index b4be6d6..4a9b70b 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 );
// 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 +1,18 @@
-------------------------------------------------------------------
Tue Apr 15 08:32:38 UTC 2014 - tchvatal@suse.com
- Fix haning in KDE by applying upstream fix. Will be included
in next release.
- added patches:
* kde4-4.2.3.3-timer-mutex.patch
-------------------------------------------------------------------
Mon Apr 14 20:00:00 UTC 2014 - tbehrens@suse.com
- fix for non-working bluetooth remote control from upstream
- added patches:
* bluez5-support-for-impress-remote.diff
-------------------------------------------------------------------
Fri Apr 11 14:14:14 UTC 2014 - tchvatal@suse.com

View File

@ -87,6 +87,10 @@ 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
Patch990: install-with-hardlinks.diff
BuildRequires: ImageMagick
@ -837,6 +841,8 @@ Provides additional %{langname} translations and resources for %{project}. \
%patch12
%patch13 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1 -R
%patch990 -p1
# 256x256 icons
tar -xjf %{SOURCE20}