From: Sergei Chernyadyev 1892-Cherser-s@users.noreply.gitlab.winehq.org
--- dlls/winesni.drv/Makefile.in | 2 +- dlls/winesni.drv/dbus.c | 159 +++++++++++++++++++++++++++-------- 2 files changed, 127 insertions(+), 34 deletions(-)
diff --git a/dlls/winesni.drv/Makefile.in b/dlls/winesni.drv/Makefile.in index ed73bf9092b..a3ab6f1075a 100644 --- a/dlls/winesni.drv/Makefile.in +++ b/dlls/winesni.drv/Makefile.in @@ -2,7 +2,7 @@ MODULE = winesni.drv UNIXLIB = winesni.so IMPORTS = uuid win32u UNIX_CFLAGS = $(DBUS_CFLAGS) $(HAL_CFLAGS) -UNIX_LIBS = -lwin32u +UNIX_LIBS = -lwin32u $(PTHREAD_LIBS)
SOURCES = \ dllmain.c \ diff --git a/dlls/winesni.drv/dbus.c b/dlls/winesni.drv/dbus.c index 19aa762d3f0..b04eddd05b2 100644 --- a/dlls/winesni.drv/dbus.c +++ b/dlls/winesni.drv/dbus.c @@ -73,6 +73,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(winesni); DO_FUNC(dbus_connection_unref); \ DO_FUNC(dbus_connection_get_object_path_data); \ DO_FUNC(dbus_connection_get_unix_fd); \ + DO_FUNC(dbus_connection_set_watch_functions); \ + DO_FUNC(dbus_watch_get_unix_fd); \ + DO_FUNC(dbus_watch_handle); \ + DO_FUNC(dbus_watch_get_flags); \ + DO_FUNC(dbus_watch_get_enabled); \ DO_FUNC(dbus_error_free); \ DO_FUNC(dbus_error_init); \ DO_FUNC(dbus_error_is_set); \ @@ -127,11 +132,14 @@ struct tray_icon char tiptext[128 * 3]; /* tooltip text */ UINT version; /* notify icon api version */ DBusConnection* connection; + DBusWatch* watch; + int watch_fd; + UINT watch_flags; pthread_mutex_t mutex; /* mutex */ };
static struct list sni_list = LIST_INIT( sni_list ); -static pthread_mutex_t list_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t list_mutex;
#define BALLOON_SHOW_MIN_TIMEOUT 10000 #define BALLOON_SHOW_MAX_TIMEOUT 30000 @@ -146,6 +154,10 @@ static const char* freedesktop_item_interface_name = "org.freedesktop.StatusNoti static const char* item_interface_name = "org.kde.StatusNotifierItem";
static DBusConnection *global_connection; +static DBusWatch *global_connection_watch; +static int global_connection_watch_fd; +static UINT global_connection_watch_flags; + static char* status_notifier_dst_path = NULL;
static const char *status_field = "Status"; @@ -258,8 +270,6 @@ static BOOL get_owner_for_interface(DBusConnection* connection, const char* inte if (!p_dbus_connection_send_with_reply (connection, msg, &pending, -1)) goto err; if (!pending) goto err;
- p_dbus_connection_flush(connection); - p_dbus_message_unref(msg);
p_dbus_pending_call_block(pending); @@ -299,12 +309,76 @@ BOOL get_notifier_watcher_owner_for_interface(DBusConnection* connection, const return TRUE; }
+ +static dbus_bool_t add_watch(DBusWatch *w, void *data) +{ + int fd; + unsigned int flags, poll_flags; + if (!p_dbus_watch_get_enabled(w)) + return TRUE; + + fd = p_dbus_watch_get_unix_fd(w); + flags = p_dbus_watch_get_flags(w); + poll_flags = 0; + + if (flags & DBUS_WATCH_READABLE) + poll_flags |= POLLIN; + if (flags & DBUS_WATCH_WRITABLE) + poll_flags |= POLLOUT; + + pthread_mutex_lock(&list_mutex); + if (data != NULL) { + struct tray_icon *icon = (struct tray_icon *) data; + icon->watch_fd = fd; + icon->watch_flags = poll_flags; + icon->watch = w; + } else { + /* global connection */ + global_connection_watch_fd = fd; + global_connection_watch_flags = poll_flags; + global_connection_watch = w; + } + pthread_mutex_unlock(&list_mutex); + + return TRUE; +} +static void remove_watch(DBusWatch *w, void *data) +{ + pthread_mutex_lock(&list_mutex); + if (data != NULL) { + struct tray_icon *icon = (struct tray_icon *) data; + icon->watch_fd = 0; + icon->watch_flags = 0; + icon->watch = NULL; + } else { + /* global connection */ + global_connection_watch_fd = 0; + global_connection_watch_flags = 0; + global_connection_watch = NULL; + } + pthread_mutex_unlock(&list_mutex); +} + + +static void toggle_watch(DBusWatch *w, void *data) +{ + if (p_dbus_watch_get_enabled(w)) + add_watch(w, data); + else + remove_watch(w, data); +} + BOOL get_notifier_watcher_owner(void) { DBusError error; + pthread_mutexattr_t attr; p_dbus_error_init( &error ); if (!p_dbus_threads_init_default()) goto err;
+ pthread_mutexattr_init( &attr ); + pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); + pthread_mutex_init( &list_mutex, &attr ); + if (!(global_connection = p_dbus_bus_get_private( DBUS_BUS_SESSION, &error ))) { WARN("failed to get system dbus connection: %s\n", error.message ); @@ -312,6 +386,12 @@ BOOL get_notifier_watcher_owner(void) goto err; }
+ if (!p_dbus_connection_set_watch_functions(global_connection, add_watch, remove_watch, + toggle_watch, NULL, NULL)) { + WARN("dbus_set_watch_functions() failed\n"); + goto err; + } + if (!get_notifier_watcher_owner_for_interface(global_connection, kde_watcher_interface_name, kde_item_interface_name) && !get_notifier_watcher_owner_for_interface(global_connection, freedesktop_watcher_interface_name, freedesktop_item_interface_name)) { @@ -327,9 +407,11 @@ BOOL get_notifier_watcher_owner(void) p_dbus_error_free( &error); goto err; } + pthread_mutexattr_destroy( &attr ); return TRUE;
err: + pthread_mutexattr_destroy( &attr ); return FALSE; }
@@ -513,8 +595,6 @@ static BOOL send_notification(DBusConnection* connection, const WCHAR* title, co goto err; if (!pending) goto err;
- p_dbus_connection_flush(connection); - p_dbus_message_unref(msg);
p_dbus_pending_call_block(pending); @@ -541,9 +621,11 @@ void dbus_finalize() { if (global_connection != NULL) { + p_dbus_connection_flush(global_connection); p_dbus_connection_close(global_connection); p_dbus_connection_unref(global_connection); } + pthread_mutex_destroy(&list_mutex); if (dbus_module != NULL) { dlclose(dbus_module); @@ -652,7 +734,7 @@ static DBusHandlerResult notification_send_error(DBusConnection *conn, DBusMessa p_dbus_message_unref(reply); return DBUS_HANDLER_RESULT_NEED_MEMORY; } - p_dbus_connection_flush(conn); + p_dbus_message_unref(reply); return DBUS_HANDLER_RESULT_HANDLED; } @@ -803,7 +885,6 @@ DBusHandlerResult get_all_tray_properties(DBusConnection* conn, DBusMessage *mes if (!p_dbus_connection_send(conn, reply, &serial)) goto send_fail;
- p_dbus_connection_flush(conn); p_dbus_message_unref(reply); return DBUS_HANDLER_RESULT_HANDLED; fail: @@ -912,7 +993,6 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage goto err_get; }
- p_dbus_connection_flush(conn); p_dbus_message_unref(reply); err_get: pthread_mutex_unlock((pthread_mutex_t*)&icon->mutex); @@ -1019,40 +1099,44 @@ const DBusObjectPathVTable notification_vtable =
void run_dbus_loop(void) { - int dbus_conn_fd; DBusConnection* conns[128]; + DBusWatch* watches[128]; struct pollfd fd_info[128]; int fd_count; struct pollfd* fd_ptr = fd_info; - p_dbus_connection_get_unix_fd(global_connection, &dbus_conn_fd);
- conns[0] = global_connection; - fd_info[0] = (struct pollfd) { - .fd = dbus_conn_fd, - .events = POLLIN, - }; while (true) { int i, poll_ret; struct tray_icon* icon; - fd_count = 1; + fd_count = 0; pthread_mutex_lock(&list_mutex); + if (global_connection_watch_fd) + { + conns[fd_count] = p_dbus_connection_ref(global_connection); + watches[fd_count] = global_connection_watch; + fd_info[fd_count++] = (struct pollfd) { + .fd = global_connection_watch_fd, + .events = global_connection_watch_flags, + .revents = 0, + }; + } LIST_FOR_EACH_ENTRY( icon, &sni_list, struct tray_icon, entry ) { - int sni_dbus_conn_fd; if (fd_count >= 128) break; - - p_dbus_connection_get_unix_fd(icon->connection, &sni_dbus_conn_fd); + if (!icon->watch_fd) + continue; conns[fd_count] = p_dbus_connection_ref(icon->connection); + watches[fd_count] = icon->watch; fd_info[fd_count++] = (struct pollfd) { - .fd = sni_dbus_conn_fd, - .events = POLLIN, + .fd = icon->watch_fd, + .events = icon->watch_flags, .revents = 0, }; } pthread_mutex_unlock(&list_mutex); - /* TODO: utilize DBusWatch */ + poll_ret = poll(fd_ptr, fd_count, 100); if (poll_ret == 0) continue; @@ -1063,17 +1147,21 @@ void run_dbus_loop(void) } for ( i = 0; i < fd_count; i++ ) { - if ((fd_info[i].revents & POLLIN) && !(fd_info[i].revents & (POLLERR | POLLHUP | POLLNVAL))) - { - /* non blocking read of the next available message */ - if (!p_dbus_connection_read_write(conns[i], 0)) - break; + if (fd_info[i].revents & (POLLERR | POLLHUP | POLLNVAL)) continue; + if (fd_info[i].revents & POLLIN) { + p_dbus_watch_handle(watches[i], DBUS_WATCH_READABLE); while ( p_dbus_connection_get_dispatch_status ( conns[i] ) == DBUS_DISPATCH_DATA_REMAINS ) { p_dbus_connection_dispatch ( conns[i] ) ; } } - if (i > 0) p_dbus_connection_unref(conns[i]); + if (fd_info[i].revents & POLLOUT) { + p_dbus_watch_handle(watches[i], DBUS_WATCH_WRITABLE); + } + } + for ( i = 0; i < fd_count; i++ ) + { + p_dbus_connection_unref(conns[i]); } } } @@ -1122,9 +1210,7 @@ static BOOL register_notification_item(DBusConnection* connection)
if (!p_dbus_connection_send_with_reply (connection, msg, &pending, -1)) goto err; - if (!pending) goto err;
- p_dbus_connection_flush(connection); p_dbus_message_unref(msg);
p_dbus_pending_call_block(pending); @@ -1165,8 +1251,6 @@ static BOOL send_signal_to_item(DBusConnection* connection, const char* signal_n return FALSE; }
- p_dbus_connection_flush(connection); - p_dbus_message_unref(msg);
return TRUE; @@ -1209,6 +1293,7 @@ BOOL add_icon(const NOTIFYICONDATAW* icon_data) p_dbus_error_free( &error ); goto fail; } + icon = malloc(sizeof(struct tray_icon)); if (!icon) goto fail;
@@ -1221,6 +1306,13 @@ BOOL add_icon(const NOTIFYICONDATAW* icon_data) WARN("failed to initialize mutex\n" ); goto fail; } + + if (!p_dbus_connection_set_watch_functions(connection, add_watch, remove_watch, + toggle_watch, icon, NULL)) { + WARN("dbus_set_watch_functions() failed\n"); + goto fail; + } + if (icon_data->uFlags & NIF_ICON) { if (!get_icon_data(icon_data, icon)) @@ -1272,9 +1364,11 @@ fail: BOOL cleanup_icon(struct tray_icon* icon) { pthread_mutex_lock(&icon->mutex); + p_dbus_connection_flush(icon->connection); p_dbus_connection_close(icon->connection); p_dbus_connection_unref(icon->connection); pthread_mutex_unlock(&icon->mutex); + if (icon->hIcon) NtUserDestroyCursor(icon->hIcon, 0); if (icon->icon_bitmap) free(icon->icon_bitmap); if (icon) pthread_mutex_destroy(&icon->mutex); @@ -1387,6 +1481,5 @@ BOOL cleanup_icons(HWND owner) } } pthread_mutex_unlock(&list_mutex); - return TRUE; }