1 /*
2  * Compton - a compositor for X11
3  *
4  * Based on `xcompmgr` - Copyright (c) 2003, Keith Packard
5  *
6  * Copyright (c) 2011-2013, Christopher Jeffrey
7  * See LICENSE for more information.
8  *
9  */
10 
11 #include "common.h"
12 #include <ctype.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 
16 #define CDBUS_SERVICE_NAME      "com.github.chjj.compton"
17 #define CDBUS_INTERFACE_NAME    CDBUS_SERVICE_NAME
18 #define CDBUS_OBJECT_NAME       "/com/github/chjj/compton"
19 #define CDBUS_ERROR_PREFIX      CDBUS_INTERFACE_NAME ".error"
20 #define CDBUS_ERROR_UNKNOWN     CDBUS_ERROR_PREFIX ".unknown"
21 #define CDBUS_ERROR_UNKNOWN_S   "Well, I don't know what happened. Do you?"
22 #define CDBUS_ERROR_BADMSG      CDBUS_ERROR_PREFIX ".bad_message"
23 #define CDBUS_ERROR_BADMSG_S    "Unrecognized command. Beware compton " \
24                                 "cannot make you a sandwich."
25 #define CDBUS_ERROR_BADARG      CDBUS_ERROR_PREFIX ".bad_argument"
26 #define CDBUS_ERROR_BADARG_S    "Failed to parse argument %d: %s"
27 #define CDBUS_ERROR_BADWIN      CDBUS_ERROR_PREFIX ".bad_window"
28 #define CDBUS_ERROR_BADWIN_S    "Requested window %#010lx not found."
29 #define CDBUS_ERROR_BADTGT      CDBUS_ERROR_PREFIX ".bad_target"
30 #define CDBUS_ERROR_BADTGT_S    "Target \"%s\" not found."
31 #define CDBUS_ERROR_FORBIDDEN   CDBUS_ERROR_PREFIX ".forbidden"
32 #define CDBUS_ERROR_FORBIDDEN_S "Incorrect password, access denied."
33 #define CDBUS_ERROR_CUSTOM      CDBUS_ERROR_PREFIX ".custom"
34 #define CDBUS_ERROR_CUSTOM_S    "%s"
35 
36 // Window type
37 typedef uint32_t cdbus_window_t;
38 #define CDBUS_TYPE_WINDOW       DBUS_TYPE_UINT32
39 #define CDBUS_TYPE_WINDOW_STR   DBUS_TYPE_UINT32_AS_STRING
40 
41 typedef uint16_t cdbus_enum_t;
42 #define CDBUS_TYPE_ENUM         DBUS_TYPE_UINT16
43 #define CDBUS_TYPE_ENUM_STR     DBUS_TYPE_UINT16_AS_STRING
44 
45 static dbus_bool_t
46 cdbus_callback_add_timeout(DBusTimeout *timeout, void *data);
47 
48 static void
49 cdbus_callback_remove_timeout(DBusTimeout *timeout, void *data);
50 
51 static void
52 cdbus_callback_timeout_toggled(DBusTimeout *timeout, void *data);
53 
54 static bool
55 cdbus_callback_handle_timeout(session_t *ps, timeout_t *ptmout);
56 
57 /**
58  * Determine the poll condition of a DBusWatch.
59  */
60 static inline short
cdbus_get_watch_cond(DBusWatch * watch)61 cdbus_get_watch_cond(DBusWatch *watch) {
62   const unsigned flags = dbus_watch_get_flags(watch);
63   short condition = POLLERR | POLLHUP;
64   if (flags & DBUS_WATCH_READABLE)
65     condition |= POLLIN;
66   if (flags & DBUS_WATCH_WRITABLE)
67     condition |= POLLOUT;
68 
69   return condition;
70 }
71 
72 static dbus_bool_t
73 cdbus_callback_add_watch(DBusWatch *watch, void *data);
74 
75 static void
76 cdbus_callback_remove_watch(DBusWatch *watch, void *data);
77 
78 static void
79 cdbus_callback_watch_toggled(DBusWatch *watch, void *data);
80 
81 static bool
82 cdbus_apdarg_bool(session_t *ps, DBusMessage *msg, const void *data);
83 
84 static bool
85 cdbus_apdarg_int32(session_t *ps, DBusMessage *msg, const void *data);
86 
87 static bool
88 cdbus_apdarg_uint32(session_t *ps, DBusMessage *msg, const void *data);
89 
90 static bool
91 cdbus_apdarg_double(session_t *ps, DBusMessage *msg, const void *data);
92 
93 static bool
94 cdbus_apdarg_wid(session_t *ps, DBusMessage *msg, const void *data);
95 
96 static bool
97 cdbus_apdarg_enum(session_t *ps, DBusMessage *msg, const void *data);
98 
99 static bool
100 cdbus_apdarg_string(session_t *ps, DBusMessage *msg, const void *data);
101 
102 static bool
103 cdbus_apdarg_wids(session_t *ps, DBusMessage *msg, const void *data);
104 
105 /** @name DBus signal sending
106  */
107 ///@{
108 
109 static bool
110 cdbus_signal(session_t *ps, const char *name,
111     bool (*func)(session_t *ps, DBusMessage *msg, const void *data),
112     const void *data);
113 
114 /**
115  * Send a signal with no argument.
116  */
117 static inline bool
cdbus_signal_noarg(session_t * ps,const char * name)118 cdbus_signal_noarg(session_t *ps, const char *name) {
119   return cdbus_signal(ps, name, NULL, NULL);
120 }
121 
122 /**
123  * Send a signal with a Window ID as argument.
124  */
125 static inline bool
cdbus_signal_wid(session_t * ps,const char * name,Window wid)126 cdbus_signal_wid(session_t *ps, const char *name, Window wid) {
127   return cdbus_signal(ps, name, cdbus_apdarg_wid, &wid);
128 }
129 
130 ///@}
131 
132 /** @name DBus reply sending
133  */
134 ///@{
135 
136 static bool
137 cdbus_reply(session_t *ps, DBusMessage *srcmsg,
138     bool (*func)(session_t *ps, DBusMessage *msg, const void *data),
139     const void *data);
140 
141 static bool
142 cdbus_reply_errm(session_t *ps, DBusMessage *msg);
143 
144 #define cdbus_reply_err(ps, srcmsg, err_name, err_format, ...) \
145   cdbus_reply_errm((ps), dbus_message_new_error_printf((srcmsg), (err_name), (err_format), ## __VA_ARGS__))
146 
147 /**
148  * Send a reply with no argument.
149  */
150 static inline bool
cdbus_reply_noarg(session_t * ps,DBusMessage * srcmsg)151 cdbus_reply_noarg(session_t *ps, DBusMessage *srcmsg) {
152   return cdbus_reply(ps, srcmsg, NULL, NULL);
153 }
154 
155 /**
156  * Send a reply with a bool argument.
157  */
158 static inline bool
cdbus_reply_bool(session_t * ps,DBusMessage * srcmsg,bool bval)159 cdbus_reply_bool(session_t *ps, DBusMessage *srcmsg, bool bval) {
160   return cdbus_reply(ps, srcmsg, cdbus_apdarg_bool, &bval);
161 }
162 
163 /**
164  * Send a reply with an int32 argument.
165  */
166 static inline bool
cdbus_reply_int32(session_t * ps,DBusMessage * srcmsg,int32_t val)167 cdbus_reply_int32(session_t *ps, DBusMessage *srcmsg, int32_t val) {
168   return cdbus_reply(ps, srcmsg, cdbus_apdarg_int32, &val);
169 }
170 
171 /**
172  * Send a reply with an uint32 argument.
173  */
174 static inline bool
cdbus_reply_uint32(session_t * ps,DBusMessage * srcmsg,uint32_t val)175 cdbus_reply_uint32(session_t *ps, DBusMessage *srcmsg, uint32_t val) {
176   return cdbus_reply(ps, srcmsg, cdbus_apdarg_uint32, &val);
177 }
178 
179 /**
180  * Send a reply with a double argument.
181  */
182 static inline bool
cdbus_reply_double(session_t * ps,DBusMessage * srcmsg,double val)183 cdbus_reply_double(session_t *ps, DBusMessage *srcmsg, double val) {
184   return cdbus_reply(ps, srcmsg, cdbus_apdarg_double, &val);
185 }
186 
187 /**
188  * Send a reply with a wid argument.
189  */
190 static inline bool
cdbus_reply_wid(session_t * ps,DBusMessage * srcmsg,Window wid)191 cdbus_reply_wid(session_t *ps, DBusMessage *srcmsg, Window wid) {
192   return cdbus_reply(ps, srcmsg, cdbus_apdarg_wid, &wid);
193 }
194 
195 /**
196  * Send a reply with a string argument.
197  */
198 static inline bool
cdbus_reply_string(session_t * ps,DBusMessage * srcmsg,const char * str)199 cdbus_reply_string(session_t *ps, DBusMessage *srcmsg, const char *str) {
200   return cdbus_reply(ps, srcmsg, cdbus_apdarg_string, str);
201 }
202 
203 /**
204  * Send a reply with a enum argument.
205  */
206 static inline bool
cdbus_reply_enum(session_t * ps,DBusMessage * srcmsg,cdbus_enum_t eval)207 cdbus_reply_enum(session_t *ps, DBusMessage *srcmsg, cdbus_enum_t eval) {
208   return cdbus_reply(ps, srcmsg, cdbus_apdarg_enum, &eval);
209 }
210 
211 ///@}
212 
213 static bool
214 cdbus_msg_get_arg(DBusMessage *msg, int count, const int type, void *pdest);
215 
216 /**
217  * Return a string representation of a D-Bus message type.
218  */
219 static inline const char *
cdbus_repr_msgtype(DBusMessage * msg)220 cdbus_repr_msgtype(DBusMessage *msg) {
221   return dbus_message_type_to_string(dbus_message_get_type(msg));
222 }
223 
224 /** @name Message processing
225  */
226 ///@{
227 
228 static void
229 cdbus_process(session_t *ps, DBusMessage *msg);
230 
231 static bool
232 cdbus_process_list_win(session_t *ps, DBusMessage *msg);
233 
234 static bool
235 cdbus_process_win_get(session_t *ps, DBusMessage *msg);
236 
237 static bool
238 cdbus_process_win_set(session_t *ps, DBusMessage *msg);
239 
240 static bool
241 cdbus_process_find_win(session_t *ps, DBusMessage *msg);
242 
243 static bool
244 cdbus_process_opts_get(session_t *ps, DBusMessage *msg);
245 
246 static bool
247 cdbus_process_opts_set(session_t *ps, DBusMessage *msg);
248 
249 static bool
250 cdbus_process_introspect(session_t *ps, DBusMessage *msg);
251 
252 ///@}
253