From: Sergei Chernyadyev 1892-Cherser-s@users.noreply.gitlab.winehq.org
--- dlls/winesni.drv/dbus.c | 100 +++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 32 deletions(-)
diff --git a/dlls/winesni.drv/dbus.c b/dlls/winesni.drv/dbus.c index d286f343fd1..bbe31c964d7 100644 --- a/dlls/winesni.drv/dbus.c +++ b/dlls/winesni.drv/dbus.c @@ -112,16 +112,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 */ };
@@ -146,8 +147,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) { @@ -671,6 +670,7 @@ DBusHandlerResult get_all_tray_properties(DBusConnection* conn, DBusMessage *mes 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; @@ -790,13 +790,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);
+ pthread_mutex_unlock((pthread_mutex_t*)&icon->mutex); + if (!p_dbus_connection_send(conn, reply, &serial)) { - goto fail; + 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"); @@ -811,6 +815,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, @@ -826,12 +831,16 @@ 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); p_dbus_message_iter_init_append(reply, &iter); 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); @@ -840,7 +849,8 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage p_dbus_message_iter_init_append(reply, &iter); 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); @@ -849,7 +859,8 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage p_dbus_message_iter_init_append(reply, &iter); 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); @@ -858,22 +869,29 @@ DBusHandlerResult notification_message_handler(DBusConnection *conn, DBusMessage p_dbus_message_iter_init_append(reply, &iter); 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); } 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)) { + + 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")) { const char* interface_name = ""; DBusMessageIter args; @@ -960,10 +978,9 @@ void unregister_notification_handler(DBusConnection* conn, void* user_data) struct tray_icon* icon = (struct tray_icon*)user_data;
if (icon->hIcon) NtUserDestroyCursor(icon->hIcon, 0); - if (icon->icon_bitmap) { - free(icon->icon_bitmap); - } - + if (icon->icon_bitmap) free(icon->icon_bitmap); + if (icon) pthread_mutex_destroy(&icon->mutex); + free(icon); }
@@ -1119,6 +1136,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)) { @@ -1159,6 +1179,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); @@ -1186,20 +1207,24 @@ 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) @@ -1211,16 +1236,21 @@ BOOL modify_icon(const NOTIFYICONDATAW* icon_data) new_state = (icon->state & ~icon_data->dwStateMask) | (icon_data->dwState & icon_data->dwStateMask); 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; } }
@@ -1229,6 +1259,8 @@ BOOL modify_icon(const NOTIFYICONDATAW* icon_data) } return TRUE; err: + pthread_mutex_unlock(&icon->mutex); +err_post_unlock: return FALSE; }
@@ -1243,7 +1275,11 @@ 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; }