/* $Id: daemon.c 2337 2007-01-11 19:17:30Z nick $ * * Copyright (C) 2006 Christian Hammond * Copyright (C) 2005 John (J5) Palmieri * Copyright (C) 2006 Nick Schermer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "daemon.h" NotifierContainer* GTKNotifierContainer = NULL; void real_handleGTKMain(); NotifierContainer::NotifierContainer() : TQWidget() { mPopupList.clear(); // Determine bottom of desktop TQPoint cursorPos = TQCursor::pos(); TQRect r = KGlobalSettings::desktopGeometry(cursorPos); mTopOfStack = r.height(); mRightOfStack = r.width(); } NotifierContainer::~NotifierContainer() { } void NotifierContainer::handleGTKMain() { real_handleGTKMain(); } void NotifierContainer::displayMessage(TQString title, TQString message, TQString icon, int x, int y) { TQPixmap px; KIconLoader* il = KGlobal::iconLoader(); px = il->loadIcon( icon, KIcon::NoGroup ); // if (px.isNull()) { // px = il->loadIcon( "gnome_apps", KIcon::NoGroup ); // } KPassivePopup *pop = new KPassivePopup( KPassivePopup::Boxed, this, "" ); pop->setAutoDelete( true ); pop->setView( title, message, icon ); pop->setTimeout( -1 ); TQPoint leftCorner( x, y); if (leftCorner.isNull()) { if (mPopupList.isEmpty()) { // Determine bottom of desktop TQPoint cursorPos = TQCursor::pos(); TQRect r = KGlobalSettings::desktopGeometry(cursorPos); mTopOfStack = r.height(); mRightOfStack = r.width(); } TQSize popupSize = pop->tqsizeHint(); mTopOfStack = mTopOfStack-popupSize.height(); if (mTopOfStack < 0) mTopOfStack = 0; leftCorner.setX(mRightOfStack-popupSize.width()); leftCorner.setY(mTopOfStack); } connect(pop, SIGNAL(hidden(KPassivePopup*)), this, SLOT(popupClosed(KPassivePopup*))); mPopupList.append(pop); pop->show(leftCorner); processEvents(); } void NotifierContainer::processEvents() { tqApp->processEvents(); } void NotifierContainer::popupClosed(KPassivePopup* popup) { // Remove the popup from our list of popups mPopupList.remove(popup); if (mPopupList.isEmpty()) { // Determine bottom of desktop TQPoint cursorPos = TQCursor::pos(); TQRect r = KGlobalSettings::desktopGeometry(cursorPos); mTopOfStack = r.height(); mRightOfStack = r.width(); } } #undef signals #include #include #include #include #include #include #include "notificationdaemon-dbus-glue.h" #define IMAGE_SIZE 48 #define NW_GET_NOTIFY_ID(nw) \ (GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(nw), "_notify_id"))) #define NW_GET_NOTIFY_SENDER(nw) \ (g_object_get_data(G_OBJECT(nw), "_notify_sender")) #define NW_GET_DAEMON(nw) \ (g_object_get_data(G_OBJECT(nw), "_notify_daemon")) static const char *description = I18N_NOOP("A DBUS notification to TDE interface."); static const char *message = I18N_NOOP("First release October 2011."); static const char *version = "0.01"; typedef struct { GTimeVal expiration; GTimeVal paused_diff; gboolean has_timeout; gboolean paused; guint id; GtkWindow *nw; } NotifyTimeout; static DBusConnection *dbus_conn = NULL; #define CHECK_DBUS_VERSION(major, minor) \ (DBUS_MAJOR_VER > (major) || \ (DBUS_MAJOR_VER == (major) && DBUS_MINOR_VER >= (minor))) #if !CHECK_DBUS_VERSION(0, 60) /* This is a hack that will go away in time. For now, it's fairly safe. */ struct _DBusGMethodInvocation { DBusGConnection *connection; DBusGMessage *message; const DBusGObjectInfo *object; const DBusGMethodInfo *method; }; #endif /* D-BUS < 0.60 */ G_DEFINE_TYPE(NotifyDaemon, notify_daemon, G_TYPE_OBJECT); static void notify_daemon_finalize(GObject *object) { NotifyDaemon *daemon = NOTIFY_DAEMON(object); GObjectClass *parent_class = G_OBJECT_CLASS(notify_daemon_parent_class); if (parent_class->finalize != NULL) parent_class->finalize(object); } static void notify_daemon_class_init(NotifyDaemonClass *daemon_class) { GObjectClass *object_class = G_OBJECT_CLASS(daemon_class); object_class->finalize = notify_daemon_finalize; } static void notify_daemon_init(NotifyDaemon *daemon) { } gboolean notify_daemon_notify_handler(NotifyDaemon *daemon, const gchar *app_name, guint id, const gchar *icon, const gchar *summary, const gchar *body, gchar **actions, GHashTable *hints, int timeout, DBusGMethodInvocation *context) { NotifyDaemonPrivate *priv = daemon->priv; NotifyTimeout *nt = NULL; GtkWindow *nw = NULL; GValue *data; gboolean use_pos_data = FALSE; gboolean new_notification = FALSE; gint x = 0; gint y = 0; guint return_id; gchar *sender; gint i; /* deal with x, and y hints */ if ((data = (GValue *)g_hash_table_lookup(hints, "x")) != NULL) { x = g_value_get_int(data); if ((data = (GValue *)g_hash_table_lookup(hints, "y")) != NULL) { y = g_value_get_int(data); use_pos_data = TRUE; } } // Send a notification request to KDE here... TQString messageText = TQString(body); GTKNotifierContainer->displayMessage(TQString(summary), TQString(body), TQString(icon), x, y); return_id = 0; dbus_g_method_return(context, return_id); return TRUE; } gboolean notify_daemon_close_notification_handler(NotifyDaemon *daemon, guint id, GError **error) { // Do nothing return TRUE; } gboolean notify_daemon_get_capabilities(NotifyDaemon *daemon, char ***caps) { *caps = g_new0(char *, 6); (*caps)[0] = g_strdup("actions"); (*caps)[1] = g_strdup("body"); (*caps)[2] = g_strdup("body-hyperlinks"); (*caps)[3] = g_strdup("body-markup"); (*caps)[4] = g_strdup("icon-static"); (*caps)[5] = NULL; return TRUE; } gboolean notify_daemon_reload_settings (NotifyDaemon *daemon) { // Do nothing return TRUE; } gboolean notify_daemon_get_server_information(NotifyDaemon *daemon, char **out_name, char **out_vendor, char **out_version, char **out_spec_ver) { *out_name = g_strdup("Notification Daemon"); *out_vendor = g_strdup("Trinity Desktop Project"); *out_version = g_strdup(VERSION); *out_spec_ver = g_strdup("0.1"); return TRUE; } int main(int argc, char **argv) { NotifyDaemon *daemon; DBusGConnection *connection; DBusGProxy *bus_proxy; GError *error; guint request_name_result; g_set_application_name ("notification-daemon-tde"); #ifdef G_ENABLE_DEBUG g_log_set_always_fatal(G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL); #endif gtk_init(&argc, &argv); error = NULL; connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); if (connection == NULL) { g_printerr("Failed to open connection to bus: %s\n", error->message); g_error_free(error); exit(1); } dbus_conn = dbus_g_connection_get_connection(connection); dbus_g_object_type_install_info(NOTIFY_TYPE_DAEMON, &dbus_glib_notification_daemon_tde_object_info); bus_proxy = dbus_g_proxy_new_for_name(connection, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus"); if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error, G_TYPE_STRING, "org.freedesktop.Notifications", G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &request_name_result, G_TYPE_INVALID)) { g_error("Could not aquire name: %s", error->message); } daemon = static_cast(g_object_new(NOTIFY_TYPE_DAEMON, NULL)); dbus_g_connection_register_g_object(connection, "/org/freedesktop/Notifications", G_OBJECT(daemon)); KAboutData aboutData("notification-daemon-tde", I18N_NOOP("TDE DBUS Notification Daemon"), version, description, KAboutData::License_GPL, "(c) 2011, Timothy Pearson", message, 0 /* TODO: Website */, "kb9vqf@pearsoncomputing.net"); KCmdLineArgs::init(argc, argv, &aboutData); KApplication app; NotifierContainer nc; app.setMainWidget(&nc); GTKNotifierContainer = &nc; TQTimer *gtkEventProcessor = new TQTimer( &app ); TQObject::connect( gtkEventProcessor, SIGNAL(timeout()), &nc, SLOT(handleGTKMain()) ); gtkEventProcessor->start( 100, FALSE ); // Every 0.1 seconds poll gtk for DBUS events app.disableSessionManagement(); app.exec(); return 0; } void real_handleGTKMain() { while (gtk_events_pending()) gtk_main_iteration(); }