From: Sergei Chernyadyev 1892-Cherser-s@users.noreply.gitlab.winehq.org
--- dlls/winesni.drv/dbus.c | 90 ++++++++++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 24 deletions(-)
diff --git a/dlls/winesni.drv/dbus.c b/dlls/winesni.drv/dbus.c index 732b4948377..2d14263a5a1 100644 --- a/dlls/winesni.drv/dbus.c +++ b/dlls/winesni.drv/dbus.c @@ -113,16 +113,17 @@ DBUS_FUNCS; /* an individual systray icon */ struct tray_icon { - HWND owner; /* the HWND passed in to the Shell_NotifyIcon call */ - HICON hIcon; - void* icon_bitmap; - UINT icon_width; - UINT icon_height; - UINT state; /* state flags */ - UINT id; /* the unique id given by the app */ - UINT callback_message; - char tiptext[128 * 3]; /* tooltip text */ - UINT version; /* notify icon api version */ + HWND owner; /* the HWND passed in to the Shell_NotifyIcon call */ + HICON hIcon; + void* icon_bitmap; + UINT icon_width; + UINT icon_height; + UINT state; /* state flags */ + UINT id; /* the unique id given by the app */ + UINT callback_message; + char tiptext[128 * 3]; /* tooltip text */ + UINT version; /* notify icon api version */ + pthread_mutex_t mutex; /* mutex */ };
@@ -147,8 +148,6 @@ static const char *icon_name_field = "IconName"; static const char *title_field = "Title"; static const char *category_field = "Category"; static const char *id_field = "Id"; -/*TODO: sync it*/ -/*static pthread_mutex_t status_notifier_item_mutex = PTHREAD_MUTEX_INITIALIZER;*/
BOOL load_dbus_functions(void) { @@ -688,6 +687,7 @@ DBusHandlerResult get_all_tray_properties(DBusConnection* conn, DBusMessage *mes if (!reply) goto fail;
p_dbus_message_iter_init_append(reply, &iter); + pthread_mutex_lock((pthread_mutex_t*)&icon->mutex);
if (!p_dbus_message_iter_open_container(&iter, 'a', "{sv}", &aIter)) goto fail;
@@ -818,11 +818,17 @@ DBusHandlerResult get_all_tray_properties(DBusConnection* conn, DBusMessage *mes p_dbus_message_iter_close_container(&aIter, &eIter); p_dbus_message_iter_close_container(&iter, &aIter);
- if (!p_dbus_connection_send(conn, reply, &serial)) goto fail; + pthread_mutex_unlock((pthread_mutex_t*)&icon->mutex); + + 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: + pthread_mutex_unlock((pthread_mutex_t*)&icon->mutex); +send_fail: p_dbus_message_unref(reply);
return notification_send_error(conn, message, "org.freedesktop.DBus.Error.Failed", "got an error while processing properties"); @@ -838,6 +844,7 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage DBusMessage* reply = NULL; DBusMessageIter iter, vIter; unsigned serial = 0; + DBusHandlerResult ret = DBUS_HANDLER_RESULT_HANDLED; DBusError error; p_dbus_error_init(&error); if (!p_dbus_message_get_args( message, &error, DBUS_TYPE_STRING, &interface_name, @@ -855,6 +862,9 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage snprintf(error_message, sizeof(error_message), "unsupported interface %s", interface_name); return notification_send_error (conn, message, "org.freedesktop.DBus.Error.UnknownProperty", error_message); } + + pthread_mutex_lock((pthread_mutex_t*)&icon->mutex); + if (strcmp(property_name, title_field) == 0) { reply = p_dbus_message_new_method_return(message); @@ -862,7 +872,8 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage if (!p_dbus_message_iter_open_container(&iter, 'v', "s", &vIter)) { p_dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; + ret = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto err_get; } handle_title(conn, &vIter, icon); p_dbus_message_iter_close_container(&iter, &vIter); @@ -874,7 +885,8 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage if (!p_dbus_message_iter_open_container(&iter, 'v', "s", &vIter)) { p_dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; + ret = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto err_get; } handle_id(conn, &vIter, icon); p_dbus_message_iter_close_container(&iter, &vIter); @@ -886,7 +898,8 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage if (!p_dbus_message_iter_open_container(&iter, 'v', "a(iiay)", &vIter)) { p_dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; + ret = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto err_get; } handle_icon(conn, &vIter, icon); p_dbus_message_iter_close_container(&iter, &vIter); @@ -898,7 +911,8 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage if (!p_dbus_message_iter_open_container(&iter, 'v', "s", &vIter)) { p_dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; + ret = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto err_get; } handle_status(conn, &vIter, icon); p_dbus_message_iter_close_container(&iter, &vIter); @@ -906,17 +920,23 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage else { char error_message[128]; + pthread_mutex_unlock((pthread_mutex_t*)&icon->mutex); snprintf(error_message, sizeof(error_message), "interface doesn't have the property %s", property_name); return notification_send_error (conn, message, "org.freedesktop.DBus.Error.UnknownProperty", error_message); } + if (!p_dbus_connection_send(conn, reply, &serial)) { p_dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_NEED_MEMORY; + ret = DBUS_HANDLER_RESULT_NEED_MEMORY; + goto err_get; } + p_dbus_connection_flush(conn); p_dbus_message_unref(reply); - return DBUS_HANDLER_RESULT_HANDLED; + err_get: + pthread_mutex_unlock((pthread_mutex_t*)&icon->mutex); + return ret; } else if (p_dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll")) { @@ -1017,6 +1037,7 @@ void unregister_notification_handler(DBusConnection* conn, void* user_data)
if (icon->hIcon) NtUserDestroyCursor(icon->hIcon, 0); if (icon->icon_bitmap) free(icon->icon_bitmap); + if (icon) pthread_mutex_destroy(&icon->mutex);
free(icon); } @@ -1165,6 +1186,9 @@ BOOL add_icon(const NOTIFYICONDATAW* icon_data) memset(icon, 0, sizeof(*icon)); icon->id = icon_data->uID; icon->owner = icon_data->hWnd; + if (pthread_mutex_init(&icon->mutex, NULL)) { + goto fail; + } if (icon_data->uFlags & NIF_ICON) { if (!get_icon_data(icon_data, icon)) goto fail; @@ -1201,6 +1225,7 @@ BOOL add_icon(const NOTIFYICONDATAW* icon_data) fail: if (icon && icon->hIcon) NtUserDestroyCursor(icon->hIcon, 0); if (icon && icon->icon_bitmap) free(icon->icon_bitmap); + if (icon) pthread_mutex_destroy(&icon->mutex); free(icon); if (registered) p_dbus_connection_unregister_object_path(connection, object_name); @@ -1228,19 +1253,23 @@ BOOL modify_icon(const NOTIFYICONDATAW* icon_data) DBusError error; char object_path[64]; struct tray_icon* icon; + const char* pending_signals[4]; + UINT signal_count = 0; UINT new_state; + UINT i; p_dbus_error_init( &error ); snprintf(object_path, sizeof(object_path), tray_path_format, (size_t)icon_data->hWnd, icon_data->uID);
if (!p_dbus_connection_get_object_path_data(connection, object_path, (void**)&icon)) return FALSE;
+ pthread_mutex_lock(&icon->mutex); + if (icon_data->uFlags & NIF_ICON) { if (!get_icon_data(icon_data, icon)) goto err; - if (!send_signal_to_item(object_path, "NewIcon")) - goto err; + pending_signals[signal_count++] = "NewIcon"; }
if (icon_data->uFlags & NIF_MESSAGE) @@ -1254,14 +1283,23 @@ BOOL modify_icon(const NOTIFYICONDATAW* icon_data) if (new_state != icon->state) { icon->state = new_state; - if (!send_signal_to_item(object_path, "NewStatus")) goto err; + pending_signals[signal_count++] = "NewStatus"; } }
if (icon_data->uFlags & NIF_TIP) { ntdll_wcstoumbs(icon_data->szTip, wcslen(icon_data->szTip) + 1, icon->tiptext, ARRAY_SIZE(icon->tiptext), FALSE); - if (!send_signal_to_item(object_path, "NewTitle")) goto err; + pending_signals[signal_count++] = "NewTitle"; + } + + pthread_mutex_unlock(&icon->mutex); + + /* send the signals */ + for (i = 0; i < signal_count; i++) + { + if (!send_signal_to_item(object_path, pending_signals[i])) + goto err_post_unlock; }
if (icon_data->uFlags & NIF_INFO && icon_data->cbSize >= NOTIFYICONDATAA_V2_SIZE) @@ -1269,6 +1307,8 @@ BOOL modify_icon(const NOTIFYICONDATAW* icon_data)
return TRUE; err: + pthread_mutex_unlock(&icon->mutex); +err_post_unlock: return FALSE; }
@@ -1282,8 +1322,10 @@ BOOL set_icon_version(const NOTIFYICONDATAW* icon_data)
if (!p_dbus_connection_get_object_path_data(connection, object_path, (void**)&icon)) return FALSE; - + pthread_mutex_lock(&icon->mutex); icon->version = icon_data->uVersion; + pthread_mutex_unlock(&icon->mutex); + return TRUE; }