Various fixes for khotkeys. This resolves issue #326.

1. ensure there is a single khotkeys instance running per session
   instead of per screen (remote multihead related code)
2. allow khotkeys to be run as a kded module
3. make sure that khotkeys run either as a standalone application or as
   a kded module, but not both at the same time
4. do not register khotkeys as a main DCOP entry (like an app) anymore.
   When run as kded module, this was causing kded to be registered as
   khotkeys a second time.

Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
pull/536/head
Michele Calgaro 2 months ago
parent 7f1a1e931e
commit 94368f4722
Signed by: MicheleC
GPG Key ID: 2A75B7CA8ADED5CF

@ -3,3 +3,9 @@
tde_l10n_create_template( "khotkeys" )
tde_l10n_auto_add_subdirectories()
tde_l10n_create_template(
CATALOG "desktop_files/khotkeys.desktop/"
SOURCES app/khotkeys.desktop kcontrol/khotkeys.desktop
DESTINATION "${CMAKE_SOURCE_DIR}/translations"
)

@ -22,6 +22,14 @@ link_directories(
)
##### other data ################################
tde_create_translated_desktop(
SOURCE khotkeys.desktop
DESTINATION ${SERVICES_INSTALL_DIR}/kded
)
##### kded_khotkeys (module) ####################
tde_add_kpart( kded_khotkeys AUTOMOC

@ -16,6 +16,7 @@
#include "app.h"
#include <dcopclient.h>
#include <tdecmdlineargs.h>
#include <tdeconfig.h>
#include <tdelocale.h>
@ -42,18 +43,16 @@ KHotKeysApp::KHotKeysApp()
delete_helper( new TQObject )
{
init_global_data( true, delete_helper ); // grab keys
// CHECKME triggery a dalsi vytvaret az tady za inicializaci
actions_root = NULL;
reread_configuration();
}
KHotKeysApp::~KHotKeysApp()
{
// CHECKME triggery a dalsi rusit uz tady pred cleanupem
delete actions_root;
// Many global data should be destroyed while the TQApplication object still
// exists, and therefore 'this' cannot be the parent, as ~Object
// for 'this' would be called after ~TQApplication - use proxy object
// Many global data should be destroyed while the TQApplication object still
// exists, and therefore 'this' cannot be the parent, as ~Object()
// for 'this' would be called after ~TQApplication() - use proxy object
delete delete_helper;
}
@ -93,66 +92,52 @@ static int khotkeys_screen_number = 0;
extern "C"
int TDE_EXPORT kdemain( int argc, char** argv )
{
// Check if khotkeys is already running as a kded module.
// In such case just exit.
DCOPClient *dcopClient = new DCOPClient;
if (!dcopClient->isAttached())
{
if (!dcopClient->attach())
{
kdWarning(1217) << "khotkeys [application]: could not register with DCOP. Exiting." << endl;
delete dcopClient;
return 1;
}
}
TQCString replyType;
TQByteArray replyData;
if (dcopClient->call("kded", "kded", "loadedModules()",
TQByteArray(), replyType, replyData))
{
if (replyType == "QCStringList")
{
{
// multiheaded hotkeys
TQCString multiHead = getenv("TDE_MULTIHEAD");
if (multiHead.lower() == "true") {
Display *dpy = XOpenDisplay(NULL);
if (! dpy) {
fprintf(stderr, "%s: FATAL ERROR while trying to open display %s\n",
argv[0], XDisplayName(NULL));
exit(1);
}
int number_of_screens = ScreenCount(dpy);
khotkeys_screen_number = DefaultScreen(dpy);
int pos;
TQCString displayname = XDisplayString(dpy);
XCloseDisplay(dpy);
dpy = 0;
if ((pos = displayname.findRev('.')) != -1)
displayname.remove(pos, 10);
TQCString env;
if (number_of_screens != 1) {
for (int i = 0; i < number_of_screens; i++) {
if (i != khotkeys_screen_number && fork() == 0) {
khotkeys_screen_number = i;
// break here because we are the child process, we don't
// want to fork() anymore
break;
}
}
env.sprintf("DISPLAY=%s.%d", displayname.data(), khotkeys_screen_number);
if (putenv(strdup(env.data()))) {
fprintf(stderr,
"%s: WARNING: unable to set DISPLAY environment variable\n",
argv[0]);
perror("putenv()");
}
}
}
}
TQCString appname;
if (khotkeys_screen_number == 0)
appname = "khotkeys";
else
appname.sprintf("khotkeys-screen-%d", khotkeys_screen_number);
// no need to i18n these, no GUI
TDECmdLineArgs::init( argc, argv, appname, I18N_NOOP( "KHotKeys" ),
I18N_NOOP( "KHotKeys daemon" ), KHOTKEYS_VERSION );
KUniqueApplication::addCmdLineOptions();
if( !KHotKeysApp::start()) // already running
return 0;
KHotKeysApp app;
app.disableSessionManagement();
return app.exec();
TQDataStream reply(replyData, IO_ReadOnly);
QCStringList modules;
reply >> modules;
if (modules.contains("khotkeys"))
{
// khotkeys is already running as a service, do nothing
kdWarning(1217) << "khotkeys is already running as a kded module. Exiting." << endl;
delete dcopClient;
return 2;
}
}
}
delete dcopClient;
// no need to i18n these, no GUI
TDECmdLineArgs::init( argc, argv, "khotkeys", I18N_NOOP( "KHotKeys" ),
I18N_NOOP( "KHotKeys daemon" ), KHOTKEYS_VERSION );
KUniqueApplication::addCmdLineOptions();
if( !KHotKeysApp::start()) // already running
{
return 0;
}
KHotKeysApp app;
app.disableSessionManagement();
return app.exec();
}
#include "app.moc"

@ -16,6 +16,7 @@
#include "kded.h"
#include <dcopclient.h>
#include <tdecmdlineargs.h>
#include <tdeconfig.h>
#include <tdelocale.h>
@ -35,9 +36,17 @@
extern "C"
TDE_EXPORT KDEDModule *create_khotkeys( const TQCString& obj )
{
return new KHotKeys::KHotKeysModule( obj );
}
{
// Check if khotkeys is already running as a stand alone application.
// In such case just exit.
if (kapp->dcopClient()->isApplicationRegistered("khotkeys"))
{
kdWarning(1217) << "khotkeys [kded module] is already running as a standalone application. Exiting." << endl;
return nullptr;
}
return new KHotKeys::KHotKeysModule( obj );
}
namespace KHotKeys
{
@ -47,22 +56,7 @@ namespace KHotKeys
KHotKeysModule::KHotKeysModule( const TQCString& obj )
: KDEDModule( obj )
{
for( int i = 0;
i < 5;
++i )
{
if( kapp->dcopClient()->isApplicationRegistered( "khotkeys" ))
{
TQByteArray data, replyData;
TQCString reply;
// wait for it to finish
kapp->dcopClient()->call( "khotkeys*", "khotkeys", "quit()", data, reply, replyData );
sleep( 1 );
}
}
client.registerAs( "khotkeys", false ); // extra dcop connection (like if it was an app)
init_global_data( true, this ); // grab keys
// CHECKME triggery a dalsi vytvaret az tady za inicializaci
actions_root = NULL;
reread_configuration();
}

@ -12,27 +12,27 @@
#define _KHOTKEYS_KDED_H_
#include <kdedmodule.h>
#include <dcopclient.h>
namespace KHotKeys
{
class Action_data_group;
class KHotKeysModule
: public KDEDModule
class KHotKeysModule : public KDEDModule
{
TQ_OBJECT
K_DCOP
k_dcop:
ASYNC reread_configuration();
ASYNC quit();
public:
KHotKeysModule( const TQCString& obj );
virtual ~KHotKeysModule();
private:
Action_data_group* actions_root;
DCOPClient client;
};
//***************************************************************************

@ -0,0 +1,13 @@
[Desktop Entry]
Type=Service
Name=KHotkeys Daemon
Comment=Handles input actions for the current session
X-TDE-ServiceTypes=KDEDModule
X-TDE-ModuleType=Library
X-TDE-Library=khotkeys
X-TDE-FactoryName=khotkeys
X-TDE-Kded-autoload=true
X-TDE-Kded-load-on-demand=false

@ -1,7 +0,0 @@
##### create translation templates ##############
tde_l10n_create_template(
CATALOG "desktop_files/khotkeys.desktop/"
SOURCES khotkeys.desktop
DESTINATION "${CMAKE_SOURCE_DIR}/translations"
)

@ -24,24 +24,17 @@ extern "C"
{
TDE_EXPORT void init_khotkeys()
{
TDEConfig cfg( "khotkeysrc", true );
cfg.setGroup( "Main" );
if( !cfg.readBoolEntry( "Autostart", false ))
return;
// Non-xinerama multhead support in KDE is just a hack
// involving forking apps per-screen. Don't bother with
// kded modules in such case.
TQCString multiHead = getenv("TDE_MULTIHEAD");
if (multiHead.lower() == "true")
kapp->tdeinitExec( "khotkeys" );
else
{
DCOPRef ref( "kded", "kded" );
if( !ref.call( "loadModule", TQCString( "khotkeys" )))
{
kdWarning( 1217 ) << "Loading of khotkeys module failed." << endl;
kapp->tdeinitExec( "khotkeys" );
}
}
TDEConfig cfg( "khotkeysrc", true );
cfg.setGroup( "Main" );
if( !cfg.readBoolEntry( "Autostart", false ))
{
return;
}
DCOPRef ref( "kded", "kded" );
if( !ref.call( "loadModule", TQCString( "khotkeys" )))
{
kdWarning( 1217 ) << "Loading of khotkeys module failed." << endl;
kapp->tdeinitExec( "khotkeys" );
}
}
}

Loading…
Cancel
Save