1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_SERVER_OBJECT_H_
6 #define UI_OZONE_PLATFORM_WAYLAND_TEST_SERVER_OBJECT_H_
7
8 #include <memory>
9 #include <type_traits>
10 #include <utility>
11
12 #include "base/macros.h"
13
14 #include <wayland-server-core.h>
15
16 struct wl_client;
17 struct wl_resource;
18
19 namespace wl {
20
21 // Base class for managing the life cycle of server objects.
22 class ServerObject {
23 public:
24 explicit ServerObject(wl_resource* resource);
25 virtual ~ServerObject();
26
resource()27 wl_resource* resource() const { return resource_; }
28
29 static void OnResourceDestroyed(wl_resource* resource);
30
31 private:
32 wl_resource* resource_;
33
34 DISALLOW_COPY_AND_ASSIGN(ServerObject);
35 };
36
37 template <class T>
GetUserDataAs(wl_resource * resource)38 T* GetUserDataAs(wl_resource* resource) {
39 return static_cast<T*>(wl_resource_get_user_data(resource));
40 }
41
42 template <class T>
TakeUserDataAs(wl_resource * resource)43 std::unique_ptr<T> TakeUserDataAs(wl_resource* resource) {
44 std::unique_ptr<T> user_data(GetUserDataAs<T>(resource));
45 if (std::is_base_of<ServerObject, T>::value) {
46 // Make sure ServerObject doesn't try to destroy the resource twice.
47 ServerObject::OnResourceDestroyed(resource);
48 }
49 wl_resource_set_user_data(resource, nullptr);
50 return user_data;
51 }
52
53 template <class T>
DestroyUserData(wl_resource * resource)54 void DestroyUserData(wl_resource* resource) {
55 TakeUserDataAs<T>(resource);
56 }
57
58 template <class T>
SetImplementation(wl_resource * resource,const void * implementation,std::unique_ptr<T> user_data)59 void SetImplementation(wl_resource* resource,
60 const void* implementation,
61 std::unique_ptr<T> user_data) {
62 wl_resource_set_implementation(resource, implementation, user_data.release(),
63 DestroyUserData<T>);
64 }
65
66 template <typename ImplClass, typename... ImplArgs>
CreateResourceWithImpl(wl_client * client,const struct wl_interface * interface,int version,const void * implementation,uint32_t id,ImplArgs &&...impl_args)67 wl_resource* CreateResourceWithImpl(wl_client* client,
68 const struct wl_interface* interface,
69 int version,
70 const void* implementation,
71 uint32_t id,
72 ImplArgs&&... impl_args) {
73 wl_resource* resource = wl_resource_create(client, interface, version, id);
74 if (!resource) {
75 wl_client_post_no_memory(client);
76 return nullptr;
77 }
78 SetImplementation(resource, implementation,
79 std::make_unique<ImplClass>(
80 resource, std::forward<ImplArgs&&>(impl_args)...));
81 return resource;
82 }
83
84 // Does not transfer ownership of the user_data. Use with caution. The only
85 // legitimate purpose is setting more than one implementation to the same user
86 // data.
87 template <class T>
SetImplementationUnretained(wl_resource * resource,const void * implementation,T * user_data)88 void SetImplementationUnretained(wl_resource* resource,
89 const void* implementation,
90 T* user_data) {
91 static_assert(std::is_base_of<ServerObject, T>::value,
92 "Only types derived from ServerObject are supported!");
93 wl_resource_set_implementation(resource, implementation, user_data,
94 &ServerObject::OnResourceDestroyed);
95 }
96
97 bool ResourceHasImplementation(wl_resource* resource,
98 const wl_interface* interface,
99 const void* impl);
100
101 void DestroyResource(wl_client* client, wl_resource* resource);
102
103 } // namespace wl
104
105 #endif // UI_OZONE_PLATFORM_WAYLAND_TEST_SERVER_OBJECT_H_
106