Added initial support for displaying on Wayland compositors.
[vuplus_xbmc] / xbmc / windowing / WaylandProtocol.h
1 #pragma once
2
3 /*
4  *      Copyright (C) 2005-2013 Team XBMC
5  *      http://www.xbmc.org
6  *
7  *  This Program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2, or (at your option)
10  *  any later version.
11  *
12  *  This Program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with XBMC; see the file COPYING.  If not, see
19  *  <http://www.gnu.org/licenses/>.
20  *
21  */
22
23 #include <iomanip>
24 #include <stdexcept>
25 #include <sstream>
26
27 #include "DllWaylandClient.h"
28
29 /* These functions are wrappers around using the wayland protocol
30  * directly. Unfortunately, since most of the protocol has autogenerated
31  * binding code, and that binding code assumes that we're directly
32  * linked to the client library (we're not), we can't use it. So
33  * we need to use wl_proxy_create, wl_proxy_marshal and wl_proxy_destory
34  * directly.
35  * 
36  * These functions effectively exist to reduce some of the duplication
37  * that surrounds using these functions directly. You should look
38  * at the autogenerated binding code to determine how wl_proxy_marshal
39  * should be used to call a particular method.
40  * 
41  * Also note that there may be some cases where additional constructor
42  * or destructor functions might need to be called before or after
43  * CreateWaylandObject and DestroyWaylandObject.
44  * 
45  * If you need to call a method with more than six arguments,
46  * you'll need to add a new overload here */
47 namespace xbmc
48 {
49 namespace wayland
50 {
51 namespace protocol
52 {
53 /* These functions call a method on a specifed wayland object
54  * (you should use the pointer provided by the client library
55  *  and not the wrapper) with the specified opcode and
56  * arguments.
57  * 
58  * THERE IS NO TYPE CHECKING so you should be especially sure that
59  * you're calling it with the right arguments. Failure to do so
60  * will result in very strange behaviour
61  */
62 template <typename Object>
63 void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary,
64                                Object object,
65                                uint32_t opcode)
66 {
67   struct wl_proxy *proxy =
68     reinterpret_cast<struct wl_proxy *>(object);
69   clientLibrary.wl_proxy_marshaller()(proxy,
70                                       opcode);
71 }
72 template <typename Object,
73           typename A1>
74 void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary,
75                                Object object,
76                                uint32_t opcode,
77                                A1 arg1)
78 {
79   struct wl_proxy *proxy =
80     reinterpret_cast<struct wl_proxy *>(object);
81   clientLibrary.wl_proxy_marshaller()(proxy,
82                                       opcode,
83                                       arg1);
84 }
85
86 template <typename Object,
87           typename A1,
88           typename A2>
89 void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary,
90                                Object object,
91                                uint32_t opcode,
92                                A1 arg1,
93                                A2 arg2)
94 {
95   struct wl_proxy *proxy =
96     reinterpret_cast<struct wl_proxy *>(object);
97   clientLibrary.wl_proxy_marshaller()(proxy,
98                                       opcode,
99                                       arg1,
100                                       arg2);
101 }
102
103 template <typename Object,
104           typename A1,
105           typename A2,
106           typename A3>
107 void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary,
108                                Object object,
109                                uint32_t opcode,
110                                A1 arg1,
111                                A2 arg2,
112                                A3 arg3)
113 {
114   struct wl_proxy *proxy =
115     reinterpret_cast<struct wl_proxy *>(object);
116   clientLibrary.wl_proxy_marshaller()(proxy,
117                                       opcode,
118                                       arg1,
119                                       arg2,
120                                       arg3);
121 }
122
123 template <typename Object,
124           typename A1,
125           typename A2,
126           typename A3,
127           typename A4>
128 void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary,
129                                Object object,
130                                uint32_t opcode,
131                                A1 arg1,
132                                A2 arg2,
133                                A3 arg3,
134                                A4 arg4)
135 {
136   struct wl_proxy *proxy =
137     reinterpret_cast<struct wl_proxy *>(object);
138   clientLibrary.wl_proxy_marshaller()(proxy,
139                                       opcode,
140                                       arg1,
141                                       arg2,
142                                       arg3,
143                                       arg4);
144 }
145
146 template <typename Object,
147           typename A1,
148           typename A2,
149           typename A3,
150           typename A4,
151           typename A5>
152 void CallMethodOnWaylandObject(IDllWaylandClient &clientLibrary,
153                                Object object,
154                                uint32_t opcode,
155                                A1 arg1,
156                                A2 arg2,
157                                A3 arg3,
158                                A4 arg4,
159                                A5 arg5)
160 {
161   struct wl_proxy *proxy =
162     reinterpret_cast<struct wl_proxy *>(object);
163   clientLibrary.wl_proxy_marshaller()(proxy,
164                                       opcode,
165                                       arg1,
166                                       arg2,
167                                       arg3,
168                                       arg4,
169                                       arg5);
170 }
171
172 /* This function template returns a new unmanaged object pointer
173  * as specified by Create with the RPC interface as specified
174  * as a child in the server ownership hierarchy of factory.
175  * 
176  * Create must be castable to struct wl_proxy *, which
177  * means that struct wl_proxy should be its first member. Generally
178  * all wayland library proxy objects satisfy this criteria
179  */ 
180 template <typename Create, typename Factory>
181 Create CreateWaylandObject(IDllWaylandClient &clientLibrary,
182                            Factory factory,
183                            struct wl_interface **interface)
184 {
185   struct wl_proxy *pfactory =
186     reinterpret_cast<struct wl_proxy *>(factory);
187   struct wl_proxy *proxy =
188     clientLibrary.wl_proxy_create(pfactory,
189                                   reinterpret_cast<struct wl_interface *>(interface));
190
191   if (!proxy)
192   {
193     std::stringstream ss;
194     ss << "Failed to create "
195        << typeid(Create).name()
196        << " from factory "
197        << typeid(Factory).name()
198        << " at 0x"
199        << std::hex
200        << reinterpret_cast<void *>(pfactory)
201        << std::dec;
202     throw std::runtime_error(ss.str());
203   }
204
205   return reinterpret_cast<Create>(proxy);
206 }
207
208 /* This function adds a new "listener" to the object specified.
209  * A "listener" is generally a struct of function pointers as specified
210  * by the object's RPC interface for each event it can generate. These
211  * can usually be found in the protocol header. "data" is passed
212  * to each callback to make it a full closure. */
213 template <typename Object, typename Listener>
214 int AddListenerOnWaylandObject(IDllWaylandClient &clientLibrary,
215                                Object object,
216                                Listener listener,
217                                void *data)
218 {
219   struct wl_proxy *proxy =
220     reinterpret_cast<struct wl_proxy *>(object);
221   
222   /* C-style casts are bad, but there is no equavilent to
223    * std::remove_const in C++98 and we are reinterpret_cast'ing
224    * anyways */
225   IDllWaylandClient::wl_proxy_listener_func *listenerFunc =
226     (IDllWaylandClient::wl_proxy_listener_func *)((void *)listener);
227   return clientLibrary.wl_proxy_add_listener(proxy, listenerFunc, data);
228 }
229
230 /* This function destroys the proxy object and releases its resources
231  * on the client side. There may be an additional destroy request to
232  * release resources on the server side. That must be called
233  * prior to this. */
234 template <typename Object>
235 void DestroyWaylandObject(IDllWaylandClient &clientLibrary,
236                           Object *object)
237 {
238   struct wl_proxy *proxy =
239     reinterpret_cast<struct wl_proxy *>(object);
240   clientLibrary.wl_proxy_destroy(proxy);
241 }
242 }
243 }
244 }