| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/exo/wayland/zcr_notification_shell.h" |
| |
| #include <notification-shell-unstable-v1-server-protocol.h> |
| #include <wayland-server-core.h> |
| #include <wayland-server-protocol-core.h> |
| |
| #include <string> |
| |
| #include "base/atomic_sequence_num.h" |
| #include "base/optional.h" |
| #include "components/exo/notification.h" |
| #include "components/exo/notification_surface.h" |
| #include "components/exo/notification_surface_manager.h" |
| #include "components/exo/wayland/server_util.h" |
| |
| namespace exo { |
| namespace wayland { |
| |
| namespace { |
| |
| // Notification id and notifier id used for NotificationShell. |
| constexpr char kNotificationShellNotificationIdFormat[] = |
| "exo-notification-shell.%d.%s"; |
| constexpr char kNotificationShellNotifierId[] = "exo-notification-shell"; |
| |
| // Incremental id for notification shell instance. |
| base::AtomicSequenceNumber g_next_notification_shell_id; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // zcr_notification_shell_notification_v1 interface: |
| |
| // Implements notification interface. |
| class WaylandNotificationShellNotification { |
| public: |
| WaylandNotificationShellNotification(const std::string& title, |
| const std::string& message, |
| const std::string& display_source, |
| const std::string& notification_id, |
| const std::vector<std::string>& buttons, |
| wl_resource* resource) |
| : resource_(resource), weak_ptr_factory_(this) { |
| notification_ = std::make_unique<Notification>( |
| title, message, display_source, notification_id, |
| kNotificationShellNotifierId, buttons, |
| base::BindRepeating(&WaylandNotificationShellNotification::OnClose, |
| weak_ptr_factory_.GetWeakPtr()), |
| base::BindRepeating(&WaylandNotificationShellNotification::OnClick, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void Close() { notification_->Close(); } |
| |
| private: |
| void OnClose(bool by_user) { |
| zcr_notification_shell_notification_v1_send_closed(resource_, by_user); |
| wl_client_flush(wl_resource_get_client(resource_)); |
| } |
| |
| void OnClick(const base::Optional<int>& button_index) { |
| int32_t index = button_index ? *button_index : -1; |
| zcr_notification_shell_notification_v1_send_clicked(resource_, index); |
| wl_client_flush(wl_resource_get_client(resource_)); |
| } |
| |
| wl_resource* const resource_; |
| std::unique_ptr<Notification> notification_; |
| |
| base::WeakPtrFactory<WaylandNotificationShellNotification> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WaylandNotificationShellNotification); |
| }; |
| |
| void notification_destroy(wl_client* client, wl_resource* resource) { |
| wl_resource_destroy(resource); |
| } |
| |
| void notification_close(wl_client* client, wl_resource* resource) { |
| GetUserDataAs<WaylandNotificationShellNotification>(resource)->Close(); |
| } |
| |
| const struct zcr_notification_shell_notification_v1_interface |
| notification_implementation = {notification_destroy, notification_close}; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // zcr_notification_shell_v1 interface: |
| |
| // Implements notification shell interface. |
| class WaylandNotificationShell { |
| public: |
| WaylandNotificationShell() : id_(g_next_notification_shell_id.GetNext()) {} |
| |
| ~WaylandNotificationShell() = default; |
| |
| // Creates a notification on message center from textual information. |
| std::unique_ptr<WaylandNotificationShellNotification> CreateNotification( |
| const std::string& title, |
| const std::string& message, |
| const std::string& display_source, |
| const std::string& notification_key, |
| const std::vector<std::string>& buttons, |
| wl_resource* notification_resource) { |
| auto notification_id = base::StringPrintf( |
| kNotificationShellNotificationIdFormat, id_, notification_key.c_str()); |
| |
| return std::make_unique<WaylandNotificationShellNotification>( |
| title, message, display_source, notification_id, buttons, |
| notification_resource); |
| } |
| |
| private: |
| // Id for this notification shell instance. |
| const uint32_t id_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WaylandNotificationShell); |
| }; |
| |
| void notification_shell_create_notification(wl_client* client, |
| wl_resource* resource, |
| uint32_t id, |
| const char* title, |
| const char* message, |
| const char* display_source, |
| const char* notification_key, |
| wl_array* buttons) { |
| wl_resource* notification_resource = wl_resource_create( |
| client, &zcr_notification_shell_notification_v1_interface, |
| wl_resource_get_version(resource), id); |
| |
| // Converts wl_array of strings into std::vector<std::string>. All elements |
| // are 0-terminated so we use it as the mark of the element's end. |
| std::vector<std::string> button_strings; |
| const char* data = static_cast<const char*>(buttons->data); |
| int len = 0; |
| for (const char *pos = data; pos < data + buttons->size; ++pos, ++len) { |
| if (*pos == '\0') { |
| button_strings.emplace_back(std::string(pos - len, len)); |
| len = 0; |
| } |
| } |
| |
| std::unique_ptr<WaylandNotificationShellNotification> notification = |
| GetUserDataAs<WaylandNotificationShell>(resource)->CreateNotification( |
| title, message, display_source, notification_key, button_strings, |
| notification_resource); |
| |
| SetImplementation(notification_resource, ¬ification_implementation, |
| std::move(notification)); |
| } |
| |
| void notification_shell_get_notification_surface(wl_client* client, |
| wl_resource* resource, |
| uint32_t id, |
| wl_resource* surface, |
| const char* notification_key) { |
| NOTIMPLEMENTED(); |
| } |
| |
| const struct zcr_notification_shell_v1_interface |
| zcr_notification_shell_v1_implementation = { |
| notification_shell_create_notification, |
| notification_shell_get_notification_surface, |
| }; |
| |
| } // namespace |
| |
| void bind_notification_shell(wl_client* client, |
| void* data, |
| uint32_t version, |
| uint32_t id) { |
| wl_resource* resource = |
| wl_resource_create(client, &zcr_notification_shell_v1_interface, 1, id); |
| |
| SetImplementation(resource, &zcr_notification_shell_v1_implementation, |
| std::make_unique<WaylandNotificationShell>()); |
| } |
| |
| } // namespace wayland |
| } // namespace exo |